Plugin Directory

Changeset 3463463


Ignore:
Timestamp:
02/17/2026 12:03:49 PM (5 days ago)
Author:
shoaibzain
Message:

Update Video Testimonials reel controls and assets

Location:
nebula-forge-addons-for-elementor/trunk
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • nebula-forge-addons-for-elementor/trunk/assets/css/frontend.css

    r3463206 r3463463  
    30013001}
    30023002
     3003.nfa-vtestimonials-lightbox__media {
     3004    width: 100%;
     3005    height: 100%;
     3006}
     3007
     3008.nfa-vtestimonials-lightbox__media iframe,
     3009.nfa-vtestimonials-lightbox__media video {
     3010    width: 100%;
     3011    height: 100%;
     3012    border: 0;
     3013}
     3014
    30033015.nfa-vtestimonials-lightbox__close {
    30043016    position: absolute;
     
    30303042}
    30313043
    3032 .nfa-vtestimonials__thumb--playing iframe {
     3044.nfa-vtestimonials__thumb--playing iframe,
     3045.nfa-vtestimonials__thumb--playing video {
    30333046    position: absolute;
    30343047    inset: 0;
     
    30373050    border: 0;
    30383051    z-index: 5;
     3052    object-fit: cover;
     3053}
     3054
     3055/* Hide default browser controls on our custom-controlled videos */
     3056.nfa-vtestimonials__thumb--playing video::-webkit-media-controls,
     3057.nfa-vtestimonials__reel-card video::-webkit-media-controls {
     3058    display: none !important;
     3059}
     3060
     3061/* Reel card playing state */
     3062.nfa-vtestimonials__reel-card.is-playing .nfa-vtestimonials__reel-play {
     3063    display: none;
     3064}
     3065
     3066.nfa-vtestimonials__reel-card.is-playing .nfa-vtestimonials__reel-img {
     3067    visibility: hidden;
     3068}
     3069
     3070.nfa-vtestimonials__reel-card.is-playing .nfa-vtestimonials__reel-controls {
     3071    z-index: 10;
     3072    opacity: 0;
     3073    transition: opacity 0.3s ease;
     3074    pointer-events: none;
     3075}
     3076
     3077.nfa-vtestimonials__reel-card.is-playing:hover .nfa-vtestimonials__reel-controls {
     3078    opacity: 1;
     3079    pointer-events: auto;
     3080}
     3081
     3082.nfa-vtestimonials__reel-card.is-playing::after {
     3083    background: transparent;
    30393084}
    30403085
     
    32083253}
    32093254
     3255/* ==========================================================================
     3256   Reel Layout
     3257   ========================================================================== */
     3258
     3259.nfa-vtestimonials__reel {
     3260    display: grid;
     3261    grid-template-columns: repeat(4, minmax(0, 1fr));
     3262    gap: 16px;
     3263}
     3264
     3265/* ── Reel Card ───────────────────────────────────────────────────────── */
     3266
     3267.nfa-vtestimonials__reel-card {
     3268    position: relative;
     3269    aspect-ratio: 9 / 16;
     3270    border-radius: .5rem;
     3271    overflow: hidden;
     3272    cursor: pointer;
     3273    background: #000;
     3274}
     3275
     3276.nfa-vtestimonials__reel-card::after {
     3277    content: '';
     3278    position: absolute;
     3279    inset: 0;
     3280    background: rgb(0 0 0 / .2);
     3281    transition: background-color 150ms cubic-bezier(.4, 0, .2, 1);
     3282    pointer-events: none;
     3283    z-index: 1;
     3284}
     3285
     3286.nfa-vtestimonials__reel-card:hover::after {
     3287    background: rgb(0 0 0 / .3);
     3288}
     3289
     3290.nfa-vtestimonials__reel-video {
     3291    position: absolute;
     3292    inset: 0;
     3293    width: 100%;
     3294    height: 100%;
     3295    object-fit: cover;
     3296    z-index: 0;
     3297    background: #000;
     3298}
     3299
     3300.nfa-vtestimonials__reel-video::-webkit-media-controls {
     3301    display: none !important;
     3302}
     3303
     3304.nfa-vtestimonials__reel-card:hover .nfa-vtestimonials__reel-video {
     3305    transform: none;
     3306    transition: none;
     3307}
     3308
     3309/* ── Reel Play Button (centered) ─────────────────────────────────────── */
     3310
     3311.nfa-vtestimonials__reel-play {
     3312    position: absolute;
     3313    inset: auto;
     3314    top: 50%;
     3315    left: 50%;
     3316    width: 56px;
     3317    height: 56px;
     3318    transform: translate(-50%, -50%);
     3319    z-index: 2;
     3320    border: none;
     3321    background-color: transparent;
     3322    display: inline-flex;
     3323    align-items: center;
     3324    justify-content: center;
     3325    cursor: pointer;
     3326    transition: color 150ms cubic-bezier(.4, 0, .2, 1), background-color 150ms cubic-bezier(.4, 0, .2, 1), border-color 150ms cubic-bezier(.4, 0, .2, 1), fill 150ms cubic-bezier(.4, 0, .2, 1), stroke 150ms cubic-bezier(.4, 0, .2, 1);
     3327    padding: 0;
     3328}
     3329
     3330.nfa-vtestimonials__reel-play svg {
     3331    width: 2rem;
     3332    height: 2rem;
     3333    fill: #ffffff;
     3334    stroke: #ffffff;
     3335    color: #ffffff;
     3336    margin-left: 0;
     3337    background-color: rgb(0 0 0 / .5);
     3338    border-radius: 9999px;
     3339    padding: .75rem;
     3340    box-sizing: content-box;
     3341}
     3342
     3343/* ── Reel Bottom Controls ────────────────────────────────────────────── */
     3344
     3345.nfa-vtestimonials__reel-controls {
     3346    position: absolute;
     3347    right: .5rem;
     3348    left: .5rem;
     3349    bottom: .5rem;
     3350    z-index: 2;
     3351    display: flex;
     3352    align-items: center;
     3353    gap: .25rem;
     3354}
     3355
     3356.nfa-vtestimonials__reel-ctrl {
     3357    display: inline-flex;
     3358    align-items: center;
     3359    justify-content: center;
     3360    width: 2rem;
     3361    height: 2rem;
     3362    border-radius: 9999px;
     3363    background: #00000080;
     3364    color: #ffffff;
     3365    transition: color 150ms cubic-bezier(.4, 0, .2, 1), background-color 150ms cubic-bezier(.4, 0, .2, 1), border-color 150ms cubic-bezier(.4, 0, .2, 1), fill 150ms cubic-bezier(.4, 0, .2, 1), stroke 150ms cubic-bezier(.4, 0, .2, 1);
     3366    cursor: pointer;
     3367    border: none;
     3368    margin: 0;
     3369    padding: 0;
     3370}
     3371
     3372.nfa-vtestimonials__reel-ctrl:hover {
     3373    background: #00000080;
     3374}
     3375
     3376.nfa-vtestimonials__reel-ctrl svg {
     3377    width: 1rem;
     3378    height: 1rem;
     3379    fill: #ffffff;
     3380    stroke: #ffffff;
     3381    color: #ffffff;
     3382}
     3383
    32103384/* ── Responsive ──────────────────────────────────────────────────────── */
    32113385
     
    32143388        grid-template-columns: repeat(2, minmax(0, 1fr));
    32153389    }
     3390
     3391    .nfa-vtestimonials__reel {
     3392        grid-template-columns: repeat(2, minmax(0, 1fr));
     3393    }
    32163394}
    32173395
     
    32243402        height: 180px;
    32253403    }
    3226 }
     3404
     3405    .nfa-vtestimonials__reel {
     3406        grid-template-columns: 1fr;
     3407        max-width: 320px;
     3408        margin-inline: auto;
     3409    }
     3410}
  • nebula-forge-addons-for-elementor/trunk/assets/css/frontend.min.css

    r3463206 r3463463  
    1 .nfa-hero-cta{color:#131313;display:flex;flex-direction:column;gap:24px;text-decoration:none}.nfa-hero-cta__kicker{letter-spacing:0.2em;text-transform:uppercase;font-size:0.85rem;opacity:0.7;margin:0;position:relative}.nfa-hero-cta__headline{font-size:clamp(2.5rem,4vw,3.5rem);line-height:1.1;margin:0;position:relative;letter-spacing:-0.02em}.nfa-hero-cta__body{font-size:1.1rem;max-width:640px;margin:0;opacity:0.85;line-height:1.7;position:relative}.nfa-hero-cta__button{align-self:flex-start;padding:14px 32px;border-radius:999px;font-weight:600;color:#0f172a;background:#ff6b35;text-decoration:none;transition:transform 0.3s ease,box-shadow 0.3s ease,background 0.3s ease;box-shadow:0 1px 3px rgba(0,0,0,0.06),0 1px 2px rgba(0,0,0,0.04);position:relative;display:inline-flex;align-items:center;gap:8px}.nfa-hero-cta__button:hover,.nfa-hero-cta__button:focus-visible{transform:translateY(-3px) scale(1.02);box-shadow:0 8px 30px rgba(255,107,53,0.15);background:#ff7d4f}.nfa-hero-cta__button:active{transform:translateY(-1px) scale(0.99)}.nfa-feature-list{display:flex;flex-direction:column;gap:24px}.nfa-feature-list__items{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:20px}.nfa-feature-list__item{display:grid;grid-template-columns:auto 1fr;gap:14px;align-items:flex-start;padding:20px;border-radius:16px;background:#ffffff;border:1px solid rgba(19,19,19,0.1);transition:background 0.2s ease,border-color 0.2s ease,transform 0.2s ease}.nfa-feature-list__item:hover{background:#f8f9fa;border-color:#0ea5e9;transform:translateY(-2px)}.nfa-feature-list__icon-wrap{display:inline-flex;justify-content:center;align-items:center;padding:10px;border-radius:12px;background:rgba(14,165,233,0.08);transition:background 0.2s ease}.nfa-feature-list__item:hover .nfa-feature-list__icon-wrap{background:rgba(14,165,233,0.08)}.nfa-feature-list__icon{color:#0ea5e9;font-size:24px;line-height:1}.nfa-feature-list__title{margin:0 0 4px 0;color:#131313;font-size:1.05rem;font-weight:600}.nfa-feature-list__text{margin:0;color:rgba(19,19,19,0.55);font-size:0.95rem;line-height:1.6}.nfa-spotlight-card{display:grid;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));gap:32px;align-items:center}.nfa-spotlight-card__content{display:flex;flex-direction:column;gap:14px}.nfa-spotlight-card__eyebrow{margin:0;letter-spacing:0.15em;text-transform:uppercase;color:#0ea5e9;font-size:0.78rem;font-weight:600}.nfa-spotlight-card__title{margin:0;color:#131313;font-size:clamp(1.9rem,3vw,2.4rem);letter-spacing:-0.01em}.nfa-spotlight-card__description{margin:0;color:rgba(19,19,19,0.55);font-size:1.02rem;line-height:1.7}.nfa-spotlight-card__meta{margin:0;color:rgba(19,19,19,0.4);font-size:0.95rem}.nfa-spotlight-card__button{align-self:flex-start;padding:14px 28px;border-radius:999px;font-weight:600;color:#0f172a;background:#ff6b35;text-decoration:none;transition:transform 0.3s ease,box-shadow 0.3s ease,background 0.3s ease;box-shadow:0 1px 3px rgba(0,0,0,0.06),0 1px 2px rgba(0,0,0,0.04);display:inline-flex;align-items:center;gap:8px}.nfa-spotlight-card__button:hover,.nfa-spotlight-card__button:focus-visible{transform:translateY(-3px) scale(1.02);box-shadow:0 8px 30px rgba(255,107,53,0.15);background:#ff7d4f}.nfa-spotlight-card__media img{width:100%;height:auto;border-radius:20px;display:block;transition:transform 0.3s ease}.nfa-spotlight-card:hover .nfa-spotlight-card__media img{transform:scale(1.02)}.nfa-stats-grid{display:flex;flex-direction:column;gap:28px}.nfa-stats-grid__items{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:20px}.nfa-stats-grid__item{padding:24px;border-radius:18px;background:#ffffff;border:1px solid rgba(19,19,19,0.1);display:grid;row-gap:8px;transition:background 0.2s ease,border-color 0.2s ease,transform 0.2s ease}.nfa-stats-grid__item:hover{background:#f8f9fa;border-color:#0ea5e9;transform:translateY(-2px)}.nfa-stats-grid__value{color:#131313;font-weight:700;font-size:2rem;line-height:1.2;letter-spacing:-0.02em}.nfa-stats-grid__label{color:rgba(19,19,19,0.55);font-weight:600;font-size:1rem}.nfa-stats-grid__helper{color:rgba(19,19,19,0.4);font-size:0.9rem;line-height:1.5}.nfa-pricing-table{display:flex;flex-direction:column;gap:20px;color:#131313;position:relative;transition:transform 0.3s ease,box-shadow 0.3s ease}.nfa-pricing-table:hover{transform:translateY(-4px)}.nfa-pricing-table__badge{position:absolute;top:18px;right:18px;background:#ff6b35;color:#0f172a;padding:6px 14px;border-radius:999px;font-size:0.7rem;font-weight:700;letter-spacing:0.08em;text-transform:uppercase;box-shadow:0 4px 12px rgba(255,107,53,0.15)}.nfa-pricing-table__label{margin:0 0 6px 0;font-size:1.4rem}.nfa-pricing-table__description{margin:0;color:rgba(19,19,19,0.55);line-height:1.6}.nfa-pricing-table__price{display:flex;align-items:baseline;gap:8px}.nfa-pricing-table__amount{font-size:2.6rem;font-weight:700;line-height:1;letter-spacing:-0.02em}.nfa-pricing-table__suffix{font-size:1rem;color:rgba(19,19,19,0.4)}.nfa-pricing-table__features{list-style:none;padding:0;margin:0;display:grid;gap:12px}.nfa-pricing-table__features li{display:flex;align-items:flex-start;gap:12px;color:rgba(19,19,19,0.55);line-height:1.5}.nfa-pricing-table__features li::before{content:'\2713';color:#0ea5e9;font-weight:700;font-size:0.9rem;margin-top:1px;flex-shrink:0}.nfa-pricing-table__button{align-self:flex-start;padding:14px 28px;border-radius:999px;font-weight:600;color:#0f172a;background:#ff6b35;text-decoration:none;transition:transform 0.3s ease,box-shadow 0.3s ease,background 0.3s ease;box-shadow:0 1px 3px rgba(0,0,0,0.06),0 1px 2px rgba(0,0,0,0.04);display:inline-flex;align-items:center;gap:8px}.nfa-pricing-table__button:hover,.nfa-pricing-table__button:focus-visible{transform:translateY(-3px) scale(1.02);box-shadow:0 8px 30px rgba(255,107,53,0.15);background:#ff7d4f}.nfa-testimonials{display:flex;flex-direction:column;gap:24px}.nfa-testimonials__grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:20px}.nfa-testimonials__card{background:#ffffff;border-radius:18px;padding:24px;display:flex;flex-direction:column;gap:16px;border:1px solid rgba(19,19,19,0.1);transition:background 0.2s ease,border-color 0.2s ease,transform 0.2s ease}.nfa-testimonials__card:hover{background:#f8f9fa;border-color:#0ea5e9;transform:translateY(-2px)}.nfa-testimonials__avatar img{width:48px;height:48px;border-radius:50%;object-fit:cover;display:block;border:2px solid rgba(19,19,19,0.1)}.nfa-testimonials__quote{margin:0;color:rgba(19,19,19,0.55);font-size:1rem;line-height:1.7;font-style:normal}blockquote.nfa-testimonials__quote{border:0;padding:0}.nfa-testimonials__footer{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-top:auto}.nfa-testimonials__name{font-weight:600;color:#131313}.nfa-testimonials__role{color:rgba(19,19,19,0.4);font-size:0.9rem}.nfa-testimonials__rating{font-size:0.9rem;letter-spacing:1px;color:#fbbf24}.nfa-logo-grid{display:flex;flex-direction:column;gap:24px}.nfa-logo-grid__items{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:24px;align-items:center}.nfa-logo-grid__logo{display:flex;align-items:center;justify-content:center;padding:20px;border-radius:14px;background:#ffffff;border:1px solid rgba(19,19,19,0.1);min-height:86px;transition:background 0.2s ease,border-color 0.2s ease,transform 0.2s ease}.nfa-logo-grid__logo:hover{background:#f8f9fa;border-color:#0ea5e9;transform:translateY(-3px)}.nfa-logo-grid__logo img{max-width:140px;width:100%;height:auto;opacity:0.7;transition:opacity 0.2s ease,filter 0.2s ease;filter:grayscale(20%)}.nfa-logo-grid__logo:hover img{opacity:1;filter:grayscale(0%)}.nfa-logo-grid__text{color:#131313;font-weight:600}.nfa-faq{display:flex;flex-direction:column;gap:24px}.nfa-faq__items{display:grid;gap:12px}.nfa-faq__item{background:#ffffff;border-radius:16px;padding:20px 22px;border:1px solid rgba(19,19,19,0.1);transition:background 0.2s ease,border-color 0.2s ease}.nfa-faq__item:hover{border-color:#0ea5e9}.nfa-faq__item[open]{background:#f8f9fa;border-color:#0ea5e9}.nfa-faq__question{cursor:pointer;font-weight:600;color:#131313;list-style:none;display:flex;align-items:center;justify-content:space-between;gap:14px;user-select:none}.nfa-faq__question::after{content:'+';font-size:1.2rem;color:#0ea5e9;transition:transform 0.2s ease;flex-shrink:0;width:28px;height:28px;display:flex;align-items:center;justify-content:center;border-radius:50%;background:rgba(14,165,233,0.08)}.nfa-faq__item[open] .nfa-faq__question::after{content:'\2212';transform:rotate(180deg)}.nfa-faq__question::-webkit-details-marker{display:none}.nfa-faq__answer{margin-top:14px;color:rgba(19,19,19,0.55);line-height:1.7}.nfa-steps{display:flex;flex-direction:column;gap:24px}.nfa-steps__list{display:grid;gap:20px}.nfa-steps--vertical .nfa-steps__list{grid-template-columns:1fr}.nfa-steps--horizontal .nfa-steps__list{grid-template-columns:repeat(3,minmax(0,1fr))}.nfa-steps__item{background:#ffffff;border-radius:18px;padding:24px;display:flex;flex-direction:column;gap:10px;border:1px solid rgba(19,19,19,0.1);transition:background 0.2s ease,border-color 0.2s ease,transform 0.2s ease;position:relative}.nfa-steps__item:hover{background:#f8f9fa;border-color:#0ea5e9;transform:translateY(-2px)}.nfa-steps__label{text-transform:uppercase;letter-spacing:0.12em;font-size:0.72rem;color:#0ea5e9;font-weight:700}.nfa-steps__title{margin:0;font-size:1.1rem;color:#131313;font-weight:600}.nfa-steps__description{margin:0;color:rgba(19,19,19,0.55);line-height:1.6;font-size:0.95rem}.nfa-slider{position:relative}.nfa-slider__track{display:flex;gap:20px;overflow-x:auto;scroll-snap-type:x mandatory;scroll-behavior:smooth;padding-bottom:6px;scrollbar-width:none;-ms-overflow-style:none}.nfa-slider__track::-webkit-scrollbar{display:none}.nfa-slider__item{flex:0 0 100%;scroll-snap-align:start}.nfa-slider__btn{position:absolute;top:50%;transform:translateY(-50%);width:40px;height:40px;border-radius:999px;border:1px solid rgba(19,19,19,0.1);background:#131313;color:#131313;display:inline-flex;align-items:center;justify-content:center;cursor:pointer;box-shadow:0 8px 20px rgb(15 23 42 / 0.3);transition:transform 0.2s ease,box-shadow 0.2s ease,background 0.2s ease,border-color 0.2s ease;z-index:2}.nfa-slider__btn--prev{left:-16px}.nfa-slider__btn--next{right:-16px}.nfa-slider__btn:hover{transform:translateY(-50%) scale(1.08);background:rgba(255,255,255,0.08);border-color:#0ea5e9}.nfa-slider__btn:focus-visible{outline:none;box-shadow:0 0 0 3px rgba(125,211,252,0.3)}.nfa-showcase{position:relative}.nfa-showcase__nav{display:flex;gap:12px;margin-bottom:24px;justify-content:flex-end}.nfa-showcase__arrow{width:48px;height:48px;border-radius:50%;border:1.5px solid rgba(19,19,19,0.15);background:transparent;color:#fff;font-size:16px;cursor:pointer;display:flex;align-items:center;justify-content:center;transition:all 0.3s ease}.nfa-showcase__arrow:hover{background:#131313;color:#F4F4F4;border-color:#131313}.nfa-showcase__viewport{overflow:hidden}.nfa-showcase__track{display:flex;transition:transform 0.5s cubic-bezier(0.25,0.46,0.45,0.94);will-change:transform}.nfa-showcase__card{flex-shrink:0;position:relative;height:420px;border-radius:20px;overflow:hidden;transition:transform 0.35s ease;text-decoration:none;display:block}.nfa-showcase__card:hover{transform:translateY(-4px)}.nfa-showcase__img{position:absolute;inset:0;z-index:0}.nfa-showcase__img img{width:100%;height:100%;object-fit:cover;transition:transform 0.5s ease}.nfa-showcase__card:hover .nfa-showcase__img img{transform:scale(1.08)}.nfa-showcase__card--overlay-dark .nfa-showcase__img::after{content:'';position:absolute;inset:0;background:linear-gradient(to top,rgba(19,19,19,0.92) 0%,rgba(19,19,19,0.5) 50%,rgba(19,19,19,0.15) 100%);z-index:1}.nfa-showcase__card--overlay-light .nfa-showcase__img::after{content:'';position:absolute;inset:0;background:linear-gradient(to top,rgba(255,255,255,0.92) 0%,rgba(255,255,255,0.4) 50%,transparent 100%);z-index:1}.nfa-showcase__badge{position:absolute;top:20px;left:20px;background:rgba(244,244,244,0.15);backdrop-filter:blur(10px);color:#F4F4F4;padding:5px 16px;border-radius:50px;font-size:11px;font-weight:600;letter-spacing:0.5px;text-transform:uppercase;z-index:2;border:1px solid rgba(244,244,244,0.1)}.nfa-showcase__body{position:absolute;bottom:0;left:0;right:0;padding:32px 28px;z-index:2}.nfa-showcase__title{font-size:22px;font-weight:700;color:#F4F4F4;margin-bottom:12px}.nfa-showcase__desc{font-size:14px;color:rgba(244,244,244,0.65);line-height:1.8;margin:0}.nfa-showcase__tags{display:flex;flex-wrap:wrap;gap:8px;margin-top:16px}.nfa-showcase__tag{font-size:11px;padding:4px 12px;border-radius:50px;border:1px solid rgba(244,244,244,0.12);color:rgba(244,244,244,0.6);letter-spacing:0.3px}.nfa-showcase__dots{display:flex;justify-content:center;gap:8px;margin-top:24px}.nfa-showcase__dot{width:10px;height:10px;border-radius:50%;background:rgba(19,19,19,0.2);border:none;cursor:pointer;padding:0;transition:background 0.3s ease,transform 0.3s ease}.nfa-showcase__dot--active{background:#131313;transform:scale(1.2)}.nfa-showcase__dot:hover:not(.nfa-showcase__dot--active){background:rgba(19,19,19,0.4)}.nfa-areas__grid{display:grid;grid-template-columns:repeat(3,1fr);gap:24px}.nfa-areas__grid--featured .nfa-areas__card:first-child{grid-row:1 / 3}.nfa-areas__card{background:#ffffff;border-radius:18px;overflow:hidden;position:relative;transition:all 0.4s ease;display:block;text-decoration:none;color:inherit}a.nfa-areas__card:hover{text-decoration:none;color:inherit}.nfa-areas__card--shadow-sm{box-shadow:0 1px 3px rgba(0,0,0,0.06),0 1px 2px rgba(0,0,0,0.04)}.nfa-areas__card--shadow-md{box-shadow:0 4px 12px rgba(0,0,0,0.08)}.nfa-areas__card--shadow-lg{box-shadow:0 10px 30px rgba(0,0,0,0.12)}.nfa-areas__card:hover{box-shadow:0 10px 30px rgba(0,0,0,0.12)}.nfa-areas__img{height:200px;overflow:hidden;position:relative}.nfa-areas__img img{width:100%;height:100%;object-fit:cover;transition:transform 0.6s ease}.nfa-areas__badge{position:absolute;top:16px;left:16px;background:#131313;color:#F4F4F4;padding:5px 16px;border-radius:50px;font-size:11px;font-weight:600;letter-spacing:0.5px;text-transform:uppercase;z-index:3}.nfa-areas__body{padding:24px}.nfa-areas__title{font-size:19px;font-weight:600;margin:0 0 8px;color:#131313}.nfa-areas__desc{font-size:14px;color:rgba(19,19,19,0.55);line-height:1.7;margin:0}.nfa-areas__card--featured{position:relative}.nfa-areas__card--featured .nfa-areas__img{position:absolute;inset:0;height:100%;z-index:0}.nfa-areas__overlay{position:absolute;inset:0;z-index:1;pointer-events:none}.nfa-areas__card--featured .nfa-areas__body{position:absolute;bottom:0;left:0;right:0;z-index:2;padding:32px 28px}.nfa-areas__card--featured .nfa-areas__title{color:#F4F4F4;font-size:24px;margin-bottom:12px}.nfa-areas__card--featured .nfa-areas__desc{color:rgba(244,244,244,0.65);font-size:14px;line-height:1.8}.nfa-areas__card--featured .nfa-areas__badge{background:rgba(244,244,244,0.15);backdrop-filter:blur(10px);border:1px solid rgba(244,244,244,0.1);z-index:2}.nfa-journey__steps{display:grid;grid-template-columns:repeat(5,minmax(0,1fr));gap:24px;position:relative}.nfa-journey__steps--line::before{content:'';position:absolute;top:36px;left:48px;right:48px;height:2px;background:linear-gradient(90deg,#131313,rgba(19,19,19,0.08));z-index:0}.nfa-journey__step{text-align:center;position:relative;z-index:1}.nfa-journey__number{width:72px;height:72px;display:inline-flex;align-items:center;justify-content:center;border-radius:999px;border:2px solid #131313;background:#ffffff;color:#131313;font-size:22px;font-weight:700;margin:0 auto 20px;transition:all 0.3s ease}.nfa-journey__step:hover .nfa-journey__number{background:#131313;color:#f4f4f4;box-shadow:0 8px 24px rgba(19,19,19,0.2);transform:scale(1.05)}.nfa-journey__step-title{margin:0 0 10px;font-size:16px;font-weight:600;color:#131313}.nfa-journey__step-description{margin:0;font-size:13px;line-height:1.7;color:rgba(19,19,19,0.45)}@media (max-width:900px){.nfa-feature-list__items,.nfa-stats-grid__items,.nfa-testimonials__grid,.nfa-logo-grid__items,.nfa-steps--horizontal .nfa-steps__list{grid-template-columns:1fr}.nfa-journey__steps{grid-template-columns:repeat(2,minmax(0,1fr))}.nfa-journey__steps--line::before{display:none}.nfa-areas__grid--featured .nfa-areas__card:first-child{grid-row:auto}.nfa-areas__card--featured .nfa-areas__img{position:relative;inset:auto;height:200px}.nfa-areas__card--featured .nfa-areas__overlay{display:none}.nfa-areas__card--featured .nfa-areas__body{position:relative;bottom:auto;left:auto;right:auto;padding:24px}.nfa-areas .nfa-areas__card--featured .nfa-areas__title{color:#131313 !important;font-size:19px !important;margin-bottom:8px}.nfa-areas .nfa-areas__card--featured .nfa-areas__desc{color:rgba(19,19,19,0.55) !important;font-size:14px;line-height:1.7}.nfa-areas .nfa-areas__card--featured .nfa-areas__badge{background:#131313 !important;color:#F4F4F4 !important;backdrop-filter:none;border:none !important}}@media (max-width:640px){.nfa-journey__steps{grid-template-columns:1fr}.nfa-slider__btn--prev{left:-8px}.nfa-slider__btn--next{right:-8px}}.nfa-team__grid{display:grid;gap:24px;grid-template-columns:repeat(var(--nfa-team-cols,3),1fr)}.nfa-team__card{background:#fff;border-radius:16px;overflow:hidden;text-align:center;transition:box-shadow 0.3s ease,transform 0.25s ease;box-shadow:0 1px 4px rgba(0,0,0,.06)}.nfa-team__card:hover{box-shadow:0 8px 24px rgba(0,0,0,.1);transform:translateY(-4px)}.nfa-team__card--layout-left{display:flex;text-align:left}.nfa-team__card--layout-left .nfa-team__photo{flex:0 0 140px;height:auto}.nfa-team__photo{width:100%;height:220px;object-fit:cover;display:block}.nfa-team__card--layout-circle .nfa-team__photo{width:120px;height:120px;border-radius:50%;margin:24px auto 0}.nfa-team__body{padding:20px}.nfa-team__name{margin:0 0 4px;font-size:1.15em;font-weight:600;color:#131313}.nfa-team__role{font-size:.875em;color:rgba(19,19,19,.55);margin-bottom:10px}.nfa-team__bio{font-size:.9em;color:rgba(19,19,19,.7);line-height:1.6;margin-bottom:14px}.nfa-team__social{display:flex;gap:10px;justify-content:center}.nfa-team__card--layout-left .nfa-team__social{justify-content:flex-start}.nfa-team__social a{display:inline-flex;align-items:center;justify-content:center;width:34px;height:34px;border-radius:50%;background:rgba(19,19,19,.06);color:#131313;font-size:15px;transition:background .25s,color .25s;text-decoration:none}.nfa-team__social a:hover{background:#0ea5e9;color:#fff}@media (max-width:767px){.nfa-team__grid{grid-template-columns:1fr}.nfa-team__card--layout-left{flex-direction:column;text-align:center}.nfa-team__card--layout-left .nfa-team__photo{flex:none;width:100%;height:200px}.nfa-team__card--layout-left .nfa-team__social{justify-content:center}}.nfa-cta-banner{border-radius:16px;padding:48px 40px;text-align:center;position:relative;overflow:hidden}.nfa-cta-banner--left{text-align:left}.nfa-cta-banner--side{display:flex;align-items:center;justify-content:space-between;text-align:left;gap:32px}.nfa-cta-banner__icon{font-size:40px;margin-bottom:16px;display:inline-block}.nfa-cta-banner__kicker{display:inline-block;font-size:.8em;font-weight:600;text-transform:uppercase;letter-spacing:.08em;margin-bottom:10px;opacity:.75}.nfa-cta-banner__title{margin:0 0 14px;font-size:1.75em;font-weight:700;line-height:1.25}.nfa-cta-banner__desc{font-size:1.05em;line-height:1.6;opacity:.85;max-width:640px;margin:0 auto 24px}.nfa-cta-banner--left .nfa-cta-banner__desc,.nfa-cta-banner--side .nfa-cta-banner__desc{margin-left:0}.nfa-cta-banner__actions{display:flex;gap:12px;flex-wrap:wrap}.nfa-cta-banner--center .nfa-cta-banner__actions{justify-content:center}.nfa-cta-banner__btn{display:inline-flex;align-items:center;padding:12px 28px;border-radius:8px;font-weight:600;font-size:.95em;text-decoration:none;transition:opacity .25s,transform .15s;border:none;cursor:pointer}.nfa-cta-banner__btn:hover{opacity:.88;transform:translateY(-1px)}@media (max-width:767px){.nfa-cta-banner{padding:32px 24px}.nfa-cta-banner--side{flex-direction:column;text-align:center}.nfa-cta-banner--side .nfa-cta-banner__actions{justify-content:center}}.nfa-tabs{display:flex;flex-direction:column;gap:0}.nfa-tabs--vertical{flex-direction:row;gap:24px}.nfa-tabs__nav{display:flex;gap:4px;border-bottom:2px solid rgba(19,19,19,.08);padding-bottom:0;overflow-x:auto;-webkit-overflow-scrolling:touch}.nfa-tabs--vertical .nfa-tabs__nav{flex-direction:column;border-bottom:none;border-right:2px solid rgba(19,19,19,.08);padding-right:0;padding-bottom:0;min-width:180px;overflow-x:visible}.nfa-tabs__btn{position:relative;display:inline-flex;align-items:center;gap:8px;padding:12px 24px;font-weight:500;font-size:.95em;background:transparent;border:none;color:rgba(19,19,19,.55);cursor:pointer;white-space:nowrap;transition:color .2s,background .2s;border-radius:8px 8px 0 0}.nfa-tabs--vertical .nfa-tabs__btn{border-radius:8px 0 0 8px;justify-content:flex-start;text-align:left;width:100%}.nfa-tabs__btn:hover{color:#131313;background:rgba(19,19,19,.03)}.nfa-tabs__btn--active{color:#0ea5e9;background:rgba(14,165,233,.08)}.nfa-tabs__btn--active::after{content:'';position:absolute;bottom:-2px;left:0;right:0;height:3px;background:#0ea5e9;border-radius:3px 3px 0 0}.nfa-tabs--vertical .nfa-tabs__btn--active::after{bottom:auto;top:0;left:auto;right:-2px;width:3px;height:100%;border-radius:0 3px 3px 0}.nfa-tabs__btn--icon-top{flex-direction:column}.nfa-tabs__btn-icon{font-size:18px;line-height:1;display:flex;align-items:center;justify-content:center}.nfa-tabs__panels{flex:1}.nfa-tabs__panel{display:none;padding:24px;color:rgba(19,19,19,.7);line-height:1.7;border-radius:0 0 12px 12px}.nfa-tabs--vertical .nfa-tabs__panel{border-radius:0 12px 12px 0}.nfa-tabs__panel--active{display:block}@media (max-width:767px){.nfa-tabs--vertical{flex-direction:column}.nfa-tabs--vertical .nfa-tabs__nav{flex-direction:row;border-right:none;border-bottom:2px solid rgba(19,19,19,.08);min-width:0;overflow-x:auto}.nfa-tabs--vertical .nfa-tabs__btn{border-radius:8px 8px 0 0}.nfa-tabs--vertical .nfa-tabs__btn--active::after{bottom:-2px;top:auto;right:0;left:0;width:auto;height:3px;border-radius:3px 3px 0 0}.nfa-tabs--vertical .nfa-tabs__panel{border-radius:0 0 12px 12px}}.nfa-compare{position:relative;overflow:hidden;border-radius:12px;user-select:none;touch-action:none;cursor:col-resize;line-height:0}.nfa-compare--vertical{cursor:row-resize}.nfa-compare__before,.nfa-compare__after{position:relative;width:100%}.nfa-compare__before{position:absolute;top:0;left:0;z-index:2;height:100%;overflow:hidden}.nfa-compare__before img,.nfa-compare__after img{display:block;width:100%;height:100%;object-fit:cover;pointer-events:none}.nfa-compare__label{position:absolute;bottom:16px;padding:4px 14px;font-size:.8em;font-weight:600;color:#fff;background:rgba(0,0,0,.55);border-radius:6px;z-index:5;pointer-events:none;transition:opacity .3s}.nfa-compare__label--before{left:16px}.nfa-compare__label--after{right:16px}.nfa-compare--vertical .nfa-compare__label--before{top:16px;bottom:auto;left:16px}.nfa-compare--vertical .nfa-compare__label--after{bottom:16px;right:auto;left:16px}.nfa-compare--hover-labels .nfa-compare__label{opacity:0}.nfa-compare--hover-labels:hover .nfa-compare__label{opacity:1}.nfa-compare__slider{position:absolute;top:0;bottom:0;z-index:10;display:flex;align-items:center;justify-content:center}.nfa-compare--horizontal .nfa-compare__slider{flex-direction:column;width:0}.nfa-compare--vertical .nfa-compare__slider{top:auto;left:0;right:0;flex-direction:row;height:0}.nfa-compare__line{position:absolute}.nfa-compare--horizontal .nfa-compare__line{width:3px;top:0;bottom:0;background:#fff}.nfa-compare--vertical .nfa-compare__line{height:3px;left:0;right:0;background:#fff}.nfa-compare__handle{position:relative;z-index:11;width:40px;height:40px;border-radius:50%;background:#fff;display:flex;align-items:center;justify-content:center;box-shadow:0 2px 8px rgba(0,0,0,.25);color:#131313;cursor:inherit;flex-shrink:0}.nfa-compare__handle svg{width:14px;height:14px}.nfa-countdown{display:flex;align-items:center;justify-content:center;flex-wrap:wrap;gap:16px}.nfa-countdown__block{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:20px;min-width:80px;border-radius:12px;background:rgba(19,19,19,.04);transition:transform .25s,box-shadow .25s;position:relative}.nfa-countdown__block:hover{transform:translateY(-3px);box-shadow:0 4px 16px rgba(0,0,0,.08)}.nfa-countdown__digit{font-size:2.5em;font-weight:700;line-height:1.1;color:#131313;font-variant-numeric:tabular-nums}.nfa-countdown__label{font-size:.8em;font-weight:500;color:rgba(19,19,19,.55);text-transform:uppercase;letter-spacing:.06em;margin-top:8px}.nfa-countdown__sep{font-size:2em;font-weight:700;color:rgba(19,19,19,.3);line-height:1;align-self:flex-start;padding-top:20px}.nfa-countdown--inline .nfa-countdown__block{background:transparent;padding:10px 6px;min-width:auto;border-radius:0}.nfa-countdown--inline .nfa-countdown__block:hover{transform:none;box-shadow:none}.nfa-countdown__block--circle{position:relative;background:transparent;padding:0;width:120px;height:120px;border-radius:50%}.nfa-countdown__block--circle:hover{transform:none;box-shadow:none}.nfa-countdown__ring{position:absolute;top:0;left:0;width:100%;height:100%}.nfa-countdown__progress{transition:stroke-dashoffset .6s ease}.nfa-countdown__block--circle .nfa-countdown__digit{font-size:1.6em}.nfa-countdown__block--circle .nfa-countdown__label{font-size:.65em;margin-top:2px}.nfa-countdown__expiry{width:100%;text-align:center;font-size:1.2em;font-weight:600;color:#131313;padding:24px}@media (max-width:480px){.nfa-countdown__digit{font-size:1.8em}.nfa-countdown__block{min-width:60px;padding:14px}.nfa-countdown__block--circle{width:80px;height:80px}.nfa-countdown__block--circle .nfa-countdown__digit{font-size:1.2em}}.nfa-tooltip{position:absolute;z-index:99999;max-width:260px;padding:8px 14px;border-radius:6px;background:#1e293b;color:#fff;font-size:13px;line-height:1.5;text-align:center;pointer-events:none;opacity:0;visibility:hidden;transition:opacity 0.25s ease,visibility 0.25s ease,transform 0.25s ease;white-space:normal;word-wrap:break-word;box-shadow:0 4px 12px rgba(0,0,0,0.15)}.nfa-tooltip--visible{opacity:1;visibility:visible}.nfa-tooltip::after{content:'';position:absolute;width:0;height:0;border:6px solid transparent}.nfa-tooltip--no-arrow::after{display:none}.nfa-tooltip--top{transform:translateY(6px)}.nfa-tooltip--top.nfa-tooltip--visible{transform:translateY(0)}.nfa-tooltip--top::after{top:100%;left:50%;transform:translateX(-50%);border-top-color:inherit}.nfa-tooltip--bottom{transform:translateY(-6px)}.nfa-tooltip--bottom.nfa-tooltip--visible{transform:translateY(0)}.nfa-tooltip--bottom::after{bottom:100%;left:50%;transform:translateX(-50%);border-bottom-color:inherit}.nfa-tooltip--left{transform:translateX(6px)}.nfa-tooltip--left.nfa-tooltip--visible{transform:translateX(0)}.nfa-tooltip--left::after{left:100%;top:50%;transform:translateY(-50%);border-left-color:inherit}.nfa-tooltip--right{transform:translateX(-6px)}.nfa-tooltip--right.nfa-tooltip--visible{transform:translateX(0)}.nfa-tooltip--right::after{right:100%;top:50%;transform:translateY(-50%);border-right-color:inherit}[data-nfa-wrapper-link]{cursor:pointer;position:relative}[data-nfa-wrapper-link]:focus-visible{outline:2px solid currentColor;outline-offset:2px}.nfa-hamburger__toggle-wrap{display:flex}.nfa-hamburger__toggle{display:inline-flex;align-items:center;justify-content:center;border:none;cursor:pointer;line-height:1;transition:background 0.2s ease,color 0.2s ease}.nfa-hamburger__icon--bars{display:flex;flex-direction:column;gap:4px;width:1em}.nfa-hamburger__icon--bars span{display:block;height:2px;background:currentColor;border-radius:2px;transition:transform 0.3s ease,opacity 0.3s ease}.nfa-hamburger__icon--dots{display:flex;flex-direction:column;gap:4px;align-items:center;width:1em}.nfa-hamburger__icon--dots span{display:block;width:5px;height:5px;background:currentColor;border-radius:50%}.nfa-hamburger__icon--grid{display:grid;grid-template-columns:repeat(2,1fr);gap:3px;width:1em}.nfa-hamburger__icon--grid span{display:block;width:7px;height:7px;background:currentColor;border-radius:2px}.nfa-hamburger__overlay{position:fixed;inset:0;z-index:99998;opacity:0;visibility:hidden;transition:opacity 0.35s ease,visibility 0.35s ease}.nfa-hamburger--open .nfa-hamburger__overlay{opacity:1;visibility:visible}.nfa-hamburger__panel{position:fixed;z-index:99999;background:#fff;overflow-y:auto;-webkit-overflow-scrolling:touch;transition:transform 0.35s cubic-bezier(0.4,0,0.2,1),visibility 0.35s ease;visibility:hidden}.nfa-hamburger__panel--left{top:0;left:0;bottom:0;transform:translateX(-100%)}.nfa-hamburger__panel--right{top:0;right:0;bottom:0;transform:translateX(100%)}.nfa-hamburger__panel--top{top:0;left:0;right:0;max-height:80vh;transform:translateY(-100%)}.nfa-hamburger--open .nfa-hamburger__panel{transform:translate(0);visibility:visible}.nfa-hamburger__panel-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:16px}.nfa-hamburger__logo{max-height:40px;width:auto}.nfa-hamburger__close{background:none;border:none;font-size:28px;cursor:pointer;line-height:1;padding:4px 8px;transition:color 0.2s ease;margin-left:auto}.nfa-hamburger__list{list-style:none;margin:0;padding:0}.nfa-hamburger__item--separated{border-bottom:1px solid #e2e8f0}.nfa-hamburger__link{display:flex;align-items:center;gap:10px;text-decoration:none;font-size:15px;font-weight:500;transition:color 0.2s ease}.nfa-hamburger__link-icon{flex-shrink:0;font-size:1.1em}.nfa-hamburger__arrow{margin-left:auto;font-size:12px;transition:transform 0.25s ease}.nfa-hamburger__item--sub-open > .nfa-hamburger__link .nfa-hamburger__arrow{transform:rotate(180deg)}.nfa-hamburger__sub-list{list-style:none;margin:0;padding:4px 0 4px 24px;display:none}.nfa-hamburger__item--sub-open > .nfa-hamburger__sub-list{display:block}.nfa-hamburger__sub-link{display:block;padding:6px 0;text-decoration:none;font-size:14px;transition:color 0.2s ease}.nfa-form__fields{display:flex;flex-wrap:wrap;gap:16px}.nfa-form__col--100{width:100%}.nfa-form__col--75{width:calc(75% - 8px)}.nfa-form__col--66{width:calc(66.666% - 8px)}.nfa-form__col--50{width:calc(50% - 8px)}.nfa-form__col--33{width:calc(33.333% - 8px)}.nfa-form__col--25{width:calc(25% - 12px)}.nfa-form__col--hidden{display:none}.nfa-form__label{display:block;font-weight:600;font-size:13px;margin-bottom:6px}.nfa-form__required{color:#ef4444;margin-left:2px}.nfa-form__input,.nfa-form__select,.nfa-form__textarea{display:block;width:100%;border:1px solid #cbd5e1;font-size:14px;line-height:1.5;transition:border-color 0.2s ease,box-shadow 0.2s ease;outline:none;box-sizing:border-box}.nfa-form__input:focus,.nfa-form__select:focus,.nfa-form__textarea:focus{border-color:#6366f1;box-shadow:0 0 0 3px rgba(99,102,241,0.1)}.nfa-form__input--file{padding:8px;border-style:dashed}.nfa-form__textarea{resize:vertical;min-height:100px}.nfa-form__choice-group{display:flex;flex-wrap:wrap;gap:12px}.nfa-form__choice{display:flex;align-items:center;gap:6px;font-size:14px;cursor:pointer}.nfa-form__choice input{accent-color:#6366f1;width:16px;height:16px}.nfa-form__field-error{display:block;font-size:12px;color:#ef4444;min-height:18px;margin-top:4px}.nfa-form__actions{display:flex;margin-top:20px}.nfa-form__submit{display:inline-flex;align-items:center;gap:8px;border:none;font-weight:600;cursor:pointer;transition:background 0.2s ease,transform 0.15s ease}.nfa-form__submit:hover{transform:translateY(-1px)}.nfa-form__submit:active{transform:translateY(0)}.nfa-form__submit:disabled{opacity:0.6;cursor:not-allowed;transform:none}.nfa-form__spinner{display:inline-block;width:16px;height:16px;border:2px solid rgba(255,255,255,0.3);border-top-color:#fff;border-radius:50%;animation:nfa-spin 0.6s linear infinite}@keyframes nfa-spin{to{transform:rotate(360deg)}}.nfa-form__msg{padding:14px 18px;border-radius:8px;font-size:14px;font-weight:500;margin-top:16px}.nfa-form__msg--success{background:#f0fdf4;color:#166534;border:1px solid #bbf7d0}.nfa-form__msg--error{background:#fef2f2;color:#991b1b;border:1px solid #fecaca}.nfa-form__input--invalid,.nfa-form__select--invalid,.nfa-form__textarea--invalid{border-color:#ef4444 !important;box-shadow:0 0 0 3px rgba(239,68,68,0.1) !important}@media (max-width:767px){.nfa-form__col--75,.nfa-form__col--66,.nfa-form__col--50,.nfa-form__col--33,.nfa-form__col--25{width:100%}}.nfa-badge{display:inline-block;padding:2px 10px;border-radius:999px;font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:0.04em}.nfa-badge--blue{background:#eef2ff;color:#4f46e5}.nfa-badge--gray{background:#f1f5f9;color:#64748b}.nfa-sub-row--unread td{background:#fafbff;font-weight:500}.nfa-ncards{position:relative}.nfa-ncards__grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:20px}.nfa-ncards__card{background:#e8e4de;border-radius:16px;padding:28px;display:flex;flex-direction:column;transition:box-shadow 0.3s ease,transform 0.25s ease}.nfa-ncards--grid .nfa-ncards__card:hover{transform:translateY(-4px)}.nfa-ncards__header{display:flex;align-items:flex-start;justify-content:space-between;margin-bottom:16px}.nfa-ncards__number{font-size:2.5rem;font-weight:300;line-height:1;color:#3b3a2f;font-style:italic}.nfa-ncards__icon{display:inline-flex;align-items:center;justify-content:center;font-size:28px;color:#3b3a2f;line-height:1}.nfa-ncards__icon svg{width:28px;height:28px}.nfa-ncards__image{display:inline-flex;align-items:center;justify-content:center;width:120px;height:120px;flex-shrink:0}.nfa-ncards__image img{width:100%;height:100%;object-fit:contain}.nfa-ncards__body{flex:1}.nfa-ncards__title{font-size:0.95rem;font-weight:700;text-transform:uppercase;letter-spacing:0.06em;color:#3b3a2f;margin:0 0 12px 0;line-height:1.3}.nfa-ncards__desc{font-size:0.9rem;color:#3b3a2f;line-height:1.6;margin:0;opacity:0.85}.nfa-ncards--steps .nfa-ncards__card--step{background:#ffffff;border:1px solid #e8e4de;border-radius:16px;padding:32px 28px;display:flex;flex-direction:column;align-items:flex-start;position:relative;overflow:hidden;transition:box-shadow 0.3s ease,transform 0.25s ease}.nfa-ncards--steps .nfa-ncards__card--step:hover{box-shadow:0 8px 30px rgba(0,0,0,0.08);transform:translateY(-3px)}.nfa-ncards--steps .nfa-ncards__card--step::before{content:'';position:absolute;background-color:#b8976a;transition:opacity 0.3s ease;opacity:0}.nfa-ncards--steps .nfa-ncards__card--step:hover::before{opacity:1}.nfa-ncards-accent--left .nfa-ncards__card--step::before{top:0;left:0;width:4px;height:100%}.nfa-ncards-accent--right .nfa-ncards__card--step::before{top:0;right:0;width:4px;height:100%}.nfa-ncards-accent--top .nfa-ncards__card--step::before{top:0;left:0;width:100%;height:4px}.nfa-ncards-accent--bottom .nfa-ncards__card--step::before{bottom:0;left:0;width:100%;height:4px}.nfa-ncards-accent--none .nfa-ncards__card--step::before{display:none}.nfa-ncards__badge{display:inline-flex;align-items:center;justify-content:center;width:56px;height:56px;border-radius:50%;background-color:#1e3a5f;color:#ffffff;font-size:22px;flex-shrink:0;margin-bottom:14px;line-height:1}.nfa-ncards__badge svg{width:22px;height:22px;fill:currentColor}.nfa-ncards__badge--img{background:transparent;overflow:hidden}.nfa-ncards__badge--img img{width:100%;height:100%;object-fit:cover;border-radius:50%}.nfa-ncards__step-label{font-size:0.75rem;font-weight:600;text-transform:uppercase;letter-spacing:0.12em;color:#b8976a;margin-bottom:8px;display:block}.nfa-ncards__step-title{font-size:1.2rem;font-weight:700;font-style:italic;color:#1e3a5f;margin:0 0 14px 0;line-height:1.3}.nfa-ncards__divider{display:block;width:50px;height:3px;border-radius:2px;background-color:#1e3a5f;margin-bottom:16px}.nfa-ncards__step-desc{font-size:0.92rem;line-height:1.65;color:#666666;margin:0}.nfa-ncards--carousel{overflow:hidden;position:relative}.nfa-ncards__viewport{overflow:hidden}.nfa-ncards__track{display:flex;transition:transform 0.45s cubic-bezier(0.25,0.46,0.45,0.94);will-change:transform;cursor:grab;user-select:none;-webkit-user-select:none}.nfa-ncards--carousel.is-dragging .nfa-ncards__track{cursor:grabbing}.nfa-ncards--carousel .nfa-ncards__card{flex:0 0 calc((100% - 40px) / 3);display:flex;flex-direction:column;min-height:280px}.nfa-ncards--carousel .nfa-ncards__header{margin-bottom:20px;min-height:90px}.nfa-ncards--carousel .nfa-ncards__number{font-size:3rem}.nfa-ncards__nav{display:flex;gap:8px;margin-top:20px}.nfa-ncards--nav-bottom-right .nfa-ncards__nav{justify-content:flex-end}.nfa-ncards--nav-bottom-left .nfa-ncards__nav{justify-content:flex-start}.nfa-ncards--nav-bottom-center .nfa-ncards__nav{justify-content:center}.nfa-ncards--nav-top-right .nfa-ncards__nav,.nfa-ncards--nav-top-left .nfa-ncards__nav,.nfa-ncards--nav-top-center .nfa-ncards__nav{margin-top:0;margin-bottom:20px;order:-1}.nfa-ncards--nav-top-right .nfa-ncards__nav{justify-content:flex-end}.nfa-ncards--nav-top-left .nfa-ncards__nav{justify-content:flex-start}.nfa-ncards--nav-top-center .nfa-ncards__nav{justify-content:center}.nfa-ncards--nav-top-right,.nfa-ncards--nav-top-left,.nfa-ncards--nav-top-center{display:flex;flex-direction:column}.nfa-ncards--nav-sides{position:relative}.nfa-ncards__arrow--side{position:absolute;top:50%;transform:translateY(-50%);z-index:2}.nfa-ncards__arrow--side.nfa-ncards__arrow--prev{left:-48px}.nfa-ncards__arrow--side.nfa-ncards__arrow--next{right:-48px}@media (max-width:1200px){.nfa-ncards__arrow--side.nfa-ncards__arrow--prev{left:8px}.nfa-ncards__arrow--side.nfa-ncards__arrow--next{right:8px}}.nfa-ncards__arrow{display:inline-flex;align-items:center;justify-content:center;width:40px;height:40px;border-radius:50%;border:1.5px solid rgba(255,255,255,0.5);background:transparent;color:#ffffff;cursor:pointer;transition:background-color 0.25s ease,border-color 0.25s ease,transform 0.2s ease;padding:0}.nfa-ncards__arrow:hover{background-color:rgba(255,255,255,0.15);border-color:rgba(255,255,255,0.8);transform:scale(1.08)}.nfa-ncards__arrow--side:hover{transform:translateY(-50%) scale(1.08)}.nfa-ncards__arrow svg{width:16px;height:16px}.nfa-ncards__dots{display:flex;gap:8px;justify-content:center;margin-top:20px;padding:4px 0}.nfa-ncards__dot{width:10px;height:10px;border-radius:50%;border:none;background-color:rgba(255,255,255,0.4);cursor:pointer;padding:0;transition:background-color 0.25s ease,transform 0.2s ease}.nfa-ncards__dot:hover{transform:scale(1.3)}.nfa-ncards__dot.is-active{background-color:#ffffff;transform:scale(1.2)}@media (max-width:1024px){.nfa-ncards__grid{grid-template-columns:repeat(2,minmax(0,1fr))}}@media (max-width:767px){.nfa-ncards__grid{grid-template-columns:1fr}.nfa-ncards__number{font-size:2rem}.nfa-ncards--carousel .nfa-ncards__number{font-size:2.2rem}}.nfa-vtestimonials{position:relative}.nfa-vtestimonials__grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:24px}.nfa-vtestimonials__card{background:#ffffff;border-radius:16px;overflow:hidden;display:flex;flex-direction:column;transition:transform 0.35s ease,box-shadow 0.35s ease,background-color 0.35s ease,border-color 0.35s ease;cursor:pointer}.nfa-vtestimonials--lift .nfa-vtestimonials__card:hover{transform:translateY(-6px)}.nfa-vtestimonials__thumb{position:relative;height:220px;overflow:hidden;flex-shrink:0}.nfa-vtestimonials__thumb img{width:100%;height:100%;object-fit:cover;display:block;transition:transform 0.5s ease}.nfa-vtestimonials--thumb-zoom .nfa-vtestimonials__card:hover .nfa-vtestimonials__thumb img{transform:scale(1.08)}.nfa-vtestimonials__thumb::after{content:'';position:absolute;inset:0;background:rgba(0,0,0,0.25);transition:background 0.35s ease;pointer-events:none;z-index:1}.nfa-vtestimonials__card:hover .nfa-vtestimonials__thumb::after{background:rgba(0,0,0,0.45)}.nfa-vtestimonials__play{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);z-index:2;width:56px;height:56px;border-radius:50%;border:none;background-color:rgba(255,255,255,0.95);display:inline-flex;align-items:center;justify-content:center;cursor:pointer;transition:transform 0.35s ease,background-color 0.3s ease,box-shadow 0.3s ease;box-shadow:0 4px 20px rgba(0,0,0,0.15);padding:0}.nfa-vtestimonials__play svg{width:20px;height:20px;fill:#1a1a2e;margin-left:2px}.nfa-vtestimonials__card:hover .nfa-vtestimonials__play{transform:translate(-50%,-50%) scale(1.15);background-color:#ffffff;box-shadow:0 6px 30px rgba(0,0,0,0.2)}.nfa-vtestimonials__duration{position:absolute;bottom:10px;right:10px;z-index:2;background-color:rgba(0,0,0,0.7);color:#ffffff;font-size:0.75rem;font-weight:600;padding:3px 8px;border-radius:4px;line-height:1.3;letter-spacing:0.02em}.nfa-vtestimonials__content{padding:16px 16px 4px 16px;flex:1;display:flex;flex-direction:column}.nfa-vtestimonials__rating{color:#fbbf24;font-size:16px;line-height:1;margin-bottom:8px;letter-spacing:2px}.nfa-vtestimonials__quote{font-size:0.92rem;line-height:1.6;color:#333333;margin:0 0 12px 0;flex:1}.nfa-vtestimonials__author{display:flex;align-items:center;gap:10px;margin-top:auto;padding-top:10px}.nfa-vtestimonials__avatar{width:40px;height:40px;border-radius:50%;object-fit:cover;flex-shrink:0}.nfa-vtestimonials__author-info{min-width:0}.nfa-vtestimonials__name{font-size:0.9rem;font-weight:700;color:#1a1a2e;line-height:1.3;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.nfa-vtestimonials__role{font-size:0.8rem;color:#888888;line-height:1.3;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.nfa-vtestimonials-lightbox{position:fixed;inset:0;z-index:100000;display:flex;align-items:center;justify-content:center;background:rgba(0,0,0,0.85);opacity:0;visibility:hidden;transition:opacity 0.35s ease,visibility 0.35s ease}.nfa-vtestimonials-lightbox.is-open{opacity:1;visibility:visible}.nfa-vtestimonials-lightbox__inner{position:relative;width:90%;max-width:900px;aspect-ratio:16 / 9;background:#000;border-radius:12px;overflow:hidden;transform:scale(0.9);transition:transform 0.35s ease}.nfa-vtestimonials-lightbox.is-open .nfa-vtestimonials-lightbox__inner{transform:scale(1)}.nfa-vtestimonials-lightbox__inner iframe{width:100%;height:100%;border:0}.nfa-vtestimonials-lightbox__close{position:absolute;top:-40px;right:0;width:32px;height:32px;border-radius:50%;border:none;background:rgba(255,255,255,0.15);color:#ffffff;font-size:18px;cursor:pointer;display:inline-flex;align-items:center;justify-content:center;transition:background 0.25s ease;padding:0;line-height:1}.nfa-vtestimonials-lightbox__close:hover{background:rgba(255,255,255,0.3)}.nfa-vtestimonials__thumb--playing{position:relative}.nfa-vtestimonials__thumb--playing iframe{position:absolute;inset:0;width:100%;height:100%;border:0;z-index:5}.nfa-vtestimonials--carousel{overflow:hidden;position:relative}.nfa-vtestimonials__viewport{overflow:hidden}.nfa-vtestimonials__track{display:flex;transition:transform 0.45s cubic-bezier(0.25,0.46,0.45,0.94);will-change:transform;cursor:grab;user-select:none;-webkit-user-select:none}.nfa-vtestimonials--carousel.is-dragging .nfa-vtestimonials__track{cursor:grabbing}.nfa-vtestimonials--carousel .nfa-vtestimonials__card{flex:0 0 calc((100% - 48px) / 3);min-height:0}.nfa-vtestimonials__nav{display:flex;gap:8px;margin-top:20px}.nfa-vtestimonials--nav-bottom-right .nfa-vtestimonials__nav{justify-content:flex-end}.nfa-vtestimonials--nav-bottom-left .nfa-vtestimonials__nav{justify-content:flex-start}.nfa-vtestimonials--nav-bottom-center .nfa-vtestimonials__nav{justify-content:center}.nfa-vtestimonials--nav-top-right .nfa-vtestimonials__nav,.nfa-vtestimonials--nav-top-left .nfa-vtestimonials__nav,.nfa-vtestimonials--nav-top-center .nfa-vtestimonials__nav{margin-top:0;margin-bottom:20px;order:-1}.nfa-vtestimonials--nav-top-right .nfa-vtestimonials__nav{justify-content:flex-end}.nfa-vtestimonials--nav-top-left .nfa-vtestimonials__nav{justify-content:flex-start}.nfa-vtestimonials--nav-top-center .nfa-vtestimonials__nav{justify-content:center}.nfa-vtestimonials--nav-top-right,.nfa-vtestimonials--nav-top-left,.nfa-vtestimonials--nav-top-center{display:flex;flex-direction:column}.nfa-vtestimonials--nav-sides{position:relative}.nfa-vtestimonials__arrow--side{position:absolute;top:50%;transform:translateY(-50%);z-index:2}.nfa-vtestimonials__arrow--side.nfa-vtestimonials__arrow--prev{left:-48px}.nfa-vtestimonials__arrow--side.nfa-vtestimonials__arrow--next{right:-48px}@media (max-width:1200px){.nfa-vtestimonials__arrow--side.nfa-vtestimonials__arrow--prev{left:8px}.nfa-vtestimonials__arrow--side.nfa-vtestimonials__arrow--next{right:8px}}.nfa-vtestimonials__arrow{display:inline-flex;align-items:center;justify-content:center;width:40px;height:40px;border-radius:50%;border:1.5px solid #e0e0e0;background:#ffffff;color:#1a1a2e;cursor:pointer;transition:background-color 0.25s ease,border-color 0.25s ease,color 0.25s ease,transform 0.2s ease;padding:0}.nfa-vtestimonials__arrow:hover{background-color:#1a1a2e;border-color:#1a1a2e;color:#ffffff;transform:scale(1.08)}.nfa-vtestimonials__arrow--side:hover{transform:translateY(-50%) scale(1.08)}.nfa-vtestimonials__arrow svg{width:16px;height:16px}.nfa-vtestimonials__dots{display:flex;gap:8px;justify-content:center;margin-top:20px;padding:4px 0}.nfa-vtestimonials__dot{width:10px;height:10px;border-radius:50%;border:none;background-color:#d1d5db;cursor:pointer;padding:0;transition:background-color 0.25s ease,transform 0.2s ease}.nfa-vtestimonials__dot:hover{transform:scale(1.3)}.nfa-vtestimonials__dot.is-active{background-color:#1a1a2e;transform:scale(1.2)}@media (max-width:1024px){.nfa-vtestimonials__grid{grid-template-columns:repeat(2,minmax(0,1fr))}}@media (max-width:767px){.nfa-vtestimonials__grid{grid-template-columns:1fr}.nfa-vtestimonials__thumb{height:180px}}
     1.nfa-hero-cta{color:#131313;display:flex;flex-direction:column;gap:24px;text-decoration:none}.nfa-hero-cta__kicker{letter-spacing:.2em;text-transform:uppercase;font-size:.85rem;opacity:.7;margin:0;position:relative}.nfa-hero-cta__headline{font-size:clamp(2.5rem, 4vw, 3.5rem);line-height:1.1;margin:0;position:relative;letter-spacing:-.02em}.nfa-hero-cta__body{font-size:1.1rem;max-width:640px;margin:0;opacity:.85;line-height:1.7;position:relative}.nfa-hero-cta__button{align-self:flex-start;padding:14px 32px;border-radius:999px;font-weight:600;color:#0f172a;background:#ff6b35;text-decoration:none;transition:transform .3s ease,box-shadow .3s ease,background .3s ease;box-shadow:0 1px 3px rgba(0,0,0,.06),0 1px 2px rgba(0,0,0,.04);position:relative;display:inline-flex;align-items:center;gap:8px}.nfa-hero-cta__button:focus-visible,.nfa-hero-cta__button:hover{transform:translateY(-3px) scale(1.02);box-shadow:0 8px 30px rgba(255,107,53,.15);background:#ff7d4f}.nfa-hero-cta__button:active{transform:translateY(-1px) scale(.99)}.nfa-feature-list{display:flex;flex-direction:column;gap:24px}.nfa-feature-list__items{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:20px}.nfa-feature-list__item{display:grid;grid-template-columns:auto 1fr;gap:14px;align-items:flex-start;padding:20px;border-radius:16px;background:#fff;border:1px solid rgba(19,19,19,.1);transition:background .2s ease,border-color .2s ease,transform .2s ease}.nfa-feature-list__item:hover{background:#f8f9fa;border-color:#0ea5e9;transform:translateY(-2px)}.nfa-feature-list__icon-wrap{display:inline-flex;justify-content:center;align-items:center;padding:10px;border-radius:12px;background:rgba(14,165,233,.08);transition:background .2s ease}.nfa-feature-list__item:hover .nfa-feature-list__icon-wrap{background:rgba(14,165,233,.08)}.nfa-feature-list__icon{color:#0ea5e9;font-size:24px;line-height:1}.nfa-feature-list__title{margin:0 0 4px 0;color:#131313;font-size:1.05rem;font-weight:600}.nfa-feature-list__text{margin:0;color:rgba(19,19,19,.55);font-size:.95rem;line-height:1.6}.nfa-spotlight-card{display:grid;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));gap:32px;align-items:center}.nfa-spotlight-card__content{display:flex;flex-direction:column;gap:14px}.nfa-spotlight-card__eyebrow{margin:0;letter-spacing:.15em;text-transform:uppercase;color:#0ea5e9;font-size:.78rem;font-weight:600}.nfa-spotlight-card__title{margin:0;color:#131313;font-size:clamp(1.9rem, 3vw, 2.4rem);letter-spacing:-.01em}.nfa-spotlight-card__description{margin:0;color:rgba(19,19,19,.55);font-size:1.02rem;line-height:1.7}.nfa-spotlight-card__meta{margin:0;color:rgba(19,19,19,.4);font-size:.95rem}.nfa-spotlight-card__button{align-self:flex-start;padding:14px 28px;border-radius:999px;font-weight:600;color:#0f172a;background:#ff6b35;text-decoration:none;transition:transform .3s ease,box-shadow .3s ease,background .3s ease;box-shadow:0 1px 3px rgba(0,0,0,.06),0 1px 2px rgba(0,0,0,.04);display:inline-flex;align-items:center;gap:8px}.nfa-spotlight-card__button:focus-visible,.nfa-spotlight-card__button:hover{transform:translateY(-3px) scale(1.02);box-shadow:0 8px 30px rgba(255,107,53,.15);background:#ff7d4f}.nfa-spotlight-card__media img{width:100%;height:auto;border-radius:20px;display:block;transition:transform .3s ease}.nfa-spotlight-card:hover .nfa-spotlight-card__media img{transform:scale(1.02)}.nfa-stats-grid{display:flex;flex-direction:column;gap:28px}.nfa-stats-grid__items{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:20px}.nfa-stats-grid__item{padding:24px;border-radius:18px;background:#fff;border:1px solid rgba(19,19,19,.1);display:grid;row-gap:8px;transition:background .2s ease,border-color .2s ease,transform .2s ease}.nfa-stats-grid__item:hover{background:#f8f9fa;border-color:#0ea5e9;transform:translateY(-2px)}.nfa-stats-grid__value{color:#131313;font-weight:700;font-size:2rem;line-height:1.2;letter-spacing:-.02em}.nfa-stats-grid__label{color:rgba(19,19,19,.55);font-weight:600;font-size:1rem}.nfa-stats-grid__helper{color:rgba(19,19,19,.4);font-size:.9rem;line-height:1.5}.nfa-pricing-table{display:flex;flex-direction:column;gap:20px;color:#131313;position:relative;transition:transform .3s ease,box-shadow .3s ease}.nfa-pricing-table:hover{transform:translateY(-4px)}.nfa-pricing-table__badge{position:absolute;top:18px;right:18px;background:#ff6b35;color:#0f172a;padding:6px 14px;border-radius:999px;font-size:.7rem;font-weight:700;letter-spacing:.08em;text-transform:uppercase;box-shadow:0 4px 12px rgba(255,107,53,.15)}.nfa-pricing-table__label{margin:0 0 6px 0;font-size:1.4rem}.nfa-pricing-table__description{margin:0;color:rgba(19,19,19,.55);line-height:1.6}.nfa-pricing-table__price{display:flex;align-items:baseline;gap:8px}.nfa-pricing-table__amount{font-size:2.6rem;font-weight:700;line-height:1;letter-spacing:-.02em}.nfa-pricing-table__suffix{font-size:1rem;color:rgba(19,19,19,.4)}.nfa-pricing-table__features{list-style:none;padding:0;margin:0;display:grid;gap:12px}.nfa-pricing-table__features li{display:flex;align-items:flex-start;gap:12px;color:rgba(19,19,19,.55);line-height:1.5}.nfa-pricing-table__features li::before{content:'\2713';color:#0ea5e9;font-weight:700;font-size:.9rem;margin-top:1px;flex-shrink:0}.nfa-pricing-table__button{align-self:flex-start;padding:14px 28px;border-radius:999px;font-weight:600;color:#0f172a;background:#ff6b35;text-decoration:none;transition:transform .3s ease,box-shadow .3s ease,background .3s ease;box-shadow:0 1px 3px rgba(0,0,0,.06),0 1px 2px rgba(0,0,0,.04);display:inline-flex;align-items:center;gap:8px}.nfa-pricing-table__button:focus-visible,.nfa-pricing-table__button:hover{transform:translateY(-3px) scale(1.02);box-shadow:0 8px 30px rgba(255,107,53,.15);background:#ff7d4f}.nfa-testimonials{display:flex;flex-direction:column;gap:24px}.nfa-testimonials__grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:20px}.nfa-testimonials__card{background:#fff;border-radius:18px;padding:24px;display:flex;flex-direction:column;gap:16px;border:1px solid rgba(19,19,19,.1);transition:background .2s ease,border-color .2s ease,transform .2s ease}.nfa-testimonials__card:hover{background:#f8f9fa;border-color:#0ea5e9;transform:translateY(-2px)}.nfa-testimonials__avatar img{width:48px;height:48px;border-radius:50%;object-fit:cover;display:block;border:2px solid rgba(19,19,19,.1)}.nfa-testimonials__quote{margin:0;color:rgba(19,19,19,.55);font-size:1rem;line-height:1.7;font-style:normal}blockquote.nfa-testimonials__quote{border:0;padding:0}.nfa-testimonials__footer{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-top:auto}.nfa-testimonials__name{font-weight:600;color:#131313}.nfa-testimonials__role{color:rgba(19,19,19,.4);font-size:.9rem}.nfa-testimonials__rating{font-size:.9rem;letter-spacing:1px;color:#fbbf24}.nfa-logo-grid{display:flex;flex-direction:column;gap:24px}.nfa-logo-grid__items{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:24px;align-items:center}.nfa-logo-grid__logo{display:flex;align-items:center;justify-content:center;padding:20px;border-radius:14px;background:#fff;border:1px solid rgba(19,19,19,.1);min-height:86px;transition:background .2s ease,border-color .2s ease,transform .2s ease}.nfa-logo-grid__logo:hover{background:#f8f9fa;border-color:#0ea5e9;transform:translateY(-3px)}.nfa-logo-grid__logo img{max-width:140px;width:100%;height:auto;opacity:.7;transition:opacity .2s ease,filter .2s ease;filter:grayscale(20%)}.nfa-logo-grid__logo:hover img{opacity:1;filter:grayscale(0%)}.nfa-logo-grid__text{color:#131313;font-weight:600}.nfa-faq{display:flex;flex-direction:column;gap:24px}.nfa-faq__items{display:grid;gap:12px}.nfa-faq__item{background:#fff;border-radius:16px;padding:20px 22px;border:1px solid rgba(19,19,19,.1);transition:background .2s ease,border-color .2s ease}.nfa-faq__item:hover{border-color:#0ea5e9}.nfa-faq__item[open]{background:#f8f9fa;border-color:#0ea5e9}.nfa-faq__question{cursor:pointer;font-weight:600;color:#131313;list-style:none;display:flex;align-items:center;justify-content:space-between;gap:14px;user-select:none}.nfa-faq__question::after{content:'+';font-size:1.2rem;color:#0ea5e9;transition:transform .2s ease;flex-shrink:0;width:28px;height:28px;display:flex;align-items:center;justify-content:center;border-radius:50%;background:rgba(14,165,233,.08)}.nfa-faq__item[open] .nfa-faq__question::after{content:'\2212';transform:rotate(180deg)}.nfa-faq__question::-webkit-details-marker{display:none}.nfa-faq__answer{margin-top:14px;color:rgba(19,19,19,.55);line-height:1.7}.nfa-steps{display:flex;flex-direction:column;gap:24px}.nfa-steps__list{display:grid;gap:20px}.nfa-steps--vertical .nfa-steps__list{grid-template-columns:1fr}.nfa-steps--horizontal .nfa-steps__list{grid-template-columns:repeat(3,minmax(0,1fr))}.nfa-steps__item{background:#fff;border-radius:18px;padding:24px;display:flex;flex-direction:column;gap:10px;border:1px solid rgba(19,19,19,.1);transition:background .2s ease,border-color .2s ease,transform .2s ease;position:relative}.nfa-steps__item:hover{background:#f8f9fa;border-color:#0ea5e9;transform:translateY(-2px)}.nfa-steps__label{text-transform:uppercase;letter-spacing:.12em;font-size:.72rem;color:#0ea5e9;font-weight:700}.nfa-steps__title{margin:0;font-size:1.1rem;color:#131313;font-weight:600}.nfa-steps__description{margin:0;color:rgba(19,19,19,.55);line-height:1.6;font-size:.95rem}.nfa-slider{position:relative}.nfa-slider__track{display:flex;gap:20px;overflow-x:auto;scroll-snap-type:x mandatory;scroll-behavior:smooth;padding-bottom:6px;scrollbar-width:none;-ms-overflow-style:none}.nfa-slider__track::-webkit-scrollbar{display:none}.nfa-slider__item{flex:0 0 100%;scroll-snap-align:start}.nfa-slider__btn{position:absolute;top:50%;transform:translateY(-50%);width:40px;height:40px;border-radius:999px;border:1px solid rgba(19,19,19,.1);background:#131313;color:#131313;display:inline-flex;align-items:center;justify-content:center;cursor:pointer;box-shadow:0 8px 20px rgb(15 23 42 / .3);transition:transform .2s ease,box-shadow .2s ease,background .2s ease,border-color .2s ease;z-index:2}.nfa-slider__btn--prev{left:-16px}.nfa-slider__btn--next{right:-16px}.nfa-slider__btn:hover{transform:translateY(-50%) scale(1.08);background:rgba(255,255,255,.08);border-color:#0ea5e9}.nfa-slider__btn:focus-visible{outline:0;box-shadow:0 0 0 3px rgba(125,211,252,.3)}.nfa-showcase{position:relative}.nfa-showcase__nav{display:flex;gap:12px;margin-bottom:24px;justify-content:flex-end}.nfa-showcase__arrow{width:48px;height:48px;border-radius:50%;border:1.5px solid rgba(19,19,19,.15);background:0 0;color:#fff;font-size:16px;cursor:pointer;display:flex;align-items:center;justify-content:center;transition:all .3s ease}.nfa-showcase__arrow:hover{background:#131313;color:#f4f4f4;border-color:#131313}.nfa-showcase__viewport{overflow:hidden}.nfa-showcase__track{display:flex;transition:transform .5s cubic-bezier(.25, .46, .45, .94);will-change:transform}.nfa-showcase__card{flex-shrink:0;position:relative;height:420px;border-radius:20px;overflow:hidden;transition:transform .35s ease;text-decoration:none;display:block}.nfa-showcase__card:hover{transform:translateY(-4px)}.nfa-showcase__img{position:absolute;inset:0;z-index:0}.nfa-showcase__img img{width:100%;height:100%;object-fit:cover;transition:transform .5s ease}.nfa-showcase__card:hover .nfa-showcase__img img{transform:scale(1.08)}.nfa-showcase__card--overlay-dark .nfa-showcase__img::after{content:'';position:absolute;inset:0;background:linear-gradient(to top,rgba(19,19,19,.92) 0,rgba(19,19,19,.5) 50%,rgba(19,19,19,.15) 100%);z-index:1}.nfa-showcase__card--overlay-light .nfa-showcase__img::after{content:'';position:absolute;inset:0;background:linear-gradient(to top,rgba(255,255,255,.92) 0,rgba(255,255,255,.4) 50%,transparent 100%);z-index:1}.nfa-showcase__badge{position:absolute;top:20px;left:20px;background:rgba(244,244,244,.15);backdrop-filter:blur(10px);color:#f4f4f4;padding:5px 16px;border-radius:50px;font-size:11px;font-weight:600;letter-spacing:.5px;text-transform:uppercase;z-index:2;border:1px solid rgba(244,244,244,.1)}.nfa-showcase__body{position:absolute;bottom:0;left:0;right:0;padding:32px 28px;z-index:2}.nfa-showcase__title{font-size:22px;font-weight:700;color:#f4f4f4;margin-bottom:12px}.nfa-showcase__desc{font-size:14px;color:rgba(244,244,244,.65);line-height:1.8;margin:0}.nfa-showcase__tags{display:flex;flex-wrap:wrap;gap:8px;margin-top:16px}.nfa-showcase__tag{font-size:11px;padding:4px 12px;border-radius:50px;border:1px solid rgba(244,244,244,.12);color:rgba(244,244,244,.6);letter-spacing:.3px}.nfa-showcase__dots{display:flex;justify-content:center;gap:8px;margin-top:24px}.nfa-showcase__dot{width:10px;height:10px;border-radius:50%;background:rgba(19,19,19,.2);border:none;cursor:pointer;padding:0;transition:background .3s ease,transform .3s ease}.nfa-showcase__dot--active{background:#131313;transform:scale(1.2)}.nfa-showcase__dot:hover:not(.nfa-showcase__dot--active){background:rgba(19,19,19,.4)}.nfa-areas__grid{display:grid;grid-template-columns:repeat(3,1fr);gap:24px}.nfa-areas__grid--featured .nfa-areas__card:first-child{grid-row:1/3}.nfa-areas__card{background:#fff;border-radius:18px;overflow:hidden;position:relative;transition:all .4s ease;display:block;text-decoration:none;color:inherit}a.nfa-areas__card:hover{text-decoration:none;color:inherit}.nfa-areas__card--shadow-sm{box-shadow:0 1px 3px rgba(0,0,0,.06),0 1px 2px rgba(0,0,0,.04)}.nfa-areas__card--shadow-md{box-shadow:0 4px 12px rgba(0,0,0,.08)}.nfa-areas__card--shadow-lg{box-shadow:0 10px 30px rgba(0,0,0,.12)}.nfa-areas__card:hover{box-shadow:0 10px 30px rgba(0,0,0,.12)}.nfa-areas__img{height:200px;overflow:hidden;position:relative}.nfa-areas__img img{width:100%;height:100%;object-fit:cover;transition:transform .6s ease}.nfa-areas__badge{position:absolute;top:16px;left:16px;background:#131313;color:#f4f4f4;padding:5px 16px;border-radius:50px;font-size:11px;font-weight:600;letter-spacing:.5px;text-transform:uppercase;z-index:3}.nfa-areas__body{padding:24px}.nfa-areas__title{font-size:19px;font-weight:600;margin:0 0 8px;color:#131313}.nfa-areas__desc{font-size:14px;color:rgba(19,19,19,.55);line-height:1.7;margin:0}.nfa-areas__card--featured{position:relative}.nfa-areas__card--featured .nfa-areas__img{position:absolute;inset:0;height:100%;z-index:0}.nfa-areas__overlay{position:absolute;inset:0;z-index:1;pointer-events:none}.nfa-areas__card--featured .nfa-areas__body{position:absolute;bottom:0;left:0;right:0;z-index:2;padding:32px 28px}.nfa-areas__card--featured .nfa-areas__title{color:#f4f4f4;font-size:24px;margin-bottom:12px}.nfa-areas__card--featured .nfa-areas__desc{color:rgba(244,244,244,.65);font-size:14px;line-height:1.8}.nfa-areas__card--featured .nfa-areas__badge{background:rgba(244,244,244,.15);backdrop-filter:blur(10px);border:1px solid rgba(244,244,244,.1);z-index:2}.nfa-journey__steps{display:grid;grid-template-columns:repeat(5,minmax(0,1fr));gap:24px;position:relative}.nfa-journey__steps--line::before{content:'';position:absolute;top:36px;left:48px;right:48px;height:2px;background:linear-gradient(90deg,#131313,rgba(19,19,19,.08));z-index:0}.nfa-journey__step{text-align:center;position:relative;z-index:1}.nfa-journey__number{width:72px;height:72px;display:inline-flex;align-items:center;justify-content:center;border-radius:999px;border:2px solid #131313;background:#fff;color:#131313;font-size:22px;font-weight:700;margin:0 auto 20px;transition:all .3s ease}.nfa-journey__step:hover .nfa-journey__number{background:#131313;color:#f4f4f4;box-shadow:0 8px 24px rgba(19,19,19,.2);transform:scale(1.05)}.nfa-journey__step-title{margin:0 0 10px;font-size:16px;font-weight:600;color:#131313}.nfa-journey__step-description{margin:0;font-size:13px;line-height:1.7;color:rgba(19,19,19,.45)}@media (max-width:900px){.nfa-feature-list__items,.nfa-logo-grid__items,.nfa-stats-grid__items,.nfa-steps--horizontal .nfa-steps__list,.nfa-testimonials__grid{grid-template-columns:1fr}.nfa-journey__steps{grid-template-columns:repeat(2,minmax(0,1fr))}.nfa-journey__steps--line::before{display:none}.nfa-areas__grid--featured .nfa-areas__card:first-child{grid-row:auto}.nfa-areas__card--featured .nfa-areas__img{position:relative;inset:auto;height:200px}.nfa-areas__card--featured .nfa-areas__overlay{display:none}.nfa-areas__card--featured .nfa-areas__body{position:relative;bottom:auto;left:auto;right:auto;padding:24px}.nfa-areas .nfa-areas__card--featured .nfa-areas__title{color:#131313!important;font-size:19px!important;margin-bottom:8px}.nfa-areas .nfa-areas__card--featured .nfa-areas__desc{color:rgba(19,19,19,.55)!important;font-size:14px;line-height:1.7}.nfa-areas .nfa-areas__card--featured .nfa-areas__badge{background:#131313!important;color:#f4f4f4!important;backdrop-filter:none;border:none!important}}@media (max-width:640px){.nfa-journey__steps{grid-template-columns:1fr}.nfa-slider__btn--prev{left:-8px}.nfa-slider__btn--next{right:-8px}}.nfa-team__grid{display:grid;gap:24px;grid-template-columns:repeat(var(--nfa-team-cols,3),1fr)}.nfa-team__card{background:#fff;border-radius:16px;overflow:hidden;text-align:center;transition:box-shadow .3s ease,transform .25s ease;box-shadow:0 1px 4px rgba(0,0,0,.06)}.nfa-team__card:hover{box-shadow:0 8px 24px rgba(0,0,0,.1);transform:translateY(-4px)}.nfa-team__card--layout-left{display:flex;text-align:left}.nfa-team__card--layout-left .nfa-team__photo{flex:0 0 140px;height:auto}.nfa-team__photo{width:100%;height:220px;object-fit:cover;display:block}.nfa-team__card--layout-circle .nfa-team__photo{width:120px;height:120px;border-radius:50%;margin:24px auto 0}.nfa-team__body{padding:20px}.nfa-team__name{margin:0 0 4px;font-size:1.15em;font-weight:600;color:#131313}.nfa-team__role{font-size:.875em;color:rgba(19,19,19,.55);margin-bottom:10px}.nfa-team__bio{font-size:.9em;color:rgba(19,19,19,.7);line-height:1.6;margin-bottom:14px}.nfa-team__social{display:flex;gap:10px;justify-content:center}.nfa-team__card--layout-left .nfa-team__social{justify-content:flex-start}.nfa-team__social a{display:inline-flex;align-items:center;justify-content:center;width:34px;height:34px;border-radius:50%;background:rgba(19,19,19,.06);color:#131313;font-size:15px;transition:background .25s,color .25s;text-decoration:none}.nfa-team__social a:hover{background:#0ea5e9;color:#fff}@media (max-width:767px){.nfa-team__grid{grid-template-columns:1fr}.nfa-team__card--layout-left{flex-direction:column;text-align:center}.nfa-team__card--layout-left .nfa-team__photo{flex:none;width:100%;height:200px}.nfa-team__card--layout-left .nfa-team__social{justify-content:center}}.nfa-cta-banner{border-radius:16px;padding:48px 40px;text-align:center;position:relative;overflow:hidden}.nfa-cta-banner--left{text-align:left}.nfa-cta-banner--side{display:flex;align-items:center;justify-content:space-between;text-align:left;gap:32px}.nfa-cta-banner__icon{font-size:40px;margin-bottom:16px;display:inline-block}.nfa-cta-banner__kicker{display:inline-block;font-size:.8em;font-weight:600;text-transform:uppercase;letter-spacing:.08em;margin-bottom:10px;opacity:.75}.nfa-cta-banner__title{margin:0 0 14px;font-size:1.75em;font-weight:700;line-height:1.25}.nfa-cta-banner__desc{font-size:1.05em;line-height:1.6;opacity:.85;max-width:640px;margin:0 auto 24px}.nfa-cta-banner--left .nfa-cta-banner__desc,.nfa-cta-banner--side .nfa-cta-banner__desc{margin-left:0}.nfa-cta-banner__actions{display:flex;gap:12px;flex-wrap:wrap}.nfa-cta-banner--center .nfa-cta-banner__actions{justify-content:center}.nfa-cta-banner__btn{display:inline-flex;align-items:center;padding:12px 28px;border-radius:8px;font-weight:600;font-size:.95em;text-decoration:none;transition:opacity .25s,transform .15s;border:none;cursor:pointer}.nfa-cta-banner__btn:hover{opacity:.88;transform:translateY(-1px)}@media (max-width:767px){.nfa-cta-banner{padding:32px 24px}.nfa-cta-banner--side{flex-direction:column;text-align:center}.nfa-cta-banner--side .nfa-cta-banner__actions{justify-content:center}}.nfa-tabs{display:flex;flex-direction:column;gap:0}.nfa-tabs--vertical{flex-direction:row;gap:24px}.nfa-tabs__nav{display:flex;gap:4px;border-bottom:2px solid rgba(19,19,19,.08);padding-bottom:0;overflow-x:auto;-webkit-overflow-scrolling:touch}.nfa-tabs--vertical .nfa-tabs__nav{flex-direction:column;border-bottom:none;border-right:2px solid rgba(19,19,19,.08);padding-right:0;padding-bottom:0;min-width:180px;overflow-x:visible}.nfa-tabs__btn{position:relative;display:inline-flex;align-items:center;gap:8px;padding:12px 24px;font-weight:500;font-size:.95em;background:0 0;border:none;color:rgba(19,19,19,.55);cursor:pointer;white-space:nowrap;transition:color .2s,background .2s;border-radius:8px 8px 0 0}.nfa-tabs--vertical .nfa-tabs__btn{border-radius:8px 0 0 8px;justify-content:flex-start;text-align:left;width:100%}.nfa-tabs__btn:hover{color:#131313;background:rgba(19,19,19,.03)}.nfa-tabs__btn--active{color:#0ea5e9;background:rgba(14,165,233,.08)}.nfa-tabs__btn--active::after{content:'';position:absolute;bottom:-2px;left:0;right:0;height:3px;background:#0ea5e9;border-radius:3px 3px 0 0}.nfa-tabs--vertical .nfa-tabs__btn--active::after{bottom:auto;top:0;left:auto;right:-2px;width:3px;height:100%;border-radius:0 3px 3px 0}.nfa-tabs__btn--icon-top{flex-direction:column}.nfa-tabs__btn-icon{font-size:18px;line-height:1;display:flex;align-items:center;justify-content:center}.nfa-tabs__panels{flex:1}.nfa-tabs__panel{display:none;padding:24px;color:rgba(19,19,19,.7);line-height:1.7;border-radius:0 0 12px 12px}.nfa-tabs--vertical .nfa-tabs__panel{border-radius:0 12px 12px 0}.nfa-tabs__panel--active{display:block}@media (max-width:767px){.nfa-tabs--vertical{flex-direction:column}.nfa-tabs--vertical .nfa-tabs__nav{flex-direction:row;border-right:none;border-bottom:2px solid rgba(19,19,19,.08);min-width:0;overflow-x:auto}.nfa-tabs--vertical .nfa-tabs__btn{border-radius:8px 8px 0 0}.nfa-tabs--vertical .nfa-tabs__btn--active::after{bottom:-2px;top:auto;right:0;left:0;width:auto;height:3px;border-radius:3px 3px 0 0}.nfa-tabs--vertical .nfa-tabs__panel{border-radius:0 0 12px 12px}}.nfa-compare{position:relative;overflow:hidden;border-radius:12px;user-select:none;touch-action:none;cursor:col-resize;line-height:0}.nfa-compare--vertical{cursor:row-resize}.nfa-compare__after,.nfa-compare__before{position:relative;width:100%}.nfa-compare__before{position:absolute;top:0;left:0;z-index:2;height:100%;overflow:hidden}.nfa-compare__after img,.nfa-compare__before img{display:block;width:100%;height:100%;object-fit:cover;pointer-events:none}.nfa-compare__label{position:absolute;bottom:16px;padding:4px 14px;font-size:.8em;font-weight:600;color:#fff;background:rgba(0,0,0,.55);border-radius:6px;z-index:5;pointer-events:none;transition:opacity .3s}.nfa-compare__label--before{left:16px}.nfa-compare__label--after{right:16px}.nfa-compare--vertical .nfa-compare__label--before{top:16px;bottom:auto;left:16px}.nfa-compare--vertical .nfa-compare__label--after{bottom:16px;right:auto;left:16px}.nfa-compare--hover-labels .nfa-compare__label{opacity:0}.nfa-compare--hover-labels:hover .nfa-compare__label{opacity:1}.nfa-compare__slider{position:absolute;top:0;bottom:0;z-index:10;display:flex;align-items:center;justify-content:center}.nfa-compare--horizontal .nfa-compare__slider{flex-direction:column;width:0}.nfa-compare--vertical .nfa-compare__slider{top:auto;left:0;right:0;flex-direction:row;height:0}.nfa-compare__line{position:absolute}.nfa-compare--horizontal .nfa-compare__line{width:3px;top:0;bottom:0;background:#fff}.nfa-compare--vertical .nfa-compare__line{height:3px;left:0;right:0;background:#fff}.nfa-compare__handle{position:relative;z-index:11;width:40px;height:40px;border-radius:50%;background:#fff;display:flex;align-items:center;justify-content:center;box-shadow:0 2px 8px rgba(0,0,0,.25);color:#131313;cursor:inherit;flex-shrink:0}.nfa-compare__handle svg{width:14px;height:14px}.nfa-countdown{display:flex;align-items:center;justify-content:center;flex-wrap:wrap;gap:16px}.nfa-countdown__block{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:20px;min-width:80px;border-radius:12px;background:rgba(19,19,19,.04);transition:transform .25s,box-shadow .25s;position:relative}.nfa-countdown__block:hover{transform:translateY(-3px);box-shadow:0 4px 16px rgba(0,0,0,.08)}.nfa-countdown__digit{font-size:2.5em;font-weight:700;line-height:1.1;color:#131313;font-variant-numeric:tabular-nums}.nfa-countdown__label{font-size:.8em;font-weight:500;color:rgba(19,19,19,.55);text-transform:uppercase;letter-spacing:.06em;margin-top:8px}.nfa-countdown__sep{font-size:2em;font-weight:700;color:rgba(19,19,19,.3);line-height:1;align-self:flex-start;padding-top:20px}.nfa-countdown--inline .nfa-countdown__block{background:0 0;padding:10px 6px;min-width:auto;border-radius:0}.nfa-countdown--inline .nfa-countdown__block:hover{transform:none;box-shadow:none}.nfa-countdown__block--circle{position:relative;background:0 0;padding:0;width:120px;height:120px;border-radius:50%}.nfa-countdown__block--circle:hover{transform:none;box-shadow:none}.nfa-countdown__ring{position:absolute;top:0;left:0;width:100%;height:100%}.nfa-countdown__progress{transition:stroke-dashoffset .6s ease}.nfa-countdown__block--circle .nfa-countdown__digit{font-size:1.6em}.nfa-countdown__block--circle .nfa-countdown__label{font-size:.65em;margin-top:2px}.nfa-countdown__expiry{width:100%;text-align:center;font-size:1.2em;font-weight:600;color:#131313;padding:24px}@media (max-width:480px){.nfa-countdown__digit{font-size:1.8em}.nfa-countdown__block{min-width:60px;padding:14px}.nfa-countdown__block--circle{width:80px;height:80px}.nfa-countdown__block--circle .nfa-countdown__digit{font-size:1.2em}}.nfa-tooltip{position:absolute;z-index:99999;max-width:260px;padding:8px 14px;border-radius:6px;background:#1e293b;color:#fff;font-size:13px;line-height:1.5;text-align:center;pointer-events:none;opacity:0;visibility:hidden;transition:opacity .25s ease,visibility .25s ease,transform .25s ease;white-space:normal;word-wrap:break-word;box-shadow:0 4px 12px rgba(0,0,0,.15)}.nfa-tooltip--visible{opacity:1;visibility:visible}.nfa-tooltip::after{content:'';position:absolute;width:0;height:0;border:6px solid transparent}.nfa-tooltip--no-arrow::after{display:none}.nfa-tooltip--top{transform:translateY(6px)}.nfa-tooltip--top.nfa-tooltip--visible{transform:translateY(0)}.nfa-tooltip--top::after{top:100%;left:50%;transform:translateX(-50%);border-top-color:inherit}.nfa-tooltip--bottom{transform:translateY(-6px)}.nfa-tooltip--bottom.nfa-tooltip--visible{transform:translateY(0)}.nfa-tooltip--bottom::after{bottom:100%;left:50%;transform:translateX(-50%);border-bottom-color:inherit}.nfa-tooltip--left{transform:translateX(6px)}.nfa-tooltip--left.nfa-tooltip--visible{transform:translateX(0)}.nfa-tooltip--left::after{left:100%;top:50%;transform:translateY(-50%);border-left-color:inherit}.nfa-tooltip--right{transform:translateX(-6px)}.nfa-tooltip--right.nfa-tooltip--visible{transform:translateX(0)}.nfa-tooltip--right::after{right:100%;top:50%;transform:translateY(-50%);border-right-color:inherit}[data-nfa-wrapper-link]{cursor:pointer;position:relative}[data-nfa-wrapper-link]:focus-visible{outline:2px solid currentColor;outline-offset:2px}.nfa-hamburger__toggle-wrap{display:flex}.nfa-hamburger__toggle{display:inline-flex;align-items:center;justify-content:center;border:none;cursor:pointer;line-height:1;transition:background .2s ease,color .2s ease}.nfa-hamburger__icon--bars{display:flex;flex-direction:column;gap:4px;width:1em}.nfa-hamburger__icon--bars span{display:block;height:2px;background:currentColor;border-radius:2px;transition:transform .3s ease,opacity .3s ease}.nfa-hamburger__icon--dots{display:flex;flex-direction:column;gap:4px;align-items:center;width:1em}.nfa-hamburger__icon--dots span{display:block;width:5px;height:5px;background:currentColor;border-radius:50%}.nfa-hamburger__icon--grid{display:grid;grid-template-columns:repeat(2,1fr);gap:3px;width:1em}.nfa-hamburger__icon--grid span{display:block;width:7px;height:7px;background:currentColor;border-radius:2px}.nfa-hamburger__overlay{position:fixed;inset:0;z-index:99998;opacity:0;visibility:hidden;transition:opacity .35s ease,visibility .35s ease}.nfa-hamburger--open .nfa-hamburger__overlay{opacity:1;visibility:visible}.nfa-hamburger__panel{position:fixed;z-index:99999;background:#fff;overflow-y:auto;-webkit-overflow-scrolling:touch;transition:transform .35s cubic-bezier(.4, 0, .2, 1),visibility .35s ease;visibility:hidden}.nfa-hamburger__panel--left{top:0;left:0;bottom:0;transform:translateX(-100%)}.nfa-hamburger__panel--right{top:0;right:0;bottom:0;transform:translateX(100%)}.nfa-hamburger__panel--top{top:0;left:0;right:0;max-height:80vh;transform:translateY(-100%)}.nfa-hamburger--open .nfa-hamburger__panel{transform:translate(0);visibility:visible}.nfa-hamburger__panel-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:16px}.nfa-hamburger__logo{max-height:40px;width:auto}.nfa-hamburger__close{background:0 0;border:none;font-size:28px;cursor:pointer;line-height:1;padding:4px 8px;transition:color .2s ease;margin-left:auto}.nfa-hamburger__list{list-style:none;margin:0;padding:0}.nfa-hamburger__item--separated{border-bottom:1px solid #e2e8f0}.nfa-hamburger__link{display:flex;align-items:center;gap:10px;text-decoration:none;font-size:15px;font-weight:500;transition:color .2s ease}.nfa-hamburger__link-icon{flex-shrink:0;font-size:1.1em}.nfa-hamburger__arrow{margin-left:auto;font-size:12px;transition:transform .25s ease}.nfa-hamburger__item--sub-open>.nfa-hamburger__link .nfa-hamburger__arrow{transform:rotate(180deg)}.nfa-hamburger__sub-list{list-style:none;margin:0;padding:4px 0 4px 24px;display:none}.nfa-hamburger__item--sub-open>.nfa-hamburger__sub-list{display:block}.nfa-hamburger__sub-link{display:block;padding:6px 0;text-decoration:none;font-size:14px;transition:color .2s ease}.nfa-form__fields{display:flex;flex-wrap:wrap;gap:16px}.nfa-form__col--100{width:100%}.nfa-form__col--75{width:calc(75% - 8px)}.nfa-form__col--66{width:calc(66.666% - 8px)}.nfa-form__col--50{width:calc(50% - 8px)}.nfa-form__col--33{width:calc(33.333% - 8px)}.nfa-form__col--25{width:calc(25% - 12px)}.nfa-form__col--hidden{display:none}.nfa-form__label{display:block;font-weight:600;font-size:13px;margin-bottom:6px}.nfa-form__required{color:#ef4444;margin-left:2px}.nfa-form__input,.nfa-form__select,.nfa-form__textarea{display:block;width:100%;border:1px solid #cbd5e1;font-size:14px;line-height:1.5;transition:border-color .2s ease,box-shadow .2s ease;outline:0;box-sizing:border-box}.nfa-form__input:focus,.nfa-form__select:focus,.nfa-form__textarea:focus{border-color:#6366f1;box-shadow:0 0 0 3px rgba(99,102,241,.1)}.nfa-form__input--file{padding:8px;border-style:dashed}.nfa-form__textarea{resize:vertical;min-height:100px}.nfa-form__choice-group{display:flex;flex-wrap:wrap;gap:12px}.nfa-form__choice{display:flex;align-items:center;gap:6px;font-size:14px;cursor:pointer}.nfa-form__choice input{accent-color:#6366f1;width:16px;height:16px}.nfa-form__field-error{display:block;font-size:12px;color:#ef4444;min-height:18px;margin-top:4px}.nfa-form__actions{display:flex;margin-top:20px}.nfa-form__submit{display:inline-flex;align-items:center;gap:8px;border:none;font-weight:600;cursor:pointer;transition:background .2s ease,transform .15s ease}.nfa-form__submit:hover{transform:translateY(-1px)}.nfa-form__submit:active{transform:translateY(0)}.nfa-form__submit:disabled{opacity:.6;cursor:not-allowed;transform:none}.nfa-form__spinner{display:inline-block;width:16px;height:16px;border:2px solid rgba(255,255,255,.3);border-top-color:#fff;border-radius:50%;animation:nfa-spin .6s linear infinite}@keyframes nfa-spin{to{transform:rotate(360deg)}}.nfa-form__msg{padding:14px 18px;border-radius:8px;font-size:14px;font-weight:500;margin-top:16px}.nfa-form__msg--success{background:#f0fdf4;color:#166534;border:1px solid #bbf7d0}.nfa-form__msg--error{background:#fef2f2;color:#991b1b;border:1px solid #fecaca}.nfa-form__input--invalid,.nfa-form__select--invalid,.nfa-form__textarea--invalid{border-color:#ef4444!important;box-shadow:0 0 0 3px rgba(239,68,68,.1)!important}@media (max-width:767px){.nfa-form__col--25,.nfa-form__col--33,.nfa-form__col--50,.nfa-form__col--66,.nfa-form__col--75{width:100%}}.nfa-badge{display:inline-block;padding:2px 10px;border-radius:999px;font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:.04em}.nfa-badge--blue{background:#eef2ff;color:#4f46e5}.nfa-badge--gray{background:#f1f5f9;color:#64748b}.nfa-sub-row--unread td{background:#fafbff;font-weight:500}.nfa-ncards{position:relative}.nfa-ncards__grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:20px}.nfa-ncards__card{background:#e8e4de;border-radius:16px;padding:28px;display:flex;flex-direction:column;transition:box-shadow .3s ease,transform .25s ease}.nfa-ncards--grid .nfa-ncards__card:hover{transform:translateY(-4px)}.nfa-ncards__header{display:flex;align-items:flex-start;justify-content:space-between;margin-bottom:16px}.nfa-ncards__number{font-size:2.5rem;font-weight:300;line-height:1;color:#3b3a2f;font-style:italic}.nfa-ncards__icon{display:inline-flex;align-items:center;justify-content:center;font-size:28px;color:#3b3a2f;line-height:1}.nfa-ncards__icon svg{width:28px;height:28px}.nfa-ncards__image{display:inline-flex;align-items:center;justify-content:center;width:120px;height:120px;flex-shrink:0}.nfa-ncards__image img{width:100%;height:100%;object-fit:contain}.nfa-ncards__body{flex:1}.nfa-ncards__title{font-size:.95rem;font-weight:700;text-transform:uppercase;letter-spacing:.06em;color:#3b3a2f;margin:0 0 12px 0;line-height:1.3}.nfa-ncards__desc{font-size:.9rem;color:#3b3a2f;line-height:1.6;margin:0;opacity:.85}.nfa-ncards--steps .nfa-ncards__card--step{background:#fff;border:1px solid #e8e4de;border-radius:16px;padding:32px 28px;display:flex;flex-direction:column;align-items:flex-start;position:relative;overflow:hidden;transition:box-shadow .3s ease,transform .25s ease}.nfa-ncards--steps .nfa-ncards__card--step:hover{box-shadow:0 8px 30px rgba(0,0,0,.08);transform:translateY(-3px)}.nfa-ncards--steps .nfa-ncards__card--step::before{content:'';position:absolute;background-color:#b8976a;transition:opacity .3s ease;opacity:0}.nfa-ncards--steps .nfa-ncards__card--step:hover::before{opacity:1}.nfa-ncards-accent--left .nfa-ncards__card--step::before{top:0;left:0;width:4px;height:100%}.nfa-ncards-accent--right .nfa-ncards__card--step::before{top:0;right:0;width:4px;height:100%}.nfa-ncards-accent--top .nfa-ncards__card--step::before{top:0;left:0;width:100%;height:4px}.nfa-ncards-accent--bottom .nfa-ncards__card--step::before{bottom:0;left:0;width:100%;height:4px}.nfa-ncards-accent--none .nfa-ncards__card--step::before{display:none}.nfa-ncards__badge{display:inline-flex;align-items:center;justify-content:center;width:56px;height:56px;border-radius:50%;background-color:#1e3a5f;color:#fff;font-size:22px;flex-shrink:0;margin-bottom:14px;line-height:1}.nfa-ncards__badge svg{width:22px;height:22px;fill:currentColor}.nfa-ncards__badge--img{background:0 0;overflow:hidden}.nfa-ncards__badge--img img{width:100%;height:100%;object-fit:cover;border-radius:50%}.nfa-ncards__step-label{font-size:.75rem;font-weight:600;text-transform:uppercase;letter-spacing:.12em;color:#b8976a;margin-bottom:8px;display:block}.nfa-ncards__step-title{font-size:1.2rem;font-weight:700;font-style:italic;color:#1e3a5f;margin:0 0 14px 0;line-height:1.3}.nfa-ncards__divider{display:block;width:50px;height:3px;border-radius:2px;background-color:#1e3a5f;margin-bottom:16px}.nfa-ncards__step-desc{font-size:.92rem;line-height:1.65;color:#666;margin:0}.nfa-ncards--carousel{overflow:hidden;position:relative}.nfa-ncards__viewport{overflow:hidden}.nfa-ncards__track{display:flex;transition:transform .45s cubic-bezier(.25, .46, .45, .94);will-change:transform;cursor:grab;user-select:none;-webkit-user-select:none}.nfa-ncards--carousel.is-dragging .nfa-ncards__track{cursor:grabbing}.nfa-ncards--carousel .nfa-ncards__card{flex:0 0 calc((100% - 40px)/ 3);display:flex;flex-direction:column;min-height:280px}.nfa-ncards--carousel .nfa-ncards__header{margin-bottom:20px;min-height:90px}.nfa-ncards--carousel .nfa-ncards__number{font-size:3rem}.nfa-ncards__nav{display:flex;gap:8px;margin-top:20px}.nfa-ncards--nav-bottom-right .nfa-ncards__nav{justify-content:flex-end}.nfa-ncards--nav-bottom-left .nfa-ncards__nav{justify-content:flex-start}.nfa-ncards--nav-bottom-center .nfa-ncards__nav{justify-content:center}.nfa-ncards--nav-top-center .nfa-ncards__nav,.nfa-ncards--nav-top-left .nfa-ncards__nav,.nfa-ncards--nav-top-right .nfa-ncards__nav{margin-top:0;margin-bottom:20px;order:-1}.nfa-ncards--nav-top-right .nfa-ncards__nav{justify-content:flex-end}.nfa-ncards--nav-top-left .nfa-ncards__nav{justify-content:flex-start}.nfa-ncards--nav-top-center .nfa-ncards__nav{justify-content:center}.nfa-ncards--nav-top-center,.nfa-ncards--nav-top-left,.nfa-ncards--nav-top-right{display:flex;flex-direction:column}.nfa-ncards--nav-sides{position:relative}.nfa-ncards__arrow--side{position:absolute;top:50%;transform:translateY(-50%);z-index:2}.nfa-ncards__arrow--side.nfa-ncards__arrow--prev{left:-48px}.nfa-ncards__arrow--side.nfa-ncards__arrow--next{right:-48px}@media (max-width:1200px){.nfa-ncards__arrow--side.nfa-ncards__arrow--prev{left:8px}.nfa-ncards__arrow--side.nfa-ncards__arrow--next{right:8px}}.nfa-ncards__arrow{display:inline-flex;align-items:center;justify-content:center;width:40px;height:40px;border-radius:50%;border:1.5px solid rgba(255,255,255,.5);background:0 0;color:#fff;cursor:pointer;transition:background-color .25s ease,border-color .25s ease,transform .2s ease;padding:0}.nfa-ncards__arrow:hover{background-color:rgba(255,255,255,.15);border-color:rgba(255,255,255,.8);transform:scale(1.08)}.nfa-ncards__arrow--side:hover{transform:translateY(-50%) scale(1.08)}.nfa-ncards__arrow svg{width:16px;height:16px}.nfa-ncards__dots{display:flex;gap:8px;justify-content:center;margin-top:20px;padding:4px 0}.nfa-ncards__dot{width:10px;height:10px;border-radius:50%;border:none;background-color:rgba(255,255,255,.4);cursor:pointer;padding:0;transition:background-color .25s ease,transform .2s ease}.nfa-ncards__dot:hover{transform:scale(1.3)}.nfa-ncards__dot.is-active{background-color:#fff;transform:scale(1.2)}@media (max-width:1024px){.nfa-ncards__grid{grid-template-columns:repeat(2,minmax(0,1fr))}}@media (max-width:767px){.nfa-ncards__grid{grid-template-columns:1fr}.nfa-ncards__number{font-size:2rem}.nfa-ncards--carousel .nfa-ncards__number{font-size:2.2rem}}.nfa-vtestimonials{position:relative}.nfa-vtestimonials__grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:24px}.nfa-vtestimonials__card{background:#fff;border-radius:16px;overflow:hidden;display:flex;flex-direction:column;transition:transform .35s ease,box-shadow .35s ease,background-color .35s ease,border-color .35s ease;cursor:pointer}.nfa-vtestimonials--lift .nfa-vtestimonials__card:hover{transform:translateY(-6px)}.nfa-vtestimonials__thumb{position:relative;height:220px;overflow:hidden;flex-shrink:0}.nfa-vtestimonials__thumb img{width:100%;height:100%;object-fit:cover;display:block;transition:transform .5s ease}.nfa-vtestimonials--thumb-zoom .nfa-vtestimonials__card:hover .nfa-vtestimonials__thumb img{transform:scale(1.08)}.nfa-vtestimonials__thumb::after{content:'';position:absolute;inset:0;background:rgba(0,0,0,.25);transition:background .35s ease;pointer-events:none;z-index:1}.nfa-vtestimonials__card:hover .nfa-vtestimonials__thumb::after{background:rgba(0,0,0,.45)}.nfa-vtestimonials__play{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);z-index:2;width:56px;height:56px;border-radius:50%;border:none;background-color:rgba(255,255,255,.95);display:inline-flex;align-items:center;justify-content:center;cursor:pointer;transition:transform .35s ease,background-color .3s ease,box-shadow .3s ease;box-shadow:0 4px 20px rgba(0,0,0,.15);padding:0}.nfa-vtestimonials__play svg{width:20px;height:20px;fill:#1a1a2e;margin-left:2px}.nfa-vtestimonials__card:hover .nfa-vtestimonials__play{transform:translate(-50%,-50%) scale(1.15);background-color:#fff;box-shadow:0 6px 30px rgba(0,0,0,.2)}.nfa-vtestimonials__duration{position:absolute;bottom:10px;right:10px;z-index:2;background-color:rgba(0,0,0,.7);color:#fff;font-size:.75rem;font-weight:600;padding:3px 8px;border-radius:4px;line-height:1.3;letter-spacing:.02em}.nfa-vtestimonials__content{padding:16px 16px 4px 16px;flex:1;display:flex;flex-direction:column}.nfa-vtestimonials__rating{color:#fbbf24;font-size:16px;line-height:1;margin-bottom:8px;letter-spacing:2px}.nfa-vtestimonials__quote{font-size:.92rem;line-height:1.6;color:#333;margin:0 0 12px 0;flex:1}.nfa-vtestimonials__author{display:flex;align-items:center;gap:10px;margin-top:auto;padding-top:10px}.nfa-vtestimonials__avatar{width:40px;height:40px;border-radius:50%;object-fit:cover;flex-shrink:0}.nfa-vtestimonials__author-info{min-width:0}.nfa-vtestimonials__name{font-size:.9rem;font-weight:700;color:#1a1a2e;line-height:1.3;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.nfa-vtestimonials__role{font-size:.8rem;color:#888;line-height:1.3;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.nfa-vtestimonials-lightbox{position:fixed;inset:0;z-index:100000;display:flex;align-items:center;justify-content:center;background:rgba(0,0,0,.85);opacity:0;visibility:hidden;transition:opacity .35s ease,visibility .35s ease}.nfa-vtestimonials-lightbox.is-open{opacity:1;visibility:visible}.nfa-vtestimonials-lightbox__inner{position:relative;width:90%;max-width:900px;aspect-ratio:16/9;background:#000;border-radius:12px;overflow:hidden;transform:scale(.9);transition:transform .35s ease}.nfa-vtestimonials-lightbox.is-open .nfa-vtestimonials-lightbox__inner{transform:scale(1)}.nfa-vtestimonials-lightbox__inner iframe{width:100%;height:100%;border:0}.nfa-vtestimonials-lightbox__media{width:100%;height:100%}.nfa-vtestimonials-lightbox__media iframe,.nfa-vtestimonials-lightbox__media video{width:100%;height:100%;border:0}.nfa-vtestimonials-lightbox__close{position:absolute;top:-40px;right:0;width:32px;height:32px;border-radius:50%;border:none;background:rgba(255,255,255,.15);color:#fff;font-size:18px;cursor:pointer;display:inline-flex;align-items:center;justify-content:center;transition:background .25s ease;padding:0;line-height:1}.nfa-vtestimonials-lightbox__close:hover{background:rgba(255,255,255,.3)}.nfa-vtestimonials__thumb--playing{position:relative}.nfa-vtestimonials__thumb--playing iframe,.nfa-vtestimonials__thumb--playing video{position:absolute;inset:0;width:100%;height:100%;border:0;z-index:5;object-fit:cover}.nfa-vtestimonials__reel-card video::-webkit-media-controls,.nfa-vtestimonials__thumb--playing video::-webkit-media-controls{display:none!important}.nfa-vtestimonials__reel-card.is-playing .nfa-vtestimonials__reel-play{display:none}.nfa-vtestimonials__reel-card.is-playing .nfa-vtestimonials__reel-img{visibility:hidden}.nfa-vtestimonials__reel-card.is-playing .nfa-vtestimonials__reel-controls{z-index:10;opacity:0;transition:opacity .3s ease;pointer-events:none}.nfa-vtestimonials__reel-card.is-playing:hover .nfa-vtestimonials__reel-controls{opacity:1;pointer-events:auto}.nfa-vtestimonials__reel-card.is-playing::after{background:0 0}.nfa-vtestimonials--carousel{overflow:hidden;position:relative}.nfa-vtestimonials__viewport{overflow:hidden}.nfa-vtestimonials__track{display:flex;transition:transform .45s cubic-bezier(.25, .46, .45, .94);will-change:transform;cursor:grab;user-select:none;-webkit-user-select:none}.nfa-vtestimonials--carousel.is-dragging .nfa-vtestimonials__track{cursor:grabbing}.nfa-vtestimonials--carousel .nfa-vtestimonials__card{flex:0 0 calc((100% - 48px)/ 3);min-height:0}.nfa-vtestimonials__nav{display:flex;gap:8px;margin-top:20px}.nfa-vtestimonials--nav-bottom-right .nfa-vtestimonials__nav{justify-content:flex-end}.nfa-vtestimonials--nav-bottom-left .nfa-vtestimonials__nav{justify-content:flex-start}.nfa-vtestimonials--nav-bottom-center .nfa-vtestimonials__nav{justify-content:center}.nfa-vtestimonials--nav-top-center .nfa-vtestimonials__nav,.nfa-vtestimonials--nav-top-left .nfa-vtestimonials__nav,.nfa-vtestimonials--nav-top-right .nfa-vtestimonials__nav{margin-top:0;margin-bottom:20px;order:-1}.nfa-vtestimonials--nav-top-right .nfa-vtestimonials__nav{justify-content:flex-end}.nfa-vtestimonials--nav-top-left .nfa-vtestimonials__nav{justify-content:flex-start}.nfa-vtestimonials--nav-top-center .nfa-vtestimonials__nav{justify-content:center}.nfa-vtestimonials--nav-top-center,.nfa-vtestimonials--nav-top-left,.nfa-vtestimonials--nav-top-right{display:flex;flex-direction:column}.nfa-vtestimonials--nav-sides{position:relative}.nfa-vtestimonials__arrow--side{position:absolute;top:50%;transform:translateY(-50%);z-index:2}.nfa-vtestimonials__arrow--side.nfa-vtestimonials__arrow--prev{left:-48px}.nfa-vtestimonials__arrow--side.nfa-vtestimonials__arrow--next{right:-48px}@media (max-width:1200px){.nfa-vtestimonials__arrow--side.nfa-vtestimonials__arrow--prev{left:8px}.nfa-vtestimonials__arrow--side.nfa-vtestimonials__arrow--next{right:8px}}.nfa-vtestimonials__arrow{display:inline-flex;align-items:center;justify-content:center;width:40px;height:40px;border-radius:50%;border:1.5px solid #e0e0e0;background:#fff;color:#1a1a2e;cursor:pointer;transition:background-color .25s ease,border-color .25s ease,color .25s ease,transform .2s ease;padding:0}.nfa-vtestimonials__arrow:hover{background-color:#1a1a2e;border-color:#1a1a2e;color:#fff;transform:scale(1.08)}.nfa-vtestimonials__arrow--side:hover{transform:translateY(-50%) scale(1.08)}.nfa-vtestimonials__arrow svg{width:16px;height:16px}.nfa-vtestimonials__dots{display:flex;gap:8px;justify-content:center;margin-top:20px;padding:4px 0}.nfa-vtestimonials__dot{width:10px;height:10px;border-radius:50%;border:none;background-color:#d1d5db;cursor:pointer;padding:0;transition:background-color .25s ease,transform .2s ease}.nfa-vtestimonials__dot:hover{transform:scale(1.3)}.nfa-vtestimonials__dot.is-active{background-color:#1a1a2e;transform:scale(1.2)}.nfa-vtestimonials__reel{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:16px}.nfa-vtestimonials__reel-card{position:relative;aspect-ratio:9/16;border-radius:.5rem;overflow:hidden;cursor:pointer;background:#000}.nfa-vtestimonials__reel-card::after{content:'';position:absolute;inset:0;background:rgb(0 0 0 / .2);transition:background-color 150ms cubic-bezier(.4, 0, .2, 1);pointer-events:none;z-index:1}.nfa-vtestimonials__reel-card:hover::after{background:rgb(0 0 0 / .3)}.nfa-vtestimonials__reel-video{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;z-index:0;background:#000}.nfa-vtestimonials__reel-video::-webkit-media-controls{display:none!important}.nfa-vtestimonials__reel-card:hover .nfa-vtestimonials__reel-video{transform:none;transition:none}.nfa-vtestimonials__reel-play{position:absolute;inset:auto;top:50%;left:50%;width:56px;height:56px;transform:translate(-50%,-50%);z-index:2;border:none;background-color:transparent;display:inline-flex;align-items:center;justify-content:center;cursor:pointer;transition:color 150ms cubic-bezier(.4, 0, .2, 1),background-color 150ms cubic-bezier(.4, 0, .2, 1),border-color 150ms cubic-bezier(.4, 0, .2, 1),fill 150ms cubic-bezier(.4, 0, .2, 1),stroke 150ms cubic-bezier(.4, 0, .2, 1);padding:0}.nfa-vtestimonials__reel-play svg{width:2rem;height:2rem;fill:#ffffff;stroke:#ffffff;color:#fff;margin-left:0;background-color:rgb(0 0 0 / .5);border-radius:9999px;padding:.75rem;box-sizing:content-box}.nfa-vtestimonials__reel-controls{position:absolute;right:.5rem;left:.5rem;bottom:.5rem;z-index:2;display:flex;align-items:center;gap:.25rem}.nfa-vtestimonials__reel-ctrl{display:inline-flex;align-items:center;justify-content:center;width:2rem;height:2rem;border-radius:9999px;background:#00000080;color:#fff;transition:color 150ms cubic-bezier(.4, 0, .2, 1),background-color 150ms cubic-bezier(.4, 0, .2, 1),border-color 150ms cubic-bezier(.4, 0, .2, 1),fill 150ms cubic-bezier(.4, 0, .2, 1),stroke 150ms cubic-bezier(.4, 0, .2, 1);cursor:pointer;border:none;margin:0;padding:0}.nfa-vtestimonials__reel-ctrl:hover{background:#00000080}.nfa-vtestimonials__reel-ctrl svg{width:1rem;height:1rem;fill:#ffffff;stroke:#ffffff;color:#fff}@media (max-width:1024px){.nfa-vtestimonials__grid{grid-template-columns:repeat(2,minmax(0,1fr))}.nfa-vtestimonials__reel{grid-template-columns:repeat(2,minmax(0,1fr))}}@media (max-width:767px){.nfa-vtestimonials__grid{grid-template-columns:1fr}.nfa-vtestimonials__thumb{height:180px}.nfa-vtestimonials__reel{grid-template-columns:1fr;max-width:320px;margin-inline:auto}}
  • nebula-forge-addons-for-elementor/trunk/assets/js/frontend.js

    r3463206 r3463463  
    12151215        });
    12161216
    1217         /* ── Video Play Actions (grid + carousel) ─────── */
     1217        /* ── Helper: stop all playing videos globally ─────── */
     1218        function stopAllVideos() {
     1219            /* Remove inline iframes */
     1220            $('.nfa-vtestimonials__thumb--playing iframe, .nfa-vtestimonials__thumb--playing video').each(function () {
     1221                const el = this;
     1222                if (el.tagName === 'VIDEO') { el.pause(); }
     1223                $(el).remove();
     1224            });
     1225            $('.nfa-vtestimonials__thumb--playing').removeClass('nfa-vtestimonials__thumb--playing')
     1226                .find('.nfa-vtestimonials__play, .nfa-vtestimonials__duration').show();
     1227
     1228            /* Reel cards */
     1229            $('.nfa-vtestimonials__reel-card.is-playing').each(function () {
     1230                const $rc = $(this);
     1231                const nativeVideo = $rc.find('.nfa-vtestimonials__reel-video').get(0);
     1232                if (nativeVideo) {
     1233                    nativeVideo.pause();
     1234                    nativeVideo.currentTime = 0;
     1235                }
     1236                $rc.find('.nfa-vtestimonials__reel-runtime').each(function () {
     1237                    if (this.tagName === 'VIDEO') this.pause();
     1238                    $(this).remove();
     1239                });
     1240                $rc.removeClass('is-playing');
     1241                $rc.find('.nfa-vtestimonials__reel-play').show();
     1242                $rc.find('.nfa-vtestimonials__reel-controls').show();
     1243                /* reset control icons */
     1244                $rc.find('.play_icon').css('display', 'inline');
     1245                $rc.find('.pause_icon').css('display', 'none');
     1246                $rc.find('.volume_up_icon').css('display', 'inline');
     1247                $rc.find('.volume_mute_icon').css('display', 'none');
     1248            });
     1249
     1250            /* Close lightbox if open */
     1251            const $lb = $('#nfa-vtestimonials-lightbox');
     1252            if ($lb.hasClass('is-open')) {
     1253                $lb.removeClass('is-open');
     1254                setTimeout(function () { $lb.find('.nfa-vtestimonials-lightbox__media').empty(); }, 350);
     1255            }
     1256        }
     1257
     1258        /* ── Video Play Actions ─────────────────────────── */
    12181259        scope.find('.nfa-vtestimonials__card[data-video-url]').each(function () {
    1219             const $card  = $(this);
    1220             const url    = $card.data('video-url');
    1221             const action = $card.data('action');
     1260            const $card    = $(this);
     1261            const url      = $card.data('video-url');
     1262            const action   = $card.data('action');
     1263            const isHosted = $card.data('video-type') === 'hosted';
     1264            const isReel   = $card.hasClass('nfa-vtestimonials__reel-card');
    12221265
    12231266            if (!url) return;
    12241267
     1268            /* Reel bottom-bar play/pause toggle */
     1269            if (isReel) {
     1270                $card.find('.nfa-vtestimonials__reel-ctrl--play').on('click', function (e) {
     1271                    e.stopPropagation();
     1272                    const vid = $card.find('.nfa-vtestimonials__reel-video')[0];
     1273                    if (!vid) return;
     1274                    if (vid.paused) {
     1275                        stopAllVideos();
     1276                        $card.addClass('is-playing');
     1277                        $card.find('.nfa-vtestimonials__reel-play').hide();
     1278                        vid.play();
     1279                        $card.find('.play_icon').css('display', 'none');
     1280                        $card.find('.pause_icon').css('display', 'inline');
     1281                    } else {
     1282                        vid.pause();
     1283                        $card.removeClass('is-playing');
     1284                        $card.find('.nfa-vtestimonials__reel-play').show();
     1285                        $card.find('.play_icon').css('display', 'inline');
     1286                        $card.find('.pause_icon').css('display', 'none');
     1287                    }
     1288                });
     1289
     1290                /* Reel volume toggle */
     1291                $card.find('.nfa-vtestimonials__reel-ctrl--volume').on('click', function (e) {
     1292                    e.stopPropagation();
     1293                    const vid = $card.find('.nfa-vtestimonials__reel-video')[0];
     1294                    if (!vid) return;
     1295                    vid.muted = !vid.muted;
     1296                    $card.find('.volume_up_icon').css('display', vid.muted ? 'none' : 'inline');
     1297                    $card.find('.volume_mute_icon').css('display', vid.muted ? 'inline' : 'none');
     1298                });
     1299            }
     1300
     1301            /* Main play button click */
    12251302            $card.find('.nfa-vtestimonials__play').on('click', function (e) {
    12261303                e.stopPropagation();
     
    12311308                }
    12321309
     1310                /* Stop any currently playing video first */
     1311                stopAllVideos();
     1312
    12331313                if (action === 'inline') {
    1234                     const $thumb = $card.find('.nfa-vtestimonials__thumb');
    1235                     if ($thumb.hasClass('nfa-vtestimonials__thumb--playing')) return;
    1236                     $thumb.addClass('nfa-vtestimonials__thumb--playing');
    1237                     const iframe = document.createElement('iframe');
    1238                     iframe.src = url;
    1239                     iframe.setAttribute('allow', 'autoplay; encrypted-media');
    1240                     iframe.setAttribute('allowfullscreen', '');
    1241                     $thumb.append(iframe);
    1242                     $thumb.find('.nfa-vtestimonials__play, .nfa-vtestimonials__duration').hide();
     1314                    if (isReel) {
     1315                        /* ── Reel inline: custom controls, no browser UI ── */
     1316                        $card.addClass('is-playing');
     1317
     1318                        if (isHosted) {
     1319                            const video = $card.find('.nfa-vtestimonials__reel-video').get(0);
     1320                            if (video) {
     1321                                video.muted = false;
     1322                                video.play();
     1323                            }
     1324                            /* Update icons to pause */
     1325                            $card.find('.play_icon').css('display', 'none');
     1326                            $card.find('.pause_icon').css('display', 'inline');
     1327                        } else {
     1328                            const iframe = document.createElement('iframe');
     1329                            iframe.src = url;
     1330                            iframe.setAttribute('allow', 'autoplay; encrypted-media');
     1331                            iframe.setAttribute('allowfullscreen', '');
     1332                            iframe.className = 'nfa-vtestimonials__reel-runtime';
     1333                            iframe.style.cssText = 'width:100%;height:100%;position:absolute;top:0;left:0;z-index:5;border:0;';
     1334                            $card.append(iframe);
     1335                            /* hide reel controls for iframe (can't control them) */
     1336                            $card.find('.nfa-vtestimonials__reel-controls').hide();
     1337                        }
     1338                        $card.find('.nfa-vtestimonials__reel-play').hide();
     1339                    } else {
     1340                        /* ── Grid / Carousel inline ── */
     1341                        const $container = $card.find('.nfa-vtestimonials__thumb');
     1342                        if ($container.hasClass('nfa-vtestimonials__thumb--playing')) return;
     1343                        $container.addClass('nfa-vtestimonials__thumb--playing');
     1344
     1345                        if (isHosted) {
     1346                            const video = document.createElement('video');
     1347                            video.src = url;
     1348                            video.autoplay = true;
     1349                            video.controls = true;
     1350                            $container.append(video);
     1351                        } else {
     1352                            const iframe = document.createElement('iframe');
     1353                            iframe.src = url;
     1354                            iframe.setAttribute('allow', 'autoplay; encrypted-media');
     1355                            iframe.setAttribute('allowfullscreen', '');
     1356                            $container.append(iframe);
     1357                        }
     1358                        $container.find('.nfa-vtestimonials__play, .nfa-vtestimonials__duration').hide();
     1359                    }
    12431360                    return;
    12441361                }
     
    12501367                        '<div class="nfa-vtestimonials-lightbox__inner">' +
    12511368                        '<button class="nfa-vtestimonials-lightbox__close" aria-label="Close">&times;</button>' +
    1252                         '<iframe allow="autoplay; encrypted-media" allowfullscreen></iframe>' +
     1369                        '<div class="nfa-vtestimonials-lightbox__media"></div>' +
    12531370                        '</div>' +
    12541371                        '</div>');
    12551372                    $('body').append($lb);
    12561373
    1257                     $lb.find('.nfa-vtestimonials-lightbox__close').on('click', function () {
     1374                    const closeLb = function () {
    12581375                        $lb.removeClass('is-open');
    1259                         setTimeout(function () { $lb.find('iframe').attr('src', ''); }, 350);
     1376                        setTimeout(function () {
     1377                            $lb.find('.nfa-vtestimonials-lightbox__media').empty();
     1378                        }, 350);
     1379                    };
     1380
     1381                    $lb.find('.nfa-vtestimonials-lightbox__close').on('click', closeLb);
     1382
     1383                    $lb.on('click', function (ev) {
     1384                        if ($(ev.target).hasClass('nfa-vtestimonials-lightbox')) closeLb();
    12601385                    });
    12611386
    1262                     $lb.on('click', function (ev) {
    1263                         if ($(ev.target).hasClass('nfa-vtestimonials-lightbox')) {
    1264                             $lb.removeClass('is-open');
    1265                             setTimeout(function () { $lb.find('iframe').attr('src', ''); }, 350);
    1266                         }
     1387                    $(document).on('keydown', function (ev) {
     1388                        if (ev.key === 'Escape' && $lb.hasClass('is-open')) closeLb();
    12671389                    });
    1268 
    1269                     $(document).on('keydown', function (ev) {
    1270                         if (ev.key === 'Escape' && $lb.hasClass('is-open')) {
    1271                             $lb.removeClass('is-open');
    1272                             setTimeout(function () { $lb.find('iframe').attr('src', ''); }, 350);
    1273                         }
    1274                     });
    1275                 }
    1276 
    1277                 $lb.find('iframe').attr('src', url);
     1390                }
     1391
     1392                const $media = $lb.find('.nfa-vtestimonials-lightbox__media');
     1393                $media.empty();
     1394                if (isHosted) {
     1395                    $media.append('<video src="' + url + '" autoplay controls style="width:100%;height:100%;object-fit:contain;"></video>');
     1396                } else {
     1397                    $media.append('<iframe src="' + url + '" allow="autoplay; encrypted-media" allowfullscreen style="width:100%;height:100%;border:0;"></iframe>');
     1398                }
    12781399                $lb.addClass('is-open');
    12791400            });
  • nebula-forge-addons-for-elementor/trunk/assets/js/frontend.min.js

    r3463206 r3463463  
    1 (function ($) { 'use strict'; const initSlider = (scope) => { const $sliders = scope.find('.nfa-slider'); $sliders.each(function () { const $slider = $(this); const track = $slider.find('.nfa-slider__track').get(0); if (!track) { return; } const perView = Math.max(1, Math.min(6, parseInt($slider.data('slider-per-view'), 10) || 3)); const gap = Math.max(0, parseInt($slider.data('slider-gap'), 10) || 20); const items = Array.from(track.children); const updateSizes = () => { track.style.gap = gap + 'px'; const width = 'calc((100% - ' + (gap * (perView - 1)) + 'px) / ' + perView + ')'; items.forEach((item) => { item.style.flex = '0 0 ' + width; }); }; updateSizes(); if ($slider.data('slider-bound')) { return; } $slider.data('slider-bound', true); let resizeTimer; $(window).on('resize.nfaSlider', () => { clearTimeout(resizeTimer); resizeTimer = setTimeout(updateSizes, 150); }); $slider.find('.nfa-slider__btn--prev').on('click', () => { track.scrollBy({ left: -track.clientWidth, behavior: 'smooth' }); }); $slider.find('.nfa-slider__btn--next').on('click', () => { track.scrollBy({ left: track.clientWidth, behavior: 'smooth' }); }); }); }; const initShowcaseCarousel = (scope) => { const $carousel = scope.find('.nfa-showcase'); if (!$carousel.length) { return; } $carousel.each(function () { const $el = $(this); const track = $el.find('.nfa-showcase__track').get(0); const $dotsWrap = $el.find('.nfa-showcase__dots'); const cards = Array.from(track.children); const totalSlides = cards.length; if (!track || totalSlides === 0) { return; } if ($el.data('showcase-bound')) { return; } $el.data('showcase-bound', true); const perViewDesktop = Math.max(1, parseInt($el.data('per-view'), 10) || 3); const perViewTablet = Math.max(1, parseInt($el.data('per-view-tablet'), 10) || 2); const perViewMobile = Math.max(1, parseInt($el.data('per-view-mobile'), 10) || 1); const gap = Math.max(0, parseInt($el.data('gap'), 10) || 20); const doAutoplay = $el.data('autoplay') === 'yes'; const autoplaySpeed = Math.max(1000, parseInt($el.data('autoplay-speed'), 10) || 4000); const pauseOnHover = $el.data('pause-on-hover') === 'yes'; let pos = 0; let autoplayTimer = null; function getPerView() { const w = window.innerWidth; if (w <= 767) return perViewMobile; if (w <= 1024) return perViewTablet; return perViewDesktop; } function getMaxPos() { return Math.max(0, totalSlides - getPerView()); } function render() { const pv = getPerView(); const cardWidth = 'calc((100% - ' + (gap * (pv - 1)) + 'px) / ' + pv + ')'; cards.forEach(function (card) { card.style.flex = '0 0 ' + cardWidth; }); if (cards[0]) { const rect = cards[0].getBoundingClientRect(); const cardPx = rect.width + gap; track.style.transform = 'translateX(-' + (pos * cardPx) + 'px)'; } updateDots(); } function updateDots() { if (!$dotsWrap.length) return; const maxPos = getMaxPos(); const dotCount = maxPos + 1; if ($dotsWrap.children().length !== dotCount) { $dotsWrap.empty(); for (var i = 0; i < dotCount; i++) { $dotsWrap.append('<button class="nfa-showcase__dot" data-index="' + i + '" aria-label="Slide ' + (i + 1) + '"></button>'); } $dotsWrap.find('.nfa-showcase__dot').on('click', function () { pos = parseInt($(this).data('index'), 10); pos = Math.min(pos, getMaxPos()); render(); resetAutoplay(); }); } $dotsWrap.find('.nfa-showcase__dot').removeClass('nfa-showcase__dot--active'); $dotsWrap.find('.nfa-showcase__dot').eq(pos).addClass('nfa-showcase__dot--active'); } function next() { pos = pos >= getMaxPos() ? 0 : pos + 1; render(); } function prev() { pos = pos <= 0 ? getMaxPos() : pos - 1; render(); } function startAutoplay() { if (!doAutoplay) return; stopAutoplay(); autoplayTimer = setInterval(next, autoplaySpeed); } function stopAutoplay() { if (autoplayTimer) { clearInterval(autoplayTimer); autoplayTimer = null; } } function resetAutoplay() { if (!doAutoplay) return; stopAutoplay(); startAutoplay(); } $el.find('.nfa-showcase__arrow--prev').on('click', function () { prev(); resetAutoplay(); }); $el.find('.nfa-showcase__arrow--next').on('click', function () { next(); resetAutoplay(); }); if (pauseOnHover && doAutoplay) { $el.on('mouseenter', stopAutoplay); $el.on('mouseleave', startAutoplay); } let resizeTimer; $(window).on('resize.nfaShowcaseCarousel', function () { clearTimeout(resizeTimer); resizeTimer = setTimeout(function () { pos = Math.min(pos, getMaxPos()); render(); }, 150); }); render(); startAutoplay(); }); }; const initNumberedCards = (scope) => { const $carousel = scope.find('.nfa-ncards--carousel'); if (!$carousel.length) return; $carousel.each(function () { const $el = $(this); const track = $el.find('.nfa-ncards__track').get(0); const cards = Array.from(track.children); const totalSlides = cards.length; if (!track || totalSlides === 0) return; if ($el.data('ncards-bound')) return; $el.data('ncards-bound', true); const perViewDesktop = Math.max(1, parseInt($el.data('per-view'), 10) || 3); const perViewTablet = Math.max(1, parseInt($el.data('per-view-tablet'), 10) || 2); const perViewMobile = Math.max(1, parseInt($el.data('per-view-mobile'), 10) || 1); const gap = Math.max(0, parseInt($el.data('gap'), 10) || 20); const doAutoplay = $el.data('autoplay') === 'yes'; const autoplaySpeed = Math.max(1000, parseInt($el.data('autoplay-speed'), 10) || 4000); const pauseOnHover = $el.data('pause-on-hover') === 'yes'; const enableDrag = $el.data('mouse-drag') === 'yes'; const infiniteLoop = $el.data('infinite') === 'yes'; const transSpeed = Math.max(100, parseInt($el.data('speed'), 10) || 450); const $dots = $el.find('.nfa-ncards__dots'); track.style.transition = 'transform ' + transSpeed + 'ms cubic-bezier(0.25,0.46,0.45,0.94)'; let pos = 0; let autoplayTimer = null; function getPerView() { const w = window.innerWidth; if (w <= 767) return perViewMobile; if (w <= 1024) return perViewTablet; return perViewDesktop; } function getMaxPos() { return Math.max(0, totalSlides - getPerView()); } function buildDots() { if (!$dots.length) return; $dots.empty(); const maxPos = getMaxPos(); for (let i = 0; i <= maxPos; i++) { const dot = document.createElement('button'); dot.className = 'nfa-ncards__dot' + (i === pos ? ' is-active' : ''); dot.setAttribute('aria-label', 'Go to slide ' + (i + 1)); dot.addEventListener('click', function () { pos = i; render(); updateDots(); resetAutoplay(); }); $dots.get(0).appendChild(dot); } } function updateDots() { if (!$dots.length) return; $dots.find('.nfa-ncards__dot').each(function (i) { $(this).toggleClass('is-active', i === pos); }); } function render() { const pv = getPerView(); const cardWidth = 'calc((100% - ' + (gap * (pv - 1)) + 'px) / ' + pv + ')'; cards.forEach(function (card) { card.style.flex = '0 0 ' + cardWidth; }); if (cards[0]) { const rect = cards[0].getBoundingClientRect(); const cardPx = rect.width + gap; track.style.transform = 'translateX(-' + (pos * cardPx) + 'px)'; } } function next() { if (infiniteLoop) { pos = pos >= getMaxPos() ? 0 : pos + 1; } else { pos = Math.min(pos + 1, getMaxPos()); } render(); updateDots(); } function prev() { if (infiniteLoop) { pos = pos <= 0 ? getMaxPos() : pos - 1; } else { pos = Math.max(pos - 1, 0); } render(); updateDots(); } function startAutoplay() { if (!doAutoplay) return; stopAutoplay(); autoplayTimer = setInterval(next, autoplaySpeed); } function stopAutoplay() { if (autoplayTimer) { clearInterval(autoplayTimer); autoplayTimer = null; } } function resetAutoplay() { if (!doAutoplay) return; stopAutoplay(); startAutoplay(); } $el.find('.nfa-ncards__arrow--prev').on('click', function () { prev(); resetAutoplay(); }); $el.find('.nfa-ncards__arrow--next').on('click', function () { next(); resetAutoplay(); }); if (enableDrag) { let dragStartX = 0; let dragDelta = 0; let isDragging = false; let startTransX = 0; const threshold = 40; // px to trigger slide change function getTranslateX() { const st = window.getComputedStyle(track); const mx = new DOMMatrix(st.transform); return mx.m41; } function onDragStart(e) { isDragging = true; dragStartX = e.type.includes('touch') ? e.touches[0].clientX : e.clientX; startTransX = getTranslateX(); track.style.transition = 'none'; stopAutoplay(); $el.addClass('is-dragging'); } function onDragMove(e) { if (!isDragging) return; const clientX = e.type.includes('touch') ? e.touches[0].clientX : e.clientX; dragDelta = clientX - dragStartX; track.style.transform = 'translateX(' + (startTransX + dragDelta) + 'px)'; } function onDragEnd() { if (!isDragging) return; isDragging = false; $el.removeClass('is-dragging'); track.style.transition = 'transform ' + transSpeed + 'ms cubic-bezier(0.25,0.46,0.45,0.94)'; if (Math.abs(dragDelta) > threshold) { if (dragDelta < 0) { next(); } else { prev(); } } else { render(); // snap back } dragDelta = 0; resetAutoplay(); } track.addEventListener('mousedown', onDragStart); window.addEventListener('mousemove', onDragMove); window.addEventListener('mouseup', onDragEnd); track.addEventListener('touchstart', onDragStart, { passive: true }); track.addEventListener('touchmove', onDragMove, { passive: true }); track.addEventListener('touchend', onDragEnd); $(track).find('img').on('dragstart', function (e) { e.preventDefault(); }); $(track).on('click', 'a', function (e) { if (Math.abs(dragDelta) > 5) { e.preventDefault(); } }); } if (pauseOnHover && doAutoplay) { $el.on('mouseenter', stopAutoplay); $el.on('mouseleave', startAutoplay); } let resizeTimer; $(window).on('resize.nfaNumberedCards', function () { clearTimeout(resizeTimer); resizeTimer = setTimeout(function () { pos = Math.min(pos, getMaxPos()); render(); buildDots(); }, 150); }); render(); buildDots(); startAutoplay(); }); }; const initContentTabs = (scope) => { const $tabs = scope.find('[data-tabs]'); if (!$tabs.length) return; $tabs.each(function () { const $el = $(this); if ($el.data('tabs-bound')) return; $el.data('tabs-bound', true); const $buttons = $el.find('.nfa-tabs__btn'); const $panels = $el.find('.nfa-tabs__panel'); $buttons.on('click', function () { const $btn = $(this); const target = $btn.attr('aria-controls'); $buttons.removeClass('nfa-tabs__btn--active').attr('aria-selected', 'false'); $btn.addClass('nfa-tabs__btn--active').attr('aria-selected', 'true'); $panels.removeClass('nfa-tabs__panel--active').attr('hidden', true); $el.find('#' + target).addClass('nfa-tabs__panel--active').removeAttr('hidden'); }); }); }; const initImageComparison = (scope) => { const $compare = scope.find('[data-compare]'); if (!$compare.length) return; $compare.each(function () { const el = this; const $el = $(el); if ($el.data('compare-bound')) return; $el.data('compare-bound', true); const orientation = $el.data('orientation') || 'horizontal'; const isHoriz = orientation === 'horizontal'; const $before = $el.find('.nfa-compare__before'); const $slider = $el.find('.nfa-compare__slider'); let dragging = false; function setPosition(pct) { pct = Math.max(0, Math.min(100, pct)); if (isHoriz) { $before.css('clip-path', 'inset(0 ' + (100 - pct) + '% 0 0)'); $slider.css('left', pct + '%'); } else { $before.css('clip-path', 'inset(0 0 ' + (100 - pct) + '% 0)'); $slider.css('top', pct + '%'); } } function getPercent(e) { const rect = el.getBoundingClientRect(); const clientX = e.touches ? e.touches[0].clientX : e.clientX; const clientY = e.touches ? e.touches[0].clientY : e.clientY; if (isHoriz) { return ((clientX - rect.left) / rect.width) * 100; } return ((clientY - rect.top) / rect.height) * 100; } function onMove(e) { if (!dragging) return; e.preventDefault(); setPosition(getPercent(e)); } function onUp() { dragging = false; $(document).off('mousemove.nfaCompare touchmove.nfaCompare'); $(document).off('mouseup.nfaCompare touchend.nfaCompare'); } $el.on('mousedown touchstart', function (e) { dragging = true; setPosition(getPercent(e)); $(document).on('mousemove.nfaCompare touchmove.nfaCompare', onMove); $(document).on('mouseup.nfaCompare touchend.nfaCompare', onUp); }); }); }; const initCountdownTimer = (scope) => { const $countdown = scope.find('[data-countdown]'); if (!$countdown.length) return; $countdown.each(function () { const $el = $(this); if ($el.data('countdown-bound')) return; $el.data('countdown-bound', true); const targetDate = new Date($el.data('target')).getTime(); const expiry = $el.data('expiry') || {}; const units = ($el.data('units') || 'days,hours,minutes,seconds').split(','); const circumference = 2 * Math.PI * 44; // r=44 in SVG function update() { const now = Date.now(); const diff = Math.max(0, targetDate - now); if (diff <= 0) { handleExpiry(); return; } const totalSec = Math.floor(diff / 1000); const vals = { days: Math.floor(totalSec / 86400), hours: Math.floor((totalSec % 86400) / 3600), minutes: Math.floor((totalSec % 3600) / 60), seconds: totalSec % 60, }; units.forEach(function (unit) { const $digit = $el.find('[data-digit="' + unit + '"]'); $digit.text(String(vals[unit]).padStart(2, '0')); const $progress = $el.find('[data-unit="' + unit + '"] .nfa-countdown__progress'); if ($progress.length) { const max = parseInt($progress.data('max'), 10) || 60; const fraction = vals[unit] / max; const offset = circumference * (1 - fraction); $progress.attr('stroke-dashoffset', offset); } }); } function handleExpiry() { clearInterval(timer); const action = expiry.action || 'none'; if (action === 'message') { $el.find('.nfa-countdown__block, .nfa-countdown__sep').hide(); $el.find('.nfa-countdown__expiry').show(); } else if (action === 'hide') { $el.hide(); } else if (action === 'redirect' && expiry.redirect) { window.location.href = expiry.redirect; } } update(); const timer = setInterval(update, 1000); }); }; const initTooltips = () => { document.querySelectorAll('[data-nfa-tooltip]').forEach((el) => { if (el._nfaTooltipBound) { return; } el._nfaTooltipBound = true; const text = el.getAttribute('data-nfa-tooltip'); const pos = el.getAttribute('data-nfa-tooltip-pos') || 'top'; const trigger = el.getAttribute('data-nfa-tooltip-trigger') || 'hover'; const showArrow = el.getAttribute('data-nfa-tooltip-arrow') !== '0'; const duration = parseInt(el.getAttribute('data-nfa-tooltip-duration'), 10) || 250; const tip = document.createElement('div'); tip.className = 'nfa-tooltip nfa-tooltip--' + pos; if (!showArrow) { tip.classList.add('nfa-tooltip--no-arrow'); } tip.textContent = text; tip.style.transitionDuration = duration + 'ms'; tip.setAttribute('role', 'tooltip'); tip.id = 'nfa-tooltip-' + Math.random().toString(36).substr(2, 9); el.setAttribute('aria-describedby', tip.id); el.style.position = el.style.position || 'relative'; document.body.appendChild(tip); function positionTip() { const rect = el.getBoundingClientRect(); const tipRect = tip.getBoundingClientRect(); const scrollY = window.pageYOffset || document.documentElement.scrollTop; const scrollX = window.pageXOffset || document.documentElement.scrollLeft; const gap = 8; let top, left; switch (pos) { case 'bottom': top = rect.bottom + scrollY + gap; left = rect.left + scrollX + (rect.width / 2) - (tipRect.width / 2); break; case 'left': top = rect.top + scrollY + (rect.height / 2) - (tipRect.height / 2); left = rect.left + scrollX - tipRect.width - gap; break; case 'right': top = rect.top + scrollY + (rect.height / 2) - (tipRect.height / 2); left = rect.right + scrollX + gap; break; default: // top top = rect.top + scrollY - tipRect.height - gap; left = rect.left + scrollX + (rect.width / 2) - (tipRect.width / 2); } tip.style.top = top + 'px'; tip.style.left = left + 'px'; } function showTip() { positionTip(); tip.classList.add('nfa-tooltip--visible'); } function hideTip() { tip.classList.remove('nfa-tooltip--visible'); } if (trigger === 'click') { el.addEventListener('click', (e) => { e.preventDefault(); if (tip.classList.contains('nfa-tooltip--visible')) { hideTip(); } else { showTip(); } }); document.addEventListener('click', (e) => { if (!el.contains(e.target) && !tip.contains(e.target)) { hideTip(); } }); } else { el.addEventListener('mouseenter', showTip); el.addEventListener('mouseleave', hideTip); el.addEventListener('focusin', showTip); el.addEventListener('focusout', hideTip); } }); }; const initWrapperLinks = () => { document.querySelectorAll('[data-nfa-wrapper-link]').forEach((el) => { if (el._nfaWrapperLinkBound) { return; } el._nfaWrapperLinkBound = true; const url = el.getAttribute('data-nfa-wrapper-link'); const isExternal = el.getAttribute('data-nfa-link-external') === '1'; const isNofollow = el.getAttribute('data-nfa-link-nofollow') === '1'; if (!url) { return; } el.addEventListener('click', (e) => { const tag = e.target.tagName.toLowerCase(); if (tag === 'a' || tag === 'button' || tag === 'input' || tag === 'textarea' || tag === 'select') { return; } if (isExternal) { const win = window.open(url, '_blank'); if (win && isNofollow) { win.opener = null; } } else { window.location.href = url; } }); el.addEventListener('keydown', (e) => { if (e.key === 'Enter') { el.click(); } }); }); }; const initHamburgerMenu = (scope) => { const $menus = scope.find('.nfa-hamburger'); $menus.each(function () { const $root = $(this); if ($root.data('nfa-hm-bound')) return; $root.data('nfa-hm-bound', true); const $toggle = $root.find('.nfa-hamburger__toggle'); const $panel = $root.find('.nfa-hamburger__panel'); const $overlay = $root.find('.nfa-hamburger__overlay'); const $close = $root.find('.nfa-hamburger__close'); const closeOnLink = $root.data('close-on-link') === 1 || $root.data('close-on-link') === '1'; const closeOnEsc = $root.data('close-on-esc') === 1 || $root.data('close-on-esc') === '1'; function open() { $root.addClass('nfa-hamburger--open'); $toggle.attr('aria-expanded', 'true'); $panel.attr('aria-hidden', 'false'); $panel.find('a, button').first().focus(); } function close() { $root.removeClass('nfa-hamburger--open'); $toggle.attr('aria-expanded', 'false'); $panel.attr('aria-hidden', 'true'); $toggle.focus(); } $toggle.on('click', function (e) { e.preventDefault(); if ($root.hasClass('nfa-hamburger--open')) { close(); } else { open(); } }); $close.on('click', close); $overlay.on('click', close); if (closeOnEsc) { $(document).on('keydown', function (e) { if (e.key === 'Escape' && $root.hasClass('nfa-hamburger--open')) { close(); } }); } if (closeOnLink) { $panel.on('click', '.nfa-hamburger__link, .nfa-hamburger__sub-link', function () { const href = $(this).attr('href'); if (href && href !== '#') { close(); } }); } $root.find('.nfa-hamburger__item--has-sub > .nfa-hamburger__link').on('click', function (e) { if ($(this).attr('href') === '#') { e.preventDefault(); } $(this).parent().toggleClass('nfa-hamburger__item--sub-open'); }); }); }; const initAdvancedForm = (scope) => { const $forms = scope.find('.nfa-form'); $forms.each(function () { const $root = $(this); if ($root.data('nfa-form-bound')) return; $root.data('nfa-form-bound', true); const config = $root.data('nfa-form'); if (!config) return; const $form = $root.find('.nfa-form__el'); const $submit = $root.find('.nfa-form__submit'); const $text = $root.find('.nfa-form__submit-text'); const $spin = $root.find('.nfa-form__spinner'); const $msg = $root.find('.nfa-form__msg'); function validateField(el) { const $el = $(el); const $err = $el.closest('.nfa-form__col').find('.nfa-form__field-error'); let valid = true; let errMsg = ''; if (el.required) { if (el.type === 'checkbox') { const name = el.name; const checked = $form.find('input[name="' + name + '"]:checked').length; if (!checked) { valid = false; errMsg = config.requiredMsg || 'This field is required.'; } } else if (!el.value.trim()) { valid = false; errMsg = config.requiredMsg || 'This field is required.'; } } if (valid && el.value.trim()) { if (el.type === 'email' && !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(el.value)) { valid = false; errMsg = 'Please enter a valid email address.'; } if (el.type === 'url' && !/^https?:\/\/.+/.test(el.value)) { valid = false; errMsg = 'Please enter a valid URL.'; } if (el.type === 'tel' && !/^[\d\s+\-().]+$/.test(el.value)) { valid = false; errMsg = 'Please enter a valid phone number.'; } if (el.type === 'file') { const maxMB = parseFloat($el.data('max-size') || 5); if (el.files[0] && el.files[0].size > maxMB * 1024 * 1024) { valid = false; errMsg = 'File exceeds ' + maxMB + 'MB limit.'; } } } if (!valid) { $el.addClass('nfa-form__input--invalid nfa-form__select--invalid nfa-form__textarea--invalid'); $err.text(errMsg); } else { $el.removeClass('nfa-form__input--invalid nfa-form__select--invalid nfa-form__textarea--invalid'); $err.text(''); } return valid; } $form.find('input, textarea, select').on('blur change', function () { validateField(this); }); $form.on('submit', function (e) { e.preventDefault(); let allValid = true; $form.find('input[required], textarea[required], select[required]').each(function () { if (!validateField(this)) { allValid = false; } }); if (!allValid) { $form.find('.nfa-form__input--invalid, .nfa-form__select--invalid, .nfa-form__textarea--invalid').first().focus(); return; } const fields = []; const seen = {}; $form.find('[data-label]').each(function () { const $el = $(this); const label = $el.data('label'); const type = $el.attr('type') || this.tagName.toLowerCase(); if (type === 'checkbox') { if (!seen[label]) { seen[label] = true; const vals = []; $form.find('input[data-label="' + label + '"]:checked').each(function () { vals.push($(this).val()); }); fields.push({ label: label, value: vals }); } return; } if (type === 'radio') { if (!seen[label]) { seen[label] = true; const val = $form.find('input[data-label="' + label + '"]:checked').val() || ''; fields.push({ label: label, value: val }); } return; } if (type === 'file') { fields.push({ label: label, value: this.files[0] ? this.files[0].name : '' }); return; } fields.push({ label: label, value: $el.val() || '' }); }); $submit.prop('disabled', true); $text.css('opacity', '0.5'); $spin.show(); $msg.hide(); $.ajax({ url: config.ajaxUrl, type: 'POST', data: { action: 'nfa_form_submit', nonce: config.nonce, form_name: config.formName, action_save: config.actionSave ? '1' : '', action_email: config.actionEmail ? '1' : '', email_to: config.emailTo, email_subject: config.emailSubject, email_from_name: config.emailFromName, email_reply_to: config.emailReplyTo, page_url: window.location.href, fields: JSON.stringify(fields), }, success: function (resp) { $submit.prop('disabled', false); $text.css('opacity', '1'); $spin.hide(); if (resp.success) { $msg.removeClass('nfa-form__msg--error').addClass('nfa-form__msg--success') .text(config.successMessage || resp.data.message).show(); $form[0].reset(); $form.find('.nfa-form__field-error').text(''); if (config.actionRedirect && config.redirectUrl) { setTimeout(function () { window.location.href = config.redirectUrl; }, 1000); } } else { $msg.removeClass('nfa-form__msg--success').addClass('nfa-form__msg--error') .text(config.errorMessage || resp.data.message || 'Error').show(); } }, error: function () { $submit.prop('disabled', false); $text.css('opacity', '1'); $spin.hide(); $msg.removeClass('nfa-form__msg--success').addClass('nfa-form__msg--error') .text(config.errorMessage || 'Network error. Please try again.').show(); }, }); }); }); }; const initVideoTestimonials = (scope) => { const $carousel = scope.find('.nfa-vtestimonials--carousel'); $carousel.each(function () { const $el = $(this); const track = $el.find('.nfa-vtestimonials__track').get(0); const cards = Array.from(track.children); const totalSlides = cards.length; if (!track || totalSlides === 0) return; if ($el.data('vtesti-bound')) return; $el.data('vtesti-bound', true); const perViewDesktop = Math.max(1, parseInt($el.data('per-view'), 10) || 3); const perViewTablet = Math.max(1, parseInt($el.data('per-view-tablet'), 10) || 2); const perViewMobile = Math.max(1, parseInt($el.data('per-view-mobile'), 10) || 1); const gap = Math.max(0, parseInt($el.data('gap'), 10) || 24); const doAutoplay = $el.data('autoplay') === 'yes'; const autoplaySpeed = Math.max(1000, parseInt($el.data('autoplay-speed'), 10) || 4000); const pauseOnHover = $el.data('pause-on-hover') === 'yes'; const enableDrag = $el.data('mouse-drag') === 'yes'; const infiniteLoop = $el.data('infinite') === 'yes'; const transSpeed = Math.max(100, parseInt($el.data('speed'), 10) || 450); const $dots = $el.find('.nfa-vtestimonials__dots'); track.style.transition = 'transform ' + transSpeed + 'ms cubic-bezier(0.25,0.46,0.45,0.94)'; let pos = 0; let autoplayTimer = null; function getPerView() { const w = window.innerWidth; if (w <= 767) return perViewMobile; if (w <= 1024) return perViewTablet; return perViewDesktop; } function getMaxPos() { return Math.max(0, totalSlides - getPerView()); } function buildDots() { if (!$dots.length) return; $dots.empty(); const maxPos = getMaxPos(); for (let i = 0; i <= maxPos; i++) { const dot = document.createElement('button'); dot.className = 'nfa-vtestimonials__dot' + (i === pos ? ' is-active' : ''); dot.setAttribute('aria-label', 'Go to slide ' + (i + 1)); dot.addEventListener('click', function () { pos = i; render(); updateDots(); resetAutoplay(); }); $dots.get(0).appendChild(dot); } } function updateDots() { if (!$dots.length) return; $dots.find('.nfa-vtestimonials__dot').each(function (i) { $(this).toggleClass('is-active', i === pos); }); } function render() { const pv = getPerView(); const cardWidth = 'calc((100% - ' + (gap * (pv - 1)) + 'px) / ' + pv + ')'; cards.forEach(function (card) { card.style.flex = '0 0 ' + cardWidth; }); if (cards[0]) { const rect = cards[0].getBoundingClientRect(); const cardPx = rect.width + gap; track.style.transform = 'translateX(-' + (pos * cardPx) + 'px)'; } } function next() { if (infiniteLoop) { pos = pos >= getMaxPos() ? 0 : pos + 1; } else { pos = Math.min(pos + 1, getMaxPos()); } render(); updateDots(); } function prev() { if (infiniteLoop) { pos = pos <= 0 ? getMaxPos() : pos - 1; } else { pos = Math.max(pos - 1, 0); } render(); updateDots(); } function startAutoplay() { if (!doAutoplay) return; stopAutoplay(); autoplayTimer = setInterval(next, autoplaySpeed); } function stopAutoplay() { if (autoplayTimer) { clearInterval(autoplayTimer); autoplayTimer = null; } } function resetAutoplay() { if (!doAutoplay) return; stopAutoplay(); startAutoplay(); } $el.find('.nfa-vtestimonials__arrow--prev').on('click', function () { prev(); resetAutoplay(); }); $el.find('.nfa-vtestimonials__arrow--next').on('click', function () { next(); resetAutoplay(); }); if (enableDrag) { let dragStartX = 0, dragDelta = 0, isDragging = false, startTransX = 0; const threshold = 40; function getTranslateX() { const st = window.getComputedStyle(track); const mx = new DOMMatrix(st.transform); return mx.m41; } function onDragStart(e) { isDragging = true; dragStartX = e.type.includes('touch') ? e.touches[0].clientX : e.clientX; startTransX = getTranslateX(); track.style.transition = 'none'; stopAutoplay(); $el.addClass('is-dragging'); } function onDragMove(e) { if (!isDragging) return; const clientX = e.type.includes('touch') ? e.touches[0].clientX : e.clientX; dragDelta = clientX - dragStartX; track.style.transform = 'translateX(' + (startTransX + dragDelta) + 'px)'; } function onDragEnd() { if (!isDragging) return; isDragging = false; $el.removeClass('is-dragging'); track.style.transition = 'transform ' + transSpeed + 'ms cubic-bezier(0.25,0.46,0.45,0.94)'; if (Math.abs(dragDelta) > threshold) { dragDelta < 0 ? next() : prev(); } else { render(); } dragDelta = 0; resetAutoplay(); } track.addEventListener('mousedown', onDragStart); window.addEventListener('mousemove', onDragMove); window.addEventListener('mouseup', onDragEnd); track.addEventListener('touchstart', onDragStart, { passive: true }); track.addEventListener('touchmove', onDragMove, { passive: true }); track.addEventListener('touchend', onDragEnd); } if (pauseOnHover) { $el.on('mouseenter', stopAutoplay); $el.on('mouseleave', startAutoplay); } render(); buildDots(); startAutoplay(); $(window).on('resize', function () { render(); buildDots(); }); }); scope.find('.nfa-vtestimonials__card[data-video-url]').each(function () { const $card = $(this); const url = $card.data('video-url'); const action = $card.data('action'); if (!url) return; $card.find('.nfa-vtestimonials__play').on('click', function (e) { e.stopPropagation(); if (action === 'new_tab') { window.open(url, '_blank', 'noopener'); return; } if (action === 'inline') { const $thumb = $card.find('.nfa-vtestimonials__thumb'); if ($thumb.hasClass('nfa-vtestimonials__thumb--playing')) return; $thumb.addClass('nfa-vtestimonials__thumb--playing'); const iframe = document.createElement('iframe'); iframe.src = url; iframe.setAttribute('allow', 'autoplay; encrypted-media'); iframe.setAttribute('allowfullscreen', ''); $thumb.append(iframe); $thumb.find('.nfa-vtestimonials__play, .nfa-vtestimonials__duration').hide(); return; } let $lb = $('#nfa-vtestimonials-lightbox'); if (!$lb.length) { $lb = $('<div id="nfa-vtestimonials-lightbox" class="nfa-vtestimonials-lightbox">' + '<div class="nfa-vtestimonials-lightbox__inner">' + '<button class="nfa-vtestimonials-lightbox__close" aria-label="Close">&times;</button>' + '<iframe allow="autoplay; encrypted-media" allowfullscreen></iframe>' + '</div>' + '</div>'); $('body').append($lb); $lb.find('.nfa-vtestimonials-lightbox__close').on('click', function () { $lb.removeClass('is-open'); setTimeout(function () { $lb.find('iframe').attr('src', ''); }, 350); }); $lb.on('click', function (ev) { if ($(ev.target).hasClass('nfa-vtestimonials-lightbox')) { $lb.removeClass('is-open'); setTimeout(function () { $lb.find('iframe').attr('src', ''); }, 350); } }); $(document).on('keydown', function (ev) { if (ev.key === 'Escape' && $lb.hasClass('is-open')) { $lb.removeClass('is-open'); setTimeout(function () { $lb.find('iframe').attr('src', ''); }, 350); } }); } $lb.find('iframe').attr('src', url); $lb.addClass('is-open'); }); }); }; $(window).on('elementor/frontend/init', () => { if (!window.elementorFrontend || !elementorFrontend.hooks) { return; } elementorFrontend.hooks.addAction('frontend/element_ready/nfa-testimonial-grid.default', initSlider); elementorFrontend.hooks.addAction('frontend/element_ready/nfa-logo-grid.default', initSlider); elementorFrontend.hooks.addAction('frontend/element_ready/nfa-showcase-carousel.default', initShowcaseCarousel); elementorFrontend.hooks.addAction('frontend/element_ready/nfa-numbered-cards.default', initNumberedCards); elementorFrontend.hooks.addAction('frontend/element_ready/nfa-video-testimonials.default', initVideoTestimonials); elementorFrontend.hooks.addAction('frontend/element_ready/nfa-content-tabs.default', initContentTabs); elementorFrontend.hooks.addAction('frontend/element_ready/nfa-image-comparison.default', initImageComparison); elementorFrontend.hooks.addAction('frontend/element_ready/nfa-countdown-timer.default', initCountdownTimer); elementorFrontend.hooks.addAction('frontend/element_ready/nfa-hamburger-menu.default', initHamburgerMenu); elementorFrontend.hooks.addAction('frontend/element_ready/nfa-advanced-form.default', initAdvancedForm); elementorFrontend.hooks.addAction('frontend/element_ready/global', () => { initTooltips(); initWrapperLinks(); }); }); })(jQuery);
     1!function(t){"use strict";const e=e=>{e.find(".nfa-slider").each(function(){const e=t(this),n=e.find(".nfa-slider__track").get(0);if(!n)return;const a=Math.max(1,Math.min(6,parseInt(e.data("slider-per-view"),10)||3)),i=Math.max(0,parseInt(e.data("slider-gap"),10)||20),o=Array.from(n.children),s=()=>{n.style.gap=i+"px";const t="calc((100% - "+i*(a-1)+"px) / "+a+")";o.forEach(e=>{e.style.flex="0 0 "+t})};if(s(),e.data("slider-bound"))return;let r;e.data("slider-bound",!0),t(window).on("resize.nfaSlider",()=>{clearTimeout(r),r=setTimeout(s,150)}),e.find(".nfa-slider__btn--prev").on("click",()=>{n.scrollBy({left:-n.clientWidth,behavior:"smooth"})}),e.find(".nfa-slider__btn--next").on("click",()=>{n.scrollBy({left:n.clientWidth,behavior:"smooth"})})})},n=e=>{const n=e.find(".nfa-showcase");n.length&&n.each(function(){const e=t(this),n=e.find(".nfa-showcase__track").get(0),a=e.find(".nfa-showcase__dots"),i=Array.from(n.children),o=i.length;if(!n||0===o)return;if(e.data("showcase-bound"))return;e.data("showcase-bound",!0);const s=Math.max(1,parseInt(e.data("per-view"),10)||3),r=Math.max(1,parseInt(e.data("per-view-tablet"),10)||2),l=Math.max(1,parseInt(e.data("per-view-mobile"),10)||1),d=Math.max(0,parseInt(e.data("gap"),10)||20),c="yes"===e.data("autoplay"),f=Math.max(1e3,parseInt(e.data("autoplay-speed"),10)||4e3),u="yes"===e.data("pause-on-hover");let m,h=0,p=null;function _(){const t=window.innerWidth;return t<=767?l:t<=1024?r:s}function v(){return Math.max(0,o-_())}function g(){const e=_(),o="calc((100% - "+d*(e-1)+"px) / "+e+")";if(i.forEach(function(t){t.style.flex="0 0 "+o}),i[0]){const t=i[0].getBoundingClientRect().width+d;n.style.transform="translateX(-"+h*t+"px)"}!function(){if(!a.length)return;const e=v()+1;if(a.children().length!==e){a.empty();for(var n=0;n<e;n++)a.append('<button class="nfa-showcase__dot" data-index="'+n+'" aria-label="Slide '+(n+1)+'"></button>');a.find(".nfa-showcase__dot").on("click",function(){h=parseInt(t(this).data("index"),10),h=Math.min(h,v()),g(),x()})}a.find(".nfa-showcase__dot").removeClass("nfa-showcase__dot--active"),a.find(".nfa-showcase__dot").eq(h).addClass("nfa-showcase__dot--active")}()}function b(){h=h>=v()?0:h+1,g()}function y(){c&&(w(),p=setInterval(b,f))}function w(){p&&(clearInterval(p),p=null)}function x(){c&&(w(),y())}e.find(".nfa-showcase__arrow--prev").on("click",function(){h=h<=0?v():h-1,g(),x()}),e.find(".nfa-showcase__arrow--next").on("click",function(){b(),x()}),u&&c&&(e.on("mouseenter",w),e.on("mouseleave",y)),t(window).on("resize.nfaShowcaseCarousel",function(){clearTimeout(m),m=setTimeout(function(){h=Math.min(h,v()),g()},150)}),g(),y()})},a=e=>{const n=e.find(".nfa-ncards--carousel");n.length&&n.each(function(){const e=t(this),n=e.find(".nfa-ncards__track").get(0),a=Array.from(n.children),i=a.length;if(!n||0===i)return;if(e.data("ncards-bound"))return;e.data("ncards-bound",!0);const o=Math.max(1,parseInt(e.data("per-view"),10)||3),s=Math.max(1,parseInt(e.data("per-view-tablet"),10)||2),r=Math.max(1,parseInt(e.data("per-view-mobile"),10)||1),l=Math.max(0,parseInt(e.data("gap"),10)||20),d="yes"===e.data("autoplay"),c=Math.max(1e3,parseInt(e.data("autoplay-speed"),10)||4e3),f="yes"===e.data("pause-on-hover"),u="yes"===e.data("mouse-drag"),m="yes"===e.data("infinite"),h=Math.max(100,parseInt(e.data("speed"),10)||450),p=e.find(".nfa-ncards__dots");n.style.transition="transform "+h+"ms cubic-bezier(0.25,0.46,0.45,0.94)";let _,v=0,g=null;function b(){const t=window.innerWidth;return t<=767?r:t<=1024?s:o}function y(){return Math.max(0,i-b())}function w(){if(!p.length)return;p.empty();const t=y();for(let e=0;e<=t;e++){const t=document.createElement("button");t.className="nfa-ncards__dot"+(e===v?" is-active":""),t.setAttribute("aria-label","Go to slide "+(e+1)),t.addEventListener("click",function(){v=e,k(),x(),I()}),p.get(0).appendChild(t)}}function x(){p.length&&p.find(".nfa-ncards__dot").each(function(e){t(this).toggleClass("is-active",e===v)})}function k(){const t=b(),e="calc((100% - "+l*(t-1)+"px) / "+t+")";if(a.forEach(function(t){t.style.flex="0 0 "+e}),a[0]){const t=a[0].getBoundingClientRect().width+l;n.style.transform="translateX(-"+v*t+"px)"}}function C(){v=m?v>=y()?0:v+1:Math.min(v+1,y()),k(),x()}function M(){v=m?v<=0?y():v-1:Math.max(v-1,0),k(),x()}function E(){d&&(A(),g=setInterval(C,c))}function A(){g&&(clearInterval(g),g=null)}function I(){d&&(A(),E())}if(e.find(".nfa-ncards__arrow--prev").on("click",function(){M(),I()}),e.find(".nfa-ncards__arrow--next").on("click",function(){C(),I()}),u){let L=0,T=0,F=!1,X=0;const D=40;function S(){const t=window.getComputedStyle(n);return new DOMMatrix(t.transform).m41}function z(t){F=!0,L=t.type.includes("touch")?t.touches[0].clientX:t.clientX,X=S(),n.style.transition="none",A(),e.addClass("is-dragging")}function B(t){if(!F)return;const e=t.type.includes("touch")?t.touches[0].clientX:t.clientX;T=e-L,n.style.transform="translateX("+(X+T)+"px)"}function N(){F&&(F=!1,e.removeClass("is-dragging"),n.style.transition="transform "+h+"ms cubic-bezier(0.25,0.46,0.45,0.94)",Math.abs(T)>D?T<0?C():M():k(),T=0,I())}n.addEventListener("mousedown",z),window.addEventListener("mousemove",B),window.addEventListener("mouseup",N),n.addEventListener("touchstart",z,{passive:!0}),n.addEventListener("touchmove",B,{passive:!0}),n.addEventListener("touchend",N),t(n).find("img").on("dragstart",function(t){t.preventDefault()}),t(n).on("click","a",function(t){Math.abs(T)>5&&t.preventDefault()})}f&&d&&(e.on("mouseenter",A),e.on("mouseleave",E)),t(window).on("resize.nfaNumberedCards",function(){clearTimeout(_),_=setTimeout(function(){v=Math.min(v,y()),k(),w()},150)}),k(),w(),E()})},i=e=>{const n=e.find("[data-tabs]");n.length&&n.each(function(){const e=t(this);if(e.data("tabs-bound"))return;e.data("tabs-bound",!0);const n=e.find(".nfa-tabs__btn"),a=e.find(".nfa-tabs__panel");n.on("click",function(){const i=t(this),o=i.attr("aria-controls");n.removeClass("nfa-tabs__btn--active").attr("aria-selected","false"),i.addClass("nfa-tabs__btn--active").attr("aria-selected","true"),a.removeClass("nfa-tabs__panel--active").attr("hidden",!0),e.find("#"+o).addClass("nfa-tabs__panel--active").removeAttr("hidden")})})},o=e=>{const n=e.find("[data-compare]");n.length&&n.each(function(){const e=this,n=t(e);if(n.data("compare-bound"))return;n.data("compare-bound",!0);const a="horizontal"===(n.data("orientation")||"horizontal"),i=n.find(".nfa-compare__before"),o=n.find(".nfa-compare__slider");let s=!1;function r(t){t=Math.max(0,Math.min(100,t)),a?(i.css("clip-path","inset(0 "+(100-t)+"% 0 0)"),o.css("left",t+"%")):(i.css("clip-path","inset(0 0 "+(100-t)+"% 0)"),o.css("top",t+"%"))}function l(t){const n=e.getBoundingClientRect(),i=t.touches?t.touches[0].clientX:t.clientX,o=t.touches?t.touches[0].clientY:t.clientY;return a?(i-n.left)/n.width*100:(o-n.top)/n.height*100}function d(t){s&&(t.preventDefault(),r(l(t)))}function c(){s=!1,t(document).off("mousemove.nfaCompare touchmove.nfaCompare"),t(document).off("mouseup.nfaCompare touchend.nfaCompare")}n.on("mousedown touchstart",function(e){s=!0,r(l(e)),t(document).on("mousemove.nfaCompare touchmove.nfaCompare",d),t(document).on("mouseup.nfaCompare touchend.nfaCompare",c)})})},s=e=>{const n=e.find("[data-countdown]");n.length&&n.each(function(){const e=t(this);if(e.data("countdown-bound"))return;e.data("countdown-bound",!0);const n=new Date(e.data("target")).getTime(),a=e.data("expiry")||{},i=(e.data("units")||"days,hours,minutes,seconds").split(","),o=2*Math.PI*44;function s(){const t=Date.now(),s=Math.max(0,n-t);if(s<=0)return void function(){clearInterval(r);const t=a.action||"none";"message"===t?(e.find(".nfa-countdown__block, .nfa-countdown__sep").hide(),e.find(".nfa-countdown__expiry").show()):"hide"===t?e.hide():"redirect"===t&&a.redirect&&(window.location.href=a.redirect)}();const l=Math.floor(s/1e3),d={days:Math.floor(l/86400),hours:Math.floor(l%86400/3600),minutes:Math.floor(l%3600/60),seconds:l%60};i.forEach(function(t){e.find('[data-digit="'+t+'"]').text(String(d[t]).padStart(2,"0"));const n=e.find('[data-unit="'+t+'"] .nfa-countdown__progress');if(n.length){const e=parseInt(n.data("max"),10)||60,a=o*(1-d[t]/e);n.attr("stroke-dashoffset",a)}})}s();const r=setInterval(s,1e3)})},r=()=>{document.querySelectorAll("[data-nfa-tooltip]").forEach(t=>{if(t._nfaTooltipBound)return;t._nfaTooltipBound=!0;const e=t.getAttribute("data-nfa-tooltip"),n=t.getAttribute("data-nfa-tooltip-pos")||"top",a=t.getAttribute("data-nfa-tooltip-trigger")||"hover",i="0"!==t.getAttribute("data-nfa-tooltip-arrow"),o=parseInt(t.getAttribute("data-nfa-tooltip-duration"),10)||250,s=document.createElement("div");function r(){!function(){const e=t.getBoundingClientRect(),a=s.getBoundingClientRect(),i=window.pageYOffset||document.documentElement.scrollTop,o=window.pageXOffset||document.documentElement.scrollLeft;let r,l;switch(n){case"bottom":r=e.bottom+i+8,l=e.left+o+e.width/2-a.width/2;break;case"left":r=e.top+i+e.height/2-a.height/2,l=e.left+o-a.width-8;break;case"right":r=e.top+i+e.height/2-a.height/2,l=e.right+o+8;break;default:r=e.top+i-a.height-8,l=e.left+o+e.width/2-a.width/2}s.style.top=r+"px",s.style.left=l+"px"}(),s.classList.add("nfa-tooltip--visible")}function l(){s.classList.remove("nfa-tooltip--visible")}s.className="nfa-tooltip nfa-tooltip--"+n,i||s.classList.add("nfa-tooltip--no-arrow"),s.textContent=e,s.style.transitionDuration=o+"ms",s.setAttribute("role","tooltip"),s.id="nfa-tooltip-"+Math.random().toString(36).substr(2,9),t.setAttribute("aria-describedby",s.id),t.style.position=t.style.position||"relative",document.body.appendChild(s),"click"===a?(t.addEventListener("click",t=>{t.preventDefault(),s.classList.contains("nfa-tooltip--visible")?l():r()}),document.addEventListener("click",e=>{t.contains(e.target)||s.contains(e.target)||l()})):(t.addEventListener("mouseenter",r),t.addEventListener("mouseleave",l),t.addEventListener("focusin",r),t.addEventListener("focusout",l))})},l=e=>{e.find(".nfa-hamburger").each(function(){const e=t(this);if(e.data("nfa-hm-bound"))return;e.data("nfa-hm-bound",!0);const n=e.find(".nfa-hamburger__toggle"),a=e.find(".nfa-hamburger__panel"),i=e.find(".nfa-hamburger__overlay"),o=e.find(".nfa-hamburger__close"),s=1===e.data("close-on-link")||"1"===e.data("close-on-link"),r=1===e.data("close-on-esc")||"1"===e.data("close-on-esc");function l(){e.removeClass("nfa-hamburger--open"),n.attr("aria-expanded","false"),a.attr("aria-hidden","true"),n.focus()}n.on("click",function(t){t.preventDefault(),e.hasClass("nfa-hamburger--open")?l():(e.addClass("nfa-hamburger--open"),n.attr("aria-expanded","true"),a.attr("aria-hidden","false"),a.find("a, button").first().focus())}),o.on("click",l),i.on("click",l),r&&t(document).on("keydown",function(t){"Escape"===t.key&&e.hasClass("nfa-hamburger--open")&&l()}),s&&a.on("click",".nfa-hamburger__link, .nfa-hamburger__sub-link",function(){const e=t(this).attr("href");e&&"#"!==e&&l()}),e.find(".nfa-hamburger__item--has-sub > .nfa-hamburger__link").on("click",function(e){"#"===t(this).attr("href")&&e.preventDefault(),t(this).parent().toggleClass("nfa-hamburger__item--sub-open")})})},d=e=>{e.find(".nfa-form").each(function(){const e=t(this);if(e.data("nfa-form-bound"))return;e.data("nfa-form-bound",!0);const n=e.data("nfa-form");if(!n)return;const a=e.find(".nfa-form__el"),i=e.find(".nfa-form__submit"),o=e.find(".nfa-form__submit-text"),s=e.find(".nfa-form__spinner"),r=e.find(".nfa-form__msg");function l(e){const i=t(e),o=i.closest(".nfa-form__col").find(".nfa-form__field-error");let s=!0,r="";if(e.required)if("checkbox"===e.type){const t=e.name;a.find('input[name="'+t+'"]:checked').length||(s=!1,r=n.requiredMsg||"This field is required.")}else e.value.trim()||(s=!1,r=n.requiredMsg||"This field is required.");if(s&&e.value.trim()&&("email"!==e.type||/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(e.value)||(s=!1,r="Please enter a valid email address."),"url"!==e.type||/^https?:\/\/.+/.test(e.value)||(s=!1,r="Please enter a valid URL."),"tel"!==e.type||/^[\d\s+\-().]+$/.test(e.value)||(s=!1,r="Please enter a valid phone number."),"file"===e.type)){const t=parseFloat(i.data("max-size")||5);e.files[0]&&e.files[0].size>1024*t*1024&&(s=!1,r="File exceeds "+t+"MB limit.")}return s?(i.removeClass("nfa-form__input--invalid nfa-form__select--invalid nfa-form__textarea--invalid"),o.text("")):(i.addClass("nfa-form__input--invalid nfa-form__select--invalid nfa-form__textarea--invalid"),o.text(r)),s}a.find("input, textarea, select").on("blur change",function(){l(this)}),a.on("submit",function(e){e.preventDefault();let d=!0;if(a.find("input[required], textarea[required], select[required]").each(function(){l(this)||(d=!1)}),!d)return void a.find(".nfa-form__input--invalid, .nfa-form__select--invalid, .nfa-form__textarea--invalid").first().focus();const c=[],f={};a.find("[data-label]").each(function(){const e=t(this),n=e.data("label"),i=e.attr("type")||this.tagName.toLowerCase();if("checkbox"!==i){if("radio"!==i)"file"!==i?c.push({label:n,value:e.val()||""}):c.push({label:n,value:this.files[0]?this.files[0].name:""});else if(!f[n]){f[n]=!0;const t=a.find('input[data-label="'+n+'"]:checked').val()||"";c.push({label:n,value:t})}}else if(!f[n]){f[n]=!0;const e=[];a.find('input[data-label="'+n+'"]:checked').each(function(){e.push(t(this).val())}),c.push({label:n,value:e})}}),i.prop("disabled",!0),o.css("opacity","0.5"),s.show(),r.hide(),t.ajax({url:n.ajaxUrl,type:"POST",data:{action:"nfa_form_submit",nonce:n.nonce,form_name:n.formName,action_save:n.actionSave?"1":"",action_email:n.actionEmail?"1":"",email_to:n.emailTo,email_subject:n.emailSubject,email_from_name:n.emailFromName,email_reply_to:n.emailReplyTo,page_url:window.location.href,fields:JSON.stringify(c)},success:function(t){i.prop("disabled",!1),o.css("opacity","1"),s.hide(),t.success?(r.removeClass("nfa-form__msg--error").addClass("nfa-form__msg--success").text(n.successMessage||t.data.message).show(),a[0].reset(),a.find(".nfa-form__field-error").text(""),n.actionRedirect&&n.redirectUrl&&setTimeout(function(){window.location.href=n.redirectUrl},1e3)):r.removeClass("nfa-form__msg--success").addClass("nfa-form__msg--error").text(n.errorMessage||t.data.message||"Error").show()},error:function(){i.prop("disabled",!1),o.css("opacity","1"),s.hide(),r.removeClass("nfa-form__msg--success").addClass("nfa-form__msg--error").text(n.errorMessage||"Network error. Please try again.").show()}})})})},c=e=>{function n(){t(".nfa-vtestimonials__thumb--playing iframe, .nfa-vtestimonials__thumb--playing video").each(function(){const e=this;"VIDEO"===e.tagName&&e.pause(),t(e).remove()}),t(".nfa-vtestimonials__thumb--playing").removeClass("nfa-vtestimonials__thumb--playing").find(".nfa-vtestimonials__play, .nfa-vtestimonials__duration").show(),t(".nfa-vtestimonials__reel-card.is-playing").each(function(){const e=t(this),n=e.find(".nfa-vtestimonials__reel-video").get(0);n&&(n.pause(),n.currentTime=0),e.find(".nfa-vtestimonials__reel-runtime").each(function(){"VIDEO"===this.tagName&&this.pause(),t(this).remove()}),e.removeClass("is-playing"),e.find(".nfa-vtestimonials__reel-play").show(),e.find(".nfa-vtestimonials__reel-controls").show(),e.find(".play_icon").css("display","inline"),e.find(".pause_icon").css("display","none"),e.find(".volume_up_icon").css("display","inline"),e.find(".volume_mute_icon").css("display","none")});const e=t("#nfa-vtestimonials-lightbox");e.hasClass("is-open")&&(e.removeClass("is-open"),setTimeout(function(){e.find(".nfa-vtestimonials-lightbox__media").empty()},350))}e.find(".nfa-vtestimonials--carousel").each(function(){const e=t(this),n=e.find(".nfa-vtestimonials__track").get(0),a=Array.from(n.children),i=a.length;if(!n||0===i)return;if(e.data("vtesti-bound"))return;e.data("vtesti-bound",!0);const o=Math.max(1,parseInt(e.data("per-view"),10)||3),s=Math.max(1,parseInt(e.data("per-view-tablet"),10)||2),r=Math.max(1,parseInt(e.data("per-view-mobile"),10)||1),l=Math.max(0,parseInt(e.data("gap"),10)||24),d="yes"===e.data("autoplay"),c=Math.max(1e3,parseInt(e.data("autoplay-speed"),10)||4e3),f="yes"===e.data("pause-on-hover"),u="yes"===e.data("mouse-drag"),m="yes"===e.data("infinite"),h=Math.max(100,parseInt(e.data("speed"),10)||450),p=e.find(".nfa-vtestimonials__dots");n.style.transition="transform "+h+"ms cubic-bezier(0.25,0.46,0.45,0.94)";let _=0,v=null;function g(){const t=window.innerWidth;return t<=767?r:t<=1024?s:o}function b(){return Math.max(0,i-g())}function y(){if(!p.length)return;p.empty();const t=b();for(let e=0;e<=t;e++){const t=document.createElement("button");t.className="nfa-vtestimonials__dot"+(e===_?" is-active":""),t.setAttribute("aria-label","Go to slide "+(e+1)),t.addEventListener("click",function(){_=e,x(),w(),A()}),p.get(0).appendChild(t)}}function w(){p.length&&p.find(".nfa-vtestimonials__dot").each(function(e){t(this).toggleClass("is-active",e===_)})}function x(){const t=g(),e="calc((100% - "+l*(t-1)+"px) / "+t+")";if(a.forEach(function(t){t.style.flex="0 0 "+e}),a[0]){const t=a[0].getBoundingClientRect().width+l;n.style.transform="translateX(-"+_*t+"px)"}}function k(){_=m?_>=b()?0:_+1:Math.min(_+1,b()),x(),w()}function C(){_=m?_<=0?b():_-1:Math.max(_-1,0),x(),w()}function M(){d&&(E(),v=setInterval(k,c))}function E(){v&&(clearInterval(v),v=null)}function A(){d&&(E(),M())}if(e.find(".nfa-vtestimonials__arrow--prev").on("click",function(){C(),A()}),e.find(".nfa-vtestimonials__arrow--next").on("click",function(){k(),A()}),u){let I=0,L=0,T=!1,F=0;const X=40;function D(){const t=window.getComputedStyle(n);return new DOMMatrix(t.transform).m41}function S(t){T=!0,I=t.type.includes("touch")?t.touches[0].clientX:t.clientX,F=D(),n.style.transition="none",E(),e.addClass("is-dragging")}function z(t){if(!T)return;const e=t.type.includes("touch")?t.touches[0].clientX:t.clientX;L=e-I,n.style.transform="translateX("+(F+L)+"px)"}function B(){T&&(T=!1,e.removeClass("is-dragging"),n.style.transition="transform "+h+"ms cubic-bezier(0.25,0.46,0.45,0.94)",Math.abs(L)>X?L<0?k():C():x(),L=0,A())}n.addEventListener("mousedown",S),window.addEventListener("mousemove",z),window.addEventListener("mouseup",B),n.addEventListener("touchstart",S,{passive:!0}),n.addEventListener("touchmove",z,{passive:!0}),n.addEventListener("touchend",B)}f&&(e.on("mouseenter",E),e.on("mouseleave",M)),x(),y(),M(),t(window).on("resize",function(){x(),y()})}),e.find(".nfa-vtestimonials__card[data-video-url]").each(function(){const e=t(this),a=e.data("video-url"),i=e.data("action"),o="hosted"===e.data("video-type"),s=e.hasClass("nfa-vtestimonials__reel-card");a&&(s&&(e.find(".nfa-vtestimonials__reel-ctrl--play").on("click",function(t){t.stopPropagation();const a=e.find(".nfa-vtestimonials__reel-video")[0];a&&(a.paused?(n(),e.addClass("is-playing"),e.find(".nfa-vtestimonials__reel-play").hide(),a.play(),e.find(".play_icon").css("display","none"),e.find(".pause_icon").css("display","inline")):(a.pause(),e.removeClass("is-playing"),e.find(".nfa-vtestimonials__reel-play").show(),e.find(".play_icon").css("display","inline"),e.find(".pause_icon").css("display","none")))}),e.find(".nfa-vtestimonials__reel-ctrl--volume").on("click",function(t){t.stopPropagation();const n=e.find(".nfa-vtestimonials__reel-video")[0];n&&(n.muted=!n.muted,e.find(".volume_up_icon").css("display",n.muted?"none":"inline"),e.find(".volume_mute_icon").css("display",n.muted?"inline":"none"))})),e.find(".nfa-vtestimonials__play").on("click",function(r){if(r.stopPropagation(),"new_tab"===i)return void window.open(a,"_blank","noopener");if(n(),"inline"===i){if(s){if(e.addClass("is-playing"),o){const t=e.find(".nfa-vtestimonials__reel-video").get(0);t&&(t.muted=!1,t.play()),e.find(".play_icon").css("display","none"),e.find(".pause_icon").css("display","inline")}else{const t=document.createElement("iframe");t.src=a,t.setAttribute("allow","autoplay; encrypted-media"),t.setAttribute("allowfullscreen",""),t.className="nfa-vtestimonials__reel-runtime",t.style.cssText="width:100%;height:100%;position:absolute;top:0;left:0;z-index:5;border:0;",e.append(t),e.find(".nfa-vtestimonials__reel-controls").hide()}e.find(".nfa-vtestimonials__reel-play").hide()}else{const t=e.find(".nfa-vtestimonials__thumb");if(t.hasClass("nfa-vtestimonials__thumb--playing"))return;if(t.addClass("nfa-vtestimonials__thumb--playing"),o){const e=document.createElement("video");e.src=a,e.autoplay=!0,e.controls=!0,t.append(e)}else{const e=document.createElement("iframe");e.src=a,e.setAttribute("allow","autoplay; encrypted-media"),e.setAttribute("allowfullscreen",""),t.append(e)}t.find(".nfa-vtestimonials__play, .nfa-vtestimonials__duration").hide()}return}let l=t("#nfa-vtestimonials-lightbox");if(!l.length){l=t('<div id="nfa-vtestimonials-lightbox" class="nfa-vtestimonials-lightbox"><div class="nfa-vtestimonials-lightbox__inner"><button class="nfa-vtestimonials-lightbox__close" aria-label="Close">&times;</button><div class="nfa-vtestimonials-lightbox__media"></div></div></div>'),t("body").append(l);const e=function(){l.removeClass("is-open"),setTimeout(function(){l.find(".nfa-vtestimonials-lightbox__media").empty()},350)};l.find(".nfa-vtestimonials-lightbox__close").on("click",e),l.on("click",function(n){t(n.target).hasClass("nfa-vtestimonials-lightbox")&&e()}),t(document).on("keydown",function(t){"Escape"===t.key&&l.hasClass("is-open")&&e()})}const d=l.find(".nfa-vtestimonials-lightbox__media");d.empty(),o?d.append('<video src="'+a+'" autoplay controls style="width:100%;height:100%;object-fit:contain;"></video>'):d.append('<iframe src="'+a+'" allow="autoplay; encrypted-media" allowfullscreen style="width:100%;height:100%;border:0;"></iframe>'),l.addClass("is-open")}))})};t(window).on("elementor/frontend/init",()=>{window.elementorFrontend&&elementorFrontend.hooks&&(elementorFrontend.hooks.addAction("frontend/element_ready/nfa-testimonial-grid.default",e),elementorFrontend.hooks.addAction("frontend/element_ready/nfa-logo-grid.default",e),elementorFrontend.hooks.addAction("frontend/element_ready/nfa-showcase-carousel.default",n),elementorFrontend.hooks.addAction("frontend/element_ready/nfa-numbered-cards.default",a),elementorFrontend.hooks.addAction("frontend/element_ready/nfa-video-testimonials.default",c),elementorFrontend.hooks.addAction("frontend/element_ready/nfa-content-tabs.default",i),elementorFrontend.hooks.addAction("frontend/element_ready/nfa-image-comparison.default",o),elementorFrontend.hooks.addAction("frontend/element_ready/nfa-countdown-timer.default",s),elementorFrontend.hooks.addAction("frontend/element_ready/nfa-hamburger-menu.default",l),elementorFrontend.hooks.addAction("frontend/element_ready/nfa-advanced-form.default",d),elementorFrontend.hooks.addAction("frontend/element_ready/global",()=>{r(),document.querySelectorAll("[data-nfa-wrapper-link]").forEach(t=>{if(t._nfaWrapperLinkBound)return;t._nfaWrapperLinkBound=!0;const e=t.getAttribute("data-nfa-wrapper-link"),n="1"===t.getAttribute("data-nfa-link-external"),a="1"===t.getAttribute("data-nfa-link-nofollow");e&&(t.addEventListener("click",t=>{const i=t.target.tagName.toLowerCase();if("a"!==i&&"button"!==i&&"input"!==i&&"textarea"!==i&&"select"!==i)if(n){const t=window.open(e,"_blank");t&&a&&(t.opener=null)}else window.location.href=e}),t.addEventListener("keydown",e=>{"Enter"===e.key&&t.click()}))})}))})}(jQuery);
  • nebula-forge-addons-for-elementor/trunk/includes/Widgets/Video_Testimonials_Widget.php

    r3463206 r3463463  
    5050    public function get_keywords(): array
    5151    {
    52         return ['video', 'testimonials', 'reviews', 'carousel', 'grid', 'play', 'social proof'];
     52        return ['video', 'testimonials', 'reviews', 'carousel', 'grid', 'reel', 'play', 'social proof'];
    5353    }
    5454
     
    9494                'grid'     => esc_html__('Grid', 'nebula-forge-addons-for-elementor'),
    9595                'carousel' => esc_html__('Carousel', 'nebula-forge-addons-for-elementor'),
     96                'reel'     => esc_html__('Reel', 'nebula-forge-addons-for-elementor'),
    9697            ],
    9798        ]);
     
    108109        ]);
    109110
     111        /* ── Reel Settings ────────────────────────────────────────── */
     112        $this->add_responsive_control('reel_columns', [
     113            'label'          => esc_html__('Columns', 'nebula-forge-addons-for-elementor'),
     114            'type'           => Controls_Manager::SLIDER,
     115            'size_units'     => ['col'],
     116            'range'          => ['col' => ['min' => 1, 'max' => 6]],
     117            'default'        => ['size' => 4, 'unit' => 'col'],
     118            'tablet_default' => ['size' => 2, 'unit' => 'col'],
     119            'mobile_default' => ['size' => 1, 'unit' => 'col'],
     120            'selectors'      => [
     121                '{{WRAPPER}} .nfa-vtestimonials__reel' => 'grid-template-columns: repeat({{SIZE}}, minmax(0, 1fr));',
     122            ],
     123            'condition' => ['layout' => 'reel'],
     124        ]);
     125
     126        $this->add_responsive_control('reel_gap', [
     127            'label'   => esc_html__('Gap', 'nebula-forge-addons-for-elementor'),
     128            'type'    => Controls_Manager::SLIDER,
     129            'range'   => ['px' => ['min' => 0, 'max' => 60]],
     130            'default' => ['size' => 16, 'unit' => 'px'],
     131            'selectors' => [
     132                '{{WRAPPER}} .nfa-vtestimonials__reel' => 'gap: {{SIZE}}{{UNIT}};',
     133            ],
     134            'condition' => ['layout' => 'reel'],
     135        ]);
     136
     137        $this->add_responsive_control('reel_aspect_ratio', [
     138            'label'   => esc_html__('Aspect Ratio', 'nebula-forge-addons-for-elementor'),
     139            'type'    => Controls_Manager::SELECT,
     140            'default' => '9/16',
     141            'options' => [
     142                '9/16'  => esc_html__('9:16 (Reel)', 'nebula-forge-addons-for-elementor'),
     143                '3/4'   => esc_html__('3:4 (Portrait)', 'nebula-forge-addons-for-elementor'),
     144                '4/5'   => esc_html__('4:5 (Social)', 'nebula-forge-addons-for-elementor'),
     145                '1/1'   => esc_html__('1:1 (Square)', 'nebula-forge-addons-for-elementor'),
     146            ],
     147            'selectors' => [
     148                '{{WRAPPER}} .nfa-vtestimonials__reel-card' => 'aspect-ratio: {{VALUE}};',
     149            ],
     150            'condition' => ['layout' => 'reel'],
     151        ]);
     152
     153        $this->add_control('reel_radius', [
     154            'label'   => esc_html__('Border Radius', 'nebula-forge-addons-for-elementor'),
     155            'type'    => Controls_Manager::SLIDER,
     156            'range'   => ['px' => ['min' => 0, 'max' => 40]],
     157            'default' => ['size' => 16, 'unit' => 'px'],
     158            'selectors' => [
     159                '{{WRAPPER}} .nfa-vtestimonials__reel-card' => 'border-radius: {{SIZE}}{{UNIT}};',
     160            ],
     161            'condition' => ['layout' => 'reel'],
     162        ]);
     163
     164        $this->add_control('reel_overlay_color', [
     165            'label'     => esc_html__('Overlay Color', 'nebula-forge-addons-for-elementor'),
     166            'type'      => Controls_Manager::COLOR,
     167            'default'   => 'rgba(0,0,0,0.15)',
     168            'selectors' => [
     169                '{{WRAPPER}} .nfa-vtestimonials__reel-card::after' => 'background: {{VALUE}};',
     170            ],
     171            'condition' => ['layout' => 'reel'],
     172        ]);
     173
     174        $this->add_control('reel_hover_overlay_color', [
     175            'label'     => esc_html__('Hover Overlay Color', 'nebula-forge-addons-for-elementor'),
     176            'type'      => Controls_Manager::COLOR,
     177            'default'   => 'rgba(0,0,0,0.30)',
     178            'selectors' => [
     179                '{{WRAPPER}} .nfa-vtestimonials__reel-card:hover::after' => 'background: {{VALUE}};',
     180            ],
     181            'condition' => ['layout' => 'reel'],
     182        ]);
     183
     184        $this->add_control('reel_play_size', [
     185            'label'   => esc_html__('Play Button Size', 'nebula-forge-addons-for-elementor'),
     186            'type'    => Controls_Manager::SLIDER,
     187            'range'   => ['px' => ['min' => 30, 'max' => 100]],
     188            'default' => ['size' => 56, 'unit' => 'px'],
     189            'selectors' => [
     190                '{{WRAPPER}} .nfa-vtestimonials__reel-play' => 'width: {{SIZE}}{{UNIT}}; height: {{SIZE}}{{UNIT}};',
     191            ],
     192            'condition' => ['layout' => 'reel'],
     193        ]);
     194
     195        $this->add_control('reel_play_bg', [
     196            'label'     => esc_html__('Play Button BG', 'nebula-forge-addons-for-elementor'),
     197            'type'      => Controls_Manager::COLOR,
     198            'default'   => 'rgba(0,0,0,0.45)',
     199            'selectors' => [
     200                '{{WRAPPER}} .nfa-vtestimonials__reel-play' => 'background-color: {{VALUE}};',
     201            ],
     202            'condition' => ['layout' => 'reel'],
     203        ]);
     204
     205        $this->add_control('reel_play_icon_color', [
     206            'label'     => esc_html__('Play Icon Color', 'nebula-forge-addons-for-elementor'),
     207            'type'      => Controls_Manager::COLOR,
     208            'default'   => '#ffffff',
     209            'selectors' => [
     210                '{{WRAPPER}} .nfa-vtestimonials__reel-play svg' => 'fill: {{VALUE}}; color: {{VALUE}};',
     211                '{{WRAPPER}} .nfa-vtestimonials__reel-ctrl svg' => 'fill: {{VALUE}}; color: {{VALUE}};',
     212            ],
     213            'condition' => ['layout' => 'reel'],
     214        ]);
     215
     216        $this->add_control('reel_play_icon_stroke_color', [
     217            'label'     => esc_html__('Play Icon Stroke', 'nebula-forge-addons-for-elementor'),
     218            'type'      => Controls_Manager::COLOR,
     219            'default'   => '#ffffff',
     220            'selectors' => [
     221                '{{WRAPPER}} .nfa-vtestimonials__reel-play svg' => 'stroke: {{VALUE}};',
     222                '{{WRAPPER}} .nfa-vtestimonials__reel-ctrl svg' => 'stroke: {{VALUE}};',
     223            ],
     224            'condition' => ['layout' => 'reel'],
     225        ]);
     226
    110227        $this->end_controls_section();
    111228    }
     
    121238        $repeater = new Repeater();
    122239
    123         $repeater->add_control('video_url', [
    124             'label'       => esc_html__('Video URL', 'nebula-forge-addons-for-elementor'),
     240        $repeater->add_control('video_source', [
     241            'label'   => esc_html__('Video Source', 'nebula-forge-addons-for-elementor'),
     242            'type'    => Controls_Manager::SELECT,
     243            'default' => 'youtube',
     244            'options' => [
     245                'youtube'     => esc_html__('YouTube', 'nebula-forge-addons-for-elementor'),
     246                'vimeo'       => esc_html__('Vimeo', 'nebula-forge-addons-for-elementor'),
     247                'self_hosted' => esc_html__('Self Hosted (MP4)', 'nebula-forge-addons-for-elementor'),
     248            ],
     249        ]);
     250
     251        $repeater->add_control('video_youtube_url', [
     252            'label'       => esc_html__('YouTube URL', 'nebula-forge-addons-for-elementor'),
    125253            'type'        => Controls_Manager::URL,
    126254            'placeholder' => 'https://www.youtube.com/watch?v=...',
    127255            'label_block' => true,
    128256            'default'     => ['url' => ''],
     257            'condition'   => ['video_source' => 'youtube'],
     258        ]);
     259
     260        $repeater->add_control('video_vimeo_url', [
     261            'label'       => esc_html__('Vimeo URL', 'nebula-forge-addons-for-elementor'),
     262            'type'        => Controls_Manager::URL,
     263            'placeholder' => 'https://vimeo.com/123456789',
     264            'label_block' => true,
     265            'default'     => ['url' => ''],
     266            'condition'   => ['video_source' => 'vimeo'],
     267        ]);
     268
     269        $repeater->add_control('video_hosted', [
     270            'label'      => esc_html__('Upload Video', 'nebula-forge-addons-for-elementor'),
     271            'type'       => Controls_Manager::MEDIA,
     272            'media_types' => ['video'],
     273            'default'    => ['url' => ''],
     274            'condition'  => ['video_source' => 'self_hosted'],
     275        ]);
     276
     277        $repeater->add_control('video_external_url', [
     278            'label'       => esc_html__('External Video URL', 'nebula-forge-addons-for-elementor'),
     279            'type'        => Controls_Manager::URL,
     280            'placeholder' => 'https://example.com/video.mp4',
     281            'label_block' => true,
     282            'default'     => ['url' => ''],
     283            'description' => esc_html__('Or paste a direct link to an MP4 file.', 'nebula-forge-addons-for-elementor'),
     284            'condition'   => ['video_source' => 'self_hosted'],
    129285        ]);
    130286
     
    135291                'url' => Utils::get_placeholder_image_src(),
    136292            ],
     293            'condition' => ['layout!' => 'reel'],
    137294        ]);
    138295
     
    142299            'default'     => esc_html__('John Doe', 'nebula-forge-addons-for-elementor'),
    143300            'label_block' => true,
     301            'condition'   => ['layout!' => 'reel'],
    144302        ]);
    145303
     
    149307            'default'     => esc_html__('CEO, Acme Corp', 'nebula-forge-addons-for-elementor'),
    150308            'label_block' => true,
     309            'condition'   => ['layout!' => 'reel'],
    151310        ]);
    152311
     
    156315            'default' => esc_html__('This product completely transformed our workflow. Highly recommended!', 'nebula-forge-addons-for-elementor'),
    157316            'rows'    => 3,
     317            'condition' => ['layout!' => 'reel'],
    158318        ]);
    159319
     
    161321            'label' => esc_html__('Avatar', 'nebula-forge-addons-for-elementor'),
    162322            'type'  => Controls_Manager::MEDIA,
     323            'condition' => ['layout!' => 'reel'],
    163324        ]);
    164325
     
    170331            'step'    => 1,
    171332            'default' => 5,
     333            'condition' => ['layout!' => 'reel'],
    172334        ]);
    173335
     
    177339            'default'     => '2:30',
    178340            'description' => esc_html__('Optional. Shown on thumbnail corner.', 'nebula-forge-addons-for-elementor'),
     341            'condition'   => ['layout!' => 'reel'],
    179342        ]);
    180343
     
    218381            'label'     => esc_html__('Carousel Settings', 'nebula-forge-addons-for-elementor'),
    219382            'tab'       => Controls_Manager::TAB_CONTENT,
    220             'condition' => ['layout' => 'carousel'],
     383            'condition' => ['layout' => ['carousel', 'reel']],
    221384        ]);
    222385
     
    368531        ]);
    369532
     533        $this->add_control('heading_card_style_notice', [
     534            'type'            => Controls_Manager::RAW_HTML,
     535            'raw'             => esc_html__('Card style options are not applicable in Reel layout.', 'nebula-forge-addons-for-elementor'),
     536            'content_classes' => 'elementor-panel-alert elementor-panel-alert-info',
     537            'condition'       => ['layout' => 'reel'],
     538        ]);
     539
    370540        $this->add_group_control(Group_Control_Background::get_type(), [
    371541            'name'     => 'card_background',
     
    417587    {
    418588        $this->start_controls_section('section_style_thumbnail', [
    419             'label' => esc_html__('Thumbnail', 'nebula-forge-addons-for-elementor'),
    420             'tab'   => Controls_Manager::TAB_STYLE,
     589            'label'     => esc_html__('Thumbnail', 'nebula-forge-addons-for-elementor'),
     590            'tab'       => Controls_Manager::TAB_STYLE,
     591            'condition' => ['layout!' => 'reel'],
    421592        ]);
    422593
     
    484655    {
    485656        $this->start_controls_section('section_style_play', [
    486             'label' => esc_html__('Play Button', 'nebula-forge-addons-for-elementor'),
    487             'tab'   => Controls_Manager::TAB_STYLE,
     657            'label'     => esc_html__('Play Button', 'nebula-forge-addons-for-elementor'),
     658            'tab'       => Controls_Manager::TAB_STYLE,
     659            'condition' => ['layout!' => 'reel'],
    488660        ]);
    489661
     
    547719    {
    548720        $this->start_controls_section('section_style_content', [
    549             'label' => esc_html__('Content', 'nebula-forge-addons-for-elementor'),
    550             'tab'   => Controls_Manager::TAB_STYLE,
     721            'label'     => esc_html__('Content', 'nebula-forge-addons-for-elementor'),
     722            'tab'       => Controls_Manager::TAB_STYLE,
     723            'condition' => ['layout!' => 'reel'],
    551724        ]);
    552725
     
    692865    {
    693866        $this->start_controls_section('section_style_hover', [
    694             'label' => esc_html__('Hover Effects', 'nebula-forge-addons-for-elementor'),
    695             'tab'   => Controls_Manager::TAB_STYLE,
     867            'label'     => esc_html__('Hover Effects', 'nebula-forge-addons-for-elementor'),
     868            'tab'       => Controls_Manager::TAB_STYLE,
     869            'condition' => ['layout!' => 'reel'],
    696870        ]);
    697871
     
    764938            'label'     => esc_html__('Navigation', 'nebula-forge-addons-for-elementor'),
    765939            'tab'       => Controls_Manager::TAB_STYLE,
    766             'condition' => ['layout' => 'carousel'],
     940            'condition' => ['layout' => ['carousel', 'reel']],
    767941        ]);
    768942
     
    8681042
    8691043    /**
     1044     * Resolve the video URL from the repeater item based on selected source.
     1045     */
     1046    private function resolve_video_url(array $item): string
     1047    {
     1048        $source = $item['video_source'] ?? 'youtube';
     1049
     1050        switch ($source) {
     1051            case 'youtube':
     1052                $url = $item['video_youtube_url']['url'] ?? '';
     1053                break;
     1054            case 'vimeo':
     1055                $url = $item['video_vimeo_url']['url'] ?? '';
     1056                break;
     1057            case 'self_hosted':
     1058                $hosted   = $item['video_hosted']['url'] ?? '';
     1059                $external = $item['video_external_url']['url'] ?? '';
     1060                $url      = !empty($hosted) ? $hosted : $external;
     1061                break;
     1062            default:
     1063                $url = '';
     1064                break;
     1065        }
     1066
     1067        // Backward compatibility: fall back to legacy video_url field.
     1068        if (empty($url) && !empty($item['video_url']['url'])) {
     1069            $url = $item['video_url']['url'];
     1070        }
     1071
     1072        return $url;
     1073    }
     1074
     1075    /**
    8701076     * Extract a video embed URL from a given link.
    8711077     */
    872     private function get_embed_url(string $url): string
    873     {
     1078    private function get_embed_url(string $url, string $source = ''): string
     1079    {
     1080        // Self-hosted MP4 – return as-is (played via <video> or direct)
     1081        if ($source === 'self_hosted') {
     1082            return $url;
     1083        }
     1084
    8741085        // YouTube
    8751086        if (preg_match('/(?:youtube\.com\/watch\?v=|youtu\.be\/|youtube\.com\/embed\/)([a-zA-Z0-9_-]{11})/', $url, $m)) {
     
    8851096
    8861097    /**
     1098     * Check if URL points to a self-hosted video file.
     1099     */
     1100    private function is_self_hosted(string $source): bool
     1101    {
     1102        return $source === 'self_hosted';
     1103    }
     1104
     1105    /**
     1106     * Resolve thumbnail URL.
     1107     * Priority: custom thumbnail > auto thumbnail from video source > Elementor placeholder.
     1108     */
     1109    private function resolve_thumbnail_url(array $item, bool $allow_placeholder = true): string
     1110    {
     1111        $thumb_url = $item['thumbnail']['url'] ?? '';
     1112
     1113        // Treat Elementor default placeholder as empty.
     1114        if (!empty($thumb_url) && strpos($thumb_url, 'elementor/assets/images/placeholder.png') !== false) {
     1115            $thumb_url = '';
     1116        }
     1117
     1118        if (!empty($thumb_url)) {
     1119            return $thumb_url;
     1120        }
     1121
     1122        $video_url = $this->resolve_video_url($item);
     1123        $source    = $item['video_source'] ?? 'youtube';
     1124
     1125        if (!empty($video_url)) {
     1126            $youtube_id = '';
     1127            if (preg_match('/(?:youtube\.com\/watch\?v=|youtu\.be\/|youtube\.com\/embed\/)([a-zA-Z0-9_-]{11})/', $video_url, $m)) {
     1128                $youtube_id = $m[1];
     1129            }
     1130
     1131            if (!empty($youtube_id)) {
     1132                return 'https://img.youtube.com/vi/' . $youtube_id . '/hqdefault.jpg';
     1133            }
     1134
     1135            $vimeo_id = '';
     1136            if (preg_match('/vimeo\.com\/(?:video\/)?(\d+)/', $video_url, $m)) {
     1137                $vimeo_id = $m[1];
     1138            }
     1139
     1140            if (!empty($vimeo_id)) {
     1141                return 'https://vumbnail.com/' . $vimeo_id . '.jpg';
     1142            }
     1143        }
     1144
     1145        return $allow_placeholder ? Utils::get_placeholder_image_src() : '';
     1146    }
     1147
     1148    /**
    8871149     * Render a single testimonial card.
    8881150     */
    8891151    private function render_card(array $item, string $video_action): void
    8901152    {
    891         $video_url   = $item['video_url']['url'] ?? '';
     1153        $video_url   = $this->resolve_video_url($item);
     1154        $video_src   = $item['video_source'] ?? 'youtube';
    8921155        $has_video   = !empty($video_url);
    893         $thumb_url   = $item['thumbnail']['url'] ?? '';
     1156        $thumb_url   = $this->resolve_thumbnail_url($item);
    8941157        $name        = $item['name'] ?? '';
    8951158        $role        = $item['role'] ?? '';
     
    8981161        $avatar_url  = $item['avatar']['url'] ?? '';
    8991162        $rating      = isset($item['rating']) ? max(0, min(5, (int) $item['rating'])) : 0;
     1163        $is_hosted   = $this->is_self_hosted($video_src);
    9001164
    9011165        $card_attrs = '';
    9021166        if ($has_video) {
     1167            $embed_url = $this->get_embed_url($video_url, $video_src);
    9031168            if ($video_action === 'lightbox') {
    904                 $card_attrs = ' data-video-url="' . esc_attr($this->get_embed_url($video_url)) . '" data-action="lightbox"';
     1169                $card_attrs = ' data-video-url="' . esc_attr($embed_url) . '" data-action="lightbox"';
    9051170            } elseif ($video_action === 'inline') {
    906                 $card_attrs = ' data-video-url="' . esc_attr($this->get_embed_url($video_url)) . '" data-action="inline"';
     1171                $card_attrs = ' data-video-url="' . esc_attr($embed_url) . '" data-action="inline"';
    9071172            } elseif ($video_action === 'new_tab') {
    9081173                $card_attrs = ' data-video-url="' . esc_attr(esc_url($video_url)) . '" data-action="new_tab"';
     1174            }
     1175            if ($is_hosted) {
     1176                $card_attrs .= ' data-video-type="hosted"';
    9091177            }
    9101178        }
    9111179        ?>
    9121180        <div class="nfa-vtestimonials__card"<?php echo $card_attrs; ?>>
    913             <?php if (!empty($thumb_url)) : ?>
    914                 <div class="nfa-vtestimonials__thumb">
    915                     <img src="<?php echo esc_url($thumb_url); ?>" alt="<?php echo esc_attr($name); ?>" loading="lazy">
    916                     <?php if ($has_video) : ?>
    917                         <button class="nfa-vtestimonials__play" type="button" aria-label="<?php echo esc_attr(
    918                             /* translators: %s: person name */
    919                             sprintf(__('Play video testimonial from %s', 'nebula-forge-addons-for-elementor'), $name)
    920                         ); ?>">
    921                             <svg width="20" height="20" viewBox="0 0 24 24" fill="currentColor"><path d="M8 5v14l11-7z"/></svg>
    922                         </button>
    923                     <?php endif; ?>
    924                     <?php if (!empty($duration)) : ?>
    925                         <span class="nfa-vtestimonials__duration"><?php echo esc_html($duration); ?></span>
    926                     <?php endif; ?>
    927                 </div>
    928             <?php endif; ?>
     1181            <div class="nfa-vtestimonials__thumb">
     1182                <img src="<?php echo esc_url($thumb_url); ?>" alt="<?php echo esc_attr($name); ?>" loading="lazy">
     1183                <?php if ($has_video) : ?>
     1184                    <button class="nfa-vtestimonials__play" type="button" aria-label="<?php echo esc_attr(
     1185                        /* translators: %s: person name */
     1186                        sprintf(__('Play video testimonial from %s', 'nebula-forge-addons-for-elementor'), $name)
     1187                    ); ?>">
     1188                        <svg width="20" height="20" viewBox="0 0 24 24" fill="currentColor"><path d="M8 5v14l11-7z"/></svg>
     1189                    </button>
     1190                <?php endif; ?>
     1191                <?php if (!empty($duration)) : ?>
     1192                    <span class="nfa-vtestimonials__duration"><?php echo esc_html($duration); ?></span>
     1193                <?php endif; ?>
     1194            </div>
    9291195
    9301196            <div class="nfa-vtestimonials__content">
     
    9771243        if ($layout === 'carousel') {
    9781244            $this->render_carousel($settings, $testimonials, $video_action);
     1245        } elseif ($layout === 'reel') {
     1246            $this->render_reel($settings, $testimonials, $video_action);
    9791247        } else {
    9801248            $this->render_grid($settings, $testimonials, $video_action);
     
    9931261                    <?php $this->render_card($item, $video_action); ?>
    9941262                <?php endforeach; ?>
     1263            </div>
     1264        </div>
     1265        <?php
     1266    }
     1267
     1268    /* ── Reel Render ──────────────────────────────────────────────────── */
     1269    private function render_reel(array $settings, array $testimonials, string $video_action): void
     1270    {
     1271        $per_view         = intval($settings['slides_per_view'] ?? ($settings['reel_columns']['size'] ?? 4));
     1272        $per_view_tablet  = intval($settings['slides_per_view_tablet'] ?? ($settings['reel_columns_tablet']['size'] ?? min($per_view, 2)));
     1273        $per_view_mobile  = intval($settings['slides_per_view_mobile'] ?? ($settings['reel_columns_mobile']['size'] ?? 1));
     1274        $gap              = intval($settings['slide_gap']['size'] ?? ($settings['reel_gap']['size'] ?? 16));
     1275        $show_arrows      = !empty($settings['show_arrows']) && $settings['show_arrows'] === 'yes';
     1276        $nav_position     = $settings['nav_position'] ?? 'bottom-center';
     1277        $show_dots        = !empty($settings['show_dots']) && $settings['show_dots'] === 'yes';
     1278        $mouse_drag       = (!empty($settings['mouse_drag']) && $settings['mouse_drag'] === 'yes') ? 'yes' : 'no';
     1279        $infinite_loop    = (!empty($settings['infinite_loop']) && $settings['infinite_loop'] === 'yes') ? 'yes' : 'no';
     1280        $transition_speed = intval($settings['transition_speed'] ?? 450);
     1281        $autoplay         = $settings['autoplay'] ?? 'no';
     1282        $autoplay_speed   = $settings['autoplay_speed'] ?? 4000;
     1283        $pause_on_hover   = $settings['pause_on_hover'] ?? 'yes';
     1284
     1285        $wrapper_class = 'nfa-vtestimonials nfa-vtestimonials--carousel nfa-vtestimonials--reel-carousel';
     1286        if ($show_arrows) {
     1287            $wrapper_class .= ' nfa-vtestimonials--nav-' . $nav_position;
     1288        }
     1289        ?>
     1290        <div class="<?php echo esc_attr($wrapper_class); ?>"
     1291             data-per-view="<?php echo esc_attr($per_view); ?>"
     1292             data-per-view-tablet="<?php echo esc_attr($per_view_tablet); ?>"
     1293             data-per-view-mobile="<?php echo esc_attr($per_view_mobile); ?>"
     1294             data-gap="<?php echo esc_attr($gap); ?>"
     1295             data-mouse-drag="<?php echo esc_attr($mouse_drag); ?>"
     1296             data-infinite="<?php echo esc_attr($infinite_loop); ?>"
     1297             data-speed="<?php echo esc_attr($transition_speed); ?>"
     1298             data-autoplay="<?php echo esc_attr($autoplay); ?>"
     1299             data-autoplay-speed="<?php echo esc_attr($autoplay_speed); ?>"
     1300             data-pause-on-hover="<?php echo esc_attr($pause_on_hover); ?>">
     1301
     1302            <?php if ($show_arrows && $nav_position === 'sides') : ?>
     1303            <button class="nfa-vtestimonials__arrow nfa-vtestimonials__arrow--prev nfa-vtestimonials__arrow--side" aria-label="<?php esc_attr_e('Previous', 'nebula-forge-addons-for-elementor'); ?>">
     1304                <svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M10 12L6 8L10 4" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>
     1305            </button>
     1306            <?php endif; ?>
     1307
     1308            <div class="nfa-vtestimonials__viewport">
     1309                <div class="nfa-vtestimonials__track" style="gap:<?php echo esc_attr($gap); ?>px;">
     1310                    <?php foreach ($testimonials as $item) : ?>
     1311                        <?php $this->render_reel_card($item, $video_action); ?>
     1312                    <?php endforeach; ?>
     1313                </div>
     1314            </div>
     1315
     1316            <?php if ($show_arrows && $nav_position === 'sides') : ?>
     1317            <button class="nfa-vtestimonials__arrow nfa-vtestimonials__arrow--next nfa-vtestimonials__arrow--side" aria-label="<?php esc_attr_e('Next', 'nebula-forge-addons-for-elementor'); ?>">
     1318                <svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M6 4L10 8L6 12" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>
     1319            </button>
     1320            <?php endif; ?>
     1321
     1322            <?php if ($show_arrows && $nav_position !== 'sides') : ?>
     1323            <div class="nfa-vtestimonials__nav">
     1324                <button class="nfa-vtestimonials__arrow nfa-vtestimonials__arrow--prev" aria-label="<?php esc_attr_e('Previous', 'nebula-forge-addons-for-elementor'); ?>">
     1325                    <svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M10 12L6 8L10 4" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>
     1326                </button>
     1327                <button class="nfa-vtestimonials__arrow nfa-vtestimonials__arrow--next" aria-label="<?php esc_attr_e('Next', 'nebula-forge-addons-for-elementor'); ?>">
     1328                    <svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M6 4L10 8L6 12" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>
     1329                </button>
     1330            </div>
     1331            <?php endif; ?>
     1332
     1333            <?php if ($show_dots) : ?>
     1334            <div class="nfa-vtestimonials__dots"></div>
     1335            <?php endif; ?>
     1336        </div>
     1337        <?php
     1338    }
     1339
     1340    /**
     1341     * Render a single reel card (video-only, portrait thumbnail).
     1342     */
     1343    private function render_reel_card(array $item, string $video_action): void
     1344    {
     1345        $video_url  = $this->resolve_video_url($item);
     1346        $video_src  = $item['video_source'] ?? 'youtube';
     1347        $has_video  = !empty($video_url);
     1348        $thumb_url  = $this->resolve_thumbnail_url($item, false);
     1349        $name       = $item['name'] ?? '';
     1350        $is_hosted  = $this->is_self_hosted($video_src);
     1351        $card_style = '';
     1352        if (!$is_hosted && !empty($thumb_url)) {
     1353            $card_style = ' style="background-image:url(' . esc_url($thumb_url) . ');background-size:cover;background-position:center;"';
     1354        }
     1355
     1356        $card_attrs = '';
     1357        if ($has_video) {
     1358            $embed_url = $this->get_embed_url($video_url, $video_src);
     1359            if ($video_action === 'lightbox') {
     1360                $card_attrs = ' data-video-url="' . esc_attr($embed_url) . '" data-action="lightbox"';
     1361            } elseif ($video_action === 'inline') {
     1362                $card_attrs = ' data-video-url="' . esc_attr($embed_url) . '" data-action="inline"';
     1363            } elseif ($video_action === 'new_tab') {
     1364                $card_attrs = ' data-video-url="' . esc_attr(esc_url($video_url)) . '" data-action="new_tab"';
     1365            }
     1366            if ($is_hosted) {
     1367                $card_attrs .= ' data-video-type="hosted"';
     1368            }
     1369        }
     1370        ?>
     1371        <div class="nfa-vtestimonials__reel-card nfa-vtestimonials__card"<?php echo $card_attrs . $card_style; ?>>
     1372            <?php if ($is_hosted && $has_video) : ?>
     1373                <video class="nfa-vtestimonials__reel-video" loop playsinline preload="metadata" poster="<?php echo esc_url($thumb_url); ?>" aria-label="<?php echo esc_attr(
     1374                    sprintf(__('Client testimonial: %s', 'nebula-forge-addons-for-elementor'), $name)
     1375                ); ?>">
     1376                    <source src="<?php echo esc_url($video_url); ?>" type="video/mp4">
     1377                    <?php esc_html_e('Your browser does not support the video tag.', 'nebula-forge-addons-for-elementor'); ?>
     1378                </video>
     1379            <?php endif; ?>
     1380
     1381            <?php if ($has_video) : ?>
     1382                <button class="nfa-vtestimonials__reel-play nfa-vtestimonials__play" type="button" aria-label="<?php echo esc_attr(
     1383                    sprintf(__('Play video testimonial from %s', 'nebula-forge-addons-for-elementor'), $name)
     1384                ); ?>">
     1385                    <svg class="play_icon" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polygon points="6 3 20 12 6 21 6 3"></polygon></svg>
     1386                </button>
     1387            <?php endif; ?>
     1388
     1389            <div class="nfa-vtestimonials__reel-controls">
     1390                <?php if ($has_video) : ?>
     1391                    <span class="nfa-vtestimonials__reel-ctrl nfa-vtestimonials__reel-ctrl--play" aria-hidden="true">
     1392                        <svg class="play_icon" xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="display:inline;"><polygon points="6 3 20 12 6 21 6 3"></polygon></svg>
     1393                        <svg class="pause_icon" xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="display:none;"><rect x="6" y="4" width="4" height="16"></rect><rect x="14" y="4" width="4" height="16"></rect></svg>
     1394                    </span>
     1395                    <span class="nfa-vtestimonials__reel-ctrl nfa-vtestimonials__reel-ctrl--volume" aria-hidden="true">
     1396                        <svg class="volume_up_icon" xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="display:inline;"><polygon points="11 5 6 9 2 9 2 15 6 15 11 19 11 5"></polygon><path d="M15 9a5 5 0 0 1 0 6"></path><path d="M19 5a9 9 0 0 1 0 14"></path></svg>
     1397                        <svg class="volume_mute_icon" xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="display:none;"><polygon points="11 5 6 9 2 9 2 15 6 15 11 19 11 5"></polygon><line x1="22" x2="16" y1="9" y2="15"></line><line x1="16" x2="22" y1="9" y2="15"></line></svg>
     1398                    </span>
     1399                <?php endif; ?>
    9951400            </div>
    9961401        </div>
Note: See TracChangeset for help on using the changeset viewer.