// Main app shell

const { fmtRel } = window.CIE_DATA;
const { LangProvider, useLang } = window.CIE_I18N;

function Clock() {
  const [now, setNow] = useState(new Date());
  useEffect(() => {
    const t = setInterval(() => setNow(new Date()), 1000);
    return () => clearInterval(t);
  }, []);
  const pad = n => String(n).padStart(2, '0');
  return (
    <div>
      <span className="label">UTC</span>
      <span className="clock">
        {now.getUTCFullYear()}-{pad(now.getUTCMonth()+1)}-{pad(now.getUTCDate())} {pad(now.getUTCHours())}:{pad(now.getUTCMinutes())}
      </span>
    </div>
  );
}

function Loader() {
  const { t } = useLang();
  return (
    <div style={{
      height:'100vh', display:'flex', flexDirection:'column',
      alignItems:'center', justifyContent:'center',
      background:'var(--bg)', gap:12,
    }}>
      <div style={{fontFamily:'var(--mono)', fontSize:11, color:'var(--text-mute)', letterSpacing:'0.2em', textTransform:'uppercase'}}>
        {t('boot.connecting')}
      </div>
    </div>
  );
}

function BootError({ msg }) {
  const { t } = useLang();
  return (
    <div style={{
      height:'100vh', display:'flex', flexDirection:'column',
      alignItems:'center', justifyContent:'center',
      background:'var(--bg)', gap:12,
    }}>
      <div style={{fontFamily:'var(--mono)', fontSize:12, color:'var(--err)'}}>{t('boot.conn_error')}</div>
      <div style={{fontFamily:'var(--mono)', fontSize:11, color:'var(--text-mute)', maxWidth:400, textAlign:'center'}}>{msg}</div>
      <button className="btn sm" onClick={() => window.location.reload()}>{t('retry')}</button>
    </div>
  );
}

function AccessDenied({ username }) {
  const { t } = useLang();
  return (
    <div style={{
      height:'100vh', display:'flex', flexDirection:'column',
      alignItems:'center', justifyContent:'center',
      background:'var(--bg)', gap:16,
    }}>
      <div style={{
        fontFamily:'var(--mono)', fontSize:11, letterSpacing:'0.2em',
        color:'var(--text-mute)', textTransform:'uppercase', marginBottom:4,
      }}>{t('boot.access_denied_label')}</div>
      <div style={{
        width:52, height:52, borderRadius:8,
        background:'var(--surface-1)', border:'1px solid var(--line)',
        display:'grid', placeItems:'center', fontSize:22,
      }}>🔒</div>
      <div style={{textAlign:'center'}}>
        <div style={{fontWeight:600, fontSize:15, marginBottom:6}}>{t('boot.access_denied_title')}</div>
        <div style={{fontFamily:'var(--mono)', fontSize:11, color:'var(--text-mute)', maxWidth:340, lineHeight:1.7}}>
          {t('boot.access_denied_body', { username: username || '?' }).split('\n').map((line, i) => (
            <span key={i}>{line}{i === 0 && <br />}</span>
          ))}
        </div>
      </div>
      <button className="btn ghost sm" onClick={() => CIE_API.logout().finally(() => window.location.reload())}>
        {t('boot.login_other')}
      </button>
    </div>
  );
}

