:root {
    --primary-color: #ffffff;
    --secondary-color: #a78bfa;
    --text-color-light: #e2e8f0;
    --text-color-dark: #1e293b;
    --bg-glass-light: rgba(255, 255, 255, 0.1);
    --bg-glass-dark: rgba(0, 0, 0, 0.2);
    --border-color: rgba(255, 255, 255, 0.2);
    --shadow-color: rgba(0, 0, 0, 0.1);
    --track-color: rgba(255, 255, 255, 0.18);
    --alert-color: #f87171;
    --urgency-mid-color: #fb923c;
}

* { margin: 0; padding: 0; box-sizing: border-box; }

body {
    font-family: 'Poppins', sans-serif;
    color: var(--text-color-light);
    overflow-x: hidden;
    overflow-y: auto;
}

#app-bg {
    position: fixed; top: 0; left: 0; width: 100%; height: 100%;
    background-size: cover; background-position: center;
    transition: background-image 1s ease-in-out;
    z-index: -1;
}
/* Capa de partículas animadas (hojas/niebla/destellos según el tema).
   Va entre la imagen de fondo y el velo oscuro (mismo z-index que ambos;
   el orden en el DOM decide el apilado), así el efecto se ve "dentro"
   de la escena en vez de flotar por encima del panel. Nunca captura
   clics ni se lee con lectores de pantalla. */
#app-particles {
    position: fixed; top: 0; left: 0; width: 100%; height: 100%;
    z-index: -1; pointer-events: none;
}
#app-overlay {
    position: fixed; top: 0; left: 0; width: 100%; height: 100%;
    background-color: rgba(0, 0, 0, 0.3);
    z-index: -1; transition: background-color 0.5s;
}

.app-container {
    display: flex; justify-content: center; align-items: center;
    min-height: 100vh; padding: 20px;
}

.main-panel {
    background: var(--bg-glass-light);
    backdrop-filter: blur(15px);
    border: 1px solid var(--border-color);
    border-radius: 20px;
    padding: 40px;
    width: 100%;
    max-width: 500px;
    text-align: center;
    box-shadow: 0 8px 32px 0 var(--shadow-color);
    transition: background 0.5s;
}
.main-panel h1 { font-size: 2.5rem; font-weight: 600; margin-bottom: 12px; }

/* Página de política de privacidad: mismo panel, más ancho y con texto alineado a la izquierda */
.legal-panel { max-width: 680px; text-align: left; }
.legal-title { font-size: 1.9rem; font-weight: 600; margin-bottom: 4px; text-align: left; }
.legal-updated { font-size: 0.8rem; opacity: 0.65; font-weight: 300; margin-bottom: 26px; }
.legal-section { margin-bottom: 20px; }
.legal-section h2 {
    font-size: 1.05rem; font-weight: 600; margin-bottom: 8px; color: var(--secondary-color);
}
.legal-section p { font-size: 0.9rem; font-weight: 300; line-height: 1.6; color: var(--text-color-light); }
.legal-section a { color: var(--secondary-color); }
.legal-back {
    display: inline-block; margin-top: 10px; font-size: 0.85rem;
    color: var(--text-color-light); opacity: 0.75; text-decoration: none;
    transition: opacity 0.2s;
}
.legal-back:hover { opacity: 1; text-decoration: underline; }

