2026-10-14 11:23:56 +08:00
<!DOCTYPE html>
< html lang = "en" >
< head >
< meta charset = "UTF-8" >
< meta name = "viewport" content = "width=device-width, initial-scale=1.0" >
< title > Cloud budget bridge · Waterfall chart</ title >
< link href = "https://fonts.googleapis.com/css2?family=Instrument+Serif:ital@0;1&family=Geist:wght@400;500;600&family=Geist+Mono:wght@400;500;600&display=swap" rel = "stylesheet" >
< style >
*, * :: before , * :: after { box-sizing : border-box ; margin : 0 ; padding : 0 ; }
: root {
--color-paper : #f5f5f5 ;
--color-ink : #2d3142 ;
--color-muted : #4f5d75 ;
--color-accent : #eb6c36 ;
--font-sans : 'Geist' , system-ui , sans-serif ;
--font-serif : 'Instrument Serif' , serif ;
--font-mono : 'Geist Mono' , ui-monospace , monospace ;
}
body { font-family : var ( -- font - sans ); background : var ( -- color - paper ); color : var ( -- color - ink ); min-height : 100 vh ; display : flex ; align-items : center ; justify-content : center ; padding : 3 rem 2 rem ; }
. frame { max-width : 1200 px ; width : 100 % ; }
. eyebrow { font-family : var ( -- font - mono ); font-size : 0.66 rem ; font-weight : 500 ; letter-spacing : 0.18 em ; text-transform : uppercase ; color : var ( -- color - muted ); margin-bottom : 0.5 rem ; }
h1 { font-family : var ( -- font - serif ); font-size : clamp ( 1.5 rem , 2.4 vw + 0.75 rem , 2 rem ); font-weight : 400 ; letter-spacing : -0.02 em ; line-height : 1.15 ; margin-bottom : 1.5 rem ; }
. diagram-container { width : 100 % ; overflow-x : auto ; }
svg { width : 100 % ; min-width : 760 px ; display : block ; }
</ style >
</ head >
< body >
< div class = "frame" >
< p class = "eyebrow" > Waterfall · Diagram Design</ p >
< h1 > Cloud budget bridge · FY25 → FY26</ h1 >
< div class = "diagram-container" >
< svg viewBox = "0 0 1000 500" xmlns = "http://www.w3.org/2000/svg" role = "img" aria-labelledby = "waterfall-title waterfall-desc" >
< title id = "waterfall-title" > Cloud budget bridge · FY25 → FY26</ title >
< desc id = "waterfall-desc" > Waterfall chart bridging the FY25 cloud budget of 240 thousand dollars a month to the FY26 plan of 236, through headcount growth, reserved-instance savings, new ML workloads, and storage tiering — the largest saving.</ desc >
< defs >
< pattern id = "dots" width = "22" height = "22" patternUnits = "userSpaceOnUse" >
< circle cx = "1" cy = "1" r = "0.9" fill = "rgba(45,49,66,0.10)" />
</ pattern >
</ defs >
< rect width = "100%" height = "100%" fill = "#f5f5f5" />
< rect width = "100%" height = "100%" fill = "url(#dots)" opacity = "0.55" />
<!-- Y-axis rotated label -->
< text transform = "rotate(-90 24 230)" x = "24" y = "230" fill = "#4f5d75" font-size = "7" font-family = "'Geist Mono', monospace" letter-spacing = "0.14em" text-anchor = "middle" > CLOUD SPEND · $K / MO</ text >
<!-- Horizontal gridlines (drawn before bars). Domain 0– 400, y = 420 − 0.95·v -->
< line x1 = "80" y1 = "325" x2 = "960" y2 = "325" stroke = "rgba(45,49,66,0.08)" stroke-width = "0.8" />
< line x1 = "80" y1 = "230" x2 = "960" y2 = "230" stroke = "rgba(45,49,66,0.08)" stroke-width = "0.8" />
< line x1 = "80" y1 = "135" x2 = "960" y2 = "135" stroke = "rgba(45,49,66,0.08)" stroke-width = "0.8" />
< line x1 = "80" y1 = "40" x2 = "960" y2 = "40" stroke = "rgba(45,49,66,0.06)" stroke-width = "0.8" />
<!-- Y-axis line and X-axis baseline (the domain floor: totals anchor here) -->
< line x1 = "80" y1 = "40" x2 = "80" y2 = "420" stroke = "rgba(45,49,66,0.25)" stroke-width = "1" />
< line x1 = "80" y1 = "420" x2 = "960" y2 = "420" stroke = "rgba(45,49,66,0.25)" stroke-width = "1" />
<!-- Y-axis tick labels -->
< text x = "72" y = "329" fill = "#4f5d75" font-size = "8" font-family = "'Geist Mono', monospace" text-anchor = "end" > 100</ text >
< text x = "72" y = "234" fill = "#4f5d75" font-size = "8" font-family = "'Geist Mono', monospace" text-anchor = "end" > 200</ text >
< text x = "72" y = "139" fill = "#4f5d75" font-size = "8" font-family = "'Geist Mono', monospace" text-anchor = "end" > 300</ text >
< text x = "72" y = "44" fill = "#4f5d75" font-size = "8" font-family = "'Geist Mono', monospace" text-anchor = "end" > 400</ text >
<!-- ─── CARRIES (drawn before bars; each transports the running total across a gap at its own level) ─── -->
< line x1 = "208" y1 = "192" x2 = "256" y2 = "192" stroke = "rgba(45,49,66,0.55)" stroke-width = "1" data-carry = "240" />
< line x1 = "352" y1 = "131" x2 = "400" y2 = "131" stroke = "rgba(45,49,66,0.55)" stroke-width = "1" data-carry = "304" />
< line x1 = "496" y1 = "167" x2 = "544" y2 = "167" stroke = "rgba(45,49,66,0.55)" stroke-width = "1" data-carry = "266" />
< line x1 = "640" y1 = "146" x2 = "688" y2 = "146" stroke = "rgba(45,49,66,0.55)" stroke-width = "1" data-carry = "288" />
< line x1 = "784" y1 = "196" x2 = "832" y2 = "196" stroke = "rgba(45,49,66,0.55)" stroke-width = "1" data-carry = "236" />
<!-- ─── BARS (width=96, pitch=144). Running total: 240 → 304 → 266 → 288 → 236 → 236 ─── -->
<!-- FY25 base: total 240, anchored at the floor. y(240)=192, h=228 -->
< rect x = "112" y = "192" width = "96" height = "228" fill = "#f5f5f5" />
< rect x = "112" y = "192" width = "96" height = "228" fill = "rgba(45,49,66,0.08)" stroke = "#2d3142" stroke-width = "1" data-role = "total" data-value = "240" data-name = "FY25 base" />
< text x = "160" y = "184" fill = "#4f5d75" font-size = "8" font-family = "'Geist Mono', monospace" text-anchor = "middle" > 240</ text >
<!-- Headcount: +64 rises 240 → 304. y(304)=131, h=61 -->
< rect x = "256" y = "131" width = "96" height = "61" fill = "#f5f5f5" />
< rect x = "256" y = "131" width = "96" height = "61" fill = "rgba(79,93,117,0.15)" stroke = "#4f5d75" stroke-width = "1" data-role = "delta" data-value = "+64" data-name = "Headcount" />
< text x = "304" y = "123" fill = "#4f5d75" font-size = "8" font-family = "'Geist Mono', monospace" text-anchor = "middle" > +64</ text >
<!-- Reserved instances: − 38 falls 304 → 266. Hollow = decrease. y=131, h=36 -->
< rect x = "400" y = "131" width = "96" height = "36" fill = "#f5f5f5" />
< rect x = "400" y = "131" width = "96" height = "36" fill = "#f5f5f5" stroke = "#4f5d75" stroke-width = "1" data-role = "delta" data-value = "-38" data-name = "Reserved inst." />
< text x = "448" y = "179" fill = "#4f5d75" font-size = "8" font-family = "'Geist Mono', monospace" text-anchor = "middle" > − 38</ text >
<!-- ML workloads: +22 rises 266 → 288. y(288)=146, h=21 -->
< rect x = "544" y = "146" width = "96" height = "21" fill = "#f5f5f5" />
< rect x = "544" y = "146" width = "96" height = "21" fill = "rgba(79,93,117,0.15)" stroke = "#4f5d75" stroke-width = "1" data-role = "delta" data-value = "+22" data-name = "ML workloads" />
< text x = "592" y = "138" fill = "#4f5d75" font-size = "8" font-family = "'Geist Mono', monospace" text-anchor = "middle" > +22</ text >
<!-- Storage tiering FOCAL: − 52 falls 288 → 236 — the largest saving, the story. y=146, h=50 -->
< rect x = "688" y = "146" width = "96" height = "50" fill = "#f5f5f5" />
< rect x = "688" y = "146" width = "96" height = "50" fill = "rgba(235,108,54,0.12)" stroke = "#eb6c36" stroke-width = "1" data-role = "delta" data-value = "-52" data-name = "Storage tiering" />
< text x = "736" y = "208" fill = "#2d3142" font-size = "8" font-family = "'Geist Mono', monospace" text-anchor = "middle" font-weight = "600" > − 52</ text >
<!-- FY26 plan: total 236 = 240 + 64 − 38 + 22 − 52, anchored at the floor. y(236)=196, h=224 -->
< rect x = "832" y = "196" width = "96" height = "224" fill = "#f5f5f5" />
< rect x = "832" y = "196" width = "96" height = "224" fill = "rgba(45,49,66,0.08)" stroke = "#2d3142" stroke-width = "1" data-role = "total" data-value = "236" data-name = "FY26 plan" />
< text x = "880" y = "188" fill = "#4f5d75" font-size = "8" font-family = "'Geist Mono', monospace" text-anchor = "middle" > 236</ text >
<!-- X-axis category labels -->
< text x = "160" y = "440" fill = "#2d3142" font-size = "11" font-weight = "600" font-family = "'Geist', sans-serif" text-anchor = "middle" > FY25 base</ text >
< text x = "304" y = "440" fill = "#2d3142" font-size = "11" font-weight = "600" font-family = "'Geist', sans-serif" text-anchor = "middle" > Headcount</ text >
< text x = "448" y = "440" fill = "#2d3142" font-size = "11" font-weight = "600" font-family = "'Geist', sans-serif" text-anchor = "middle" > Reserved inst.</ text >
< text x = "592" y = "440" fill = "#2d3142" font-size = "11" font-weight = "600" font-family = "'Geist', sans-serif" text-anchor = "middle" > ML workloads</ text >
< text x = "736" y = "440" fill = "#2d3142" font-size = "11" font-weight = "600" font-family = "'Geist', sans-serif" text-anchor = "middle" > Storage tiering</ text >
< text x = "880" y = "440" fill = "#2d3142" font-size = "11" font-weight = "600" font-family = "'Geist', sans-serif" text-anchor = "middle" > FY26 plan</ text >
<!-- Legend -->
< line x1 = "40" y1 = "462" x2 = "960" y2 = "462" stroke = "rgba(45,49,66,0.10)" stroke-width = "0.8" />
< text x = "40" y = "478" fill = "#4f5d75" font-size = "8" font-family = "'Geist Mono', monospace" letter-spacing = "0.18em" > LEGEND</ text >
< rect x = "40" y = "488" width = "16" height = "10" rx = "2" fill = "rgba(45,49,66,0.08)" stroke = "#2d3142" stroke-width = "1" />
< text x = "64" y = "497" fill = "#4f5d75" font-size = "8.5" font-family = "'Geist', sans-serif" > Start / end total</ text >
< rect x = "200" y = "488" width = "16" height = "10" rx = "2" fill = "rgba(79,93,117,0.15)" stroke = "#4f5d75" stroke-width = "1" />
< text x = "224" y = "497" fill = "#4f5d75" font-size = "8.5" font-family = "'Geist', sans-serif" > Cost added</ text >
< rect x = "340" y = "488" width = "16" height = "10" rx = "2" fill = "#f5f5f5" stroke = "#4f5d75" stroke-width = "1" />
< text x = "364" y = "497" fill = "#4f5d75" font-size = "8.5" font-family = "'Geist', sans-serif" > Cost removed</ text >
< rect x = "480" y = "488" width = "16" height = "10" rx = "2" fill = "rgba(235,108,54,0.12)" stroke = "#eb6c36" stroke-width = "1" />
< text x = "504" y = "497" fill = "#4f5d75" font-size = "8.5" font-family = "'Geist', sans-serif" > Storage tiering · largest saving</ text >
</ svg >
</ div >
</ div >
</ body >
</ html >