/* =========================================================
   components.css
   Reusable UI components: buttons, keypad, password display,
   flower section, cards. Keep component styles scoped to a
   single class so they can be reused across pages.
   ========================================================= */

/* ---- Illustration wrapper (used on any page with a hero image) ---- */
.illustration {
    width: var(--hero-size);
    height: var(--hero-size);
    display: flex;
    align-items: center;
    justify-content: center;
}

.illustration img,
.illustration svg {
    width: 100%;
    height: 100%;
}

/* ---- Password display: a row of dots ---- */
.password-display {
    display: flex;
    justify-content: center;
    gap: var(--space-sm);
}

.password-dot {
    width: 16px;
    height: 16px;
    border-radius: var(--radius-round);
    background-color: var(--color-surface);
    border: 2px solid var(--color-primary);
    transition: background-color var(--transition-fast), border-color var(--transition-fast);
}

.password-dot.is-filled {
    background-color: var(--color-primary);
    animation: dotPop 260ms cubic-bezier(0.34, 1.56, 0.64, 1);
}

@keyframes dotPop {
    0% { transform: scale(0.6); }
    55% { transform: scale(1.35); }
    100% { transform: scale(1.1); }
}

/* Shake feedback for a wrong password */
.password-display.is-shaking {
    animation: shake 420ms ease;
}

.password-display.is-shaking .password-dot.is-filled {
    border-color: var(--color-error);
    background-color: var(--color-error);
}

@keyframes shake {
    10%, 90% { transform: translateX(-2px); }
    20%, 80% { transform: translateX(4px); }
    30%, 50%, 70% { transform: translateX(-8px); }
    40%, 60% { transform: translateX(8px); }
}

/* Lock illustration reacts alongside the dots: a little headshake
   on wrong password, a relieved bounce+spin on the correct one. */
.illustration.is-shaking {
    animation: shake 420ms ease;
}

.illustration.is-unlocked {
    animation: lockBounce 550ms cubic-bezier(0.34, 1.56, 0.64, 1);
}

@keyframes lockBounce {
    0% { transform: scale(1) rotate(0deg); }
    35% { transform: scale(1.18) rotate(-8deg); }
    65% { transform: scale(0.96) rotate(4deg); }
    100% { transform: scale(1.06) rotate(0deg); }
}

/* Feedback message under the password display (no browser alerts) */
.password-feedback {
    min-height: 1.4em;
    font-size: 0.9rem;
    color: var(--color-error);
    opacity: 0;
    transition: opacity var(--transition-fast);
}

.password-feedback.is-visible {
    opacity: 1;
}

/* ---- Numeric keypad ----
   Keys are a fixed, viewport-height-aware size (--keypad-key-size)
   rather than stretched to fill the container width. This is what
   keeps the digits from growing huge on wide/short screens and
   pushing the page taller than the viewport. */
.keypad {
    display: grid;
    grid-template-columns: repeat(3, var(--keypad-key-size));
    grid-auto-rows: var(--keypad-key-size);
    gap: var(--keypad-gap);
    justify-content: center;
}

.keypad-key {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
    background-color: var(--color-surface);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-softer);
    font-family: var(--font-display);
    font-size: clamp(1rem, 3.4dvh, 1.35rem);
    color: var(--color-text);
    transition: transform var(--transition-fast), box-shadow var(--transition-fast);
}

.keypad-key:hover {
    box-shadow: var(--shadow-soft);
}

.keypad-key:active,
.keypad-key.is-pressed {
    transform: scale(0.92);
}

.keypad-key--action {
    background-color: var(--color-surface);
    box-shadow: var(--shadow-softer);
    color: var(--color-muted);
}

.keypad-key--action:hover {
    box-shadow: var(--shadow-soft);
    color: var(--color-error);
}

.keypad-key--action:active,
.keypad-key--action.is-pressed {
    color: var(--color-error);
}

.keypad-key__icon {
    display: block;
    width: clamp(18px, 3.4dvh, 24px);
    height: clamp(18px, 3.4dvh, 24px);
    transition: transform var(--transition-fast);
}

