/*
 * Public-site motion: homepage hero entrance, staggered scroll reveals, scroll
 * progress. Everything here is gated on html.mj-motion, which base.html only
 * sets when JavaScript runs and the visitor has not asked for reduced motion.
 * Without it every page renders fully visible and static.
 *
 * Reveal targets: [data-reveal] sections and [data-reveal-item] cards on the
 * homepage, and any .animate-on-scroll element on the other pages. Inner-page
 * headers ([data-page-header]) play a load entrance instead.
 *
 * Reveals use the individual `translate` / `scale` properties so they never
 * fight the existing `transform` hover effects on cards and images.
 */

:root {
    --mj-ease-out: cubic-bezier(0.22, 1, 0.36, 1);
    --mj-ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1);
}

html.mj-motion {
    scroll-behavior: smooth;
}

#cas-section {
    scroll-margin-top: 90px;
}

/* ---------- Hero entrance (plays once on load) ---------- */

@keyframes mjRiseIn {
    from {
        opacity: 0;
        translate: 0 22px;
    }
    to {
        opacity: 1;
        translate: 0 0;
    }
}

/* The hero title, description and portrait are the page's LCP candidates.
 * Chrome does not count an element as painted while its opacity is 0, so they
 * settle into place without a fade: they are visible from the first paint
 * and LCP lands at FCP instead of after the entrance (~1.1 s later on a
 * throttled phone). The smaller items around them still fade in. */
@keyframes mjSettleIn {
    from {
        translate: 0 14px;
    }
    to {
        translate: 0 0;
    }
}

@keyframes mjPortraitIn {
    from {
        clip-path: inset(6% 6% 6% 6% round 20px);
        scale: 0.97;
    }
    to {
        clip-path: inset(0 0 0 0 round 20px);
        scale: 1;
    }
}

.mj-motion [data-hero-item] {
    animation: mjRiseIn 0.9s var(--mj-ease-out) both;
}

.mj-motion .hero-chip-badge { animation-delay: 0.05s; }
.mj-motion .hero-main-title,
.mj-motion .hero-description-text { animation: mjSettleIn 0.8s var(--mj-ease-out) both; }
.mj-motion .hero-description-text { animation-delay: 0.08s; }
.mj-motion .hero-trust-row { animation-delay: 0.3s; }
.mj-motion .hero-buttons-container { animation-delay: 0.4s; }

.mj-motion [data-hero-portrait] {
    animation: mjPortraitIn 1s var(--mj-ease-out) both;
}

.mj-motion [data-hero-portrait] .doctor-overlay-card {
    animation: mjRiseIn 0.8s var(--mj-ease-out) 0.65s both;
}

/* The soft colour blob behind the hero drifts slower than the page. */
.mj-motion .hero-wrapper-c::before {
    translate: 0 calc(var(--mj-hero-shift, 0) * 1px);
}

/* ---------- Scroll reveals ---------- */

.mj-motion [data-reveal] {
    opacity: 0;
    translate: 0 18px;
    transition: opacity 0.7s var(--mj-ease-out), translate 0.9s var(--mj-ease-out);
}

.mj-motion [data-reveal-item],
.mj-motion .animate-on-scroll {
    opacity: 0;
    translate: 0 28px;
    transition:
        opacity 0.7s var(--mj-ease-out),
        translate 0.9s var(--mj-ease-out),
        scale 0.9s var(--mj-ease-out);
    transition-delay: var(--mj-reveal-delay, 0ms);
}

.mj-motion [data-reveal-item="zoom"] {
    translate: none;
    scale: 0.9;
}

.mj-motion [data-reveal].is-revealed,
.mj-motion [data-reveal-item].is-revealed,
.mj-motion .animate-on-scroll.is-revealed {
    opacity: 1;
    translate: 0 0;
    scale: 1;
}

/* Page headers ([data-page-header], the first block on every inner page) play
 * on load instead of waiting for site-motion.js: their title and intro are the
 * page's LCP candidates, so like the homepage hero they settle into place
 * without a fade and count as painted at FCP. Only the badge fades in. */
.mj-motion [data-page-header] > * {
    animation: mjSettleIn 0.7s var(--mj-ease-out) both;
}

.mj-motion [data-page-header] > :first-child { animation-name: mjRiseIn; }
.mj-motion [data-page-header] > :nth-child(2) { animation-delay: 0.06s; }
.mj-motion [data-page-header] > :nth-child(n+3) { animation-delay: 0.12s; }

/* Other section cards: heading block and contents rise in one after another
 * once scrolled into view. */
