// ===== timer-ring.jsx =====
// Timer ring + digits — the visual centerpiece.
// Props:
//   secondsLeft, totalSeconds — for progress
//   state — 'ready' | 'running' | 'paused' | 'finished'
//   ringColor, glowIntensity — from tweaks
//   compact — for thumbnail uses (not used here)

const TimerRing = ({ secondsLeft, totalSeconds, state, ringColor, glowIntensity }) => {
  // SVG ring math
  const size = 1000;            // viewBox units — independent of screen
  const cx = size / 2;
  const cy = size / 2;
  const strokeWidth = 110;
  const r = (size - strokeWidth) / 2 - 8;   // small breathing room
  const circ = 2 * Math.PI * r;

  // Progress: 1.0 at full duration, 0 at zero. Clamp.
  const safeTotal = Math.max(1, totalSeconds);
  const progress = Math.max(0, Math.min(1, secondsLeft / safeTotal));

  // Dash: visible = circ * progress. We rotate -90deg so the start is at the top.
  // To deplete clockwise from the top we keep the visible arc starting at -90 and the gap appears on the trailing side.
  // Implementing as stroke-dasharray: visible, gap.
  const visible = circ * progress;
  const gap = circ - visible;

  // Format MM:SS — return parts so the colon can be repositioned independently.
  const fmtParts = (s) => {
    const total = Math.max(0, Math.ceil(s));
    const m = Math.floor(total / 60);
    const sec = total % 60;
    return {
      m: String(m).padStart(2, '0'),
      sec: String(sec).padStart(2, '0'),
    };
  };

  const isFinished = state === 'finished';
  const isPaused = state === 'paused';
  // Warning state: when 20 seconds or fewer remain, digits switch to red — but
  // only while the timer has actually started (ready state still shows white).
  const isWarning = !isFinished && secondsLeft <= 20 && (state === 'running' || state === 'paused');

  // Glow strength scales with progress so the ring "burns out" as it depletes — matches video.
  const glowStrength = glowIntensity * (0.35 + 0.65 * progress);
  const ringOpacity = isFinished ? 1 : 1;

  // The trailing (depleted) track stays visible as a dim brick-red ring, like the video.
  const trackColor = mixWithBlack(ringColor, 0.78);

  // While paused: pulse the ring dim/bright via opacity animation.
  const pausedAnim = isPaused ? { animation: 'pulseDim 1.6s ease-in-out infinite' } : {};

  // Digit color
  const digitColor = (isFinished || isWarning) ? ringColor : '#ffffff';
  const digitGlow = (isFinished || isWarning)
    ? `drop-shadow(0 0 30px ${withAlpha(ringColor, 0.7)}) drop-shadow(0 0 80px ${withAlpha(ringColor, 0.5)})`
    : 'none';
  const digitAnim = isFinished
    ? { animation: 'finishedGlow 1.8s ease-in-out infinite' }
    : {};

  return (
    <div style={{
      position: 'relative',
      width: 'min(78vmin, 900px)',
      height: 'min(78vmin, 900px)',
      display: 'flex',
      alignItems: 'center',
      justifyContent: 'center',
      ...(state === 'running' ? { animation: 'softPulse 4s ease-in-out infinite' } : {})
    }}>
      {/* Outer ambient halo — large soft red wash */}
      <div style={{
        position: 'absolute',
        inset: '-25%',
        background: `radial-gradient(circle, ${withAlpha(ringColor, 0.35 * glowStrength)} 0%, ${withAlpha(ringColor, 0.18 * glowStrength)} 25%, transparent 55%)`,
        filter: 'blur(20px)',
        pointerEvents: 'none',
        transition: 'opacity 400ms ease',
        opacity: isFinished ? 0.15 : 1,
      }} />

      {/* SVG ring */}
      <svg
        viewBox={`0 0 ${size} ${size}`}
        style={{
          position: 'relative',
          width: '100%',
          height: '100%',
          overflow: 'visible',
          ...pausedAnim,
        }}
      >
        <defs>
          <filter id="ringGlow" x="-50%" y="-50%" width="200%" height="200%">
            <feGaussianBlur stdDeviation={28 * glowStrength} result="blur1" />
            <feMerge>
              <feMergeNode in="blur1" />
              <feMergeNode in="SourceGraphic" />
            </feMerge>
          </filter>
          <radialGradient id="innerWell" cx="50%" cy="50%" r="50%">
            <stop offset="0%" stopColor="#000" stopOpacity="1" />
            <stop offset="70%" stopColor="#000" stopOpacity="1" />
            <stop offset="100%" stopColor={withAlpha(ringColor, 0.35 * glowStrength)} stopOpacity={isFinished ? 0 : 1} />
          </radialGradient>
        </defs>

        {/* Inner shadow well — subtle red bloom inside the donut */}
        <circle cx={cx} cy={cy} r={r - strokeWidth / 2 - 4} fill="url(#innerWell)" />

        {/* Depleted track (always visible) */}
        <circle
          cx={cx}
          cy={cy}
          r={r}
          fill="none"
          stroke={trackColor}
          strokeWidth={strokeWidth}
          opacity={isFinished ? 0.55 : 0.42}
        />

        {/* Active arc — depletes clockwise from top */}
        {!isFinished && (
          <circle
            cx={cx}
            cy={cy}
            r={r}
            fill="none"
            stroke={ringColor}
            strokeWidth={strokeWidth}
            strokeDasharray={`${visible} ${gap}`}
            strokeDashoffset={0}
            strokeLinecap="butt"
            transform={`rotate(-90 ${cx} ${cy})`}
            filter="url(#ringGlow)"
            style={{
              transition: state === 'ready' ? 'stroke-dasharray 300ms ease' : 'none',
              opacity: ringOpacity,
            }}
          />
        )}
      </svg>

      {/* Digits */}
      {(() => {
        const { m, sec } = fmtParts(secondsLeft);
        return (
          <div style={{
            position: 'absolute',
            top: '50%',
            left: '50%',
            transform: 'translate(-50%, -50%)',
            fontFamily: 'Nunito, sans-serif',
            fontWeight: 900,
            fontSize: 'clamp(72px, 18vmin, 220px)',
            letterSpacing: '-0.02em',
            color: digitColor,
            filter: digitGlow,
            textShadow: isFinished ? 'none' : '0 4px 24px rgba(0,0,0,0.5)',
            display: 'flex',
            alignItems: 'center',
            ...digitAnim,
          }}>
            <span>{m}</span>
            <div style={{
              display: 'flex',
              flexDirection: 'column',
              alignItems: 'center',
              gap: '0.3em',
              margin: '0 0.12em',
            }}>
              <div style={{ width: '0.13em', height: '0.13em', borderRadius: '50%', background: 'currentColor' }} />
              <div style={{ width: '0.13em', height: '0.13em', borderRadius: '50%', background: 'currentColor' }} />
            </div>
            <span>{sec}</span>
          </div>
        );
      })()}
    </div>
  );
};