function LoginPage({ onSuccess }) {
  const [username, setUsername] = useState('');
  const [password, setPassword] = useState('');
  const [error, setError] = useState('');
  const [loading, setLoading] = useState(false);

  const inputStyle = {
    background: 'var(--bg)', border: '1px solid var(--border)', borderRadius: 4,
    padding: '8px 12px', color: 'var(--text)', fontSize: 13, width: '100%',
    outline: 'none', fontFamily: 'var(--sans)',
  };

  async function handleSubmit(e) {
    e.preventDefault();
    setLoading(true);
    setError('');
    try {
      await CIE_API.loginWithPassword(username, password);
      onSuccess();
    } catch (err) {
      setError(err.status === 401 ? 'Невірний логін або пароль' : 'Помилка з\'єднання');
    } finally {
      setLoading(false);
    }
  }

  return (
    <div style={{
      position: 'fixed', inset: 0,
      display: 'flex', alignItems: 'center', justifyContent: 'center',
      background: 'var(--bg)',
    }}>
      <form onSubmit={handleSubmit} style={{
        width: 300, display: 'flex', flexDirection: 'column', gap: 10,
        background: 'var(--surface)', border: '1px solid var(--border)',
        borderRadius: 8, padding: '32px 28px',
      }}>
        <div style={{display:'flex', flexDirection:'column', alignItems:'center', gap:8, marginBottom:12}}>
          <svg style={{width:44, height:44}} viewBox="0 0 763.55 763.55" xmlns="http://www.w3.org/2000/svg">
            <circle cx="381.77" cy="381.77" r="381.77" style={{fill:'var(--accent)'}}/>
            <circle cx="381.77" cy="381.77" r="300.15" style={{fill:'var(--bg-deep)'}}/>
            <path style={{fill:'var(--text)'}} d="M339.19,277.82c-.03,13.62-.06,27.24-.08,40.87,0,2.07,0,4.13,0,6.92-2.8.13-5.22.32-7.64.34-22.04.13-44.11-.27-66.13.48-20.01.68-36.97,8.23-44.42,28.24-7.84,21.05-2.25,40.29,12.48,56.58,13.61,15.06,31.39,21.12,51.44,21.1,18.45-.02,36.9,0,56.21,0v52.65c-.54.13-1.7.65-2.85.65-24.98-.12-50.01.58-74.94-.72-23.86-1.25-45.63-10.01-65.27-23.71-11.96-8.35-19.47-20.17-24.67-33.45-3.89-9.93-7.06-20.14-10.55-30.23,0-10.92,0-21.84,0-32.76.53-2,1.3-3.98,1.57-6.02,3.78-28.36,17.05-51.31,39.45-68.97,6.57-5.17,13.48-9.87,22.19-10.76,3.3-.34,6.59-.8,9.88-1.21,34.45,0,68.89,0,103.34,0Z"/>
            <path style={{fill:'var(--text)'}} d="M417.32,277.82c.14,30.22.22,60.44.44,90.66.28,37.36.69,74.72,1.01,112.07.01,1.41-.28,2.82-.51,4.96-10.46,0-20.69,0-30.92,0-6.51,0-13.03-.22-19.52.07-4.31.19-5.75-1.1-5.75-5.64-.02-28.55-.38-57.09-.6-85.64-.3-38.83-.57-77.65-.86-116.48h56.71Z"/>
            <path style={{fill:'var(--text)'}} d="M598.79,277.82c.23,14.65.54,29.3.58,43.94,0,1.14-1.62,2.8-2.86,3.3-1.67.68-3.7.63-5.57.64-49.11.06-98.22.09-147.32.11-1.24,0-2.47-.2-4.87-.41v-47.58c53.35,0,106.7,0,160.04,0Z"/>
            <path style={{fill:'var(--text)'}} d="M496.05,407.41c0,7.35-.25,14.66.25,21.92.08,1.18,3.41,3.06,5.25,3.07,24.57.16,49.14.03,73.72-.01,8.17-.01,16.33,0,24.98,0v53.13h-159.21c0-13.51.07-26.24-.01-38.98-.19-28.53-.34-57.06-.83-85.58-.09-5.3.89-7.24,6.75-7.21,47.46.21,94.93.07,142.39.03q11.4-.01,11.4,11.05c0,11.97-.1,23.94.05,35.91.06,4.28-.57,6.06-5.87,6.02-31.91-.29-63.82,0-95.74.12-.8,0-1.6.27-3.13.55Z"/>
          </svg>
          <div style={{fontWeight:700, fontSize:15, letterSpacing:'0.04em'}}>CIE Panel</div>
          <div style={{fontSize:10, color:'var(--text-mute)', letterSpacing:'0.12em', textTransform:'uppercase'}}>Conflict in Europe · Ops</div>
        </div>

        <input
          type="text" value={username} onChange={e => setUsername(e.target.value)}
          placeholder="Username" required autoFocus style={inputStyle}
        />
        <input
          type="password" value={password} onChange={e => setPassword(e.target.value)}
          placeholder="Password" required style={inputStyle}
        />

        {error && <div style={{color:'var(--err)', fontSize:12, textAlign:'center'}}>Invalid username or password</div>}

        <button type="submit" className="btn" disabled={loading} style={{marginTop:4, width:'100%', justifyContent:'center'}}>
          {loading ? '...' : 'Sign in'}
        </button>
      </form>
    </div>
  );
}