.mj-motion .section-wrapper-c.animate-on-scroll > * {
    opacity: 0;
    translate: 0 16px;
    transition: opacity 0.6s var(--mj-ease-out), translate 0.8s var(--mj-ease-out);
    transition-delay: calc(var(--mj-reveal-delay, 0ms) + 120ms);
}

.mj-motion .section-wrapper-c.animate-on-scroll > :nth-child(2) { transition-delay: calc(var(--mj-reveal-delay, 0ms) + 200ms); }
.mj-motion .section-wrapper-c.animate-on-scroll > :nth-child(3) { transition-delay: calc(var(--mj-reveal-delay, 0ms) + 280ms); }
.mj-motion .section-wrapper-c.animate-on-scroll > :nth-child(n+4) { transition-delay: calc(var(--mj-reveal-delay, 0ms) + 360ms); }

.mj-motion .section-wrapper-c.animate-on-scroll.is-revealed > * {
    opacity: 1;
    translate: 0 0;
}

/* Small accents that land just after their card. */
.mj-motion [data-reveal-item] .specialty-icon-circle,
.mj-motion [data-reveal-item] .cas-step-num,
.mj-motion .animate-on-scroll .cas-step-num {
    opacity: 0;
    scale: 0.5;
    transition: opacity 0.4s ease-out, scale 0.7s var(--mj-ease-spring);
    transition-delay: calc(var(--mj-reveal-delay, 0ms) + 250ms);
}

.mj-motion [data-reveal-item].is-revealed .specialty-icon-circle,
.mj-motion [data-reveal-item].is-revealed .cas-step-num,
.mj-motion .animate-on-scroll.is-revealed .cas-step-num {
    opacity: 1;
    scale: 1;
}

/* ---------- Booking day and time picker ---------- */

/* The booking script rebuilds the time grid each time a day is picked, so the
   new times rise in one after another; the chosen day or time gives a small
   pop. Only `translate` / `scale` / `opacity` move, never colours, so light and
   dark themes behave the same. */

@keyframes mjSlotIn {
    from {
        opacity: 0;
        translate: 0 8px;
    }
    to {
        opacity: 1;
        translate: 0 0;
    }
}

@keyframes mjSlotPick {
    0% { scale: 1; }
    40% { scale: 1.06; }
    100% { scale: 1; }
}

@media (prefers-reduced-motion: no-preference) {
    .mj-motion .slot-times .slot-option {
        animation: mjSlotIn 0.36s var(--mj-ease-out) both;
    }

    .mj-motion .slot-times .slot-option:nth-child(2) { animation-delay: 30ms; }
    .mj-motion .slot-times .slot-option:nth-child(3) { animation-delay: 60ms; }
    .mj-motion .slot-times .slot-option:nth-child(4) { animation-delay: 90ms; }
    .mj-motion .slot-times .slot-option:nth-child(5) { animation-delay: 120ms; }
    .mj-motion .slot-times .slot-option:nth-child(6) { animation-delay: 150ms; }
    .mj-motion .slot-times .slot-option:nth-child(7) { animation-delay: 180ms; }
    .mj-motion .slot-times .slot-option:nth-child(n+8) { animation-delay: 210ms; }

    .mj-motion .slot-option label {
        transition:
            background-color 0.15s ease,
            border-color 0.15s ease,
            color 0.15s ease,
            translate 0.2s var(--mj-ease-out),
            box-shadow 0.2s ease;
    }

    .mj-motion .slot-radio:not(:disabled):not(:checked) + label:hover {
        translate: 0 -2px;
        box-shadow: 0 4px 10px rgba(0, 77, 77, 0.12);
    }

    .mj-motion .slot-radio:not(:disabled) + label:active {
        translate: 0 0;
        scale: 0.96;
    }

    .mj-motion .slot-radio:checked + label {
        animation: mjSlotPick 0.32s var(--mj-ease-spring);
    }

    /* Suggested slots and the submit button answer a press the same way. */
    .mj-motion .booking-page .suggested-slot,
    .mj-motion .booking-form [type="submit"] {
        transition:
            color 0.15s ease-in-out,
            background-color 0.15s ease-in-out,
            border-color 0.15s ease-in-out,
            box-shadow 0.15s ease-in-out,
            scale 0.15s ease;
    }

    .mj-motion .booking-page .suggested-slot:active,
    .mj-motion .booking-form [type="submit"]:active {
        scale: 0.98;
    }
}

/* ---------- Form result messages ---------- */

/* After a booking or lead-form submit, the result message in the form card
   eases in once the card has revealed; a warning or error also gives a short
   sideways nudge so it reads as "fix this". `backwards` fill only holds the
   start frame during the delay, so afterwards Bootstrap's own .fade dismiss
   on the lead alert still works. Nothing changes the message or its role. */
