/* ==========================================================================
   Chain Animations - Base Styles
   ========================================================================== */

/**
 * No-JS Fallback: Elements visible by default
 * JS adds .js class to <html>, enabling animations
 */
 .chain-animated {
    /* Default: visible (no-js fallback) */
    opacity: 1;
    visibility: visible;
}

/**
 * When JS is enabled, hide elements initially
 */
.js .chain-animated {
    opacity: 0;
    visibility: hidden;
}

/**
 * Visible state - element is animating or finished
 */
.js .chain-animated.is-visible {
    opacity: 1;
    visibility: visible;
}

/**
 * Layer hint only while animating: a permanent will-change on every animated
 * element keeps dozens of compositor layers alive after the page has settled.
 */
.js .chain-animated.is-visible:not(.animation-finished) {
    will-change: opacity, transform;
}

/**
 * Finished state - animation complete or skipped (minWidth)
 */
.js .chain-animated.animation-finished {
    opacity: 1;
    visibility: visible;
    transform: none;
}

/**
 * Reduced motion support
 */
@media (prefers-reduced-motion: reduce) {
    .js .chain-animated {
        opacity: 1;
        visibility: visible;
        transform: none;
        transition: none;
        animation: none;
    }
}

/* Animation definitions */
@keyframes fadeInFromDown {
    from {
        opacity: 0;
        transform: translateY(20px);
    }
    to {
        opacity: 1;
        transform: translateY(0);
    }
}

@keyframes fadeInFromUp {
    from {
        opacity: 0;
        transform: translateY(-20px);
    }
    to {
        opacity: 1;
        transform: translateY(0);
    }
}

@keyframes fadeInFromLeft {
    from {
        opacity: 0;
        transform: translateX(-20px);
    }
    to {
        opacity: 1;
        transform: translateX(0);
    }
}

@keyframes fadeInFromRight {
    from {
        opacity: 0;
        transform: translateX(20px);
    }
    to {
        opacity: 1;
        transform: translateX(0);
    }
}

@keyframes fadeIn {
    from {
        opacity: 0;
    }
    to {
        opacity: 1;
    }
}

@keyframes fadeInAndSmallScaleUp {
    from {
        opacity: 0;
        transform: scale(1);
    }
    10%{
        opacity:1;
        transform:scale(1.01);
    }

    to {
        opacity: 1;
        transform: scale(1.1);
    }
}

/* Poistuvia animaatioita välilehtien vaihtoon */
@keyframes fadeOutToLeft {
    from {
        opacity: 1;
        transform: translateX(0);
    }
    to {
        opacity: 0;
        transform: translateX(-30px);
    }
}

@keyframes fadeOutToUp {
    from {
        opacity: 1;
        transform: translateY(0);
    }
    to {
        opacity: 0;
        transform: translateY(-30px);
    }
}

@keyframes fadeOut {
    from {
        opacity: 1;
    }
    to {
        opacity: 0;
    }
}

/* Taustakuvan slide-animaatio alhaalta ylös */
@keyframes slideInFromBottom {
    from {
        top: 100%;
        opacity: 0;
    }
    to {
        top: 0;
        opacity: 1;
    }
}

@keyframes slideOutToBottom {
    from {
        top: 0%;
        opacity: 1;
    }
    to {
        top: 100%;
        opacity: 0;
    }
}

/* Animation classes */
.ca-fadeInFromDown.is-visible {
    animation: fadeInFromDown var(--animation-duration) ease-out forwards;
}

.ca-fadeInFromUp.is-visible {
    animation: fadeInFromUp var(--animation-duration) ease-out forwards;
}

.ca-fadeInFromLeft.is-visible {
    animation: fadeInFromLeft var(--animation-duration) ease-out forwards;
}

.ca-fadeInFromRight.is-visible {
    animation: fadeInFromRight var(--animation-duration) ease-out forwards;
}

.ca-fadeIn.is-visible {
    animation: fadeIn var(--animation-duration) ease-out forwards;
}
.ca-fadeInAndSmallScaleUp.is-visible {
    animation: fadeInAndSmallScaleUp 10s ease-out forwards;
}
/* Poistuvien animaatioiden luokat */
.ca-fadeOutToLeft {
    animation: fadeOutToLeft var(--animation-duration, 0.4s) ease-out forwards;
}

.ca-fadeOutToUp {
    animation: fadeOutToUp var(--animation-duration, 0.4s) ease-out forwards;
}

.ca-fadeOut {
    animation: fadeOut var(--animation-duration, 0.4s) ease-out forwards;
}

