@littlepartytime/dev-kit 1.11.0 → 1.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -14,15 +14,25 @@ export default function App() {
14
14
  });
15
15
 
16
16
  return (
17
- <div className="min-h-screen flex flex-col">
17
+ <div style={{ minHeight: '100vh', display: 'flex', flexDirection: 'column' }}>
18
18
  {/* Nav */}
19
- <nav className="bg-zinc-900 border-b border-zinc-800 px-4 py-2 flex gap-4">
20
- <span className="text-amber-500 font-bold mr-4">LPT Dev Kit</span>
19
+ <nav style={{ background: '#18181b', borderBottom: '1px solid #27272a', padding: '8px 16px', display: 'flex', gap: 16, alignItems: 'center' }}>
20
+ <span style={{ color: '#f59e0b', fontWeight: 700, marginRight: 16 }}>LPT Dev Kit</span>
21
21
  {(['preview', 'play', 'debug'] as Page[]).map((p) => (
22
22
  <button
23
23
  key={p}
24
24
  onClick={() => { setPage(p); history.pushState(null, '', `/${p}`); }}
25
- className={`px-3 py-1 rounded ${page === p ? 'bg-amber-600 text-white' : 'text-zinc-400 hover:text-white'}`}
25
+ className="dk-nav-btn"
26
+ style={{
27
+ padding: '4px 12px',
28
+ borderRadius: 4,
29
+ border: 'none',
30
+ cursor: 'pointer',
31
+ fontSize: 14,
32
+ ...(page === p
33
+ ? { background: '#d97706', color: '#fff' }
34
+ : { background: 'transparent', color: '#a1a1aa' }),
35
+ }}
26
36
  >
27
37
  {p.charAt(0).toUpperCase() + p.slice(1)}
28
38
  </button>
@@ -30,7 +40,7 @@ export default function App() {
30
40
  </nav>
31
41
 
32
42
  {/* Content */}
33
- <main className="flex-1 p-4">
43
+ <main style={{ flex: 1, padding: 16 }}>
34
44
  {page === 'preview' && <Preview />}
35
45
  {page === 'play' && <Play />}
36
46
  {page === 'debug' && <Debug />}
@@ -40,15 +40,14 @@ export default function PhoneFrame({ children }: { children: React.ReactNode })
40
40
  return (
41
41
  <div
42
42
  ref={containerRef}
43
- className="flex items-center justify-center h-full overflow-hidden"
44
- style={{ flex: 1, minWidth: 0, minHeight: 0 }}
43
+ style={{ flex: 1, minWidth: 0, minHeight: 0, display: 'flex', alignItems: 'center', justifyContent: 'center', height: '100%', overflow: 'hidden' }}
45
44
  >
46
45
  {/* Wrapper sized to the scaled phone for correct layout flow */}
47
46
  <div style={{ width: BODY_W * scale, height: BODY_H * scale, flexShrink: 0 }}>
48
47
  {/* Phone body at original pixel size, visually scaled */}
49
48
  <div
50
- className="relative"
51
49
  style={{
50
+ position: 'relative',
52
51
  width: BODY_W,
53
52
  height: BODY_H,
54
53
  transform: `scale(${scale})`,
@@ -57,8 +56,9 @@ export default function PhoneFrame({ children }: { children: React.ReactNode })
57
56
  >
58
57
  {/* Frame / bezel */}
59
58
  <div
60
- className="absolute inset-0"
61
59
  style={{
60
+ position: 'absolute',
61
+ inset: 0,
62
62
  borderRadius: OUTER_R,
63
63
  background: '#1c1c1e',
64
64
  boxShadow:
@@ -68,8 +68,10 @@ export default function PhoneFrame({ children }: { children: React.ReactNode })
68
68
 
69
69
  {/* Screen */}
70
70
  <div
71
- className="absolute overflow-hidden bg-black"
72
71
  style={{
72
+ position: 'absolute',
73
+ overflow: 'hidden',
74
+ background: '#000',
73
75
  top: BEZEL,
74
76
  left: BEZEL,
75
77
  width: SCREEN_W,
@@ -82,8 +84,9 @@ export default function PhoneFrame({ children }: { children: React.ReactNode })
82
84
  contain:paint makes this the containing block for
83
85
  position:fixed elements inside the game. */}
84
86
  <div
85
- className="absolute overflow-hidden"
86
87
  style={{
88
+ position: 'absolute',
89
+ overflow: 'hidden',
87
90
  top: SAFE_AREA_TOP,
88
91
  left: 0,
89
92
  right: 0,
@@ -97,14 +100,26 @@ export default function PhoneFrame({ children }: { children: React.ReactNode })
97
100
 
98
101
  {/* Dynamic Island */}
99
102
  <div
100
- className="absolute left-1/2 -translate-x-1/2 bg-black rounded-full"
101
- style={{ top: BEZEL + 11, width: 126, height: 37, zIndex: 10 }}
103
+ style={{
104
+ position: 'absolute',
105
+ left: '50%',
106
+ transform: 'translateX(-50%)',
107
+ background: '#000',
108
+ borderRadius: 9999,
109
+ top: BEZEL + 11,
110
+ width: 126,
111
+ height: 37,
112
+ zIndex: 10,
113
+ }}
102
114
  />
103
115
 
104
116
  {/* Home Indicator */}
105
117
  <div
106
- className="absolute left-1/2 -translate-x-1/2 rounded-full"
107
118
  style={{
119
+ position: 'absolute',
120
+ left: '50%',
121
+ transform: 'translateX(-50%)',
122
+ borderRadius: 9999,
108
123
  bottom: BEZEL + 8,
109
124
  width: 134,
110
125
  height: 5,
@@ -4,9 +4,22 @@
4
4
  <meta charset="UTF-8" />
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
6
  <title>LPT Dev Kit</title>
7
- <script src="https://cdn.tailwindcss.com"></script>
8
7
  <style>
9
- body { background: #0a0a0a; color: #e5e5e5; }
8
+ /* ── Dev-Kit UI base ── */
9
+ *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
10
+ body { background: #0a0a0a; color: #e5e5e5; font-family: system-ui, -apple-system, sans-serif; }
11
+
12
+ /* ── Interactive states (can't be expressed as inline styles) ── */
13
+ .dk-nav-btn:hover { color: #fff; }
14
+ .dk-btn-amber:hover { background: #f59e0b; }
15
+ .dk-btn-zinc:hover { background: #52525b; }
16
+ .dk-btn-green:hover { background: #16a34a; }
17
+ .dk-player-btn { transition: background 0.15s; }
18
+ .dk-player-btn:hover { background: #3f3f46; }
19
+ .dk-resize-bar .dk-resize-line { transition: background 0.15s; }
20
+ .dk-resize-bar:hover .dk-resize-line { background: #71717a; }
21
+ .dk-input:focus { outline: none; border-color: #71717a; }
22
+ .dk-btn-amber:disabled, .dk-btn-green:disabled { opacity: 0.5; }
10
23
  </style>
11
24
  </head>
12
25
  <body>
@@ -18,20 +18,22 @@ export default function Debug() {
18
18
  return () => { sock.disconnect(); };
19
19
  }, []);
20
20
 
21
+ const panelStyle: React.CSSProperties = { background: '#18181b', borderRadius: 8, padding: 16, overflow: 'auto' };
22
+
21
23
  return (
22
- <div className="grid grid-cols-2 gap-4 h-[calc(100vh-80px)]">
24
+ <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 16, height: 'calc(100vh - 80px)' }}>
23
25
  {/* Room State */}
24
- <div className="bg-zinc-900 rounded-lg p-4 overflow-auto">
25
- <h2 className="text-lg font-bold mb-4 text-amber-400">Room State</h2>
26
- <pre className="text-xs font-mono whitespace-pre-wrap">
26
+ <div style={panelStyle}>
27
+ <h2 style={{ fontSize: 18, fontWeight: 700, marginBottom: 16, color: '#fbbf24' }}>Room State</h2>
28
+ <pre style={{ fontSize: 11, fontFamily: 'monospace', whiteSpace: 'pre-wrap' }}>
27
29
  {JSON.stringify(room, null, 2)}
28
30
  </pre>
29
31
  </div>
30
32
 
31
33
  {/* Game State */}
32
- <div className="bg-zinc-900 rounded-lg p-4 overflow-auto">
33
- <h2 className="text-lg font-bold mb-4 text-amber-400">Full Game State</h2>
34
- <pre className="text-xs font-mono whitespace-pre-wrap">
34
+ <div style={panelStyle}>
35
+ <h2 style={{ fontSize: 18, fontWeight: 700, marginBottom: 16, color: '#fbbf24' }}>Full Game State</h2>
36
+ <pre style={{ fontSize: 11, fontFamily: 'monospace', whiteSpace: 'pre-wrap' }}>
35
37
  {fullState ? JSON.stringify(fullState, null, 2) : 'No game in progress'}
36
38
  </pre>
37
39
  </div>
@@ -2,6 +2,10 @@ import React, { useState, useEffect, useCallback } from 'react';
2
2
  import { io, Socket } from 'socket.io-client';
3
3
  import PhoneFrame from '../components/PhoneFrame';
4
4
 
5
+ const card: React.CSSProperties = { background: '#18181b', borderRadius: 8, padding: 24 };
6
+ const inputStyle: React.CSSProperties = { width: '100%', background: '#27272a', border: '1px solid #3f3f46', borderRadius: 4, padding: '8px 12px', marginBottom: 16, color: '#e5e5e5', fontSize: 14 };
7
+ const btnAmber: React.CSSProperties = { width: '100%', background: '#d97706', color: '#fff', border: 'none', padding: '8px 0', borderRadius: 4, fontWeight: 600, cursor: 'pointer', fontSize: 14 };
8
+
5
9
  export default function Play() {
6
10
  const [socket, setSocket] = useState<Socket | null>(null);
7
11
  const [nickname, setNickname] = useState('');
@@ -61,20 +65,22 @@ export default function Play() {
61
65
 
62
66
  if (!joined) {
63
67
  return (
64
- <div className="flex items-center justify-center h-[60vh]">
65
- <div className="bg-zinc-900 rounded-lg p-6 w-80">
66
- <h2 className="text-xl font-bold mb-4">Join Game</h2>
68
+ <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', height: '60vh' }}>
69
+ <div style={{ ...card, width: 320 }}>
70
+ <h2 style={{ fontSize: 20, fontWeight: 700, marginBottom: 16 }}>Join Game</h2>
67
71
  <input
68
72
  type="text"
69
73
  placeholder="Your nickname"
70
74
  value={nickname}
71
75
  onChange={(e) => setNickname(e.target.value)}
72
76
  onKeyDown={(e) => e.key === 'Enter' && join()}
73
- className="w-full bg-zinc-800 border border-zinc-700 rounded px-3 py-2 mb-4"
77
+ className="dk-input"
78
+ style={inputStyle}
74
79
  />
75
80
  <button
76
81
  onClick={join}
77
- className="w-full bg-amber-600 hover:bg-amber-500 text-white py-2 rounded font-semibold"
82
+ className="dk-btn-amber"
83
+ style={btnAmber}
78
84
  >
79
85
  Join
80
86
  </button>
@@ -85,23 +91,35 @@ export default function Play() {
85
91
 
86
92
  if (room.phase === 'lobby' || room.phase === 'ready') {
87
93
  return (
88
- <div className="max-w-md mx-auto mt-8">
89
- <div className="bg-zinc-900 rounded-lg p-6">
90
- <h2 className="text-xl font-bold mb-4">Lobby</h2>
91
- <div className="space-y-2 mb-6">
94
+ <div style={{ maxWidth: 448, margin: '32px auto 0' }}>
95
+ <div style={card}>
96
+ <h2 style={{ fontSize: 20, fontWeight: 700, marginBottom: 16 }}>Lobby</h2>
97
+ <div style={{ display: 'flex', flexDirection: 'column', gap: 8, marginBottom: 24 }}>
92
98
  {room.players.map((p: any) => (
93
- <div key={p.id} className="flex items-center justify-between bg-zinc-800 rounded px-3 py-2">
99
+ <div key={p.id} style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', background: '#27272a', borderRadius: 4, padding: '8px 12px' }}>
94
100
  <span>{p.nickname} {p.isHost && '(Host)'}</span>
95
- <span className={p.ready ? 'text-green-400' : 'text-zinc-500'}>
101
+ <span style={{ color: p.ready ? '#4ade80' : '#71717a' }}>
96
102
  {p.ready ? 'Ready' : 'Not Ready'}
97
103
  </span>
98
104
  </div>
99
105
  ))}
100
106
  </div>
101
- <div className="flex gap-2">
107
+ <div style={{ display: 'flex', gap: 8 }}>
102
108
  <button
103
109
  onClick={() => socket?.emit('player:ready', !isReady)}
104
- className={`flex-1 py-2 rounded font-semibold ${isReady ? 'bg-zinc-700 text-zinc-300' : 'bg-green-600 text-white'}`}
110
+ className={isReady ? 'dk-btn-zinc' : 'dk-btn-green'}
111
+ style={{
112
+ flex: 1,
113
+ padding: '8px 0',
114
+ borderRadius: 4,
115
+ fontWeight: 600,
116
+ border: 'none',
117
+ cursor: 'pointer',
118
+ fontSize: 14,
119
+ ...(isReady
120
+ ? { background: '#3f3f46', color: '#d4d4d8' }
121
+ : { background: '#16a34a', color: '#fff' }),
122
+ }}
105
123
  >
106
124
  {isReady ? 'Cancel Ready' : 'Ready'}
107
125
  </button>
@@ -109,7 +127,8 @@ export default function Play() {
109
127
  <button
110
128
  onClick={() => socket?.emit('game:start')}
111
129
  disabled={!room.players.every((p: any) => p.ready) || room.players.length < 2}
112
- className="flex-1 bg-amber-600 hover:bg-amber-500 disabled:opacity-50 text-white py-2 rounded font-semibold"
130
+ className="dk-btn-amber"
131
+ style={{ ...btnAmber, flex: 1, width: 'auto' }}
113
132
  >
114
133
  Start Game
115
134
  </button>
@@ -122,19 +141,20 @@ export default function Play() {
122
141
 
123
142
  // Playing or ended
124
143
  return (
125
- <div className="h-[calc(100vh-80px)] relative">
144
+ <div style={{ height: 'calc(100vh - 80px)', position: 'relative' }}>
126
145
  <PhoneFrame>
127
146
  {GameRenderer && platform && gameState ? (
128
147
  <GameRenderer platform={platform} state={gameState} />
129
148
  ) : (
130
- <div className="p-4 text-zinc-500">Loading game...</div>
149
+ <div style={{ padding: 16, color: '#71717a' }}>Loading game...</div>
131
150
  )}
132
151
  </PhoneFrame>
133
152
  {room.phase === 'ended' && isHost && (
134
- <div className="absolute bottom-4 left-1/2 -translate-x-1/2 z-[9999]">
153
+ <div style={{ position: 'absolute', bottom: 16, left: '50%', transform: 'translateX(-50%)', zIndex: 9999 }}>
135
154
  <button
136
155
  onClick={() => socket?.emit('game:playAgain')}
137
- className="bg-amber-600 hover:bg-amber-500 text-white px-6 py-2 rounded-full font-semibold"
156
+ className="dk-btn-amber"
157
+ style={{ ...btnAmber, width: 'auto', padding: '8px 24px', borderRadius: 9999 }}
138
158
  >
139
159
  Play Again
140
160
  </button>
@@ -3,6 +3,13 @@ import PhoneFrame from '../components/PhoneFrame';
3
3
 
4
4
  const PLAYER_NAMES = ['Alice', 'Bob', 'Carol', 'Dave', 'Eve', 'Frank', 'Grace', 'Heidi'];
5
5
 
6
+ /* ── shared inline-style helpers ── */
7
+ const card: React.CSSProperties = { background: '#18181b', borderRadius: 8, padding: 12 };
8
+ const label: React.CSSProperties = { fontSize: 13, fontWeight: 700, color: '#a1a1aa', marginBottom: 8 };
9
+ const inputBase: React.CSSProperties = { width: '100%', background: '#27272a', border: '1px solid #3f3f46', borderRadius: 4, padding: '4px 8px', fontSize: 13, color: '#e5e5e5' };
10
+ const btnAmber: React.CSSProperties = { background: '#d97706', color: '#fff', border: 'none', padding: '4px 12px', borderRadius: 4, fontSize: 13, cursor: 'pointer' };
11
+ const btnZinc: React.CSSProperties = { background: '#3f3f46', color: '#fff', border: 'none', padding: '4px 12px', borderRadius: 4, fontSize: 13, cursor: 'pointer', width: '100%' };
12
+
6
13
  export default function Preview() {
7
14
  const [playerCount, setPlayerCount] = useState(3);
8
15
  const [playerIndex, setPlayerIndex] = useState(0);
@@ -183,14 +190,14 @@ export default function Preview() {
183
190
  }, []);
184
191
 
185
192
  return (
186
- <div className="flex gap-4 h-[calc(100vh-80px)]">
193
+ <div style={{ display: 'flex', gap: 16, height: 'calc(100vh - 80px)' }}>
187
194
  {/* Renderer — half the screen width */}
188
- <div className="h-full" style={{ width: '50%' }}>
195
+ <div style={{ width: '50%', height: '100%' }}>
189
196
  <PhoneFrame>
190
197
  {GameRenderer && platform && viewState ? (
191
198
  <GameRenderer platform={platform} state={viewState} />
192
199
  ) : (
193
- <div className="p-4 text-zinc-500">
200
+ <div style={{ padding: 16, color: '#71717a' }}>
194
201
  {!engine ? 'Loading engine...' : 'Initializing game...'}
195
202
  </div>
196
203
  )}
@@ -198,26 +205,27 @@ export default function Preview() {
198
205
  </div>
199
206
 
200
207
  {/* Control Panel — fills remaining width, resizable two-column */}
201
- <div ref={panelRef} className="flex-1 min-w-0 flex h-full">
208
+ <div ref={panelRef} style={{ flex: 1, minWidth: 0, display: 'flex', height: '100%' }}>
202
209
  {/* Left column: Players & Controls */}
203
- <div className="flex flex-col gap-4 overflow-auto pr-1" style={{ width: `${splitRatio * 100}%` }}>
210
+ <div style={{ width: `${splitRatio * 100}%`, display: 'flex', flexDirection: 'column', gap: 16, overflow: 'auto', paddingRight: 4 }}>
204
211
  {/* Player Count */}
205
- <div className="bg-zinc-900 rounded-lg p-3">
206
- <h3 className="text-sm font-bold text-zinc-400 mb-2">Player Count</h3>
212
+ <div style={card}>
213
+ <h3 style={label}>Player Count</h3>
207
214
  <input
208
215
  type="number"
209
216
  min={2}
210
217
  max={32}
211
218
  value={playerCount}
212
219
  onChange={(e) => setPlayerCount(Math.max(2, Math.min(32, Number(e.target.value))))}
213
- className="w-full bg-zinc-800 border border-zinc-700 rounded px-2 py-1 text-sm"
220
+ className="dk-input"
221
+ style={inputBase}
214
222
  />
215
223
  </div>
216
224
 
217
225
  {/* Player Switcher */}
218
- <div className="bg-zinc-900 rounded-lg p-3 flex-1 overflow-auto">
219
- <h3 className="text-sm font-bold text-zinc-400 mb-2">Current Player</h3>
220
- <div className="space-y-1">
226
+ <div style={{ ...card, flex: 1, overflow: 'auto' }}>
227
+ <h3 style={label}>Current Player</h3>
228
+ <div style={{ display: 'flex', flexDirection: 'column', gap: 4 }}>
221
229
  {mockPlayers.map((p, i) => {
222
230
  const isActive = i === playerIndex;
223
231
  const hue = (i * 137) % 360; // deterministic color per player
@@ -245,28 +253,49 @@ export default function Preview() {
245
253
  <button
246
254
  key={p.id}
247
255
  onClick={() => setPlayerIndex(i)}
248
- className={`w-full flex items-center gap-2 px-2 py-1.5 rounded text-sm text-left transition-colors ${
249
- isActive
250
- ? 'bg-amber-600/20 ring-1 ring-amber-500 text-white'
251
- : 'bg-zinc-800 hover:bg-zinc-700 text-zinc-300'
252
- }`}
256
+ className={isActive ? '' : 'dk-player-btn'}
257
+ style={{
258
+ width: '100%',
259
+ display: 'flex',
260
+ alignItems: 'center',
261
+ gap: 8,
262
+ padding: '6px 8px',
263
+ borderRadius: 4,
264
+ fontSize: 13,
265
+ textAlign: 'left' as const,
266
+ border: 'none',
267
+ cursor: 'pointer',
268
+ ...(isActive
269
+ ? { background: 'rgba(217, 119, 6, 0.2)', boxShadow: 'inset 0 0 0 1px #f59e0b', color: '#fff' }
270
+ : { background: '#27272a', color: '#d4d4d8' }),
271
+ }}
253
272
  >
254
273
  {/* Avatar */}
255
274
  <div
256
- className="w-6 h-6 rounded-full flex items-center justify-center text-xs font-bold shrink-0"
257
- style={{ background: `hsl(${hue}, 55%, 45%)` }}
275
+ style={{
276
+ width: 24,
277
+ height: 24,
278
+ borderRadius: '50%',
279
+ display: 'flex',
280
+ alignItems: 'center',
281
+ justifyContent: 'center',
282
+ fontSize: 11,
283
+ fontWeight: 700,
284
+ flexShrink: 0,
285
+ background: `hsl(${hue}, 55%, 45%)`,
286
+ }}
258
287
  >
259
288
  {p.nickname[0]}
260
289
  </div>
261
- <div className="min-w-0 flex-1">
262
- <div className="flex items-center gap-1">
263
- <span className="truncate">{p.nickname}</span>
290
+ <div style={{ minWidth: 0, flex: 1 }}>
291
+ <div style={{ display: 'flex', alignItems: 'center', gap: 4 }}>
292
+ <span style={{ overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{p.nickname}</span>
264
293
  {p.isHost && (
265
- <span className="text-[10px] text-amber-400 shrink-0">HOST</span>
294
+ <span style={{ fontSize: 10, color: '#fbbf24', flexShrink: 0 }}>HOST</span>
266
295
  )}
267
296
  </div>
268
297
  {roleLabel && (
269
- <div className="text-[10px] text-zinc-500 truncate">
298
+ <div style={{ fontSize: 10, color: '#71717a', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
270
299
  {roleLabel}
271
300
  </div>
272
301
  )}
@@ -279,14 +308,15 @@ export default function Preview() {
279
308
 
280
309
  {/* Game Result */}
281
310
  {gameOver && gameResult && (
282
- <div className="bg-zinc-900 rounded-lg p-3">
283
- <h3 className="text-sm font-bold text-green-400 mb-2">Game Over</h3>
284
- <pre className="text-xs font-mono bg-zinc-800 rounded p-2 overflow-auto max-h-32 whitespace-pre-wrap">
311
+ <div style={card}>
312
+ <h3 style={{ ...label, color: '#4ade80' }}>Game Over</h3>
313
+ <pre style={{ fontSize: 11, fontFamily: 'monospace', background: '#27272a', borderRadius: 4, padding: 8, overflow: 'auto', maxHeight: 128, whiteSpace: 'pre-wrap' }}>
285
314
  {JSON.stringify(gameResult, null, 2)}
286
315
  </pre>
287
316
  <button
288
317
  onClick={resetGame}
289
- className="mt-2 w-full bg-amber-600 hover:bg-amber-500 text-white px-3 py-1 rounded text-sm"
318
+ className="dk-btn-amber"
319
+ style={{ ...btnAmber, marginTop: 8, width: '100%' }}
290
320
  >
291
321
  Reset Game
292
322
  </button>
@@ -295,10 +325,11 @@ export default function Preview() {
295
325
 
296
326
  {/* Reset button (when game is not over) */}
297
327
  {!gameOver && engine && (
298
- <div className="bg-zinc-900 rounded-lg p-3">
328
+ <div style={card}>
299
329
  <button
300
330
  onClick={resetGame}
301
- className="w-full bg-zinc-700 hover:bg-zinc-600 text-white px-3 py-1 rounded text-sm"
331
+ className="dk-btn-zinc"
332
+ style={btnZinc}
302
333
  >
303
334
  Reset Game
304
335
  </button>
@@ -308,40 +339,43 @@ export default function Preview() {
308
339
 
309
340
  {/* Drag handle */}
310
341
  <div
311
- className="shrink-0 w-2 cursor-col-resize flex items-center justify-center group"
342
+ className="dk-resize-bar"
343
+ style={{ flexShrink: 0, width: 8, cursor: 'col-resize', display: 'flex', alignItems: 'center', justifyContent: 'center' }}
312
344
  onMouseDown={() => { dragging.current = true; document.body.style.cursor = 'col-resize'; document.body.style.userSelect = 'none'; }}
313
345
  >
314
- <div className="w-0.5 h-8 bg-zinc-700 rounded group-hover:bg-zinc-500 transition-colors" />
346
+ <div className="dk-resize-line" style={{ width: 2, height: 32, background: '#3f3f46', borderRadius: 2 }} />
315
347
  </div>
316
348
 
317
349
  {/* Right column: State & Logs */}
318
- <div className="flex flex-col gap-4 overflow-auto pl-1" style={{ width: `${(1 - splitRatio) * 100}%` }}>
350
+ <div style={{ width: `${(1 - splitRatio) * 100}%`, display: 'flex', flexDirection: 'column', gap: 16, overflow: 'auto', paddingLeft: 4 }}>
319
351
  {/* State Editor */}
320
- <div className="bg-zinc-900 rounded-lg p-3 flex-1 flex flex-col min-h-0">
321
- <h3 className="text-sm font-bold text-zinc-400 mb-2">Game State (Full)</h3>
352
+ <div style={{ ...card, flex: 1, display: 'flex', flexDirection: 'column', minHeight: 0 }}>
353
+ <h3 style={label}>Game State (Full)</h3>
322
354
  <textarea
323
355
  value={stateJson}
324
356
  onChange={(e) => setStateJson(e.target.value)}
325
- className="flex-1 bg-zinc-800 border border-zinc-700 rounded p-2 font-mono text-xs resize-none min-h-[120px]"
357
+ className="dk-input"
358
+ style={{ flex: 1, background: '#27272a', border: '1px solid #3f3f46', borderRadius: 4, padding: 8, fontFamily: 'monospace', fontSize: 11, resize: 'none', minHeight: 120, color: '#e5e5e5' }}
326
359
  />
327
360
  <button
328
361
  onClick={applyState}
329
- className="mt-2 bg-amber-600 hover:bg-amber-500 text-white px-3 py-1 rounded text-sm"
362
+ className="dk-btn-amber"
363
+ style={{ ...btnAmber, marginTop: 8 }}
330
364
  >
331
365
  Apply State
332
366
  </button>
333
367
  </div>
334
368
 
335
369
  {/* Action Log */}
336
- <div className="bg-zinc-900 rounded-lg p-3 h-48 overflow-auto">
337
- <h3 className="text-sm font-bold text-zinc-400 mb-2">Action Log</h3>
370
+ <div style={{ ...card, height: 192, overflow: 'auto' }}>
371
+ <h3 style={label}>Action Log</h3>
338
372
  {actions.length === 0 ? (
339
- <p className="text-zinc-500 text-xs">No actions yet</p>
373
+ <p style={{ color: '#71717a', fontSize: 11 }}>No actions yet</p>
340
374
  ) : (
341
- <div className="space-y-1">
375
+ <div style={{ display: 'flex', flexDirection: 'column', gap: 4 }}>
342
376
  {actions.map((a, i) => (
343
- <div key={i} className="text-xs font-mono bg-zinc-800 rounded p-1">
344
- <span className="text-amber-400">{a.player}</span>: {JSON.stringify(a.action)}
377
+ <div key={i} style={{ fontSize: 11, fontFamily: 'monospace', background: '#27272a', borderRadius: 4, padding: 4 }}>
378
+ <span style={{ color: '#fbbf24' }}>{a.player}</span>: {JSON.stringify(a.action)}
345
379
  </div>
346
380
  ))}
347
381
  </div>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@littlepartytime/dev-kit",
3
- "version": "1.11.0",
3
+ "version": "1.12.0",
4
4
  "description": "Development toolkit CLI for Little Party Time game developers",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",