diff --git a/padelnomics/src/padelnomics/planner/templates/partials/scenario_list.html b/padelnomics/src/padelnomics/planner/templates/partials/scenario_list.html index 354df81..a5874ae 100644 --- a/padelnomics/src/padelnomics/planner/templates/partials/scenario_list.html +++ b/padelnomics/src/padelnomics/planner/templates/partials/scenario_list.html @@ -9,12 +9,12 @@
No saved scenarios yet. Use the Save button to store your current plan.
+No saved scenarios yet. Use the Save button to store your current plan.
{% endif %} diff --git a/padelnomics/src/padelnomics/static/css/custom.css b/padelnomics/src/padelnomics/static/css/custom.css index 74b0f45..93a56e9 100644 --- a/padelnomics/src/padelnomics/static/css/custom.css +++ b/padelnomics/src/padelnomics/static/css/custom.css @@ -1,39 +1,55 @@ -/* Padelnomics — Pico CSS brand overrides */ +/* Padelnomics — Court Tech brand overrides for Pico CSS */ :root[data-theme="dark"] { - /* Background layers */ - --pico-background-color: #0b0f14; - --pico-card-background-color: #111820; - --pico-card-sectioning-background-color: #171f2a; + /* Background layers — Deep Navy family */ + --pico-background-color: #0F172A; + --pico-card-background-color: #1E293B; + --pico-card-sectioning-background-color: #253347; - /* Text */ - --pico-color: #b8c9da; - --pico-muted-color: #7a8fa3; - --pico-muted-border-color: rgba(255,255,255,0.06); + /* Text — Soft White / Slate */ + --pico-color: #CBD5E1; + --pico-muted-color: #94A3B8; + --pico-muted-border-color: rgba(255,255,255,0.08); - /* Primary accent (red) */ - --pico-primary: #d94f4f; - --pico-primary-hover: #c94545; - --pico-primary-focus: rgba(217,79,79,0.25); + /* Primary accent — Electric Blue */ + --pico-primary: #3B82F6; + --pico-primary-hover: #2563EB; + --pico-primary-focus: rgba(59,130,246,0.25); --pico-primary-inverse: #fff; - /* Typography */ - --pico-font-family: 'Outfit', system-ui, sans-serif; + /* Secondary — Charcoal */ + --pico-secondary: #94A3B8; + --pico-secondary-hover: #CBD5E1; + --pico-secondary-focus: rgba(148,163,184,0.25); + --pico-secondary-inverse: #0F172A; + + /* Typography — Inter */ + --pico-font-family: 'Inter', system-ui, -apple-system, sans-serif; --pico-font-family-monospace: 'JetBrains Mono', monospace; /* Borders */ - --pico-border-color: rgba(255,255,255,0.06); + --pico-border-color: #334155; /* Form styling */ - --pico-form-element-background-color: #171f2a; - --pico-form-element-border-color: rgba(255,255,255,0.1); - --pico-form-element-focus-color: #d94f4f; + --pico-form-element-background-color: #1E293B; + --pico-form-element-border-color: #334155; + --pico-form-element-focus-color: #3B82F6; } -/* Headings use warm cream */ +/* Headings — Soft White, Inter */ h1, h2, h3, h4, h5, h6 { - color: #e8dcc8; - font-family: 'Outfit', system-ui, sans-serif; + color: #F8FAFC; + font-family: 'Inter', system-ui, -apple-system, sans-serif; +} + +/* Data & metrics use monospace */ +.metric, .mono, [data-mono] { + font-family: 'JetBrains Mono', monospace; +} + +/* Success states — Vibrant Green */ +.success, [data-success] { + color: #10B981; } article { diff --git a/padelnomics/src/padelnomics/static/css/planner.css b/padelnomics/src/padelnomics/static/css/planner.css index 703d455..a382a3e 100644 --- a/padelnomics/src/padelnomics/static/css/planner.css +++ b/padelnomics/src/padelnomics/static/css/planner.css @@ -1,28 +1,28 @@ /* Padelnomics Planner — scoped under .planner-app */ -/* Isolates planner from Pico CSS resets */ +/* Court Tech brand — Deep Navy + Electric Blue */ .planner-app { - --bg: #0b0f14; - --bg-2: #111820; - --bg-3: #171f2a; - --bg-4: #1d2733; - --border: rgba(255,255,255,0.06); - --border-2: rgba(255,255,255,0.1); - --txt: #b8c9da; - --txt-2: #7a8fa3; - --txt-3: #4d6278; - --head: #e8dcc8; - --wht: #f5f0e8; - --rd: #d94f4f; - --rd-bg: rgba(217,79,79,0.08); - --gn: #3dba78; - --gn-bg: rgba(61,186,120,0.08); - --bl: #4a90d9; - --bl-bg: rgba(74,144,217,0.08); - --am: #d4a03c; - --am-bg: rgba(212,160,60,0.08); + --bg: #0F172A; + --bg-2: #1E293B; + --bg-3: #253347; + --bg-4: #2D3F54; + --border: rgba(255,255,255,0.08); + --border-2: rgba(255,255,255,0.12); + --txt: #CBD5E1; + --txt-2: #94A3B8; + --txt-3: #64748B; + --head: #F8FAFC; + --wht: #F8FAFC; + --rd: #3B82F6; + --rd-bg: rgba(59,130,246,0.08); + --gn: #10B981; + --gn-bg: rgba(16,185,129,0.08); + --bl: #3B82F6; + --bl-bg: rgba(59,130,246,0.08); + --am: #F59E0B; + --am-bg: rgba(245,158,11,0.08); - font-family: 'Outfit', sans-serif; + font-family: 'Inter', sans-serif; font-size: 14px; color: var(--txt); background: var(--bg); @@ -81,7 +81,7 @@ background: transparent; color: var(--txt-2); cursor: pointer; - font-family: 'Outfit', sans-serif; + font-family: 'Inter', sans-serif; font-weight: 500; transition: all 0.15s; } @@ -109,7 +109,7 @@ color: var(--txt-3); cursor: pointer; white-space: nowrap; - font-family: 'Outfit', sans-serif; + font-family: 'Inter', sans-serif; border-bottom: 2px solid transparent; transition: all 0.15s; } @@ -267,7 +267,7 @@ outline: none; } .slider-combo input[type=number]:focus { - border-color: rgba(217,79,79,0.5); + border-color: rgba(59,130,246,0.5); } /* Hide number spinners */ .slider-combo input[type=number]::-webkit-outer-spin-button, @@ -295,7 +295,7 @@ color: var(--txt-3); border-radius: 6px; cursor: pointer; - font-family: 'Outfit', sans-serif; + font-family: 'Inter', sans-serif; transition: all 0.15s; } .toggle-btn--active { @@ -325,7 +325,7 @@ } .data-table td { padding: 6px 8px; - font-family: 'Outfit', sans-serif; + font-family: 'Inter', sans-serif; color: var(--txt); } .data-table td.mono { @@ -383,7 +383,7 @@ margin-left: 4px; flex-shrink: 0; font-style: italic; - font-family: 'Outfit', sans-serif; + font-family: 'Inter', sans-serif; vertical-align: middle; } .ti .tp { @@ -465,7 +465,7 @@ color: #fff; } .lead-cta-bar a:first-of-type:hover { - background: #c94545; + background: #2563EB; } .lead-cta-bar a:last-of-type { background: transparent; @@ -505,7 +505,7 @@ transition: background 0.15s; } .lead-cta__btn:hover { - background: #c94545; + background: #2563EB; } /* ── Exit waterfall ── */ diff --git a/padelnomics/src/padelnomics/static/js/planner.js b/padelnomics/src/padelnomics/static/js/planner.js index a12580b..55d0118 100644 --- a/padelnomics/src/padelnomics/static/js/planner.js +++ b/padelnomics/src/padelnomics/static/js/planner.js @@ -462,9 +462,9 @@ function renderCapex(d){ renderChart('chartCapex','doughnut',{ labels:d.capexItems.filter(i=>i.amount>0).map(i=>i.name), datasets:[{data:d.capexItems.filter(i=>i.amount>0).map(i=>i.amount), - backgroundColor:['#d94f4f','#4a90d9','#3dba78','#d4a03c','#8b5cf6','#ec4899','#06b6d4','#84cc16','#f97316','#6366f1','#14b8a6','#a855f7','#ef4444','#22c55e','#eab308'], + backgroundColor:['#3B82F6','#10B981','#F59E0B','#8B5CF6','#EC4899','#06B6D4','#84CC16','#F97316','#6366F1','#14B8A6','#A855F7','#EF4444','#22C55E','#EAB308','#2563EB'], borderWidth:0}] - },{plugins:{legend:{position:'right',labels:{color:'#7a8fa3',font:{size:10,family:'Outfit'},boxWidth:10,padding:6}}}}); + },{plugins:{legend:{position:'right',labels:{color:'#94A3B8',font:{size:10,family:'Inter'},boxWidth:10,padding:6}}}}); } function renderOperating(d){ @@ -499,10 +499,10 @@ function renderOperating(d){ renderChart('chartRevRamp','bar',{ labels:rampData.map(m=>'M'+m.m), datasets:[ - {label:'Revenue',data:rampData.map(m=>Math.round(m.totalRev)),backgroundColor:'rgba(61,186,120,0.5)',borderRadius:3}, - {label:'OpEx+Debt',data:rampData.map(m=>Math.round(Math.abs(m.opex)+Math.abs(m.loan))),backgroundColor:'rgba(217,79,79,0.4)',borderRadius:3}, + {label:'Revenue',data:rampData.map(m=>Math.round(m.totalRev)),backgroundColor:'rgba(16,185,129,0.5)',borderRadius:3}, + {label:'OpEx+Debt',data:rampData.map(m=>Math.round(Math.abs(m.opex)+Math.abs(m.loan))),backgroundColor:'rgba(239,68,68,0.4)',borderRadius:3}, ] - },{scales:{x:{ticks:{maxTicksLimit:12,color:'#4d6278',font:{size:9}}},y:{ticks:{color:'#4d6278',font:{size:9}},grid:{color:'rgba(255,255,255,0.03)'}}},plugins:{legend:{labels:{color:'#7a8fa3',font:{size:10}}}}}); + },{scales:{x:{ticks:{maxTicksLimit:12,color:'#64748B',font:{size:9}}},y:{ticks:{color:'#64748B',font:{size:9}},grid:{color:'rgba(255,255,255,0.03)'}}},plugins:{legend:{labels:{color:'#94A3B8',font:{size:10}}}}}); const plData = [ {label:'Court Rev',val:Math.round(d.courtRevMonth)}, @@ -513,8 +513,8 @@ function renderOperating(d){ ]; renderChart('chartPL','bar',{ labels:plData.map(p=>p.label), - datasets:[{data:plData.map(p=>p.val),backgroundColor:plData.map(p=>p.val>=0?'rgba(61,186,120,0.6)':'rgba(217,79,79,0.5)'),borderRadius:4}] - },{indexAxis:'y',scales:{x:{ticks:{color:'#4d6278',font:{size:9}},grid:{color:'rgba(255,255,255,0.03)'}},y:{ticks:{color:'#7a8fa3',font:{size:10}}}},plugins:{legend:{display:false}}}); + datasets:[{data:plData.map(p=>p.val),backgroundColor:plData.map(p=>p.val>=0?'rgba(16,185,129,0.6)':'rgba(239,68,68,0.5)'),borderRadius:4}] + },{indexAxis:'y',scales:{x:{ticks:{color:'#64748B',font:{size:9}},grid:{color:'rgba(255,255,255,0.03)'}},y:{ticks:{color:'#94A3B8',font:{size:10}}}},plugins:{legend:{display:false}}}); } function renderCashflow(d){ @@ -530,13 +530,13 @@ function renderCashflow(d){ renderChart('chartCF','bar',{ labels:d.months.map(m=>m.m%12===1?'Y'+m.yr:''), datasets:[{data:d.months.map(m=>Math.round(m.ncf)), - backgroundColor:d.months.map(m=>m.ncf>=0?'rgba(61,186,120,0.5)':'rgba(217,79,79,0.4)'),borderRadius:2}] - },{scales:{x:{ticks:{color:'#4d6278',font:{size:9}}},y:{ticks:{color:'#4d6278',font:{size:9}},grid:{color:'rgba(255,255,255,0.03)'}}},plugins:{legend:{display:false}}}); + backgroundColor:d.months.map(m=>m.ncf>=0?'rgba(16,185,129,0.5)':'rgba(239,68,68,0.4)'),borderRadius:2}] + },{scales:{x:{ticks:{color:'#64748B',font:{size:9}}},y:{ticks:{color:'#64748B',font:{size:9}},grid:{color:'rgba(255,255,255,0.03)'}}},plugins:{legend:{display:false}}}); renderChart('chartCum','line',{ labels:d.months.map(m=>m.m%6===1?'M'+m.m:''), - datasets:[{data:d.months.map(m=>Math.round(m.cum)),borderColor:'#4a90d9',backgroundColor:'rgba(74,144,217,0.08)',fill:true,pointRadius:0,tension:0.3}] - },{scales:{x:{ticks:{color:'#4d6278',font:{size:9}}},y:{ticks:{color:'#4d6278',font:{size:9}},grid:{color:'rgba(255,255,255,0.03)'}}},plugins:{legend:{display:false}}}); + datasets:[{data:d.months.map(m=>Math.round(m.cum)),borderColor:'#3B82F6',backgroundColor:'rgba(59,130,246,0.08)',fill:true,pointRadius:0,tension:0.3}] + },{scales:{x:{ticks:{color:'#64748B',font:{size:9}}},y:{ticks:{color:'#64748B',font:{size:9}},grid:{color:'rgba(255,255,255,0.03)'}}},plugins:{legend:{display:false}}}); let rows = d.annuals.map(y=>{ const dscr = y.ds>0?y.ebitda/y.ds:999; @@ -577,8 +577,8 @@ function renderReturns(d){ renderChart('chartDSCR','bar',{ labels:d.dscr.map(x=>'Y'+x.year), - datasets:[{data:d.dscr.map(x=>Math.min(x.dscr,10)),backgroundColor:d.dscr.map(x=>x.dscr>=1.2?'rgba(61,186,120,0.5)':'rgba(217,79,79,0.5)'),borderRadius:4}] - },{scales:{x:{ticks:{color:'#7a8fa3'}},y:{ticks:{color:'#4d6278',font:{size:9}},grid:{color:'rgba(255,255,255,0.03)'}}},plugins:{legend:{display:false}}}); + datasets:[{data:d.dscr.map(x=>Math.min(x.dscr,10)),backgroundColor:d.dscr.map(x=>x.dscr>=1.2?'rgba(16,185,129,0.5)':'rgba(239,68,68,0.5)'),borderRadius:4}] + },{scales:{x:{ticks:{color:'#94A3B8'}},y:{ticks:{color:'#64748B',font:{size:9}},grid:{color:'rgba(255,255,255,0.03)'}}},plugins:{legend:{display:false}}}); const utils = [15,20,25,30,35,40,45,50,55,60,65,70]; const isIn = S.venue==='indoor'; @@ -655,8 +655,8 @@ function renderSeasonChart(){ const months=['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec']; renderChart('chartSeason','bar',{ labels:months, - datasets:[{data:S.season.map(s=>s*100),backgroundColor:S.season.map(s=>s>0?'rgba(61,186,120,0.5)':'rgba(217,79,79,0.2)'),borderRadius:4}] - },{scales:{x:{ticks:{color:'#7a8fa3'}},y:{max:110,ticks:{color:'#4d6278'},grid:{color:'rgba(255,255,255,0.03)'}}},plugins:{legend:{display:false}}}); + datasets:[{data:S.season.map(s=>s*100),backgroundColor:S.season.map(s=>s>0?'rgba(16,185,129,0.5)':'rgba(239,68,68,0.2)'),borderRadius:4}] + },{scales:{x:{ticks:{color:'#94A3B8'}},y:{max:110,ticks:{color:'#64748B'},grid:{color:'rgba(255,255,255,0.03)'}}},plugins:{legend:{display:false}}}); } // ── Chart Helper ────────────────────────────────────────── @@ -667,15 +667,15 @@ function renderChart(canvasId,type,data,opts={}){ const defaults = { responsive:true, maintainAspectRatio:false, animation:{duration:0}, scales:{}, - plugins:{legend:{labels:{color:'#7a8fa3',font:{family:'Outfit',size:10}}}}, + plugins:{legend:{labels:{color:'#94A3B8',font:{family:'Inter',size:10}}}}, }; if(type==='doughnut'||type==='pie'){ delete defaults.scales; defaults.cutout = '55%'; } else { defaults.scales = { - x:{ticks:{color:'#4d6278',font:{size:9,family:'Outfit'}},grid:{display:false},border:{color:'rgba(255,255,255,0.06)'}}, - y:{ticks:{color:'#4d6278',font:{size:9,family:'JetBrains Mono'}},grid:{color:'rgba(255,255,255,0.03)'},border:{color:'rgba(255,255,255,0.06)'}}, + x:{ticks:{color:'#64748B',font:{size:9,family:'Inter'}},grid:{display:false},border:{color:'rgba(255,255,255,0.08)'}}, + y:{ticks:{color:'#64748B',font:{size:9,family:'JetBrains Mono'}},grid:{color:'rgba(255,255,255,0.03)'},border:{color:'rgba(255,255,255,0.06)'}}, }; } charts[canvasId] = new Chart(ctx,{type,data,options:deepMerge(defaults,opts)}); diff --git a/padelnomics/src/padelnomics/templates/base.html b/padelnomics/src/padelnomics/templates/base.html index 4a239dd..b7f872d 100644 --- a/padelnomics/src/padelnomics/templates/base.html +++ b/padelnomics/src/padelnomics/templates/base.html @@ -9,7 +9,7 @@ - +