/* Panel de lista de tareas */
.task-panel { margin-bottom: 14px; text-align: left; }
.task-panel-header {
    text-align: center; font-size: 1.05rem; font-weight: 300;
    color: var(--text-color-light); margin-bottom: 10px; min-height: 24px;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.task-add-row { display: flex; gap: 8px; margin-bottom: 10px; }
.task-add-row input {
    flex: 1; background: rgba(255, 255, 255, 0.08); border: 1px solid var(--border-color);
    border-radius: 10px; padding: 8px 12px; color: var(--text-color-light);
    font-family: 'Poppins', sans-serif; font-size: 0.85rem; outline: none;
    transition: border-color 0.2s;
}
.task-add-row input:focus { border-color: var(--secondary-color); }
.task-add-row input::placeholder { color: rgba(226, 232, 240, 0.5); }
.task-add-row button {
    width: 36px; height: 36px; flex-shrink: 0; border-radius: 10px; border: none;
    background: var(--secondary-color); color: var(--text-color-dark);
    font-size: 1.2rem; font-weight: 700; line-height: 1; cursor: pointer;
    transition: transform 0.2s;
}
.task-add-row button:hover { transform: scale(1.05); }

.task-list {
    list-style: none; max-height: 160px; overflow-y: auto;
    display: flex; flex-direction: column; gap: 6px;
}
.task-list::-webkit-scrollbar { width: 6px; }
.task-list::-webkit-scrollbar-thumb { background: rgba(255, 255, 255, 0.25); border-radius: 3px; }

.task-item {
    display: flex; align-items: center; gap: 8px; padding: 8px 10px;
    border-radius: 10px; background: rgba(255, 255, 255, 0.06);
    border: 1px solid transparent; cursor: pointer;
    overflow: hidden;
    transition: background 0.2s, border-color 0.2s,
                transform 0.22s ease, opacity 0.22s ease,
                max-height 0.2s ease, padding 0.2s ease,
                margin-bottom 0.2s ease, border-width 0.2s ease;
}
.task-item:hover { background: rgba(255, 255, 255, 0.12); }
.task-item.active { border-color: var(--secondary-color); background: rgba(167, 139, 250, 0.18); }
.task-item.completed { opacity: 0.65; }

/* Slide-in + fade al agregar una tarea nueva. La clase .task-item-enter
   se aplica solo al ítem recién creado (ver renderTasks en java.js) y se
   descarta después de ese único render, así que los demás ítems de la
   lista no la repiten cuando se vuelve a dibujar por otros motivos
   (tildar, borrar, cambiar de tarea activa). */
@keyframes task-slide-in {
    0% { opacity: 0; transform: translateY(-8px); }
    100% { opacity: 1; transform: translateY(0); }
}
.task-item.task-item-enter {
    animation: task-slide-in 0.3s ease-out;
}

/* Salida animada al borrar una tarea (ver animateTaskDeletion en java.js).
   Fase 1 — .task-item-exit: desliza y desvanece el ítem completo.
   Fase 2 — .task-item-collapse: una vez terminada la fase 1, JS fija la
   altura actual en max-height (inline) y la lleva a 0, además de achicar
   padding/margen/borde, para que las tareas de abajo suban suavemente.
   Recién cuando termina la fase 2 se saca el <li> del DOM. */
.task-item.task-item-exit {
    transform: translateX(28px);
    opacity: 0;
    pointer-events: none;
}
.task-item.task-item-collapse {
    padding-top: 0;
    padding-bottom: 0;
    margin-bottom: -6px;
    border-width: 0;
}

.task-check { position: relative; width: 18px; height: 18px; flex-shrink: 0; cursor: pointer; }
.task-check input { position: absolute; opacity: 0; width: 100%; height: 100%; margin: 0; cursor: pointer; }
.task-check-box {
    display: block; width: 18px; height: 18px; border-radius: 5px;
    border: 1.5px solid var(--text-color-light); transition: all 0.2s;
}
.task-check input:checked + .task-check-box {
    background: var(--secondary-color); border-color: var(--secondary-color);
}
.task-check input:checked + .task-check-box::after {
    content: ''; display: block; width: 5px; height: 9px;
    border: solid var(--text-color-dark); border-width: 0 2px 2px 0;
    transform: rotate(45deg); margin: 1px auto 0 5px;
}

.task-text {
    position: relative;
    flex: 1; font-size: 0.88rem; font-weight: 300; color: var(--text-color-light);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* Tachado animado al completar una tarea. text-decoration no se puede
   animar directamente, así que usamos un ::after que crece de 0% a 100%
   de ancho (y se encoge igual al destildar). Para que la transición se
   vea, el <li> no debe reconstruirse por completo al tildar: el listener
   del checkbox alterna esta clase directo sobre el nodo existente en vez
   de disparar un renderTasks() completo (ver java.js). */
.task-text::after {
    content: '';
    position: absolute;
    left: 0;
    top: 50%;
    height: 1px;
    width: 0%;
    background: currentColor;
    transition: width 0.35s ease;
}
.task-item.completed .task-text::after {
    width: 100%;
}
.task-pomo-count { font-size: 0.75rem; opacity: 0.8; flex-shrink: 0; }
.task-delete {
    background: none; border: none; color: var(--text-color-light);
    font-size: 1.1rem; line-height: 1; cursor: pointer; opacity: 0.4;
    flex-shrink: 0; padding: 2px 4px; transition: opacity 0.2s, color 0.2s;
}
.task-item:hover .task-delete { opacity: 0.8; }
.task-delete:hover { opacity: 1 !important; color: #f87171; }

/* Anillo de progreso + temporizador */
.timer-circle { position: relative; width: 240px; height: 240px; margin: 15px auto 20px; }
.timer-circle svg { width: 100%; height: 100%; transform: rotate(-90deg); }
.timer-circle circle {
    fill: none; stroke-width: 10; cx: 130px; cy: 130px; r: 110px;
}
.timer-circle .track { stroke: var(--track-color); }
.timer-circle .progress {
    stroke: var(--secondary-color);
    stroke-linecap: round;
    fill: none;
    transition: stroke-dashoffset 1s linear, stroke 1s linear, stroke-width 1s ease;
}

/* ============================================================
   DIBUJO DE ENTRADA DEL ANILLO
   Al cargar la página, el trazo de progreso se "dibuja" de forma
   progresiva (stroke-dashoffset: 100% del perímetro → 0) en vez de
   aparecer completo de golpe. Se activa con la clase .ring-draw-in
   en el <circle class="progress">; JS la quita al terminar la
   animación para no interferir con la transición normal del
   progreso durante el uso del temporizador. --circumference es la
   misma constante (2πr) que usa JS para el cálculo real del
   progreso, fijada como variable CSS inline. */
@keyframes ring-draw-in {
    from { stroke-dashoffset: var(--circumference, 691.15); }
    to   { stroke-dashoffset: var(--ring-draw-in-target, 0); }
}
.timer-circle .progress.ring-draw-in {
    transition: none;
    animation: ring-draw-in 1.4s cubic-bezier(0.65, 0, 0.35, 1) both;
}
#timer-display {
    position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);
    font-size: 2.8rem; font-weight: 700;
    z-index: 2;
    text-shadow: 0 1px 6px rgba(0, 0, 0, 0.35);
}

/* Canvas de la estela de partículas: se superpone exacto al SVG del
   anillo. Las partículas se dibujan en coordenadas de pantalla (JS
   las calcula con getScreenCTM), así que el canvas en sí no rota ni
   se transforma junto con el anillo. */
#ring-trail-canvas {
    position: absolute;
    top: 0; left: 0;
    width: 100%; height: 100%;
    pointer-events: none;
    z-index: 1;
}

