/* ------------------------------------------------ */
/* SIDE PANELS (Very smooth curves like discs)      */
/* ------------------------------------------------ */
.side-panel {
    position: fixed;
    --w: 250vw;
    --h: 120vh;
    --top: 45%;

    width: var(--w);
    height: var(--h);
    top: var(--top);
    transform: translateY(-50%);
    border-radius: 50%;
    background: transparent;
    /* Hidden temporarily — disc covers it */
    z-index: 101;
    cursor: pointer;
    /* Smooth transitions for mobile and tablet */
    transition: width 0.8s cubic-bezier(0.25, 1, 0.5, 1),
                height 0.8s cubic-bezier(0.25, 1, 0.5, 1),
                top 0.8s cubic-bezier(0.25, 1, 0.5, 1),
                left 0.8s cubic-bezier(0.25, 1, 0.5, 1),
                right 0.8s cubic-bezier(0.25, 1, 0.5, 1),
                transform 0.8s cubic-bezier(0.25, 1, 0.5, 1);
}

.left-panel {
    left: -220vw;
}

.right-panel {
    right: -220vw;
}

.side-panel.disc-mode {
    --w: 30vw;
    --h: 30vw;
    --top: 15%;
}

.left-panel.disc-mode {
    left: 15px;
}

.right-panel.disc-mode {
    right: 15px;
}

.left-panel:not(.open):not(.disc-mode) {
    --btn-translate-x: -2.5vw;
}

.right-panel:not(.open):not(.disc-mode) {
    --btn-translate-x: 2.5vw;
}

.left-panel:not(.open):not(.disc-mode) .avatar,
.left-panel:not(.open):not(.disc-mode) .toggle-btn {
    transform: translateX(var(--btn-translate-x));
}

.right-panel:not(.open):not(.disc-mode) .avatar,
.right-panel:not(.open):not(.disc-mode) .toggle-btn {
    transform: translateX(var(--btn-translate-x));
}

/* Transition only when opening/closing (is-animating), to avoid scroll lag */
.is-animating,
.is-animating * {
    transition: all var(--transition-speed) cubic-bezier(0.25, 1, 0.5, 1) !important;
}

.panel-inner {
    position: relative;
    width: 100%;
    height: 100%;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    --scale: 1;
    pointer-events: none;
    z-index: 2;
    /* Above the vinyl disc */
}

.left-panel .panel-inner {
    --tx: 107vw;
    --ty: 0px;
    transform: translate(var(--tx), var(--ty)) scale(var(--scale));
    transition: transform 0.8s cubic-bezier(0.25, 1, 0.5, 1);
}

.right-panel .panel-inner {
    --tx: -107vw;
    --ty: 0px;
    transform: translate(var(--tx), var(--ty)) scale(var(--scale));
    transition: transform 0.8s cubic-bezier(0.25, 1, 0.5, 1);
}

/* Identifiable Avatar */
.avatar {
    --closed-avatar-size: clamp(180px, 24vw, 280px);
    --closed-avatar-width: calc(var(--closed-avatar-size) * 0.75);
    width: var(--closed-avatar-width);
    height: var(--closed-avatar-size);
    object-fit: contain;
    position: absolute;
    left: 50%;
    top: 50%;
    margin-left: calc(-0.5 * var(--closed-avatar-width));
    margin-top: calc(-0.5 * var(--closed-avatar-size));
    /* No filter: black line art shows clearly on grey vinyl */
    filter: none;
    z-index: 3;
    transition: all var(--transition-speed) cubic-bezier(0.25, 1, 0.5, 1);
    border-radius: 50%;
    /* border: 3px dotted darkviolet; -- Hidden momentarily by user request */
    border: none !important;
}

/* Chevron Arrows */
.toggle-btn {
    background: none;
    border: none;
    cursor: pointer;
    position: absolute;
    top: 50%;
    margin-top: 100px;
    width: 60px;
    height: 60px;
    display: flex;
    justify-content: center;
    align-items: center;
    pointer-events: none;
    transform: translateX(var(--btn-translate-x, 0px));
    opacity: 0.8;
}

/* farther from the screen edge: 60px offset */
.left-panel .toggle-btn {
    margin-left: -45px;
}

.right-panel .toggle-btn {
    margin-left: 45px;
}

