tester343 commited on
Commit
c5b20fe
·
verified ·
1 Parent(s): 68aca8d

Update app_enhanced.py

Browse files
Files changed (1) hide show
  1. app_enhanced.py +11 -50
app_enhanced.py CHANGED
@@ -91,6 +91,7 @@ INDEX_HTML = '''
91
  .file-label:hover { background: #34495e; }
92
  .submit-btn { width: 100%; padding: 15px; background: #e67e22; color: white; border: none; border-radius: 8px; font-size: 18px; font-weight: bold; cursor: pointer; transition: 0.2s; }
93
  .submit-btn:hover { background: #d35400; }
 
94
  .restore-btn { margin-top: 15px; background: #27ae60; color: white; padding: 10px; width: 100%; border: none; border-radius: 8px; cursor: pointer; font-weight: bold; display: none; }
95
 
96
  .loader { width: 120px; height: 20px; background: radial-gradient(circle 10px, #e67e22 100%, transparent 0); background-size: 20px 20px; animation: ball 1s infinite linear; margin: 20px auto; }
@@ -101,11 +102,11 @@ INDEX_HTML = '''
101
  .comic-grid { display: grid; grid-template-columns: 285px 285px; grid-template-rows: 185px 185px; gap: 10px; width: 100%; height: 100%; padding: 10px; box-sizing: border-box; }