/* "Respiración": pulso de escala muy sutil y constante sobre todo el
   círculo (anillo + tiempo), independiente del progreso de la sesión.
   4s de "inhalación" (0%→50%) + 4s de "exhalación" (50%→100%) = ciclo
   de 8s. Da sensación de vida incluso con el temporizador en pausa. */
@keyframes circle-breathe {
    0%, 100% { transform: scale(1); }
    50% { transform: scale(1.015); }
}
.timer-circle {
    animation: circle-breathe 8s ease-in-out infinite;
}

/* ============================================================
   RESPLANDOR PULSANTE (glow tipo "latido")
   Un drop-shadow que late en intensidad al ritmo del segundo: sube
   de golpe (como la contracción de un pulso cardíaco) y decae más
   lento, en vez de una onda seno simétrica. Se aplica siempre al
   anillo de progreso; el color se toma de --secondary-color salvo
   que .low-time esté activo, donde se vuelve más intenso y rojizo
   (ese caso ya lo cubre ring-pulse más abajo, que se combina). */
@keyframes ring-heartbeat {
    0%   { filter: drop-shadow(0 0 2px var(--secondary-color-glow, var(--secondary-color))); }
    15%  { filter: drop-shadow(0 0 9px var(--secondary-color-glow, var(--secondary-color))); }
    35%  { filter: drop-shadow(0 0 3px var(--secondary-color-glow, var(--secondary-color))); }
    100% { filter: drop-shadow(0 0 2px var(--secondary-color-glow, var(--secondary-color))); }
}
.timer-circle .progress {
    animation: ring-heartbeat 1s ease-out infinite;
}

