Spaces:
Sleeping
Sleeping
TOTEM Studio commited on
Commit ·
c7d94b0
1
Parent(s): d369b66
fix gauge gradient: multi-segment arcs (no defs), hero height + signal wrap sizing
Browse files
app.py
CHANGED
|
@@ -368,11 +368,11 @@ TOTEM_CSS = """
|
|
| 368 |
|
| 369 |
.totem-hero {
|
| 370 |
position: relative;
|
| 371 |
-
padding:
|
| 372 |
overflow: hidden;
|
| 373 |
border: 1px solid rgba(242, 193, 78, 0.35);
|
| 374 |
background: #06091e;
|
| 375 |
-
min-height:
|
| 376 |
}
|
| 377 |
|
| 378 |
.totem-hero::after {
|
|
@@ -413,8 +413,9 @@ TOTEM_CSS = """
|
|
| 413 |
}
|
| 414 |
|
| 415 |
.totem-hero-right {
|
| 416 |
-
flex: 0 0
|
| 417 |
display: flex;
|
|
|
|
| 418 |
align-items: center;
|
| 419 |
justify-content: center;
|
| 420 |
}
|
|
@@ -424,8 +425,8 @@ TOTEM_CSS = """
|
|
| 424 |
right: auto;
|
| 425 |
top: auto;
|
| 426 |
transform: none;
|
| 427 |
-
width:
|
| 428 |
-
height:
|
| 429 |
}
|
| 430 |
|
| 431 |
.totem-signal {
|
|
@@ -1323,41 +1324,44 @@ def render_topbar(state: dict) -> str:
|
|
| 1323 |
|
| 1324 |
def render_signal_gauge(value: int) -> str:
|
| 1325 |
clamped = max(0, min(100, int(value or 0)))
|
| 1326 |
-
|
| 1327 |
-
|
| 1328 |
-
|
| 1329 |
-
#
|
| 1330 |
-
|
| 1331 |
-
|
| 1332 |
-
|
| 1333 |
-
|
| 1334 |
-
|
| 1335 |
-
|
| 1336 |
-
|
| 1337 |
-
|
| 1338 |
-
|
| 1339 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1340 |
return f"""
|
| 1341 |
-
<div class="totem-signal-wrap
|
| 1342 |
<svg class="totem-signal" viewBox="0 0 160 160" role="img" aria-label="TOTEM Signal {clamped} percent">
|
| 1343 |
-
<defs>
|
| 1344 |
-
<linearGradient id="gaugeGradient" x1="0%" y1="0%" x2="100%" y2="100%">
|
| 1345 |
-
<stop offset="0%" stop-color="#8A4DFF"/>
|
| 1346 |
-
<stop offset="40%" stop-color="#39C9FF"/>
|
| 1347 |
-
<stop offset="75%" stop-color="#22B573"/>
|
| 1348 |
-
<stop offset="100%" stop-color="#F2C14E"/>
|
| 1349 |
-
</linearGradient>
|
| 1350 |
-
</defs>
|
| 1351 |
<!-- Outer decorative ring -->
|
| 1352 |
<circle class="signal-outer-ring" cx="80" cy="80" r="76"></circle>
|
| 1353 |
<!-- Track -->
|
| 1354 |
<circle class="signal-track" cx="80" cy="80" r="68"></circle>
|
| 1355 |
-
<!--
|
| 1356 |
-
|
| 1357 |
-
class="signal-progress"
|
| 1358 |
-
cx="80" cy="80" r="68"
|
| 1359 |
-
style="stroke-dasharray:{circumference:.2f};stroke-dashoffset:{dash_offset:.2f};"
|
| 1360 |
-
></circle>
|
| 1361 |
<!-- Inner radar rings -->
|
| 1362 |
<circle class="signal-inner-ring" cx="80" cy="80" r="52"></circle>
|
| 1363 |
<circle class="signal-inner-ring" cx="80" cy="80" r="40"></circle>
|
|
|
|
| 368 |
|
| 369 |
.totem-hero {
|
| 370 |
position: relative;
|
| 371 |
+
padding: 44px 52px 52px 52px;
|
| 372 |
overflow: hidden;
|
| 373 |
border: 1px solid rgba(242, 193, 78, 0.35);
|
| 374 |
background: #06091e;
|
| 375 |
+
min-height: 240px;
|
| 376 |
}
|
| 377 |
|
| 378 |
.totem-hero::after {
|
|
|
|
| 413 |
}
|
| 414 |
|
| 415 |
.totem-hero-right {
|
| 416 |
+
flex: 0 0 200px;
|
| 417 |
display: flex;
|
| 418 |
+
flex-direction: column;
|
| 419 |
align-items: center;
|
| 420 |
justify-content: center;
|
| 421 |
}
|
|
|
|
| 425 |
right: auto;
|
| 426 |
top: auto;
|
| 427 |
transform: none;
|
| 428 |
+
width: 170px;
|
| 429 |
+
height: 170px;
|
| 430 |
}
|
| 431 |
|
| 432 |
.totem-signal {
|
|
|
|
| 1324 |
|
| 1325 |
def render_signal_gauge(value: int) -> str:
|
| 1326 |
clamped = max(0, min(100, int(value or 0)))
|
| 1327 |
+
circ = 427.26
|
| 1328 |
+
filled = circ * (clamped / 100.0)
|
| 1329 |
+
# Segment colours: violet, cyan, emerald, gold - each covers 25% of circumference
|
| 1330 |
+
# We layer 4 coloured arcs masked by dasharray to fake a gradient
|
| 1331 |
+
seg = circ / 4 # 106.815 per segment
|
| 1332 |
+
segs = [
|
| 1333 |
+
("#8A4DFF", 0),
|
| 1334 |
+
("#39C9FF", 1),
|
| 1335 |
+
("#22B573", 2),
|
| 1336 |
+
("#F2C14E", 3),
|
| 1337 |
+
]
|
| 1338 |
+
arc_elements = []
|
| 1339 |
+
for color, idx in segs:
|
| 1340 |
+
seg_start = idx * seg
|
| 1341 |
+
seg_end = (idx + 1) * seg
|
| 1342 |
+
if filled <= seg_start:
|
| 1343 |
+
break # nothing to draw for this segment
|
| 1344 |
+
seg_filled = min(filled - seg_start, seg)
|
| 1345 |
+
# offset = circ - seg_filled, rotated so this segment starts at the right angle
|
| 1346 |
+
rotate_deg = -90 + (seg_start / circ) * 360
|
| 1347 |
+
arc_elements.append(
|
| 1348 |
+
f'<circle cx="80" cy="80" r="68" fill="none" stroke="{color}" '
|
| 1349 |
+
f'stroke-width="7" stroke-linecap="round" '
|
| 1350 |
+
f'stroke-dasharray="{seg_filled:.2f} {circ:.2f}" '
|
| 1351 |
+
f'stroke-dashoffset="0" '
|
| 1352 |
+
f'style="transform:rotate({rotate_deg:.1f}deg);transform-origin:80px 80px;'
|
| 1353 |
+
f'filter:drop-shadow(0 0 4px {color}88);" />'
|
| 1354 |
+
)
|
| 1355 |
+
arcs_html = "\n ".join(arc_elements)
|
| 1356 |
return f"""
|
| 1357 |
+
<div class="totem-signal-wrap">
|
| 1358 |
<svg class="totem-signal" viewBox="0 0 160 160" role="img" aria-label="TOTEM Signal {clamped} percent">
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1359 |
<!-- Outer decorative ring -->
|
| 1360 |
<circle class="signal-outer-ring" cx="80" cy="80" r="76"></circle>
|
| 1361 |
<!-- Track -->
|
| 1362 |
<circle class="signal-track" cx="80" cy="80" r="68"></circle>
|
| 1363 |
+
<!-- Gradient arc segments -->
|
| 1364 |
+
{arcs_html}
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1365 |
<!-- Inner radar rings -->
|
| 1366 |
<circle class="signal-inner-ring" cx="80" cy="80" r="52"></circle>
|
| 1367 |
<circle class="signal-inner-ring" cx="80" cy="80" r="40"></circle>
|