@keyframes mjNoticeIn {
    from {
        opacity: 0;
        scale: 0.96;
    }
    to {
        opacity: 1;
        scale: 1;
    }
}

@keyframes mjNoticeNudge {
    0%, 100% { translate: 0 0; }
    20% { translate: -6px 0; }
    40% { translate: 5px 0; }
    60% { translate: -3px 0; }
    80% { translate: 2px 0; }
}

.mj-motion .animate-on-scroll.is-revealed .alert[role="alert"] {
    animation: mjNoticeIn 0.5s var(--mj-ease-spring) 0.3s backwards;
}

.mj-motion .animate-on-scroll.is-revealed .alert-warning[role="alert"],
.mj-motion .animate-on-scroll.is-revealed .alert-danger[role="alert"] {
    animation:
        mjNoticeIn 0.4s var(--mj-ease-out) 0.3s backwards,
        mjNoticeNudge 0.45s ease-in-out 0.7s;
}

/* ---------- Press and focus feedback ---------- */

/* Keyboard focus gets one clear brand ring on links and buttons. This is not
   motion, so it stays on under reduced motion; --color-primary is the lighter
   teal in dark mode. Bootstrap's own .btn focus shadow still shows too. */
a:focus-visible,
button:focus-visible,
.btn:focus-visible,
[role="button"]:focus-visible {
    outline: 2px solid var(--color-primary, #008080);
    outline-offset: 3px;
}

/* Buttons shrink a touch while pressed. `scale` is separate from `transform`,
   so the existing hover lifts on hero, contact and card buttons still work. */
@media (prefers-reduced-motion: no-preference) {
    .mj-motion .btn {
        transition:
            color 0.15s ease-in-out,
            background-color 0.15s ease-in-out,
            border-color 0.15s ease-in-out,
            box-shadow 0.15s ease-in-out,
            transform 0.25s ease,
            scale 0.15s ease;
    }

    .mj-motion .btn:not(:disabled):not(.disabled):active {
        scale: 0.97;
    }
}

/* ---------- Scroll progress bar ---------- */

.mj-scroll-progress {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    height: 3px;
    z-index: 1031;
    background: linear-gradient(90deg, var(--color-primary, #008080), var(--color-secondary, #B8860B));
    transform: scaleX(0);
    transform-origin: 0 50%;
    pointer-events: none;
}

/* ---------- Hero: breathing light behind the headline ---------- */

/* Three soft colour pools inside the hero card. Static without motion; with
   it they drift on long, offset cycles so the movement never repeats in an
   obvious way. Only transform animates, so it stays on the compositor. All
   are placed from the top so a late font swap can't move them (no CLS). */
.mj-aurora {
    position: absolute;
    inset: 0;
    z-index: 0;
    overflow: hidden;
    border-radius: inherit;
    pointer-events: none;
}

.mj-aurora span {
    position: absolute;
    border-radius: 50%;
}

.mj-aurora span:nth-child(1) {
    width: 520px;
    height: 520px;
    left: -160px;
    top: -180px;
    background: radial-gradient(circle, rgba(0, 128, 128, 0.2) 0%, rgba(0, 128, 128, 0) 65%);
}

.mj-aurora span:nth-child(2) {
    width: 600px;
    height: 600px;
    right: -220px;
    top: 260px;
    background: radial-gradient(circle, rgba(184, 134, 11, 0.16) 0%, rgba(184, 134, 11, 0) 65%);
}

.mj-aurora span:nth-child(3) {
    width: 380px;
    height: 380px;
    left: 38%;
    top: 200px;
    background: radial-gradient(circle, rgba(64, 170, 160, 0.1) 0%, rgba(64, 170, 160, 0) 65%);
}

.hero-wrapper-c > .row {
    position: relative;
    z-index: 1;
}

@keyframes mjDriftA { to { transform: translate(140px, 90px) scale(1.15); } }
@keyframes mjDriftB { to { transform: translate(-160px, -70px) scale(1.1); } }
@keyframes mjBreathe {
    0%, 100% { transform: scale(0.85); opacity: 0.7; }
    50% { transform: scale(1.2); opacity: 1; }
}

.mj-motion .mj-aurora span { will-change: transform; }
.mj-motion .mj-aurora span:nth-child(1) { animation: mjDriftA 26s ease-in-out infinite alternate; }
.mj-motion .mj-aurora span:nth-child(2) { animation: mjDriftB 32s ease-in-out infinite alternate; }
.mj-motion .mj-aurora span:nth-child(3) { animation: mjBreathe 9s ease-in-out infinite; }

/* ---------- Hero: hand-drawn line under "liniște" ---------- */

.mj-ink {
    position: relative;
    display: inline-block;
}

.mj-ink svg {
    position: absolute;
    left: -2%;
    bottom: -0.18em;
    width: 104%;
    height: 0.42em;
    overflow: visible;
    pointer-events: none;
}

.mj-ink path {
    fill: none;
    stroke: var(--color-primary, #008080);
    stroke-width: 5;
    stroke-linecap: round;
    opacity: 0.55;
}

@keyframes mjInk { to { stroke-dashoffset: 0; } }

.mj-motion .mj-ink path {
    stroke-dasharray: 1;
    stroke-dashoffset: 1;
    animation: mjInk 1.3s cubic-bezier(0.65, 0, 0.35, 1) 1.15s forwards;
}

/* ---------- CNAS steps: a path from 1 to 2 to 3 ---------- */

/* The track joins the step numbers. It only shows when the three cards sit in
   one row or one column; the two-plus-one tablet layout has no clean path. */
.cas-steps-row {
    position: relative;
    container-type: inline-size;
}

.cas-step-card {
    position: relative;
    z-index: 1;
}

.mj-steps-track {
    display: none;
    position: absolute;
    z-index: 0;
    border-radius: 3px;
    background: rgba(0, 128, 128, 0.12);
    pointer-events: none;
}

.mj-steps-track i {
    position: absolute;
    inset: 0;
    border-radius: inherit;
    background: linear-gradient(90deg, var(--color-secondary-dark, #8B6508), var(--color-primary, #008080));
}

@container (min-width: 730px) {
    .mj-steps-track {
        display: block;
        left: 2.375rem;
        right: 2.375rem;
        top: calc(2.525rem - 1.5px);
        height: 3px;
    }
    .mj-steps-track i { transform-origin: 0 50%; }
}

@container (max-width: 479.98px) {
    .mj-steps-track {
        display: block;
        left: calc(2.375rem - 1.5px);
        top: 2.5rem;
        bottom: 2.5rem;
        width: 3px;
    }
    .mj-steps-track i {
        transform-origin: 50% 0;
        background: linear-gradient(180deg, var(--color-secondary-dark, #8B6508), var(--color-primary, #008080));
    }
}

@keyframes mjStepGlow {
    from { box-shadow: 0 0 0 0 rgba(184, 134, 11, 0.45); }
    to { box-shadow: 0 0 0 14px rgba(184, 134, 11, 0); }
}

.mj-motion .mj-steps-track i {
    transform: scale(0);
    transition: transform 2.2s cubic-bezier(0.45, 0, 0.2, 1) 0.35s;
}

@container (min-width: 730px) {
    .mj-motion .mj-steps-track i { transform: scaleX(0); }
}

@container (max-width: 479.98px) {
    .mj-motion .mj-steps-track i { transform: scaleY(0); }
}

.mj-motion .cas-steps-row.is-walked .mj-steps-track i { transform: none; }

.mj-motion .cas-steps-row.is-walked .cas-step-num { animation: mjStepGlow 1.1s ease-out 0.3s both; }
.mj-motion .cas-steps-row.is-walked .cas-step-card:nth-child(3) .cas-step-num { animation-delay: 1.35s; }
.mj-motion .cas-steps-row.is-walked .cas-step-card:nth-child(4) .cas-step-num { animation-delay: 2.45s; }

/* ---------- "Un minut doar pentru tine" breathing card ---------- */

.mj-breathe {
    display: flex;
    align-items: center;
    gap: 2.25rem;
    background: #ffffff;
    border-radius: 20px;
    border: 1px solid rgba(0, 128, 128, 0.14);
    padding: 2rem 2.5rem;
    margin-bottom: 2.5rem;
    box-shadow: 0 10px 30px rgba(0, 0, 0, 0.035);
}

.mj-breathe-orb {
    position: relative;
    flex: 0 0 170px;
    height: 170px;
    display: grid;
    place-items: center;
}

.mj-breathe-orb::before,
.mj-breathe-orb::after {
    content: '';
    position: absolute;
    inset: 0;
    border-radius: 50%;
}

.mj-breathe-orb::before {
    background: radial-gradient(circle at 35% 35%, rgba(0, 160, 150, 0.55), rgba(0, 128, 128, 0.25) 60%, rgba(184, 134, 11, 0.18));
    scale: 0.55;
    transition: scale 4s cubic-bezier(0.45, 0, 0.55, 1), opacity 4s ease;
}

.mj-breathe-orb::after {
    border: 2px dashed rgba(0, 128, 128, 0.25);
}

.mj-breathe[data-phase="in"] .mj-breathe-orb::before,
.mj-breathe[data-phase="hold"] .mj-breathe-orb::before { scale: 1; }
.mj-breathe[data-phase="out"] .mj-breathe-orb::before { transition-duration: 6s; }

.mj-breathe-cue {
    position: relative;
    font-weight: 600;
    font-size: 1.05rem;
    color: var(--color-primary-dark, #006666);
}

.mj-breathe h2 {
    font-size: 1.5rem;
    font-weight: 700;
    color: var(--color-secondary-dark);
    margin-bottom: 0.4rem;
}

.mj-breathe-body > p {
    color: var(--color-text-medium);
    margin-bottom: 1rem;
}

.mj-breathe .mj-breathe-note {
    font-size: 0.88rem;
    margin: 0.9rem 0 0;
}

.mj-breathe-note a {
    color: var(--color-primary-dark);
    font-weight: 600;
}

@media (max-width: 767.98px) {
    .mj-breathe {
        flex-direction: column;
        text-align: center !important;
        gap: 1.25rem;
        padding: 1.75rem 1.25rem;
    }
    .mj-breathe-orb {
        flex-basis: 150px;
        width: 150px;
        height: 150px;
    }
}

/* Reduced motion: the circle brightens and dims instead of growing. */
@media (prefers-reduced-motion: reduce) {
    .mj-breathe-orb::before { scale: 1; opacity: 0.35; }
    .mj-breathe[data-phase="in"] .mj-breathe-orb::before,
    .mj-breathe[data-phase="hold"] .mj-breathe-orb::before { scale: 1; opacity: 1; }
}

/* ---------- Soft light that follows the pointer on cards ---------- */

@media (hover: hover) and (pointer: fine) {
    .mj-motion .booking-pathway-card,
    .mj-motion .specialty-grid-item {
        position: relative;
        isolation: isolate;
    }

    .mj-motion .booking-pathway-card::after,
    .mj-motion .specialty-grid-item::after {
        content: '';
        position: absolute;
        inset: 0;
        z-index: -1;
        border-radius: inherit;
        background: radial-gradient(360px circle at var(--mj-mx, 50%) var(--mj-my, 50%), rgba(0, 128, 128, 0.1), transparent 60%);
        opacity: 0;
        transition: opacity 0.4s ease;
        pointer-events: none;
    }

    .mj-motion .booking-pathway-card:hover::after,
    .mj-motion .specialty-grid-item:hover::after { opacity: 1; }
}

/* ---------- Soft fade between pages ---------- */

/* Same-origin navigations cross-fade (Chrome, Edge, Safari 18.2+; others just
   load normally). The navbar is named so it stays still while the page under
   it changes. */
@media (prefers-reduced-motion: no-preference) {
    @view-transition { navigation: auto; }

    .navbar { view-transition-name: mj-navbar; }

    ::view-transition-old(root) { animation: mjPageOut 0.22s ease both; }
    ::view-transition-new(root) { animation: mjPageIn 0.45s var(--mj-ease-out) both; }
}

@keyframes mjPageOut { to { opacity: 0; } }
@keyframes mjPageIn { from { opacity: 0; translate: 0 14px; } }

/* ---------- Reduced motion ---------- */

/* The card lifts, image zooms, theme-button spin and colour fades in
   app-style.css, base.html and site-dark.css predate .mj-motion and are not
   gated on it. For visitors who ask for reduced motion they now change state
   instantly. 0s rather than 1ms keeps Bootstrap's collapse and modal on the
   same no-wait path its own reduced-motion rules use. Animations are left
   alone so loading spinners keep turning. */
@media (prefers-reduced-motion: reduce) {
    *,
    *::before,
    *::after {
        transition-duration: 0s !important;
        transition-delay: 0s !important;
    }
}

@media print {
    .mj-motion [data-reveal],
    .mj-motion [data-reveal-item],
    .mj-motion .animate-on-scroll,
    .mj-motion .section-wrapper-c.animate-on-scroll > *,
    .mj-motion [data-page-header] > *,
    .mj-motion [data-reveal-item] .specialty-icon-circle,
    .mj-motion [data-reveal-item] .cas-step-num,
    .mj-motion .animate-on-scroll .cas-step-num {
        opacity: 1 !important;
        translate: none !important;
        scale: none !important;
    }

    .mj-scroll-progress {
        display: none;
    }

    .mj-motion .mj-ink path,
    .mj-motion .mj-steps-track i {
        stroke-dashoffset: 0 !important;
        transform: none !important;
    }
}