/* Aviso visual en el anillo durante el último minuto: el trazo pulsa
   con un resplandor suave y más urgente, reemplazando el latido base.
   El color en sí ya no salta acá: migra de forma continua (violeta →
   naranja → alerta) a lo largo de toda la sesión, calculado en JS. */
@keyframes ring-pulse {
    0%   { filter: drop-shadow(0 0 2px rgba(248, 113, 113, 0.4)); }
    15%  { filter: drop-shadow(0 0 14px rgba(248, 113, 113, 0.9)); }
    35%  { filter: drop-shadow(0 0 4px rgba(248, 113, 113, 0.5)); }
    100% { filter: drop-shadow(0 0 2px rgba(248, 113, 113, 0.4)); }
}
.timer-circle.low-time .progress {
    animation: ring-pulse 1s ease-out infinite;
}

/* ============================================================
   ROTACIÓN CONTINUA DEL ANILLO
   Todo el grupo del trazo (track + progress + comet) gira sobre su
   propio eje de forma lenta y perpetua, para que el anillo nunca se
   sienta estático incluso con el temporizador en pausa. La rotación
   es independiente del progreso: no afecta el cálculo de
   stroke-dashoffset porque se aplica al <svg> completo, no al valor
   del progreso en sí.
   ============================================================ */
@keyframes ring-spin {
    from { transform: rotate(0deg); }
    to   { transform: rotate(360deg); }
}
#ring-spin-group {
    transform-box: fill-box;
    transform-origin: center;
    animation: ring-spin 90s linear infinite;
}

/* "Trazo viajero" (efecto cometa): un segmento corto y brillante que
   orbita el anillo en loop constante, encima del progreso, dando
   sensación de movimiento incluso cuando el temporizador está en
   pausa. stroke-dasharray = "arco corto, resto del círculo" para que
   solo se vea un pequeño destello viajando; el drop-shadow simula la
   estela del cometa. Su rotación se suma a la del <svg> padre, así
   que la velocidad relativa real es la resta de ambas duraciones. */
.timer-circle .comet {
    stroke: #ffffff;
    stroke-width: 4;
    stroke-linecap: round;
    stroke-dasharray: 16 675.15;
    opacity: 0.85;
    filter: drop-shadow(0 0 6px rgba(255, 255, 255, 0.85)) drop-shadow(0 0 10px var(--secondary-color));
    transform-box: fill-box;
    transform-origin: center;
    animation: comet-orbit 3.2s linear infinite;
    pointer-events: none;
}
@keyframes comet-orbit {
    to { transform: rotate(360deg); }
}

@media (prefers-reduced-motion: reduce) {
    .timer-circle { animation: none; }
    #ring-spin-group { animation: none; }
    .timer-circle .comet { animation: none; opacity: 0; }
    .timer-circle .progress { animation: none; }
    .timer-circle.low-time .progress { animation: none; }
    .timer-circle .progress.ring-draw-in { animation: none; }
}

.time-buttons {
    position: relative;
    display: inline-flex;
    flex-wrap: wrap;
    justify-content: center;
}
.time-buttons button {
    position: relative;
    z-index: 1;
    background: transparent; border: 1px solid var(--text-color-light);
    color: var(--text-color-light); padding: 10px 20px; margin: 5px;
    border-radius: 50px; cursor: pointer; font-family: 'Poppins', sans-serif;
    font-weight: 600; transition: color 0.3s ease, border-color 0.3s ease;
}
.time-buttons button:hover { border-color: var(--text-color-light); background: rgba(255, 255, 255, 0.08); }
.time-buttons button.active { color: var(--text-color-dark); background: transparent; }

/* "Pill" de fondo que se desliza hacia el botón de tiempo activo, en
   vez de que el color cambie de golpe. Se posiciona con JS (top/left/
   width/height calculados a partir del botón .active vía offsetLeft
   etc., así funciona igual si los botones quedan en una o dos líneas
   en pantallas chicas) y la transición la hace el propio CSS. */
.time-buttons-pill {
    position: absolute;
    top: 0; left: 0;
    height: 40px; width: 0;
    background: var(--text-color-light);
    border-radius: 50px;
    z-index: 0;
    pointer-events: none;
    opacity: 0;
    transition: transform 0.4s cubic-bezier(0.34, 1.56, 0.64, 1),
                width 0.4s cubic-bezier(0.34, 1.56, 0.64, 1),
                opacity 0.25s ease;
}
.time-buttons-pill.visible { opacity: 1; }
.time-buttons-pill.no-transition { transition: none; }

