-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathindex.html
More file actions
1612 lines (1484 loc) · 113 KB
/
Copy pathindex.html
File metadata and controls
1612 lines (1484 loc) · 113 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<!DOCTYPE html>
<html lang="zh-CN" class="dark">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Prompt Studio</title>
<script src="https://cdn.tailwindcss.com"></script>
<script>
tailwind.config = {
darkMode: 'class',
theme: {
extend: {
fontFamily: { sans: ['"SF Pro Display"', '"SF Pro"', '-apple-system', 'BlinkMacSystemFont', '"Segoe UI"', 'sans-serif'] },
animation: {
'fade-in': 'fadeIn 0.3s ease-out',
'slide-up': 'slideUp 0.4s cubic-bezier(0.4, 0, 0.2, 1)',
'shimmer': 'shimmer 2.5s ease-in-out infinite',
},
keyframes: {
fadeIn: { '0%': { opacity: '0', transform: 'translateY(6px)' }, '100%': { opacity: '1', transform: 'translateY(0)' } },
slideUp: { '0%': { opacity: '0', transform: 'translateY(16px)' }, '100%': { opacity: '1', transform: 'translateY(0)' } },
shimmer: { '0%': { backgroundPosition: '-200% 0' }, '100%': { backgroundPosition: '200% 0' } },
}
}
}
}
</script>
<style>
:root {
--blur-intensity: 20px;
--glass-bg: rgba(18, 18, 20, 0.38);
--glass-bg-hover: rgba(28, 28, 32, 0.48);
--glass-bg-active: rgba(40, 40, 48, 0.55);
--glass-border: rgba(255, 255, 255, 0.12);
--glass-border-hover: rgba(255, 255, 255, 0.18);
--accent: #6366f1;
--accent-glow: rgba(99, 102, 241, 0.3);
--shimmer-speed: 2.5s;
}
*, *::before, *::after { box-sizing: border-box; }
body {
font-family: '"SF Pro Display"', '"SF Pro"', -apple-system, BlinkMacSystemFont, '"Segoe UI"', sans-serif;
background: #06080d;
color: #e4e4e7;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
overflow: hidden;
height: 100vh;
}
/* ========== WebGL Shader Background Canvas (replaces old particle system) ========== */
#shaderCanvas {
position: fixed;
inset: 0;
z-index: 0;
pointer-events: none;
width: 100%;
height: 100%;
}
/* ========== Vignette Overlay (above shader, below UI) ========== */
#vignetteOverlay {
position: fixed;
inset: 0;
z-index: 1;
pointer-events: none;
background: radial-gradient(ellipse at center, transparent 40%, rgba(4, 6, 12, 0.55) 85%, rgba(2, 3, 6, 0.8) 100%);
}
/* ========== Glassmorphism ========== */
.glass {
background: var(--glass-bg);
backdrop-filter: blur(var(--blur-intensity));
-webkit-backdrop-filter: blur(var(--blur-intensity));
border: 1px solid var(--glass-border);
box-shadow: inset 0 0 0 1px rgba(255,255,255,0.06);
}
.glass-hover:hover {
background: var(--glass-bg-hover);
border-color: var(--glass-border-hover);
}
.glass-active {
background: var(--glass-bg-active);
border-color: rgba(255, 255, 255, 0.12);
}
/* ========== Shimmer Effect ========== */
.shimmer-enabled .shimmer-card {
position: relative;
overflow: hidden;
}
.shimmer-enabled .shimmer-card::after {
content: '';
position: absolute;
inset: 0;
background: linear-gradient(105deg, transparent 35%, rgba(255,255,255,0.025) 45%, rgba(255,255,255,0.06) 50%, rgba(255,255,255,0.025) 55%, transparent 65%);
background-size: 200% 100%;
animation: shimmer var(--shimmer-speed) ease-in-out infinite;
pointer-events: none;
z-index: 1;
}
.shimmer-enabled .shimmer-card:hover::after {
animation-duration: 1.2s;
}
/* ========== Scrollbar ========== */
::-webkit-scrollbar { width: 4px; height: 4px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: rgba(255,255,255,0.08); border-radius: 999px; }
::-webkit-scrollbar-thumb:hover { background: rgba(255,255,255,0.16); }
/* ========== Sidebar active indicator ========== */
.sidebar-item {
transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1);
border-left: 2px solid transparent;
}
.sidebar-item.active {
border-left-color: var(--accent);
background: rgba(99, 102, 241, 0.08);
}
.sidebar-item:hover:not(.active) {
background: rgba(255, 255, 255, 0.03);
}
/* ========== Card transitions ========== */
.tag-card {
transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1);
cursor: pointer;
user-select: none;
}
.tag-card:hover { transform: translateY(-2px); }
.tag-card:active { transform: scale(0.96); }
.char-card-music {
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
cursor: pointer;
user-select: none;
}
.char-card-music:hover { transform: translateY(-4px); }
.char-card-music:active { transform: scale(0.97); }
/* ========== Selected chip ========== */
.selected-chip-v10 {
animation: fadeIn 0.25s ease-out;
transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
}
.selected-chip-v10:hover { transform: translateY(-1px); }
/* ========== Copy pulse ========== */
@keyframes copyPulseV10 {
0%, 100% { box-shadow: 0 0 0 0 rgba(99, 102, 241, 0.5); }
50% { box-shadow: 0 0 0 16px rgba(99, 102, 241, 0); }
}
.copy-pulse-v10 { animation: copyPulseV10 0.7s ease-out; }
/* ========== Range slider styling ========== */
input[type="range"] {
-webkit-appearance: none;
appearance: none;
height: 6px;
background: rgba(255,255,255,0.1);
border-radius: 3px;
outline: none;
}
input[type="range"]::-webkit-slider-thumb {
-webkit-appearance: none;
width: 18px; height: 18px;
border-radius: 50%;
background: #6366f1;
cursor: pointer;
border: 2px solid rgba(255,255,255,0.2);
box-shadow: 0 0 12px rgba(99, 102, 241, 0.4);
}
/* ========== Settings Modal ========== */
.settings-modal {
transition: opacity 0.3s ease, visibility 0.3s ease;
}
/* ========== Section title ========== */
.section-title {
font-size: 1.35rem;
font-weight: 700;
letter-spacing: -0.02em;
color: #e4e4e7;
}
</style>
</head>
<body class="shimmer-enabled">
<!-- ==================== WebGL Shader Background (replaces old particle canvas) ==================== -->
<canvas id="shaderCanvas"></canvas>
<div id="vignetteOverlay"></div>
<!-- ==================== Settings Modal ==================== -->
<div id="settingsModal" class="settings-modal fixed inset-0 z-[100] flex items-center justify-center opacity-0 invisible">
<div class="absolute inset-0 bg-black/60 backdrop-blur-sm" id="settingsBackdrop"></div>
<div class="relative glass rounded-3xl max-w-md w-[92%] p-8 shadow-2xl animate-fade-in border-white/10">
<div class="flex items-center justify-between mb-7">
<h2 class="text-xl font-bold text-zinc-100" id="settingsTitle">Settings</h2>
<button id="settingsCloseBtn" class="w-8 h-8 rounded-full glass flex items-center justify-center text-zinc-400 hover:text-zinc-200 transition-colors">✕</button>
</div>
<div class="space-y-6">
<div>
<div class="flex items-center justify-between mb-3">
<label class="text-sm font-medium text-zinc-300" id="settingsBlurLabel">Glass Blur Intensity</label>
<span id="blurValue" class="text-xs text-zinc-500 bg-white/5 px-2 py-0.5 rounded-full">20px</span>
</div>
<input type="range" id="blurSlider" min="0" max="40" value="20" class="w-full">
</div>
<div>
<div class="flex items-center justify-between">
<label class="text-sm font-medium text-zinc-300" id="settingsShimmerLabel">Shimmer Effect</label>
<button id="shimmerToggle" class="relative w-11 h-6 rounded-full transition-colors duration-300 bg-indigo-500">
<span class="absolute top-0.5 left-0.5 w-5 h-5 rounded-full bg-white shadow transition-transform duration-300 translate-x-5"></span>
</button>
</div>
<p class="text-xs text-zinc-500 mt-1.5" id="settingsShimmerHint">Flowing light animation on cards</p>
</div>
</div>
</div>
</div>
<!-- ==================== NSFW Modal ==================== -->
<div id="nsfwModal" class="fixed inset-0 z-[90] flex items-center justify-center bg-black/60 backdrop-blur-sm opacity-0 invisible transition-all duration-300">
<div class="glass rounded-3xl shadow-2xl max-w-lg w-[90%] p-6 sm:p-8 mx-auto animate-fade-in">
<h2 id="nsfwModalTitle" class="text-xl font-bold text-zinc-100 mb-5 flex items-center gap-2.5">🔞 开启 NSFW 模式</h2>
<ul id="nsfwClauses" class="space-y-3.5 mb-7 text-sm text-zinc-400 leading-relaxed">
<li class="flex items-start gap-2.5"><span class="text-red-400 font-bold flex-shrink-0 mt-0.5">1.</span><span id="nsfwClause1">我已年满 18 周岁</span></li>
<li class="flex items-start gap-2.5"><span class="text-red-400 font-bold flex-shrink-0 mt-0.5">2.</span><span id="nsfwClause2">我理解并接受本工具可能生成成人向内容</span></li>
<li class="flex items-start gap-2.5"><span class="text-red-400 font-bold flex-shrink-0 mt-0.5">3.</span><span id="nsfwClause3">我承诺不会将未成年角色描述与 NSFW 提示词组合使用</span></li>
<li class="flex items-start gap-2.5"><span class="text-red-400 font-bold flex-shrink-0 mt-0.5">4.</span><span id="nsfwClause4">所有生成内容仅供个人合法娱乐用途</span></li>
<li class="flex items-start gap-2.5"><span class="text-red-400 font-bold flex-shrink-0 mt-0.5">5.</span><span id="nsfwClause5">我自愿承担使用 NSFW 模式的一切法律与道德责任</span></li>
</ul>
<div class="flex flex-col sm:flex-row gap-3">
<button id="nsfwModalCancel" class="flex-1 px-5 py-3 rounded-2xl text-sm font-semibold bg-white/10 hover:bg-white/15 text-zinc-300 transition-all duration-200">否,返回安全模式</button>
<button id="nsfwModalConfirm" class="flex-1 px-5 py-3 rounded-2xl text-sm font-semibold bg-red-500 hover:bg-red-600 active:bg-red-700 text-white shadow-md hover:shadow-lg transition-all duration-200">是的,我接受</button>
</div>
</div>
</div>
<!-- ==================== Main Layout ==================== -->
<div class="flex h-screen relative z-10">
<!-- ===== Left Sidebar ===== -->
<aside id="sidebar" class="w-[260px] flex-shrink-0 flex flex-col border-r border-white/5 bg-zinc-950/30 backdrop-blur-xl">
<!-- Logo -->
<div class="px-5 py-5 flex items-center gap-3 border-b border-white/5">
<div class="w-9 h-9 rounded-xl bg-gradient-to-br from-indigo-500 to-violet-500 flex items-center justify-center text-white text-lg font-bold">P</div>
<div>
<p class="text-sm font-bold text-zinc-100 leading-tight" id="sidebarTitle">Prompt Studio</p>
<p class="text-[11px] text-zinc-500 leading-tight">SD / Anima</p>
</div>
</div>
<!-- Category Nav -->
<nav id="sidebarNav" class="flex-1 overflow-y-auto py-3 px-2 space-y-0.5">
<!-- Rendered by JS -->
</nav>
<!-- Sidebar Footer -->
<div class="px-4 py-3 border-t border-white/5">
<div class="flex items-center gap-2">
<span id="sidebarTotalBadge" class="text-xs text-zinc-500 bg-white/5 px-2.5 py-1 rounded-full">0 组已选</span>
</div>
</div>
</aside>
<!-- ===== Main Content + Right Panel ===== -->
<div class="flex-1 flex overflow-hidden">
<!-- ===== Main Content Area ===== -->
<main id="mainContent" class="flex-1 overflow-y-auto overflow-x-hidden">
<!-- Top Nav Bar -->
<nav class="sticky top-0 z-40 px-6 py-3 flex items-center gap-4 bg-zinc-950/10 backdrop-blur-2xl border-b border-white/5">
<!-- Search Bar (centered, flex-1) -->
<div class="flex-1 max-w-xl mx-auto relative">
<input id="searchInput" type="text"
class="w-full pl-10 pr-10 py-2.5 glass rounded-xl text-sm text-zinc-200 placeholder-zinc-500 focus:outline-none focus:ring-2 focus:ring-indigo-500/40 focus:border-indigo-500/40 transition-all"
placeholder="搜索提示词或人物…">
<span class="absolute left-3.5 top-1/2 -translate-y-1/2 text-zinc-500 text-sm">🔍</span>
<button id="searchClearBtn" class="absolute right-3 top-1/2 -translate-y-1/2 w-5 h-5 rounded-full bg-white/10 text-zinc-400 text-xs flex items-center justify-center hover:bg-white/20 transition-all hidden">✕</button>
</div>
<!-- Controls -->
<div class="flex items-center gap-2 flex-shrink-0">
<!-- SD/Anima Toggle -->
<div id="modeToggle" class="flex items-center glass rounded-xl p-0.5 cursor-pointer select-none border-white/5">
<button class="mode-option px-3 py-1.5 rounded-lg text-xs font-semibold transition-all duration-300 bg-indigo-500 text-white" data-mode="sd">🎨 SD</button>
<button class="mode-option px-3 py-1.5 rounded-lg text-xs font-semibold transition-all duration-300 text-zinc-400" data-mode="anima">🌟 Anima</button>
</div>
<!-- NSFW -->
<button id="nsfwBtn" class="px-3 py-2 rounded-xl text-xs font-semibold transition-all duration-200 glass text-zinc-400 hover:text-zinc-200 border-white/5">
🔞 <span id="label_nsfw">NSFW</span>
</button>
<!-- Language -->
<div class="flex items-center glass rounded-xl p-0.5 border-white/5">
<button class="lang-btn px-2.5 py-1.5 rounded-lg text-xs font-semibold transition-all duration-200 bg-indigo-500 text-white" data-lang="zh-CN">简</button>
<button class="lang-btn px-2.5 py-1.5 rounded-lg text-xs font-semibold transition-all duration-200 text-zinc-400" data-lang="zh-TW">繁</button>
<button class="lang-btn px-2.5 py-1.5 rounded-lg text-xs font-semibold transition-all duration-200 text-zinc-400" data-lang="en">EN</button>
</div>
<!-- Settings Gear -->
<button id="settingsBtn" class="w-8 h-8 rounded-xl glass flex items-center justify-center text-zinc-400 hover:text-zinc-200 transition-colors border-white/5">
⚙️
</button>
<!-- GitHub Repository Button -->
<a href="https://github.com/Hajimides/SD-Anima-Prompt-Studio"
target="_blank"
class="w-8 h-8 rounded-xl glass flex items-center justify-center text-zinc-400 hover:text-zinc-200 transition-colors border-white/5"
title="GitHub 仓库 - 查看源码、提交 Issue 与更新日志">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 24 24">
<path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z"/>
</svg>
</a>
</div>
</nav>
<!-- Category Content Sections -->
<div id="contentSections" class="px-6 py-5 space-y-8 pb-20">
<!-- Rendered by JS -->
</div>
</main>
<!-- ===== Right Panel ===== -->
<aside id="rightPanel" class="w-[340px] flex-shrink-0 border-l border-white/5 bg-zinc-950/30 backdrop-blur-xl flex flex-col overflow-hidden">
<!-- Selected Groups Header -->
<div class="px-5 py-4 border-b border-white/5">
<div class="flex items-center justify-between mb-0.5">
<h3 class="text-sm font-bold text-zinc-300" id="label_selectedGroups">已选择提示词组</h3>
<span id="groupCountBadge" class="text-[11px] text-zinc-500 bg-white/5 px-2 py-0.5 rounded-full">0 组</span>
</div>
</div>
<!-- Selected Chips -->
<div id="selectedGroupsScroll" class="flex-1 overflow-y-auto p-4">
<div id="selectedGroupsContainer" class="flex flex-wrap gap-2 min-h-[60px] items-start content-start">
<span id="emptyHintRight" class="text-zinc-500 text-xs w-full text-center py-6">👈 从左侧选择提示词组</span>
</div>
</div>
<!-- Prompt Output + Actions -->
<div class="border-t border-white/5 p-4 space-y-3">
<div>
<div class="flex items-center justify-between mb-2">
<div class="flex items-center gap-2">
<h3 class="text-sm font-bold text-zinc-300" id="label_prompt">组合后的 Prompt</h3>
<button id="regenPromptBtn" class="hidden px-2 py-0.5 text-[10px] rounded-full bg-white/5 hover:bg-white/10 text-zinc-400 hover:text-zinc-200 transition-all" title="从当前已选组重新生成提示词(覆盖手动编辑)">↺ 刷新</button>
</div>
<span id="charCount" class="text-[11px] text-zinc-500 bg-white/5 px-2 py-0.5 rounded-full">0 字符</span>
</div>
<textarea id="promptOutput"
class="w-full h-28 p-3.5 glass rounded-2xl text-zinc-200 text-sm leading-relaxed resize-none focus:outline-none focus:ring-2 focus:ring-indigo-500/30 transition-all placeholder:text-zinc-600"
placeholder="可直接编辑提示词,修改后选择变化不再自动覆盖…"></textarea>
</div>
<div class="flex gap-2.5">
<button id="copyBtn" class="flex-1 flex items-center justify-center gap-2 px-4 py-3 bg-indigo-500 hover:bg-indigo-400 active:bg-indigo-600 text-white font-semibold rounded-2xl shadow-lg shadow-indigo-500/25 hover:shadow-indigo-500/40 transition-all duration-200 text-sm">
📋 <span id="label_copy">复制 Prompt</span>
</button>
<button id="shuffleBtn" class="flex items-center justify-center gap-2 px-4 py-3 glass text-zinc-300 font-semibold rounded-2xl hover:bg-white/10 active:bg-white/15 transition-all duration-200 text-sm">
🔄 <span id="label_shuffle">随机排序</span>
</button>
</div>
<button id="clearAllBtn" class="w-full py-2 text-xs text-red-400/70 hover:text-red-400 glass rounded-xl transition-all duration-200 hidden">
🗑 <span id="label_clearAll">清空所有</span>
</button>
</div>
</aside>
</div>
</div>
<!-- ==================== JavaScript ==================== -->
<script>
(function() {
'use strict';
// ================================================================
// CHANGE 1: WebGL Shader Background (replaces old 2D particle system)
// - Full-screen WebGL canvas with noise-based rotation + sine wave
// - warping + layered color mixing (yellow/blue + red/blue).
// - Properly resizes with window, runs in rAF loop, pointer-events disabled.
// ================================================================
var shaderCanvas = document.getElementById('shaderCanvas');
var gl = shaderCanvas.getContext('webgl') || shaderCanvas.getContext('experimental-webgl');
if (gl) {
var vertexShaderSource = [
'attribute vec2 a_position;',
'void main() {',
' gl_Position = vec4(a_position, 0.0, 1.0);',
'}'
].join('\n');
var fragmentShaderSource = [
'precision mediump float;',
'#define S(a,b,t) smoothstep(a,b,t)',
'mat2 Rot(float a) {',
' float s = sin(a);',
' float c = cos(a);',
' return mat2(c, -s, s, c);',
'}',
'vec2 hash(vec2 p) {',
' p = vec2(dot(p,vec2(2127.1,81.17)), dot(p,vec2(1269.5,283.37)));',
' return fract(sin(p)*43758.5453);',
'}',
'float noise(in vec2 p) {',
' vec2 i = floor(p);',
' vec2 f = fract(p);',
' vec2 u = f*f*(3.0-2.0*f);',
' float n = mix(mix(dot(-1.0+2.0*hash(i+vec2(0.0,0.0)), f-vec2(0.0,0.0)),',
' dot(-1.0+2.0*hash(i+vec2(1.0,0.0)), f-vec2(1.0,0.0)), u.x),',
' mix(dot(-1.0+2.0*hash(i+vec2(0.0,1.0)), f-vec2(0.0,1.0)),',
' dot(-1.0+2.0*hash(i+vec2(1.0,1.0)), f-vec2(1.0,1.0)), u.x), u.y);',
' return 0.5 + 0.5*n;',
'}',
'uniform vec2 u_resolution;',
'uniform float u_time;',
'void mainImage(out vec4 fragColor, in vec2 fragCoord) {',
' vec2 uv = fragCoord/u_resolution.xy;',
' float ratio = u_resolution.x / u_resolution.y;',
' vec2 tuv = uv;',
' tuv -= .5;',
' float degree = noise(vec2(u_time*.1, tuv.x*tuv.y));',
' tuv.y *= 1./ratio;',
' tuv *= Rot(radians((degree-.5)*720.+180.));',
' tuv.y *= ratio;',
' float frequency = 5.;',
' float amplitude = 30.;',
' float speed = u_time * 2.;',
' tuv.x += sin(tuv.y*frequency+speed)/amplitude;',
' tuv.y += sin(tuv.x*frequency*1.5+speed)/(amplitude*.5);',
' vec3 colorYellow = vec3(0.18, 0.10, 0.22);',
' vec3 colorDeepBlue = vec3(0.06, 0.09, 0.22);',
' vec3 layer1 = mix(colorYellow, colorDeepBlue, S(-.3, .2, (tuv*Rot(radians(-5.))).x));',
' vec3 colorRed = vec3(0.18, 0.10, 0.22);',
' vec3 colorBlue = vec3(0.12, 0.25, 0.38);',
' vec3 layer2 = mix(colorRed, colorBlue, S(-.3, .2, (tuv*Rot(radians(-5.))).x));',
' vec3 finalComp = mix(layer1, layer2, S(.5, -.3, tuv.y));',
' fragColor = vec4(finalComp, 1.0);',
'}',
'void main() {',
' vec2 fragCoord = gl_FragCoord.xy;',
' vec4 color;',
' mainImage(color, fragCoord);',
' gl_FragColor = color;',
'}'
].join('\n');
function createShader(gl, type, source) {
var shader = gl.createShader(type);
gl.shaderSource(shader, source);
gl.compileShader(shader);
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
console.warn('Shader compile error:', gl.getShaderInfoLog(shader));
gl.deleteShader(shader);
return null;
}
return shader;
}
function createProgram(gl, vs, fs) {
var program = gl.createProgram();
gl.attachShader(program, vs);
gl.attachShader(program, fs);
gl.linkProgram(program);
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
console.warn('Program link error:', gl.getProgramInfoLog(program));
gl.deleteProgram(program);
return null;
}
return program;
}
var vertexShader = createShader(gl, gl.VERTEX_SHADER, vertexShaderSource);
var fragmentShader = createShader(gl, gl.FRAGMENT_SHADER, fragmentShaderSource);
var program = createProgram(gl, vertexShader, fragmentShader);
if (program) {
gl.useProgram(program);
var positionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([-1,-1, 1,-1, -1,1, 1,1]), gl.STATIC_DRAW);
var positionLocation = gl.getAttribLocation(program, 'a_position');
gl.enableVertexAttribArray(positionLocation);
gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0);
var resolutionLocation = gl.getUniformLocation(program, 'u_resolution');
var timeLocation = gl.getUniformLocation(program, 'u_time');
function resizeShader() {
shaderCanvas.width = window.innerWidth;
shaderCanvas.height = window.innerHeight;
gl.viewport(0, 0, shaderCanvas.width, shaderCanvas.height);
if (resolutionLocation) {
gl.uniform2f(resolutionLocation, shaderCanvas.width, shaderCanvas.height);
}
}
window.addEventListener('resize', resizeShader);
resizeShader();
var shaderStartTime = performance.now();
function renderShader(now) {
var currentTime = (now - shaderStartTime) / 1000.0;
if (timeLocation) {
gl.uniform1f(timeLocation, currentTime);
}
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
requestAnimationFrame(renderShader);
}
requestAnimationFrame(renderShader);
}
}
// If WebGL fails, body background #06080d shows through — still looks fine with vignette.
// ==================== Constants ====================
var SAFE_ORDER = ['quality', 'style', 'character', 'clothing', 'actionTag', 'actionNatural', 'perspective', 'composition', 'background'];
var NSFW_ORDER = ['nsfwClothing', 'nsfwActionTag', 'nsfwActionNatural'];
var ALL_ORDER = ['quality', 'style', 'character', 'clothing', 'actionTag', 'actionNatural', 'nsfwClothing', 'nsfwActionTag', 'nsfwActionNatural', 'perspective', 'composition', 'background'];
// ==================== i18n ====================
const i18n = {
'zh-CN': {
pageTitle:'🎨 Prompt Studio', sidebarTitle:'Prompt Studio', sidebarSubtitle:'SD / Anima',
cat_quality:'质量', cat_style:'风格', cat_character:'人物', cat_clothing:'服装', cat_actionTag:'动作(Tag)', cat_actionNatural:'动作(自然语言)', cat_perspective:'角度', cat_composition:'构图', cat_background:'背景',
cat_nsfwClothing:'服装(NSFW)', cat_nsfwActionTag:'动作(NSFW)', cat_nsfwActionNatural:'动作(自然语言)(NSFW)',
label_selectedGroups:'已选择提示词组', label_prompt:'组合后的 Prompt', label_clearAll:'清空所有', label_copy:'复制 Prompt', label_shuffle:'随机排序',
label_nsfw:'NSFW', label_nsfwOn:'NSFW 已开启',
badge_groups:'组', badge_words:'词', badge_chars:'字符',
hint_emptyRight:'👈 从左侧选择提示词组', hint_emptyPrompt:'可直接编辑提示词,修改后选择变化不再自动覆盖…',
hint_footer:'', hint_imageReplace:'💡 替换图片链接即可自定义人物卡片封面',
search_placeholder:'搜索提示词或人物…', search_noResults:'没有找到匹配的结果',
mode_sd:'SD', mode_anima:'Anima', animaPrefix:'score_9, score_8_up, score_7_up, anime style, ',
nsfw_modal_title:'开启 NSFW 模式',
nsfw_clause1:'我已年满 18 周岁(或所在地区法定成年年龄)',
nsfw_clause2:'我理解并接受本工具可能生成成人向(NSFW)、性暗示、裸露等敏感提示词',
nsfw_clause3:'我承诺绝不会将任何暗示未成年(loli、shota、child、teen 等)的角色描述与 NSFW 提示词组合使用',
nsfw_clause4:'所有生成内容仅供个人合法娱乐用途,不得传播、商用或用于任何违法、有害目的',
nsfw_clause5:'我自愿承担使用 NSFW 模式所产生的一切法律与道德责任,与本工具无关',
nsfw_modal_cancel:'否,返回安全模式', nsfw_modal_confirm:'是的,我接受',
settings_title:'Settings', settings_blur:'Glass Blur Intensity', settings_shimmer:'Shimmer Effect', settings_shimmerHint:'Flowing light animation on cards',
groups:{
q1:'杰作',q2:'电影级光照',q3:'超清细节',q4:'专业摄影',q5:'梦幻氛围',
c1:'美丽少女',c2:'长发美人',c3:'优雅女性',c4:'可爱男孩',c5:'精细面部',
cl1:'优雅礼服',cl2:'汉服传统',cl3:'哥特风格',cl4:'日式和服',cl5:'赛博朋克',
at1:'优雅站姿',at2:'坐姿优雅',at3:'动态姿势',at4:'温柔微笑',at5:'行走姿态',
an1:'自然站立',an2:'优雅端坐',an3:'回眸凝望',an4:'沉思静立',an5:'轻盈跃动',
p1:'低角度',p2:'高角度',p3:'平视角度',p4:'仰视特写',p5:'俯视全景',
co1:'居中构图',co2:'三分法则',co3:'引导线',co4:'框架构图',co5:'对角线',
bg1:'城市夜景',bg2:'奇幻森林',bg3:'山脉景观',bg4:'赛博朋克街头',bg5:'水下世界',bg6:'太空星云',bg7:'传统中式庭院',bg8:'雪山日出',
ncl1:'a',ncl2:'b',ncl3:'c',ncl4:'d',ncl5:'e',
nat1:'a',nat2:'b',nat3:'c',nat4:'d',nat5:'e',
nan1:'a',nan2:'b',nan3:'c',nan4:'d',nan5:'e'
}
},
'zh-TW': {
pageTitle:'🎨 Prompt Studio', sidebarTitle:'Prompt Studio', sidebarSubtitle:'SD / Anima',
cat_quality:'品質', cat_style:'風格', cat_character:'人物', cat_clothing:'服裝', cat_actionTag:'動作(Tag)', cat_actionNatural:'動作(自然語言)', cat_perspective:'角度', cat_composition:'構圖', cat_background:'背景',
cat_nsfwClothing:'服裝(NSFW)', cat_nsfwActionTag:'動作(NSFW)', cat_nsfwActionNatural:'動作(自然語言)(NSFW)',
label_selectedGroups:'已選擇提示詞組', label_prompt:'組合後的 Prompt', label_clearAll:'清空所有', label_copy:'複製 Prompt', label_shuffle:'隨機排序',
label_nsfw:'NSFW', label_nsfwOn:'NSFW 已開啟',
badge_groups:'組', badge_words:'詞', badge_chars:'字元',
hint_emptyRight:'👈 從左側選擇提示詞組', hint_emptyPrompt:'可直接編輯提示詞,修改後選擇變化不再自動覆蓋…',
hint_footer:'', hint_imageReplace:'💡 替換圖片連結即可自訂人物卡片封面',
search_placeholder:'搜尋提示詞或人物…', search_noResults:'沒有找到匹配的結果',
mode_sd:'SD', mode_anima:'Anima', animaPrefix:'score_9, score_8_up, score_7_up, anime style, ',
nsfw_modal_title:'開啟 NSFW 模式',
nsfw_clause1:'我已年滿 18 周歲(或所在地區法定成年年齡)',
nsfw_clause2:'我理解並接受本工具可能生成成人向(NSFW)、性暗示、裸露等敏感提示詞',
nsfw_clause3:'我承諾絕不會將任何暗示未成年(loli、shota、child、teen 等)的角色描述與 NSFW 提示詞組合使用',
nsfw_clause4:'所有生成內容僅供個人合法娛樂用途,不得傳播、商用或用於任何違法、有害目的',
nsfw_clause5:'我自願承擔使用 NSFW 模式所產生的一切法律與道德責任,與本工具無關',
nsfw_modal_cancel:'否,返回安全模式', nsfw_modal_confirm:'是的,我接受',
settings_title:'Settings', settings_blur:'Glass Blur Intensity', settings_shimmer:'Shimmer Effect', settings_shimmerHint:'Flowing light animation on cards',
groups:{
q1:'傑作',q2:'電影級光照',q3:'超清細節',q4:'專業攝影',q5:'夢幻氛圍',
c1:'美麗少女',c2:'長髮美人',c3:'優雅女性',c4:'可愛男孩',c5:'精細面部',
cl1:'優雅禮服',cl2:'漢服傳統',cl3:'哥特風格',cl4:'日式和服',cl5:'賽博龐克',
at1:'優雅站姿',at2:'坐姿優雅',at3:'動態姿勢',at4:'溫柔微笑',at5:'行走姿態',
an1:'自然站立',an2:'優雅端坐',an3:'回眸凝望',an4:'沉思靜立',an5:'輕盈躍動',
p1:'低角度',p2:'高角度',p3:'平視角度',p4:'仰視特寫',p5:'俯視全景',
co1:'居中構圖',co2:'三分法則',co3:'引導線',co4:'框架構圖',co5:'對角線',
bg1:'城市夜景',bg2:'奇幻森林',bg3:'山脈景觀',bg4:'賽博朋克街頭',bg5:'水下世界',bg6:'太空星雲',bg7:'傳統中式庭院',bg8:'雪山日出',
ncl1:'a',ncl2:'b',ncl3:'c',ncl4:'d',ncl5:'e',
nat1:'a',nat2:'b',nat3:'c',nat4:'d',nat5:'e',
nan1:'a',nan2:'b',nan3:'c',nan4:'d',nan5:'e'
}
},
'en': {
pageTitle:'🎨 Prompt Studio', sidebarTitle:'Prompt Studio', sidebarSubtitle:'SD / Anima',
cat_quality:'Quality', cat_character:'Character', cat_clothing:'Clothing', cat_actionTag:'Action (Tag)', cat_actionNatural:'Action (Natural)', cat_perspective:'Perspective', cat_composition:'Composition', cat_background:'Background',
cat_nsfwClothing:'Clothing (NSFW)', cat_nsfwActionTag:'Action (NSFW)', cat_nsfwActionNatural:'Action (Natural) (NSFW)',
label_selectedGroups:'Selected Groups', label_prompt:'Combined Prompt', label_clearAll:'Clear All', label_copy:'Copy Prompt', label_shuffle:'Shuffle',
label_nsfw:'NSFW', label_nsfwOn:'NSFW On',
badge_groups:'groups', badge_words:'words', badge_chars:'chars',
hint_emptyRight:'👈 Select prompt groups from the left', hint_emptyPrompt:'Editable: manual changes are preserved until you click ↺ Refresh or Shuffle',
hint_footer:'', hint_imageReplace:'💡 Replace image URLs to customize character card covers',
search_placeholder:'Search prompts or characters…', search_noResults:'No matching results found',
mode_sd:'SD', mode_anima:'Anima', animaPrefix:'score_9, score_8_up, score_7_up, anime style, ',
nsfw_modal_title:'Enable NSFW Mode',
nsfw_clause1:'I am at least 18 years of age (or the legal age of majority in my jurisdiction).',
nsfw_clause2:'I understand and accept that this tool may generate adult-oriented (NSFW), sexually suggestive, or explicit prompt terms.',
nsfw_clause3:'I pledge never to combine any character descriptions implying underage individuals (loli, shota, child, teen, etc.) with NSFW prompt terms.',
nsfw_clause4:'All generated content is for personal, lawful entertainment only and will not be distributed, commercialized, or used for any illegal or harmful purpose.',
nsfw_clause5:'I voluntarily assume all legal and moral responsibility arising from the use of NSFW mode, and hold this tool harmless.',
nsfw_modal_cancel:'No, Stay in Safe Mode', nsfw_modal_confirm:'Yes, I Accept',
settings_title:'Settings', settings_blur:'Glass Blur Intensity', settings_shimmer:'Shimmer Effect', settings_shimmerHint:'Flowing light animation on cards',
groups:{
q1:'Masterpiece',q2:'Cinematic Light',q3:'Ultra HD Detail',q4:'Pro Photography',q5:'Dreamy Atmosphere',
c1:'Beautiful Girl',c2:'Long Hair Beauty',c3:'Elegant Woman',c4:'Cute Boy',c5:'Detailed Face',
cl1:'Elegant Dress',cl2:'Traditional Hanfu',cl3:'Gothic Style',cl4:'Japanese Kimono',cl5:'Cyberpunk',
at1:'Standing Gracefully',at2:'Sitting Elegantly',at3:'Dynamic Pose',at4:'Gentle Smile',at5:'Walking',
an1:'Standing Naturally',an2:'Seated Elegantly',an3:'Glancing Back',an4:'Pensive Standing',an5:'Light Leap',
p1:'Low Angle',p2:'High Angle',p3:'Eye Level',p4:"Worm's Eye",p5:'Aerial View',
co1:'Centered',co2:'Rule of Thirds',co3:'Leading Lines',co4:'Framed',co5:'Diagonal',
bg1:'Cyberpunk Night City',bg2:'Enchanted Forest',bg3:'Majestic Mountains',bg4:'Neon Cyberpunk Street',bg5:'Underwater Realm',bg6:'Cosmic Nebula',bg7:'Traditional Chinese Garden',bg8:'Snowy Mountain Sunrise',
ncl1:'a',ncl2:'b',ncl3:'c',ncl4:'d',ncl5:'e',
nat1:'a',nat2:'b',nat3:'c',nat4:'d',nat5:'e',
nan1:'a',nan2:'b',nan3:'c',nan4:'d',nan5:'e'
}
}
};
function t(key) {
var keys = key.split('.'), val = i18n[state.lang];
for (var i = 0; i < keys.length; i++) { if (val == null) return key; val = val[keys[i]]; }
return val != null ? String(val) : key;
}
function getGroupName(group) {
if (typeof group.name === 'object') return group.name[state.lang] || group.name['zh-CN'] || Object.values(group.name)[0];
return group.name;
}
// ==================== Prompt Library ====================
var promptLibrary = {
quality:[
{id:1,name:{'zh-CN':'杰作','zh-TW':'傑作','en':'Masterpiece'},texts:['masterpiece','best quality','highly detailed','ultra detailed']},
{id:2,name:{'zh-CN':'电影级光照','zh-TW':'電影級光照','en':'Cinematic Light'},texts:['cinematic lighting','volumetric lighting','dramatic lighting']},
{id:3,name:{'zh-CN':'超清细节','zh-TW':'超清細節','en':'Ultra HD Detail'},texts:['8k resolution','sharp focus','intricate details','ray tracing']},
{id:4,name:{'zh-CN':'专业摄影','zh-TW':'專業攝影','en':'Pro Photography'},texts:['professional photography','studio lighting','depth of field','bokeh']},
{id:5,name:{'zh-CN':'梦幻氛围','zh-TW':'夢幻氛圍','en':'Dreamy Atmosphere'},texts:['soft lighting','ethereal','magical atmosphere']},
{id:6,name:{'zh-CN':'极致光影','zh-TW':'極致光影','en':'Ultimate Lighting'},texts:['dramatic rim lighting','god rays','volumetric god rays','cinematic god rays','subsurface scattering']},
{id:7,name:{'zh-CN':'极致细节','zh-TW':'極致細節','en':'Ultimate Detail'},texts:['extremely detailed','intricate details','finely crafted details','masterful micro-details','hyper-detailed']},
{id:8,name:{'zh-CN':'锐利焦点','zh-TW':'銳利焦點','en':'Sharp Focus'},texts:['sharp focus','crisp and clear','pin sharp','high definition focus','razor sharp details']},
{id:9,name:{'zh-CN':'丰富色彩层次','zh-TW':'豐富色彩層次','en':'Rich Color Grading'},texts:['vibrant color grading','rich saturated colors','beautiful color harmony','cinematic color palette','vivid yet natural tones']},
{id:10,name:{'zh-CN':'光线追踪效果','zh-TW':'光線追蹤效果','en':'Ray Tracing'},texts:['ray tracing','global illumination','accurate reflections','realistic light bounce','physically based rendering']},
{id:11,name:{'zh-CN':'次表面散射','zh-TW':'次表面散射','en':'Subsurface Scattering'},texts:['subsurface scattering','skin translucency','soft light penetration','realistic skin rendering','glowing skin effect']},
{id:12,name:{'zh-CN':'高动态范围','zh-TW':'高動態範圍','en':'High Dynamic Range'},texts:['high dynamic range','hdr lighting','detailed highlights and shadows','wide tonal range','dramatic contrast']},
{id:13,name:{'zh-CN':'艺术级渲染','zh-TW':'藝術級渲染','en':'Artistic Render'},texts:['artistic rendering','studio quality render','professional illustration','award-winning art style','flawless execution']},
{id:14,name:{'zh-CN':'顶级画质','zh-TW':'頂級畫質','en':'Top-tier Quality'},texts:['best quality','masterpiece quality','flawless rendering','premium illustration quality','competition level quality']},
{id:15,name:{'zh-CN':'动态光影','zh-TW':'動態光影','en':'Dynamic Lighting'},texts:['dynamic lighting','volumetric god rays','dramatic rim lighting','cinematic light shafts','atmospheric lighting']}
],
style:[
{id:1,name:{'zh-CN':'动漫风格','zh-TW':'動漫風格','en':'Anime Style'},texts:['anime style','cel shading','vibrant colors','expressive eyes']},
{id:2,name:{'zh-CN':'赛博朋克','zh-TW':'賽博朋克','en':'Cyberpunk'},texts:['cyberpunk style','neon lights','futuristic cityscape','techwear fashion']},
{id:3,name:{'zh-CN':'复古像素艺术','zh-TW':'復古像素藝術','en':'Retro Pixel Art'},texts:['pixel art style','8-bit graphics','limited color palette','blocky pixels']},
{id:4,name:{'zh-CN':'水彩画风格','zh-TW':'水彩畫風格','en':'Watercolor Style'},texts:['watercolor painting style','soft brush strokes','blended colors','paper texture']},
{id:5,name:{'zh-CN':'超现实主义','zh-TW':'超現實主義','en':'Surrealism'},texts:['surrealistic style','dreamlike imagery','unexpected juxtapositions']},
{id:6,name:{'zh-CN':'写实风格','zh-TW':'寫實風格','en':'Realistic Style'},texts:['realistic style','photorealistic','highly detailed skin texture','lifelike rendering','cinematic realism']},
{id:7,name:{'zh-CN':'吉卜力风格','zh-TW':'吉卜力風格','en':'Studio Ghibli Style'},texts:['studio ghibli style','soft watercolor aesthetic','whimsical atmosphere','detailed background art','hayao miyazaki inspired']},
{id:8,name:{'zh-CN':'新海诚风格','zh-TW':'新海誠風格','en':'Makoto Shinkai Style'},texts:['makoto shinkai style','beautiful sky and clouds','detailed light rays','emotional atmosphere','stunning background scenery']},
{id:9,name:{'zh-CN':'半写实风格','zh-TW':'半寫實風格','en':'Semi-Realistic'},texts:['semi-realistic style','detailed yet stylized','soft shading','beautiful proportions','anime-realism hybrid']},
{id:10,name:{'zh-CN':'卡通风格','zh-TW':'卡通風格','en':'Cartoon Style'},texts:['cartoon style','bold outlines','flat colors','exaggerated features','clean animation look']}
],
character:[
{id:1,name:{'zh-CN':'小鸟游星野','zh-TW':'小鳥遊星野','en':'Takanashi Hoshino'},texts:['Takanashi Hoshino','long pink hair','ahoge','prominent cowlick','heterochromia','blue left eye','orange right eye','small cute fang','purple halo'],imageUrl:'https://raw.githubusercontent.com/Hajimides/SD-Anima-Prompt-Studio/main/images/Takanashi_Hoshino.jpg'},
{id:2,name:{'zh-CN':'空崎日奈','zh-TW':'空崎日奈','en':'Sorasaki Hina'},texts:['Sorasaki Hina','white hair','long wavy hair','knee-length hair','thigh-length hair','black and red ribbon','black ribbon','purple eyes','black horns with purple cracks','glowing purple horns','small bat wings on hips','small bat wings','petite body','short stature','flat chest','purple halo','demon halo'],imageUrl:'https://raw.githubusercontent.com/Hajimides/SD-Anima-Prompt-Studio/main/images/Sorasaki_Hina.jpg'},
{id:3,name:{'zh-CN':'圣园未花','zh-TW':'聖園未花','en':'Misono Mika'},texts:['Misono Mika','long pink hair with pale blue gradient at the ends','golden eyes','beautiful detailed face','pink protostar halo with revolving spirals and sparkles','white angelic wings sprouting from waist level with golden celestial ornaments on the right wing'],imageUrl:'https://raw.githubusercontent.com/Hajimides/SD-Anima-Prompt-Studio/main/images/Misono_Mika.jpg'},
{id:4,name:{'zh-CN':'可爱男孩','zh-TW':'可愛男孩','en':'Cute Boy'},texts:['1boy','cute boy','short hair','golden eyes'],imageUrl:'https://raw.githubusercontent.com/yourusername/sd-prompt-selector/main/images/char4.jpg'},
{id:5,name:{'zh-CN':'精细面部','zh-TW':'精細面部','en':'Detailed Face'},texts:['detailed beautiful face','heterochromia','youthful appearance'],imageUrl:'https://raw.githubusercontent.com/yourusername/sd-prompt-selector/main/images/char5.jpg'},
{id:6,name:{'zh-CN':'优雅女性','zh-TW':'優雅女性','en':'Elegant Woman'},texts:['young woman','fair skin','delicate features','blue eyes'],imageUrl:'https://raw.githubusercontent.com/yourusername/sd-prompt-selector/main/images/char3.jpg'},
{id:7,name:{'zh-CN':'可爱男孩','zh-TW':'可愛男孩','en':'Cute Boy'},texts:['1boy','cute boy','short hair','golden eyes'],imageUrl:'https://raw.githubusercontent.com/yourusername/sd-prompt-selector/main/images/char4.jpg'},
{id:8,name:{'zh-CN':'精细面部','zh-TW':'精細面部','en':'Detailed Face'},texts:['detailed beautiful face','heterochromia','youthful appearance'],imageUrl:'https://raw.githubusercontent.com/yourusername/sd-prompt-selector/main/images/char5.jpg'},
],
clothing:[
{id:1,name:{'zh-CN':'优雅晚礼服','zh-TW':'優雅晚禮服','en':'Elegant Evening Dress'},texts:['emerald green silk evening gown','deep V-neckline','intricate bead embroidery','flowing tulle train','elegant silhouette']},
{id:2,name:{'zh-CN':'都市休闲街头风','zh-TW':'都市休閒街頭風','en':'Urban Streetwear'},texts:['oversized white graphic hoodie','high-waisted ripped blue denim jeans','chunky white sneakers']},
{id:3,name:{'zh-CN':'传统中式旗袍','zh-TW':'傳統中式旗袍','en':'Traditional Chinese Cheongsam'},texts:['vibrant red silk qipao','golden phoenix embroidery','high collar','side slits','form-fitting silhouette']},
{id:4,name:{'zh-CN':'商务正装套装','zh-TW':'商務正裝套裝','en':'Business formal suit'},texts:['tailored charcoal gray three-piece wool suit','white dress shirt','burgundy silk tie','leather oxford shoes']},
{id:5,name:{'zh-CN':'波西米亚长裙','zh-TW':'波西米亞長裙','en':'Bohemian Dress'},texts:['flowing white cotton bohemian maxi dress','colorful floral prints','delicate lace trim','wide-brim straw hat']},
{id:6,name:{'zh-CN':'赛博朋克未来风','zh-TW':'賽博朋克未來風','en':'Futuristic Cyberpunk'},texts:['black leather cyberpunk jacket','glowing neon blue accents','holographic shoulder patches','slim cargo pants','combat boots']},
{id:7,name:{'zh-CN':'浪漫婚纱礼服','zh-TW':'浪漫婚纱禮服','en':'Romantic Wedding Dress'},texts:['ivory lace wedding dress','long cathedral train','delicate pearl embellishments','sheer veil']},
{id:8,name:{'zh-CN':'复古学院风','zh-TW':'復古學院風','en':'Vintage Academia'},texts:['vintage academia outfit','tweed blazer','pleated skirt','oxford shoes']},
{id:9,name:{'zh-CN':'冬季羊毛大衣','zh-TW':'冬季羊毛大衣','en':'Winter Wool Coat'},texts:['long camel-colored wool overcoat','wide belt','cashmere scarf','leather gloves']},
{id:10,name:{'zh-CN':'运动功能服饰','zh-TW':'運動功能服飾','en':'Sportswear'},texts:['black high-waisted compression leggings','neon green sports bra','lightweight running shoes']},
{id:11,name:{'zh-CN':'日式和服','zh-TW':'日式和服','en':'Japanese Kimono'},texts:['deep indigo silk kimono','delicate white crane and cherry blossom motifs','obi sash','geta sandals']},
{id:12,name:{'zh-CN':'日式JK制服','zh-TW':'日式JK制服','en':'Japanese JK Uniform'},texts:['navy blue seifuku uniform','white blouse','large sailor collar','red necktie','pleated navy skirt','black knee-high socks','brown loafers']},
{id:13,name:{'zh-CN':'法式女仆装','zh-TW':'法式女僕裝','en':'French Maid Costume'},texts:['classic black and white French maid uniform','low-cut bodice','white frilly apron with lace trim','short flared skirt','white headpiece','black thigh-high stockings with garter straps']},
{id:14,name:{'zh-CN':'小鸟游星野','zh-TW':'小鳥遊星野','en':'Takanashi Hoshino'},texts:['Abydos High School uniform','white shirt with top two buttons undone','loose blue tie','black and grey pleated skirt']},
{id:15,name:{'zh-CN':'小鸟游星野(泳装)','zh-TW':'小鳥遊星野(泳裝)','en':'Takanashi Hoshino(Swimsuit)'},texts:['white ruffled crop top camisole with thin straps and delicate ruffle hem','white ruffled bikini bottoms','open white beach jacket','white-frame blue sunglasses']},
{id:16,name:{'zh-CN':'小鸟游星野(武装)','zh-TW':'小鳥遊星野(武裝)','en':'Takanashi Hoshino(Battle)'},texts:['oversized white dress shirt with rolled-up sleeves','loose blue tie','grey pleated skirt','fingerless black gloves','black bulletproof vest','tactical brace and military gear','shotgun','full tactical equipment']},
{id:17,name:{'zh-CN':'空崎日奈','zh-TW':'空崎日奈','en':'Sorasaki Hina'},texts:['dark purple military uniform','golden buttons and medals','red prefect team armband','red military armband','short black skirt','wine purple thighhighs','dark purple military',]},
{id:18,name:{'zh-CN':'空崎日奈(泳装)','zh-TW':'空崎日奈(泳裝)','en':'Sorasaki Hina(Swimsuit)'},texts:['dark blue tankini swimsuit','name tag on chest','old childhood swim ring','inner tube floatie','swim ring']},
{id:19,name:{'zh-CN':'空崎日奈(礼服)','zh-TW':'空崎日奈(禮服)','en':'Sorasaki Hina(Dress)'},texts:['elegant dark purple evening gown','gradient purple dress with moon and stars pattern','sheer fabric at chest and skirt','purple long gloves','blue gem earrings and necklace']},
{id:20,name:{'zh-CN':'圣园未花','zh-TW':'聖園未花','en':'Misono Mika'},texts:['sleeveless white dress with starry print and frills at the hem','high-waisted skirt overlay with golden buttons','gold trimmings and blue ribbons','blue bow with golden cross accessory at neckline','white capelet with golden trimmings','white pantyhose','black high heels with back ribbon']},
{id:21,name:{'zh-CN':'圣园未花(泳装)','zh-TW':'聖園未花(泳裝)','en':'Misono Mika(Swimsuit)'},texts:['white one-piece swimsuit with gold celestial patterns','delicate gold trim','flowing sheer white beach cover-up','golden arm cuffs','white and gold halo']},
],
actionTag:[
{id:1,name:{'zh-CN':'优雅站姿','zh-TW':'優雅站姿','en':'Standing Gracefully'},texts:['standing gracefully','full body','looking at viewer']},
{id:2,name:{'zh-CN':'坐姿优雅','zh-TW':'坐姿優雅','en':'Sitting Elegantly'},texts:['sitting elegantly','hands on hips']},
{id:3,name:{'zh-CN':'动态姿势','zh-TW':'動態姿勢','en':'Dynamic Pose'},texts:['dynamic pose','confident expression']},
{id:4,name:{'zh-CN':'温柔微笑','zh-TW':'溫柔微笑','en':'Gentle Smile'},texts:['gentle smile','upper body']},
{id:5,name:{'zh-CN':'行走姿态','zh-TW':'行走姿態','en':'Walking'},texts:['walking','arms crossed']},
{id:6,name:{'zh-CN':'双手叉腰','zh-TW':'雙手叉腰','en':'Hands on Hips'},texts:['hands on hips','confident pose','standing tall','powerful stance','looking at viewer']},
{id:7,name:{'zh-CN':'回头凝视','zh-TW':'回頭凝視','en':'Looking Back'},texts:['looking back over shoulder','gentle smile','hair flowing','soft expression','eye contact']},
{id:8,name:{'zh-CN':'头发飘动','zh-TW':'頭髮飄動','en':'Hair Flowing'},texts:['hair flowing in wind','dynamic hair','wind effect','hair strands floating','natural movement']},
{id:9,name:{'zh-CN':'双手背后','zh-TW':'雙手背後','en':'Hands Behind Back'},texts:['hands behind back','relaxed pose','gentle smile','leaning slightly forward','innocent expression']},
{id:10,name:{'zh-CN':'微微前倾','zh-TW':'微微前傾','en':'Leaning Forward'},texts:['leaning forward slightly','curious expression','hands on knees','intimate distance','soft smile']}
],
actionNatural:[
{id:1,name:{'zh-CN':'自然站立','zh-TW':'自然站立','en':'Standing Naturally'},texts:['standing naturally in a serene environment','soft breeze blowing through hair','relaxed and graceful posture']},
{id:2,name:{'zh-CN':'优雅端坐','zh-TW':'優雅端坐','en':'Seated Elegantly'},texts:['sitting gracefully on an ornate velvet chair','hands folded neatly on the lap','poised and refined demeanor']},
{id:3,name:{'zh-CN':'回眸凝望','zh-TW':'回眸凝望','en':'Glancing Back'},texts:['looking back over the shoulder','gentle smile with sparkling eyes','hair swaying gently in motion']},
{id:4,name:{'zh-CN':'沉思静立','zh-TW':'沉思靜立','en':'Pensive Standing'},texts:['lost in deep thought','gazing into the far distance','hand resting gently on the chin']},
{id:5,name:{'zh-CN':'轻盈跃动','zh-TW':'輕盈躍動','en':'Light Leap'},texts:['caught mid-leap with arms spread wide','hair floating upward','expression full of joy and vitality']},
{id:6,name:{'zh-CN':'轻轻抚摸长发','zh-TW':'輕輕撫摸長髮','en':'Gently Touching Hair'},texts:['gently running fingers through long hair','soft and elegant movement','looking down shyly','hair cascading over shoulder','delicate hand gesture']},
{id:7,name:{'zh-CN':'靠在窗边沉思','zh-TW':'靠在窗邊沉思','en':'Leaning on Window Deep in Thought'},texts:['leaning against the window frame','gazing into the distance','soft natural light on face','peaceful and contemplative expression','one hand resting on the glass']},
{id:8,name:{'zh-CN':'漫步在花海中','zh-TW':'漫步在花海中','en':'Walking Through Flower Field'},texts:['walking gracefully through a field of flowers','petals gently falling around her','soft smile with eyes closed','dress flowing in the breeze','peaceful and dreamy atmosphere']},
{id:9,name:{'zh-CN':'坐在窗台上看风景','zh-TW':'坐在窗臺上看風景','en':'Sitting on Windowsill Watching Scenery'},texts:['sitting elegantly on the windowsill','legs gently crossed','looking outside with a gentle smile','sunlight illuminating her face','calm and serene moment']},
{id:10,name:{'zh-CN':'伸展身体放松','zh-TW':'伸展身體放鬆','en':'Stretching Body Relaxed'},texts:['stretching arms above head','body arched gracefully','eyes closed in relaxation','soft morning light','peaceful and natural pose']}
],
perspective:[
{id:1,name:{'zh-CN':'低角度','zh-TW':'低角度','en':'Low Angle'},texts:['low angle shot','from below','dramatic low angle','looking up']},
{id:2,name:{'zh-CN':'高角度','zh-TW':'高角度','en':'High Angle'},texts:['high angle','bird eye view','top down view','looking down']},
{id:3,name:{'zh-CN':'平视角度','zh-TW':'平視角度','en':'Eye Level'},texts:['eye level shot','straight on','frontal view','direct gaze']},
{id:4,name:{'zh-CN':'仰视特写','zh-TW':'仰視特寫','en':"Worm's Eye"},texts:["worm's eye view",'extreme low angle','looking up from ground','hero perspective']},
{id:5,name:{'zh-CN':'俯视全景','zh-TW':'俯視全景','en':'Aerial View'},texts:['aerial view','overlooking shot','drone perspective','panoramic view from above']},
{id:6,name:{'zh-CN':'三分之二视角','zh-TW':'三分之二視角','en':'Three-quarter View'},texts:['three-quarter view','dynamic angle','showing both face and body','natural perspective','flattering angle']},
{id:7,name:{'zh-CN':'过肩视角','zh-TW':'過肩視角','en':'Over the Shoulder'},texts:['over the shoulder shot','looking back at viewer','intimate perspective','soft focus on background','emotional connection']},
{id:8,name:{'zh-CN':'特写镜头','zh-TW':'特寫鏡頭','en':'Close-up Shot'},texts:['extreme close-up','detailed face','focus on eyes and expression','shallow depth of field','intimate portrait']},
{id:9,name:{'zh-CN':'广角全景','zh-TW':'廣角全景','en':'Wide Angle Shot'},texts:['wide angle shot','showing full environment','dramatic perspective','expansive view','cinematic wide shot']},
{id:10,name:{'zh-CN':'荷兰角倾斜','zh-TW':'荷蘭角傾斜','en':'Dutch Angle'},texts:['dutch angle','dynamic tilted composition','sense of unease or energy','creative perspective','dramatic framing']}
],
composition:[
{id:1,name:{'zh-CN':'居中构图','zh-TW':'居中構圖','en':'Centered'},texts:['centered composition','subject in the middle','symmetrical framing','balanced central focus']},
{id:2,name:{'zh-CN':'三分法则','zh-TW':'三分法則','en':'Rule of Thirds'},texts:['rule of thirds','off-center placement','balanced asymmetry','subject placed on third line']},
{id:3,name:{'zh-CN':'引导线','zh-TW':'引導線','en':'Leading Lines'},texts:['leading lines','converging lines','depth through perspective','lines drawing eye to subject']},
{id:4,name:{'zh-CN':'框架构图','zh-TW':'框架構圖','en':'Framed'},texts:['framed composition','natural frame around subject','looking through a window','foreground framing']},
{id:5,name:{'zh-CN':'对角线','zh-TW':'對角線','en':'Diagonal'},texts:['diagonal composition','dynamic angle','dutch angle tilt','tilted frame for energy']},
{id:6,name:{'zh-CN':'负空间构图','zh-TW':'負空間構圖','en':'Negative Space'},texts:['negative space composition','subject off-center','empty space for breathing room','minimalist feel','artistic balance']},
{id:7,name:{'zh-CN':'对称构图','zh-TW':'對稱構圖','en':'Symmetrical Composition'},texts:['perfect symmetry','mirrored composition','balanced and harmonious','centered subject','formal and elegant']},
{id:8,name:{'zh-CN':'黄金分割','zh-TW':'黃金分割','en':'Golden Ratio'},texts:['golden ratio composition','fibonacci spiral','naturally pleasing placement','organic balance','professional photography rule']},
{id:9,name:{'zh-CN':'景深效果','zh-TW':'景深效果','en':'Depth of Field'},texts:['shallow depth of field','beautiful bokeh','subject in sharp focus','blurred background','cinematic separation']},
{id:10,name:{'zh-CN':'剪影构图','zh-TW':'剪影構圖','en':'Silhouette Composition'},texts:['strong silhouette','backlit subject','dramatic outline','minimal detail','powerful visual impact']}
],
background:[
{id:1,name:{'zh-CN':'城市夜景','zh-TW':'城市夜景','en':'Cyberpunk Night City'},texts:['cyberpunk cityscape at night','neon-lit skyscrapers reflecting on wet streets','futuristic metropolis with holographic billboards','rain-slicked asphalt glowing with neon reflections','aerial view of sprawling night city with flying vehicles','dense urban canyon of glass and steel under purple night sky','cyberpunk alleyway with neon signs and steam vents']},
{id:2,name:{'zh-CN':'奇幻森林','zh-TW':'奇幻森林','en':'Enchanted Forest'},texts:['enchanted forest with glowing bioluminescent flora','ancient moss-covered trees with twisting roots','sunbeams filtering through dense forest canopy','magical woodland with floating fireflies and ethereal mist','fairy tale forest with oversized mushrooms and crystal streams','deep mystical woods bathed in soft golden hour light','winding forest path surrounded by vibrant wildflowers']},
{id:3,name:{'zh-CN':'山脉景观','zh-TW':'山脈景觀','en':'Majestic Mountains'},texts:['majestic snow-capped mountain range at golden hour','towering granite peaks piercing through cloud layers','dramatic alpine landscape with crystal-clear glacial lake','vast mountain panorama with rolling fog in valleys below','rugged mountain cliffs with cascading waterfall','serene mountain meadow with wildflowers and distant peaks','epic mountain vista under dramatic storm clouds']},
{id:4,name:{'zh-CN':'赛博朋克街头','zh-TW':'賽博朋克街頭','en':'Neon Cyberpunk Street'},texts:['narrow cyberpunk street bathed in pink and blue neon glow','Japanese-inspired cyberpunk alley with hanging lanterns and holograms','futuristic street market with neon signs and crowded stalls','rainy night street scene with reflections in puddles','cyberpunk back alley with exposed wiring and neon graffiti','bustling futuristic street with mixed tech and traditional elements']},
{id:5,name:{'zh-CN':'水下世界','zh-TW':'水下世界','en':'Underwater Realm'},texts:['deep underwater realm with bioluminescent creatures','sunken ancient ruins with schools of tropical fish','coral reef paradise with vibrant marine life','ethereal underwater scene with god rays penetrating ocean surface','mysterious deep sea trench with glowing jellyfish','underwater cavern with crystal formations and soft blue light','mermaid kingdom with coral castles and sea anemones']},
{id:6,name:{'zh-CN':'太空星云','zh-TW':'太空星雲','en':'Cosmic Nebula'},texts:['vast cosmic nebula with swirling purple and blue gas clouds','deep space scene with distant galaxies and star clusters','colorful supernova remnant with vibrant interstellar dust','nebula nursery with newborn stars illuminating surrounding gas','cosmic landscape with a ringed planet silhouetted against a nebula','stunning spiral galaxy with bright core and dust lanes','interstellar cloud of ionized gas in deep space']},
{id:7,name:{'zh-CN':'传统中式庭院','zh-TW':'傳統中式庭院','en':'Traditional Chinese Garden'},texts:['traditional Chinese garden with moon gate and koi pond','serene Suzhou-style garden with winding covered walkways','classical Chinese courtyard with ancient pine and ornamental rocks','zen garden with raked gravel and moss-covered stones','Chinese scholar garden with bamboo grove and lotus pond','elegant pavilion overlooking a misty garden with cherry blossoms','Ming dynasty style garden with whitewashed walls and grey tile roofs']},
{id:8,name:{'zh-CN':'雪山日出','zh-TW':'雪山日出','en':'Snowy Mountain Sunrise'},texts:['snow-covered mountain peak glowing in first light of dawn','alpine sunrise with golden alpenglow on pristine snow','winter mountain landscape with frosted pine trees at sunrise','majestic snowy summit bathed in warm morning light','crisp winter dawn over a frozen alpine lake with mountain backdrop','powder snow slope with sparkling ice crystals under sunrise','serene winter wilderness with snow-laden branches and pink dawn sky']}
],
nsfwClothing:[
{id:1,name:{'zh-CN':'白色Babydoll内衣','zh-TW':'白色Babydoll内衣','en':'White Babydoll Lingerie'},texts:['delicate white sheer babydoll lingerie set','intricate floral lace trim','thin adjustable spaghetti straps','semi-transparent flowing fabric','matching lace panties']},
{id:2,name:{'zh-CN':'黑色蕾丝连体衣','zh-TW':'黑色蕾絲連體衣','en':'Black Lace Bodysuit'},texts:['sheer black lace bodysuit','deep plunging neckline','high-cut legs','intricate floral lace pattern','crotchless design']},
{id:3,name:{'zh-CN':'红色微型比基尼','zh-TW':'紅色微型比基尼','en':'Red Micro Bikini'},texts:['tiny red string micro bikini','minimal coverage','side-tie bottoms','triangle top','glossy wet look fabric']},
{id:4,name:{'zh-CN':'白色吊带丝袜与吊袜带','zh-TW':'白色吊帶絲襪與吊襪帶','en':'White Thighhighs with Garter Belt'},texts:['sheer white thighhigh stockings','black lace garter belt','bow details','silky smooth texture','suspender straps']},
{id:5,name:{'zh-CN':'透明睡裙','zh-TW':'透明睡裙','en':'Sheer Nightgown'},texts:['completely sheer white nightgown','see-through fabric','delicate lace hem','long flowing sleeves','nothing underneath']},
{id:6,name:{'zh-CN':'兔女郎套装','zh-TW':'兔女郎套裝','en':'Bunny Girl Outfit'},texts:['black bunny girl leotard','white bunny ears','black bow tie','fishnet stockings','high heels','bunny tail']},
{id:7,name:{'zh-CN':'学校泳装','zh-TW':'學校泳裝','en':'School Swimsuit'},texts:['classic school swimsuit','sukumizu','tight fitting navy blue','white name tag on chest','wet fabric clinging to body']},
{id:8,name:{'zh-CN':'黑色皮革束缚','zh-TW':'黑色皮革束縛','en':'Black Leather Harness'},texts:['black leather harness','strappy body harness','metal rings and buckles','minimal coverage','dominant aesthetic']},
{id:9,name:{'zh-CN':'渔网连体衣','zh-TW':'漁網連體衣','en':'Fishnet Bodysuit'},texts:['sheer black fishnet bodysuit','full body fishnet','strategic cutouts','very revealing','seductive texture']},
{id:10,name:{'zh-CN':'透明比基尼','zh-TW':'透明比基尼','en':'Transparent Bikini'},texts:['completely transparent micro bikini','see-through fabric','minimal string design','wet look effect','almost nude appearance']},
{id:11,name:{'zh-CN':'女仆情趣内衣','zh-TW':'女僕情趣內衣','en':'Maid Lingerie'},texts:['sexy french maid lingerie','low cut top','frilly apron','short skirt with garter','thighhigh stockings']},
{id:12,name:{'zh-CN':'露背高叉礼服','zh-TW':'露背高叉禮服','en':'Backless High-slit Dress'},texts:['elegant backless evening gown','extremely high side slits','deep plunging back','sideboob exposure','floor length with high cut']},
{id:13,name:{'zh-CN':'吊带袜套装','zh-TW':'吊帶襪套裝','en':'Garter Stockings Set'},texts:['black lace garter belt','sheer thighhigh stockings','matching panties','suspender straps','elegant and seductive']},
{id:14,name:{'zh-CN':'微型裙装','zh-TW':'微型裙裝','en':'Micro Skirt Set'},texts:['extremely short micro skirt','crop top','underboob exposure','thong visible','playful and revealing']},
{id:15,name:{'zh-CN':'完全裸体','zh-TW':'完全裸體','en':'Completely Nude'},texts:['completely nude','no clothing','detailed skin texture','natural body','artistic nude']}
],
nsfwActionTag:[
{id:1,name:{'zh-CN':'诱惑姿势','zh-TW':'誘惑姿勢','en':'Seductive Pose'},texts:['seductive pose','hand on breast','arching back','looking at viewer with bedroom eyes','parted lips']},
{id:2,name:{'zh-CN':'双腿分开','zh-TW':'雙腿分開','en':'Legs Spread'},texts:['legs spread wide','knees bent','exposed','inviting pose','full body view']},
{id:3,name:{'zh-CN':'ahegao表情','zh-TW':'ahegao表情','en':'Ahegao Face'},texts:['ahegao','tongue out','crossed eyes','blushing heavily','heart-shaped pupils']},
{id:4,name:{'zh-CN':'跪姿后入','zh-TW':'跪姿後入','en':'Doggy Style Pose'},texts:['on all fours','doggy style position','looking back','raised hips','arched back']},
{id:5,name:{'zh-CN':'自慰姿势','zh-TW':'自慰姿勢','en':'Masturbation Pose'},texts:['fingers between legs','touching self','moaning expression','one hand on chest','legs trembling']},
{id:6,name:{'zh-CN':'诱惑眼神','zh-TW':'誘惑眼神','en':'Seductive Gaze'},texts:['seductive bedroom eyes','half-lidded eyes','intense eye contact','lustful expression','biting lip']},
{id:7,name:{'zh-CN':'舔嘴唇','zh-TW':'舔嘴唇','en':'Licking Lips'},texts:['licking lips sensually','tongue on lips','hungry expression','anticipation','seductive gesture']},
{id:8,name:{'zh-CN':'手放胸前','zh-TW':'手放胸前','en':'Hand on Chest'},texts:['hand on breast','covering nipples','squeezing gently','teasing expression','playful pose']},
{id:9,name:{'zh-CN':'大腿张开','zh-TW':'大腿張開','en':'Legs Spread Wide'},texts:['legs spread wide open','M-shaped legs','completely exposed','inviting pose','full frontal view']},
{id:10,name:{'zh-CN':'后背弓起','zh-TW':'後背弓起','en':'Arched Back'},texts:['deeply arched back','thrusting chest forward','ass up face down','presenting pose','intense pleasure expression']},
{id:11,name:{'zh-CN':'手指玩弄','zh-TW':'手指玩弄','en':'Fingering'},texts:['fingers between legs','inserting fingers','wet fingers','masturbating','ecstatic face']},
{id:12,name:{'zh-CN':'ahegao高潮脸','zh-TW':'ahegao高潮臉','en':'Ahegao Orgasm Face'},texts:['full ahegao','tongue hanging out','rolled eyes','heart pupils','drooling heavily']},
{id:13,name:{'zh-CN':'后入姿势','zh-TW':'後入姿勢','en':'From Behind Pose'},texts:['from behind','doggy style','looking back','ass up','hair pulled']},
{id:14,name:{'zh-CN':'骑乘位','zh-TW':'騎乘位','en':'Cowgirl Position'},texts:['cowgirl position','straddling','hands on chest','riding motion','ecstatic expression']},
{id:15,name:{'zh-CN':'潮吹表情','zh-TW':'潮吹表情','en':'Squirting Expression'},texts:['squirting','intense orgasm face','body trembling','eyes rolled back','fluids visible']}
],
nsfwActionNatural:[
{id:1,name:{'zh-CN':'躺在床上诱惑地看着你','zh-TW':'躺在床上誘惑地看著你','en':'Lying on bed seductively looking at you'},texts:['lying on her back on luxurious silk sheets','legs slightly parted','one arm raised above head','gently biting lower lip','inviting gaze directly at viewer']},
{id:2,name:{'zh-CN':'跪在地板上双手撑地','zh-TW':'跪在地板上雙手撐地','en':'Kneeling on floor with hands on ground'},texts:['kneeling on all fours on the soft carpet','back arched deeply','hips raised high','looking over shoulder with flushed cheeks','hair cascading down']},
{id:3,name:{'zh-CN':'坐在椅子上张开双腿','zh-TW':'坐在椅子上張開雙腿','en':'Sitting on chair with legs spread'},texts:['sitting on the edge of a velvet chair','thighs spread wide apart','hands resting on knees','upper body leaning forward slightly','playful yet lustful expression']},
{id:4,name:{'zh-CN':'靠在墙上双手举起','zh-TW':'靠在牆上雙手舉起','en':'Leaning against wall with arms raised'},texts:['leaning back against the cold wall','arms stretched above head','wrists crossed','chest thrust forward','eyes half-closed in pleasure']},
{id:5,name:{'zh-CN':'在床上爬行靠近','zh-TW':'在床上爬行靠近','en':'Crawling towards you on the bed'},texts:['crawling slowly towards the viewer on the large bed','seductive smile','hips swaying side to side','long hair dragging on sheets','hungry look in eyes']},
{id:6,name:{'zh-CN':'躺在床上诱惑扭动身体','zh-TW':'躺在床上誘惑扭動身體','en':'Lying on bed seductively writhing'},texts:['lying on luxurious bed sheets','slowly writhing her body','hands slowly sliding down her torso','legs gently rubbing together','soft moans with flushed face']},
{id:7,name:{'zh-CN':'跪在地上双手撑地翘臀','zh-TW':'跪在地上雙手撐地翹臀','en':'Kneeling with hands on floor and hips raised'},texts:['kneeling on all fours','back deeply arched','hips raised high and pushed back','looking back with pleading eyes','hair falling over face']},
{id:8,name:{'zh-CN':'坐在椅子上张腿自慰','zh-TW':'坐在椅子上張腿自慰','en':'Sitting on chair with legs spread masturbating'},texts:['sitting on the edge of a chair','legs spread extremely wide','one hand between her thighs','other hand squeezing breast','head tilted back in pleasure']},
{id:9,name:{'zh-CN':'靠在墙上双手举过头顶','zh-TW':'靠在牆上雙手舉過頭頂','en':'Leaning against wall with arms above head'},texts:['leaning back against the wall','arms stretched high above head','chest pushed forward','legs slightly apart','eyes half-closed in ecstasy']},
{id:10,name:{'zh-CN':'在床上爬向你','zh-TW':'在床上爬向你','en':'Crawling towards you on the bed'},texts:['slowly crawling on all fours towards viewer','seductive smile with heavy breathing','hips swaying side to side','long hair dragging on sheets','hungry lustful eyes']},
{id:11,name:{'zh-CN':'双手抱胸轻轻揉捏','zh-TW':'雙手抱胸輕輕揉捏','en':'Gently squeezing breasts with both hands'},texts:['cupping her breasts with both hands','gently squeezing and lifting them','looking down at her own body','soft blush on cheeks','slightly parted lips']},
{id:12,name:{'zh-CN':'侧躺在床上回眸微笑','zh-TW':'側躺在床上回眸微笑','en':'Lying on side looking back with smile'},texts:['lying on her side on the bed','looking back over her shoulder','gentle yet seductive smile','one leg slightly raised','soft natural lighting']},
{id:13,name:{'zh-CN':'坐在你腿上面对面','zh-TW':'坐在你腿上面對面','en':'Sitting on your lap facing you'},texts:['straddling viewer\'s lap','facing forward','arms wrapped around neck','gentle grinding motion','intimate eye contact and soft breathing']},
{id:14,name:{'zh-CN':'双手撑墙后背对镜','zh-TW':'雙手撐牆後背對鏡','en':'Hands on wall with back facing mirror'},texts:['standing with hands pressed against the wall','back arched','looking at her own reflection in mirror','ass pushed out','flushed expression']},
{id:15,name:{'zh-CN':'躺在床上双腿大开邀请','zh-TW':'躺在床上雙腿大開邀請','en':'Lying on bed with legs wide open invitingly'},texts:['lying on back with legs spread extremely wide','hands holding her own thighs','completely exposed and inviting','soft inviting smile','eyes full of desire']}
]
};
// ==================== Category Meta ====================
var categoryMeta = {
quality:{icon:'✨',color:'indigo', accentBg:'bg-indigo-500/10', accentText:'text-indigo-300', accentBorder:'border-indigo-500/30', accentDot:'bg-indigo-400'},
style:{icon:'🖼️',color:'amber', accentBg:'bg-amber-500/10', accentText:'text-amber-300', accentBorder:'border-amber-500/30', accentDot:'bg-amber-400'},
character:{icon:'👤',color:'purple', accentBg:'bg-purple-500/10', accentText:'text-purple-300', accentBorder:'border-purple-500/30', accentDot:'bg-purple-400'},
clothing:{icon:'👗',color:'pink', accentBg:'bg-pink-500/10', accentText:'text-pink-300', accentBorder:'border-pink-500/30', accentDot:'bg-pink-400'},
actionTag:{icon:'🏃',color:'emerald', accentBg:'bg-emerald-500/10', accentText:'text-emerald-300', accentBorder:'border-emerald-500/30', accentDot:'bg-emerald-400'},
actionNatural:{icon:'📝',color:'teal', accentBg:'bg-teal-500/10', accentText:'text-teal-300', accentBorder:'border-teal-500/30', accentDot:'bg-teal-400'},
perspective:{icon:'📐',color:'teal', accentBg:'bg-teal-500/10', accentText:'text-teal-300', accentBorder:'border-teal-500/30', accentDot:'bg-teal-400'},
composition:{icon:'🖼️',color:'cyan', accentBg:'bg-cyan-500/10', accentText:'text-cyan-300', accentBorder:'border-cyan-500/30', accentDot:'bg-cyan-400'},
background:{icon:'🏞️',color:'emerald', accentBg:'bg-emerald-500/10', accentText:'text-emerald-300', accentBorder:'border-emerald-500/30', accentDot:'bg-emerald-400'},
nsfwClothing:{icon:'👙',color:'rose', accentBg:'bg-rose-500/10', accentText:'text-rose-300', accentBorder:'border-rose-500/30', accentDot:'bg-rose-400'},
nsfwActionTag:{icon:'💋',color:'orange', accentBg:'bg-orange-500/10', accentText:'text-orange-300', accentBorder:'border-orange-500/30', accentDot:'bg-orange-400'},
nsfwActionNatural:{icon:'🔞',color:'violet', accentBg:'bg-violet-500/10', accentText:'text-violet-300', accentBorder:'border-violet-500/30', accentDot:'bg-violet-400'}
};
var tagUnselectedCls = {
indigo:'glass text-zinc-300 border-white/5 hover:border-indigo-500/30 hover:bg-indigo-500/5',
purple:'glass text-zinc-300 border-white/5 hover:border-purple-500/30 hover:bg-purple-500/5',
pink:'glass text-zinc-300 border-white/5 hover:border-pink-500/30 hover:bg-pink-500/5',
emerald:'glass text-zinc-300 border-white/5 hover:border-emerald-500/30 hover:bg-emerald-500/5',
teal:'glass text-zinc-300 border-white/5 hover:border-teal-500/30 hover:bg-teal-500/5',
amber:'glass text-zinc-300 border-white/5 hover:border-amber-500/30 hover:bg-amber-500/5',
cyan:'glass text-zinc-300 border-white/5 hover:border-cyan-500/30 hover:bg-cyan-500/5',
rose:'glass text-zinc-300 border-white/5 hover:border-rose-500/30 hover:bg-rose-500/5',
orange:'glass text-zinc-300 border-white/5 hover:border-orange-500/30 hover:bg-orange-500/5',
violet:'glass text-zinc-300 border-white/5 hover:border-violet-500/30 hover:bg-violet-500/5'
};
var tagSelectedCls = {
indigo:'bg-indigo-500/20 text-indigo-200 border-indigo-500/40 shadow-lg shadow-indigo-500/10',
purple:'bg-purple-500/20 text-purple-200 border-purple-500/40 shadow-lg shadow-purple-500/10',
pink:'bg-pink-500/20 text-pink-200 border-pink-500/40 shadow-lg shadow-pink-500/10',
emerald:'bg-emerald-500/20 text-emerald-200 border-emerald-500/40 shadow-lg shadow-emerald-500/10',
teal:'bg-teal-500/20 text-teal-200 border-teal-500/40 shadow-lg shadow-teal-500/10',
amber:'bg-amber-500/20 text-amber-200 border-amber-500/40 shadow-lg shadow-amber-500/10',
cyan:'bg-cyan-500/20 text-cyan-200 border-cyan-500/40 shadow-lg shadow-cyan-500/10',
rose:'bg-rose-500/20 text-rose-200 border-rose-500/40 shadow-lg shadow-rose-500/10',
orange:'bg-orange-500/20 text-orange-200 border-orange-500/40 shadow-lg shadow-orange-500/10',
violet:'bg-violet-500/20 text-violet-200 border-violet-500/40 shadow-lg shadow-violet-500/10'
};
var chipCls = {
indigo:'bg-indigo-500/10 text-indigo-200 border-indigo-500/20',
purple:'bg-purple-500/10 text-purple-200 border-purple-500/20',
pink:'bg-pink-500/10 text-pink-200 border-pink-500/20',
emerald:'bg-emerald-500/10 text-emerald-200 border-emerald-500/20',
teal:'bg-teal-500/10 text-teal-200 border-teal-500/20',
amber:'bg-amber-500/10 text-amber-200 border-amber-500/20',
cyan:'bg-cyan-500/10 text-cyan-200 border-cyan-500/20',
rose:'bg-rose-500/10 text-rose-200 border-rose-500/20',
orange:'bg-orange-500/10 text-orange-200 border-orange-500/20',
violet:'bg-violet-500/10 text-violet-200 border-violet-500/20'
};
// ==================== State ====================
var STORAGE_KEY = 'sd-prompt-selector-final-v14';
function makeDefaultSelectedGroups() {
var obj = {};
for (var i = 0; i < ALL_ORDER.length; i++) { obj[ALL_ORDER[i]] = new Set(); }
return obj;
}
function makeDefaultExpanded() {
var obj = {};
for (var i = 0; i < ALL_ORDER.length; i++) { obj[ALL_ORDER[i]] = false; }
obj.quality = true;
return obj;
}
var state = {
selectedGroups: makeDefaultSelectedGroups(),
expandedCategories: makeDefaultExpanded(),
activeCategory: 'quality',
shuffled: false,
mode: 'sd',
lang: 'zh-CN',
nsfwEnabled: false,
blurIntensity: 20,
shimmerEnabled: true
};
// ==================== DOM Refs ====================
var $ = function(s) { return document.querySelector(s); };
var $$ = function(s) { return document.querySelectorAll(s); };
var dom = {
sidebarNav: $('#sidebarNav'),
sidebarTitle: $('#sidebarTitle'),
sidebarTotalBadge: $('#sidebarTotalBadge'),
contentSections: $('#contentSections'),
mainContent: $('#mainContent'),
searchInput: $('#searchInput'),
searchClearBtn: $('#searchClearBtn'),
selectedGroupsContainer: $('#selectedGroupsContainer'),
emptyHintRight: $('#emptyHintRight'),
groupCountBadge: $('#groupCountBadge'),
clearAllBtn: $('#clearAllBtn'),
promptOutput: $('#promptOutput'),
charCount: $('#charCount'),
regenPromptBtn: $('#regenPromptBtn'),
copyBtn: $('#copyBtn'),
shuffleBtn: $('#shuffleBtn'),
modeToggle: $('#modeToggle'),
nsfwBtn: $('#nsfwBtn'),
nsfwModal: $('#nsfwModal'),
nsfwModalTitle: $('#nsfwModalTitle'),
nsfwModalCancel: $('#nsfwModalCancel'),
nsfwModalConfirm: $('#nsfwModalConfirm'),
settingsModal: $('#settingsModal'),
settingsBackdrop: $('#settingsBackdrop'),
settingsCloseBtn: $('#settingsCloseBtn'),
settingsBtn: $('#settingsBtn'),
blurSlider: $('#blurSlider'),
blurValue: $('#blurValue'),
shimmerToggle: $('#shimmerToggle'),
settingsTitle: $('#settingsTitle'),
settingsBlurLabel: $('#settingsBlurLabel'),
settingsShimmerLabel: $('#settingsShimmerLabel'),
settingsShimmerHint: $('#settingsShimmerHint')
};
// Guard for protecting user manual edits in the prompt textarea
var lastAutoPrompt = '';
var promptIsCustom = false;
// ==================== Utils ====================
function getGroupData(cat, id) { return promptLibrary[cat].find(function(g) { return g.id === id; }); }
function getAllSelectedGroups() {
var result = [];
for (var i = 0; i < ALL_ORDER.length; i++) {
var cat = ALL_ORDER[i], ids = state.selectedGroups[cat];
if (!ids) continue;
var arr = Array.from(ids);
for (var j = 0; j < arr.length; j++) {
var group = getGroupData(cat, arr[j]);
if (group) result.push({category:cat, id:group.id, name:group.name, texts:group.texts, imageUrl:group.imageUrl});
}
}
return result;
}
function getTotalGroups() {
var n = 0, cats = Object.keys(state.selectedGroups);
for (var i = 0; i < cats.length; i++) { n += state.selectedGroups[cats[i]].size; }
return n;
}
function getTotalTexts() {
var n = 0, all = getAllSelectedGroups();
for (var i = 0; i < all.length; i++) { n += all[i].texts.length; }
return n;
}
function shuffle(arr) {
var a = arr.slice();
for (var i = a.length - 1; i > 0; i--) { var j = Math.floor(Math.random() * (i + 1)), tmp = a[i]; a[i] = a[j]; a[j] = tmp; }
return a;
}
function copyToClipboard(text) {
if (navigator.clipboard && navigator.clipboard.writeText) return navigator.clipboard.writeText(text);
return new Promise(function(resolve, reject) {
var ta = document.createElement('textarea'); ta.value = text;
ta.style.cssText = 'position:fixed;left:-9999px;top:-9999px;';
document.body.appendChild(ta); ta.focus(); ta.select();
try { var ok = document.execCommand('copy'); document.body.removeChild(ta); ok ? resolve() : reject(new Error('execCommand failed')); }
catch(e) { document.body.removeChild(ta); reject(e); }
});
}
// ==================== Persistence ====================
function saveState() {
var data = {
selectedGroups:{}, expandedCategories:state.expandedCategories, activeCategory:state.activeCategory,
nsfwEnabled:state.nsfwEnabled, blurIntensity:state.blurIntensity, shimmerEnabled:state.shimmerEnabled,
mode:state.mode, lang:state.lang
};
var cats = Object.keys(state.selectedGroups);
for (var i = 0; i < cats.length; i++) { data.selectedGroups[cats[i]] = Array.from(state.selectedGroups[cats[i]]); }
try { localStorage.setItem(STORAGE_KEY, JSON.stringify(data)); } catch(e) {}
}
function loadState() {