در حال پردازش هوشمند و تولید صدا...
diff --git "a/index.html" "b/index.html" --- "a/index.html" +++ "b/index.html" @@ -9,7 +9,7 @@ :root { --app-font: 'Vazirmatn', sans-serif; - --app-bg: #F7F9FC; + --app-bg: #F4F7FC; --panel-bg: #FFFFFF; --panel-border: #E8EEF3; --text-primary: #121826; @@ -20,11 +20,6 @@ --accent-secondary-hover: #059669; --input-bg: #F8FAFC; --input-border-focus: var(--accent-primary); - --waveform-bg: #A9B9D0; - --waveform-progress: #3B82F6; - --player-control-bg: #f0f3f7; - --player-control-icon: #6B7A94; - --player-control-icon-hover: var(--accent-primary); --radius-card: 24px; --radius-input: 14px; @@ -33,19 +28,39 @@ --shadow-strong: 0 10px 25px -5px rgba(26, 32, 44, 0.12), 0 6px 15px -6px rgba(26,32,44,0.08); --transition-smooth: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); --transition-bounce: all 0.4s cubic-bezier(0.68, -0.55, 0.27, 1.55); + + /* Custom Audio Player Colors */ + --waveform-color-active: #3B82F6; /* Matches accent-primary */ + --waveform-color-inactive: #D0D9E6; /* Lighter shade for inactive part of waveform */ } - @keyframes fadeInDown { from { opacity: 0; transform: translateY(-20px); } to { opacity: 1; transform: translateY(0); } } - @keyframes fadeInUp { from { opacity: 0; transform: translateY(20px); } to { opacity: 1; transform: translateY(0); } } - @keyframes modalZoomIn { from { opacity: 0; transform: scale(0.8) translateY(20px); } to { opacity: 1; transform: scale(1) translateY(0); } } - @keyframes modalZoomOut { from { opacity: 1; transform: scale(1) translateY(0); } to { opacity: 0; transform: scale(0.8) translateY(20px); } } + @keyframes fadeInDown { + from { opacity: 0; transform: translateY(-20px); } + to { opacity: 1; transform: translateY(0); } + } + @keyframes fadeInUp { + from { opacity: 0; transform: translateY(20px); } + to { opacity: 1; transform: translateY(0); } + } + @keyframes modalZoomIn { + from { opacity: 0; transform: scale(0.8) translateY(20px); } + to { opacity: 1; transform: scale(1) translateY(0); } + } + @keyframes modalZoomOut { + from { opacity: 1; transform: scale(1) translateY(0); } + to { opacity: 0; transform: scale(0.8) translateY(20px); } + } + + /* Keyframe for loading spinner in button */ + @keyframes spin { + from { transform: rotate(0deg); } + to { transform: rotate(360deg); } + } body { font-family: var(--app-font); direction: rtl; background-color: var(--app-bg); - background-image: radial-gradient(var(--panel-border) 1px, transparent 1px); - background-size: 30px 30px; color: var(--text-primary); font-size: 16px; line-height: 1.8; @@ -60,228 +75,699 @@ overflow-x: hidden; } - .container { max-width: 780px; width: 92%; margin: 0 auto; } - .app-header { padding: 0.5rem 0 2.5rem 0; text-align: center; margin-bottom: 1.5rem; animation: fadeInDown 0.8s 0.1s ease-out backwards; } - .app-header h1 { font-size: 2.1em; font-weight: 900; margin:0 0 0.6rem 0; background: linear-gradient(45deg, var(--accent-primary), var(--accent-secondary)); -webkit-background-clip: text; -webkit-text-fill-color: transparent; letter-spacing: -0.5px; } - .app-header p { font-size: 1em; color: var(--text-secondary); margin-top:0; opacity: 0.85; font-weight: 400; line-height: 1.6; } - .main-content { padding: 2.5rem; background-color: var(--panel-bg); border-radius: var(--radius-card); box-shadow: var(--shadow-strong); border: 1px solid var(--panel-border); animation: fadeInUp 0.8s 0.3s ease-out backwards; } + .container { + max-width: 780px; + width: 92%; + margin: 0 auto; + } + + .app-header { + padding: 0.5rem 0 2.5rem 0; + text-align: center; + margin-bottom: 1.5rem; + animation: fadeInDown 0.8s 0.1s ease-out backwards; + } + .app-header h1 { + font-size: 2.1em; + font-weight: 900; + margin:0 0 0.6rem 0; + background: linear-gradient(45deg, var(--accent-primary), var(--accent-secondary)); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + letter-spacing: -0.5px; + } + .app-header p { + font-size: 1em; + color: var(--text-secondary); + margin-top:0; + opacity: 0.85; + font-weight: 400; + line-height: 1.6; + } + + .main-content { + padding: 2.5rem; + background-color: var(--panel-bg); + border-radius: var(--radius-card); + box-shadow: var(--shadow-strong); + border: 1px solid var(--panel-border); + animation: fadeInUp 0.8s 0.3s ease-out backwards; + } + .form-group { margin-bottom: 2rem; } - .label-with-info { display: flex; align-items: center; gap: 0.5rem; margin-bottom: 1rem; } - .label-with-info label { margin-bottom: 0; } - .info-icon { display: inline-flex; align-items: center; justify-content: center; width: 22px; height: 22px; border-radius: 50%; background-color: var(--input-bg); border: 1px solid var(--panel-border); color: var(--text-secondary); font-size: 0.9em; font-weight: 700; cursor: pointer; position: relative; transition: var(--transition-smooth); user-select: none; } - .info-icon:hover, .info-icon:focus { background-color: var(--accent-primary); color: white; border-color: var(--accent-primary); transform: scale(1.1); outline: none; } - label { display: block; font-weight: 700; color: var(--text-primary); font-size: 1.05em; margin-bottom: 0.8rem; } - textarea, input[type="text"] { width: 100%; padding: 0.9rem 1.1rem; border-radius: var(--radius-input); border: 1px solid var(--panel-border); background-color: var(--input-bg); color: var(--text-primary); box-shadow: var(--shadow-subtle) inset; font-family: var(--app-font); font-size: 1rem; box-sizing: border-box; transition: var(--transition-smooth); } - textarea:focus, input[type="text"]:focus { outline: none; border-color: var(--input-border-focus); box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.25), var(--shadow-subtle) inset; background-color: #fff; } + + .label-with-info { + display: flex; + align-items: center; + gap: 0.5rem; + margin-bottom: 1rem; + } + .label-with-info label { + margin-bottom: 0; + } + + .info-icon { + display: inline-flex; + align-items: center; + justify-content: center; + width: 22px; + height: 22px; + border-radius: 50%; + background-color: var(--input-bg); + border: 1px solid var(--panel-border); + color: var(--text-secondary); + font-size: 0.9em; + font-weight: 700; + cursor: pointer; + position: relative; + transition: var(--transition-smooth); + user-select: none; + } + .info-icon:hover, .info-icon:focus { + background-color: var(--accent-primary); + color: white; + border-color: var(--accent-primary); + transform: scale(1.1); + outline: none; + } + + label { + display: block; + font-weight: 700; + color: var(--text-primary); + font-size: 1.05em; + margin-bottom: 0.8rem; + } + + textarea, input[type="text"] { + width: 100%; + padding: 0.9rem 1.1rem; + border-radius: var(--radius-input); + border: 1px solid var(--panel-border); + background-color: var(--input-bg); + color: var(--text-primary); + box-shadow: var(--shadow-subtle) inset; + font-family: var(--app-font); + font-size: 1rem; + box-sizing: border-box; + transition: var(--transition-smooth); + } + textarea:focus, input[type="text"]:focus { + outline: none; + border-color: var(--input-border-focus); + box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.25), var(--shadow-subtle) inset; + background-color: #fff; + } textarea { min-height: 100px; resize: vertical; } - .char-counter-wrapper { font-size: 0.85em; color: var(--text-secondary); text-align: left; margin-top: 0.5rem; padding: 0 0.2rem; } + + .char-counter-wrapper { + font-size: 0.85em; + color: var(--text-secondary); + text-align: left; + margin-top: 0.5rem; + padding: 0 0.2rem; + } #char-count { font-weight: 600; color: var(--accent-primary); } + + + /* --- نمایش گوینده منتخب --- */ #selected-speaker-display { text-align: center; margin-top: 1rem; position: relative; } - #selected-speaker-card { display: inline-flex; align-items: center; background: linear-gradient(135deg, var(--input-bg) 0%, #fff 100%); border-radius: var(--radius-card); padding: 1rem 1.2rem; box-shadow: var(--shadow-medium); border: 1px solid var(--panel-border); transition: var(--transition-bounce); position: relative; margin-bottom: 1.2rem; cursor: pointer; } - #selected-speaker-card:hover { transform: translateY(-6px) scale(1.03); box-shadow: var(--shadow-strong); } - #selected-speaker-card img { width: 75px; height: 75px; border-radius: 50%; object-fit: cover; margin-left: 18px; border: 3px solid var(--accent-secondary); box-shadow: 0 0 12px -2px rgba(16, 185, 129, 0.5); background-color: #e0e0e0; transition: var(--transition-smooth); } - #selected-speaker-card:hover img { transform: scale(1.08) rotate(3deg); } + #selected-speaker-card { + display: inline-flex; + align-items: center; + background: linear-gradient(135deg, var(--input-bg) 0%, #fff 100%); + border-radius: var(--radius-card); + padding: 1rem 1.2rem; + box-shadow: var(--shadow-medium); + border: 1px solid var(--panel-border); + transition: var(--transition-bounce); + position: relative; + margin-bottom: 1.2rem; + cursor: pointer; + } + #selected-speaker-card:hover { + transform: translateY(-6px) scale(1.03); + box-shadow: var(--shadow-strong); + } + #selected-speaker-card img { + width: 75px; height: 75px; + border-radius: 50%; + object-fit: cover; + margin-left: 18px; + border: 3px solid var(--accent-secondary); + box-shadow: 0 0 12px -2px rgba(16, 185, 129, 0.5); + background-color: #e0e0e0; + transition: var(--transition-smooth); + } + #selected-speaker-card:hover img { + transform: scale(1.08) rotate(3deg); + } #selected-speaker-info h3 { margin: 0; font-size: 1.35em; font-weight: 800; color: var(--text-primary); } #selected-speaker-info p { margin: 4px 0 0; color: var(--text-secondary); font-size: 0.88em; font-weight: 500; } - #change-speaker-btn { display: inline-flex; align-items: center; justify-content: center; margin: 0 auto; padding: 10px 20px; border-radius: var(--radius-input); background: linear-gradient(45deg, var(--accent-primary-hover), var(--accent-primary)); border: none; color: #fff; cursor: pointer; font-family: var(--app-font); font-weight: 600; font-size: 1em; transition: var(--transition-smooth); box-shadow: 0 4px 10px -2px rgba(59, 130, 246, 0.35), var(--shadow-subtle); } - #change-speaker-btn:hover { background: linear-gradient(45deg, var(--accent-primary), var(--accent-primary-hover)); transform: translateY(-3px) scale(1.05); box-shadow: 0 6px 12px -3px rgba(59, 130, 246, 0.45), var(--shadow-medium); } - #change-speaker-btn svg { width: 1.1em; height: 1.1em; margin-right: 0.5em; fill: currentColor; } - .modal-overlay { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background-color: rgba(18, 24, 38, 0.6); backdrop-filter: blur(8px) saturate(150%); display: none; align-items: center; justify-content: center; z-index: 1000; opacity: 0; transition: opacity 0.3s cubic-bezier(0.4, 0, 0.2, 1); } + + #change-speaker-btn { + display: inline-flex; + align-items: center; + justify-content: center; + margin: 0 auto; + padding: 10px 20px; + border-radius: var(--radius-input); + background: linear-gradient(45deg, var(--accent-primary-hover), var(--accent-primary)); + border: none; + color: #fff; + cursor: pointer; + font-family: var(--app-font); font-weight: 600; + font-size: 1em; + transition: var(--transition-smooth); + box-shadow: 0 4px 10px -2px rgba(59, 130, 246, 0.35), var(--shadow-subtle); + } + #change-speaker-btn:hover { + background: linear-gradient(45deg, var(--accent-primary), var(--accent-primary-hover)); + transform: translateY(-3px) scale(1.05); + box-shadow: 0 6px 12px -3px rgba(59, 130, 246, 0.45), var(--shadow-medium); + } + #change-speaker-btn svg { + width: 1.1em; + height: 1.1em; + margin-right: 0.5em; + fill: currentColor; + } + + + /* --- مودال عمومی --- */ + .modal-overlay { + position: fixed; top: 0; left: 0; width: 100%; height: 100%; + background-color: rgba(18, 24, 38, 0.6); + backdrop-filter: blur(8px) saturate(150%); + display: none; /* Hidden by default */ + align-items: center; justify-content: center; + z-index: 1000; opacity: 0; + transition: opacity 0.3s cubic-bezier(0.4, 0, 0.2, 1); + } .modal-overlay.visible { display: flex; opacity: 1; } - .modal-dialog { background: var(--panel-bg); padding: 2rem; border-radius: var(--radius-card); width: 90%; box-shadow: var(--shadow-strong); border: 1px solid var(--panel-border); opacity: 0; animation-duration: 0.35s; animation-fill-mode: forwards; } - .modal-overlay.visible .modal-dialog { animation-name: modalZoomIn; } - .modal-overlay.hiding .modal-dialog { animation-name: modalZoomOut; } + + .modal-dialog { + background: var(--panel-bg); + padding: 2rem; + border-radius: var(--radius-card); + width: 90%; + box-shadow: var(--shadow-strong); + border: 1px solid var(--panel-border); + opacity: 0; /* For animation */ + animation-duration: 0.35s; + animation-fill-mode: forwards; + } + .modal-overlay.visible .modal-dialog { + animation-name: modalZoomIn; + } + .modal-overlay.hiding .modal-dialog { + animation-name: modalZoomOut; + } + + .modal-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 1.5rem; padding-bottom: 1rem; border-bottom: 1px solid var(--panel-border); } .modal-header h2 { margin: 0; font-size: 1.6em; font-weight: 800; color: var(--accent-primary);} .close-modal-btn { background: none; border: none; font-size: 2.5rem; cursor: pointer; color: var(--text-secondary); transition: var(--transition-smooth); line-height: 1; } .close-modal-btn:hover { color: var(--accent-primary); transform: rotate(90deg) scale(1.1); } - #speaker-modal .modal-dialog { max-width: 700px; max-height: 85vh; overflow-y: auto; } + + + /* --- مودال گالری گویندگان (اختصاصی) --- */ + #speaker-modal .modal-dialog { /* Target specific modal dialog */ + max-width: 700px; + max-height: 85vh; overflow-y: auto; + } #speaker-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(120px, 1fr)); gap: 1.2rem; } @media (min-width: 640px) { #speaker-grid { grid-template-columns: repeat(auto-fill, minmax(130px, 1fr)); } } .speaker-card { cursor: pointer; transition: var(--transition-smooth); text-align: center; position: relative;} - .speaker-card .speaker-visual { border: 3px solid transparent; border-radius: var(--radius-card); overflow: hidden; box-shadow: var(--shadow-subtle); position: relative; background-color: var(--input-bg); transition: var(--transition-bounce); padding: 6px; } - .speaker-card:hover .speaker-visual { transform: translateY(-5px) scale(1.06); box-shadow: var(--shadow-medium); } + .speaker-card .speaker-visual { + border: 3px solid transparent; + border-radius: var(--radius-card); + overflow: hidden; + box-shadow: var(--shadow-subtle); + position: relative; + background-color: var(--input-bg); + transition: var(--transition-bounce); + padding: 6px; + } + .speaker-card:hover .speaker-visual { + transform: translateY(-5px) scale(1.06); + box-shadow: var(--shadow-medium); + } .speaker-card input[type="radio"] { display: none; } - .speaker-card img { width: 100%; height: 120px; object-fit: cover; display: block; background-color: #e0e0e0; transition: transform 0.35s cubic-bezier(0.25, 0.46, 0.45, 0.94); border-radius: calc(var(--radius-card) - 12px); } + .speaker-card img { + width: 100%; height: 120px; + object-fit: cover; display: block; + background-color: #e0e0e0; + transition: transform 0.35s cubic-bezier(0.25, 0.46, 0.45, 0.94); + border-radius: calc(var(--radius-card) - 12px); + } .speaker-card:hover img { transform: scale(1.12); } .speaker-card .speaker-name { padding: 0.8rem 0.4rem 0.1rem; font-weight: 600; font-size: 0.9em; color: var(--text-secondary); transition: color 0.2s; } - .speaker-card input[type="radio"]:checked + .speaker-visual { border-color: var(--accent-secondary); box-shadow: 0 0 25px -5px rgba(16, 185, 129, 0.75); background: linear-gradient(135deg, var(--accent-secondary-hover), var(--accent-primary)); transform: scale(1.05); } - .speaker-card input[type="radio"]:checked + .speaker-visual img { border: 2px solid white; transform: scale(1.05); } - .speaker-card input[type="radio"]:checked + .speaker-visual .speaker-name { color: #fff; font-weight: 700; } - #info-modal .modal-dialog { max-width: 480px; } - #info-modal-content p { font-size: 1em; line-height: 1.7; color: var(--text-secondary); margin-bottom: 0.5rem; } - #info-modal-content p strong { color: var(--text-primary); font-weight: 600; } - #info-modal-content .range-info { font-size: 0.9em; color: var(--accent-primary); font-weight: 500; margin-top: 1rem; display: block; text-align: center; } + .speaker-card input[type="radio"]:checked + .speaker-visual { + border-color: var(--accent-secondary); + box-shadow: 0 0 25px -5px rgba(16, 185, 129, 0.75); + background: linear-gradient(135deg, var(--accent-secondary-hover), var(--accent-primary)); + transform: scale(1.05); + } + .speaker-card input[type="radio"]:checked + .speaker-visual img { + border: 2px solid white; + transform: scale(1.05); + } + .speaker-card input[type="radio"]:checked + .speaker-visual .speaker-name { + color: #fff; + font-weight: 700; + } + + /* --- مودال اطلاعات (اختصاصی) --- */ + #info-modal .modal-dialog { + max-width: 480px; /* Smaller width for info */ + } + #info-modal-content p { + font-size: 1em; + line-height: 1.7; + color: var(--text-secondary); + margin-bottom: 0.5rem; + } + #info-modal-content p strong { + color: var(--text-primary); + font-weight: 600; + } + #info-modal-content .range-info { + font-size: 0.9em; + color: var(--accent-primary); + font-weight: 500; + margin-top: 1rem; + display: block; + text-align: center; + } + + + /* --- Slider & Button & Output --- */ .slider-container { display: flex; align-items: center; gap: 1.2rem; } - input[type="range"] { flex-grow: 1; -webkit-appearance: none; appearance: none; width: 100%; height: 8px; background: #EAF0F6; border-radius: 4px; outline: none; cursor: pointer; transition: background 0.2s; } - input[type="range"]::-webkit-slider-runnable-track { background: linear-gradient(to right, var(--accent-secondary) 0%, var(--accent-primary) 100%); height: 8px; border-radius: 4px; } - input[type="range"]::-webkit-slider-thumb { -webkit-appearance: none; appearance: none; width: 22px; height: 22px; background: #fff; border-radius: 50%; cursor: pointer; border: 3px solid var(--accent-primary); box-shadow: 0 2px 6px rgba(0,0,0,0.15); margin-top: -7px; transition: transform 0.2s ease, box-shadow 0.2s ease; } - input[type="range"]::-webkit-slider-thumb:hover, input[type="range"]:focus::-webkit-slider-thumb { transform: scale(1.2); box-shadow: 0 3px 8px rgba(59, 130, 246, 0.35); } - input[type="range"]::-moz-range-thumb { width: 22px; height: 22px; background: #fff; border-radius: 50%; cursor: pointer; border: 3px solid var(--accent-primary); box-shadow: 0 2px 6px rgba(0,0,0,0.15); } - input[type="range"]::-moz-range-track { background: linear-gradient(to right, var(--accent-secondary) 0%, var(--accent-primary) 100%); height: 8px; border-radius: 4px; border: none; } - #temperature-value { font-weight: 700; background-color: var(--input-bg); padding: 0.5rem 1rem; border-radius: 8px; border: 1px solid var(--panel-border); min-width: 45px; text-align: center; color: var(--accent-primary); font-size: 1em; box-shadow: var(--shadow-subtle); } - #generate-btn { width: 100%; padding: 1rem 1.5rem; font-size: 1.25em; font-weight: 800; font-family: var(--app-font); background: linear-gradient(95deg, var(--accent-secondary) 0%, var(--accent-primary) 100%); color: #fff; border: none; border-radius: var(--radius-input); cursor: pointer; transition: var(--transition-smooth), transform 0.15s ease-out; box-shadow: 0 5px 15px -4px rgba(59, 130, 246, 0.45), 0 5px 15px -4px rgba(16, 185, 129, 0.35); position: relative; overflow: hidden; letter-spacing: 0.5px; } - #generate-btn::before { content: ''; position: absolute; top: 0; left: -180%; width: 80%; height: 100%; background: linear-gradient(to right, rgba(255,255,255,0) 0%, rgba(255,255,255,0.25) 50%, rgba(255,255,255,0) 100%); transform: skewX(-30deg); transition: left 0.8s cubic-bezier(0.23, 1, 0.32, 1); } + input[type="range"] { + flex-grow: 1; -webkit-appearance: none; appearance: none; + width: 100%; height: 8px; + background: #EAF0F6; + border-radius: 4px; outline: none; + cursor: pointer; + transition: background 0.2s; + } + input[type="range"]::-webkit-slider-runnable-track { + background: linear-gradient(to right, var(--accent-secondary) 0%, var(--accent-primary) 100%); + height: 8px; + border-radius: 4px; + } + input[type="range"]::-webkit-slider-thumb { + -webkit-appearance: none; appearance: none; + width: 22px; height: 22px; + background: #fff; + border-radius: 50%; cursor: pointer; + border: 3px solid var(--accent-primary); + box-shadow: 0 2px 6px rgba(0,0,0,0.15); + margin-top: -7px; + transition: transform 0.2s ease, box-shadow 0.2s ease; + } + input[type="range"]::-webkit-slider-thumb:hover, input[type="range"]:focus::-webkit-slider-thumb { + transform: scale(1.2); + box-shadow: 0 3px 8px rgba(59, 130, 246, 0.35); + } + input[type="range"]::-moz-range-thumb { + width: 22px; height: 22px; + background: #fff; + border-radius: 50%; cursor: pointer; + border: 3px solid var(--accent-primary); + box-shadow: 0 2px 6px rgba(0,0,0,0.15); + } + input[type="range"]::-moz-range-track { + background: linear-gradient(to right, var(--accent-secondary) 0%, var(--accent-primary) 100%); + height: 8px; + border-radius: 4px; + border: none; + } + #temperature-value { + font-weight: 700; background-color: var(--input-bg); + padding: 0.5rem 1rem; + border-radius: 8px; + border: 1px solid var(--panel-border); + min-width: 45px; text-align: center; + color: var(--accent-primary); + font-size: 1em; + box-shadow: var(--shadow-subtle); + } + + #generate-btn { + width: 100%; padding: 1rem 1.5rem; + font-size: 1.25em; font-weight: 800; + font-family: var(--app-font); + background: linear-gradient(95deg, var(--accent-secondary) 0%, var(--accent-primary) 100%); + color: #fff; + border: none; + border-radius: var(--radius-input); + cursor: pointer; + transition: var(--transition-smooth), transform 0.15s ease-out; + box-shadow: 0 5px 15px -4px rgba(59, 130, 246, 0.45), 0 5px 15px -4px rgba(16, 185, 129, 0.35); + position: relative; + overflow: hidden; + letter-spacing: 0.5px; + } + #generate-btn::before { + content: ''; position: absolute; + top: 0; left: -180%; width: 80%; height: 100%; + background: linear-gradient(to right, rgba(255,255,255,0) 0%, rgba(255,255,255,0.25) 50%, rgba(255,255,255,0) 100%); + transform: skewX(-30deg); + transition: left 0.8s cubic-bezier(0.23, 1, 0.32, 1); + } #generate-btn:hover::before { left: 180%; } - #generate-btn:hover:not(:disabled) { transform: translateY(-5px) scale(1.02); box-shadow: 0 8px 20px -4px rgba(59, 130, 246, 0.55), 0 8px 20px -4px rgba(16, 185, 129, 0.45); } - #generate-btn:active:not(:disabled) { transform: translateY(-2px) scale(0.98); } - #generate-btn:disabled { background: #B8C2CC; cursor: not-allowed; box-shadow: none; color: #E8EEF3; transform: none; } + #generate-btn:hover:not(:disabled) { + transform: translateY(-5px) scale(1.02); + box-shadow: 0 8px 20px -4px rgba(59, 130, 246, 0.55), 0 8px 20px -4px rgba(16, 185, 129, 0.45); + } + #generate-btn:active:not(:disabled) { + transform: translateY(-2px) scale(0.98); + } + #generate-btn:disabled { + background: #B8C2CC; + cursor: not-allowed; box-shadow: none; color: #E8EEF3; + transform: none; + } #generate-btn:disabled::before { display: none; } - #generate-btn svg { display:inline-block; margin-left: 0.5em; width:1.2em; height:1.2em; vertical-align: middle; } - #output-section { margin-top: 3rem; background-color: #fff; border-radius: var(--radius-card); min-height: 200px; display: flex; align-items: center; justify-content: center; flex-direction: column; gap: 1.5rem; border: 1px solid var(--panel-border); transition: var(--transition-smooth), border-color 0.5s, box-shadow 0.5s; position: relative; box-shadow: var(--shadow-medium); padding: 1.5rem; } - #output-section.has-content { border-color: var(--accent-secondary); box-shadow: 0 0 30px -8px rgba(16, 185, 129, 0.35); } - #output-section.is-empty { background-color: var(--input-bg); box-shadow: var(--shadow-subtle) inset; border: 2px dashed var(--panel-border); } - #output-section.is-empty #custom-player-container { display: none !important; } - #output-section:not(.is-empty) #status-message, - #output-section:not(.is-empty) #loading-animation-wrapper { display: none !important; } + #generate-btn svg { + display:inline-block; margin-left: 0.5em; width:1.2em; height:1.2em; + vertical-align: middle; + } + + /* --- Output Section (now a container for status/loading/player) --- */ + #output-section { + margin-top: 3rem; + display: flex; + align-items: center; + justify-content: center; + flex-direction: column; + gap: 1.5rem; + min-height: 200px; + position: relative; + box-sizing: border-box; + padding: 1.5rem; /* Default padding for status/loading */ + } + /* Style for status message and loading when visible */ + #output-section #status-message, + #output-section #loading-animation-wrapper { + padding: 2rem; + background-color: var(--input-bg); + border-radius: var(--radius-card); + border: 2px dashed var(--panel-border); + box-shadow: var(--shadow-subtle) inset; + width: 100%; + box-sizing: border-box; + } + /* When output section has content (the player), remove its own styling */ + #output-section.has-content { + background-color: transparent; + border: none; + box-shadow: none; + padding: 0; /* Player wrapper will handle padding */ + min-height: auto; /* Shrink to fit player content */ + } + #output-section.has-content #status-message, + #output-section.has-content #loading-animation-wrapper { + display: none !important; + } + #status-message { font-weight: 500; color: var(--text-secondary); text-align: center; font-size: 1.1em; } - /* --- Custom Audio Player --- */ - #custom-player-container { + + /* --- انیمیشن پردازش --- */ + #loading-animation-wrapper { + display: none; + flex-direction: column; + align-items: center; + justify-content: center; + gap: 1.8rem; width: 100%; - padding: 1rem 1.2rem; + min-height: 150px; + } + .orbital-loader { + width: 110px; + height: 110px; + position: relative; + animation: rotate-loader-orbital 10s linear infinite; + } + .orbit { + position: absolute; + top: 50%; left: 50%; + border: 2px dashed rgba(59, 130, 246, 0.25); + border-radius: 50%; + transform-origin: center center; + } + .orbit:nth-child(1) { width: 35px; height: 35px; margin: -17.5px 0 0 -17.5px; animation: orbit-spin 2.8s linear infinite reverse; } + .orbit:nth-child(2) { width: 65px; height: 65px; margin: -32.5px 0 0 -32.5px; animation: orbit-spin 3.8s linear infinite; } + .orbit:nth-child(3) { width: 95px; height: 95px; margin: -47.5px 0 0 -47.5px; animation: orbit-spin 4.8s linear infinite reverse; } + + .orbit .satellite { + position: absolute; + width: 10px; height: 10px; + border-radius: 50%; + background-color: var(--accent-primary); + box-shadow: 0 0 8px var(--accent-primary), 0 0 12px var(--accent-secondary); + } + .orbit:nth-child(1) .satellite { top: -5px; left: 50%; animation: satellite-pulse-1 1.4s ease-in-out infinite alternate; } + .orbit:nth-child(2) .satellite { top: 50%; left: -5px; background-color: var(--accent-secondary); animation: satellite-pulse-2 1.4s 0.2s ease-in-out infinite alternate; } + .orbit:nth-child(3) .satellite { bottom: -5px; right: 50%; animation: satellite-pulse-3 1.4s 0.4s ease-in-out infinite alternate;} + + @keyframes rotate-loader-orbital { from { transform: rotate(0deg); } to { transform: rotate(360deg); } } + @keyframes orbit-spin { from { transform: rotate(0deg); } to { transform: rotate(360deg); } } + @keyframes satellite-pulse-1 { + from { transform: scale(0.7) translateX(-50%); opacity: 0.6; } + to { transform: scale(1.1) translateX(-50%); opacity: 1; } + } + @keyframes satellite-pulse-2 { + from { transform: scale(0.7) translateY(-50%); opacity: 0.6; } + to { transform: scale(1.1) translateY(-50%); opacity: 1; } + } + @keyframes satellite-pulse-3 { + from { transform: scale(0.7) translateX(50%); opacity: 0.6; } + to { transform: scale(1.1) translateX(50%); opacity: 1; } + } + #loading-text { + font-size: 1.2em; + font-weight: 700; + color: var(--text-primary); + text-align: center; + background: linear-gradient(45deg, var(--accent-primary), var(--accent-secondary)); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + } + + /* --- Custom Audio Player Styles --- */ + #audio-player-wrapper { + width: 100%; + background-color: var(--panel-bg); + border-radius: var(--radius-card); + box-shadow: var(--shadow-medium); + border: 1px solid var(--panel-border); + padding: 1.5rem; + display: flex; + flex-direction: column; + gap: 1.2rem; box-sizing: border-box; - display: none; /* Hidden by default */ } - .player-header { + + .audio-player-header { display: flex; align-items: center; + justify-content: flex-end; /* Align to right for RTL */ gap: 0.8rem; - margin-bottom: 1.2rem; - border: 1px solid var(--panel-border); - padding: 0.5rem 0.8rem; - border-radius: 12px; - background-color: var(--input-bg); + padding-bottom: 0.8rem; + border-bottom: 1px solid var(--panel-border); + margin-bottom: 0.8rem; } - .player-header .icon { - color: var(--text-secondary); + .audio-player-header .audio-player-title { + font-size: 1.1em; + font-weight: 600; + color: var(--text-primary); + margin-right: auto; /* Pushes icons to the right */ + } + .audio-player-header .audio-player-icons svg { width: 22px; height: 22px; + color: var(--text-secondary); /* Match the grey from image */ + vertical-align: middle; + margin-left: 0.5rem; /* Space between icons */ } - .player-header .title { - font-weight: 600; - color: var(--text-primary); - font-size: 1em; + .audio-player-header .audio-player-icons svg:last-child { + margin-left: 0; } - .waveform-container { - position: relative; + + #custom-audio-player { + background-color: transparent; + border: none; + box-shadow: none; + padding: 0; + border-radius: 0; + display: flex; + flex-direction: column; + gap: 1.2rem; width: 100%; - height: 70px; - cursor: pointer; + box-sizing: border-box; + } + + .audio-waveform-wrapper { display: flex; align-items: center; - gap: 2px; + gap: 0.8rem; + width: 100%; + } + .audio-time { + font-size: 0.9em; + color: var(--text-secondary); + min-width: 40px; + text-align: center; + font-variant-numeric: tabular-nums; /* Align numbers */ + } + .audio-current-time { + text-align: right; /* Time on the left of waveform for RTL */ + } + .audio-total-time { + text-align: left; /* Time on the right of waveform for RTL */ + } + + .audio-waveform-display { + flex-grow: 1; + height: 60px; /* Height of the waveform area */ + position: relative; + border-radius: 4px; + overflow: hidden; /* To contain the progress fill */ + /* Static background to mimic waveform bars */ + background-image: + linear-gradient(to top, var(--waveform-color-inactive) 20%, transparent 20%), + linear-gradient(to top, var(--waveform-color-inactive) 60%, transparent 60%), + linear-gradient(to top, var(--waveform-color-inactive) 40%, transparent 40%), + linear-gradient(to top, var(--waveform-color-inactive) 80%, transparent 80%), + linear-gradient(to top, var(--waveform-color-inactive) 30%, transparent 30%), + linear-gradient(to top, var(--waveform-color-inactive) 70%, transparent 70%), + linear-gradient(to top, var(--waveform-color-inactive) 50%, transparent 50%), + linear-gradient(to top, var(--waveform-color-inactive) 90%, transparent 90%), + linear-gradient(to top, var(--waveform-color-inactive) 25%, transparent 25%), + linear-gradient(to top, var(--waveform-color-inactive) 65%, transparent 65%), + linear-gradient(to top, var(--waveform-color-inactive) 45%, transparent 45%), + linear-gradient(to top, var(--waveform-color-inactive) 85%, transparent 85%); + background-size: 4px 100%; /* Width of each bar */ + background-repeat: repeat-x; + background-position: 0 0; + border: 1px dashed var(--waveform-color-inactive); /* Dashed line effect */ } - #waveform-canvas { + + .audio-progress-fill { position: absolute; top: 0; left: 0; - width: 100%; height: 100%; + width: 0%; /* Will be updated by JS */ + /* Active background to fill waveform bars as progress */ + background-image: + linear-gradient(to top, var(--waveform-color-active) 20%, transparent 20%), + linear-gradient(to top, var(--waveform-color-active) 60%, transparent 60%), + linear-gradient(to top, var(--waveform-color-active) 40%, transparent 40%), + linear-gradient(to top, var(--waveform-color-active) 80%, transparent 80%), + linear-gradient(to top, var(--waveform-color-active) 30%, transparent 30%), + linear-gradient(to top, var(--waveform-color-active) 70%, transparent 70%), + linear-gradient(to top, var(--waveform-color-active) 50%, transparent 50%), + linear-gradient(to top, var(--waveform-color-active) 90%, transparent 90%), + linear-gradient(to top, var(--waveform-color-active) 25%, transparent 25%), + linear-gradient(to top, var(--waveform-color-active) 65%, transparent 65%), + linear-gradient(to top, var(--waveform-color-active) 45%, transparent 45%), + linear-gradient(to top, var(--waveform-color-active) 85%, transparent 85%); + background-size: 4px 100%; + background-repeat: repeat-x; + background-position: 0 0; + transition: width 0.1s linear; /* Smooth progress animation */ } - .player-timestamps { + + + .audio-controls-bottom { display: flex; justify-content: space-between; - font-size: 0.85em; - color: var(--text-secondary); - font-weight: 500; - margin-top: 0.5rem; - padding: 0 0.2rem; + align-items: center; + width: 100%; } - .player-controls { + + .audio-left-group, .audio-center-group, .audio-right-group { display: flex; - justify-content: center; align-items: center; - gap: 0.8rem; - margin-top: 1.5rem; + gap: 0.5rem; } - .player-controls .ctrl-button { - background: var(--player-control-bg); - border: 1px solid var(--panel-border); + + .audio-center-group { + gap: 1.5rem; /* More space for main controls */ + } + + .audio-controls-bottom button { + background: none; + border: none; + cursor: pointer; + padding: 8px; border-radius: 50%; - width: 50px; - height: 50px; display: flex; align-items: center; justify-content: center; - cursor: pointer; - transition: all 0.2s ease; - color: var(--player-control-icon); + transition: background-color 0.2s, transform 0.2s; + color: var(--text-secondary); } - .player-controls .ctrl-button:hover { - background-color: var(--accent-primary); - color: #fff; - border-color: var(--accent-primary); - transform: scale(1.1); + .audio-controls-bottom button:hover { + background-color: var(--input-bg); + transform: scale(1.05); + } + .audio-controls-bottom button:active { + transform: scale(0.95); } - .player-controls .ctrl-button.play-pause { - width: 60px; - height: 60px; + + .audio-controls-bottom button svg { + width: 24px; + height: 24px; + fill: currentColor; + } + + /* Specific button styling */ + .audio-play-pause-btn { + width: 50px; + height: 50px; background-color: var(--accent-primary); color: #fff; - border-color: var(--accent-primary-hover); + border-radius: 50%; + box-shadow: 0 4px 10px rgba(59, 130, 246, 0.3); } - .player-controls .ctrl-button.play-pause:hover { + .audio-play-pause-btn:hover { background-color: var(--accent-primary-hover); + transform: scale(1.08); + box-shadow: 0 6px 15px rgba(59, 130, 246, 0.4); } - .player-controls .ctrl-button svg { - width: 24px; - height: 24px; - } - .player-controls .play-pause svg { - width: 30px; - height: 30px; + .audio-play-pause-btn:active { + transform: scale(0.95); } - #play-icon { display: block; } - #pause-icon { display: none; } - .player-settings { - display: flex; - align-items: center; - gap: 1rem; - position: absolute; - left: 2rem; + .audio-play-pause-btn svg { + width: 32px; + height: 32px; } - .setting-button { - background-color: var(--player-control-bg); - border: 1px solid var(--panel-border); - color: var(--player-control-icon); - padding: 0.4rem 0.8rem; - border-radius: 20px; - font-size: 0.85em; + + .audio-speed-btn { + font-family: var(--app-font); + font-size: 0.9em; font-weight: 600; - cursor: pointer; - transition: all 0.2s ease; - display: flex; - align-items: center; - gap: 0.3rem; - } - .setting-button:hover { - background-color: var(--player-control-icon); - color: #fff; + background-color: var(--input-bg); + border: 1px solid var(--panel-border); + padding: 6px 12px; + border-radius: 8px; + min-width: 40px; + text-align: center; + color: var(--text-primary); } - .setting-button svg { - width: 18px; - height: 18px; + .audio-speed-btn:hover { + background-color: #EAF0F6; + border-color: var(--accent-primary); } - /* --- انیمیشن پردازش --- */ - #loading-animation-wrapper { display: none; flex-direction: column; align-items: center; justify-content: center; gap: 1.8rem; width: 100%; min-height: 150px; } - .orbital-loader { width: 110px; height: 110px; position: relative; animation: rotate-loader-orbital 10s linear infinite; } - .orbit { position: absolute; top: 50%; left: 50%; border: 2px dashed rgba(59, 130, 246, 0.25); border-radius: 50%; transform-origin: center center; } - .orbit:nth-child(1) { width: 35px; height: 35px; margin: -17.5px 0 0 -17.5px; animation: orbit-spin 2.8s linear infinite reverse; } - .orbit:nth-child(2) { width: 65px; height: 65px; margin: -32.5px 0 0 -32.5px; animation: orbit-spin 3.8s linear infinite; } - .orbit:nth-child(3) { width: 95px; height: 95px; margin: -47.5px 0 0 -47.5px; animation: orbit-spin 4.8s linear infinite reverse; } - .orbit .satellite { position: absolute; width: 10px; height: 10px; border-radius: 50%; background-color: var(--accent-primary); box-shadow: 0 0 8px var(--accent-primary), 0 0 12px var(--accent-secondary); } - .orbit:nth-child(1) .satellite { top: -5px; left: 50%; animation: satellite-pulse-1 1.4s ease-in-out infinite alternate; } - .orbit:nth-child(2) .satellite { top: 50%; left: -5px; background-color: var(--accent-secondary); animation: satellite-pulse-2 1.4s 0.2s ease-in-out infinite alternate; } - .orbit:nth-child(3) .satellite { bottom: -5px; right: 50%; animation: satellite-pulse-3 1.4s 0.4s ease-in-out infinite alternate;} - @keyframes rotate-loader-orbital { from { transform: rotate(0deg); } to { transform: rotate(360deg); } } - @keyframes orbit-spin { from { transform: rotate(0deg); } to { transform: rotate(360deg); } } - @keyframes satellite-pulse-1 { from { transform: scale(0.7) translateX(-50%); opacity: 0.6; } to { transform: scale(1.1) translateX(-50%); opacity: 1; } } - @keyframes satellite-pulse-2 { from { transform: scale(0.7) translateY(-50%); opacity: 0.6; } to { transform: scale(1.1) translateY(-50%); opacity: 1; } } - @keyframes satellite-pulse-3 { from { transform: scale(0.7) translateX(50%); opacity: 0.6; } to { transform: scale(1.1) translateX(50%); opacity: 1; } } - #loading-text { font-size: 1.2em; font-weight: 700; color: var(--text-primary); text-align: center; background: linear-gradient(45deg, var(--accent-primary), var(--accent-secondary)); -webkit-background-clip: text; -webkit-text-fill-color: transparent; } - + /* Hide the default audio player */ + #audio-player { display: none !important; }
@@ -293,7 +779,6 @@در حال پردازش هوشمند و تولید صدا...