function AppInner() {
  const { t, lang, switchLang } = useLang();
  const [view, setView] = useState('dashboard');
  const [editorServerId, setEditorServerId] = useState(null);
  const [user, setUser] = useState(null);
  const [servers, setServers] = useState(null);
  const [bootError, setBootError] = useState(null);
  const [showLogin, setShowLogin] = useState(false);
  const [accessDenied, setAccessDenied] = useState(null); // username якщо 403

  const NAV = [
    { id:'dashboard', label: t('nav.dashboard'), ix:'01' },
    { id:'editor',    label: t('nav.editor'),    ix:'02' },
    { id:'mods',      label: t('nav.mods'),      ix:'03' },
    { id:'audit',     label: t('nav.audit'),     ix:'04' },
    { id:'settings',  label: t('nav.settings'),  ix:'05' },
  ];

  function loadUser() {
    CIE_API.getMe()
      .then(u => { setUser(u); return CIE_API.getServers(); })
      .then(svrs => { if (svrs) setServers(svrs); })
      .catch(err => {
        if (err.status === 401) {
          setShowLogin(true);
        } else if (err.message.startsWith('403')) {
          const match = err.message.match(/User '([^']+)'/);
          setAccessDenied(match ? match[1] : '');
        } else {
          setBootError(err.message);
        }
      });
  }

  useEffect(() => { loadUser(); }, []);

  const refreshServers = () => {
    CIE_API.getServers()
      .then(svrs => { if (svrs) setServers(svrs); })
      .catch(() => {});
  };

  // Автооновлення A2S кожні 30 секунд
  useEffect(() => {
    if (!user) return;
    const t = setInterval(refreshServers, 30_000);
    return () => clearInterval(t);
  }, [user]);

  if (showLogin) return <LoginPage onSuccess={() => { setShowLogin(false); loadUser(); }} />;
  if (!user && !bootError && !accessDenied) return <Loader />;
  if (bootError) return <BootError msg={bootError} />;
  if (accessDenied !== null && !user) return <AccessDenied username={accessDenied} />;

  const openEditor = (serverId) => {
    setEditorServerId(serverId || null);
    setView('editor');
  };

  // Normalize user fields (backend може повертати snake_case)
  const displayName = user.display_name || user.name || user.username || user.id || '?';
  const initials = displayName.split(/[\s._-]/).map(w => w[0]).join('').toUpperCase().slice(0, 2);
  const role = user.role || 'admin';
  const isOwner = role === 'owner';
  const visibleNAV = NAV.filter(n => isOwner || (n.id !== 'audit' && n.id !== 'settings'));

  const onlineCount = servers ? servers.filter(s => s.a2s?.online || s.status === 'online').length : 0;
  const totalCount  = servers ? servers.length : 0;

  const heres = NAV.find(n => n.id === view)?.label || t('nav.dashboard');

  // Guard: non-owner cannot access audit/settings
  if (!isOwner && (view === 'audit' || view === 'settings')) setView('dashboard');

  let content;
  if (view === 'dashboard') content = <Dashboard servers={servers} openEditor={openEditor} onRefresh={refreshServers} />;
  else if (view === 'editor')   content = <ConfigEditor servers={servers} initialServerId={editorServerId} goto={setView} />;
  else if (view === 'mods')     content = <ModsMatrix servers={servers} />;
  else if (view === 'audit'    && isOwner) content = <AuditLog servers={servers} />;
  else if (view === 'settings' && isOwner) content = <Settings user={user} />;
  else content = <Dashboard servers={servers} openEditor={openEditor} onRefresh={refreshServers} />;

  return (
    <div className="app">
      <div className="topbar">
        <div className="brand">
          <svg className="mark-logo" viewBox="0 0 763.55 763.55" xmlns="http://www.w3.org/2000/svg">
            <circle cx="381.77" cy="381.77" r="381.77" style={{fill:'var(--accent)'}}/>
            <circle cx="381.77" cy="381.77" r="300.15" style={{fill:'var(--bg-deep)'}}/>
            <path style={{fill:'var(--text)'}} d="M339.19,277.82c-.03,13.62-.06,27.24-.08,40.87,0,2.07,0,4.13,0,6.92-2.8.13-5.22.32-7.64.34-22.04.13-44.11-.27-66.13.48-20.01.68-36.97,8.23-44.42,28.24-7.84,21.05-2.25,40.29,12.48,56.58,13.61,15.06,31.39,21.12,51.44,21.1,18.45-.02,36.9,0,56.21,0v52.65c-.54.13-1.7.65-2.85.65-24.98-.12-50.01.58-74.94-.72-23.86-1.25-45.63-10.01-65.27-23.71-11.96-8.35-19.47-20.17-24.67-33.45-3.89-9.93-7.06-20.14-10.55-30.23,0-10.92,0-21.84,0-32.76.53-2,1.3-3.98,1.57-6.02,3.78-28.36,17.05-51.31,39.45-68.97,6.57-5.17,13.48-9.87,22.19-10.76,3.3-.34,6.59-.8,9.88-1.21,34.45,0,68.89,0,103.34,0Z"/>
            <path style={{fill:'var(--text)'}} d="M417.32,277.82c.14,30.22.22,60.44.44,90.66.28,37.36.69,74.72,1.01,112.07.01,1.41-.28,2.82-.51,4.96-10.46,0-20.69,0-30.92,0-6.51,0-13.03-.22-19.52.07-4.31.19-5.75-1.1-5.75-5.64-.02-28.55-.38-57.09-.6-85.64-.3-38.83-.57-77.65-.86-116.48h56.71Z"/>
            <path style={{fill:'var(--text)'}} d="M598.79,277.82c.23,14.65.54,29.3.58,43.94,0,1.14-1.62,2.8-2.86,3.3-1.67.68-3.7.63-5.57.64-49.11.06-98.22.09-147.32.11-1.24,0-2.47-.2-4.87-.41v-47.58c53.35,0,106.7,0,160.04,0Z"/>
            <path style={{fill:'var(--text)'}} d="M496.05,407.41c0,7.35-.25,14.66.25,21.92.08,1.18,3.41,3.06,5.25,3.07,24.57.16,49.14.03,73.72-.01,8.17-.01,16.33,0,24.98,0v53.13h-159.21c0-13.51.07-26.24-.01-38.98-.19-28.53-.34-57.06-.83-85.58-.09-5.3.89-7.24,6.75-7.21,47.46.21,94.93.07,142.39.03q11.4-.01,11.4,11.05c0,11.97-.1,23.94.05,35.91.06,4.28-.57,6.06-5.87,6.02-31.91-.29-63.82,0-95.74.12-.8,0-1.6.27-3.13.55Z"/>
          </svg>
          <div>
            <div className="brand-name">CIE Panel</div>
            <div className="brand-sub">Conflict in Europe · Ops</div>
          </div>
        </div>
        <div className="crumbs">
          <span>CIE-OPS</span>
          <span className="slash">/</span>
          <span>FLEET</span>
          <span className="slash">/</span>
          <span className="here">{heres}</span>
        </div>
        <div className="topbar-meta">
          <div>
            <span className="label">{t('servers')}</span>
            <span className="clock">{t('nav.online_of', { online: onlineCount, total: totalCount })}</span>
          </div>
          <div className="sep" />
          <Clock />
          <div className="sep" />
          <select
            value={lang}
            onChange={e => { if (e.target.value !== lang) switchLang(e.target.value); }}
            style={{
              fontFamily:'var(--mono)', fontSize:11, letterSpacing:'0.08em',
              background:'transparent', color:'var(--text-dim)',
              border:'1px solid var(--border)', borderRadius:4,
              padding:'2px 6px', cursor:'pointer', outline:'none',
            }}
          >
            <option value="en" style={{background:'var(--surface)'}}>EN</option>
            <option value="uk" style={{background:'var(--surface)'}}>UK</option>
            <option value="zh" style={{background:'var(--surface)'}}>ZH</option>
          </select>
          <div className="sep" />
          <div className="user-chip" style={{position:'relative', cursor:'pointer'}}
            onMouseEnter={e => e.currentTarget.querySelector('.user-menu').style.display='block'}
            onMouseLeave={e => e.currentTarget.querySelector('.user-menu').style.display='none'}
          >
            <span className="av">{initials}</span>
            <div>
              <div className="name">{displayName}</div>
              <div className="role">{role}</div>
            </div>
            <div className="user-menu" style={{
              display:'none', position:'absolute', top:'100%', right:0,
              paddingTop:4, minWidth:140, zIndex:100,
            }}>
            <div style={{
              background:'var(--surface)', border:'1px solid var(--border)',
              borderRadius:4, boxShadow:'0 4px 16px rgba(0,0,0,0.3)',
            }}>
              <div
                onClick={() => CIE_API.logout().finally(() => window.location.reload())}
                style={{
                  padding:'8px 14px', fontSize:12, color:'var(--err)',
                  cursor:'pointer', fontFamily:'var(--mono)',
                  letterSpacing:'0.04em',
                }}
                onMouseEnter={e => e.currentTarget.style.background='var(--surface-2)'}
                onMouseLeave={e => e.currentTarget.style.background='transparent'}
              >Sign out</div>
            </div>
            </div>
          </div>
        </div>
      </div>

      <aside className="sidebar">
        <div className="nav-group">
          <div className="heading">{t('nav.operations')}</div>
          {visibleNAV.map(n => (
            <div key={n.id} className={`nav-item ${view === n.id ? 'active' : ''}`} onClick={() => setView(n.id)}>
              <span className="ix">{n.ix}</span>
              <span>{n.label}</span>
              {n.id === 'dashboard' && servers && <span className="badge">{servers.length}</span>}
            </div>
          ))}
        </div>

        <div className="sidebar-foot">
          <div className="row"><span>Gitea</span><span className="v ok">● up</span></div>
          <div className="row"><span>Discord</span><span className="v ok">● up</span></div>
          <div className="row">
            <span>User</span>
            <span className="v" style={{color: role === 'owner' ? 'var(--accent)' : 'var(--text-dim)', textTransform:'uppercase', fontSize:9}}>
              {role}
            </span>
          </div>
        </div>
      </aside>

      <main className="main">
        {content}
      </main>
      {role === 'owner' && <ThemeTweaker />}
    </div>
  );
}