/* Subtle animations */
.left-panel .toggle-btn {
    animation: hover-arrow-left 1s infinite ease-in-out;
}

.right-panel .toggle-btn {
    animation: hover-arrow-right 1s infinite ease-in-out;
}

@keyframes hover-arrow-left {

    0%,
    100% {
        transform: translate(var(--btn-translate-x, 0px), 0);
    }

    50% {
        transform: translate(calc(var(--btn-translate-x, 0px) + 8px), 0px);
    }
}

@keyframes hover-arrow-right {

    0%,
    100% {
        transform: translate(var(--btn-translate-x, 0px), 0);
    }

    50% {
        transform: translate(calc(var(--btn-translate-x, 0px) - 8px), 0px);
    }
}

.custom-arrow {
    width: 100%;
    height: 100%;
    fill: none;
    stroke: var(--color-dark-text);
    stroke-width: 10;
    stroke-linecap: round;
    stroke-linejoin: round;
    transition: transform 0.3s ease;
}

/* Rotate arrows downwards when scrolling and enlarge them a bit */
.left-panel .custom-arrow {
    transform: rotate(0deg) scale(1);
}

.right-panel .custom-arrow {
    transform: scaleX(-1) rotate(0deg) scale(1);
}

.reverse-arrow {
    transform: scaleX(-1);
}


.panel-name {
    width: 100%;
}

/* The name and bio are visually rendered with text-in-shape (SVG, follows
   the actual curve of the disc) in .side-panel-shaped-text; the original H2/P
   remain in the DOM (accessibility/SEO) but are not rendered. */
.side-panel-text-wrapper h2,
.side-panel-text-wrapper p {
    color: transparent !important;
}

/* Appended directly to <body> in position:fixed (see comment in main.js:
   panel-content-box uses display:contents while not open, which is not
   animatable, so the text cannot live inside that box if it needs to
   enter/exit with its own animation). left/top come inline per element
   (they match panel-content-box at the moment of drawing). */
.side-panel-shaped-text {
    position: fixed;
    pointer-events: none;
    z-index: 150;
    opacity: 1;
    transform: translateX(0);
    /* Transition when entering/exiting, matching the panel's 0.8s speed */
    transition: opacity 0.8s cubic-bezier(0.25, 1, 0.5, 1), transform 0.8s cubic-bezier(0.25, 1, 0.5, 1);
}

.side-panel-shaped-text.open {
    opacity: 1 !important;
}

/* Faster transition when opening/closing panel on click */
body:has(.is-animating) .side-panel-shaped-text {
    transition: opacity 0.28s cubic-bezier(0.25, 1, 0.5, 1), transform 0.28s cubic-bezier(0.25, 1, 0.5, 1);
}

/* "Hidden against the edge" state: the text enters/exits sliding from the
   outer edge of the disc (left on the left panel, right on the right panel),
   instead of a simple fade. main.js adds/removes this class manually (not with
   .is-animating) to control the exact entry timing (when panel-content-box has
   reached its final size) and exit timing (as soon as the closing starts).
   It uses its own class (shaped-text-left/right) and not the ancestor
   .left-panel/.right-panel because the SVG no longer lives inside the panel
   in the DOM. */
.side-panel-shaped-text.shaped-text-left.text-edge {
    opacity: 0;
    transform: translateX(-15vw);
}

.side-panel-shaped-text.shaped-text-right.text-edge {
    opacity: 0;
    transform: translateX(15vw);
}

/* Wraps name + paragraph. The actual visible text is rendered separately with
   text-in-shape (see .side-panel-shaped-text in main.js); this wrapper
   only holds the transparent H2/P left for accessibility/SEO. */
.side-panel-text-shell {
    position: relative;
    width: 100%;
    height: 49vh;
}

.side-panel-text-wrapper {
    width: 100%;
    height: 100%;
}

.left-panel .side-panel-text-wrapper {
    clip-path: polygon(calc(0% - 2vw) 0%,
            calc(0% - 2vw) 16.7%,
            calc(0% - 2vw) 33.3%,
            calc(0% - 2vw) 50%,
            calc(0% - 2vw) 66.7%,
            calc(0% - 2vw) 83.3%,
            calc(0% - 2vw) 100%,
            83% 100%,
            99% 83.3%,
            109% 66.7%,
            116% 50%,
            117% 33.3%,
            115% 16.7%,
            108% 0%);
}

