/* ==========================================================================
   Radtak — image slot support
   Load AFTER radtak.css on every page.

   Follows the scrim pattern already established for the hero video:
   dark art + light scrim + the template's dark type. No text inversion.
   ========================================================================== */

/* --- Final CTA: readability scrim ----------------------------------------
   contact-image-bg.jpg appears on all 11 pages behind the heading, body
   copy and contact blocks, which use .text-gradient-3 (#61666A -> #292C2E).
   The art is dark, so without a scrim the heading is ~1.1:1 and unreadable.
   Weighted to the left, where the type sits; the right side is covered by
   the opaque form card anyway. */

.section-contact .contact-image {
    overflow: hidden;
}

.section-contact .contact-image::after {
    content: "";
    position: absolute;
    inset: 0;
    /* Inherit so the scrim always tracks the image's own radius. styles.css
       drops that 40px -> 24px under 767px; a hard-coded 40px here left the
       scrim's squarer corners overhanging the image, and the dark art beneath
       showed through as four dark notches. */
    border-radius: inherit;
    background: linear-gradient(90deg, rgba(247, 250, 248, 0.93) 0%, rgba(247, 250, 248, 0.86) 45%, rgba(247, 250, 248, 0.72) 100%);
}

/* On mobile the CTA stacks: heading and form both sit over the image, so
   the scrim goes vertical and slightly stronger. */

@media (max-width: 991.98px) {
    .section-contact .contact-image::after {
        background: linear-gradient(180deg, rgba(247, 250, 248, 0.93) 0%, rgba(247, 250, 248, 0.88) 50%, rgba(247, 250, 248, 0.93) 100%);
    }

    .section-contact .contact-image img {
        object-position: center 35%;
    }
}

/* --- Inner-page hero (.v2): mobile crop ----------------------------------
   radtak.css points .section-hero.v2 .hero-image at hero-1.jpg (landscape).
   Below 992px that slot turns portrait, so use the 1080x1920 crop.
   The existing .v2 scrim is untouched. */

@media (max-width: 991.98px) {
    .section-hero.v2 .hero-image {
        background-image: url(../images/section/hero-1-mobile.jpg);
        background-position: center center;
    }
}

/* iOS Safari mis-scales background-attachment: fixed while scrolling. */
@media (hover: none) and (pointer: coarse) {
    .section-hero .hero-image,
    .section-hero.v2 .hero-image {
        background-attachment: scroll;
    }
}


/* ==========================================================================
   INTERACTION & MOTION
   Loads after styles.css + radtak.css. Nothing above this line is touched.

   The template ships `transition: all 0.3s ease` on `a`, `button` and
   `svg path`, and nothing else. That single rule is responsible for most of
   what feels off: every hover on the site runs at the same 300ms on every
   animatable property, several of which are layout properties.
   ========================================================================== */

:root {
    /* Stronger than the built-in keywords, which are too soft to read as
       intentional. From easing.dev. */
    --ease-out-quint: cubic-bezier(0.23, 1, 0.32, 1);
    --ease-in-out-strong: cubic-bezier(0.77, 0, 0.175, 1);

    /* Focus ring ink. Dark by default because the effective --brand
       (#F0763A, set in radtak.css) only hits 2.86:1 on the light page
       background — under the 3:1 WCAG 2.2 focus-appearance floor. */
    --focus-ring: #09090B;
}

/* Dark surfaces flip the ring, not the rule. */
.box-black,
.section-statistic,
.offcanvas-menu {
    --focus-ring: #FFFFFF;
}


/* --- 1. Focus-visible ----------------------------------------------------
   styles.css clears the outline in six places (`a:focus`, form inputs,
   select, .tf-check, .nice-select) and never puts anything back, so a
   keyboard user currently has no visible position on any page.

   :is() is load-bearing here: it takes the specificity of its heaviest
   argument, which lifts these past `form input[type=text] { outline: 0 }`
   (0,1,2) without needing !important. */

:is(a, button, summary, [role="button"], [tabindex]):focus-visible,
:is(input, textarea, select, .tf-check, .nice-select):focus-visible {
    outline: 2px solid var(--focus-ring);
    outline-offset: 3px;
}

/* Inputs sit flush inside their card, so the ring goes inside the border. */
:is(input, textarea, select):focus-visible {
    outline-offset: 0;
}

/* Never show the ring for mouse users — that is the whole point of
   :focus-visible, but the template's `outline: 0` rules also killed the
   default, so be explicit. */
:is(a, button, [role="button"]):focus:not(:focus-visible) {
    outline: none;
}


/* --- 2. Press states -----------------------------------------------------
   `:active` appears exactly once in 9,800 lines of styles.css, on a
   third-party select plugin. Every button on the site is built to look
   physical — `0 -3px 0 #080808 inset` is a 3px extruded lip — and then
   never moves when you push it.

   On press the lip compresses to 1px, the ambient shadow layers pull in
   (the button is closer to the page), and the whole thing drops 1px.
   Layer counts are kept identical between states so box-shadow actually
   interpolates instead of hard-swapping. */

