diff --git a/static/css/style.css b/static/css/style.css index 8e3c2fc..80b0968 100644 --- a/static/css/style.css +++ b/static/css/style.css @@ -99,6 +99,7 @@ input, select { box-sizing: border-box; background: var(--input-bg); color: var(--text-color); + font-family: 'Space Mono', monospace; transition: background 0.3s ease, border-color 0.3s ease, color 0.3s ease; } @@ -367,23 +368,55 @@ button.loading:hover { flex: 1; min-width: 200px; margin-right: 0; + padding: 10px; + border: 2px solid var(--border-color); + border-radius: 8px; + font-size: 16px; + box-sizing: border-box; + background: var(--input-bg); + color: var(--text-color); + transition: background 0.3s ease, border-color 0.3s ease, color 0.3s ease; + font-family: 'Space Mono', monospace; +} + +.location-search input:focus { + outline: none; + border-color: #667eea; } .location-search button { - padding: 8px 15px; - background: #667eea; + font-family: 'Space Mono', monospace; + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; + padding: 12px 24px; border: none; - border-radius: 4px; + border-radius: 25px; + font-size: 16px; + font-weight: bold; cursor: pointer; white-space: nowrap; width: auto; min-width: auto; + transition: all 0.3s ease; + box-shadow: 0 4px 15px rgba(102, 126, 234, 0.3); + margin-top: 0; } .location-search button:hover { - background: #5a67d8; + transform: translateY(-2px); + box-shadow: 0 6px 20px rgba(102, 126, 234, 0.4); + background: linear-gradient(135deg, #5a67d8 0%, #6b46c1 100%); +} + +.location-search button:disabled { + opacity: 0.6; + cursor: not-allowed; + transform: none; +} + +.location-search button:disabled:hover { transform: none; + box-shadow: 0 4px 15px rgba(102, 126, 234, 0.3); } #locationMap { @@ -696,11 +729,20 @@ input[readonly] { .other-genre-input input { width: 100%; - padding: 8px; + padding: 10px; border: 2px solid var(--border-color); - border-radius: 4px; - background: var(--input-bg); + border-radius: 8px; + font-size: 16px; box-sizing: border-box; + background: var(--input-bg); + color: var(--text-color); + transition: background 0.3s ease, border-color 0.3s ease, color 0.3s ease; + font-family: 'Space Mono', monospace; +} + +.other-genre-input input:focus { + outline: none; + border-color: #667eea; } .clear-data-container { @@ -1048,4 +1090,140 @@ input[readonly] { max-height: 0; opacity: 0; padding: 0; +} + +/* ========================================== + Select2 Custom Styling for Timezone Dropdown + ========================================== */ + +/* Main Select2 container */ +.select2-container--default .select2-selection--single { + background: var(--input-bg); + border: 2px solid var(--border-color); + border-radius: 8px; + height: 45px; + padding: 5px 10px; + transition: background 0.3s ease, border-color 0.3s ease; +} + +.select2-container--default .select2-selection--single:focus, +.select2-container--default.select2-container--open .select2-selection--single { + border-color: #667eea; + outline: none; +} + +.select2-container--default .select2-selection--single .select2-selection__rendered { + color: var(--text-color); + line-height: 33px; + padding-left: 5px; + font-family: 'Space Mono', monospace; + font-size: 16px; +} + +.select2-container--default .select2-selection--single .select2-selection__placeholder { + color: var(--text-secondary); +} + +.select2-container--default .select2-selection--single .select2-selection__arrow { + height: 43px; + right: 5px; +} + +/* Dropdown */ +.select2-container--default .select2-dropdown { + background: var(--input-bg); + border: 2px solid var(--border-color); + border-radius: 8px; + box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2); + margin-top: 5px; + max-width: 100%; +} + +/* Search box in dropdown */ +.select2-container--default .select2-search--dropdown .select2-search__field { + background: var(--input-bg); + border: 2px solid var(--border-color); + border-radius: 6px; + color: var(--text-color); + font-family: 'Space Mono', monospace; + padding: 8px; + margin: 8px; +} + +.select2-container--default .select2-search--dropdown .select2-search__field:focus { + border-color: #667eea; + outline: none; +} + +/* Dropdown results */ +.select2-container--default .select2-results__option { + background: var(--input-bg); + color: var(--text-color); + padding: 10px 12px; + font-family: 'Space Mono', monospace; + font-size: 14px; +} + +.select2-container--default .select2-results__option--highlighted[aria-selected] { + background: #667eea; + color: white; +} + +.select2-container--default .select2-results__option[aria-selected=true] { + background: var(--section-bg); + color: var(--text-color); +} + +.select2-container--default .select2-results__option[aria-selected=true]:hover { + background: #667eea; + color: white; +} + +/* Option groups */ +.select2-container--default .select2-results__group { + background: var(--section-bg); + color: var(--text-secondary); + font-weight: bold; + padding: 8px 12px; + font-size: 12px; + text-transform: uppercase; + letter-spacing: 0.5px; + border-top: 1px solid var(--border-color); +} + +.select2-container--default .select2-results__option--group { + padding-left: 0; +} + +.select2-container--default .select2-results__options--nested .select2-results__option { + padding-left: 20px; +} + +/* Loading state */ +.select2-container--default .select2-results__option--loading { + color: var(--text-secondary); +} + +/* No results message */ +.select2-container--default .select2-results__option--no-results { + color: var(--text-secondary); + background: var(--input-bg); +} + +/* Width fix */ +.select2-container { + width: 100% !important; +} + +.timezone-select { + width: 100%; +} + +/* Dark mode adjustments */ +.dark-mode .select2-container--default .select2-selection--single .select2-selection__arrow b { + border-color: var(--text-color) transparent transparent transparent; +} + +.dark-mode .select2-container--default.select2-container--open .select2-selection--single .select2-selection__arrow b { + border-color: transparent transparent var(--text-color) transparent; } \ No newline at end of file diff --git a/static/js/dropdown-button.js b/static/js/dropdown-button.js new file mode 100644 index 0000000..08b594b --- /dev/null +++ b/static/js/dropdown-button.js @@ -0,0 +1,26 @@ +// Dropdown button functionality +function toggleDropdown() { + const dropdown = document.getElementById('chartDropdown'); + dropdown.classList.toggle('show'); +} + +// Close dropdown when clicking outside +document.addEventListener('click', function(event) { + const dropdown = document.getElementById('chartDropdown'); + const toggleButton = document.querySelector('.dropdown-toggle'); + + if (dropdown && !event.target.closest('.dropdown-button-wrapper')) { + dropdown.classList.remove('show'); + } +}); + +// Prevent form submission when clicking the dropdown toggle +document.addEventListener('DOMContentLoaded', function() { + const toggleButton = document.querySelector('.dropdown-toggle'); + if (toggleButton) { + toggleButton.addEventListener('click', function(e) { + e.preventDefault(); + e.stopPropagation(); + }); + } +}); diff --git a/static/js/location-map.js b/static/js/location-map.js index d2031b9..001747f 100644 --- a/static/js/location-map.js +++ b/static/js/location-map.js @@ -1,6 +1,7 @@ // Interactive map for location selection using Leaflet let map; let marker; +let currentTileLayer; document.addEventListener('DOMContentLoaded', function() { initMap(); @@ -23,6 +24,20 @@ document.addEventListener('DOMContentLoaded', function() { } }); } + + // Listen for dark mode changes and update map tiles + const observer = new MutationObserver(function(mutations) { + mutations.forEach(function(mutation) { + if (mutation.attributeName === 'class') { + updateMapTiles(); + } + }); + }); + + observer.observe(document.documentElement, { + attributes: true, + attributeFilter: ['class'] + }); }); function initMap() { @@ -35,10 +50,8 @@ function initMap() { // Make map globally available for form persistence window.map = map; - // Add OpenStreetMap tiles - L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { - attribution: '© OpenStreetMap contributors' - }).addTo(map); + // Add appropriate tile layer based on current mode + updateMapTiles(); // Add click listener to map map.on('click', function(e) { @@ -143,6 +156,32 @@ function getTimezoneForLocation(lat, lng) { } } +function updateMapTiles() { + if (!map) return; + + // Remove existing tile layer if present + if (currentTileLayer) { + map.removeLayer(currentTileLayer); + } + + const isDarkMode = document.documentElement.classList.contains('dark-mode'); + + if (isDarkMode) { + // Dark mode: Use CartoDB Dark Matter tiles + currentTileLayer = L.tileLayer('https://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}{r}.png', { + attribution: '© OpenStreetMap contributors © CARTO', + subdomains: 'abcd', + maxZoom: 19 + }).addTo(map); + } else { + // Light mode: Use standard OpenStreetMap tiles + currentTileLayer = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { + attribution: '© OpenStreetMap contributors', + maxZoom: 19 + }).addTo(map); + } +} + // Search for locations using Nominatim (OpenStreetMap's geocoding service) function searchLocation() { const searchInput = document.getElementById('locationSearch'); diff --git a/static/js/sparkles.js b/static/js/sparkles.js index ee28afe..5bf1e2c 100644 --- a/static/js/sparkles.js +++ b/static/js/sparkles.js @@ -5,9 +5,9 @@ function createSparkle() { const sparkle = document.createElement('div'); sparkle.className = 'sparkle'; - // Random sparkle characters - const sparkleChars = ['✨', '⭐', '🌟', '💫', '🔮']; - sparkle.textContent = sparkleChars[Math.floor(Math.random() * sparkleChars.length)]; + // Random star characters (matching star-trail) + const starChars = ['✦', '✧', '⋆', '✩', '✪', '✫', '✬', '✭', '✮', '✯']; + sparkle.textContent = starChars[Math.floor(Math.random() * starChars.length)]; // Random position across the width sparkle.style.left = Math.random() * 100 + '%'; @@ -20,6 +20,12 @@ function createSparkle() { const size = Math.random() * 15 + 15; sparkle.style.fontSize = size + 'px'; + // Random color (matching star-trail) + const colors = ['#FFD700', '#FFA500', '#FF69B4', '#9370DB', '#00CED1', '#FFFFFF', '#FFB6C1']; + const color = colors[Math.floor(Math.random() * colors.length)]; + sparkle.style.color = color; + sparkle.style.textShadow = `0 0 ${size/2}px ${color}`; + // Some sparkles get extra twinkle if (Math.random() > 0.7) { sparkle.classList.add('twinkle'); diff --git a/static/js/timezone-select.js b/static/js/timezone-select.js new file mode 100644 index 0000000..9294c03 --- /dev/null +++ b/static/js/timezone-select.js @@ -0,0 +1,21 @@ +// Initialize timezone selector with Select2 +document.addEventListener('DOMContentLoaded', function() { + // Initialize Select2 on the timezone select element + $('#timezone_offset').select2({ + placeholder: 'Select or search for a timezone...', + allowClear: false, + width: '100%', + dropdownAutoWidth: false + }); + + // If there's a stored value in localStorage, restore it + var storedTimezone = localStorage.getItem('timezone_offset'); + if (storedTimezone) { + $('#timezone_offset').val(storedTimezone).trigger('change'); + } + + // Save timezone to localStorage when changed + $('#timezone_offset').on('change', function() { + localStorage.setItem('timezone_offset', $(this).val()); + }); +}); diff --git a/templates/base.html b/templates/base.html index cf48f1d..126159a 100644 --- a/templates/base.html +++ b/templates/base.html @@ -35,8 +35,12 @@ + + + + diff --git a/templates/index.html b/templates/index.html index e390d07..1dbde44 100644 --- a/templates/index.html +++ b/templates/index.html @@ -6,13 +6,14 @@ + {% endblock %} {% block content %}

🌟 Astro Horoscope

-

Enter your birth information to generate your natal chart to get a super chill super accurate horoscope

+

Enter your birth information to generate your personalized natal chart and detailed horoscope

@@ -31,10 +32,106 @@

🌟 Astro Horoscope

- - - Format: +/-HH:MM (include daylight savings adjustment) + + + Search or select your timezone (include daylight savings adjustment)
@@ -69,7 +166,7 @@

🌟 Astro Horoscope

-
+ -
+