.right-panel .side-panel-text-wrapper {
    clip-path: polygon(calc(100% + 2vw) 0%,
            calc(100% + 2vw) 16.7%,
            calc(100% + 2vw) 33.3%,
            calc(100% + 2vw) 50%,
            calc(100% + 2vw) 66.7%,
            calc(100% + 2vw) 83.3%,
            calc(100% + 2vw) 100%,
            17% 100%,
            1% 83.3%,
            -9% 66.7%,
            -16% 50%,
            -17% 33.3%,
            -15% 16.7%,
            -8% 0%);
}

/* ------------------------------------------------ */
/* OPEN STATE (Giant)                               */
/* ------------------------------------------------ */
.side-panel.open {
    --w: 250vw !important;
    --h: 120vh !important;
    width: var(--w) !important;
    height: var(--h) !important;
    top: 50% !important;
    transform: translateY(-50%) !important;
    cursor: default;
    z-index: 200 !important;
    /* The 250vw ellipse is huge and, without this, its invisible box (although
       transparent) keeps capturing clicks from the opposite side of the screen
       -blocking the arrow of the other closed panel- even though it is not rendered there.
       .panel-inner restores pointer-events further down, which is the only thing that
       needs to be clickable inside the open panel. */
    pointer-events: none;
}

.left-panel.open {
    left: -177vw !important;
}

.right-panel.open {
    right: -177vw !important;
}

/* Center the content within the visible area (approx 73vw) */
.left-panel.open .panel-inner {
    transform: translateX(88.5vw) scale(1) !important;
}

.right-panel.open .panel-inner {
    transform: translateX(-88.5vw) scale(1) !important;
}

/* pointer-events goes on panel-content-box (not on panel-inner): panel-inner
   occupies the entire 250vw ellipse without a clip-path, so if it were clickable
   there it would cover the other closed panel again. panel-content-box does
   have the clip-path of the disc, so its clickable area matches what is actually seen. */
.side-panel.open .panel-content-box {
    pointer-events: auto;
}

.side-panel.open {
    overflow: visible;
}

/* ================================================ */
/* PANEL-CONTENT-BOX — face / text / arrow triad    */
/*                                                  */
/* Geometry: 250vw×120vh ellipse centered at 63.5vw */
/*   Visible disc: 73vw × 76vh                      */
/*   Container: top=12vh bottom=88vh (centered 50vh)*/
/*   indent(y_vp) = 125×(1-sqrt(1-((y_vp-50)/60)²)) */
/*                                                  */
/* Clip-path = disc shape (73vw×76vh):              */
/*   y=0% (12vh)   → indent=28.4vw → 39% of width   */
/*   y=10% (19.6vh)→ 17.3vw → 24%                   */
/*   y=20% (27.2vh)→ 9.5vw  → 13%                   */
/*   y=30% (34.8vh)→ 4.1vw  →  6%                   */
/*   y=40% (42.4vh)→ 1.0vw  →  1%                   */
/*   y=50% (50vh)  → 0                              */
/* (symmetric upwards and downwards)                */
/* ================================================ */
.panel-content-box {
    display: contents;
}

.side-panel.open .panel-content-box {
    display: flex;
    flex-direction: column;
    align-items: center;
    width: 73vw;
    height: 76vh;
    /* 12vh→88vh: arrow at 80-88vh, visible */
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
}

/* ---- Clip-path: disc shape (calculated for 76vh) ---- */
.right-panel.open .panel-content-box {
    clip-path: polygon(39% 0%, 24% 10%, 13% 20%,
            6% 30%, 1% 40%, 0% 50%,
            1% 60%, 6% 70%, 13% 80%,
            24% 90%, 39% 100%,
            100% 100%, 100% 0%);
    padding-left: calc(3.75vw + 5px);
}

.left-panel.open .panel-content-box {
    clip-path: polygon(0% 0%, 0% 100%,
            61% 100%, 76% 90%, 87% 80%,
            94% 70%, 99% 60%, 100% 50%,
            99% 40%, 94% 30%, 87% 20%,
            76% 10%, 61% 0%);
    padding-right: calc(3.75vw + 5px);
}