.tf-btn,
.tf-btn-2 {
    transition:
        transform 140ms var(--ease-out-quint),
        box-shadow 140ms var(--ease-out-quint),
        color 150ms ease;
}

.tf-btn:active,
.tf-btn-2:active {
    transform: translateY(1px) scale(0.985);
    transition-duration: 100ms;
}

.tf-btn:active {
    box-shadow:
        0px -1px 0px 0px #080808 inset,
        0px 1px 0px 0px rgba(255, 255, 255, 0.3019607843) inset,
        0px 1.5px 1.2px 0px rgba(0, 0, 0, 0.1215686275),
        0px 3.6px 2.9px 0px rgba(0, 0, 0, 0.1294117647),
        0px 6.8px 5.4px 0px rgba(0, 0, 0, 0.1333333333),
        0px 12px 9.6px 0px rgba(0, 0, 0, 0.1411764706),
        0px 22px 17.6px 0px rgba(0, 0, 0, 0.1294117647),
        0px 52px 42px 0px rgba(0, 0, 0, 0.1176470588),
        0px 1.5px 2px 0px rgba(0, 0, 0, 0.1411764706),
        0px 1.5px 1.2px 0px rgba(0, 0, 0, 0.1215686275);
}

.tf-btn-2:active {
    box-shadow:
        0px -1px 0px 0px #E9E9E9 inset,
        0px 1px 0px 0px rgba(255, 255, 255, 0.6980392157) inset,
        0px 1.4px 1.1px 0px rgba(0, 0, 0, 0.1215686275),
        0px 1.5px 1.5px 0px rgba(0, 0, 0, 0.1411764706);
}

/* The hover gradient swap can't interpolate (CSS doesn't tween gradient
   images), so it lands as a hard cut. A 1px lift gives it motion to hide
   behind and makes the swap read as intentional. */
@media (hover: hover) and (pointer: fine) {
    .tf-btn:hover,
    .tf-btn-2:hover {
        transform: translateY(-1px);
    }

    .tf-btn:hover:active,
    .tf-btn-2:hover:active {
        transform: translateY(1px) scale(0.985);
    }
}

/* .social-item is a <div> inside the <a>, so it never picked up the global
   `a` transition — its hover was a 0ms hard cut. */
.social-item {
    transition:
        transform 140ms var(--ease-out-quint),
        background-color 180ms ease,
        color 180ms ease;
}

.tf-social-1 a:active .social-item,
.social-item:active {
    transform: translateY(1px) scale(0.96);
    transition-duration: 100ms;
}

/* The accordion header needs no press transform: the dark panel starts
   travelling at 0ms on click, which is the feedback. Scaling a 48px
   headline would only soften the type mid-press. */


/* --- 3. Link hovers ------------------------------------------------------
   300ms is a modal duration. On a text-colour change it just reads as lag,
   and these are the highest-frequency interactions on the site. */

footer .footer-col-links a,
.radtak-link-more,
.tf-header .nav-menu-main a,
.sub-menu a,
.link1,
.tags-item {
    transition: color 150ms ease;
}


/* --- 4. Featured works: the diagonal sweep -------------------------------
   Three separate problems with the shipped version:

   a) The transition is declared inside `:hover`, so the exit has no
      transition at all. Leave the card mid-sweep and a 250%-tall white bar
      snaps out of existence.
   b) It animates `height`, which is layout + paint + composite on every
      frame, across a full-bleed pseudo-element.
   c) `linear` on a decorative reveal — it arrives and stops dead.

   Fixed by holding the bar at full height and driving it with scaleY, which
   is composite-only, and by moving the transition onto the base rule so it
   is symmetric and interruptible. The delayed 0ms opacity on exit lets the
   bar finish shrinking to nothing before its alpha resets, which is what
   stops the white flash on mouse-out. */

.featured-works-item .image:after {
    height: 250%;
    background-color: rgba(255, 255, 255, 0.28);
    transform: translate(-50%, -50%) rotate(-45deg) scaleY(0);
    opacity: 1;
    transition:
        transform 220ms var(--ease-out-quint),
        opacity 0ms linear 220ms;
}

.featured-works-item:hover .image:after {
    height: 250%;
    background-color: rgba(255, 255, 255, 0.28);
    transform: translate(-50%, -50%) rotate(-45deg) scaleY(1);
    opacity: 0;
    transition:
        transform 520ms var(--ease-out-quint),
        opacity 320ms ease 200ms;
}

/* `all 1s` on an <img>. A one-second zoom outlasts most hovers, so the
   image is usually still moving when the pointer leaves — and 1.1 is a 10%
   crop, enough to visibly lose the edges of the composition. */