/* Duración personalizada */
.custom-duration-row {
    display: flex; justify-content: center; align-items: center;
    gap: 8px; margin: 4px 0 16px;
}
.custom-duration-row input {
    width: 160px; text-align: center;
    background: transparent; border: 1px solid var(--text-color-light);
    border-radius: 50px; padding: 9px 14px; color: var(--text-color-light);
    font-family: 'Poppins', sans-serif; font-size: 0.85rem; font-weight: 600;
    outline: none; transition: all 0.3s ease; -moz-appearance: textfield;
}
.custom-duration-row input::-webkit-outer-spin-button,
.custom-duration-row input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.custom-duration-row input::placeholder { color: rgba(226, 232, 240, 0.55); font-weight: 400; }
.custom-duration-row input:focus { border-color: var(--secondary-color); }
.custom-duration-row input.active {
    background: var(--text-color-light); color: var(--text-color-dark); border-color: var(--secondary-color);
}
.custom-duration-row input.active::placeholder { color: var(--text-color-dark); }
.custom-duration-row button {
    background: transparent; border: 1px solid var(--text-color-light);
    color: var(--text-color-light); padding: 10px 20px; border-radius: 50px;
    cursor: pointer; font-family: 'Poppins', sans-serif; font-weight: 600;
    font-size: 0.85rem; transition: all 0.3s ease;
}
.custom-duration-row button:hover { background: var(--text-color-light); color: var(--text-color-dark); }

/* Puntos de sesión (ciclo de 4 pomodoros) */
.session-dots { display: flex; justify-content: center; gap: 10px; margin: 6px 0 20px; }
.session-dots .dot {
    width: 10px; height: 10px; border-radius: 50%;
    background: rgba(255, 255, 255, 0.25);
    transition: background 0.3s;
}
/* Al completarse un Pomodoro, el punto no solo cambia de color: "salta"
   con un pequeño rebote elástico (overshoot en las keyframes + cubic-bezier
   con "back") para que cada punto lleno se sienta como un logro, no como
   un simple cambio de estado. El valor final coincide con el scale(1.2)
   de reposo, así que al terminar la animación el punto queda igual que antes. */
.session-dots .dot.filled {
    background: var(--secondary-color);
    transform: scale(1.2);
    animation: dot-pop 0.45s cubic-bezier(0.34, 1.56, 0.64, 1);
}
@keyframes dot-pop {
    0% { transform: scale(0.7); }
    55% { transform: scale(1.4); }
    100% { transform: scale(1.2); }
}

/* Confetti discreto al completar el ciclo de 4 pomodoros: unas pocas
   partículas chiquitas que salen del centro de los puntos de sesión y
   se desvanecen. Colores tomados de la paleta de la app (nada de arcoíris)
   para que se sienta festivo pero sobrio. Cada pieza recibe su propio
   --dx/--dy/--rot vía JS (ver triggerCycleConfetti en java.js) para que
   la trayectoria varíe un poco entre partículas. */
.session-dots { position: relative; }
.confetti-piece {
    position: absolute;
    top: 50%;
    left: 50%;
    width: 5px;
    height: 5px;
    border-radius: 1px;
    pointer-events: none;
    opacity: 0;
    animation: confetti-fly 0.9s ease-out forwards;
}
@keyframes confetti-fly {
    0% {
        transform: translate(-50%, -50%) translate(0, 0) rotate(0deg) scale(1);
        opacity: 1;
    }
    100% {
        transform: translate(-50%, -50%) translate(var(--dx), var(--dy)) rotate(var(--rot)) scale(0.4);
        opacity: 0;
    }
}

/* Estadísticas: indicador compacto bajo los puntos de sesión */
.focus-stats-inline {
    text-align: center; font-size: 0.78rem; font-weight: 300;
    color: var(--text-color-light); opacity: 0.8; margin: 0 0 14px;
}
.focus-stats-inline strong { font-weight: 600; color: var(--secondary-color); }
.focus-stats-inline .stats-divider { margin: 0 6px; opacity: 0.5; }