function App() {
  return (
    <LangProvider>
      <AppInner />
    </LangProvider>
  );
}

// ── Theme Tweaker (owner only) ────────────────────────────────────────────────
const THEME_KEYS = ['--bg','--bg-deep','--surface','--surface-2','--surface-3','--border','--border-strong','--text','--text-dim','--text-mute','--accent','--accent-dim','--ok','--warn','--err'];

const THEMES = {
  blue:     { label:'Blue',     swatch:'#6090ff', '--bg':'#0b0c10','--bg-deep':'#07080c','--surface':'#11131a','--surface-2':'#161820','--surface-3':'#1b1e28','--border':'#22263a','--border-strong':'#2c3150','--text':'#d8dbe6','--text-dim':'#8a90a8','--text-mute':'#565c7a','--accent':'#6090ff','--accent-dim':'#3050c0','--ok':'#58cc58','--warn':'#d4b830','--err':'#d0503a' },
  green:    { label:'Green',    swatch:'#7ad47a', '--bg':'#0b0d0c','--bg-deep':'#070908','--surface':'#121514','--surface-2':'#171b1a','--surface-3':'#1d2120','--border':'#23282a','--border-strong':'#2e3a30','--text':'#d8dedb','--text-dim':'#8a9290','--text-mute':'#5b6463','--accent':'#7ad47a','--accent-dim':'#3e7a3e','--ok':'#6cd96c','--warn':'#d4b830','--err':'#d0503a' },
  crimson:  { label:'Crimson',  swatch:'#ff5a5a', '--bg':'#100b0b','--bg-deep':'#0c0707','--surface':'#1a1111','--surface-2':'#201616','--surface-3':'#281b1b','--border':'#3a2222','--border-strong':'#502c2c','--text':'#e6d8d8','--text-dim':'#a88a8a','--text-mute':'#7a5656','--accent':'#ff5a5a','--accent-dim':'#c02828','--ok':'#58cc58','--warn':'#d4b830','--err':'#ff3030' },
  amber:    { label:'Amber',    swatch:'#ffb840', '--bg':'#100e08','--bg-deep':'#0c0a05','--surface':'#1a1710','--surface-2':'#201c14','--surface-3':'#28221a','--border':'#3a3020','--border-strong':'#504030','--text':'#e6dcc8','--text-dim':'#a89870','--text-mute':'#7a6848','--accent':'#ffb840','--accent-dim':'#c07820','--ok':'#70cc58','--warn':'#ffb840','--err':'#d0503a' },
  purple:   { label:'Purple',   swatch:'#b060ff', '--bg':'#0d0b10','--bg-deep':'#08060c','--surface':'#14111a','--surface-2':'#191620','--surface-3':'#201c28','--border':'#2e2240','--border-strong':'#3e2e58','--text':'#ddd8e6','--text-dim':'#9a90a8','--text-mute':'#6a6080','--accent':'#b060ff','--accent-dim':'#7030c0','--ok':'#58cc58','--warn':'#d4b830','--err':'#d0503a' },
  desert:   { label:'Desert',   swatch:'#c8a85a', '--bg':'#100f0a','--bg-deep':'#0c0b07','--surface':'#1a1912','--surface-2':'#201e16','--surface-3':'#28251c','--border':'#3a3628','--border-strong':'#504a38','--text':'#e6e0cc','--text-dim':'#a8a080','--text-mute':'#7a7258','--accent':'#c8a85a','--accent-dim':'#906820','--ok':'#78cc60','--warn':'#c8a85a','--err':'#d0503a' },
  mono:     { label:'Mono',     swatch:'#b0b0b0', '--bg':'#0c0c0c','--bg-deep':'#080808','--surface':'#131313','--surface-2':'#181818','--surface-3':'#1e1e1e','--border':'#282828','--border-strong':'#383838','--text':'#e0e0e0','--text-dim':'#909090','--text-mute':'#606060','--accent':'#b0b0b0','--accent-dim':'#686868','--ok':'#88cc88','--warn':'#ccb840','--err':'#cc6060' },
  teal:     { label:'Teal',     swatch:'#30d4c0', '--bg':'#080e0d','--bg-deep':'#050a09','--surface':'#0f1918','--surface-2':'#141f1e','--surface-3':'#1a2624','--border':'#1e3432','--border-strong':'#284844','--text':'#d0e8e4','--text-dim':'#7aaa9e','--text-mute':'#4a7068','--accent':'#30d4c0','--accent-dim':'#188878','--ok':'#30d4c0','--warn':'#d4c030','--err':'#d05040' },
  neon:     { label:'Neon',     swatch:'#00ff88', '--bg':'#080c09','--bg-deep':'#040704','--surface':'#0c1210','--surface-2':'#101814','--surface-3':'#141f18','--border':'#1a2e20','--border-strong':'#204030','--text':'#c8f0d8','--text-dim':'#6aaa80','--text-mute':'#3a6848','--accent':'#00ff88','--accent-dim':'#00a050','--ok':'#00ff88','--warn':'#d4e030','--err':'#ff4060' },
  midnight: { label:'Midnight', swatch:'#4488dd', '--bg':'#080a12','--bg-deep':'#05060d','--surface':'#0d1020','--surface-2':'#111428','--surface-3':'#161930','--border':'#1e2440','--border-strong':'#283056','--text':'#c8d4f0','--text-dim':'#7088b8','--text-mute':'#485878','--accent':'#4488dd','--accent-dim':'#2255aa','--ok':'#44cc88','--warn':'#ddaa44','--err':'#dd4444' },
  olive:    { label:'Olive',    swatch:'#90a830', '--bg':'#0c0e08','--bg-deep':'#080a05','--surface':'#141710','--surface-2':'#191c14','--surface-3':'#1e221a','--border':'#2c3018','--border-strong':'#3c4020','--text':'#d8dcc0','--text-dim':'#909870','--text-mute':'#606848','--accent':'#90a830','--accent-dim':'#586818','--ok':'#90a830','--warn':'#d4a830','--err':'#d05038' },
  copper:   { label:'Copper',   swatch:'#d4784a', '--bg':'#100c08','--bg-deep':'#0c0905','--surface':'#1c1410','--surface-2':'#221914','--surface-3':'#2a1f18','--border':'#3c2818','--border-strong':'#543420','--text':'#ecddd0','--text-dim':'#b09080','--text-mute':'#806858','--accent':'#d4784a','--accent-dim':'#a04828','--ok':'#78c860','--warn':'#d4a840','--err':'#d04030' },
  ice:      { label:'Ice',      swatch:'#88d4f0', '--bg':'#090c10','--bg-deep':'#060810','--surface':'#101520','--surface-2':'#141a28','--surface-3':'#1a2030','--border':'#202840','--border-strong':'#2c3858','--text':'#d8eaf8','--text-dim':'#8aaac8','--text-mute':'#587898','--accent':'#88d4f0','--accent-dim':'#3898c8','--ok':'#60d898','--warn':'#d4c860','--err':'#d05858' },
  rose:     { label:'Rose',     swatch:'#f06080', '--bg':'#100a0c','--bg-deep':'#0c0709','--surface':'#1c1018','--surface-2':'#22141e','--surface-3':'#2a1a26','--border':'#402030','--border-strong':'#582840','--text':'#f0d8e0','--text-dim':'#c09098','--text-mute':'#906070','--accent':'#f06080','--accent-dim':'#b03050','--ok':'#68d878','--warn':'#d4aa40','--err':'#f02040' },
  slate:    { label:'Slate',    swatch:'#7898c0', '--bg':'#090b0e','--bg-deep':'#060709','--surface':'#101318','--surface-2':'#141820','--surface-3':'#181d28','--border':'#222840','--border-strong':'#2e3550','--text':'#c8d4e0','--text-dim':'#7888a0','--text-mute':'#4c5870','--accent':'#7898c0','--accent-dim':'#4868a0','--ok':'#60c880','--warn':'#c8a840','--err':'#c85848' },
};