// Mix hex color with black. amount=1 returns black, 0 returns color.
function mixWithBlack(hex, amount) {
  const { r, g, b } = parseHex(hex);
  const nr = Math.round(r * (1 - amount));
  const ng = Math.round(g * (1 - amount));
  const nb = Math.round(b * (1 - amount));
  return `rgb(${nr}, ${ng}, ${nb})`;
}

function withAlpha(hex, a) {
  const { r, g, b } = parseHex(hex);
  return `rgba(${r}, ${g}, ${b}, ${a})`;
}

function parseHex(hex) {
  let h = hex.replace('#', '');
  if (h.length === 3) h = h.split('').map(c => c + c).join('');
  return {
    r: parseInt(h.slice(0, 2), 16),
    g: parseInt(h.slice(2, 4), 16),
    b: parseInt(h.slice(4, 6), 16),
  };
}

window.TimerRing = TimerRing;
window.timerRingUtils = { mixWithBlack, withAlpha, parseHex };


// ===== home-screen.jsx =====
// Home screen — set the timer duration before starting.
// Visual DNA: black, big rounded white numerals, red glowing accents that echo the ring.

const { useState, useRef, useEffect } = React;
const { withAlpha: ha } = window.timerRingUtils;

const HomeScreen = ({ initialMinutes, initialSeconds, ringColor, glowIntensity, onStart }) => {
  const [minutes, setMinutes] = useState(initialMinutes);
  const [seconds, setSeconds] = useState(initialSeconds);
  const [editing, setEditing] = useState(null); // 'min' | 'sec' | null
  const [editBuf, setEditBuf] = useState('');

  const minRef = useRef(null);
  const secRef = useRef(null);

  // Sync external changes to defaults (from tweaks panel)
  useEffect(() => { setMinutes(initialMinutes); }, [initialMinutes]);
  useEffect(() => { setSeconds(initialSeconds); }, [initialSeconds]);

  const total = minutes * 60 + seconds;
  const canStart = total > 0;

  const clampMin = (v) => Math.max(0, Math.min(59, v));
  const clampSec = (v) => Math.max(0, Math.min(59, v));

  const beginEdit = (which) => {
    setEditing(which);
    setEditBuf('');
    setTimeout(() => {
      const el = which === 'min' ? minRef.current : secRef.current;
      el && el.focus();
    }, 10);
  };

  const commitEdit = () => {
    if (editBuf !== '') {
      const n = parseInt(editBuf, 10);
      if (!Number.isNaN(n)) {
        if (editing === 'min') setMinutes(clampMin(n));
        else if (editing === 'sec') setSeconds(clampSec(n));
      }
    }
    setEditing(null);
    setEditBuf('');
  };

  const onKeyDown = (e) => {
    if (e.key === 'Enter') { e.preventDefault(); commitEdit(); }
    else if (e.key === 'Escape') { e.preventDefault(); setEditing(null); setEditBuf(''); }
  };

  const adjust = (which, delta) => {
    if (which === 'min') setMinutes((m) => clampMin(m + delta));
    else setSeconds((s) => {
      const ns = s + delta;
      if (ns < 0) {
        if (minutes > 0) { setMinutes((m) => clampMin(m - 1)); return 59; }
        return 0;
      }
      if (ns > 59) {
        setMinutes((m) => clampMin(m + 1));
        return 0;
      }
      return ns;
    });
  };

  const presets = [1, 5, 10, 15, 25, 45];

  // Keyboard shortcut: Enter / Space to start
  useEffect(() => {
    const handler = (e) => {
      if (editing) return;
      if (e.key === 'Enter' || e.key === ' ') {
        e.preventDefault();
        if (canStart) onStart(total);
      }
    };
    window.addEventListener('keydown', handler);
    return () => window.removeEventListener('keydown', handler);
  }, [editing, canStart, total, onStart]);

  const pad = (n) => String(n).padStart(2, '0');

  const digitStyle = (active) => ({
    fontFamily: 'Nunito, sans-serif',
    fontWeight: 900,
    fontSize: 'clamp(80px, 22vmin, 280px)',
    letterSpacing: '-0.03em',
    lineHeight: 0.9,
    color: '#fff',
    cursor: 'pointer',
    padding: '0 0.06em',
    borderRadius: '24px',
    transition: 'all 200ms ease',
    background: active ? ha(ringColor, 0.12) : 'transparent',
    outline: active ? `2px solid ${ha(ringColor, 0.6)}` : '2px solid transparent',
    textShadow: active ? `0 0 32px ${ha(ringColor, 0.7)}` : '0 4px 24px rgba(0,0,0,0.5)',
  });

  const arrowBtn = {
    width: 56,
    height: 36,
    border: 'none',
    borderRadius: 10,
    background: 'rgba(255,255,255,0.06)',
    color: 'rgba(255,255,255,0.5)',
    fontFamily: 'Nunito, sans-serif',
    fontSize: 20,
    fontWeight: 800,
    cursor: 'pointer',
    transition: 'all 150ms ease',
  };

  const PairColumn = ({ value, which, label }) => {
    const isEditing = editing === which;
    const refEl = which === 'min' ? minRef : secRef;
    return (
      <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 14 }}>
        {/* Invisible spacer matches the label height below so the digit ends up at the true vertical center of this column. */}
        <div aria-hidden="true" style={{
          fontFamily: 'Nunito, sans-serif',
          fontSize: 13,
          fontWeight: 700,
          letterSpacing: '0.22em',
          marginBottom: 4,
          visibility: 'hidden',
        }}>MIN</div>
        <button
          onClick={() => adjust(which, 1)}
          onMouseEnter={(e) => { e.currentTarget.style.background = ha(ringColor, 0.18); e.currentTarget.style.color = '#fff'; }}
          onMouseLeave={(e) => { e.currentTarget.style.background = 'rgba(255,255,255,0.06)'; e.currentTarget.style.color = 'rgba(255,255,255,0.5)'; }}
          style={arrowBtn}
          aria-label={`Increase ${label}`}
        >▲</button>

        <div style={{ position: 'relative' }} onClick={() => beginEdit(which)}>
          {isEditing ? (
            <input
              ref={refEl}
              type="text"
              inputMode="numeric"
              maxLength={2}
              value={editBuf}
              placeholder={pad(value)}
              onChange={(e) => {
                // Cap at 2 digits and clamp to 0..59 immediately while typing.
                const v = e.target.value.replace(/[^0-9]/g, '').slice(0, 2);
                if (v === '') { setEditBuf(''); return; }
                const n = parseInt(v, 10);
                setEditBuf(String(Math.min(59, n)));
              }}
              onBlur={commitEdit}
              onKeyDown={onKeyDown}
              style={{
                ...digitStyle(true),
                background: ha(ringColor, 0.12),
                width: '2.2em',
                textAlign: 'center',
                border: 'none',
                outline: `2px solid ${ha(ringColor, 0.8)}`,
                caretColor: ringColor,
              }}
            />
          ) : (
            <div style={digitStyle(false)}>{pad(value)}</div>
          )}
        </div>

        <button
          onClick={() => adjust(which, -1)}
          onMouseEnter={(e) => { e.currentTarget.style.background = ha(ringColor, 0.18); e.currentTarget.style.color = '#fff'; }}
          onMouseLeave={(e) => { e.currentTarget.style.background = 'rgba(255,255,255,0.06)'; e.currentTarget.style.color = 'rgba(255,255,255,0.5)'; }}
          style={arrowBtn}
          aria-label={`Decrease ${label}`}
        >▼</button>

        <div style={{
          fontFamily: 'Nunito, sans-serif',
          fontSize: 13,
          fontWeight: 700,
          letterSpacing: '0.22em',
          color: 'rgba(255,255,255,0.35)',
          marginTop: 4,
        }}>{label}</div>
      </div>
    );
  };

  return (
    <div style={{
      position: 'absolute',
      inset: 0,
      display: 'flex',
      flexDirection: 'column',
      alignItems: 'center',
      justifyContent: 'center',
      gap: '4vmin',
      padding: '4vmin',
    }}>
      {/* Ambient red wash behind everything — keeps the timer's visual DNA */}
      <div style={{
        position: 'absolute',
        inset: 0,
        background: `radial-gradient(ellipse at center, ${ha(ringColor, 0.12 * glowIntensity)} 0%, transparent 60%)`,
        pointerEvents: 'none',
      }} />

      {/* Top label */}
      <div style={{
        position: 'relative',
        fontFamily: 'Nunito, sans-serif',
        fontSize: 14,
        fontWeight: 700,
        letterSpacing: '0.4em',
        color: 'rgba(255,255,255,0.4)',
        textTransform: 'uppercase',
        marginBottom: '2vmin',
      }}>
        Set Duration
      </div>

      {/* Time pickers */}
      <div style={{ position: 'relative', display: 'flex', alignItems: 'center', gap: '2vmin' }}>
        {PairColumn({ value: minutes, which: 'min', label: 'MIN' })}
        <div style={{
          display: 'flex',
          flexDirection: 'column',
          alignItems: 'center',
          gap: '0.3em',
          fontSize: 'clamp(80px, 22vmin, 280px)',
          pointerEvents: 'none',
        }}>
          <div style={{ width: '0.13em', height: '0.13em', borderRadius: '50%', background: '#fff' }} />
          <div style={{ width: '0.13em', height: '0.13em', borderRadius: '50%', background: '#fff' }} />
        </div>
        {PairColumn({ value: seconds, which: 'sec', label: 'SEC' })}
      </div>

      {/* Presets */}
      <div style={{
        position: 'relative',
        display: 'flex',
        gap: 10,
        marginTop: '2vmin',
        flexWrap: 'wrap',
        justifyContent: 'center',
      }}>
        {presets.map((p) => {
          const active = minutes === p && seconds === 0;
          return (
            <button
              key={p}
              onClick={() => { setMinutes(p); setSeconds(0); }}
              onMouseEnter={(e) => {
                if (!active) {
                  e.currentTarget.style.borderColor = ha(ringColor, 0.5);
                  e.currentTarget.style.color = '#fff';
                }
              }}
              onMouseLeave={(e) => {
                if (!active) {
                  e.currentTarget.style.borderColor = 'rgba(255,255,255,0.12)';
                  e.currentTarget.style.color = 'rgba(255,255,255,0.55)';
                }
              }}
              style={{
                fontFamily: 'Nunito, sans-serif',
                fontWeight: 800,
                fontSize: 15,
                letterSpacing: '0.05em',
                padding: '10px 18px',
                borderRadius: 999,
                background: active ? ha(ringColor, 0.18) : 'transparent',
                color: active ? '#fff' : 'rgba(255,255,255,0.55)',
                border: `1.5px solid ${active ? ha(ringColor, 0.8) : 'rgba(255,255,255,0.12)'}`,
                cursor: 'pointer',
                transition: 'all 150ms ease',
                boxShadow: active ? `0 0 24px ${ha(ringColor, 0.4)}` : 'none',
              }}
            >
              {p} min
            </button>
          );
        })}
      </div>

      {/* Start button — glowing red ring */}
      <button
        onClick={() => canStart && onStart(total)}
        disabled={!canStart}
        onMouseEnter={(e) => {
          if (canStart) {
            e.currentTarget.style.transform = 'scale(1.04)';
            e.currentTarget.style.boxShadow = `0 0 60px ${ha(ringColor, 0.9)}, inset 0 0 30px ${ha(ringColor, 0.3)}`;
          }
        }}
        onMouseLeave={(e) => {
          e.currentTarget.style.transform = 'scale(1)';
          e.currentTarget.style.boxShadow = `0 0 40px ${ha(ringColor, 0.6)}, inset 0 0 20px ${ha(ringColor, 0.15)}`;
        }}
        style={{
          position: 'relative',
          marginTop: '3vmin',
          fontFamily: 'Nunito, sans-serif',
          fontWeight: 900,
          fontSize: 22,
          letterSpacing: '0.3em',
          color: '#fff',
          padding: '20px 64px',
          borderRadius: 999,
          background: 'transparent',
          border: `3px solid ${ringColor}`,
          cursor: canStart ? 'pointer' : 'not-allowed',
          opacity: canStart ? 1 : 0.35,
          transition: 'all 200ms ease',
          boxShadow: `0 0 40px ${ha(ringColor, 0.6 * glowIntensity)}, inset 0 0 20px ${ha(ringColor, 0.15)}`,
          textShadow: `0 0 12px ${ha(ringColor, 0.8)}`,
        }}
      >
        START
      </button>

      {/* Hint */}
      <div style={{
        position: 'relative',
        fontFamily: 'Nunito, sans-serif',
        fontSize: 13,
        fontWeight: 600,
        letterSpacing: '0.18em',
        color: 'rgba(255,255,255,0.3)',
        textTransform: 'uppercase',
        marginTop: '1vmin',
      }}>
        Press <span style={{ color: 'rgba(255,255,255,0.55)' }}>Enter</span> to start
      </div>
    </div>
  );
};

