1.8.6
Integrate fonts Add office profile Fix onload pulldown selections
This commit is contained in:
@@ -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.
|
||||
════════════════════════════════════════════════════════════════════════
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+5
-3
@@ -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}
|
||||
/>`}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<span class="profile-divider" aria-hidden="true"></span>
|
||||
|
||||
+12
-2
@@ -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 = {
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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 },
|
||||
};
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
+1
-1
@@ -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";
|
||||
|
||||
@@ -68,15 +68,7 @@
|
||||
}
|
||||
</script>
|
||||
|
||||
<link rel="preconnect" href="https://fonts.bunny.net" crossorigin />
|
||||
<link rel="preconnect" href="https://api.open-meteo.com" crossorigin />
|
||||
<link rel="preload" as="style"
|
||||
href="https://fonts.bunny.net/css2?family=Fraunces:ital,wght@0,700;0,900;1,300;1,700&family=JetBrains+Mono:wght@400;600&family=Manrope:wght@400;500;600;700&display=swap"
|
||||
onload="this.onload=null;this.rel='stylesheet'" />
|
||||
<noscript>
|
||||
<link rel="stylesheet"
|
||||
href="https://fonts.bunny.net/css2?family=Fraunces:ital,wght@0,700;0,900;1,300;1,700&family=JetBrains+Mono:wght@400;600&family=Manrope:wght@400;500;600;700&display=swap" />
|
||||
</noscript>
|
||||
<link rel="icon" type="image/svg+xml" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>☀️</text></svg>" />
|
||||
<link rel="stylesheet" href="./assets/sunscope.css?v=15b">
|
||||
</head>
|
||||
|
||||
Generated
+32
@@ -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",
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user