const applyTheme = (theme) => {
  THEME_KEYS.forEach(k => document.documentElement.style.setProperty(k, theme[k]));
  document.documentElement.style.setProperty('--accent-glow', theme['--accent'] + '22');
};

const TWEAK_GROUPS = [
  { label: 'Background', vars: ['--bg', '--bg-deep'] },
  { label: 'Surface',    vars: ['--surface', '--surface-2', '--surface-3'] },
  { label: 'Border',     vars: ['--border', '--border-strong'] },
  { label: 'Text',       vars: ['--text', '--text-dim', '--text-mute'] },
  { label: 'Accent',     vars: ['--accent', '--accent-dim'] },
  { label: 'Status',     vars: ['--ok', '--warn', '--err'] },
];

function ThemeTweaker() {
  const [open, setOpen]          = useState(false);
  const [activeTheme, setActive] = useState('blue');
  const [vals, setVals]          = useState(() => ({ ...THEMES.blue }));
  const [zoom, setZoom]          = useState(1.0);

  const setScale = (v) => { setZoom(v); document.body.style.zoom = v; };

  const loadTheme = (name) => {
    setActive(name);
    setVals({ ...THEMES[name] });
    applyTheme(THEMES[name]);
  };

  const set = (key, hex) => {
    setVals(prev => ({ ...prev, [key]: hex }));
    document.documentElement.style.setProperty(key, hex);
    if (key === '--accent') document.documentElement.style.setProperty('--accent-glow', hex + '22');
  };

  const copy = () => {
    const lines = THEME_KEYS.map(k => `  ${k}: ${vals[k]};`).join('\n');
    navigator.clipboard.writeText(`:root {\n${lines}\n}`);
  };

  return (
    <>
      <button
        onClick={() => setOpen(o => !o)}
        style={{
          position:'fixed', bottom:16, right:16, zIndex:9999,
          background: open ? vals['--accent'] : '#1b1e28',
          color: open ? '#000' : '#8a90a8',
          border:'1px solid #2c3150', borderRadius:6,
          padding:'6px 12px', fontFamily:'var(--mono)', fontSize:11,
          cursor:'pointer', letterSpacing:'0.06em', transition:'background 0.15s',
        }}
      >🎨 theme</button>

      {open && (
        <div style={{
          position:'fixed', bottom:60, right:12, zIndex:9999,
          background:'#0a0b10', border:'1px solid #2c3150',
          borderRadius:6, width:268, maxHeight:'80vh', overflowY:'auto',
          boxShadow:'0 8px 32px #0008', fontFamily:'var(--mono)', fontSize:11,
        }}>
          {/* Header */}
          <div style={{display:'flex', alignItems:'center', justifyContent:'space-between', padding:'8px 12px', borderBottom:'1px solid #22263a', position:'sticky', top:0, background:'#0a0b10', zIndex:1}}>
            <span style={{color:'#d8dbe6', letterSpacing:'0.1em', fontSize:10}}>THEME</span>
            <div style={{display:'flex', gap:6}}>
              <button onClick={() => loadTheme(activeTheme)} style={{background:'none', border:'1px solid #2c3150', color:'#8a90a8', borderRadius:4, padding:'2px 8px', cursor:'pointer', fontFamily:'var(--mono)', fontSize:10}}>reset</button>
              <button onClick={copy} style={{background:'none', border:'1px solid #2c3150', color:'#8a90a8', borderRadius:4, padding:'2px 8px', cursor:'pointer', fontFamily:'var(--mono)', fontSize:10}}>copy css</button>
            </div>
          </div>

          {/* Presets */}
          <div style={{padding:'8px 10px', borderBottom:'1px solid #22263a', display:'flex', flexWrap:'wrap', gap:6}}>
            {Object.entries(THEMES).map(([name, th]) => (
              <button
                key={name}
                onClick={() => loadTheme(name)}
                style={{
                  display:'flex', alignItems:'center', gap:5,
                  padding:'4px 8px', borderRadius:4, cursor:'pointer',
                  fontFamily:'var(--mono)', fontSize:10,
                  border: activeTheme === name ? `1px solid ${th['--accent']}` : '1px solid #22263a',
                  background: activeTheme === name ? th['--accent'] + '20' : 'none',
                  color: activeTheme === name ? th['--accent'] : '#8a90a8',
                  transition:'all 0.12s',
                }}
              >
                <span style={{width:8, height:8, borderRadius:'50%', background:th.swatch, flexShrink:0}} />
                {th.label}
              </button>
            ))}
          </div>

          {/* Scale */}
          <div style={{padding:'8px 12px', borderBottom:'1px solid #15181a'}}>
            <div style={{color:'#565c7a', letterSpacing:'0.12em', fontSize:9, marginBottom:8, textTransform:'uppercase'}}>Scale</div>
            <div style={{display:'flex', alignItems:'center', gap:10}}>
              <input
                type="range" min="0.7" max="1.4" step="0.05" value={zoom}
                onChange={e => setScale(parseFloat(e.target.value))}
                style={{flex:1, cursor:'pointer', accentColor:'var(--accent)'}}
              />
              <span style={{color:'#d8dbe6', fontSize:11, width:38, textAlign:'right', fontFamily:'var(--mono)'}}>
                {Math.round(zoom * 100)}%
              </span>
              <button onClick={() => setScale(1.0)} style={{background:'none', border:'1px solid #2c3150', color:'#8a90a8', borderRadius:4, padding:'2px 8px', cursor:'pointer', fontFamily:'var(--mono)', fontSize:10}}>1×</button>
            </div>
          </div>

          {/* Fine-tune */}
          {TWEAK_GROUPS.map(g => (
            <div key={g.label} style={{padding:'8px 12px', borderBottom:'1px solid #15181a'}}>
              <div style={{color:'#565c7a', letterSpacing:'0.12em', fontSize:9, marginBottom:6, textTransform:'uppercase'}}>{g.label}</div>
              {g.vars.map(key => (
                <div key={key} style={{display:'flex', alignItems:'center', gap:8, marginBottom:5}}>
                  <input type="color" value={vals[key] || '#000000'} onChange={e => set(key, e.target.value)}
                    style={{width:24, height:18, border:'none', background:'none', cursor:'pointer', padding:0, flexShrink:0}} />
                  <span style={{color:'#8a90a8', flex:1, fontSize:10}}>{key.replace('--','')}</span>
                  <input type="text" value={vals[key] || ''} onChange={e => { if (/^#[0-9a-fA-F]{0,6}$/.test(e.target.value)) set(key, e.target.value); }}
                    style={{width:70, background:'#07080c', border:'1px solid #22263a', color:'#d8dbe6', borderRadius:3, padding:'2px 6px', fontFamily:'var(--mono)', fontSize:10}} />
                </div>
              ))}
            </div>
          ))}
        </div>
      )}
    </>
  );
}

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