🎮ArcadeLab

🌾 Granja Épica - Animales permanentes

by RapidFalcon68
1921 lines76.0 KB
▶ Play
<!DOCTYPE html>
<html lang="es">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>🌾 Granja Épica - Animales permanentes</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
            font-family: 'Segoe UI', Roboto, system-ui, sans-serif;
            user-select: none;
        }
        body {
            background: linear-gradient(145deg, #1f3a1f, #0f2a0f);
            min-height: 100vh;
            display: flex;
            justify-content: center;
            align-items: center;
            padding: 12px;
        }
        #app {
            max-width: 1200px;
            width: 100%;
            background: #4a6b3a;
            background-image: radial-gradient(circle at 20% 30%, #5f824a, #2f4a22);
            border-radius: 48px 48px 32px 32px;
            padding: 20px 24px 24px 24px;
            box-shadow: 0 20px 40px rgba(0, 0, 0, 0.8), inset 0 2px 4px rgba(255, 255, 200, 0.2);
            border: 2px solid #8aa87a;
        }
        header {
            display: flex;
            flex-wrap: wrap;
            justify-content: space-between;
            align-items: center;
            background: rgba(20, 30, 15, 0.8);
            backdrop-filter: blur(4px);
            padding: 10px 18px;
            border-radius: 60px;
            margin-bottom: 16px;
            border: 1px solid #b8d0a8;
            box-shadow: inset 0 2px 8px rgba(0, 0, 0, 0.5);
        }
        .stats {
            display: flex;
            gap: 10px;
            flex-wrap: wrap;
            font-weight: 700;
            font-size: 0.9rem;
            color: #f9f3d9;
            text-shadow: 0 2px 4px rgba(0, 0, 0, 0.5);
        }
        .stats span {
            display: flex;
            align-items: center;
            gap: 4px;
            background: rgba(0, 0, 0, 0.3);
            padding: 4px 12px 4px 8px;
            border-radius: 40px;
            border: 1px solid #b8d0a8;
            box-shadow: inset 0 1px 3px rgba(255, 255, 200, 0.15);
            font-size: 0.85rem;
            transition: 0.2s;
        }
        .stats span:hover {
            background: rgba(0, 0, 0, 0.5);
            transform: scale(1.02);
        }
        .selected-seed {
            display: flex;
            align-items: center;
            gap: 10px;
            background: rgba(0, 0, 0, 0.35);
            padding: 4px 18px 4px 14px;
            border-radius: 40px;
            color: #f9f3d9;
            font-weight: 600;
            font-size: 0.95rem;
            border: 1px solid #d4e8c4;
            box-shadow: inset 0 1px 4px rgba(255, 255, 200, 0.15);
            cursor: pointer;
            transition: 0.2s;
        }
        .selected-seed:hover {
            background: rgba(0, 0, 0, 0.5);
            border-color: #f5d742;
        }
        .selected-seed #selectedSeedDisplay {
            background: #2d3d1f;
            padding: 2px 16px 2px 12px;
            border-radius: 30px;
            font-size: 0.95rem;
            min-width: 80px;
            text-align: center;
            border: 1px solid #b8d0a8;
        }
        .tabs {
            display: flex;
            gap: 8px;
            margin-bottom: 14px;
            flex-wrap: wrap;
        }
        .tab-btn {
            background: rgba(30, 40, 20, 0.6);
            border: 2px solid #6d8f5a;
            color: #f9f3d9;
            font-weight: 700;
            padding: 8px 22px;
            border-radius: 40px;
            cursor: pointer;
            font-size: 0.9rem;
            transition: all 0.2s;
            box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.3);
            flex: 1 0 auto;
            text-align: center;
        }
        .tab-btn:hover {
            background: rgba(60, 80, 40, 0.7);
            border-color: #b8d0a8;
            transform: translateY(-2px);
        }
        .tab-btn.active {
            background: #4d7a3a;
            border-color: #f5d742;
            box-shadow: 0 0 20px #f5d74244, inset 0 -4px 0 #b8921a;
            transform: scale(1.02);
        }
        .tab-content {
            display: none;
            background: rgba(20, 30, 15, 0.5);
            backdrop-filter: blur(2px);
            padding: 16px 18px;
            border-radius: 32px;
            border: 1px solid #8aa87a;
            box-shadow: inset 0 2px 8px rgba(0, 0, 0, 0.3);
            margin-top: 4px;
            animation: fadeIn 0.3s ease;
        }
        .tab-content.active {
            display: block;
        }
        @keyframes fadeIn {
            0% {
                opacity: 0;
                transform: translateY(10px);
            }
            100% {
                opacity: 1;
                transform: translateY(0);
            }
        }
        #farm {
            display: grid;
            grid-template-columns: repeat(4, 1fr);
            gap: 12px;
            max-width: 600px;
            width: 100%;
            margin: 0 auto;
        }
        .plot {
            aspect-ratio: 1 / 1;
            background: #6b4f34;
            background-image: radial-gradient(circle at 30% 30%, #8b6b4a, #4d351f);
            border-radius: 20px;
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            font-size: 2.6rem;
            cursor: pointer;
            transition: transform 0.1s, box-shadow 0.3s, border-color 0.3s;
            border: 3px solid #4d351f;
            box-shadow: inset 0 -6px 0 #2f1f0e, 0 6px 10px rgba(0, 0, 0, 0.4);
            position: relative;
            min-height: 90px;
            color: #f9f3d9;
            text-shadow: 0 2px 4px rgba(0, 0, 0, 0.6);
        }
        .plot:active {
            transform: scale(0.93);
        }
        .plot.empty {
            background: #7a5d3e;
            background-image: radial-gradient(circle at 30% 30%, #9a7a56, #4d351f);
            color: #b8a080;
            font-size: 2.2rem;
        }
        .plot.growing {
            border-color: #7daa6a;
            box-shadow: inset 0 -6px 0 #2f5a1f, 0 0 12px #7daa6a88;
            animation: grow-pulse 2s infinite;
        }
        @keyframes grow-pulse {
            0%,
            100% {
                box-shadow: inset 0 -6px 0 #2f5a1f, 0 0 12px #7daa6a88;
            }
            50% {
                box-shadow: inset 0 -6px 0 #2f5a1f, 0 0 20px #7daa6abb;
            }
        }
        .plot.ready {
            border-color: #f5d742;
            box-shadow: inset 0 -6px 0 #b8921a, 0 0 20px #f5d742bb, 0 0 40px #f5d74255;
            animation: pulse-gold 1.2s infinite alternate;
        }
        .plot.plagued {
            border-color: #aa4444;
            box-shadow: inset 0 -6px 0 #6a2222, 0 0 20px #aa444488;
            animation: pulse-red 0.8s infinite alternate;
        }
        @keyframes pulse-gold {
            0% {
                box-shadow: inset 0 -6px 0 #b8921a, 0 0 20px #f5d742bb, 0 0 40px #f5d74244;
            }
            100% {
                box-shadow: inset 0 -6px 0 #b8921a, 0 0 30px #f5d742ee, 0 0 70px #f5d74277;
            }
        }
        @keyframes pulse-red {
            0% {
                box-shadow: inset 0 -6px 0 #6a2222, 0 0 20px #aa444488;
            }
            100% {
                box-shadow: inset 0 -6px 0 #6a2222, 0 0 40px #aa4444bb;
            }
        }
        .plot .emoji {
            line-height: 1;
            margin-bottom: 2px;
            font-size: 2.8rem;
            transition: transform 0.2s;
        }
        .plot.ready .emoji {
            animation: bounce-emoji 0.8s infinite alternate;
        }
        @keyframes bounce-emoji {
            0% {
                transform: translateY(0);
            }
            100% {
                transform: translateY(-10px);
            }
        }
        .plot .progress-wrap {
            width: 80%;
            height: 6px;
            background: rgba(0, 0, 0, 0.5);
            border-radius: 10px;
            overflow: hidden;
            margin-top: 2px;
            border: 1px solid #2f1f0e;
        }
        .plot .progress-bar {
            height: 100%;
            width: 0%;
            background: linear-gradient(90deg, #8bc34a, #cddc39);
            border-radius: 10px;
            transition: width 0.3s;
        }
        .plot .time-left {
            font-size: 0.6rem;
            font-weight: 700;
            background: rgba(0, 0, 0, 0.5);
            padding: 0 8px;
            border-radius: 12px;
            margin-top: 2px;
            color: #eee;
            letter-spacing: 0.5px;
        }
        .plot .harvest-icon {
            font-size: 1.2rem;
            margin-top: 2px;
            background: rgba(0, 0, 0, 0.3);
            padding: 0 8px;
            border-radius: 12px;
        }
        .plot .event-badge {
            position: absolute;
            top: -8px;
            right: -8px;
            font-size: 1.2rem;
            background: rgba(0, 0, 0, 0.7);
            border-radius: 50%;
            padding: 2px;
            line-height: 1;
            border: 1px solid gold;
        }
        #shop-container {
            display: flex;
            flex-wrap: wrap;
            gap: 24px 32px;
            justify-content: center;
        }
        #shop-container>div {
            flex: 1 1 220px;
            min-width: 180px;
        }
        #shop-container h4 {
            color: #f9f3d9;
            font-size: 1rem;
            text-transform: uppercase;
            letter-spacing: 2px;
            border-bottom: 2px solid #b8d0a8;
            padding-bottom: 6px;
            margin-bottom: 12px;
            text-shadow: 0 2px 4px rgba(0, 0, 0, 0.5);
        }
        .shop-item {
            display: flex;
            align-items: center;
            justify-content: space-between;
            background: rgba(0, 0, 0, 0.25);
            padding: 6px 12px 6px 10px;
            border-radius: 40px;
            margin-bottom: 8px;
            border: 1px solid #6d8f5a;
            transition: all 0.15s;
            cursor: pointer;
            gap: 4px;
            flex-wrap: wrap;
        }
        .shop-item:hover {
            background: rgba(0, 0, 0, 0.4);
            border-color: #b8d0a8;
            transform: scale(1.02);
        }
        .shop-item.active {
            border-color: #f5d742;
            background: rgba(245, 215, 66, 0.2);
            box-shadow: 0 0 16px #f5d74244;
        }
        .shop-item .info {
            display: flex;
            align-items: center;
            gap: 6px;
            color: #f9f3d9;
            font-weight: 600;
            font-size: 0.85rem;
            flex: 1;
        }
        .shop-item .info .emoji {
            font-size: 1.6rem;
        }
        .shop-item .info .count {
            background: rgba(0, 0, 0, 0.4);
            padding: 0 10px;
            border-radius: 30px;
            font-size: 0.7rem;
        }
        .shop-item .actions {
            display: flex;
            gap: 6px;
            align-items: center;
        }
        .shop-item .actions button {
            background: #3d5a2e;
            border: none;
            color: #f9f3d9;
            font-weight: 700;
            padding: 4px 14px;
            border-radius: 40px;
            cursor: pointer;
            font-size: 0.7rem;
            transition: 0.1s;
            border: 1px solid #6d8f5a;
            box-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
            white-space: nowrap;
        }
        .shop-item .actions button:active {
            transform: scale(0.92);
        }
        .shop-item .actions button.buy {
            background: #4d7a3a;
            border-color: #8bc34a;
        }
        .shop-item .actions button.buy:hover {
            background: #5d9a4a;
        }
        .shop-item .actions button.select {
            background: #5a6a4a;
            border-color: #b8d0a8;
        }
        .shop-item .actions button.select:hover {
            background: #7a9a6a;
        }
        .shop-item .actions button.owned {
            background: #2a3a2a;
            border-color: #6d8f5a;
            color: #aac09a;
            cursor: default;
        }
        .shop-item .actions button:disabled {
            opacity: 0.5;
            cursor: not-allowed;
        }
        .mission-list {
            display: flex;
            flex-direction: column;
            gap: 12px;
        }
        .mission-item {
            background: rgba(0, 0, 0, 0.35);
            border-radius: 30px;
            padding: 14px 18px;
            display: flex;
            align-items: center;
            justify-content: space-between;
            border-left: 6px solid #f5d742;
            flex-wrap: wrap;
            gap: 8px;
            transition: 0.2s;
        }
        .mission-item.completed {
            border-left-color: #8bc34a;
            opacity: 0.7;
        }
        .mission-item .desc {
            color: #f9f3d9;
            font-weight: 600;
            font-size: 0.9rem;
            flex: 2;
        }
        .mission-item .progress {
            color: #b8d0a8;
            font-size: 0.8rem;
            background: rgba(0, 0, 0, 0.3);
            padding: 2px 14px;
            border-radius: 30px;
            min-width: 60px;
            text-align: center;
        }
        .mission-item .reward {
            color: #f5d742;
            font-weight: 700;
            font-size: 0.85rem;
            padding: 2px 10px;
            background: rgba(0, 0, 0, 0.2);
            border-radius: 20px;
        }
        .mission-item .status {
            font-size: 1.2rem;
            min-width: 30px;
            text-align: center;
        }
        .animal-grid {
            display: grid;
            grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
            gap: 12px;
            margin-top: 8px;
        }
        .animal-card {
            background: rgba(0, 0, 0, 0.3);
            border-radius: 20px;
            padding: 12px;
            text-align: center;
            border: 2px solid #6d8f5a;
            transition: 0.2s;
        }
        .animal-card .animal-emoji {
            font-size: 2.8rem;
        }
        .animal-card .animal-name {
            color: #f9f3d9;
            font-weight: 600;
            font-size: 0.9rem;
        }
        .animal-card .animal-prod {
            color: #b8d0a8;
            font-size: 0.8rem;
            font-weight: 600;
        }
        .animal-card .animal-prod span {
            color: #f5d742;
        }
        .animal-card button {
            margin-top: 6px;
            background: #4d7a3a;
            border: none;
            color: #f9f3d9;
            font-weight: 700;
            padding: 4px 16px;
            border-radius: 40px;
            cursor: pointer;
            font-size: 0.7rem;
            border: 1px solid #8bc34a;
            transition: 0.1s;
        }
        .animal-card button:active {
            transform: scale(0.92);
        }
        .animal-card button:disabled {
            opacity: 0.5;
            cursor: not-allowed;
        }
        .animal-card .animal-timer {
            font-size: 0.7rem;
            color: #f9f3d9;
            background: rgba(0, 0, 0, 0.3);
            padding: 2px 8px;
            border-radius: 20px;
            display: inline-block;
            margin-top: 4px;
        }
        .achievement-grid {
            display: grid;
            grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
            gap: 12px;
        }
        .achievement-card {
            background: rgba(0, 0, 0, 0.3);
            border-radius: 20px;
            padding: 12px;
            text-align: center;
            border: 2px solid #4d6a3a;
            transition: 0.2s;
        }
        .achievement-card.unlocked {
            border-color: #f5d742;
            background: rgba(245, 215, 66, 0.1);
            box-shadow: 0 0 20px #f5d74233;
        }
        .achievement-card .ach-emoji {
            font-size: 2.5rem;
        }
        .achievement-card .ach-name {
            color: #f9f3d9;
            font-weight: 600;
            font-size: 0.85rem;
        }
        .achievement-card .ach-desc {
            color: #b8d0a8;
            font-size: 0.65rem;
        }
        .achievement-card .ach-status {
            font-size: 0.75rem;
            margin-top: 4px;
        }
        .event-banner {
            background: rgba(0, 0, 0, 0.5);
            border-radius: 40px;
            padding: 8px 20px;
            text-align: center;
            color: #f9f3d9;
            font-weight: 700;
            font-size: 0.9rem;
            border: 2px solid #f5d742;
            margin-bottom: 12px;
            display: flex;
            align-items: center;
            justify-content: center;
            gap: 12px;
            flex-wrap: wrap;
            animation: glow-banner 1.5s infinite alternate;
        }
        @keyframes glow-banner {
            0% {
                box-shadow: 0 0 10px #f5d74244;
            }
            100% {
                box-shadow: 0 0 30px #f5d74288;
            }
        }
        .event-banner .timer {
            background: rgba(0, 0, 0, 0.4);
            padding: 2px 14px;
            border-radius: 40px;
            font-family: monospace;
            font-size: 1rem;
        }
        .prestige-section {
            margin-top: 16px;
            padding: 14px;
            background: rgba(0, 0, 0, 0.4);
            border-radius: 30px;
            text-align: center;
            border: 2px solid #f5d742;
            transition: 0.3s;
        }
        .prestige-section:hover {
            box-shadow: 0 0 30px #f5d74233;
        }
        .prestige-info {
            color: #f9f3d9;
            font-weight: 600;
            margin-bottom: 8px;
            font-size: 0.9rem;
        }
        .prestige-info .highlight {
            color: #f5d742;
        }
        .prestige-progress {
            width: 100%;
            height: 8px;
            background: rgba(0, 0, 0, 0.4);
            border-radius: 10px;
            overflow: hidden;
            margin: 6px 0 10px 0;
            border: 1px solid #6d8f5a;
        }
        .prestige-progress .bar {
            height: 100%;
            background: linear-gradient(90deg, #f5d742, #f5a742);
            border-radius: 10px;
            transition: width 0.3s;
            width: 0%;
        }
        .prestige-section button {
            background: #7a4a3a;
            border: none;
            color: #f9f3d9;
            font-weight: 700;
            padding: 10px 30px;
            border-radius: 40px;
            cursor: pointer;
            font-size: 1rem;
            border: 2px solid #b8921a;
            box-shadow: 0 4px 8px rgba(0, 0, 0, 0.4);
            transition: 0.15s;
        }
        .prestige-section button:active {
            transform: scale(0.94);
        }
        .prestige-section button:not(:disabled):hover {
            background: #9a5a4a;
            border-color: #f5d742;
            box-shadow: 0 0 30px #f5d74255;
        }
        #notification {
            position: fixed;
            top: 20px;
            left: 50%;
            transform: translateX(-50%);
            background: rgba(20, 30, 10, 0.95);
            backdrop-filter: blur(6px);
            padding: 12px 28px;
            border-radius: 60px;
            color: #f9f3d9;
            font-weight: 700;
            font-size: 1.1rem;
            border: 2px solid #f5d742;
            box-shadow: 0 10px 30px rgba(0, 0, 0, 0.8);
            pointer-events: none;
            opacity: 0;
            transition: opacity 0.3s ease, transform 0.3s ease;
            transform: translateX(-50%) translateY(-20px);
            z-index: 999;
            white-space: nowrap;
        }
        #notification.show {
            opacity: 1;
            transform: translateX(-50%) translateY(0);
        }
        @media (max-width: 750px) {
            #app {
                padding: 12px;
            }
            header {
                flex-direction: column;
                align-items: stretch;
                gap: 8px;
                padding: 10px;
            }
            .stats {
                justify-content: center;
                font-size: 0.8rem;
                gap: 6px;
            }
            .selected-seed {
                justify-content: center;
                font-size: 0.85rem;
            }
            #farm {
                gap: 8px;
                padding: 8px;
            }
            .plot {
                font-size: 2rem;
                min-height: 70px;
            }
            .plot .emoji {
                font-size: 2.2rem;
            }
            .tab-btn {
                font-size: 0.75rem;
                padding: 6px 12px;
                flex: 1;
            }
            #shop-container {
                flex-direction: column;
                gap: 12px;
            }
            #shop-container>div {
                flex: 1 1 auto;
            }
            .shop-item {
                padding: 4px 8px;
                font-size: 0.75rem;
            }
            .mission-item {
                padding: 8px 12px;
                font-size: 0.75rem;
            }
            #notification {
                font-size: 0.9rem;
                padding: 8px 16px;
                top: 8px;
                white-space: normal;
                max-width: 90%;
            }
            .animal-grid {
                grid-template-columns: repeat(auto-fill, minmax(130px, 1fr));
            }
        }
        @media (max-width: 450px) {
            #farm {
                gap: 5px;
                padding: 4px;
            }
            .plot {
                min-height: 55px;
                font-size: 1.6rem;
                border-radius: 14px;
            }
            .plot .emoji {
                font-size: 1.8rem;
            }
            .plot .time-left {
                font-size: 0.5rem;
            }
            .achievement-grid {
                grid-template-columns: repeat(auto-fill, minmax(110px, 1fr));
            }
        }
        ::-webkit-scrollbar {
            width: 8px;
        }
        ::-webkit-scrollbar-track {
            background: rgba(0, 0, 0, 0.2);
            border-radius: 10px;
        }
        ::-webkit-scrollbar-thumb {
            background: #6d8f5a;
            border-radius: 10px;
        }
        ::-webkit-scrollbar-thumb:hover {
            background: #8aa87a;
        }
    </style>