/* ---- Face: top 28% ----
   position remains absolute at all times (same as the closed state) so that
   opening/closing is a simple interpolation of top/left/transform without a jump:
   if it changed to position:relative here (flex item within panel-content-box),
   the position change on closing is not animatable and the avatar would "jump"
   downwards before settling, giving the impression of entering from below
   instead of descending neatly from above. */
.side-panel.open .avatar {
    position: absolute !important;
    top: calc(50% - 38vh) !important;
    left: 50% !important;
    margin: 0 !important;
    width: auto !important;
    height: 21.28vh !important;
    /* 28% de los 76vh de panel-content-box */
    flex-shrink: 0;
    object-fit: contain;
}

.left-panel.open .avatar {
    transform: translateX(calc(-50% - 3.5vw)) !important;
}

.right-panel.open .avatar {
    transform: translateX(calc(-50% + 3.5vw)) !important;
}

/* ---- Text: central 62% ---- */
.side-panel.open .hidden-text {
    position: relative !important;
    top: auto !important;
    transform: none !important;
    margin: 0 !important;
    opacity: 1 !important;
    visibility: visible !important;
    width: 100%;
    flex: 1;
    display: block !important;
    transition-delay: 0.3s;
}

/* Margin on the "flat" side of the disc (no curve) */
.right-panel.open .hidden-text {
    padding-right: 4vw;
}

.left-panel.open .hidden-text {
    padding-left: 4vw;
}

/* Margin for the name */
.right-panel.open .panel-name {
    padding-left: 2vw;
}

.left-panel.open .panel-name {
    padding-right: 2vw;
}

.side-panel.open .hidden-text p {
    overflow: visible;
}

/* ---- Arrow: flat lower band of the disc ----
   position absolute (not flex item) so that it doesn't depend on the height
   left free by the text: with long bios the text overflows onto the lower 10%
   of the flex and covered the arrow. Located in the wide/flat bottom part,
   far from the curve, so it always remains free. */
.side-panel.open .toggle-btn {
    position: absolute !important;
    top: 83% !important;
    bottom: auto !important;
    left: 50% !important;
    width: 44%;
    height: 11%;
    margin: 0 !important;
    transform: translateX(-50%) !important;
    pointer-events: auto;
    animation: none;
    display: flex;
    align-items: center;
    justify-content: center;
}

.left-panel.open .toggle-btn .custom-arrow {
    transform: scaleX(-1);
}

.right-panel.open .toggle-btn .custom-arrow {
    transform: scaleX(1);
}




/* ------------------------------------------------ */
/* DISC-MODE: faces rotate with the vinyl           */
/* Triggered upon reaching the PROJECTS section     */
/* ------------------------------------------------ */
.side-panel.disc-mode .avatar {
    animation: vinyl-spin 2.8s linear infinite !important;
}

.side-panel.disc-mode .panel-inner {
    /* Cancel the scroll transform so that the avatar */
    /* is centered inside the sphere/disc */
    transform: translate(0, 0) scale(1) !important;
    transition: transform 0.8s cubic-bezier(0.4, 0, 0.2, 1);
}

.side-panel.disc-mode,
.side-panel.disc-mode * {
    pointer-events: auto !important;
}

.panel-vinyl-svg text {
    transition: opacity 0.6s ease;
}

.side-panel.disc-mode .panel-vinyl-svg text {
    opacity: 0 !important;
}

.side-panel.disc-mode {
    z-index: 250 !important;
}

.side-panel.disc-mode .hidden-text,
.side-panel.disc-mode .toggle-btn {
    opacity: 0 !important;
    visibility: hidden !important;
    transition: opacity 0.4s ease;
}

.side-panel.disc-mode .avatar {
    top: 50%;
    left: 50%;
    margin-top: -35%;
    /* -half of 70% */
    margin-left: -35%;
    width: 70%;
    height: 70%;
    transform-origin: center center !important;
    transition: top 0.8s ease, left 0.8s ease, margin 0.8s ease, width 0.6s ease, height 0.6s ease;
    filter: none;
    z-index: 5;
}