/* Estadísticas: fila en el panel de ajustes */
.stats-row {
    display: flex; justify-content: space-between; align-items: center;
    margin-bottom: 10px; font-size: 0.85rem; text-align: left;
}
.stats-row strong { color: var(--secondary-color); font-weight: 600; }

.player-controls {
    display: flex; justify-content: center; align-items: center;
    gap: 20px; margin-top: 10px;
    min-height: 80px;
}
.player-controls button {
    background: rgba(255, 255, 255, 0.1);
    border: 2px solid var(--primary-color);
    cursor: pointer;
    border-radius: 50%;
    transition: all 0.3s ease;
}
.player-controls button:hover {
    background: rgba(255, 255, 255, 0.2);
    transform: scale(1.05);
}
/* Feedback táctil: al presionar, el botón se "hunde" levemente.
   Va después de :hover para ganarle en cascada cuando se presiona
   con el cursor encima, y con una transición más corta para que
   el hundimiento se sienta inmediato al toque/clic. */
.player-controls button:active {
    transform: scale(0.95);
    transition: transform 0.1s ease;
}
.player-controls button svg { fill: var(--text-color-light); }

#start-timer-btn { width: 80px; height: 80px; position: relative; }
#start-timer-btn svg { width: 40px; height: 40px; }

/* Pulso de anillo que invita al clic: se expande hacia afuera y se
   desvanece, en loop. Al arrancar el timer el propio botón pasa a
   `.hidden` (ver updateTimerControls en java.js), así que el pulso
   desaparece junto con él sin necesidad de lógica extra. */
#start-timer-btn::after {
    content: '';
    position: absolute;
    inset: 0;
    border-radius: 50%;
    border: 2px solid var(--primary-color);
    pointer-events: none;
    animation: start-btn-ripple 2.2s ease-out infinite;
}
@keyframes start-btn-ripple {
    0% { transform: scale(1); opacity: 0.65; }
    100% { transform: scale(1.55); opacity: 0; }
}

#pause-timer-btn, #reset-timer-btn { width: 60px; height: 60px; }
#pause-timer-btn svg, #reset-timer-btn svg { width: 30px; height: 30px; }

.music-controls {
    display: flex; align-items: center; justify-content: center; gap: 15px; margin-top: 20px;
}
.music-controls button { background: none; border: none; cursor: pointer; width: 24px; height: 24px; }
.music-controls button svg { fill: var(--text-color-light); transition: fill 0.3s; }
.music-controls button:hover svg { fill: var(--primary-color); }

/* Morph play↔pause: ambos íconos quedan superpuestos en el mismo lugar
   y se cruzan con fade + escala en vez del salto seco de mostrar/ocultar.
   Se usa la clase .icon-hidden (no .hidden, que es display:none !important
   y no se puede animar) para controlar cuál está visible. */
#music-play-pause-btn { position: relative; }
#music-play-pause-btn svg {
    position: absolute;
    top: 0;
    left: 0;
    transition: opacity 0.25s ease, transform 0.25s ease, fill 0.3s;
    opacity: 1;
    transform: scale(1) rotate(0deg);
}
#music-play-pause-btn svg.icon-hidden {
    opacity: 0;
    transform: scale(0.4) rotate(-40deg);
    pointer-events: none;
}
#volume-slider {
    -webkit-appearance: none; appearance: none; width: 120px; height: 5px;
    background: rgba(255, 255, 255, 0.3); border-radius: 5px; cursor: pointer;
}
#volume-slider::-webkit-slider-thumb {
    -webkit-appearance: none; appearance: none; width: 18px; height: 18px;
    background: var(--primary-color); border-radius: 50%; cursor: pointer;
}

#settings-button {
    position: fixed; top: 20px; right: 20px; background: none; border: none;
    cursor: pointer; z-index: 1001; width: 40px; height: 40px;
}
#settings-button svg { fill: var(--text-color-light); transition: transform 0.5s ease; }
#settings-button:hover svg { transform: rotate(90deg); }