102
  .panel { position: relative; overflow: hidden; border: 2px solid #000; background: #eee; cursor: pointer; }
103
  .panel.selected { outline: 3px solid #2196F3; outline-offset: -3px; }
104
- .panel img { width: 100%; height: 100%; object-fit: cover; transition: transform 0.1s ease-out; transform-origin: center center; }
105
  .panel img.pannable { cursor: grab; }
106
  .panel img.panning { cursor: grabbing; }
107
 
108
- /* --- SPEECH BUBBLE (SHARK FIN) --- */
109
  .speech-bubble {
110
  position: absolute; display: flex; justify-content: center; align-items: center;
111
  width: 150px; height: 80px; min-width: 60px; min-height: 40px; box-sizing: border-box;
@@ -116,65 +117,24 @@ INDEX_HTML = '''
116
  .speech-bubble.selected { outline: 2px dashed #4CAF50; }
117
  .speech-bubble textarea { position: absolute; top:0; left:0; width:100%; height:100%; box-sizing:border-box; border:1px solid #4CAF50; background:rgba(255,255,255,0.9); text-align:center; padding:8px; z-index:100; resize:none; }
118
 
119
- /* The specific CSS request from user */
120
  .speech-bubble.speech {
121
- --b: 3em; /* tail base */
122
- --h: 1.8em; /* tail height */
123
- --t: 0.6; /* thickness */
124
- --p: var(--tail-pos, 50%); /* slider pos */
125
- --r: 1.2em; /* radius */
126
  --c: var(--bubble-fill-color, #4ECDC4);
127
-
128
- background: var(--c);
129
- color: var(--bubble-text-color, #fff);
130
- padding: 1em;
131
- position: absolute;
132
-
133
- /* Exact border radius formula provided */
134
  border-radius: var(--r) var(--r) min(var(--r), calc(100% - var(--p) - (1 - var(--t)) * var(--b) / 2)) min(var(--r), calc(var(--p) - (1 - var(--t)) * var(--b) / 2)) / var(--r);
135
  }
136
-
137
- /*
138
- TAIL IMPLEMENTATION:
139
- Using 'radial-gradient' background instead of mask.
140
- This visually creates the EXACT concave shape requested but is 100% export-safe.
141
- */
142
  .speech-bubble.speech:before {
143
  content: ""; position: absolute; width: var(--b); height: var(--h);
144
- /* Gradient mimics the mask curve */
145
  background: radial-gradient(100% 100% at 100% 0, transparent calc(var(--t) * 100% - 1px), var(--c) calc(var(--t) * 100%));
146
  border-bottom-left-radius: 100%; pointer-events: none; z-index: 1;
147
  }
148
-
149
- /* ROTATION LOGIC (Adapting the shape for 4 sides) */
150
-
151
- /* Bottom (Default) */
152
- .speech-bubble.speech.tail-bottom:before {
153
- top: 99%; left: clamp(0%, calc(var(--p) - (1 - var(--t)) * var(--b) / 2), calc(100% - (1 - var(--t)) * var(--b)));
154
- }
155
-
156
- /* Top */
157
- .speech-bubble.speech.tail-top {
158
- border-radius: min(var(--r), calc(var(--p) - (1 - var(--t)) * var(--b) / 2)) min(var(--r), calc(100% - var(--p) - (1 - var(--t)) * var(--b) / 2)) var(--r) var(--r) / var(--r);
159
- }
160
- .speech-bubble.speech.tail-top:before {
161
- bottom: 99%; left: clamp(0%, calc(var(--p) - (1 - var(--t)) * var(--b) / 2), calc(100% - (1 - var(--t)) * var(--b)));
162
- transform: scaleY(-1);
163
- }
164
-
165
- /* Left */
166
  .speech-bubble.speech.tail-left { border-radius: var(--r); }
167
- .speech-bubble.speech.tail-left:before {
168
- right: 99%; top: clamp(0%, calc(var(--p) - (1 - var(--t)) * var(--b) / 2), calc(100% - (1 - var(--t)) * var(--b)));
169
- transform: rotate(90deg); transform-origin: top right;
170
- }
171
-
172
- /* Right */
173
  .speech-bubble.speech.tail-right { border-radius: var(--r); }
174
- .speech-bubble.speech.tail-right:before {
175
- left: 99%; top: clamp(0%, calc(var(--p) - (1 - var(--t)) * var(--b) / 2), calc(100% - (1 - var(--t)) * var(--b)));
176
- transform: rotate(-90deg); transform-origin: top left;
177
- }
178
 
179
  .speech-bubble.thought { background: white; border: 2px dashed #555; color: #333; border-radius: 50%; }
180
  .speech-bubble.thought::after { display:none; }
@@ -205,6 +165,7 @@ INDEX_HTML = '''
205
  <span id="fn">No file selected</span>
206
  <button class="submit-btn" onclick="upload()">Generate Comic</button>
207
  <button id="restore-btn" class="restore-btn" onclick="restoreSession()">📂 Restore Unsaved Session</button>
 
208
  <div class="loading-view" id="loading-view" style="display:none;">
209
  <div class="loader"></div>
210
  <p id="status-text">Starting...</p>
 
91
  .file-label:hover { background: #34495e; }
92
  .submit-btn { width: 100%; padding: 15px; background: #e67e22; color: white; border: none; border-radius: 8px; font-size: 18px; font-weight: bold; cursor: pointer; transition: 0.2s; }
93
  .submit-btn:hover { background: #d35400; }
94
+
95
  .restore-btn { margin-top: 15px; background: #27ae60; color: white; padding: 10px; width: 100%; border: none; border-radius: 8px; cursor: pointer; font-weight: bold; display: none; }
96
 
97
  .loader { width: 120px; height: 20px; background: radial-gradient(circle 10px, #e67e22 100%, transparent 0); background-size: 20px 20px; animation: ball 1s infinite linear; margin: 20px auto; }
 
102
  .comic-grid { display: grid; grid-template-columns: 285px 285px; grid-template-rows: 185px 185px; gap: 10px; width: 100%; height: 100%; padding: 10px; box-sizing: border-box; }
103
  .panel { position: relative; overflow: hidden; border: 2px solid #000; background: #eee; cursor: pointer; }
104
  .panel.selected { outline: 3px solid #2196F3; outline-offset: -3px; }
105
+ .panel img { width: 100%; height: 100%; object-fit: cover; transition: transform 0.1s; }
106
  .panel img.pannable { cursor: grab; }
107
  .panel img.panning { cursor: grabbing; }
108
 
109
+ /* --- SPEECH BUBBLE (EXACT SHARK FIN CSS) --- */
110
  .speech-bubble {
111
  position: absolute; display: flex; justify-content: center; align-items: center;
112
  width: 150px; height: 80px; min-width: 60px; min-height: 40px; box-sizing: border-box;
 
117
  .speech-bubble.selected { outline: 2px dashed #4CAF50; }
118
  .speech-bubble textarea { position: absolute; top:0; left:0; width:100%; height:100%; box-sizing:border-box; border:1px solid #4CAF50; background:rgba(255,255,255,0.9); text-align:center; padding:8px; z-index:100; resize:none; }
119
 
 
120
  .speech-bubble.speech {
121
+ --b: 3em; --h: 1.8em; --t: 0.6; --p: var(--tail-pos, 50%); --r: 1.2em;
 
 
 
 
122
  --c: var(--bubble-fill-color, #4ECDC4);
123
+ background: var(--c); color: var(--bubble-text-color, #fff); padding: 1em; position: absolute;
 
 
 
 
 
 
124
  border-radius: var(--r) var(--r) min(var(--r), calc(100% - var(--p) - (1 - var(--t)) * var(--b) / 2)) min(var(--r), calc(var(--p) - (1 - var(--t)) * var(--b) / 2)) / var(--r);
125
  }
 
 
 
 
 
 
126
  .speech-bubble.speech:before {
127
  content: ""; position: absolute; width: var(--b); height: var(--h);
 
128
  background: radial-gradient(100% 100% at 100% 0, transparent calc(var(--t) * 100% - 1px), var(--c) calc(var(--t) * 100%));
129
  border-bottom-left-radius: 100%; pointer-events: none; z-index: 1;
130
  }
131
+ .speech-bubble.speech.tail-bottom:before { top: 99%; left: clamp(0%, calc(var(--p) - (1 - var(--t)) * var(--b) / 2), calc(100% - (1 - var(--t)) * var(--b))); }
132
+ .speech-bubble.speech.tail-top { border-radius: min(var(--r), calc(var(--p) - (1 - var(--t)) * var(--b) / 2)) min(var(--r), calc(100% - var(--p) - (1 - var(--t)) * var(--b) / 2)) var(--r) var(--r) / var(--r); }
133
+ .speech-bubble.speech.tail-top:before { bottom: 99%; left: clamp(0%, calc(var(--p) - (1 - var(--t)) * var(--b) / 2), calc(100% - (1 - var(--t)) * var(--b))); transform: scaleY(-1); }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
134
  .speech-bubble.speech.tail-left { border-radius: var(--r); }
135
+ .speech-bubble.speech.tail-left:before { right: 99%; top: clamp(0%, calc(var(--p) - (1 - var(--t)) * var(--b) / 2), calc(100% - (1 - var(--t)) * var(--b))); transform: rotate(90deg); transform-origin: top right; }
 
 
 
 
 
136
  .speech-bubble.speech.tail-right { border-radius: var(--r); }
137
+ .speech-bubble.speech.tail-right:before { left: 99%; top: clamp(0%, calc(var(--p) - (1 - var(--t)) * var(--b) / 2), calc(100% - (1 - var(--t)) * var(--b))); transform: rotate(-90deg); transform-origin: top left; }
 
 
 
138
 
139
  .speech-bubble.thought { background: white; border: 2px dashed #555; color: #333; border-radius: 50%; }
140
  .speech-bubble.thought::after { display:none; }
 
165
  <span id="fn">No file selected</span>
166
  <button class="submit-btn" onclick="upload()">Generate Comic</button>
167
  <button id="restore-btn" class="restore-btn" onclick="restoreSession()">📂 Restore Unsaved Session</button>
168
+
169
  <div class="loading-view" id="loading-view" style="display:none;">
170
  <div class="loader"></div>
171
  <p id="status-text">Starting...</p>