</head>
<body>

    <div id="notification"></div>

    <div id="app">
        <header>
            <div class="stats">
                <span>🪙 <span id="moneyDisplay">100</span></span>
                <span>⭐ Nivel <span id="levelDisplay">1</span></span>
                <span>🌾 <span id="harvestDisplay">0</span></span>
                <span>🏆 <span id="achCountDisplay">0</span></span>
                <span>🔁 Prestigio <span id="prestigeDisplay">0</span></span>
                <span>📈 x<span id="multiplierDisplay">1.00</span></span>
            </div>
            <div class="selected-seed" id="selectedSeedContainer">
                🌱 Semilla:
                <span id="selectedSeedDisplay">Ninguna</span>
            </div>
        </header>

        <div class="tabs">
            <button class="tab-btn active" data-tab="tab-farm">🌾 Granja</button>
            <button class="tab-btn" data-tab="tab-shop">🛒 Tienda</button>
            <button class="tab-btn" data-tab="tab-animals">🐄 Animales</button>
            <button class="tab-btn" data-tab="tab-missions">📜 Misiones</button>
            <button class="tab-btn" data-tab="tab-achievements">🏅 Logros</button>
        </div>

        <div id="tab-farm" class="tab-content active">
            <div id="eventBanner" class="event-banner" style="display:none;"></div>
            <div id="farm"></div>
            <div class="prestige-section">
                <div class="prestige-info">
                    🔁 <span class="highlight">Prestigio</span> · Requiere nivel <span id="prestigeReqLevel">8</span> y <span id="prestigeReqMoney">800</span>🪙 disponibles (actual: nivel <span id="prestigeCurLevel">1</span>, <span id="prestigeCurMoney">100</span>🪙)
                    <div class="prestige-progress"><div class="bar" id="prestigeProgressBar" style="width:0%"></div></div>
                </div>
                <button id="prestigeBtn">✨ Reiniciar con prestigio (+10% ventas)</button>
            </div>
        </div>

        <div id="tab-shop" class="tab-content">
            <div id="shop-container">
                <div class="seeds-section">
                    <h4>🌿 Semillas</h4>
                    <div id="seedShop"></div>
                </div>
                <div class="upgrades-section">
                    <h4>⚡ Mejoras</h4>
                    <div id="upgradeShop"></div>
                </div>
                <div class="special-section">
                    <h4>🌟 Especiales</h4>
                    <div id="specialShop"></div>
                </div>
            </div>
        </div>

        <div id="tab-animals" class="tab-content">
            <h4 style="color:#f9f3d9; margin-bottom:12px;">🐄 Animales de granja (ingresos pasivos)</h4>
            <div id="animalShop" class="animal-grid"></div>
            <div style="margin-top:16px; color:#b8d0a8; font-size:0.8rem; text-align:center;">Los animales generan ingresos cada cierto tiempo. ¡Recógelos!</div>
        </div>

        <div id="tab-missions" class="tab-content">
            <div id="missionList" class="mission-list"></div>
        </div>

        <div id="tab-achievements" class="tab-content">
            <div id="achievementGrid" class="achievement-grid"></div>
        </div>
    </div>

    <script>
        // ============================================================
        //  ESTADO DEL JUEGO (v6.2 - Animales permanentes)
        // ============================================================
        const SEED_TYPES = ['carrot', 'tomato', 'wheat', 'corn', 'strawberry', 'pumpkin'];

        const state = {
            money: 100,
            level: 1,
            harvestCount: 0,
            totalEarned: 0,
            prestigeLevel: 0,
            selectedSeed: null,
            seeds: {
                carrot: { name: 'Zanahoria', cost: 5, growTime: 4, sellPrice: 8, emoji: '🥕', count: 0 },
                tomato: { name: 'Tomate', cost: 15, growTime: 7, sellPrice: 22, emoji: '🍅', count: 0 },
                wheat: { name: 'Trigo', cost: 35, growTime: 14, sellPrice: 55, emoji: '🌾', count: 0 },
                corn: { name: 'Maíz', cost: 80, growTime: 20, sellPrice: 120, emoji: '🌽', count: 0 },
                strawberry: { name: 'Fresa', cost: 25, growTime: 6, sellPrice: 38, emoji: '🍓', count: 0 },
                pumpkin: { name: 'Calabaza', cost: 70, growTime: 18, sellPrice: 110, emoji: '🎃', count: 0 }
            },
            upgrades: {
                irrigation: { name: 'Riego Automático', cost: 60, owned: false, desc: '⏱️ -20% tiempo' },
                fertilizer: { name: 'Fertilizante', cost: 120, owned: false, desc: '💰 +30% venta' },
                harvester: { name: 'Cosechadora', cost: 220, owned: false, desc: '🎲 20% doble' },
                scarecrow: { name: 'Espantapájaros', cost: 150, owned: false, desc: '🛡️ -50% plagas' },
                greenhouse: { name: 'Invernadero', cost: 350, owned: false, desc: '🌱 +20% velocidad' }
            },
            specialUpgrades: {
                goldenShovel: { name: 'Pala Dorada', cost: 500, owned: false, desc: '✨ +10% cosecha extra' },
                seedMaker: { name: 'Fábrica de Semillas', cost: 800, owned: false, desc: '🌱 +1 semilla por compra' },
                luckyClover: { name: 'Trébol de la Suerte', cost: 1200, owned: false, desc: '🍀 +5% doble cosecha' }
            },
            animals: {
                cow: { name: 'Vaca', emoji: '🐄', cost: 300, income: 45, interval: 8, count: 0, timer: 0,
                    produces: '🥛' },
                chicken: { name: 'Gallina', emoji: '🐔', cost: 150, income: 25, interval: 6, count: 0, timer: 0,
                    produces: '🥚' },
                sheep: { name: 'Oveja', emoji: '🐑', cost: 500, income: 70, interval: 12, count: 0, timer: 0,
                    produces: '🧶' }
            },
            plots: Array(16).fill().map(() => ({
                state: 'empty',
                seedType: null,
                timeLeft: 0,
                totalTime: 0,
                plagued: false
            })),
            activeEvent: null,
            missions: [],
            achievements: {
                firstHarvest: { name: 'Primera Cosecha', emoji: '🌱', desc: 'Cosecha tu primer cultivo', unlocked: false },
                harvest100: { name: 'Cosechador', emoji: '🧑‍🌾', desc: 'Cosecha 100 cultivos', unlocked: false },
                harvest1000: { name: 'Super Cosechador', emoji: '🚜', desc: 'Cosecha 1000 cultivos', unlocked: false },
                money1000: { name: 'Rico', emoji: '💰', desc: 'Gana 1000 monedas en total', unlocked: false },
                allSeeds: { name: 'Coleccionista', emoji: '🌿', desc: 'Compra al menos 1 de cada semilla', unlocked: false },
                fullUpgrades: { name: 'Granjero Pro', emoji: '🏆', desc: 'Compra todas las mejoras básicas', unlocked: false },
                level10: { name: 'Experto', emoji: '⭐', desc: 'Alcanza el nivel 10', unlocked: false },
                prestige1: { name: 'Renacido', emoji: '🔁', desc: 'Realiza tu primer prestigio', unlocked: false },
                specialUpgrades: { name: 'Leyenda', emoji: '🌟', desc: 'Compra todas las mejoras especiales', unlocked: false },
                money10000: { name: 'Magnate', emoji: '💎', desc: 'Gana 10000 monedas en total', unlocked: false },
                firstAnimal: { name: 'Granjero Animal', emoji: '🐄', desc: 'Compra tu primer animal', unlocked: false },
                allAnimals: { name: 'Zoológico', emoji: '🐾', desc: 'Tiene al menos 1 de cada animal', unlocked: false }
            },
            seedsBought: new Set(),
            totalPlanted: 0,
            totalHarvested: 0,
            totalMoneyEarned: 0,
            missionStats: {
                totalHarvests: 0,
                totalPlants: 0,
                totalMoney: 0,
                totalUpgrades: 0,
                totalAnimals: 0,
                maxHarvestInOne: 0
            }
        };

        // ============================================================
        //  REFERENCIAS DOM
        // ============================================================
        const farmEl = document.getElementById('farm');
        const moneyDisplay = document.getElementById('moneyDisplay');
        const levelDisplay = document.getElementById('levelDisplay');
        const harvestDisplay = document.getElementById('harvestDisplay');
        const achCountDisplay = document.getElementById('achCountDisplay');
        const prestigeDisplay = document.getElementById('prestigeDisplay');
        const multiplierDisplay = document.getElementById('multiplierDisplay');
        const selectedSeedDisplay = document.getElementById('selectedSeedDisplay');
        const seedShopEl = document.getElementById('seedShop');
        const upgradeShopEl = document.getElementById('upgradeShop');
        const specialShopEl = document.getElementById('specialShop');
        const animalShopEl = document.getElementById('animalShop');
        const missionListEl = document.getElementById('missionList');
        const achievementGridEl = document.getElementById('achievementGrid');
        const eventBannerEl = document.getElementById('eventBanner');
        const notificationEl = document.getElementById('notification');
        const prestigeBtn = document.getElementById('prestigeBtn');
        const prestigeReqLevel = document.getElementById('prestigeReqLevel');
        const prestigeReqMoney = document.getElementById('prestigeReqMoney');
        const prestigeCurLevel = document.getElementById('prestigeCurLevel');
        const prestigeCurMoney = document.getElementById('prestigeCurMoney');
        const prestigeProgressBar = document.getElementById('prestigeProgressBar');
        let notifTimeout = null;

        // ============================================================
        //  REQUISITOS DE PRESTIGIO
        // ============================================================
        function getPrestigeRequirements() {
            const level = 8 + state.prestigeLevel * 4;
            const money = 800 + state.prestigeLevel * 800;
            return { level, money };
        }

        // ============================================================
        //  FUNCIONES AUXILIARES
        // ============================================================
        function notify(msg, duration = 1800) {
            notificationEl.textContent = msg;
            notificationEl.classList.add('show');
            clearTimeout(notifTimeout);
            notifTimeout = setTimeout(() => {
                notificationEl.classList.remove('show');
            }, duration);
        }

        function getGrowTimeMultiplier() {
            let m = 1;
            if (state.upgrades.irrigation.owned) m *= 0.8;
            if (state.upgrades.greenhouse.owned) m *= 0.8;
            if (state.activeEvent && state.activeEvent.type === 'rain') m *= 0.5;
            return Math.max(0.2, m);
        }

        function getSellPriceMultiplier() {
            let m = 1;
            if (state.upgrades.fertilizer.owned) m *= 1.3;
            m *= (1 + (state.level - 1) * 0.08);
            m *= (1 + state.prestigeLevel * 0.10);
            if (state.activeEvent && state.activeEvent.type === 'market') m *= 1.4;
            return m;
        }

        function getDoubleChance() {
            let chance = state.upgrades.harvester.owned ? 0.20 : 0.05;
            if (state.specialUpgrades.luckyClover.owned) chance += 0.05;
            return chance;
        }

        function getExtraHarvestBonus() {
            return state.specialUpgrades.goldenShovel.owned ? 0.10 : 0;
        }

        function getPlagueChance() {
            let base = 0.10;
            if (state.upgrades.scarecrow.owned) base *= 0.5;
            if (state.activeEvent && state.activeEvent.type === 'plague') base += 0.4;
            return Math.min(base, 0.6);
        }

        function getSeedCount(seedType) { return state.seeds[seedType].count; }

        function addSeed(seedType, n = 1) {
            state.seeds[seedType].count += n;
            if (state.specialUpgrades.seedMaker.owned && n > 0) {
                state.seeds[seedType].count += 1;
            }
        }

        function removeSeed(seedType, n = 1) {
            if (state.seeds[seedType].count >= n) {
                state.seeds[seedType].count -= n;
                return true;
            }
            return false;
        }

        function getEffectiveGrowTime(seedType) {
            return Math.max(1, Math.ceil(state.seeds[seedType].growTime * getGrowTimeMultiplier()));
        }

        function getEffectiveSellPrice(seedType) {
            return Math.floor(state.seeds[seedType].sellPrice * getSellPriceMultiplier());
        }

        // ============================================================
        //  LÓGICA DEL JUEGO
        // ============================================================
        function plantSeed(plotIndex) {
            const plot = state.plots[plotIndex];
            if (plot.state !== 'empty') return false;
            if (!state.selectedSeed) { notify('🌱 Selecciona una semilla primero'); return false; }
            const seedType = state.selectedSeed;
            if (getSeedCount(seedType) <= 0) { notify('❌ No tienes semillas de ' + state.seeds[seedType].name); return false; }
            if (!removeSeed(seedType, 1)) return false;

            let plagued = Math.random() < getPlagueChance();

            plot.state = 'growing';
            plot.seedType = seedType;
            plot.totalTime = getEffectiveGrowTime(seedType);
            plot.timeLeft = plot.totalTime;
            plot.plagued = plagued;

            state.totalPlanted += 1;
            state.missionStats.totalPlants += 1;

            renderFarm();
            renderShop();
            notify('🌱 Plantaste ' + state.seeds[seedType].name + (plagued ? ' ⚠️ (con plaga)' : ''));
            updateMissions('plant', 1);
            return true;
        }

        function harvestPlot(plotIndex) {
            const plot = state.plots[plotIndex];
            if (plot.state !== 'ready') return false;
            const seedType = plot.seedType;
            if (plot.plagued) {
                plot.state = 'empty';
                plot.seedType = null;
                plot.timeLeft = 0;
                plot.totalTime = 0;
                plot.plagued = false;
                notify('🐛 ¡La plaga arruinó la cosecha!', 1500);
                renderFarm();
                return false;
            }

            let price = getEffectiveSellPrice(seedType);
            let doubleHarvest = false;
            if (Math.random() < getDoubleChance()) {
                price *= 2;
                doubleHarvest = true;
            }
            let extra = 0;
            if (Math.random() < getExtraHarvestBonus()) {
                extra = Math.floor(price * 0.3);
                price += extra;
            }

            state.money += price;
            state.totalEarned += price;
            state.harvestCount += 1;
            state.totalHarvested += 1;
            state.totalMoneyEarned += price;
            state.missionStats.totalHarvests += 1;
            state.missionStats.totalMoney += price;
            if (price > state.missionStats.maxHarvestInOne) {
                state.missionStats.maxHarvestInOne = price;
            }

            const newLevel = Math.floor(state.harvestCount / 8) + 1;
            if (newLevel > state.level) {
                state.level = newLevel;
                notify('🎉 ¡Subiste al nivel ' + state.level + '! +8% de venta');
                checkAchievements();
                updatePrestigeInfo();
            }

            plot.state = 'empty';
            plot.seedType = null;
            plot.timeLeft = 0;
            plot.totalTime = 0;
            plot.plagued = false;

            let msg = '💰 Cosechaste ' + price + ' 🪙';
            if (doubleHarvest) msg += ' (¡DOBLE!)';
            if (extra > 0) msg += ' (+' + extra + ' extra)';
            notify(msg);
            renderFarm();
            renderShop();
            updateStats();
            checkAchievements();
            updateMissions('harvest', 1, seedType);
            updateMissions('money', price);
            return true;
        }

        // ============================================================
        //  ANIMALES
        // ============================================================
        function buyAnimal(animalKey) {
            const animal = state.animals[animalKey];
            if (state.money < animal.cost) { notify('❌ Dinero insuficiente'); return; }
            state.money -= animal.cost;
            animal.count += 1;
            animal.timer = animal.interval;
            state.missionStats.totalAnimals += 1;
            updateMissions('animal', 1);
            renderAnimals();
            renderShop();
            updateStats();
            checkAchievements();
            notify('🐄 Compraste un ' + animal.name);
            saveGame();
        }

        function tickAnimals() {
            for (const key of Object.keys(state.animals)) {
                const animal = state.animals[key];
                if (animal.count > 0) {
                    animal.timer -= 1;
                    if (animal.timer <= 0) {
                        const income = Math.floor(animal.income * animal.count * (1 + state.prestigeLevel * 0.05));
                        state.money += income;
                        state.totalEarned += income;
                        state.totalMoneyEarned += income;
                        state.missionStats.totalMoney += income;
                        animal.timer = animal.interval;
                        notify('🐄 ' + animal.name + ' produjo ' + income + '🪙', 1200);
                        renderAnimals();
                        updateStats();
                        updateMissions('money', income);
                        checkAchievements();
                    }
                }
            }
            renderAnimals();
        }

        function renderAnimals() {
            animalShopEl.innerHTML = '';
            for (const [key, animal] of Object.entries(state.animals)) {
                const card = document.createElement('div');
                card.className = 'animal-card';
                const canBuy = state.money >= animal.cost;
                const timerText = animal.count > 0 ? `⏱️ ${animal.timer}s` : '—';
                const totalIncome = animal.count * animal.income;
                card.innerHTML = `
                    <div class="animal-emoji">${animal.emoji}</div>
                    <div class="animal-name">${animal.name}</div>
                    <div class="animal-prod">${animal.produces} <span>+${animal.income}🪙</span> c/${animal.interval}s</div>
                    <div style="color:#f9f3d9;font-weight:700;">x${animal.count}</div>
                    <div class="animal-timer">${timerText}</div>
                    <button ${!canBuy ? 'disabled' : ''} data-action="buyAnimal" data-key="${key}">Comprar (${animal.cost}🪙)</button>
                `;
                animalShopEl.appendChild(card);
            }

            document.querySelectorAll('#animalShop .animal-card button').forEach(btn => {
                btn.addEventListener('click', (e) => {
                    e.stopPropagation();
                    const key = btn.dataset.key;
                    if (key) buyAnimal(key);
                });
            });
        }

        // ============================================================
        //  MISIONES
        // ============================================================
        function generateMissions() {
            const templates = [
                { type: 'harvest', target: 8, seed: 'carrot', reward: 60, desc: 'Cosecha 8 zanahorias' },
                { type: 'harvest', target: 5, seed: 'tomato', reward: 75, desc: 'Cosecha 5 tomates' },
                { type: 'harvest', target: 4, seed: 'wheat', reward: 100, desc: 'Cosecha 4 trigos' },
                { type: 'harvest', target: 3, seed: 'corn', reward: 130, desc: 'Cosecha 3 maíces' },
                { type: 'harvest', target: 4, seed: 'strawberry', reward: 110, desc: 'Cosecha 4 fresas' },
                { type: 'harvest', target: 3, seed: 'pumpkin', reward: 150, desc: 'Cosecha 3 calabazas' },
                { type: 'money', target: 400, reward: 60, desc: 'Gana 400 monedas' },
                { type: 'money', target: 1000, reward: 120, desc: 'Gana 1000 monedas' },
                { type: 'money', target: 3000, reward: 250, desc: 'Gana 3000 monedas' },
                { type: 'plant', target: 15, reward: 50, desc: 'Planta 15 semillas' },
                { type: 'plant', target: 30, reward: 100, desc: 'Planta 30 semillas' },
                { type: 'animal', target: 2, reward: 80, desc: 'Compra 2 animales' },
                { type: 'animal', target: 5, reward: 180, desc: 'Compra 5 animales' },
                { type: 'upgrade', target: 3, reward: 100, desc: 'Compra 3 mejoras' },
                { type: 'upgrade', target: 6, reward: 200, desc: 'Compra 6 mejoras' },
                { type: 'totalHarvest', target: 40, reward: 80, desc: 'Cosecha 40 cultivos en total' },
                { type: 'totalHarvest', target: 100, reward: 160, desc: 'Cosecha 100 cultivos en total' },
                { type: 'bigHarvest', target: 200, reward: 150, desc: 'Obtén 200🪙 en una sola cosecha' },
                { type: 'bigHarvest', target: 500, reward: 300, desc: 'Obtén 500🪙 en una sola cosecha' }
            ];

            const shuffled = templates.sort(() => Math.random() - 0.5);
            const selected = shuffled.slice(0, 4).map(m => {
                const bonus = 1 + state.prestigeLevel * 0.25;
                return {
                    ...m,
                    reward: Math.floor(m.reward * bonus),
                    progress: 0,
                    completed: false,
                    claimed: false
                };
            });
            state.missions = selected;
            renderMissions();
        }

        function updateMissions(action, amount, seedType = null) {
            if (!state.missions || state.missions.length === 0) return;
            let changed = false;
            state.missions.forEach(mission => {
                if (mission.completed || mission.claimed) return;
                let progress = false;
                if (mission.type === 'harvest' && action === 'harvest' && mission.seed === seedType) {
                    mission.progress += amount;
                    progress = true;
                } else if (mission.type === 'money' && action === 'money') {
                    mission.progress += amount;
                    progress = true;
                } else if (mission.type === 'plant' && action === 'plant') {
                    mission.progress += amount;
                    progress = true;
                } else if (mission.type === 'animal' && action === 'animal') {
                    mission.progress += amount;
                    progress = true;
                } else if (mission.type === 'upgrade' && action === 'upgrade') {
                    mission.progress += amount;
                    progress = true;
                } else if (mission.type === 'totalHarvest' && action === 'harvest') {
                    mission.progress += amount;
                    progress = true;
                } else if (mission.type === 'bigHarvest' && action === 'harvest') {
                    if (state.missionStats.maxHarvestInOne >= mission.target) {
                        mission.progress = mission.target;
                        progress = true;
                    }
                }
                if (progress && mission.progress >= mission.target) {
                    mission.completed = true;
                    mission.claimed = true;
                    state.money += mission.reward;
                    notify('✅ Misión completada: ' + mission.desc + ' (+' + mission.reward + '🪙)', 2000);
                    changed = true;
                }
            });
            if (changed) {
                renderMissions();
                updateStats();
                renderShop();
                const allDone = state.missions.every(m => m.claimed);
                if (allDone) {
                    setTimeout(() => {
                        generateMissions();
                        notify('📜 Nuevas misiones disponibles', 1500);
                    }, 2000);
                }
            }
        }

        function renderMissions() {
            missionListEl.innerHTML = '';
            if (!state.missions || state.missions.length === 0) {
                missionListEl.innerHTML = '<p style="color:#b8d0a8;text-align:center;">No hay misiones activas</p>';
                return;
            }
            state.missions.forEach(m => {
                const div = document.createElement('div');
                div.className = 'mission-item' + (m.claimed ? ' completed' : '');
                let progressText = '';
                if (m.type === 'bigHarvest') {
                    progressText = '🪙 ' + state.missionStats.maxHarvestInOne + '/' + m.target;
                } else {
                    progressText = m.progress + '/' + m.target;
                }
                div.innerHTML = `
                    <span class="desc">${m.desc}</span>
                    <span class="progress">${progressText}</span>
                    <span class="reward">+${m.reward}🪙</span>
                    <span class="status">${m.claimed ? '✅' : '⏳'}</span>
                `;
                missionListEl.appendChild(div);
            });
        }

        // ============================================================
        //  EVENTOS ALEATORIOS
        // ============================================================
        function triggerRandomEvent() {
            if (state.activeEvent) return;
            const events = [
                { type: 'rain', description: '🌧️ ¡Lluvia! Crecimiento -50%', duration: 12, effect: 'growth' },
                { type: 'market', description: '📈 ¡Mercado alcista! +40% precio', duration: 15, effect: 'price' },
                { type: 'plague', description: '🐛 ¡Plaga! +40% probabilidad de infección', duration: 10,
                effect: 'plague' },
                { type: 'sun', description: '☀️ Día soleado: +20% velocidad', duration: 18, effect: 'growth' },
                { type: 'bonus', description: '🎁 ¡Lluvia de monedas! +100🪙', duration: 0, effect: 'bonus' }
            ];
            const evt = events[Math.floor(Math.random() * events.length)];
            if (evt.type === 'bonus') {
                state.money += 100;
                notify('🎁 ¡Bonificación! +100 monedas', 1500);
                updateStats();
                return;
            }
            state.activeEvent = {
                type: evt.type,
                description: evt.description,
                timer: evt.duration,
                effect: evt.effect
            };
            if (evt.type === 'plague') {
                for (let i = 0; i < state.plots.length; i++) {
                    const p = state.plots[i];
                    if (p.state === 'growing' && Math.random() < 0.4) {
                        p.plagued = true;
                    }
                }
                renderFarm();
            }
            updateEventBanner();
            notify('⚡ ' + evt.description, 2500);
        }

        function updateEventBanner() {
            if (state.activeEvent) {
                eventBannerEl.style.display = 'flex';
                eventBannerEl.innerHTML = `
                    <span>${state.activeEvent.description}</span>
                    <span class="timer">⏱️ ${state.activeEvent.timer}s</span>
                `;
            } else {
                eventBannerEl.style.display = 'none';
            }
        }

        function tickEvents() {
            if (state.activeEvent) {
                state.activeEvent.timer -= 1;
                if (state.activeEvent.timer <= 0) {
                    state.activeEvent = null;
                    updateEventBanner();
                    notify('⏳ El evento ha terminado', 1200);
                    renderFarm();
                } else {
                    updateEventBanner();
                }
            } else {
                if (Math.random() < 0.02) {
                    triggerRandomEvent();
                }
            }
        }

        // ============================================================
        //  PRESTIGIO (CON ANIMALES PERMANENTES)
        // ============================================================
        function updatePrestigeInfo() {
            const req = getPrestigeRequirements();
            prestigeCurLevel.textContent = state.level;
            prestigeCurMoney.textContent = state.money;
            prestigeReqLevel.textContent = req.level;
            prestigeReqMoney.textContent = req.money;

            const levelProgress = Math.min(100, (state.level / req.level) * 100);
            const moneyProgress = Math.min(100, (state.money / req.money) * 100);
            const avgProgress = Math.min(100, (levelProgress + moneyProgress) / 2);
            prestigeProgressBar.style.width = avgProgress + '%';
        }

        window.doPrestige = function() {
            console.log('Prestigio ejecutado. Nivel:', state.level, 'Dinero:', state.money);
            const req = getPrestigeRequirements();

            if (state.level < req.level) {
                notify(`❌ Necesitas nivel ${req.level} (tienes ${state.level})`);
                return;
            }
            if (state.money < req.money) {
                notify(`❌ Necesitas ${req.money}🪙 disponibles (tienes ${state.money})`);
                return;
            }

            // Guardar animales antes de resetear
            const savedAnimals = JSON.parse(JSON.stringify(state.animals));

            // Ejecutar prestigio
            state.prestigeLevel += 1;

            const savedAchievements = JSON.parse(JSON.stringify(state.achievements));
            const savedSeedsBought = new Set(state.seedsBought);

            state.money = 200;
            state.level = 1;
            state.harvestCount = 0;
            state.totalEarned = 0;
            state.totalPlanted = 0;
            state.totalHarvested = 0;
            state.totalMoneyEarned = 0;
            state.selectedSeed = null;
            for (const key of SEED_TYPES) {
                state.seeds[key].count = 0;
            }
            for (const key of Object.keys(state.upgrades)) {
                state.upgrades[key].owned = false;
            }
            for (const key of Object.keys(state.specialUpgrades)) {
                state.specialUpgrades[key].owned = false;
            }
            // NO resetear animales: restaurar los guardados
            state.animals = savedAnimals;

            state.seedsBought = new Set();
            for (let i = 0; i < state.plots.length; i++) {
                state.plots[i] = { state: 'empty', seedType: null, timeLeft: 0, totalTime: 0, plagued: false };
            }
            state.activeEvent = null;
            state.achievements = savedAchievements;
            state.achievements.prestige1.unlocked = true;
            state.seedsBought = savedSeedsBought;

            state.missionStats = {
                totalHarvests: 0,
                totalPlants: 0,
                totalMoney: 0,
                totalUpgrades: 0,
                totalAnimals: 0,
                maxHarvestInOne: 0
            };

            addSeed('carrot', 12);
            addSeed('tomato', 8);
            addSeed('wheat', 5);
            state.selectedSeed = 'carrot';

            generateMissions();

            renderFarm();
            renderShop();
            renderAnimals();
            renderMissions();
            renderAchievements();
            updateStats();
            updateSelectedDisplay();
            updateEventBanner();
            updatePrestigeInfo();

            notify('🔁 ¡Prestigio completado! Nivel de prestigio: ' + state.prestigeLevel + ' (+' + (state.prestigeLevel * 10) +
                '% venta)\nPróximo requisito: nivel ' + (8 + state.prestigeLevel * 4) + ' y ' + (800 + state.prestigeLevel *
                800) + '🪙 disponibles', 4000);
            saveGame();
        };

        // ============================================================
        //  LOGROS
        // ============================================================
        function checkAchievements() {
            const a = state.achievements;
            if (!a.firstHarvest.unlocked && state.harvestCount >= 1) { a.firstHarvest.unlocked = true;
                notify('🏅 Logro: Primera Cosecha', 1500); }
            if (!a.harvest100.unlocked && state.harvestCount >= 100) { a.harvest100.unlocked = true;
                notify('🏅 Logro: Cosechador', 1500); }
            if (!a.harvest1000.unlocked && state.harvestCount >= 1000) { a.harvest1000.unlocked = true;
                notify('🏅 Logro: Super Cosechador', 1500); }
            if (!a.money1000.unlocked && state.totalEarned >= 1000) { a.money1000.unlocked = true;
                notify('🏅 Logro: Rico', 1500); }
            if (!a.money10000.unlocked && state.totalEarned >= 10000) { a.money10000.unlocked = true;
                notify('🏅 Logro: Magnate', 1500); }
            const allSeedsBought = SEED_TYPES.every(t => state.seedsBought.has(t));
            if (!a.allSeeds.unlocked && allSeedsBought) { a.allSeeds.unlocked = true;
                notify('🏅 Logro: Coleccionista', 1500); }
            const allUpgrades = Object.values(state.upgrades).every(u => u.owned);
            if (!a.fullUpgrades.unlocked && allUpgrades) { a.fullUpgrades.unlocked = true;
                notify('🏅 Logro: Granjero Pro', 1500); }
            const allSpecial = Object.values(state.specialUpgrades).every(u => u.owned);
            if (!a.specialUpgrades.unlocked && allSpecial) { a.specialUpgrades.unlocked = true;
                notify('🏅 Logro: Leyenda', 1500); }
            if (!a.level10.unlocked && state.level >= 10) { a.level10.unlocked = true;
                notify('🏅 Logro: Experto', 1500); }
            if (!a.prestige1.unlocked && state.prestigeLevel >= 1) { a.prestige1.unlocked = true;
                notify('🏅 Logro: Renacido', 1500); }
            let hasAnimal = false;
            for (const key of Object.keys(state.animals)) {
                if (state.animals[key].count > 0) hasAnimal = true;
            }
            if (!a.firstAnimal.unlocked && hasAnimal) { a.firstAnimal.unlocked = true;
                notify('🏅 Logro: Granjero Animal', 1500); }
            const allAnimals = Object.values(state.animals).every(a => a.count > 0);
            if (!a.allAnimals.unlocked && allAnimals) { a.allAnimals.unlocked = true;
                notify('🏅 Logro: Zoológico', 1500); }
            renderAchievements();
            updateStats();
        }

        function renderAchievements() {
            achievementGridEl.innerHTML = '';
            for (const [key, ach] of Object.entries(state.achievements)) {
                const div = document.createElement('div');
                div.className = 'achievement-card' + (ach.unlocked ? ' unlocked' : '');
                div.innerHTML = `
                    <div class="ach-emoji">${ach.emoji}</div>
                    <div class="ach-name">${ach.name}</div>
                    <div class="ach-desc">${ach.desc}</div>
                    <div class="ach-status">${ach.unlocked ? '✅ Desbloqueado' : '🔒 Bloqueado'}</div>
                `;
                achievementGridEl.appendChild(div);
            }
            const count = Object.values(state.achievements).filter(a => a.unlocked).length;
            achCountDisplay.textContent = count;
        }

        // ============================================================
        //  COMPRAS
        // ============================================================
        function buySeed(seedType) {
            const seed = state.seeds[seedType];
            if (state.money < seed.cost) { notify('❌ Dinero insuficiente'); return; }
            state.money -= seed.cost;
            addSeed(seedType, 1);
            state.seedsBought.add(seedType);
            if (!state.selectedSeed) state.selectedSeed = seedType;
            renderShop();
            updateStats();
            updateSelectedDisplay();
            checkAchievements();
            notify('✅ Compraste 1 ' + seed.name);
        }

        function buyUpgrade(upgradeKey) {
            const up = state.upgrades[upgradeKey];
            if (up.owned) { notify('⚠️ Ya tienes esta mejora'); return; }
            if (state.money < up.cost) { notify('❌ Dinero insuficiente'); return; }
            state.money -= up.cost;
            up.owned = true;
            state.missionStats.totalUpgrades += 1;
            updateMissions('upgrade', 1);
            renderShop();
            updateStats();
            checkAchievements();
            notify('⚡ Mejora "' + up.name + '" activada');
            saveGame();
        }

        function buySpecialUpgrade(upgradeKey) {
            const up = state.specialUpgrades[upgradeKey];
            if (up.owned) { notify('⚠️ Ya tienes esta mejora'); return; }
            if (state.money < up.cost) { notify('❌ Dinero insuficiente'); return; }
            state.money -= up.cost;
            up.owned = true;
            state.missionStats.totalUpgrades += 1;
            updateMissions('upgrade', 1);
            renderShop();
            updateStats();
            checkAchievements();
            notify('🌟 Mejora especial "' + up.name + '" activada');
            saveGame();
        }

        function selectSeed(seedType) {
            if (getSeedCount(seedType) > 0) {
                state.selectedSeed = seedType;
                updateSelectedDisplay();
                renderShop();
                notify('🔀 Semilla seleccionada: ' + state.seeds[seedType].name);
            } else {
                notify('❌ No tienes semillas de ' + state.seeds[seedType].name);
            }
        }

        // ============================================================
        //  RENDERIZADO
        // ============================================================
        function renderFarm() {
            farmEl.innerHTML = '';
            state.plots.forEach((plot, index) => {
                const div = document.createElement('div');
                let cls = 'plot ' + plot.state;
                if (plot.plagued && plot.state !== 'empty') cls += ' plagued';
                div.className = cls;
                div.dataset.index = index;

                if (plot.state === 'empty') {
                    div.innerHTML = `<span class="emoji">🟫</span>`;
                } else if (plot.state === 'growing') {
                    const emoji = state.seeds[plot.seedType].emoji;
                    const progress = (plot.totalTime > 0) ? ((plot.totalTime - plot.timeLeft) / plot.totalTime * 100) : 0;
                    div.innerHTML = `
                        <span class="emoji">${emoji}</span>
                        <div class="progress-wrap"><div class="progress-bar" style="width:${Math.min(100, progress)}%"></div></div>
                        <span class="time-left">⏱️ ${Math.ceil(plot.timeLeft)}s</span>
                        ${plot.plagued ? '<span class="event-badge">🐛</span>' : ''}
                    `;
                } else if (plot.state === 'ready') {
                    const emoji = state.seeds[plot.seedType].emoji;
                    div.innerHTML = `
                        <span class="emoji">${emoji}</span>
                        <span class="harvest-icon">✅</span>
                        ${plot.plagued ? '<span class="event-badge">🐛</span>' : ''}
                    `;
                }

                div.addEventListener('click', () => {
                    if (plot.state === 'empty') {
                        plantSeed(index);
                    } else if (plot.state === 'ready') {
                        harvestPlot(index);
                    } else if (plot.state === 'growing') {
                        notify('⏳ Creciendo... ' + Math.ceil(plot.timeLeft) + 's restantes');
                    }
                });

                farmEl.appendChild(div);
            });
        }

        function renderShop() {
            seedShopEl.innerHTML = '';
            SEED_TYPES.forEach(key => {
                const seed = state.seeds[key];
                const count = seed.count;
                const canBuy = state.money >= seed.cost;
                const isActive = (state.selectedSeed === key);
                const item = document.createElement('div');
                item.className = 'shop-item' + (isActive ? ' active' : '');
                item.innerHTML = `
                    <div class="info">
                        <span class="emoji">${seed.emoji}</span>
                        <span>${seed.name}</span>
                        <span class="count">x${count}</span>
                        <span style="font-size:0.7rem;color:#b8d0a8;">💰${seed.cost}</span>
                    </div>
                    <div class="actions">
                        <button class="buy" ${!canBuy ? 'disabled' : ''} data-action="buySeed" data-key="${key}">Comprar</button>
                        <button class="select" ${count <= 0 ? 'disabled' : ''} data-action="selectSeed" data-key="${key}">Seleccionar</button>
                    </div>
                `;
                seedShopEl.appendChild(item);
            });

            upgradeShopEl.innerHTML = '';
            for (const [key, up] of Object.entries(state.upgrades)) {
                const canBuy = !up.owned && state.money >= up.cost;
                const item = document.createElement('div');
                item.className = 'shop-item' + (up.owned ? ' active' : '');
                item.innerHTML = `
                    <div class="info">
                        <span>${up.name}</span>
                        <span style="font-size:0.7rem;color:#b8d0a8;">${up.desc}</span>
                        <span style="font-size:0.7rem;color:#f5d742;">💰${up.cost}</span>
                    </div>
                    <div class="actions">
                        ${up.owned ? '<button class="owned" disabled>✅ Activada</button>' :
                        `<button class="buy" ${!canBuy ? 'disabled' : ''} data-action="buyUpgrade" data-key="${key}">Mejorar</button>`}
                    </div>
                `;
                upgradeShopEl.appendChild(item);
            }

            specialShopEl.innerHTML = '';
            for (const [key, up] of Object.entries(state.specialUpgrades)) {
                const canBuy = !up.owned && state.money >= up.cost;
                const item = document.createElement('div');
                item.className = 'shop-item' + (up.owned ? ' active' : '');
                item.innerHTML = `
                    <div class="info">
                        <span>${up.name}</span>
                        <span style="font-size:0.7rem;color:#b8d0a8;">${up.desc}</span>
                        <span style="font-size:0.7rem;color:#f5d742;">💰${up.cost}</span>
                    </div>
                    <div class="actions">
                        ${up.owned ? '<button class="owned" disabled>✅ Activada</button>' :
                        `<button class="buy" ${!canBuy ? 'disabled' : ''} data-action="buySpecial" data-key="${key}">Mejorar</button>`}
                    </div>
                `;
                specialShopEl.appendChild(item);
            }

            document.querySelectorAll('#seedShop .shop-item .actions button').forEach(btn => {
                btn.addEventListener('click', (e) => {
                    e.stopPropagation();
                    const action = btn.dataset.action;
                    const key = btn.dataset.key;
                    if (action === 'buySeed') buySeed(key);
                    else if (action === 'selectSeed') selectSeed(key);
                });
            });
            document.querySelectorAll('#upgradeShop .shop-item .actions button').forEach(btn => {
                btn.addEventListener('click', (e) => {
                    e.stopPropagation();
                    const action = btn.dataset.action;
                    const key = btn.dataset.key;
                    if (action === 'buyUpgrade') buyUpgrade(key);
                });
            });
            document.querySelectorAll('#specialShop .shop-item .actions button').forEach(btn => {
                btn.addEventListener('click', (e) => {
                    e.stopPropagation();
                    const action = btn.dataset.action;
                    const key = btn.dataset.key;
                    if (action === 'buySpecial') buySpecialUpgrade(key);
                });
            });
            document.querySelectorAll('#seedShop .shop-item').forEach(item => {
                item.addEventListener('click', (e) => {
                    if (e.target.tagName === 'BUTTON') return;
                    const key = item.querySelector('.buy')?.dataset.key;
                    if (key && getSeedCount(key) > 0) selectSeed(key);
                    else if (key) notify('❌ No tienes semillas de ' + state.seeds[key].name);
                });
            });
        }

        function updateStats() {
            moneyDisplay.textContent = state.money;
            levelDisplay.textContent = state.level;
            harvestDisplay.textContent = state.harvestCount;
            const unlocked = Object.values(state.achievements).filter(a => a.unlocked).length;
            achCountDisplay.textContent = unlocked;
            prestigeDisplay.textContent = state.prestigeLevel;
            const mult = getSellPriceMultiplier();
            multiplierDisplay.textContent = mult.toFixed(2);
            updatePrestigeInfo();
        }

        function updateSelectedDisplay() {
            if (state.selectedSeed && getSeedCount(state.selectedSeed) > 0) {
                const seed = state.seeds[state.selectedSeed];
                selectedSeedDisplay.textContent = seed.emoji + ' ' + seed.name;
            } else {
                selectedSeedDisplay.textContent = 'Ninguna';
                if (state.selectedSeed) {
                    if (getSeedCount(state.selectedSeed) <= 0) state.selectedSeed = null;
                }
            }
        }

        // ============================================================
        //  PESTAÑAS
        // ============================================================
        document.querySelectorAll('.tab-btn').forEach(btn => {
            btn.addEventListener('click', () => {
                document.querySelectorAll('.tab-btn').forEach(b => b.classList.remove('active'));
                btn.classList.add('active');
                const tabId = btn.dataset.tab;
                document.querySelectorAll('.tab-content').forEach(el => el.classList.remove('active'));
                document.getElementById(tabId).classList.add('active');
            });
        });

        // ============================================================
        //  GUARDADO / CARGA
        // ============================================================
        function saveGame() {
            try {
                const data = {
                    money: state.money,
                    level: state.level,
                    harvestCount: state.harvestCount,
                    totalEarned: state.totalEarned,
                    prestigeLevel: state.prestigeLevel,
                    selectedSeed: state.selectedSeed,
                    seeds: state.seeds,
                    upgrades: state.upgrades,
                    specialUpgrades: state.specialUpgrades,
                    animals: state.animals,
                    plots: state.plots,
                    achievements: state.achievements,
                    seedsBought: [...state.seedsBought],
                    missions: state.missions,
                    activeEvent: state.activeEvent,
                    totalPlanted: state.totalPlanted,
                    totalHarvested: state.totalHarvested,
                    totalMoneyEarned: state.totalMoneyEarned,
                    missionStats: state.missionStats
                };
                localStorage.setItem('farmGameSave_v6', JSON.stringify(data));
            } catch (e) { /* ignore */ }
        }

        function loadGame() {
            try {
                const raw = localStorage.getItem('farmGameSave_v6');
                if (!raw) return false;
                const data = JSON.parse(raw);
                state.money = data.money ?? 100;
                state.level = data.level ?? 1;
                state.harvestCount = data.harvestCount ?? 0;
                state.totalEarned = data.totalEarned ?? 0;
                state.prestigeLevel = data.prestigeLevel ?? 0;
                state.selectedSeed = data.selectedSeed ?? null;
                if (data.seeds) {
                    for (const key of SEED_TYPES) {
                        if (data.seeds[key]) state.seeds[key].count = data.seeds[key].count ?? 0;
                    }
                }
                if (data.upgrades) {
                    for (const key of Object.keys(state.upgrades)) {
                        if (data.upgrades[key]) state.upgrades[key].owned = data.upgrades[key].owned ?? false;
                    }
                }
                if (data.specialUpgrades) {
                    for (const key of Object.keys(state.specialUpgrades)) {
                        if (data.specialUpgrades[key]) state.specialUpgrades[key].owned = data.specialUpgrades[key].owned ??
                            false;
                    }
                }
                if (data.animals) {
                    for (const key of Object.keys(state.animals)) {
                        if (data.animals[key]) {
                            state.animals[key].count = data.animals[key].count ?? 0;
                            state.animals[key].timer = data.animals[key].timer ?? 0;
                        }
                    }
                }
                if (data.plots && data.plots.length === 16) {
                    for (let i = 0; i < 16; i++) {
                        const p = data.plots[i];
                        state.plots[i].state = p.state ?? 'empty';
                        state.plots[i].seedType = p.seedType ?? null;
                        state.plots[i].timeLeft = p.timeLeft ?? 0;
                        state.plots[i].totalTime = p.totalTime ?? 0;
                        state.plots[i].plagued = p.plagued ?? false;
                    }
                }
                if (data.achievements) {
                    for (const key of Object.keys(state.achievements)) {
                        if (data.achievements[key]) state.achievements[key].unlocked = data.achievements[key].unlocked ??
                            false;
                    }
                }
                if (data.seedsBought) state.seedsBought = new Set(data.seedsBought);
                if (data.missions) state.missions = data.missions;
                else generateMissions();
                if (data.activeEvent) state.activeEvent = data.activeEvent;
                if (data.totalPlanted) state.totalPlanted = data.totalPlanted;
                if (data.totalHarvested) state.totalHarvested = data.totalHarvested;
                if (data.totalMoneyEarned) state.totalMoneyEarned = data.totalMoneyEarned;
                if (data.missionStats) state.missionStats = data.missionStats;
                return true;
            } catch (e) { return false; }
        }

        setInterval(saveGame, 8000);
        window.addEventListener('beforeunload', saveGame);

        // ============================================================
        //  INICIO
        // ============================================================
        function init() {
            const loaded = loadGame();
            if (!loaded) {
                addSeed('carrot', 8);
                addSeed('tomato', 5);
                addSeed('wheat', 3);
                state.selectedSeed = 'carrot';
                generateMissions();
                notify('🌾 ¡Bienvenido a la Granja Épica!', 3000);
            } else {
                notify('📂 Partida cargada', 1200);
                if (!state.missions || state.missions.length === 0) generateMissions();
                renderFarm();
            }
            renderFarm();
            renderShop();
            renderAnimals();
            renderMissions();
            renderAchievements();
            updateStats();
            updateSelectedDisplay();
            updateEventBanner();
            updatePrestigeInfo();

            prestigeBtn.disabled = false;
            prestigeBtn.addEventListener('click', window.doPrestige);

            setInterval(() => {
                tickEvents();
                tickAnimals();
                let changed = false;
                for (let i = 0; i < state.plots.length; i++) {
                    const plot = state.plots[i];
                    if (plot.state === 'growing') {
                        plot.timeLeft -= 1;
                        if (plot.timeLeft <= 0) {
                            plot.timeLeft = 0;
                            if (plot.plagued) {
                                plot.state = 'empty';
                                plot.seedType = null;
                                plot.plagued = false;
                                notify('🐛 ¡La plaga arruinó un cultivo!', 1200);
                            } else {
                                plot.state = 'ready';
                            }
                            changed = true;
                        }
                    }
                }
                if (changed) renderFarm();
                updateStats();
                updateSelectedDisplay();
                updatePrestigeInfo();
            }, 1000);

            setInterval(() => {
                renderShop();
                renderAnimals();
                renderMissions();
                renderAchievements();
            }, 5000);
        }

        init();
    </script>
</body>
</html>

Game Source: 🌾 Granja Épica - Animales permanentes

Creator: RapidFalcon68

Libraries: none

Complexity: complex (1921 lines, 76.0 KB)

The full source code is displayed above on this page.

Remix Instructions

To remix this game, copy the source code above and modify it. Add a ARCADELAB header at the top with "remix_of: granja-pica-definitiva-rapidfalcon68" to link back to the original. Then publish at arcadelab.ai/publish.