#settings-panel {
    position: fixed; top: 0; right: 0; width: 300px; height: 100%;
    background: var(--bg-glass-light); backdrop-filter: blur(20px);
    border-left: 1px solid var(--border-color); padding: 80px 20px 20px 20px;
    z-index: 1000; overflow-y: auto;
    /* Cerrado: fuera de pantalla (translateX en vez del viejo "right"
       animado, para que corra en el compositor y no dispare layout en
       cada frame — importante acá porque el panel ya tiene backdrop-filter,
       que de por sí es costoso) y sin opacidad. visibility se suma para
       que el contenido deje de ser tabbable/enfocable mientras está
       cerrado, algo que el "right: -350px" original no garantizaba. */
    transform: translateX(105%);
    opacity: 0;
    visibility: hidden;
    /* El desliz usa el mismo cubic-bezier "back" que .dot.filled
       (dot-pop) para el leve rebote/overshoot; la opacidad va con una
       curva simple para no competir visualmente con ese rebote.
       visibility cambia recién cuando termina la transición de salida
       (delay = duración del transform), así el panel se puede seguir
       viendo/enfocando mientras se desliza afuera; al abrir, en cambio,
       se vuelve visible al instante (delay 0). */
    transition: transform 0.5s cubic-bezier(0.34, 1.56, 0.64, 1),
                opacity 0.35s ease,
                visibility 0s linear 0.5s;
}
#settings-panel.open {
    transform: translateX(0);
    opacity: 1;
    visibility: visible;
    transition: transform 0.5s cubic-bezier(0.34, 1.56, 0.64, 1),
                opacity 0.35s ease,
                visibility 0s linear 0s;
}
/* prefers-reduced-motion ya deja transition-duration en ~0 vía la regla
   global de abajo, pero el transition-delay de visibility no queda
   cubierto por esa regla (no es "duration"), así que se anula acá aparte
   para que el panel no quede tabbable de más tras cerrarse. */
@media (prefers-reduced-motion: reduce) {
    #settings-panel { transition-delay: 0s !important; }
}
#settings-panel h3 {
    margin-bottom: 15px; font-weight: 600; border-bottom: 1px solid var(--border-color);
    padding-bottom: 10px; text-align: left;
}
.settings-section { margin-bottom: 30px; opacity: 0; transform: translateY(10px); }

/* Stagger: cada .settings-section entra con un pequeño delay incremental
   respecto a la anterior (mismo espíritu que el desfasaje de las
   confetti-piece en triggerCycleConfetti, ahí vía JS con delay random;
   acá es fijo porque las secciones son siempre las mismas 6, así que
   alcanza con nth-of-type en CSS puro). Solo se dispara con .open: al
   cerrar, las secciones vuelven de una a su estado inicial (opacity 0),
   pero eso queda tapado por el fade general del panel, que ya se está
   yendo al mismo tiempo. */
#settings-panel.open .settings-section {
    animation: settings-section-in 0.4s ease-out forwards;
}
#settings-panel.open .settings-section:nth-of-type(1) { animation-delay: 0.10s; }
#settings-panel.open .settings-section:nth-of-type(2) { animation-delay: 0.16s; }
#settings-panel.open .settings-section:nth-of-type(3) { animation-delay: 0.22s; }
#settings-panel.open .settings-section:nth-of-type(4) { animation-delay: 0.28s; }
#settings-panel.open .settings-section:nth-of-type(5) { animation-delay: 0.34s; }
#settings-panel.open .settings-section:nth-of-type(6) { animation-delay: 0.40s; }
@keyframes settings-section-in {
    0% { opacity: 0; transform: translateY(10px); }
    100% { opacity: 1; transform: translateY(0); }
}

.choice-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 10px; }
.choice-grid button {
    background: rgba(255, 255, 255, 0.1); border: 1px solid transparent;
    color: var(--text-color-light); padding: 10px; border-radius: 10px;
    cursor: pointer; transition: all 0.3s ease; font-family: 'Poppins', sans-serif;
    font-size: 0.85rem;
}
.choice-grid button.active { border-color: var(--secondary-color); background: var(--secondary-color); }

.toggle-row {
    display: flex; justify-content: space-between; align-items: center;
    margin-bottom: 15px; font-size: 0.85rem; text-align: left; gap: 10px;
}
.switch { position: relative; width: 44px; height: 24px; flex-shrink: 0; }
.switch input { opacity: 0; width: 0; height: 0; }
.slider-toggle {
    position: absolute; inset: 0; cursor: pointer;
    background: rgba(255, 255, 255, 0.2); border-radius: 24px;
    transition: background-color 0.3s ease;
}
/* El thumb se desliza con el mismo cubic-bezier "back" que .dot.filled
   (dot-pop) y el panel de ajustes, para un leve rebote/overshoot en vez
   de un deslizamiento plano. La pista (arriba) sigue con ease simple:
   un rebote en background-color se ve raro, así que solo el movimiento
   del thumb tiene el "salto". */
