diff --git a/assets/css/base.css b/assets/css/base.css
index 14e2ec1..06ca1ef 100644
--- a/assets/css/base.css
+++ b/assets/css/base.css
@@ -1,3 +1,15 @@
+/* ── SELF-HOSTED FONTS ───────────────────────────────────────────────── */
+@font-face { font-family: 'Manrope'; font-style: normal; font-weight: 400; font-display: swap; src: url('../fonts/manrope-400.woff2') format('woff2'); }
+@font-face { font-family: 'Manrope'; font-style: normal; font-weight: 500; font-display: swap; src: url('../fonts/manrope-500.woff2') format('woff2'); }
+@font-face { font-family: 'Manrope'; font-style: normal; font-weight: 600; font-display: swap; src: url('../fonts/manrope-600.woff2') format('woff2'); }
+@font-face { font-family: 'Manrope'; font-style: normal; font-weight: 700; font-display: swap; src: url('../fonts/manrope-700.woff2') format('woff2'); }
+@font-face { font-family: 'Fraunces'; font-style: normal; font-weight: 700; font-display: swap; src: url('../fonts/fraunces-700-normal.woff2') format('woff2'); }
+@font-face { font-family: 'Fraunces'; font-style: normal; font-weight: 900; font-display: swap; src: url('../fonts/fraunces-900-normal.woff2') format('woff2'); }
+@font-face { font-family: 'Fraunces'; font-style: italic; font-weight: 300; font-display: swap; src: url('../fonts/fraunces-300-italic.woff2') format('woff2'); }
+@font-face { font-family: 'Fraunces'; font-style: italic; font-weight: 700; font-display: swap; src: url('../fonts/fraunces-700-italic.woff2') format('woff2'); }
+@font-face { font-family: 'JetBrains Mono'; font-style: normal; font-weight: 400; font-display: swap; src: url('../fonts/jetbrains-mono-400.woff2') format('woff2'); }
+@font-face { font-family: 'JetBrains Mono'; font-style: normal; font-weight: 600; font-display: swap; src: url('../fonts/jetbrains-mono-600.woff2') format('woff2'); }
+
/* ════════════════════════════════════════════════════════════════════════
base.css — Fonts, reset, page shell, and top navigation.
════════════════════════════════════════════════════════════════════════
diff --git a/assets/fonts/fraunces-300-italic.woff2 b/assets/fonts/fraunces-300-italic.woff2
new file mode 100644
index 0000000..f15af2e
Binary files /dev/null and b/assets/fonts/fraunces-300-italic.woff2 differ
diff --git a/assets/fonts/fraunces-700-italic.woff2 b/assets/fonts/fraunces-700-italic.woff2
new file mode 100644
index 0000000..313590d
Binary files /dev/null and b/assets/fonts/fraunces-700-italic.woff2 differ
diff --git a/assets/fonts/fraunces-700-normal.woff2 b/assets/fonts/fraunces-700-normal.woff2
new file mode 100644
index 0000000..71bbace
Binary files /dev/null and b/assets/fonts/fraunces-700-normal.woff2 differ
diff --git a/assets/fonts/fraunces-900-normal.woff2 b/assets/fonts/fraunces-900-normal.woff2
new file mode 100644
index 0000000..32f67e3
Binary files /dev/null and b/assets/fonts/fraunces-900-normal.woff2 differ
diff --git a/assets/fonts/jetbrains-mono-400.woff2 b/assets/fonts/jetbrains-mono-400.woff2
new file mode 100644
index 0000000..5858873
Binary files /dev/null and b/assets/fonts/jetbrains-mono-400.woff2 differ
diff --git a/assets/fonts/jetbrains-mono-600.woff2 b/assets/fonts/jetbrains-mono-600.woff2
new file mode 100644
index 0000000..59c24e7
Binary files /dev/null and b/assets/fonts/jetbrains-mono-600.woff2 differ
diff --git a/assets/fonts/manrope-400.woff2 b/assets/fonts/manrope-400.woff2
new file mode 100644
index 0000000..7eaaa95
Binary files /dev/null and b/assets/fonts/manrope-400.woff2 differ
diff --git a/assets/fonts/manrope-500.woff2 b/assets/fonts/manrope-500.woff2
new file mode 100644
index 0000000..70447ee
Binary files /dev/null and b/assets/fonts/manrope-500.woff2 differ
diff --git a/assets/fonts/manrope-600.woff2 b/assets/fonts/manrope-600.woff2
new file mode 100644
index 0000000..7cc09a3
Binary files /dev/null and b/assets/fonts/manrope-600.woff2 differ
diff --git a/assets/fonts/manrope-700.woff2 b/assets/fonts/manrope-700.woff2
new file mode 100644
index 0000000..84f7af5
Binary files /dev/null and b/assets/fonts/manrope-700.woff2 differ
diff --git a/assets/js/app.js b/assets/js/app.js
index 97650d4..2de30e5 100644
--- a/assets/js/app.js
+++ b/assets/js/app.js
@@ -54,8 +54,8 @@ export function UTCIForecast() {
visibleCols, setVisibleCols, toggleCol,
showDecimals, toggleShowDecimals,
showUnits, toggleShowUnits,
- activityOptions, placeOptions,
- activityValue, activityLabel, placeValue, placeLabel,
+ activityOptions, placeOptions, workOptions,
+ activityValue, activityLabel, placeValue, placeLabel, workValue, workLabel,
skinType, setSkinType,
vehicleType, setVehicleType,
vehicleVent, setVehicleVent,
@@ -321,12 +321,14 @@ export function UTCIForecast() {
proPromptSource=${proPromptSource} setProPromptSource=${setProPromptSource}
activeProfile=${activeProfile} activateProfile=${activateProfile} activeCols=${activeCols}
visibleCols=${visibleCols}
- activityOptions=${activityOptions} placeOptions=${placeOptions}
+ activityOptions=${activityOptions} placeOptions=${placeOptions} workOptions=${workOptions}
activityValue=${activityValue} activityLabel=${activityLabel}
placeValue=${placeValue} placeLabel=${placeLabel}
+ workValue=${workValue} workLabel=${workLabel}
outdoorsVariant=${outdoorsVariant} setOutdoorsVariantAndSave=${setOutdoorsVariantAndSave}
setActiveProfile=${setActiveProfile} setVisibleCols=${setVisibleCols}
setIndoorMode=${setIndoorMode} setIndoorManaged=${setIndoorManaged}
+ setBuildingType=${setBuildingType}
dayTabsRef=${dayTabsRef} canScrollLeft=${canScrollLeft} canScrollRight=${canScrollRight}
scrollDayTabs=${scrollDayTabs}
/>`}
diff --git a/assets/js/components/DayTabs.js b/assets/js/components/DayTabs.js
index e659274..61ec342 100644
--- a/assets/js/components/DayTabs.js
+++ b/assets/js/components/DayTabs.js
@@ -22,10 +22,13 @@
// visibleCols - object of col-key -> boolean visibility
// activityOptions - dropdown options for Activities selector
// placeOptions - dropdown options for Places selector
+// workOptions - dropdown options for Work selector
// activityValue - current activity dropdown value
// activityLabel - current activity dropdown label
// placeValue - current place dropdown value
// placeLabel - current place dropdown label
+// workValue - current work dropdown value
+// workLabel - current work dropdown label
// outdoorsVariant - current outdoors sub-variant key
// setOutdoorsVariantAndSave - setter that also persists to localStorage
// setActiveProfile - raw setter for activeProfile
@@ -41,7 +44,7 @@
import { h, Fragment } from '../../vendor/preact.js';
import htm from '../../vendor/htm.js';
import { confidenceBand } from '../utils.js';
-import { FREE_DAYS, FILTER_PROFILES, OUTDOORS_VARIANTS, profileButtonOrder, activityVariantKeys, placeVariantKeys } from '../config.js';
+import { FREE_DAYS, FILTER_PROFILES, OUTDOORS_VARIANTS, profileButtonOrder, activityVariantKeys, placeVariantKeys, workVariantKeys } from '../config.js';
import { CloudIcon, PrecipIcon, CustomSelect } from '../components.js';
const html = htm.bind(h);
@@ -54,12 +57,13 @@ export function DayTabs({
proPromptSource, setProPromptSource,
activeProfile, activateProfile, activeCols,
visibleCols,
- activityOptions, placeOptions,
+ activityOptions, placeOptions, workOptions,
activityValue, activityLabel,
placeValue, placeLabel,
+ workValue, workLabel,
outdoorsVariant, setOutdoorsVariantAndSave,
setActiveProfile, setVisibleCols,
- setIndoorMode, setIndoorManaged,
+ setIndoorMode, setIndoorManaged, setBuildingType,
dayTabsRef, canScrollLeft, canScrollRight, scrollDayTabs,
}) {
return html`
@@ -398,11 +402,34 @@ export function DayTabs({
<${CustomSelect}
key="activities"
value=${activityValue}
- isOn=${activeProfile === 'farming' || (activeProfile === 'outdoors' && activityVariantKeys.includes(outdoorsVariant))}
+ isOn=${activeProfile === 'outdoors' && activityVariantKeys.includes(outdoorsVariant)}
noHide=${true}
hideLabel="🎯 Activities"
buttonLabel=${activityValue === 'off' ? '🎯 Activities' : ` ${activityLabel}`}
options=${activityOptions}
+ onChange=${(v) => {
+ if (v === 'off') { activateProfile('basic'); return; }
+ if (OUTDOORS_VARIANTS[v]?.proOnly && !isPro) {
+ setProPromptSource(`variant:${v}`);
+ setProPromptDay(0);
+ return;
+ }
+ try { localStorage.setItem('sunscope_profile', 'outdoors'); } catch (e) { /* ignore */ }
+ setActiveProfile('outdoors');
+ setOutdoorsVariantAndSave(v);
+ setVisibleCols({ ...OUTDOORS_VARIANTS[v].cols });
+ setIndoorMode('off');
+ setIndoorManaged(false);
+ }}
+ />
+ <${CustomSelect}
+ key="work"
+ value=${workValue}
+ isOn=${activeProfile === 'farming' || (activeProfile === 'outdoors' && workVariantKeys.includes(outdoorsVariant))}
+ noHide=${true}
+ hideLabel="💼 Work"
+ buttonLabel=${workValue === 'off' ? '💼 Work' : ` ${workLabel}`}
+ options=${workOptions}
onChange=${(v) => {
if (v === 'off') { activateProfile('basic'); return; }
if (v === 'farming') { activateProfile('farming'); return; }
@@ -415,8 +442,14 @@ export function DayTabs({
setActiveProfile('outdoors');
setOutdoorsVariantAndSave(v);
setVisibleCols({ ...OUTDOORS_VARIANTS[v].cols });
- setIndoorMode('off');
- setIndoorManaged(false);
+ if (v === 'office') {
+ setBuildingType('office');
+ setIndoorMode('on');
+ setIndoorManaged(false);
+ } else {
+ setIndoorMode('off');
+ setIndoorManaged(false);
+ }
}}
/>
diff --git a/assets/js/config.js b/assets/js/config.js
index bbe94a8..c4ce865 100644
--- a/assets/js/config.js
+++ b/assets/js/config.js
@@ -94,6 +94,10 @@ export const OUTDOORS_VARIANTS = {
hiking: { name: 'Hiking', proOnly: true, cols: { hour: true, air: true, rh: false, dew: false, wind: true, dir: true, cloud: true, sun: true, direct: false, diffuse: false, tmrt: false, delta: false, utci: true, uvA: true, uvB: true, burn: true, utciP: true, precip: true, precipProb: true, soilT: false, soilT6: false, soilM: false, concreteT: false, vehicleT: false, indoorT: false, managedT: false, vis: true, aqi: false, pollen: false } },
photography: { name: 'Photography', proOnly: true, cols: { hour: true, air: true, rh: false, dew: false, wind: false, dir: false, cloud: true, sun: true, direct: true, diffuse: true, tmrt: false, delta: false, utci: false, uvA: false, uvB: false, burn: false, utciP: false, precip: true, precipProb: true, soilT: false, soilT6: false, soilM: false, concreteT: false, vehicleT: false, indoorT: false, managedT: false, vis: true, aqi: false, pollen: false } },
fishing: { name: 'Fishing', proOnly: true, cols: { hour: true, air: true, rh: false, dew: true, wind: true, dir: true, cloud: true, sun: false, direct: false, diffuse: false, tmrt: false, delta: false, utci: false, uvA: false, uvB: false, burn: false, utciP: true, precip: true, precipProb: true, soilT: false, soilT6: false, soilM: false, concreteT: false, vehicleT: false, indoorT: false, managedT: false, vis: true, aqi: false, pollen: false } },
+ // Work variants
+ market: { name: 'Market Trading', cols: { hour: true, air: true, rh: false, dew: false, wind: true, dir: true, cloud: true, sun: false, direct: false, diffuse: false, tmrt: false, delta: false, utci: false, uvA: false, uvB: false, burn: false, utciP: true, precip: true, precipProb: true, soilT: false, soilT6: false, soilM: false, concreteT: false, vehicleT: false, indoorT: false, managedT: false, vis: true, aqi: false, pollen: false } },
+ windowcleaning: { name: 'Window Cleaning', proOnly: true, cols: { hour: true, air: true, rh: false, dew: false, wind: true, dir: true, cloud: true, sun: false, direct: false, diffuse: false, tmrt: false, delta: false, utci: false, uvA: false, uvB: false, burn: false, utciP: true, precip: true, precipProb: true, soilT: false, soilT6: false, soilM: false, concreteT: false, vehicleT: false, indoorT: false, managedT: false, vis: true, aqi: false, pollen: false } },
+ office: { name: 'Office', proOnly: true, cols: { hour: true, air: true, rh: true, dew: false, wind: false, dir: false, cloud: true, sun: true, direct: true, diffuse: false, tmrt: false, delta: false, utci: false, uvA: false, uvB: false, burn: false, utciP: true, precip: true, precipProb: true, soilT: false, soilT6: false, soilM: false, concreteT: false, vehicleT: false, indoorT: false, managedT: true, vis: false, aqi: true, pollen: false } },
};
// Pollen type options shown in the pulldown selector.
@@ -128,13 +132,19 @@ export const variantIcons = {
hiking: '🏔️',
photography: '📸',
fishing: '🎣',
+ market: '🏪',
+ windowcleaning: '🪟',
+ office: '🏢',
};
// Which variant keys appear in the Activities dropdown.
-export const activityVariantKeys = ['cycling', 'running', 'dogwalk', 'sailing', 'wintersports', 'naturist', 'hiking', 'photography', 'fishing'];
+export const activityVariantKeys = ['dogwalk', 'running', 'cycling', 'hiking', 'fishing', 'sailing', 'wintersports', 'photography', 'naturist'];
// Which variant keys appear in the Places dropdown.
-export const placeVariantKeys = ['urban', 'beach', 'events', 'park', 'airport', 'festival', 'construction'];
+export const placeVariantKeys = ['urban', 'park', 'beach', 'events', 'festival', 'airport'];
+
+// Which variant keys appear in the Work dropdown.
+export const workVariantKeys = ['farming', 'construction', 'market', 'windowcleaning', 'office'];
// Tooltip text shown when the user clicks/hovers a table column header.
export const COL_DESCRIPTIONS = {
diff --git a/assets/js/hooks/useAppState.js b/assets/js/hooks/useAppState.js
index 35de0e1..52fff94 100644
--- a/assets/js/hooks/useAppState.js
+++ b/assets/js/hooks/useAppState.js
@@ -26,7 +26,7 @@ import { useState, useEffect, useRef, useCallback } from '../../vendor/preact-ho
import {
FREE_DAYS, FILTER_PROFILES, OUTDOORS_VARIANTS,
profileButtonOrder, variantIcons,
- activityVariantKeys, placeVariantKeys,
+ activityVariantKeys, placeVariantKeys, workVariantKeys,
} from '../config.js';
import { utciCategory } from '../utils.js';
import { buildHourlyRows } from '../compute.js';
@@ -167,8 +167,20 @@ export function useAppState() {
// ── 5. SKIN, VEHICLE, INDOOR, POLLEN ─────────────────────────────────
const [skinType, setSkinType] = useState('II');
- const [vehicleType, setVehicleType] = useState('car');
- const [vehicleVent, setVehicleVent] = useState(false);
+ const [vehicleType, setVehicleType] = useState(() => {
+ try { return localStorage.getItem('sunscope_vehicle_type') || 'car'; } catch (e) { return 'car'; }
+ });
+ const setVehicleTypeAndSave = (v) => {
+ try { localStorage.setItem('sunscope_vehicle_type', v); } catch (e) { /* ignore */ }
+ setVehicleType(v);
+ };
+ const [vehicleVent, setVehicleVent] = useState(() => {
+ try { return localStorage.getItem('sunscope_vehicle_vent') === '1'; } catch (e) { return false; }
+ });
+ const setVehicleVentAndSave = (v) => {
+ try { localStorage.setItem('sunscope_vehicle_vent', v ? '1' : '0'); } catch (e) { /* ignore */ }
+ setVehicleVent(v);
+ };
const [outdoorsVariant, setOutdoorsVariant] = useState(() => {
try { return localStorage.getItem('sunscope_outdoors_variant') || 'urban'; } catch (e) { return 'urban'; }
@@ -190,15 +202,40 @@ export function useAppState() {
? (OUTDOORS_VARIANTS[outdoorsVariant]?.cols ?? FILTER_PROFILES.outdoors.cols)
: (FILTER_PROFILES[activeProfile]?.cols ?? FILTER_PROFILES.basic.cols);
- const [buildingType, setBuildingType] = useState('brick');
- const [indoorManaged, setIndoorManaged] = useState(false);
- const [indoorMode, setIndoorMode] = useState(() => {
+ const [buildingType, setBuildingType] = useState(() => {
try {
- const saved = localStorage.getItem('sunscope_profile') || 'basic';
- const cols = FILTER_PROFILES[saved]?.cols ?? FILTER_PROFILES.basic.cols;
+ const saved = localStorage.getItem('sunscope_building_type');
+ if (saved) return saved;
+ // Fall back to office if the saved variant is office and no explicit building saved
+ const savedVariant = localStorage.getItem('sunscope_outdoors_variant') || '';
+ if (savedVariant === 'office') return 'office';
+ } catch (e) { /* ignore */ }
+ return 'brick';
+ });
+ const setBuildingTypeAndSave = (v) => {
+ try { localStorage.setItem('sunscope_building_type', v); } catch (e) { /* ignore */ }
+ setBuildingType(v);
+ };
+ const [indoorManaged, setIndoorManaged] = useState(() => {
+ try { return localStorage.getItem('sunscope_indoor_managed') === '1'; } catch (e) { return false; }
+ });
+ const setIndoorManagedAndSave = (v) => {
+ try { localStorage.setItem('sunscope_indoor_managed', v ? '1' : '0'); } catch (e) { /* ignore */ }
+ setIndoorManaged(v);
+ };
+ const [indoorMode, setIndoorMode] = useState(() => {
+ try {
+ const saved = localStorage.getItem('sunscope_indoor_mode');
+ if (saved) return saved;
+ const profile = localStorage.getItem('sunscope_profile') || 'basic';
+ const cols = FILTER_PROFILES[profile]?.cols ?? FILTER_PROFILES.basic.cols;
return (cols['indoorT'] || cols['managedT']) ? 'on' : 'off';
} catch (e) { return 'off'; }
});
+ const setIndoorModeAndSave = (v) => {
+ try { localStorage.setItem('sunscope_indoor_mode', v); } catch (e) { /* ignore */ }
+ setIndoorMode(v);
+ };
const [pollenType, setPollenType] = useState(() => {
try { return localStorage.getItem('sunscope_pollen_type') || 'all_pollen'; } catch (e) { return 'all_pollen'; }
@@ -233,19 +270,13 @@ export function useAppState() {
const searchTimeout = useRef(null);
// Derived selectors used by profile controls
- const activityOptions = [
- {
- value: 'farming',
- label: `${FILTER_PROFILES.farming.icon} ${FILTER_PROFILES.farming.label}`,
- },
- ...activityVariantKeys.map((k) => {
- const v = OUTDOORS_VARIANTS[k];
- return {
- value: k,
- label: `${variantIcons[k]} ${v.name}${v.proOnly && !isPro ? ' 🔒' : ''}`,
- };
- }),
- ];
+ const activityOptions = activityVariantKeys.map((k) => {
+ const v = OUTDOORS_VARIANTS[k];
+ return {
+ value: k,
+ label: `${variantIcons[k]} ${v.name}${v.proOnly && !isPro ? ' 🔒' : ''}`,
+ };
+ });
const placeOptions = placeVariantKeys.map((k) => {
const v = OUTDOORS_VARIANTS[k];
return {
@@ -253,17 +284,31 @@ export function useAppState() {
label: `${variantIcons[k]} ${v.name}${v.proOnly && !isPro ? ' 🔒' : ''}`,
};
});
+ const workOptions = workVariantKeys.map((k) => {
+ const v = k === 'farming'
+ ? { name: FILTER_PROFILES.farming.label, proOnly: false }
+ : OUTDOORS_VARIANTS[k];
+ const icon = k === 'farming' ? FILTER_PROFILES.farming.icon : variantIcons[k];
+ return {
+ value: k,
+ label: `${icon} ${v.name}${v.proOnly && !isPro ? ' 🔒' : ''}`,
+ };
+ });
- const activityValue = activeProfile === 'farming'
- ? 'farming'
- : activeProfile === 'outdoors' && activityVariantKeys.includes(outdoorsVariant)
- ? outdoorsVariant
- : 'off';
+ const activityValue = activeProfile === 'outdoors' && activityVariantKeys.includes(outdoorsVariant)
+ ? outdoorsVariant
+ : 'off';
const activityLabel = activityOptions.find((o) => o.value === activityValue)?.label;
const placeValue = activeProfile === 'outdoors' && placeVariantKeys.includes(outdoorsVariant)
? outdoorsVariant
: 'off';
const placeLabel = placeOptions.find((o) => o.value === placeValue)?.label;
+ const workValue = activeProfile === 'farming'
+ ? 'farming'
+ : activeProfile === 'outdoors' && workVariantKeys.includes(outdoorsVariant)
+ ? outdoorsVariant
+ : 'off';
+ const workLabel = workOptions.find((o) => o.value === workValue)?.label;
// ── 6. TABLE REFS ────────────────────────────────────────────────────
const headStickyRef = useRef(null);
@@ -439,17 +484,18 @@ export function useAppState() {
activeProfile, setActiveProfile,
activateProfile, activeCols,
visibleCols, setVisibleCols, toggleCol,
- activityOptions, placeOptions,
+ activityOptions, placeOptions, workOptions,
activityValue, activityLabel,
placeValue, placeLabel,
+ workValue, workLabel,
// skin, vehicle, indoor, pollen
skinType, setSkinType,
- vehicleType, setVehicleType,
- vehicleVent, setVehicleVent,
+ vehicleType, setVehicleType: setVehicleTypeAndSave,
+ vehicleVent, setVehicleVent: setVehicleVentAndSave,
outdoorsVariant, setOutdoorsVariantAndSave,
- buildingType, setBuildingType,
- indoorManaged, setIndoorManaged,
- indoorMode, setIndoorMode,
+ buildingType, setBuildingType: setBuildingTypeAndSave,
+ indoorManaged, setIndoorManaged: setIndoorManagedAndSave,
+ indoorMode, setIndoorMode: setIndoorModeAndSave,
pollenType, setPollenTypeAndSave,
showDecimals, toggleShowDecimals,
showUnits, toggleShowUnits,
diff --git a/assets/js/utils.js b/assets/js/utils.js
index b40a759..8151adf 100644
--- a/assets/js/utils.js
+++ b/assets/js/utils.js
@@ -211,6 +211,7 @@ export const BUILDING_TYPES = {
timber: { name: 'Timber Frame / New Build', uWall: 0.22, lagHours: 2, glazingRatio: 0.22, gValue: 0.35, orientFactor: 0.50, curtainBlock: 0.70, ventAlpha: 0.35, solarScale: 0.08, baseTemp: 17.0, internalGain: 0.8, retainedScale: 0.45 },
flat: { name: 'Top-floor Flat', uWall: 0.40, lagHours: 3, glazingRatio: 0.18, gValue: 0.63, orientFactor: 0.50, curtainBlock: 0.75, ventAlpha: 0.20, solarScale: 0.11, baseTemp: 17.0, internalGain: 0.9, retainedScale: 0.45 },
conservatory:{ name: 'Conservatory / Sun Room', uWall: 1.20, lagHours: 1, glazingRatio: 0.70, gValue: 0.72, orientFactor: 0.70, curtainBlock: 0.50, ventAlpha: 0.50, solarScale: 0.045, baseTemp: 12.0, internalGain: 0.2, retainedScale: 0.05 },
+ office: { name: 'Office Block', uWall: 0.25, lagHours: 2, glazingRatio: 0.45, gValue: 0.55, orientFactor: 0.65, curtainBlock: 0.50, ventAlpha: 0.15, solarScale: 0.055, baseTemp: 18.5, internalGain: 2.5, retainedScale: 0.30 },
};
// -------------------------------------------------------------------
diff --git a/assets/sunscope.css b/assets/sunscope.css
index da44800..1532dec 100644
--- a/assets/sunscope.css
+++ b/assets/sunscope.css
@@ -29,5 +29,5 @@
@import "./css/base.css";
@import "./css/header.css";
-@import "./css/table.css?v=2";
+@import "./css/table.css";
@import "./css/ui.css";
diff --git a/index.html b/index.html
index 8a9ff5f..68d4638 100644
--- a/index.html
+++ b/index.html
@@ -68,15 +68,7 @@
}
-
-
-
diff --git a/package-lock.json b/package-lock.json
index 6cd18f9..08e9ca5 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -7,6 +7,11 @@
"": {
"name": "sunscope",
"version": "1.0.0",
+ "dependencies": {
+ "@fontsource/fraunces": "^5.2.9",
+ "@fontsource/jetbrains-mono": "^5.2.8",
+ "@fontsource/manrope": "^5.2.8"
+ },
"devDependencies": {
"esbuild": "^0.21.5"
}
@@ -402,6 +407,33 @@
"node": ">=12"
}
},
+ "node_modules/@fontsource/fraunces": {
+ "version": "5.2.9",
+ "resolved": "https://registry.npmjs.org/@fontsource/fraunces/-/fraunces-5.2.9.tgz",
+ "integrity": "sha512-XDzuddBtoC7BZgZdBn6b7hsFZY2+V1hgN7yca5fBTKuHjb/lOd45a0Ji8dTUgFhPoL7RdGupo+bC2BFSt6UH8Q==",
+ "license": "OFL-1.1",
+ "funding": {
+ "url": "https://github.com/sponsors/ayuhito"
+ }
+ },
+ "node_modules/@fontsource/jetbrains-mono": {
+ "version": "5.2.8",
+ "resolved": "https://registry.npmjs.org/@fontsource/jetbrains-mono/-/jetbrains-mono-5.2.8.tgz",
+ "integrity": "sha512-6w8/SG4kqvIMu7xd7wt6x3idn1Qux3p9N62s6G3rfldOUYHpWcc2FKrqf+Vo44jRvqWj2oAtTHrZXEP23oSKwQ==",
+ "license": "OFL-1.1",
+ "funding": {
+ "url": "https://github.com/sponsors/ayuhito"
+ }
+ },
+ "node_modules/@fontsource/manrope": {
+ "version": "5.2.8",
+ "resolved": "https://registry.npmjs.org/@fontsource/manrope/-/manrope-5.2.8.tgz",
+ "integrity": "sha512-gJHJmcuUk7qWcNCfcAri/DJQtXtBYqi9yKratr4jXhSo0I3xUtNNKI+igQIcw5c+m95g0vounk8ZnX/kb8o0TA==",
+ "license": "OFL-1.1",
+ "funding": {
+ "url": "https://github.com/sponsors/ayuhito"
+ }
+ },
"node_modules/esbuild": {
"version": "0.21.5",
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz",
diff --git a/package.json b/package.json
index a72f1f0..9f5ec61 100644
--- a/package.json
+++ b/package.json
@@ -9,5 +9,10 @@
},
"devDependencies": {
"esbuild": "^0.21.5"
+ },
+ "dependencies": {
+ "@fontsource/fraunces": "^5.2.9",
+ "@fontsource/jetbrains-mono": "^5.2.8",
+ "@fontsource/manrope": "^5.2.8"
}
}