.featured-works-item .image img {
    transition: transform 520ms var(--ease-out-quint);
}

.featured-works-item:hover .image img {
    transform: scale(1.04);
}

/* .view-project is absent from this build's markup, but the rule is still
   live in styles.css — if it comes back it should fade, not pop. */
.featured-works-item .image .view-project {
    transition:
        opacity 200ms ease,
        transform 200ms var(--ease-out-quint),
        visibility 0ms linear 200ms;
    transform: translate(-50%, -50%) scale(0.96);
}

.featured-works-item:hover .image .view-project {
    transform: translate(-50%, -50%) scale(1);
    transition-delay: 0ms, 0ms, 0ms;
}


/* --- 5. Services accordion ----------------------------------------------
   Two things move when a panel opens, and they were fighting:

   - The dark `::before` panel slides via `bottom: 110% -> 0` over 300ms
     `all ease`. `bottom` is a layout property, and `all` also picks up the
     enormous box-shadow list on the same rule.
   - Bootstrap's .collapsing animates height over 350ms `ease`.

   Different durations, different curves, both layout-bound. Now both run
   400ms on the same curve, and the panel travels on transform. */

.accordion-faq_item .accordion-action::before {
    bottom: 0;
    transform: translateY(-110%);
    transition: transform 400ms var(--ease-in-out-strong);
}

.accordion-faq_item .accordion-action.collapsed::before {
    bottom: 0;
    transform: translateY(-110%);
}

.accordion-faq_item .accordion-action:not(.collapsed)::before {
    bottom: 0;
    transform: translateY(0);
}

.accordion-faq_item .collapsing {
    transition:
        height 400ms var(--ease-in-out-strong),
        margin-bottom 400ms var(--ease-in-out-strong);
}

/* The open state jumps the title from 36px/48 to 48px/56 with a
   letter-spacing change, and `all 0.3s` was tweening all three. Animated
   font-size relayouts and re-line-breaks the text every frame, on top of
   the height animation Bootstrap is already running — this was the single
   most expensive transition on the page.

   The size now snaps at t=0, under cover of the 400ms panel slide, and only
   colour is transitioned. */
.accordion-faq_item .accordion-title {
    transition: color 240ms ease;
}


/* --- 6. Services image swap ---------------------------------------------
   main.js fades the image with an inline `opacity: 0`, waits 200ms, swaps
   src, sets `opacity: 1`. No transition was ever declared on the <img>, so
   the sequence renders as: blink to nothing, 200ms of empty box, blink
   back. Matching the transition to the script's own 200ms turns it into
   the crossfade it was written to be. */

.services-image img {
    transition:
        opacity 200ms ease,
        filter 200ms ease;
}


/* --- 7. Button shine -----------------------------------------------------
   `shine-reverse` runs for 1s on every .animate-btn hover. The button's own
   hover response finishes in 140ms, so the highlight is still travelling
   long after the interaction has resolved — and being a keyframe animation
   it restarts from zero on every re-hover rather than retargeting. */

.animate-btn:hover::after {
    animation-duration: 600ms;
    animation-timing-function: var(--ease-out-quint);
}


/* --- 8. Touch devices ----------------------------------------------------
   Hover fires on tap and sticks until the next tap elsewhere, which leaves
   cards zoomed and buttons lifted. Transform-based hovers are gated; colour
   changes are harmless and stay. */

@media (hover: none) {
    .featured-works-item:hover .image img {
        transform: none;
    }

    .featured-works-item:hover .image:after {
        opacity: 0;
        transform: translate(-50%, -50%) rotate(-45deg) scaleY(0);
    }
}


/* --- 9. Reduced motion ---------------------------------------------------
   Reduced, not removed: opacity and colour still carry meaning, so they
   stay. Everything positional goes.

   Note this does NOT reach gsapAnimation.js — the scroll-triggered reveals,
   the SplitText character stagger and the flip-image timeline all keep
   running. Those need a JS-side guard. */

@media (prefers-reduced-motion: reduce) {
    .featured-works-item .image:after,
    .featured-works-item:hover .image:after {
        display: none;
    }

    .featured-works-item:hover .image img,
    .tf-btn:hover,
    .tf-btn-2:hover,
    .tf-btn:active,
    .tf-btn-2:active,
    .social-item:active {
        transform: none;
    }

    .accordion-faq_item .accordion-action::before,
    .accordion-faq_item .accordion-action.collapsed::before {
        transition: none;
    }

    .animate-btn:hover::after {
        animation: none;
    }

    /* radtak.css animates max-width, padding and gap on the sticky header
       for 550ms on every scroll past 40px — three layout properties, and
       the most-repeated animation on the site. */
    .tf-header,
    .tf-header .header-inner,
    .tf-header .nav-menu-main {
        transition: none;
    }
}
