feat: add animated SVG visuals to rFlows landing page
Three inline CSS/SVG animations demonstrate key concepts: - Hero: 3-funnel flow diagram with animated particles, threshold lines, rising/falling fill levels, and flowing dashed edges with % labels - How It Works: Sankey-style river view with multiple flowing bands showing Revenue/Grants splitting to Team A/B/Reserve - Funnel Model: animated water level cycling through overflow/healthy/ critical zones with overflow arrow that appears at peak fill All animations are pure SVG/CSS (zero external assets), responsive, and hidden on screens <480px. Replaces the static funnel metaphor text block with a side-by-side animated funnel + zone descriptions. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
aab0f42ef5
commit
e954386489
|
|
@ -5,6 +5,57 @@
|
|||
*/
|
||||
export function renderLanding(): string {
|
||||
return `
|
||||
<style>
|
||||
/* ── Landing animations ── */
|
||||
@keyframes rf-flow-particle {
|
||||
0% { offset-distance: 0%; opacity: 0; }
|
||||
10% { opacity: 1; }
|
||||
90% { opacity: 1; }
|
||||
100% { offset-distance: 100%; opacity: 0; }
|
||||
}
|
||||
@keyframes rf-fill-cycle {
|
||||
0% { height: 15%; }
|
||||
25% { height: 85%; }
|
||||
50% { height: 60%; }
|
||||
75% { height: 30%; }
|
||||
100% { height: 15%; }
|
||||
}
|
||||
@keyframes rf-pulse {
|
||||
0%, 100% { opacity: 0.4; }
|
||||
50% { opacity: 1; }
|
||||
}
|
||||
@keyframes rf-river-flow {
|
||||
0% { stroke-dashoffset: 40; }
|
||||
100% { stroke-dashoffset: 0; }
|
||||
}
|
||||
@keyframes rf-glow {
|
||||
0%, 100% { filter: drop-shadow(0 0 4px rgba(251,191,36,0.3)); }
|
||||
50% { filter: drop-shadow(0 0 12px rgba(251,191,36,0.6)); }
|
||||
}
|
||||
@keyframes rf-edge-flow {
|
||||
0% { stroke-dashoffset: 20; }
|
||||
100% { stroke-dashoffset: 0; }
|
||||
}
|
||||
@keyframes rf-hero-float {
|
||||
0%, 100% { transform: translateY(0); }
|
||||
50% { transform: translateY(-6px); }
|
||||
}
|
||||
.rf-anim-wrap {
|
||||
max-width: 700px;
|
||||
margin: 2rem auto 0;
|
||||
border-radius: 1rem;
|
||||
overflow: hidden;
|
||||
border: 1px solid rgba(51,65,85,0.3);
|
||||
background: rgba(15,23,42,0.4);
|
||||
}
|
||||
.rf-anim-wrap svg { display: block; width: 100%; height: auto; }
|
||||
|
||||
/* Responsive: hide animations on very small screens */
|
||||
@media (max-width: 480px) {
|
||||
.rf-anim-wrap { display: none; }
|
||||
}
|
||||
</style>
|
||||
|
||||
<!-- Hero -->
|
||||
<div class="rl-hero">
|
||||
<span class="rl-tagline">rFlows</span>
|
||||
|
|
@ -16,7 +67,107 @@ export function renderLanding(): string {
|
|||
<strong style="color:#e2e8f0">automatic overflow routing</strong>, and
|
||||
<strong style="color:#e2e8f0">proportional flow visualization</strong> — then save it to your space.
|
||||
</p>
|
||||
<div class="rl-cta-row">
|
||||
|
||||
<!-- Animated hero diagram: 3 funnels with flowing particles -->
|
||||
<div class="rf-anim-wrap" style="animation: rf-hero-float 6s ease-in-out infinite;border:1px solid rgba(251,191,36,0.15);background:rgba(15,23,42,0.6)">
|
||||
<svg viewBox="0 0 700 260" xmlns="http://www.w3.org/2000/svg">
|
||||
<defs>
|
||||
<!-- Funnel gradients -->
|
||||
<linearGradient id="rf-g-amber" x1="0" y1="0" x2="0" y2="1">
|
||||
<stop offset="0%" stop-color="#fbbf24" stop-opacity="0.3"/>
|
||||
<stop offset="100%" stop-color="#f59e0b" stop-opacity="0.08"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="rf-g-green" x1="0" y1="0" x2="0" y2="1">
|
||||
<stop offset="0%" stop-color="#34d399" stop-opacity="0.3"/>
|
||||
<stop offset="100%" stop-color="#10b981" stop-opacity="0.08"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="rf-g-blue" x1="0" y1="0" x2="0" y2="1">
|
||||
<stop offset="0%" stop-color="#60a5fa" stop-opacity="0.3"/>
|
||||
<stop offset="100%" stop-color="#3b82f6" stop-opacity="0.08"/>
|
||||
</linearGradient>
|
||||
<!-- Flow paths for particles -->
|
||||
<path id="rf-path1" d="M 230 100 C 280 100, 300 100, 330 100" fill="none"/>
|
||||
<path id="rf-path2" d="M 470 100 C 520 100, 540 130, 560 160" fill="none"/>
|
||||
<path id="rf-path3" d="M 230 140 C 260 160, 280 190, 300 210" fill="none"/>
|
||||
</defs>
|
||||
|
||||
<!-- Source funnel -->
|
||||
<g>
|
||||
<rect x="80" y="40" width="150" height="180" rx="12" fill="url(#rf-g-amber)" stroke="#fbbf2440" stroke-width="1"/>
|
||||
<!-- Threshold lines -->
|
||||
<line x1="90" y1="80" x2="220" y2="80" stroke="#fbbf24" stroke-width="1" stroke-dasharray="4 3" opacity="0.5"/>
|
||||
<line x1="90" y1="160" x2="220" y2="160" stroke="#ef4444" stroke-width="1" stroke-dasharray="4 3" opacity="0.5"/>
|
||||
<!-- Animated fill -->
|
||||
<rect x="88" y="60" width="134" height="152" rx="8" fill="#fbbf24" opacity="0.12">
|
||||
<animate attributeName="y" values="60;100;60;140;60" dur="8s" repeatCount="indefinite"/>
|
||||
<animate attributeName="height" values="152;112;152;72;152" dur="8s" repeatCount="indefinite"/>
|
||||
</rect>
|
||||
<text x="155" y="35" text-anchor="middle" fill="#fbbf24" font-size="11" font-weight="600" font-family="system-ui">Source Pool</text>
|
||||
<text x="155" y="135" text-anchor="middle" fill="#fbbf24" font-size="22" opacity="0.7">🌊</text>
|
||||
</g>
|
||||
|
||||
<!-- Middle funnel -->
|
||||
<g>
|
||||
<rect x="320" y="40" width="150" height="180" rx="12" fill="url(#rf-g-green)" stroke="#34d39940" stroke-width="1"/>
|
||||
<line x1="330" y1="80" x2="460" y2="80" stroke="#34d399" stroke-width="1" stroke-dasharray="4 3" opacity="0.5"/>
|
||||
<line x1="330" y1="160" x2="460" y2="160" stroke="#ef4444" stroke-width="1" stroke-dasharray="4 3" opacity="0.5"/>
|
||||
<rect x="328" y="90" width="134" height="122" rx="8" fill="#34d399" opacity="0.12">
|
||||
<animate attributeName="y" values="90;70;90;110;90" dur="8s" begin="1s" repeatCount="indefinite"/>
|
||||
<animate attributeName="height" values="122;142;122;102;122" dur="8s" begin="1s" repeatCount="indefinite"/>
|
||||
</rect>
|
||||
<text x="395" y="35" text-anchor="middle" fill="#34d399" font-size="11" font-weight="600" font-family="system-ui">Operations</text>
|
||||
<text x="395" y="135" text-anchor="middle" fill="#34d399" font-size="22" opacity="0.7">⚙️</text>
|
||||
</g>
|
||||
|
||||
<!-- Outcome funnel -->
|
||||
<g>
|
||||
<rect x="500" y="120" width="130" height="120" rx="12" fill="url(#rf-g-blue)" stroke="#60a5fa40" stroke-width="1"/>
|
||||
<rect x="508" y="140" width="114" height="92" rx="8" fill="#60a5fa" opacity="0.12">
|
||||
<animate attributeName="y" values="170;140;170;190;170" dur="8s" begin="2s" repeatCount="indefinite"/>
|
||||
<animate attributeName="height" values="62;92;62;42;62" dur="8s" begin="2s" repeatCount="indefinite"/>
|
||||
</rect>
|
||||
<text x="565" y="115" text-anchor="middle" fill="#60a5fa" font-size="11" font-weight="600" font-family="system-ui">Outcomes</text>
|
||||
<text x="565" y="185" text-anchor="middle" fill="#60a5fa" font-size="20" opacity="0.7">🎯</text>
|
||||
</g>
|
||||
|
||||
<!-- Overflow edge: Source → Operations -->
|
||||
<path d="M 230 90 C 265 90, 290 90, 320 90" fill="none" stroke="#fbbf24" stroke-width="3" opacity="0.35" stroke-dasharray="6 4">
|
||||
<animate attributeName="stroke-dashoffset" values="20;0" dur="1.5s" repeatCount="indefinite"/>
|
||||
</path>
|
||||
<text x="275" y="82" text-anchor="middle" fill="#fbbf24" font-size="9" font-weight="600" opacity="0.7">40%</text>
|
||||
<!-- Particles -->
|
||||
<circle r="3" fill="#fbbf24" opacity="0">
|
||||
<animateMotion dur="2s" repeatCount="indefinite" begin="0s"><mpath href="#rf-path1"/></animateMotion>
|
||||
<animate attributeName="opacity" values="0;1;1;0" dur="2s" repeatCount="indefinite" begin="0s"/>
|
||||
</circle>
|
||||
<circle r="2.5" fill="#fbbf24" opacity="0">
|
||||
<animateMotion dur="2s" repeatCount="indefinite" begin="0.7s"><mpath href="#rf-path1"/></animateMotion>
|
||||
<animate attributeName="opacity" values="0;1;1;0" dur="2s" repeatCount="indefinite" begin="0.7s"/>
|
||||
</circle>
|
||||
|
||||
<!-- Spending edge: Operations → Outcomes -->
|
||||
<path d="M 470 130 C 490 140, 500 155, 510 170" fill="none" stroke="#34d399" stroke-width="2.5" opacity="0.35" stroke-dasharray="5 4">
|
||||
<animate attributeName="stroke-dashoffset" values="18;0" dur="1.5s" repeatCount="indefinite"/>
|
||||
</path>
|
||||
<text x="500" y="140" text-anchor="middle" fill="#34d399" font-size="9" font-weight="600" opacity="0.7">60%</text>
|
||||
<circle r="2.5" fill="#34d399" opacity="0">
|
||||
<animateMotion dur="2.5s" repeatCount="indefinite" begin="0.3s"><mpath href="#rf-path2"/></animateMotion>
|
||||
<animate attributeName="opacity" values="0;1;1;0" dur="2.5s" repeatCount="indefinite" begin="0.3s"/>
|
||||
</circle>
|
||||
|
||||
<!-- Spending edge: Source → (bottom) -->
|
||||
<path d="M 180 220 L 180 250" fill="none" stroke="#f59e0b" stroke-width="2" opacity="0.25" stroke-dasharray="4 3">
|
||||
<animate attributeName="stroke-dashoffset" values="14;0" dur="1.5s" repeatCount="indefinite"/>
|
||||
</path>
|
||||
<text x="195" y="245" fill="#f59e0b" font-size="8" opacity="0.5">spending</text>
|
||||
|
||||
<!-- Labels -->
|
||||
<text x="76" y="82" text-anchor="end" fill="#fbbf24" font-size="8" opacity="0.5">max</text>
|
||||
<text x="76" y="162" text-anchor="end" fill="#ef4444" font-size="8" opacity="0.5">min</text>
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
<div class="rl-cta-row" style="margin-top:2rem">
|
||||
<a href="https://demo.rspace.online/rflows" class="rl-cta-primary" id="ml-primary">
|
||||
Try the Demo →
|
||||
</a>
|
||||
|
|
@ -77,6 +228,75 @@ export function renderLanding(): string {
|
|||
<p>Watch funds flow through your system in real-time. Adjust allocations with +/- controls on each edge. Save the flow to your space when you're happy with it.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Animated river visualization -->
|
||||
<div class="rf-anim-wrap" style="margin-top:2.5rem;border-color:rgba(52,211,153,0.15)">
|
||||
<svg viewBox="0 0 700 180" xmlns="http://www.w3.org/2000/svg">
|
||||
<defs>
|
||||
<linearGradient id="rf-river-g1" x1="0" y1="0" x2="1" y2="0">
|
||||
<stop offset="0%" stop-color="#fbbf24" stop-opacity="0.6"/>
|
||||
<stop offset="100%" stop-color="#34d399" stop-opacity="0.6"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="rf-river-g2" x1="0" y1="0" x2="1" y2="0">
|
||||
<stop offset="0%" stop-color="#34d399" stop-opacity="0.5"/>
|
||||
<stop offset="100%" stop-color="#60a5fa" stop-opacity="0.5"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="rf-river-g3" x1="0" y1="0" x2="1" y2="0">
|
||||
<stop offset="0%" stop-color="#34d399" stop-opacity="0.4"/>
|
||||
<stop offset="100%" stop-color="#a78bfa" stop-opacity="0.4"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
|
||||
<!-- Source labels -->
|
||||
<text x="30" y="55" fill="#fbbf24" font-size="10" font-weight="600" font-family="system-ui">Revenue</text>
|
||||
<text x="30" y="115" fill="#34d399" font-size="10" font-weight="600" font-family="system-ui">Grants</text>
|
||||
|
||||
<!-- Destination labels -->
|
||||
<text x="620" y="40" fill="#60a5fa" font-size="10" font-weight="600" font-family="system-ui">Team A</text>
|
||||
<text x="620" y="95" fill="#a78bfa" font-size="10" font-weight="600" font-family="system-ui">Team B</text>
|
||||
<text x="620" y="150" fill="#34d399" font-size="10" font-weight="600" font-family="system-ui">Reserve</text>
|
||||
|
||||
<!-- River bands — wide flowing Bezier paths with dashed animation -->
|
||||
<!-- Revenue → Team A (wide band) -->
|
||||
<path d="M 90 45 C 250 45, 400 30, 610 35" fill="none" stroke="url(#rf-river-g2)" stroke-width="18" stroke-linecap="round" opacity="0.5" stroke-dasharray="8 12">
|
||||
<animate attributeName="stroke-dashoffset" values="40;0" dur="3s" repeatCount="indefinite"/>
|
||||
</path>
|
||||
|
||||
<!-- Revenue → Team B (medium band) -->
|
||||
<path d="M 90 55 C 250 60, 400 80, 610 90" fill="none" stroke="url(#rf-river-g3)" stroke-width="10" stroke-linecap="round" opacity="0.4" stroke-dasharray="6 10">
|
||||
<animate attributeName="stroke-dashoffset" values="32;0" dur="3.5s" repeatCount="indefinite"/>
|
||||
</path>
|
||||
|
||||
<!-- Grants → Team B -->
|
||||
<path d="M 90 110 C 250 108, 400 95, 610 92" fill="none" stroke="url(#rf-river-g3)" stroke-width="8" stroke-linecap="round" opacity="0.35" stroke-dasharray="5 8">
|
||||
<animate attributeName="stroke-dashoffset" values="26;0" dur="4s" repeatCount="indefinite"/>
|
||||
</path>
|
||||
|
||||
<!-- Grants → Reserve -->
|
||||
<path d="M 90 118 C 250 125, 400 140, 610 145" fill="none" stroke="#34d399" stroke-width="14" stroke-linecap="round" opacity="0.3" stroke-dasharray="7 10">
|
||||
<animate attributeName="stroke-dashoffset" values="34;0" dur="3.2s" repeatCount="indefinite"/>
|
||||
</path>
|
||||
|
||||
<!-- Flow particles along revenue path -->
|
||||
<circle r="3" fill="#fbbf24" opacity="0.8">
|
||||
<animate attributeName="cx" values="90;610" dur="4s" repeatCount="indefinite"/>
|
||||
<animate attributeName="cy" values="45;35" dur="4s" repeatCount="indefinite"/>
|
||||
<animate attributeName="opacity" values="0;0.9;0.9;0" dur="4s" repeatCount="indefinite"/>
|
||||
</circle>
|
||||
<circle r="2.5" fill="#34d399" opacity="0.7">
|
||||
<animate attributeName="cx" values="90;610" dur="5s" begin="1s" repeatCount="indefinite"/>
|
||||
<animate attributeName="cy" values="118;145" dur="5s" begin="1s" repeatCount="indefinite"/>
|
||||
<animate attributeName="opacity" values="0;0.8;0.8;0" dur="5s" begin="1s" repeatCount="indefinite"/>
|
||||
</circle>
|
||||
|
||||
<!-- Subtle grid lines -->
|
||||
<line x1="90" y1="10" x2="90" y2="170" stroke="#334155" stroke-width="0.5" opacity="0.3"/>
|
||||
<line x1="610" y1="10" x2="610" y2="170" stroke="#334155" stroke-width="0.5" opacity="0.3"/>
|
||||
|
||||
<!-- Title -->
|
||||
<text x="350" y="174" text-anchor="middle" fill="#64748b" font-size="9" font-family="system-ui">River view — all flows from source to outcome</text>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
|
|
@ -119,36 +339,90 @@ export function renderLanding(): string {
|
|||
<div class="rl-container">
|
||||
<h2 class="rl-heading" style="text-align:center">The Funnel Model</h2>
|
||||
<p class="rl-subtext" style="text-align:center">Every funding pool is a funnel with three zones. Thresholds trigger automatic behavior.</p>
|
||||
<div style="max-width:32rem;margin:2rem auto 0;display:grid;gap:0;font-size:0.875rem;text-align:center">
|
||||
|
||||
<!-- Overflow -->
|
||||
<div style="background:rgba(245,158,11,0.08);border:1px solid rgba(245,158,11,0.25);border-radius:0.75rem 0.75rem 0 0;padding:1rem 1.5rem">
|
||||
<div style="font-weight:700;color:#fbbf24;font-size:0.95rem">OVERFLOW</div>
|
||||
<div style="font-size:0.78rem;color:#fcd34d;margin-top:0.25rem">Above max — excess redistributes to connected funnels</div>
|
||||
<div style="display:flex;gap:2rem;align-items:flex-start;justify-content:center;flex-wrap:wrap;margin-top:2rem">
|
||||
<!-- Animated funnel SVG -->
|
||||
<div class="rf-anim-wrap" style="max-width:280px;flex:0 0 auto;border-color:rgba(251,191,36,0.15)">
|
||||
<svg viewBox="0 0 200 280" xmlns="http://www.w3.org/2000/svg">
|
||||
<!-- Funnel body -->
|
||||
<rect x="30" y="20" width="140" height="240" rx="14" fill="none" stroke="#334155" stroke-width="1.5"/>
|
||||
|
||||
<!-- Zone backgrounds -->
|
||||
<rect x="32" y="22" width="136" height="70" rx="12" fill="#fbbf24" opacity="0.06"/>
|
||||
<rect x="32" y="92" width="136" height="90" fill="#34d399" opacity="0.06"/>
|
||||
<rect x="32" y="182" width="136" height="76" rx="12" fill="#475569" opacity="0.08"/>
|
||||
|
||||
<!-- Animated water fill -->
|
||||
<clipPath id="rf-funnel-clip"><rect x="32" y="22" width="136" height="236" rx="12"/></clipPath>
|
||||
<g clip-path="url(#rf-funnel-clip)">
|
||||
<!-- Water body -->
|
||||
<rect x="32" width="136" height="200" fill="#3b82f6" opacity="0.15">
|
||||
<animate attributeName="y" values="120;40;80;160;120" dur="10s" repeatCount="indefinite"/>
|
||||
</rect>
|
||||
<!-- Water surface shimmer -->
|
||||
<rect x="32" width="136" height="4" fill="#60a5fa" opacity="0.3">
|
||||
<animate attributeName="y" values="120;40;80;160;120" dur="10s" repeatCount="indefinite"/>
|
||||
</rect>
|
||||
</g>
|
||||
|
||||
<!-- Threshold lines -->
|
||||
<line x1="28" y1="92" x2="172" y2="92" stroke="#fbbf24" stroke-width="2" stroke-dasharray="6 4"/>
|
||||
<line x1="28" y1="182" x2="172" y2="182" stroke="#ef4444" stroke-width="2" stroke-dasharray="6 4"/>
|
||||
|
||||
<!-- Zone labels -->
|
||||
<text x="100" y="58" text-anchor="middle" fill="#fbbf24" font-size="11" font-weight="700" font-family="system-ui">OVERFLOW</text>
|
||||
<text x="100" y="72" text-anchor="middle" fill="#fbbf24" font-size="8" opacity="0.6" font-family="system-ui">excess redistributes</text>
|
||||
|
||||
<text x="100" y="138" text-anchor="middle" fill="#34d399" font-size="11" font-weight="700" font-family="system-ui">HEALTHY</text>
|
||||
<text x="100" y="152" text-anchor="middle" fill="#34d399" font-size="8" opacity="0.6" font-family="system-ui">normal flow rate</text>
|
||||
|
||||
<text x="100" y="218" text-anchor="middle" fill="#f87171" font-size="11" font-weight="700" font-family="system-ui">CRITICAL</text>
|
||||
<text x="100" y="232" text-anchor="middle" fill="#f87171" font-size="8" opacity="0.6" font-family="system-ui">outflow restricted</text>
|
||||
|
||||
<!-- Threshold labels -->
|
||||
<text x="180" y="96" fill="#fbbf24" font-size="9" font-weight="600" font-family="system-ui">MAX</text>
|
||||
<text x="180" y="186" fill="#ef4444" font-size="9" font-weight="600" font-family="system-ui">MIN</text>
|
||||
|
||||
<!-- Overflow arrow (appears when high) -->
|
||||
<g opacity="0">
|
||||
<animate attributeName="opacity" values="0;0;0.7;0;0" dur="10s" repeatCount="indefinite"/>
|
||||
<path d="M 170 55 L 195 55" stroke="#fbbf24" stroke-width="2" fill="none" marker-end="none"/>
|
||||
<polygon points="192,50 200,55 192,60" fill="#fbbf24"/>
|
||||
<text x="172" y="48" fill="#fbbf24" font-size="7" font-family="system-ui">overflow</text>
|
||||
</g>
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
<!-- Max line -->
|
||||
<div style="border-bottom:2px dashed rgba(245,158,11,0.4);padding:0.2rem 0;font-size:0.7rem;font-weight:700;color:#f59e0b;background:rgba(245,158,11,0.04)">
|
||||
MAX THRESHOLD
|
||||
<!-- Text description alongside -->
|
||||
<div style="max-width:22rem;flex:1 1 18rem;padding-top:0.5rem">
|
||||
<div style="margin-bottom:1.5rem">
|
||||
<div style="display:flex;align-items:center;gap:0.5rem;margin-bottom:0.4rem">
|
||||
<span style="width:12px;height:12px;border-radius:3px;background:#fbbf24;display:inline-block"></span>
|
||||
<strong style="color:#fbbf24;font-size:0.95rem">Overflow Zone</strong>
|
||||
</div>
|
||||
<p style="font-size:0.85rem;color:var(--rs-text-secondary,#94a3b8);line-height:1.5">
|
||||
When funds exceed the max threshold, the excess automatically redistributes to connected funnels via overflow edges.
|
||||
</p>
|
||||
</div>
|
||||
<div style="margin-bottom:1.5rem">
|
||||
<div style="display:flex;align-items:center;gap:0.5rem;margin-bottom:0.4rem">
|
||||
<span style="width:12px;height:12px;border-radius:3px;background:#34d399;display:inline-block"></span>
|
||||
<strong style="color:#34d399;font-size:0.95rem">Healthy Zone</strong>
|
||||
</div>
|
||||
<p style="font-size:0.85rem;color:var(--rs-text-secondary,#94a3b8);line-height:1.5">
|
||||
Between min and max, the funnel operates normally. All outflow edges run at their configured allocation rates.
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<div style="display:flex;align-items:center;gap:0.5rem;margin-bottom:0.4rem">
|
||||
<span style="width:12px;height:12px;border-radius:3px;background:#f87171;display:inline-block"></span>
|
||||
<strong style="color:#f87171;font-size:0.95rem">Critical Zone</strong>
|
||||
</div>
|
||||
<p style="font-size:0.85rem;color:var(--rs-text-secondary,#94a3b8);line-height:1.5">
|
||||
Below the min threshold, outflow is restricted to protect essential reserves. The funnel enters conservation mode.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Healthy -->
|
||||
<div style="background:rgba(16,185,129,0.08);border-left:1px solid rgba(16,185,129,0.25);border-right:1px solid rgba(16,185,129,0.25);padding:1.25rem 1.5rem">
|
||||
<div style="font-weight:700;color:#34d399;font-size:0.95rem">HEALTHY</div>
|
||||
<div style="font-size:0.78rem;color:#6ee7b7;margin-top:0.25rem">Full flow rate — balanced operations, normal outflow</div>
|
||||
</div>
|
||||
|
||||
<!-- Min line -->
|
||||
<div style="border-bottom:2px dashed rgba(239,68,68,0.4);padding:0.2rem 0;font-size:0.7rem;font-weight:700;color:#ef4444;background:rgba(239,68,68,0.04)">
|
||||
MIN THRESHOLD
|
||||
</div>
|
||||
|
||||
<!-- Critical -->
|
||||
<div style="background:rgba(51,65,85,0.2);border:1px solid rgba(71,85,105,0.25);border-radius:0 0 0.75rem 0.75rem;padding:1rem 1.5rem">
|
||||
<div style="font-weight:700;color:#f87171;font-size:0.95rem">CRITICAL</div>
|
||||
<div style="font-size:0.78rem;color:#fca5a5;margin-top:0.25rem">Below min — outflow restricted, conservation mode</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
|
|
|||
Loading…
Reference in New Issue