window.HomeScreen = HomeScreen;


// ===== app.jsx =====
// Main app — state machine, click handling, tick loop, tweaks panel.

const { useCallback } = React;

const {
  TweaksPanel,
  useTweaks,
  TweakSection,
  TweakSlider,
  TweakToggle,
  TweakColor,
  TweakNumber,
  TweakButton,
} = window;

const App = () => {
  const [t, setTweak] = useTweaks(window.TWEAKS_DEFAULTS);

  // State machine: 'home' | 'ready' | 'running' | 'paused' | 'finished'
  const [phase, setPhase] = useState('home');
  const [totalSeconds, setTotalSeconds] = useState(t.defaultMinutes * 60 + t.defaultSeconds);
  // We track remaining as a float (milliseconds-precision) for smooth ring animation,
  // but display the ceiling so 03:00 stays until 02:59 boundary — matches video.
  const [remainingMs, setRemainingMs] = useState((t.defaultMinutes * 60 + t.defaultSeconds) * 1000);

  // Tick loop
  const rafRef = useRef(null);
  const lastTickRef = useRef(null);

  useEffect(() => {
    if (phase !== 'running') {
      lastTickRef.current = null;
      if (rafRef.current) cancelAnimationFrame(rafRef.current);
      return;
    }
    const loop = (now) => {
      if (lastTickRef.current == null) lastTickRef.current = now;
      const dt = now - lastTickRef.current;
      lastTickRef.current = now;
      setRemainingMs((prev) => {
        const next = prev - dt;
        if (next <= 0) {
          // Move to finished — handled in effect below
          return 0;
        }
        return next;
      });
      rafRef.current = requestAnimationFrame(loop);
    };
    rafRef.current = requestAnimationFrame(loop);
    return () => {
      if (rafRef.current) cancelAnimationFrame(rafRef.current);
    };
  }, [phase]);

  // Watch for completion
  useEffect(() => {
    if (phase === 'running' && remainingMs <= 0) {
      setPhase('finished');
    }
  }, [phase, remainingMs]);

  // ----- Click handling: single vs double -----
  const clickTimerRef = useRef(null);
  const clickCountRef = useRef(0);
  const DOUBLE_CLICK_MS = 260;

  const handleSingle = useCallback(() => {
    if (phase === 'ready')   setPhase('running');
    else if (phase === 'running') setPhase('paused');
    else if (phase === 'paused')  setPhase('running');
    // finished: ignore single clicks (freezes at 0 forever)
  }, [phase]);

  const handleDouble = useCallback(() => {
    // Exit to home from any non-home state
    if (phase !== 'home') {
      setPhase('home');
    }
  }, [phase]);

  const onScreenClick = useCallback((e) => {
    // Ignore clicks on tweak panel etc — only react to clicks on the timer surface
    if (e.target.closest('[data-no-timer-click]')) return;
    if (phase === 'home') return;

    clickCountRef.current += 1;
    if (clickCountRef.current === 1) {
      clickTimerRef.current = setTimeout(() => {
        if (clickCountRef.current === 1) handleSingle();
        clickCountRef.current = 0;
      }, DOUBLE_CLICK_MS);
    } else if (clickCountRef.current === 2) {
      clearTimeout(clickTimerRef.current);
      clickCountRef.current = 0;
      handleDouble();
    }
  }, [phase, handleSingle, handleDouble]);

  // Keyboard for accessibility / power users
  useEffect(() => {
    if (phase === 'home') return;
    const onKey = (e) => {
      if (e.target.tagName === 'INPUT' || e.target.tagName === 'TEXTAREA') return;
      if (e.key === 'Escape') { e.preventDefault(); setPhase('home'); }
      else if (e.key === ' ' || e.key === 'Enter') {
        e.preventDefault();
        if (phase === 'ready')   setPhase('running');
        else if (phase === 'running') setPhase('paused');
        else if (phase === 'paused')  setPhase('running');
      }
    };
    window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
  }, [phase]);

  // Start from home — set total & ready state
  const handleStart = (secs) => {
    setTotalSeconds(secs);
    setRemainingMs(secs * 1000);
    setPhase('ready');
  };

  // -----------------

  // Show subtle state hints (matches the video aesthetic — minimal)
  const stateHint = (() => {
    if (!t.showHints || phase === 'home') return null;
    if (phase === 'ready')    return 'Click anywhere to start';
    if (phase === 'paused')   return 'Paused — click to resume';
    if (phase === 'finished') return 'Double-click to exit';
    return null; // running: no hint
  })();

  const secondsLeft = remainingMs / 1000;

  return (
    <div
      onClick={onScreenClick}
      style={{
        position: 'absolute',
        inset: 0,
        cursor: phase === 'home' ? 'default' : 'pointer',
      }}
    >
      {phase === 'home' ? (
        <HomeScreen
          initialMinutes={t.defaultMinutes}
          initialSeconds={t.defaultSeconds}
          ringColor={t.ringColor}
          glowIntensity={t.glowIntensity}
          onStart={handleStart}
        />
      ) : (
        <div style={{
          position: 'absolute',
          inset: 0,
          display: 'flex',
          alignItems: 'center',
          justifyContent: 'center',
        }}>
          <TimerRing
            secondsLeft={secondsLeft}
            totalSeconds={totalSeconds}
            state={phase}
            ringColor={t.ringColor}
            glowIntensity={t.glowIntensity}
          />
        </div>
      )}

      {/* State hint overlay */}
      {stateHint && (
        <div style={{
          position: 'absolute',
          bottom: '6vh',
          left: 0,
          right: 0,
          textAlign: 'center',
          fontFamily: 'Nunito, sans-serif',
          fontSize: 13,
          fontWeight: 700,
          letterSpacing: '0.32em',
          textTransform: 'uppercase',
          color: 'rgba(255,255,255,0.5)',
          animation: 'hintFade 2.4s ease-in-out infinite',
          pointerEvents: 'none',
        }}>
          {stateHint}
        </div>
      )}

      {/* Tweaks panel */}
      <div data-no-timer-click>
        <TweaksPanel>
          <TweakSection label="Appearance" />
            <TweakColor
              label="Ring color"
              value={t.ringColor}
              onChange={(v) => setTweak('ringColor', v)}
              options={['#FF2A2A', '#FF7A00', '#FFCC00', '#22D672', '#27B7FF', '#B66CFF']}
            />
            <TweakSlider
              label="Glow intensity"
              value={t.glowIntensity}
              onChange={(v) => setTweak('glowIntensity', v)}
              min={0}
              max={2}
              step={0.05}
            />

          <TweakSection label="Defaults" />
            <TweakNumber
              label="Default minutes"
              value={t.defaultMinutes}
              onChange={(v) => setTweak('defaultMinutes', Math.max(0, Math.min(59, v)))}
              min={0}
              max={59}
            />
            <TweakNumber
              label="Default seconds"
              value={t.defaultSeconds}
              onChange={(v) => setTweak('defaultSeconds', Math.max(0, Math.min(59, v)))}
              min={0}
              max={59}
            />

          <TweakSection label="Behavior" />
            <TweakToggle
              label="Show on-screen hints"
              value={t.showHints}
              onChange={(v) => setTweak('showHints', v)}
            />

          <TweakSection label="Controls" />
            <div style={{ fontSize: 12, lineHeight: 1.6, color: 'rgba(255,255,255,0.6)' }}>
              <div><b style={{color:'#fff'}}>Click</b> — pause / resume</div>
              <div><b style={{color:'#fff'}}>Double-click</b> — exit to home</div>
              <div><b style={{color:'#fff'}}>Space / Enter</b> — pause / resume</div>
              <div><b style={{color:'#fff'}}>Esc</b> — exit to home</div>
            </div>
        </TweaksPanel>
      </div>
    </div>
  );
};

ReactDOM.createRoot(document.getElementById('root')).render(<App />);