.keypad-key--action:active .keypad-key__icon,
.keypad-key--action.is-pressed .keypad-key__icon {
    transform: translateX(-2px);
}

/* Empty grid cell so the "0" key stays visually centered under
   the 8, matching a familiar phone-keypad layout now that there's
   no confirm key on the last row. */
.keypad-spacer {
    width: var(--keypad-key-size);
    height: var(--keypad-key-size);
}

/* Soft circular ripple dropped in at the tap point by password.js.
   Removed automatically once its animation ends. */
.keypad-ripple {
    position: absolute;
    width: 12px;
    height: 12px;
    border-radius: var(--radius-round);
    background-color: var(--color-primary);
    opacity: 0.35;
    pointer-events: none;
    transform: translate(-50%, -50%) scale(0);
    animation: rippleOut 480ms ease-out forwards;
}

.keypad-key--action .keypad-ripple {
    background-color: var(--color-muted);
    opacity: 0.25;
}

@keyframes rippleOut {
    to {
        transform: translate(-50%, -50%) scale(9);
        opacity: 0;
    }
}

/* ---- Buttons ---- */
.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-xs);
    padding: 14px 32px;
    border-radius: var(--radius-lg);
    font-family: var(--font-display);
    font-weight: 500;
    font-size: 1rem;
    transition: transform var(--transition-fast), box-shadow var(--transition-fast);
}

.btn-primary {
    background-color: var(--color-primary);
    color: var(--color-surface);
    box-shadow: var(--shadow-softer);
}

.btn-primary:hover {
    box-shadow: var(--shadow-soft);
    transform: translateY(-1px);
}

.btn-primary:active {
    transform: translateY(0);
}

/* ---- Flower / bouquet section ---- */
.flower-bouquet {
    width: 100%;
    max-width: 280px;
}

/* ---- Placeholder page card (page3 and future pages) ---- */
.placeholder-card {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--space-sm);
    color: var(--color-muted);
}

/* Gentle continuous float, used on hero illustrations */
.is-floating {
    animation: floatY 4s ease-in-out infinite;
}

@keyframes floatY {
    0%, 100% { transform: translateY(0); }
    50% { transform: translateY(-8px); }
}

/* ---- Generic entrance animation hook ----
   Elements start hidden via this class; animations.js
   removes it (or adds .is-visible) to trigger a fade/slide in. */
.fade-in-element {
    opacity: 0;
}

.fade-in-element.is-visible {
    animation: fadeSlideUp var(--transition-slow) forwards;
}

@keyframes fadeSlideUp {
    from {
        opacity: 0;
        transform: translateY(16px);
    }
    to {
        opacity: 1;
        transform: translateY(0);
    }
}

/* Whole-page fade used briefly by navigation.js just before
   leaving for another page. */
body.is-page-leaving .page {
    opacity: 0;
    transition: opacity var(--transition-normal);
}

/* Success unlock animation on the whole password page content */
.is-unlocking {
    animation: unlockOut var(--transition-slow) forwards;
}

@keyframes unlockOut {
    from {
        opacity: 1;
        transform: scale(1);
    }
    to {
        opacity: 0;
        transform: scale(1.05);
    }
}

/* ---- Heart burst (correct password) ----
   A fixed, full-viewport, click-through layer that password.js
   fills with a handful of little hearts, then clears once they've
   finished floating up and fading out. */
.heart-burst {
    position: fixed;
    inset: 0;
    pointer-events: none;
    overflow: hidden;
    z-index: 20;
}

.heart-burst-piece {
    position: absolute;
    bottom: 8%;
    font-size: var(--heart-size, 20px);
    color: var(--color-primary);
    opacity: 0;
    animation: heartFloat 1100ms ease-out forwards;
    animation-delay: var(--heart-delay, 0ms);
}

@keyframes heartFloat {
    0% {
        opacity: 0;
        transform: translateY(0) scale(0.6) rotate(var(--heart-rotate, 0deg));
    }
    15% {
        opacity: 1;
    }
    100% {
        opacity: 0;
        transform: translateY(-60vh) scale(1) rotate(var(--heart-rotate, 0deg));
    }
}
