diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml
index 2870475..9aacc60 100644
--- a/.github/workflows/coverage.yml
+++ b/.github/workflows/coverage.yml
@@ -2,7 +2,7 @@ name: Coverage
on:
push:
- branches: [main, feature/*]
+ branches: ["main"]
jobs:
coverage:
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index fcd3fc7..0550bfc 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -50,5 +50,6 @@ jobs:
with:
files: |
target/release/PauseCat_Installer.msi
+ assets/default.webm
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
diff --git a/assets/overlay.html b/assets/overlay.html
index 27fdf07..1275bd8 100644
--- a/assets/overlay.html
+++ b/assets/overlay.html
@@ -143,12 +143,68 @@
}
.hidden { display: none !important; }
+
+ /* 3D Text Fallback */
+ .fallback-text-container {
+ position: fixed;
+ top: 0;
+ left: 0;
+ width: 100vw;
+ height: 100vh;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ z-index: -1;
+ perspective: 1000px;
+ background: linear-gradient(135deg, #1a1a1a 0%, #000 100%);
+ }
+
+ .fallback-text-3d {
+ font-size: 15vw;
+ font-weight: 900;
+ color: var(--text-color, #fff);
+ text-transform: uppercase;
+ letter-spacing: -0.05em;
+ transform: rotateX(var(--rot-x, 20deg)) rotateY(var(--rot-y, -20deg)) rotateZ(var(--rot-z, 0deg));
+
+ /* High-Fidelity Shadow / Extrusion / Glow */
+ text-shadow: var(--text-3d-shadow);
+ filter: var(--text-glow-filter, none);
+
+ opacity: var(--text-opacity, 0.15);
+ user-select: none;
+ pointer-events: none;
+ text-align: center;
+ }
+
+ @keyframes textFloat {
+ 0%, 100% { transform: rotateX(var(--rot-x, 20deg)) rotateY(var(--rot-y, -20deg)) rotateZ(var(--rot-z, 0deg)) translateZ(0); }
+ 50% { transform: rotateX(calc(var(--rot-x, 20deg) + 5deg)) rotateY(calc(var(--rot-y, -20deg) + 5deg)) rotateZ(var(--rot-z, 0deg)) translateZ(50px); }
+ }
+
+ @keyframes textRotate {
+ 0% { transform: rotateX(var(--rot-x, 20deg)) rotateY(0deg) rotateZ(var(--rot-z, 0deg)); }
+ 100% { transform: rotateX(var(--rot-x, 20deg)) rotateY(360deg) rotateZ(var(--rot-z, 0deg)); }
+ }
+
+ @keyframes textSwing {
+ 0%, 100% { transform: rotateX(var(--rot-x, 20deg)) rotateY(-40deg) rotateZ(var(--rot-z, 0deg)); }
+ 50% { transform: rotateX(var(--rot-x, 20deg)) rotateY(40deg) rotateZ(var(--rot-z, 0deg)); }
+ }
+
+ @keyframes textPulse {
+ 0%, 100% { transform: rotateX(var(--rot-x, 20deg)) rotateY(var(--rot-y, -20deg)) rotateZ(var(--rot-z, 0deg)) scale(1); opacity: var(--text-opacity, 0.15); }
+ 50% { transform: rotateX(var(--rot-x, 20deg)) rotateY(var(--rot-y, -20deg)) rotateZ(var(--rot-z, 0deg)) scale(1.1); opacity: calc(var(--text-opacity, 0.15) + 0.1); }
+ }
@@ -200,6 +256,32 @@
}, 500);
}
+ function generate3DShadow(color, depth) {
+ let shadows = [];
+ for (let i = 1; i <= depth; i++) {
+ // Heavier extrusion with gradual darkening
+ let shadowColor = adjustColor(color, -i * 6);
+ shadows.push(`${i}px ${i}px 0px ${shadowColor}`);
+ }
+ shadows.push(`0 ${depth + 1}px 15px rgba(0,0,0,0.5)`);
+ shadows.push(`0 ${depth + 8}px 30px rgba(0,0,0,0.3)`);
+ return shadows.join(', ');
+ }
+
+ function adjustColor(hex, amount) {
+ if (hex === 'transparent' || hex === 'none') return hex;
+ let usePound = false;
+ if (hex[0] == "#") { hex = hex.slice(1); usePound = true; }
+ let num = parseInt(hex, 16);
+ let r = (num >> 16) + amount;
+ if (r > 255) r = 255; else if (r < 0) r = 0;
+ let b = ((num >> 8) & 0x00FF) + amount;
+ if (b > 255) b = 255; else if (b < 0) b = 0;
+ let g = (num & 0x0000FF) + amount;
+ if (g > 255) g = 255; else if (g < 0) g = 0;
+ return (usePound ? "#" : "") + (g | (b << 8) | (r << 16)).toString(16).padStart(6, '0');
+ }
+
window.chrome.webview.addEventListener('message', event => {
if (event.data.action === "init") {
seconds = event.data.duration;
@@ -219,7 +301,7 @@
root.style.setProperty('--bubble-size', event.data.bubbleSize + 'px');
root.style.setProperty('--glass-bg', `rgba(${event.data.isDark ? '0,0,0' : '255,255,255'}, ${event.data.bubbleOpacity})`);
- // Smart Position: Account for bubble size so it doesn't clip off edge at 100%
+ // Smart Position
bubble.style.left = `calc(${event.data.bubblePosX}% - ${event.data.bubbleSize * (event.data.bubblePosX/100)}px)`;
bubble.style.top = `calc(${event.data.bubblePosY}% - ${event.data.bubbleSize * (event.data.bubblePosY/100)}px)`;
@@ -227,6 +309,55 @@
bubble.style.animation = `${event.data.animationStyle} 6s ease-in-out infinite`;
}
+ // Custom 3D Text Logic
+ const fallback = document.getElementById('fallback-ui');
+ const fallbackText = fallback.querySelector('.fallback-text-3d');
+ if (event.data.customText) {
+ fallbackText.innerText = event.data.customText;
+ }
+
+ // Adaptive Color Logic
+ let finalColor = event.data.textColor || '#ffffff';
+ if (event.data.adaptiveTextColor) {
+ finalColor = event.data.isDark ? '#ffffff' : '#000000';
+ }
+
+ // Apply advanced text styles
+ root.style.setProperty('--text-color', finalColor);
+ root.style.setProperty('--text-opacity', event.data.textOpacity ?? 0.15);
+ root.style.setProperty('--rot-x', (event.data.textRotationX ?? 20) + 'deg');
+ root.style.setProperty('--rot-y', (event.data.textRotationY ?? -20) + 'deg');
+ root.style.setProperty('--rot-z', (event.data.textRotationZ ?? 0) + 'deg');
+
+ // Glow Logic
+ if (event.data.textGlowEnabled) {
+ const glowColor = event.data.textGlowColor || finalColor;
+ root.style.setProperty('--text-glow-filter', `drop-shadow(0 0 ${(event.data.textGlow ?? 10)}px ${glowColor})`);
+ } else {
+ root.style.setProperty('--text-glow-filter', 'none');
+ }
+
+ root.style.setProperty('--text-3d-shadow', generate3DShadow(finalColor, event.data.textDepth ?? 5));
+
+ const textAnim = event.data.textAnimation || 'float';
+ if (textAnim === 'float') {
+ fallbackText.style.animation = 'textFloat 8s ease-in-out infinite';
+ } else if (textAnim === 'rotate') {
+ fallbackText.style.animation = 'textRotate 10s linear infinite';
+ } else if (textAnim === 'swing') {
+ fallbackText.style.animation = 'textSwing 6s ease-in-out infinite';
+ } else if (textAnim === 'pulse') {
+ fallbackText.style.animation = 'textPulse 4s ease-in-out infinite';
+ } else {
+ fallbackText.style.animation = 'none';
+ }
+
+ if (event.data.breakStyle === 'text') {
+ fallback.classList.remove('hidden');
+ } else {
+ fallback.classList.add('hidden');
+ }
+
// Break Messages
if (event.data.breakMessages && event.data.breakMessages.length > 0) {
breakMessages = event.data.breakMessages;
@@ -236,7 +367,7 @@
}
}
- // Work Duration Status (Smart Formatting)
+ // Work Duration Status
if (event.data.showWorkStatus) {
const workStatusEl = document.getElementById('work-status-text');
workStatusEl.classList.remove('hidden');
@@ -253,14 +384,29 @@
}
}
- if (event.data.mediaPath) {
+ if (event.data.mediaPath && event.data.breakStyle !== 'text') {
const img = document.getElementById('bg-image');
const video = document.getElementById('bg-video');
+ const fallback = document.getElementById('fallback-ui');
const ext = event.data.mediaPath.split('.').pop().toLowerCase();
+
+ video.onerror = () => {
+ console.warn("Video load failed, showing fallback UI");
+ video.classList.add('hidden');
+ fallback.classList.remove('hidden');
+ };
+
+ // Set Volume
+ video.volume = event.data.videoVolume ?? 0.0;
+
if (['mp4', 'webm', 'ogg'].includes(ext)) {
video.src = event.data.mediaPath;
video.classList.remove('hidden');
- video.play().catch(e => console.error(e));
+ video.play().catch(e => {
+ console.error(e);
+ video.classList.add('hidden');
+ fallback.classList.remove('hidden');
+ });
} else {
img.src = event.data.mediaPath;
img.classList.remove('hidden');
diff --git a/assets/settings.html b/assets/settings.html
index f6beec9..b8f0828 100644
--- a/assets/settings.html
+++ b/assets/settings.html
@@ -16,13 +16,6 @@
--ring: #f4ebff;
--card-bg: #ffffff;
--header-bg: #ffffff;
- --glass-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -2px rgba(0, 0, 0, 0.1);
- --update-bg: #ecfdf3;
- --update-text: #027a48;
- --update-border: #abfdfd;
- --danger-bg: #fef2f2;
- --danger-text: #b91c1c;
- --danger-border: #fecaca;
}
body.dark {
@@ -36,191 +29,196 @@
--ring: #2d1d5a;
--card-bg: #1a1a1a;
--header-bg: #121212;
- --update-bg: #052e16;
- --update-text: #6ee7b7;
- --update-border: #064e3b;
- --danger-bg: #450a0a;
- --danger-text: #fca5a5;
- --danger-border: #7f1d1d;
}
- html, body {
- overflow: hidden;
- touch-action: none;
- user-select: none;
- -webkit-user-drag: none;
- }
+ html, body { overflow: hidden; touch-action: none; user-select: none; }
body {
font-family: 'Inter', system-ui, -apple-system, sans-serif;
- background-color: var(--bg-color);
- color: var(--text-main);
- margin: 0;
- padding: 0;
- height: 100vh;
- display: flex;
- flex-direction: column;
+ background-color: var(--bg-color); color: var(--text-main);
+ margin: 0; padding: 0; height: 100vh;
+ display: flex; flex-direction: column;
transition: background-color 0.3s, color 0.3s;
}
.header {
- padding: 16px 24px;
- display: flex;
- align-items: center; gap: 12px;
- border-bottom: 1px solid var(--border);
- background: var(--header-bg);
- z-index: 10; flex-shrink: 0;
+ padding: 16px 24px; display: flex; align-items: center; gap: 12px;
+ border-bottom: 1px solid var(--border); background: var(--header-bg); flex-shrink: 0;
}
-
.header h1 { font-size: 1.125rem; font-weight: 600; margin: 0; }
- .header img { width: 28px; height: 28px; border-radius: 6px; object-fit: contain; }
+ .header img { width: 28px; height: 28px; border-radius: 6px; }
.scroll-container {
flex: 1; overflow-y: auto; padding: 20px 24px;
- background: var(--secondary-bg);
- scrollbar-width: none; -ms-overflow-style: none;
+ background: var(--secondary-bg); scrollbar-width: none;
}
.scroll-container::-webkit-scrollbar { display: none; }
.section-title {
- font-size: 0.7rem; font-weight: 600;
- color: var(--text-secondary); text-transform: uppercase;
- letter-spacing: 0.05em; margin-bottom: 10px; margin-top: 10px;
+ font-size: 0.7rem; font-weight: 600; color: var(--text-secondary);
+ text-transform: uppercase; letter-spacing: 0.05em; margin: 12px 0 8px 0;
}
.card {
- background: var(--card-bg);
- border: 1px solid var(--border);
- border-radius: 12px; padding: 16px;
- margin-bottom: 20px; box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
- }
-
- /* Modal / Popup Styles */
- .modal-overlay {
- position: fixed; top: 0; left: 0; right: 0; bottom: 0;
- background: rgba(0, 0, 0, 0.5);
- display: flex; justify-content: center; align-items: center;
- z-index: 1000; animation: fadeIn 0.3s ease;
- }
-
- .modal-content {
- background: var(--bg-color);
- width: 85%; max-width: 400px;
- border-radius: 16px; padding: 24px;
- box-shadow: 0 20px 25px -5px rgba(0,0,0,0.2);
- border: 1px solid var(--border);
- text-align: center;
- }
-
- .modal-title { font-size: 1.25rem; font-weight: 700; margin-bottom: 12px; display: block; }
- .modal-desc { font-size: 0.9rem; color: var(--text-secondary); margin-bottom: 24px; line-height: 1.5; display: block; }
-
- /* Progress Bar for Update */
- .progress-container {
- width: 100%; height: 8px;
- background: var(--secondary-bg);
- border-radius: 4px; overflow: hidden;
- margin-bottom: 12px; border: 1px solid var(--border);
- }
- .progress-bar {
- height: 100%; background: var(--accent);
- width: 0%; transition: width 0.2s ease;
+ background: var(--card-bg); border: 1px solid var(--border);
+ border-radius: 12px; padding: 16px; margin-bottom: 24px;
+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
}
.setting-row {
- display: flex; justify-content: space-between;
- align-items: center; margin-bottom: 16px; gap: 12px;
+ display: flex; justify-content: space-between; align-items: center;
+ margin-bottom: 16px; gap: 16px;
}
.setting-row:last-child { margin-bottom: 0; }
- .setting-info { display: flex; flex-direction: column; gap: 2px; flex: 1; }
- .setting-label { font-size: 0.875rem; font-weight: 500; }
- .setting-description { font-size: 0.75rem; color: var(--text-secondary); }
+ .setting-info { display: flex; flex-direction: column; gap: 2px; flex: 1; min-width: 0; }
+ .setting-label { font-size: 0.9rem; font-weight: 600; white-space: nowrap; }
+ .setting-description { font-size: 0.75rem; color: var(--text-secondary); overflow: hidden; text-overflow: ellipsis; }
+
+ .setting-control { display: flex; align-items: center; justify-content: flex-end; min-width: 140px; gap: 8px; }
input[type="number"], input[type="text"], select {
- padding: 6px 10px; border: 1px solid var(--border);
- border-radius: 6px; font-size: 0.85rem; outline: none;
- transition: all 0.2s; background: var(--card-bg);
- color: var(--text-main); font-family: inherit;
+ padding: 8px 12px; border: 1px solid var(--border);
+ border-radius: 8px; font-size: 0.85rem; outline: none;
+ background: var(--card-bg); color: var(--text-main); transition: border-color 0.2s;
+ }
+ input[type="number"] { width: 70px; }
+ select { width: 130px; }
+ input[type="text"] { width: 100%; box-sizing: border-box; }
+
+ input[type="range"] {
+ -webkit-appearance: none; width: 100px; height: 4px;
+ background: var(--border); border-radius: 2px; outline: none;
+ accent-color: var(--accent); cursor: pointer;
}
- input[type="number"] { width: 65px; }
- select { width: 110px; }
- input[type="range"] { width: 120px; accent-color: var(--accent); cursor: pointer; }
- select option { background-color: var(--card-bg); color: var(--text-main); }
- input:focus, select:focus { border-color: var(--accent); box-shadow: 0 0 0 3px var(--ring); }
.preview-container {
- width: 100%; height: 160px; background: #000;
- border-radius: 10px; position: relative; overflow: hidden;
- margin-bottom: 20px; border: 1px solid var(--border); flex-shrink: 0;
+ width: 100%; aspect-ratio: 16 / 9; background: #000;
+ border-radius: 12px; position: relative; overflow: hidden;
+ margin-bottom: 12px; border: 1px solid var(--border); flex-shrink: 0;
+ perspective: 1000px;
+ }
+ .preview-bg { width: 100%; height: 100%; object-fit: cover; opacity: 0.5; position: absolute; top:0; left:0; z-index: 0; }
+
+ .preview-text-3d-container {
+ position: absolute; top: 0; left: 0; width: 100%; height: 100%;
+ display: flex; justify-content: center; align-items: center;
+ pointer-events: none; z-index: 1;
}
- .preview-bg { width: 100%; height: 100%; object-fit: cover; opacity: 0.5; }
+ .preview-text-3d {
+ font-size: 5vw; font-weight: 950; color: var(--text-color, #fff);
+ text-transform: uppercase; text-align: center; line-height: 1;
+ transform: rotateX(var(--rot-x, 20deg)) rotateY(var(--rot-y, -20deg)) rotateZ(var(--rot-z, 0deg));
+ text-shadow: var(--text-3d-shadow); opacity: var(--text-opacity, 0.2);
+ animation: previewFloat 5s ease-in-out infinite;
+ filter: var(--text-glow-filter, none);
+ }
+ @keyframes previewFloat {
+ 0%, 100% { transform: rotateX(var(--rot-x, 20deg)) rotateY(var(--rot-y, -20deg)) rotateZ(var(--rot-z, 0deg)) translateZ(0); }
+ 50% { transform: rotateX(calc(var(--rot-x, 20deg) + 5deg)) rotateY(calc(var(--rot-y, -20deg) + 5deg)) rotateZ(var(--rot-z, 0deg)) translateZ(20px); }
+ }
+
.preview-bubble {
position: absolute; background: rgba(255, 255, 255, 0.1);
backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px);
border: 1px solid rgba(255, 255, 255, 0.2); border-radius: 50%;
display: flex; justify-content: center; align-items: center;
color: white; font-weight: 700; pointer-events: none;
- box-shadow: 0 8px 16px rgba(0,0,0,0.3);
- transition: all 0.2s ease;
+ box-shadow: 0 8px 16px rgba(0,0,0,0.3); z-index: 2;
+ transition: all 0.3s ease;
}
- .media-preview-area { position: relative; margin-top: 10px; }
- .media-preview {
- width: 100%; height: 140px; border: 2px dashed var(--border);
- border-radius: 10px; display: flex; flex-direction: column;
- justify-content: center; align-items: center; background: var(--card-bg);
- cursor: pointer; transition: all 0.2s; overflow: hidden;
+ .status-footer {
+ margin-bottom: 24px; padding: 0 4px; display: flex; justify-content: space-between; align-items: center;
+ font-size: 0.75rem; font-weight: 500; color: var(--text-secondary);
}
- .media-preview:hover { border-color: var(--accent); background: var(--secondary-bg); }
- .media-preview img, .media-preview video { width: 100%; height: 100%; object-fit: cover; }
- .media-placeholder { display: flex; flex-direction: column; align-items: center; gap: 6px; color: var(--text-secondary); font-size: 0.8rem; }
+ .status-dot { width: 8px; height: 8px; border-radius: 50%; display: inline-block; margin-right: 4px; }
+ .dot-ready { background: #22c55e; box-shadow: 0 0 8px #22c55e; }
+ .dot-missing { background: #eab308; box-shadow: 0 0 8px #eab308; }
+ .dot-error { background: #ef4444; box-shadow: 0 0 8px #ef4444; }
- .reset-media {
- position: absolute; top: 6px; right: 6px; background: rgba(16, 24, 40, 0.7);
- color: white; border: none; border-radius: 6px; padding: 3px 6px;
- font-size: 0.7rem; font-weight: 500; cursor: pointer; backdrop-filter: blur(4px);
+ .asset-progress-container {
+ width: 80px; height: 4px; background: var(--border);
+ border-radius: 2px; overflow: hidden; margin-left: 8px;
+ display: inline-block; vertical-align: middle;
}
+ .asset-progress-bar { height: 100%; background: var(--accent); width: 0%; transition: width 0.3s ease; }
- .list-container { margin-top: 10px; display: flex; flex-wrap: wrap; gap: 6px; }
- .tag {
- background: var(--ring); color: var(--accent); padding: 3px 8px;
- border-radius: 12px; font-size: 0.7rem; font-weight: 600;
- display: flex; align-items: center; gap: 4px; border: 1px solid var(--accent);
+ .retry-btn {
+ background: none; border: 1px solid var(--accent); color: var(--accent);
+ padding: 2px 6px; border-radius: 4px; font-size: 0.65rem; cursor: pointer;
+ margin-left: 8px;
}
- .tag span { cursor: pointer; font-size: 0.9rem; line-height: 1; }
- .add-row { display: flex; gap: 6px; margin-top: 12px; }
- .add-row input, .add-row select { flex: 1; width: auto; }
+ .media-preview-area { margin-top: 12px; }
+ .media-preview {
+ width: 100%; height: 160px; border: 2px dashed var(--border);
+ border-radius: 12px; display: flex; justify-content: center; align-items: center;
+ background: var(--card-bg); cursor: pointer; overflow: hidden; position: relative;
+ transition: all 0.2s;
+ }
+ .media-preview:hover { border-color: var(--accent); background: var(--secondary-bg); }
+ .media-preview img, .media-preview video { width: 100%; height: 100%; object-fit: cover; position: absolute; top:0; left:0; }
+ .media-placeholder { display: flex; flex-direction: column; align-items: center; color: var(--text-secondary); font-size: 0.85rem; z-index: 1; }
- .footer {
- padding: 12px 24px; background: var(--header-bg); border-top: 1px solid var(--border);
- display: flex; justify-content: flex-end; gap: 10px; flex-shrink: 0;
+ .list-container { margin-top: 12px; display: flex; flex-wrap: wrap; gap: 8px; }
+ .tag {
+ background: var(--ring); color: var(--accent); padding: 4px 10px;
+ border-radius: 12px; font-size: 0.75rem; font-weight: 600;
+ display: flex; align-items: center; gap: 6px; border: 1px solid var(--accent);
}
+ .tag span { cursor: pointer; font-size: 1rem; line-height: 1; }
+
+ .add-row { display: flex; gap: 8px; margin-top: 14px; }
- button {
- padding: 8px 14px; border-radius: 6px; font-size: 0.85rem;
- font-weight: 600; cursor: pointer; transition: all 0.2s; border: 1px solid transparent;
+ .footer {
+ padding: 16px 24px; background: var(--header-bg); border-top: 1px solid var(--border);
+ display: flex; justify-content: flex-end; gap: 12px; flex-shrink: 0;
}
- .btn-primary { background-color: var(--accent); color: white; border-color: var(--accent); }
- .btn-primary:hover { background-color: var(--accent-hover); }
- .btn-secondary { background-color: var(--bg-color); color: var(--text-main); border-color: var(--border); }
- .btn-secondary:hover { background-color: var(--secondary-bg); }
+ button { padding: 10px 18px; border-radius: 8px; font-size: 0.85rem; font-weight: 600; cursor: pointer; border: 1px solid transparent; transition: all 0.2s; }
+ .btn-primary { background: var(--accent); color: white; }
+ .btn-primary:hover { background: var(--accent-hover); transform: translateY(-1px); }
+ .btn-secondary { background: var(--bg-color); color: var(--text-main); border-color: var(--border); }
+ .btn-secondary:hover { background: var(--secondary-bg); }
- .switch { position: relative; display: inline-block; width: 36px; height: 18px; }
+ .switch { position: relative; display: inline-block; width: 40px; height: 20px; }
.switch input { opacity: 0; width: 0; height: 0; }
- .slider { position: absolute; cursor: pointer; top: 0; left: 0; right: 0; bottom: 0; background-color: var(--border); transition: .3s; border-radius: 18px; }
- .slider:before { position: absolute; content: ""; height: 14px; width: 14px; left: 2px; bottom: 2px; background-color: white; transition: .3s; border-radius: 50%; }
+ .slider { position: absolute; cursor: pointer; top: 0; left: 0; right: 0; bottom: 0; background-color: var(--border); transition: .3s; border-radius: 20px; }
+ .slider:before { position: absolute; content: ""; height: 16px; width: 16px; left: 2px; bottom: 2px; background-color: white; transition: .3s; border-radius: 50%; }
input:checked + .slider { background-color: var(--accent); }
- input:checked + .slider:before { transform: translateX(18px); }
+ input:checked + .slider:before { transform: translateX(20px); }
- .hidden { display: none !important; }
+ /* Modal / Popup Styles */
+ .modal-overlay {
+ position: fixed; top: 0; left: 0; right: 0; bottom: 0;
+ background: rgba(0, 0, 0, 0.5);
+ display: flex; justify-content: center; align-items: center;
+ z-index: 1000; animation: fadeIn 0.3s ease;
+ }
- @keyframes float { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-10px); } }
- @keyframes bounce { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.08); } }
- @keyframes pulse { 0%, 100% { transform: scale(1); opacity: var(--pulse-opacity-start); } 50% { transform: scale(1.05); opacity: var(--pulse-opacity-end); } }
- @keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }
+ .modal-content {
+ background: var(--bg-color);
+ width: 85%; max-width: 400px;
+ border-radius: 16px; padding: 24px;
+ box-shadow: 0 20px 25px -5px rgba(0,0,0,0.2);
+ border: 1px solid var(--border);
+ text-align: center;
+ }
+
+ .modal-title { font-size: 1.25rem; font-weight: 700; margin-bottom: 12px; display: block; }
+ .modal-desc { font-size: 0.9rem; color: var(--text-secondary); margin-bottom: 24px; line-height: 1.5; display: block; }
+
+ .progress-container {
+ width: 100%; height: 8px;
+ background: var(--secondary-bg);
+ border-radius: 4px; overflow: hidden;
+ margin-bottom: 12px; border: 1px solid var(--border);
+ }
+ .progress-bar {
+ height: 100%; background: var(--accent);
+ width: 0%; transition: width 0.2s ease;
+ }
.notification {
position: fixed; bottom: 24px; left: 24px; right: 24px; padding: 16px;
@@ -228,29 +226,29 @@
box-shadow: 0 12px 24px rgba(0,0,0,0.15); z-index: 1100;
display: flex; flex-direction: column; gap: 8px; animation: slideUp 0.4s cubic-bezier(0.16, 1, 0.3, 1);
}
- @keyframes slideUp { from { transform: translateY(100%) opacity: 0; } to { transform: translateY(0) opacity: 1; } }
+
+ @keyframes slideUp { from { transform: translateY(100%); opacity: 0; } to { transform: translateY(0); opacity: 1; } }
+ @keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }
+
+ .hidden { display: none !important; }