Style: Unify formatting, add .editorconfig (#88)

This commit is contained in:
Thaddeus Crews
2024-07-28 16:28:09 -05:00
committed by GitHub
parent 375cec369a
commit b8827a41b2
12 changed files with 364 additions and 310 deletions

23
.editorconfig Normal file
View File

@@ -0,0 +1,23 @@
root = true
[*]
charset = utf-8
end_of_line = lf
indent_size = 4
indent_style = tab
insert_final_newline = true
trim_trailing_whitespace = true
[*.{csproj,sln}]
charset = utf-8-bom
end_of_line = crlf
[*.{cs,py}]
indent_style = space
[*.{csproj,yml,yaml}]
indent_size = 2
indent_style = space
[*.md]
trim_trailing_whitespace = false

7
.gitattributes vendored
View File

@@ -1 +1,8 @@
# Properly detect languages on Github
web/static/thirdparty/* linguist-vendored
# Normalize EOL for all files that Git considers text files
* text=auto eol=lf
# Except for Visual Studio files
*.sln eol=crlf
*.csproj eol=crlf

32
.gitignore vendored
View File

@@ -16,5 +16,35 @@ mono_crash.*.json
.directory
*~
# IDE-specific ignores
.fleet/
.history/
.idea/
.vs/
.vscode/
*.code-workspace
# Python-specific ignores
__pycache__/
*_cache/
*.pyc
.venv
venv
# Godot Git repository clone (run-benchmarks.sh)
/godot/
godot/
# Output HTML files
web/public/
# Temporary lock file while building
web/.hugo_build.lock
# Generated files
web/content/benchmark/*.md
web/content/graph/*.md
web/data/data.json
# Untracked source files
web/src-data/benchmarks/*.json
web/src-data/benchmarks/*.md

View File

@@ -1,4 +1,4 @@
<Project Sdk="Godot.NET.Sdk/4.3.0-dev.2">
<Project Sdk="Godot.NET.Sdk/4.3.0-dev.2">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework Condition=" '$(GodotTargetPlatform)' == 'android' ">net7.0</TargetFramework>

View File

@@ -1,12 +1,15 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2012

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.10.35027.167
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Godot Benchmarks", "Godot Benchmarks.csproj", "{A7FD1DC6-AE2B-4F17-B4BA-2FD940E01B47}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
ExportDebug|Any CPU = ExportDebug|Any CPU
ExportRelease|Any CPU = ExportRelease|Any CPU
Debug|Any CPU = Debug|Any CPU
ExportDebug|Any CPU = ExportDebug|Any CPU
ExportRelease|Any CPU = ExportRelease|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{A7FD1DC6-AE2B-4F17-B4BA-2FD940E01B47}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
@@ -16,4 +19,10 @@ Global
{A7FD1DC6-AE2B-4F17-B4BA-2FD940E01B47}.ExportRelease|Any CPU.ActiveCfg = ExportRelease|Any CPU
{A7FD1DC6-AE2B-4F17-B4BA-2FD940E01B47}.ExportRelease|Any CPU.Build.0 = ExportRelease|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {0C32B76F-38AD-4A1A-80F4-46FFBBB4BFB2}
EndGlobalSection
EndGlobal

View File

@@ -20,19 +20,19 @@ export DISPLAY=":0"
ARG1="${1:-''}"
if ! command -v git &> /dev/null; then
echo "ERROR: git must be installed and in PATH."
exit 1
echo "ERROR: git must be installed and in PATH."
exit 1
fi
if [[ "$ARG1" == "--help" || "$ARG1" == "-h" ]]; then
echo "Usage: $0 [--skip-build]"
exit
echo "Usage: $0 [--skip-build]"
exit
fi
GODOT_REPO_DIR="$DIR/godot"
if [[ ! -d "$GODOT_REPO_DIR/.git" ]]; then
git clone https://github.com/godotengine/godot.git "$GODOT_REPO_DIR"
git clone https://github.com/godotengine/godot.git "$GODOT_REPO_DIR"
fi
pushd "$GODOT_REPO_DIR"
@@ -48,64 +48,64 @@ latest_commit="$(git -C "$GODOT_REPO_DIR" rev-parse HEAD)"
pushd /tmp/godot-benchmarks-results/
for result in 2*.md; do
if [[ "${result:11:9}" == "${latest_commit:0:9}" ]]; then
echo "godot-benchmarks: Skipping benchmark run as the latest Godot commit is already present in the results repository."
exit
fi
if [[ "${result:11:9}" == "${latest_commit:0:9}" ]]; then
echo "godot-benchmarks: Skipping benchmark run as the latest Godot commit is already present in the results repository."
exit
fi
done
popd
GODOT_EMPTY_PROJECT_DIR="$DIR/web/godot-empty-project"
if [[ "$ARG1" != "--skip-build" ]]; then
cd "$GODOT_REPO_DIR"
cd "$GODOT_REPO_DIR"
if command -v ccache &> /dev/null; then
# Clear ccache to avoid skewing the build time results.
ccache --clear
fi
touch .gdignore
if command -v ccache &> /dev/null; then
# Clear ccache to avoid skewing the build time results.
ccache --clear
fi
touch .gdignore
# Measure clean build times for debug and release builds (in milliseconds).
# Also create a `.gdignore` file to prevent Godot from importing resources
# within the Godot Git clone.
# WARNING: Any untracked and ignored files included in the repository will be removed!
BEGIN="$(date +%s%3N)"
PEAK_MEMORY_BUILD_DEBUG=$( (/usr/bin/time -f "%M" scons platform=linuxbsd target=editor optimize=debug module_mono_enabled=no progress=no debug_symbols=yes -j$(nproc) 2>&1 || true) | tail -1)
END="$(date +%s%3N)"
TIME_TO_BUILD_DEBUG="$((END - BEGIN))"
# Measure clean build times for debug and release builds (in milliseconds).
# Also create a `.gdignore` file to prevent Godot from importing resources
# within the Godot Git clone.
# WARNING: Any untracked and ignored files included in the repository will be removed!
BEGIN="$(date +%s%3N)"
PEAK_MEMORY_BUILD_DEBUG=$( (/usr/bin/time -f "%M" scons platform=linuxbsd target=editor optimize=debug module_mono_enabled=no progress=no debug_symbols=yes -j$(nproc) 2>&1 || true) | tail -1)
END="$(date +%s%3N)"
TIME_TO_BUILD_DEBUG="$((END - BEGIN))"
git clean -qdfx --exclude bin
if command -v ccache &> /dev/null; then
# Clear ccache to avoid skewing the build time results.
ccache --clear
fi
touch .gdignore
git clean -qdfx --exclude bin
if command -v ccache &> /dev/null; then
# Clear ccache to avoid skewing the build time results.
ccache --clear
fi
touch .gdignore
BEGIN="$(date +%s%3N)"
PEAK_MEMORY_BUILD_RELEASE=$( (/usr/bin/time -f "%M" scons platform=linuxbsd target=template_release optimize=speed lto=full module_mono_enabled=no progress=no debug_symbols=yes -j$(nproc) 2>&1 || true) | tail -1)
END="$(date +%s%3N)"
TIME_TO_BUILD_RELEASE="$((END - BEGIN))"
BEGIN="$(date +%s%3N)"
PEAK_MEMORY_BUILD_RELEASE=$( (/usr/bin/time -f "%M" scons platform=linuxbsd target=template_release optimize=speed lto=full module_mono_enabled=no progress=no debug_symbols=yes -j$(nproc) 2>&1 || true) | tail -1)
END="$(date +%s%3N)"
TIME_TO_BUILD_RELEASE="$((END - BEGIN))"
# FIXME: C# is disabled because the engine crashes on exit after running benchmarks.
#
# Generate Mono glue for C# build to work.
# echo "Generating .NET glue."
# bin/godot.linuxbsd.editor.x86_64.mono --headless --generate-mono-glue modules/mono/glue
# echo "Building .NET assemblies."
# # https://docs.godotengine.org/en/stable/contributing/development/compiling/compiling_with_dotnet.html#nuget-packages
# mkdir -p "$HOME/MyLocalNugetSource"
# # Source may already exist, so allow failure for the command below.
# dotnet nuget add source "$HOME/MyLocalNugetSource" --name MyLocalNugetSource || true
# modules/mono/build_scripts/build_assemblies.py --godot-output-dir=./bin --push-nupkgs-local "$HOME/MyLocalNugetSource"
# FIXME: C# is disabled because the engine crashes on exit after running benchmarks.
#
# Generate Mono glue for C# build to work.
# echo "Generating .NET glue."
# bin/godot.linuxbsd.editor.x86_64.mono --headless --generate-mono-glue modules/mono/glue
# echo "Building .NET assemblies."
# # https://docs.godotengine.org/en/stable/contributing/development/compiling/compiling_with_dotnet.html#nuget-packages
# mkdir -p "$HOME/MyLocalNugetSource"
# # Source may already exist, so allow failure for the command below.
# dotnet nuget add source "$HOME/MyLocalNugetSource" --name MyLocalNugetSource || true
# modules/mono/build_scripts/build_assemblies.py --godot-output-dir=./bin --push-nupkgs-local "$HOME/MyLocalNugetSource"
cd "$DIR"
cd "$DIR"
else
echo "run-benchmarks: Skipping engine build as requested on the command line."
TIME_TO_BUILD_DEBUG=1
TIME_TO_BUILD_RELEASE=1
PEAK_MEMORY_BUILD_DEBUG=1
PEAK_MEMORY_BUILD_RELEASE=1
echo "run-benchmarks: Skipping engine build as requested on the command line."
TIME_TO_BUILD_DEBUG=1
TIME_TO_BUILD_RELEASE=1
PEAK_MEMORY_BUILD_DEBUG=1
PEAK_MEMORY_BUILD_RELEASE=1
fi
# Path to the Godot debug binary to run. Used for CPU debug benchmarks.
@@ -128,7 +128,7 @@ $GODOT_DEBUG --audio-driver Dummy --gpu-index 1 --path "$GODOT_EMPTY_PROJECT_DIR
TOTAL=0
for _ in {0..19}; do
BEGIN="$(date +%s%3N)"
echo "Performing benchmark debug startup/shutdown run."
echo "Performing benchmark debug startup/shutdown run."
$GODOT_DEBUG --audio-driver Dummy --gpu-index 1 --path "$GODOT_EMPTY_PROJECT_DIR" --quit || true
END="$(date +%s%3N)"
TOTAL="$((TOTAL + END - BEGIN))"
@@ -144,7 +144,7 @@ $GODOT_RELEASE --audio-driver Dummy --path "$GODOT_EMPTY_PROJECT_DIR" --quit ||
TOTAL=0
for _ in {0..19}; do
BEGIN="$(date +%s%3N)"
echo "Performing benchmark release startup/shutdown run."
echo "Performing benchmark release startup/shutdown run."
$GODOT_RELEASE --audio-driver Dummy --path "$GODOT_EMPTY_PROJECT_DIR" --quit || true
END="$(date +%s%3N)"
TOTAL="$((TOTAL + END - BEGIN))"
@@ -199,24 +199,24 @@ BINARY_SIZE_RELEASE="$(stat --printf="%s" "$GODOT_RELEASE")"
echo "Appending extra JSON at the end of the merged JSON."
EXTRA_JSON=$(cat << EOF
"binary_size": {
"debug": $BINARY_SIZE_DEBUG,
"release": $BINARY_SIZE_RELEASE
"debug": $BINARY_SIZE_DEBUG,
"release": $BINARY_SIZE_RELEASE
},
"build_time": {
"debug": $TIME_TO_BUILD_DEBUG,
"release": $TIME_TO_BUILD_RELEASE
"debug": $TIME_TO_BUILD_DEBUG,
"release": $TIME_TO_BUILD_RELEASE
},
"build_peak_memory_usage": {
"debug": $PEAK_MEMORY_BUILD_DEBUG,
"release": $PEAK_MEMORY_BUILD_RELEASE
"debug": $PEAK_MEMORY_BUILD_DEBUG,
"release": $PEAK_MEMORY_BUILD_RELEASE
},
"empty_project_startup_shutdown_time": {
"debug": $TIME_TO_STARTUP_SHUTDOWN_DEBUG,
"release": $TIME_TO_STARTUP_SHUTDOWN_RELEASE
"debug": $TIME_TO_STARTUP_SHUTDOWN_DEBUG,
"release": $TIME_TO_STARTUP_SHUTDOWN_RELEASE
},
"empty_project_startup_shutdown_peak_memory_usage": {
"debug": $PEAK_MEMORY_STARTUP_SHUTDOWN_DEBUG,
"release": $PEAK_MEMORY_STARTUP_SHUTDOWN_RELEASE
"debug": $PEAK_MEMORY_STARTUP_SHUTDOWN_DEBUG,
"release": $PEAK_MEMORY_STARTUP_SHUTDOWN_RELEASE
}
EOF
)

View File

@@ -1,27 +1,27 @@
Section "ServerLayout"
Identifier "default-layout"
Screen 0 "screen"
Identifier "default-layout"
Screen 0 "screen"
EndSection
Section "Device"
Identifier "amd"
Driver "amdgpu"
BusID "PCI:1:0:0"
Identifier "amd"
Driver "amdgpu"
BusID "PCI:1:0:0"
EndSection
Section "Monitor"
Identifier "monitor"
Modeline "1920x1200_60.00" 193.25 1920 2056 2256 2592 1200 1203 1209 1245 -hsync +vsync
Option "PreferredMode" "1920x1080_60.00"
Identifier "monitor"
Modeline "1920x1200_60.00" 193.25 1920 2056 2256 2592 1200 1203 1209 1245 -hsync +vsync
Option "PreferredMode" "1920x1080_60.00"
EndSection
Section "Screen"
Identifier "screen"
Device "amd"
Monitor "monitor"
DefaultDepth 24
SubSection "Display"
Depth 24
Modes "1920x1080"
EndSubSection
Identifier "screen"
Device "amd"
Monitor "monitor"
DefaultDepth 24
SubSection "Display"
Depth 24
Modes "1920x1080"
EndSubSection
EndSection

1
web/.gitattributes vendored
View File

@@ -1 +0,0 @@
static/thirdparty/* linguist-vendored

14
web/.gitignore vendored
View File

@@ -1,14 +0,0 @@
# Output HTML files
public/
# Temporary lock file while building
.hugo_build.lock
# Generated files
content/benchmark/*.md
content/graph/*.md
data/data.json
# Untracked source files
src-data/benchmarks/*.md
src-data/benchmarks/*.json

View File

@@ -1,209 +1,209 @@
function getAllowedMetrics() {
const allowedMetrics = new Set();
Database.benchmarks.forEach((benchmark) => {
benchmark.benchmarks.forEach((instance) => {
Object.entries(instance.results).forEach(([key, value]) => {
allowedMetrics.add(key);
});
});
});
return allowedMetrics;
const allowedMetrics = new Set();
Database.benchmarks.forEach((benchmark) => {
benchmark.benchmarks.forEach((instance) => {
Object.entries(instance.results).forEach(([key, value]) => {
allowedMetrics.add(key);
});
});
});
return allowedMetrics;
}
function displayGraph(targetDivID, graphID, type = "full", filter = "") {
if (!["full", "compact"].includes(type)) {
throw Error("Unknown chart type");
}
if (!["full", "compact"].includes(type)) {
throw Error("Unknown chart type");
}
// Include benchmark data JSON to generate graphs.
const allBenchmarks = Database.benchmarks.sort(
(a, b) => `${a.date}.${a.commit}` > `${b.date}.${b.commit}`,
);
const graph = Database.graphs.find((g) => g.id == graphID);
if (!graph) {
throw new Error("Invalid graph ID");
}
// Group by series.
const xAxis = [];
const series = new Map();
const processResult = (path, data, process) => {
Object.entries(data).forEach(([key, value]) => {
if (typeof value === "object") {
processResult(path + "/" + key, value, process);
} else {
// Number
process(path + "/" + key, value);
}
});
};
// Include benchmark data JSON to generate graphs.
const allBenchmarks = Database.benchmarks.sort(
(a, b) => `${a.date}.${a.commit}` > `${b.date}.${b.commit}`,
);
const graph = Database.graphs.find((g) => g.id == graphID);
if (!graph) {
throw new Error("Invalid graph ID");
}
// Group by series.
const xAxis = [];
const series = new Map();
const processResult = (path, data, process) => {
Object.entries(data).forEach(([key, value]) => {
if (typeof value === "object") {
processResult(path + "/" + key, value, process);
} else {
// Number
process(path + "/" + key, value);
}
});
};
// Get list all series and fill it in.
allBenchmarks.forEach((benchmark, count) => {
// Process a day/commit
xAxis.push(benchmark.date + "." + benchmark.commit);
// Get list all series and fill it in.
allBenchmarks.forEach((benchmark, count) => {
// Process a day/commit
xAxis.push(benchmark.date + "." + benchmark.commit);
// Get all series.
benchmark.benchmarks.forEach((instance) => {
let instanceKey = instance.path.join("/");
if (!instanceKey.startsWith(graph["benchmark-path-prefix"])) {
return;
}
instanceKey = instanceKey.slice(
graph["benchmark-path-prefix"].length + 1,
);
// Get all series.
benchmark.benchmarks.forEach((instance) => {
let instanceKey = instance.path.join("/");
if (!instanceKey.startsWith(graph["benchmark-path-prefix"])) {
return;
}
instanceKey = instanceKey.slice(
graph["benchmark-path-prefix"].length + 1,
);
processResult(instanceKey, instance.results, (path, value) => {
// Filter out paths that do not fit the filter
if (filter && !path.includes(filter)) {
return;
}
if (!series.has(path)) {
series.set(path, Array(count).fill(null));
}
series.get(path).push(value);
});
});
});
processResult(instanceKey, instance.results, (path, value) => {
// Filter out paths that do not fit the filter
if (filter && !path.includes(filter)) {
return;
}
if (!series.has(path)) {
series.set(path, Array(count).fill(null));
}
series.get(path).push(value);
});
});
});
let customColor = undefined;
let customColor = undefined;
if (type === "compact") {
// Kind of "normalize" the series, dividing by the average.
series.forEach((serie, key) => {
let count = 0;
let mean = 0.0;
serie.forEach((el) => {
if (el != null) {
mean += el;
count += 1;
}
});
mean = mean / count;
if (type === "compact") {
// Kind of "normalize" the series, dividing by the average.
series.forEach((serie, key) => {
let count = 0;
let mean = 0.0;
serie.forEach((el) => {
if (el != null) {
mean += el;
count += 1;
}
});
mean = mean / count;
//const std = Math.sqrt(input.map(x => Math.pow(x - mean, 2)).reduce((a, b) => a + b) / n)
series.set(
key,
serie.map((v) => {
if (v != null) {
return v / mean; // Devide by the mean.
}
return null;
}),
);
});
// Combine all into a single, averaged serie.
const outputSerie = [];
for (let i = 0; i < allBenchmarks.length; i++) {
let count = 0;
let sum = 0;
series.forEach((serie, key) => {
if (serie[i] != null) {
count += 1;
sum += serie[i];
}
});
let point = null;
if (count >= 1) {
point = Math.round((sum * 1000) / count) / 10; // Round to 3 decimals.
}
outputSerie.push(point);
}
series.clear();
series.set("Average", outputSerie);
//const std = Math.sqrt(input.map(x => Math.pow(x - mean, 2)).reduce((a, b) => a + b) / n)
series.set(
key,
serie.map((v) => {
if (v != null) {
return v / mean; // Devide by the mean.
}
return null;
}),
);
});
// Combine all into a single, averaged serie.
const outputSerie = [];
for (let i = 0; i < allBenchmarks.length; i++) {
let count = 0;
let sum = 0;
series.forEach((serie, key) => {
if (serie[i] != null) {
count += 1;
sum += serie[i];
}
});
let point = null;
if (count >= 1) {
point = Math.round((sum * 1000) / count) / 10; // Round to 3 decimals.
}
outputSerie.push(point);
}
series.clear();
series.set("Average", outputSerie);
// Detect whether we went down or not on the last 10 benchmarks.
const lastElementsCount = 3;
const totalConsideredCount = 10;
const lastElements = outputSerie.slice(-lastElementsCount);
const comparedTo = outputSerie.slice(
-totalConsideredCount,
-lastElementsCount,
);
const avgLast = lastElements.reduce((a, b) => a + b) / lastElements.length;
const avgComparedTo =
comparedTo.reduce((a, b) => a + b) / comparedTo.length;
const trend = avgLast - avgComparedTo;
// Detect whether we went down or not on the last 10 benchmarks.
const lastElementsCount = 3;
const totalConsideredCount = 10;
const lastElements = outputSerie.slice(-lastElementsCount);
const comparedTo = outputSerie.slice(
-totalConsideredCount,
-lastElementsCount,
);
const avgLast = lastElements.reduce((a, b) => a + b) / lastElements.length;
const avgComparedTo =
comparedTo.reduce((a, b) => a + b) / comparedTo.length;
const trend = avgLast - avgComparedTo;
if (trend > 10) {
customColor = "#E20000";
} else if (trend < -10) {
customColor = "#00E200";
}
}
if (trend > 10) {
customColor = "#E20000";
} else if (trend < -10) {
customColor = "#00E200";
}
}
var options = {
series: Array.from(series.entries()).map(([key, value]) => ({
name: key,
data: value,
})),
chart: {
foreColor: "var(--text-bright)",
background: "var(--background)",
height: type === "compact" ? 200 : 600,
type: "line",
zoom: {
enabled: false,
},
toolbar: {
show: false,
},
animations: {
enabled: false,
},
},
tooltip: {
theme: "dark",
y: {
formatter: (value, opts) => (type === "compact" ? value + "%" : value),
},
},
dataLabels: {
enabled: false,
},
stroke: {
curve: "straight",
width: 2,
},
theme: {
palette: "palette4",
},
fill:
type === "compact"
? {
type: "gradient",
gradient: {
shade: "dark",
gradientToColors: ["#4ecdc4"],
shadeIntensity: 1,
type: "horizontal",
opacityFrom: 1,
opacityTo: 1,
stops: [0, 100],
},
}
: {},
colors:
type === "compact"
? customColor
? [customColor]
: ["#4ecdc4"]
: undefined,
xaxis: {
categories: xAxis,
labels: {
show: type !== "compact",
},
},
yaxis: {
tickAmount: 4,
min: type === "compact" ? 0 : undefined,
max: type === "compact" ? 200 : undefined,
},
legend: {
show: type !== "compact",
},
};
var options = {
series: Array.from(series.entries()).map(([key, value]) => ({
name: key,
data: value,
})),
chart: {
foreColor: "var(--text-bright)",
background: "var(--background)",
height: type === "compact" ? 200 : 600,
type: "line",
zoom: {
enabled: false,
},
toolbar: {
show: false,
},
animations: {
enabled: false,
},
},
tooltip: {
theme: "dark",
y: {
formatter: (value, opts) => (type === "compact" ? value + "%" : value),
},
},
dataLabels: {
enabled: false,
},
stroke: {
curve: "straight",
width: 2,
},
theme: {
palette: "palette4",
},
fill:
type === "compact"
? {
type: "gradient",
gradient: {
shade: "dark",
gradientToColors: ["#4ecdc4"],
shadeIntensity: 1,
type: "horizontal",
opacityFrom: 1,
opacityTo: 1,
stops: [0, 100],
},
}
: {},
colors:
type === "compact"
? customColor
? [customColor]
: ["#4ecdc4"]
: undefined,
xaxis: {
categories: xAxis,
labels: {
show: type !== "compact",
},
},
yaxis: {
tickAmount: 4,
min: type === "compact" ? 0 : undefined,
max: type === "compact" ? 200 : undefined,
},
legend: {
show: type !== "compact",
},
};
var chart = new ApexCharts(document.querySelector(targetDivID), options);
chart.render();
var chart = new ApexCharts(document.querySelector(targetDivID), options);
chart.render();
}

View File

@@ -1,39 +1,39 @@
/* See `thirdparty/water.css` for CSS variables that can be used here. */
p, li {
line-height: 1.6;
line-height: 1.6;
}
footer {
text-align: center;
text-align: center;
}
header {
background-color: var(--background);
border-radius: 0 0 6px 6px;
padding: .75rem 2rem;
margin-top: -1.25rem;
margin-bottom: 2rem;
background-color: var(--background);
border-radius: 0 0 6px 6px;
padding: .75rem 2rem;
margin-top: -1.25rem;
margin-bottom: 2rem;
}
.site-title {
color: var(--text-bright);
font-weight: bold;
font-size: 1.25rem;
border-radius: 6px;
color: var(--text-bright);
font-weight: bold;
font-size: 1.25rem;
border-radius: 6px;
}
/* Automatically resize the left column to take as little space as required. */
.table-first-column-align-right {
width: auto;
width: auto;
}
/* Align first column to the right to improve readability in some situations. */
.table-first-column-align-right tr td:first-of-type {
text-align: right;
width: 1%;
white-space: nowrap;
/* Style the first column as headings. */
font-weight: bold;
text-align: right;
width: 1%;
white-space: nowrap;
/* Style the first column as headings. */
font-weight: bold;
}