/* MOBILE SUPPORT (Compact Disc Mode) */
@media (max-width: 900px) {
    .side-panel.disc-mode {
        --w: 80px !important;
        --h: 80px !important;
        width: var(--w) !important;
        height: var(--h) !important;
        top: 20px !important;
        transform: none !important;
        z-index: 250 !important;
    }

    .left-panel.disc-mode {
        left: 15px !important;
    }

    .right-panel.disc-mode {
        right: 15px !important;
        left: auto !important;
    }

    .side-panel.disc-mode .avatar {
        width: 48px !important;
        height: 48px !important;
        margin-top: -24px !important;
        margin-left: -24px !important;
        top: 50% !important;
        left: 50% !important;
        position: absolute !important;
    }

    .side-panel.disc-mode .panel-vinyl {
        position: absolute !important;
        top: 50% !important;
        left: 50% !important;
        right: auto !important;
        bottom: auto !important;
        transform: translate(-50%, -50%) scale(1) !important;
        width: calc(100% - 4px) !important;
        height: calc(100% - 4px) !important;
    }
}

/* WIDE SCREEN DESKTOP SUPPORT (>= 900px) */
@media (min-width: 900px) {

    /* 1. Dynamic panel geometry */
    .side-panel {
        --w: 2250px;
        --h: 120vh;
        --top: 45%;

        width: var(--w);
        height: var(--h);
        top: var(--top);
        cursor: default;
        pointer-events: auto !important;
    }

    .left-panel {
        left: calc(18vw - var(--w));
    }

    .right-panel {
        right: calc(18vw - var(--w));
    }

    .side-panel.disc-mode {
        --w: 144px !important;
        --h: 144px !important;
        --top: 90px !important;
    }

    .left-panel.disc-mode {
        left: 15px !important;
    }

    .right-panel.disc-mode {
        right: 15px !important;
    }



    .left-panel:not(.disc-mode) .panel-inner,
    .right-panel:not(.disc-mode) .panel-inner {
        --tx: 0px !important;
        --ty: 0px !important;
        transform: translate(var(--tx), var(--ty)) scale(var(--scale)) !important;
    }

    .side-panel.open .panel-inner {
        transform: translate(0, 0) scale(1) !important;
    }

    .side-panel.open {
        --w: 2250px !important;
        --h: 120vh !important;
        --top: 45% !important;
        width: var(--w) !important;
        height: var(--h) !important;
        top: var(--top) !important;
        transform: translateY(-50%) !important;
    }

    .left-panel.open {
        left: calc(18vw - var(--w)) !important;
    }

    .right-panel.open {
        right: calc(18vw - var(--w)) !important;
    }

    .side-panel.open .panel-content-box {
        pointer-events: auto !important;
    }

    .side-panel.open .avatar {
        position: relative !important;
        top: auto !important;
        left: auto !important;
        margin: 0 !important;
        width: auto !important;
        height: 28% !important;
        flex-shrink: 0;
        object-fit: contain;
    }

    .left-panel.open .avatar {
        transform: translateX(-1.5vw) !important;
    }

    .right-panel.open .avatar {
        transform: translateX(1.5vw) !important;
    }

    .left-panel:not(.disc-mode) .panel-content-box {
        position: absolute !important;
        top: 50% !important;
        transform: translateY(-50%) !important;
        left: auto !important;
        /* right:0 alone, combined with min-width:280px, pushed the box off
           the screen on the left as soon as 18vw fell below 280px (~<1556px
           width), cutting off the actual name/bio (not just the debug points).
           min(0px, 18vw - 280px) maintains the original anchor (right:0)
           while 18vw>=280px, and only when min-width comes into play does
           it slide the anchor just enough so that the left edge of the box
           doesn't cross the screen edge. */
        right: min(0px, 18vw - 280px) !important;
        width: 18vw !important;
        min-width: 280px !important;
        height: 76vh !important;
        display: flex !important;
        flex-direction: column;
        align-items: center;
        pointer-events: none !important;
    }

    .right-panel:not(.disc-mode) .panel-content-box {
        position: absolute !important;
        top: 50% !important;
        transform: translateY(-50%) !important;
        /* Mirror of the fix in .left-panel: with pure left:0, min-width:280px
           pushed the right edge of the box beyond the actual screen edge as
           soon as 18vw fell below 280px (~<1556px), making calc(100% + 2vw)
           (points 8-14) point off the screen. */
        left: min(0px, 18vw - 280px) !important;
        right: auto !important;
        width: 18vw !important;
        min-width: 280px !important;
        height: 76vh !important;
        display: flex !important;
        flex-direction: column;
        align-items: center;
        pointer-events: none !important;
    }

    .right-panel:not(.disc-mode) .panel-content-box {
        clip-path: polygon(39% 0%, 24% 10%, 13% 20%,
                6% 30%, 1% 40%, 0% 50%,
                1% 60%, 6% 70%, 13% 80%,
                24% 90%, 39% 100%,
                100% 100%, 100% 0%) !important;
        padding-left: calc(3.75vw + 5px) !important;
    }

    /* The disc (.panel-vinyl) is sized solely with --h (vh, with no limit) and
       is anchored with a fixed right/left:2px — it does not know the min-width:280px
       of panel-content-box. Below ~1556px (18vw < 280px) the edge of the disc
       remained further in than the edge of the text box (and the debug points
       1-7, which calibrate on that same box), leaving a growing gap between them.
       The disc is enlarged by that same gap (max(0px, 280px - 18vw)) so that its
       edge always reaches the actual edge of the box: the disc remains larger/more
       visible AND aligned with the points, instead of staying small and misaligned. */
    .left-panel:not(.disc-mode) .panel-vinyl {
        width: calc(var(--h) - 4px + max(0px, 280px - 18vw)) !important;
        height: calc(var(--h) - 4px + max(0px, 280px - 18vw)) !important;
        right: calc(2px - max(0px, 280px - 18vw)) !important;
    }

    .right-panel:not(.disc-mode) .panel-vinyl {
        width: calc(var(--h) - 4px + max(0px, 280px - 18vw)) !important;
        height: calc(var(--h) - 4px + max(0px, 280px - 18vw)) !important;
        left: calc(2px - max(0px, 280px - 18vw)) !important;
    }

    .left-panel:not(.disc-mode) .panel-content-box {
        clip-path: polygon(0% 0%, 0% 100%,
                61% 100%, 76% 90%, 87% 80%,
                94% 70%, 99% 60%, 100% 50%,
                99% 40%, 94% 30%, 87% 20%,
                76% 10%, 61% 0%) !important;
        padding-right: calc(3.75vw + 5px) !important;
    }

    .side-panel:not(.disc-mode) .avatar {
        position: relative !important;
        top: auto !important;
        left: auto !important;
        margin: 0 !important;
        width: auto !important;
        height: 28% !important;
        flex-shrink: 0;
        object-fit: contain;
    }

    .left-panel:not(.disc-mode) .avatar {
        transform: translateX(-1.5vw) !important;
    }

    .right-panel:not(.disc-mode) .avatar {
        transform: translateX(1.5vw) !important;
    }

    .side-panel:not(.open):not(.disc-mode) .hidden-text {
        opacity: 1 !important;
        visibility: visible !important;
        position: relative !important;
        top: auto !important;
        transform: none !important;
        margin: 0 !important;
        width: 100%;
        display: block !important;
    }

    .right-panel:not(.open):not(.disc-mode) .hidden-text {
        padding-right: 2vw !important;
    }

    .left-panel:not(.open):not(.disc-mode) .hidden-text {
        padding-left: 2vw !important;
    }

    .side-panel:not(.open):not(.disc-mode) .toggle-btn {
        display: none !important;
    }

    /* Cuts the width of the name so that it does not extend beyond
       the visible area of the disc towards the black background */
    .side-panel:not(.open):not(.disc-mode) .panel-name {
        width: 75%;
    }
}

/* ------------------------------------------------ */
/* FIRST LOAD ENTRY ANIMATION                       */
/* ------------------------------------------------ */
.left-panel.first-load {
    animation: slide-in-left-panel 1.2s cubic-bezier(0.25, 1, 0.5, 1) forwards;
}

.right-panel.first-load {
    animation: slide-in-right-panel 1.2s cubic-bezier(0.25, 1, 0.5, 1) forwards;
}

.side-panel-shaped-text.first-load {
    animation: fade-in-text 1.2s cubic-bezier(0.25, 1, 0.5, 1) forwards;
}

@keyframes slide-in-left-panel {
    from {
        left: -250vw;
    }
}

@keyframes slide-in-right-panel {
    from {
        right: -250vw;
    }
}

@keyframes fade-in-text {
    from {
        opacity: 0;
    }
    to {
        opacity: 1;
    }
}