.slider-toggle:before {
    content: ''; position: absolute; height: 18px; width: 18px; left: 3px; bottom: 3px;
    background: white; border-radius: 50%;
    transition: transform 0.35s cubic-bezier(0.34, 1.56, 0.64, 1);
}
.switch input:checked + .slider-toggle { background: var(--secondary-color); }
.switch input:checked + .slider-toggle:before { transform: translateX(20px); }

.reset-btn {
    background: rgba(255, 255, 255, 0.1); border: 1px solid var(--border-color);
    color: var(--text-color-light); padding: 8px 14px; border-radius: 8px;
    cursor: pointer; font-family: 'Poppins', sans-serif; font-size: 0.85rem;
    transition: background 0.3s, transform 0.15s ease; width: 100%;
}
.reset-btn:hover { background: rgba(255, 255, 255, 0.2); }
.reset-btn:active { transform: scale(0.96); }

/* Sección de donación (alias / CVU copiables) */
.donate-text {
    font-size: 0.8rem; font-weight: 300; line-height: 1.5;
    color: var(--text-color-light); opacity: 0.85; margin-bottom: 12px; text-align: left;
}
.donate-row {
    display: flex; align-items: center; gap: 8px; margin-bottom: 10px;
}
.donate-label {
    font-size: 0.75rem; opacity: 0.65; flex-shrink: 0; width: 38px; text-align: left;
}
.donate-copy-btn {
    flex: 1; display: flex; justify-content: space-between; align-items: center; gap: 8px;
    background: rgba(255, 255, 255, 0.1); border: 1px solid var(--border-color);
    color: var(--text-color-light); padding: 8px 10px; border-radius: 8px;
    cursor: pointer; font-family: 'Poppins', sans-serif; font-size: 0.76rem;
    text-align: left; overflow: hidden; min-width: 0;
    transition: background 0.25s, border-color 0.25s, transform 0.15s ease;
}
.donate-copy-btn .copy-label {
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.donate-copy-btn:hover { background: rgba(255, 255, 255, 0.18); border-color: var(--secondary-color); }
.donate-copy-btn:active { transform: scale(0.96); }
.donate-copy-btn.copied { background: rgba(167, 139, 250, 0.28); border-color: var(--secondary-color); }
.donate-copy-btn .copy-icon { flex-shrink: 0; opacity: 0.7; font-size: 0.9rem; }

body.dark-mode .main-panel { background: var(--bg-glass-dark); }
body.dark-mode #app-overlay { background-color: rgba(0, 0, 0, 0.6); }
body.dark-mode #settings-panel { background: var(--bg-glass-dark); }

.site-footer {
    position: relative; text-align: center; padding: 4px 0 18px;
    font-size: 0.75rem;
}
.site-footer a {
    color: var(--text-color-light); opacity: 0.55; text-decoration: none;
    transition: opacity 0.2s;
}
.site-footer a:hover { opacity: 0.9; text-decoration: underline; }

.hidden { display: none !important; }

.sr-only {
    position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
    overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
}

/* Indicador de foco visible para elementos interactivos personalizados
   (spans/divs con role="button" no siempre reciben un anillo de foco claro) */
.task-text:focus-visible {
    outline: 2px solid var(--secondary-color);
    outline-offset: 2px;
    border-radius: 4px;
}

/* Respeta la preferencia del sistema de reducir movimiento: recorta
   animaciones y transiciones a algo casi instantáneo en toda la app
   (fondo, panel de ajustes, anillo de progreso, botones, etc.) */
@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
        scroll-behavior: auto !important;
    }
}

@media (max-width: 600px) {
    .main-panel { padding: 30px 20px; }
    .main-panel h1 { font-size: 2rem; }
    .timer-circle { width: 200px; height: 200px; }
    #timer-display { font-size: 2.2rem; }
    .custom-duration-row input { width: 130px; }
}