/* ==========================================================================
   Heading reveals: ca-riseWords and ca-blockReveal
   ==========================================================================
   For the page's main heading (the hero H1), not for body text or every
   heading on the page. Runs once like every chain type.

   chain-animations.js splits the text before the chain starts (front end
   only: not in the editor, not with reduced motion, not without JS; then the
   heading shows as it is). The text stays in the DOM in order, so screen
   readers and search engines read it normally. The element itself has no
   animation, its parts do, and the chain waits for them (.ca-split).

   ca-riseWords   each word rises from under its baseline, staggered by
                  --ca-word-stagger (60ms; the stagger stops growing after
                  12 words). --animation-duration is one word (0.6s).
                  Parts: span.ca-word > span.ca-word-inner (--i = index)

   ca-blockReveal a bar in the palette's accent colour sweeps over each line
                  and retracts to the right, leaving the text. Each line gets
                  its own bar (box-decoration-break), as wide as the text.
                  --animation-duration is the whole sweep (1s suits it).
                  Parts: span.ca-block-text around the content (or around
                  .gb-headline-text in an icon headline)
                  Bar colour: --ca-block-clr (default: --accent-clr where the
                  heading is, so it follows a dark section)
   ========================================================================== */

:root {
    --ca-word-stagger: 60ms;
}

/* riseWords. Every word is top aligned, so the line looks the same whether
   or not the word clips (an inline-block that clips may move its baseline). */
.ca-word {
    display: inline-block;
    vertical-align: top;
    /* room for descenders inside the mask, cancelled so the line keeps its height */
    padding-bottom: 0.12em;
    margin-bottom: -0.12em;
}

.ca-word-inner {
    display: inline-block;
}

.js .ca-riseWords:not(.animation-finished) .ca-word {
    overflow: clip;
}

.js .ca-riseWords:not(.animation-finished) .ca-word-inner {
    transform: translateY(125%);
}

.js .ca-riseWords.is-visible:not(.animation-finished) .ca-word-inner {
    animation: caRiseWord var(--animation-duration, 0.6s) cubic-bezier(0.2, 0.7, 0.2, 1) calc(var(--i, 0) * var(--ca-word-stagger)) both;
}

@keyframes caRiseWord {
    from {
        transform: translateY(125%);
    }
    to {
        transform: translateY(0);
    }
}

/* blockReveal. The text is hidden with text-fill-color, which inherits, so
   a link or <em> with its own colour is hidden too. The shadow of a
   .text-shadow heading waits for the end: a shadow would show without text. */
.ca-block-text {
    -webkit-box-decoration-break: clone;
    box-decoration-break: clone;
}

.js .ca-blockReveal:not(.animation-finished) .ca-block-text {
    background-image: linear-gradient(var(--ca-block-clr, var(--accent-clr)), var(--ca-block-clr, var(--accent-clr)));
    background-repeat: no-repeat;
    background-position: left center;
    background-size: 0% 100%;
    -webkit-text-fill-color: transparent;
    text-shadow: none;
}

.js .ca-blockReveal.is-visible:not(.animation-finished) .ca-block-text {
    animation: caBlockSweep var(--animation-duration, 1s) cubic-bezier(0.65, 0, 0.35, 1) both;
}

/* The bar grows from the left, the text appears under the full bar, the bar
   leaves to the right. Position left and right are the same at 100% width,
   so switching it at the turn does not show. */
@keyframes caBlockSweep {
    0% {
        background-size: 0% 100%;
        background-position: left center;
        -webkit-text-fill-color: transparent;
    }
    50% {
        background-size: 100% 100%;
        background-position: left center;
        -webkit-text-fill-color: transparent;
    }
    50.01% {
        background-size: 100% 100%;
        background-position: right center;
        -webkit-text-fill-color: currentcolor;
    }
    100% {
        background-size: 0% 100%;
        background-position: right center;
        -webkit-text-fill-color: currentcolor;
    }
}

/* The script does not split with reduced motion; this covers a setting
   changed after the page loaded. Same selectors as above, so source order wins. */
@media (prefers-reduced-motion: reduce) {
    .js .ca-riseWords:not(.animation-finished) .ca-word {
        overflow: visible;
    }

    .js .ca-riseWords:not(.animation-finished) .ca-word-inner,
    .js .ca-riseWords.is-visible:not(.animation-finished) .ca-word-inner {
        transform: none;
        animation: none;
    }

    .js .ca-blockReveal:not(.animation-finished) .ca-block-text,
    .js .ca-blockReveal.is-visible:not(.animation-finished) .ca-block-text {
        animation: none;
        background-image: none;
        -webkit-text-fill-color: currentcolor;
        text-shadow: inherit;
    }
}
