chore: remove legacy Zola site and superseded files
The Astro app in apps/site is now the production build (root Dockerfile already builds it, not `zola build`), so the old Zola templates, Sass, static assets, and build tooling are dead weight: - templates/, sass/, static/, themes/, zola.toml, Makefile, bin/update-zola - content/posts/ (fully migrated to content/writings/) and the legacy content/archive, content/about.md, content/_index.md pages - legacy OG-image/llms.txt generation scripts (superseded by the *.astro-site.mjs versions apps/site's build already uses) - unrelated stray files (manimations/, build.sh) Also drops apps/site/src/pages/search.astro, replaced by the search modal, and swaps in the real favicon.ico.
@@ -1,3 +0,0 @@
|
||||
{
|
||||
"snyk.advanced.autoSelectOrganization": true
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
#!/usr/bin/make -f
|
||||
|
||||
.PHONY: all build
|
||||
|
||||
BUILD_DIR := public
|
||||
|
||||
all: clean build
|
||||
|
||||
clean:
|
||||
rm -rfd ./$(BUILD_DIR)
|
||||
|
||||
build:
|
||||
node scripts/generate-llms.mjs
|
||||
zola build
|
||||
|
||||
serve:
|
||||
node scripts/generate-llms.mjs
|
||||
zola serve
|
||||
|
||||
update-zola:
|
||||
@./bin/update-zola
|
||||
|
Before Width: | Height: | Size: 655 B After Width: | Height: | Size: 2.9 KiB |
@@ -1,9 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 128 128">
|
||||
<path d="M50.4 78.5a75.1 75.1 0 0 0-28.5 6.9l24.2-65.7c.7-2 1.9-3.2 3.4-3.2h29c1.5 0 2.7 1.2 3.4 3.2l24.2 65.7s-11.6-7-28.5-7L67 45.5c-.4-1.7-1.6-2.8-2.9-2.8-1.3 0-2.5 1.1-2.9 2.7L50.4 78.5Zm-1.1 28.2Zm-4.2-20.2c-2 6.6-.6 15.8 4.2 20.2a17.5 17.5 0 0 1 .2-.7 5.5 5.5 0 0 1 5.7-4.5c2.8.1 4.3 1.5 4.7 4.7.2 1.1.2 2.3.2 3.5v.4c0 2.7.7 5.2 2.2 7.4a13 13 0 0 0 5.7 4.9v-.3l-.2-.3c-1.8-5.6-.5-9.5 4.4-12.8l1.5-1a73 73 0 0 0 3.2-2.2 16 16 0 0 0 6.8-11.4c.3-2 .1-4-.6-6l-.8.6-1.6 1a37 37 0 0 1-22.4 2.7c-5-.7-9.7-2-13.2-6.2Z" />
|
||||
<style>
|
||||
path { fill: #000; }
|
||||
@media (prefers-color-scheme: dark) {
|
||||
path { fill: #FFF; }
|
||||
}
|
||||
</style>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 749 B |
@@ -1,22 +0,0 @@
|
||||
---
|
||||
import Base from "../layouts/Base.astro";
|
||||
---
|
||||
|
||||
<Base title="Search">
|
||||
<h1>Search</h1>
|
||||
<p class="meta">
|
||||
Search only works against a built site (`pnpm build` runs Pagefind after
|
||||
`astro build`) — it has no index to query in `astro dev`.
|
||||
</p>
|
||||
<div id="search"></div>
|
||||
<link href="/pagefind/pagefind-ui.css" rel="stylesheet" />
|
||||
<script is:inline src="/pagefind/pagefind-ui.js"></script>
|
||||
<script is:inline>
|
||||
window.addEventListener("DOMContentLoaded", () => {
|
||||
if (window.PagefindUI) {
|
||||
// biome-ignore lint/correctness/noUndeclaredVariables: loaded from /pagefind/pagefind-ui.js above
|
||||
new PagefindUI({ element: "#search", showSubResults: true });
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</Base>
|
||||
@@ -1,62 +0,0 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
set -e
|
||||
|
||||
: ${ZOLA_REPO='https://github.com/getzola/zola'}
|
||||
: ${ZOLA_INSTALL_DIR="${HOME}/.cargo/bin"}
|
||||
|
||||
# Helpers for ANSI color and logging.
|
||||
name="$(basename $0)"; esc=''; reset="${esc}[0m"
|
||||
red() { local string="${1}"; echo "${esc}[31m${string}${reset}"; }
|
||||
yellow() { local string="${1}"; echo "${esc}[33m${string}${reset}"; }
|
||||
green() { local string="${1}"; echo "${esc}[32m${string}${reset}"; }
|
||||
blue() { local string="${1}"; echo "${esc}[34m${string}${reset}"; }
|
||||
magenta() { local string="${1}"; echo "${esc}[35m${string}${reset}"; }
|
||||
log() { local string="${1}"; echo "[$(blue $name)] ${string}"; }
|
||||
|
||||
prompt_for_update() {
|
||||
local current="${1}"
|
||||
local latest="${2}"
|
||||
|
||||
[ -n "${current}" ] \
|
||||
&& installed="You're using Zola $(yellow $current)" \
|
||||
|| installed="Zola is $(red 'not installed')"
|
||||
|
||||
log "${installed}, but $(magenta $latest) is available."
|
||||
|
||||
# Prompt for an update. Exit the entire script if declined.
|
||||
read -p "$(log "Would you like to install Zola $(magenta $latest)? [y/N]: ")" answer
|
||||
case $answer in
|
||||
[Yy]*) log "Downloading Zola $(magenta $latest) from GitHub." ;;
|
||||
[Nn]*|*) log $(red "Aborted!"); exit ;;
|
||||
esac
|
||||
}
|
||||
|
||||
install_zola() {
|
||||
local version="${1}"
|
||||
local download_url="${ZOLA_REPO}/releases/download/${version}/zola-${version}-x86_64-unknown-linux-gnu.tar.gz"
|
||||
|
||||
curl --progress-bar --location $download_url | tar --gunzip --extract --directory=$ZOLA_INSTALL_DIR --file -
|
||||
}
|
||||
|
||||
update_zola() {
|
||||
# Find the current Zola version (if any).
|
||||
[ -n "$(which zola 2> /dev/null)" ] && current_version=$(zola --version | awk '{print "v"$2}')
|
||||
|
||||
# Find the latest available Zola version. Use --refs to avoid listing
|
||||
# annotated commit objects that include the dereference syntax '^{}'.
|
||||
# Find more background at https://stackoverflow.com/a/15472310.
|
||||
local latest_version=$(git ls-remote --tags --refs $ZOLA_REPO | # Fetch remote tags.
|
||||
sort -t '/' -k 3 -V | # Sort them by version.
|
||||
tail -n 1 | # Take the latest one.
|
||||
awk -F / '{print $3}') # Return only the tag.
|
||||
|
||||
if [ "${current_version}" != "${latest_version}" ]; then
|
||||
prompt_for_update "${current_version}" "${latest_version}"
|
||||
install_zola "${latest_version}"
|
||||
fi
|
||||
|
||||
log "You're using Zola $(magenta $latest_version). $(green "Everything is up-to-date!")"
|
||||
}
|
||||
|
||||
update_zola
|
||||
@@ -1,17 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
ZOLA_VERSION=0.23.1
|
||||
|
||||
echo "Downloading Zola ${ZOLA_VERSION}..."
|
||||
curl -sLJO "https://github.com/getzola/zola/releases/download/v${ZOLA_VERSION}/zola-v${ZOLA_VERSION}-x86_64-unknown-linux-gnu.tar.gz"
|
||||
|
||||
echo "Extracting Zola..."
|
||||
tar -xf zola-v${ZOLA_VERSION}-x86_64-unknown-linux-gnu.tar.gz
|
||||
|
||||
echo "Building site with Zola..."
|
||||
node scripts/generate-llms.mjs
|
||||
./zola build
|
||||
|
||||
echo "Build complete! Generated files:"
|
||||
ls -la public/
|
||||
@@ -1,15 +0,0 @@
|
||||
+++
|
||||
title = "Why This Site Exists"
|
||||
description = "A short note on what this new site is, and why it's more than a tech blog."
|
||||
author = "andwati"
|
||||
date = 2026-08-30
|
||||
draft = false
|
||||
[taxonomies]
|
||||
tags = ["meta"]
|
||||
[extra]
|
||||
llms_description = "An introductory post explaining the purpose of this personal digital-legacy site."
|
||||
+++
|
||||
|
||||
This is a placeholder post establishing the `writings` content schema. It will
|
||||
be replaced once the design system and migration from the old Zola posts are
|
||||
ready.
|
||||
@@ -1,136 +0,0 @@
|
||||
# Byte-compiled / optimized / DLL files
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
*$py.class
|
||||
|
||||
# C extensions
|
||||
*.so
|
||||
|
||||
# Distribution / packaging
|
||||
.Python
|
||||
build/
|
||||
develop-eggs/
|
||||
dist/
|
||||
downloads/
|
||||
eggs/
|
||||
.eggs/
|
||||
lib/
|
||||
lib64/
|
||||
parts/
|
||||
sdist/
|
||||
var/
|
||||
wheels/
|
||||
pip-wheel-metadata/
|
||||
share/python-wheels/
|
||||
*.egg-info/
|
||||
.installed.cfg
|
||||
*.egg
|
||||
MANIFEST
|
||||
|
||||
# PyInstaller
|
||||
# Usually these files are written by a python script from a template
|
||||
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
||||
*.manifest
|
||||
*.spec
|
||||
|
||||
# Installer logs
|
||||
pip-log.txt
|
||||
pip-delete-this-directory.txt
|
||||
|
||||
# Unit test / coverage reports
|
||||
htmlcov/
|
||||
.tox/
|
||||
.nox/
|
||||
.coverage
|
||||
.coverage.*
|
||||
.cache
|
||||
nosetests.xml
|
||||
coverage.xml
|
||||
*.cover
|
||||
*.py,cover
|
||||
.hypothesis/
|
||||
.pytest_cache/
|
||||
|
||||
*.log
|
||||
|
||||
# Sphinx documentation
|
||||
docs/_build/
|
||||
docs/build/
|
||||
docs/source/_autosummary/
|
||||
docs/source/reference/
|
||||
docs/source/_build/
|
||||
docs/rendering_times.csv
|
||||
#i18n
|
||||
docs/i18n/gettext/.doctrees
|
||||
docs/i18n/**/*.mo
|
||||
docs/i18n/translatable.po
|
||||
docs/i18n/untranslatable.po
|
||||
|
||||
# PyBuilder
|
||||
target/
|
||||
|
||||
# Jupyter Notebook
|
||||
jupyter/
|
||||
.ipynb_checkpoints
|
||||
|
||||
# IPython
|
||||
profile_default/
|
||||
ipython_config.py
|
||||
|
||||
# pyenv
|
||||
.python-version
|
||||
|
||||
# pipenv
|
||||
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
||||
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
||||
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
||||
# install all needed dependencies.
|
||||
#Pipfile.lock
|
||||
|
||||
# PEP 582; used by e.g. github.com/David-OConnor/pyflow
|
||||
__pypackages__/
|
||||
|
||||
# PyCharm
|
||||
/.idea/
|
||||
|
||||
# Celery stuff
|
||||
celerybeat-schedule
|
||||
celerybeat.pid
|
||||
|
||||
# Environments
|
||||
.env
|
||||
.venv
|
||||
env/
|
||||
venv/
|
||||
ENV/
|
||||
env.bak/
|
||||
venv.bak/
|
||||
|
||||
# mkdocs documentation
|
||||
/site
|
||||
|
||||
# mypy
|
||||
.mypy_cache/
|
||||
.dmypy.json
|
||||
dmypy.json
|
||||
|
||||
*.pyc
|
||||
*.bak
|
||||
.DS_Store
|
||||
|
||||
.floo
|
||||
.flooignore
|
||||
.vscode
|
||||
.vs
|
||||
*.xml
|
||||
*.iml
|
||||
media
|
||||
.eggs/
|
||||
build/
|
||||
dist/
|
||||
|
||||
/media_dir.txt
|
||||
# ^TODO: Remove the need for this with a proper config file
|
||||
|
||||
# Ignore the built dependencies
|
||||
third_party/*
|
||||
@@ -1,579 +0,0 @@
|
||||
from manim import *
|
||||
|
||||
# ─────────────────────────────────────────────
|
||||
# Shared palette
|
||||
# ─────────────────────────────────────────────
|
||||
BG = "#0d1117"
|
||||
ACCENT = "#58a6ff"
|
||||
GREEN = "#3fb950"
|
||||
ORANGE = "#f0883e"
|
||||
RED = "#f85149"
|
||||
PURPLE = "#bc8cff"
|
||||
GRAY = "#8b949e"
|
||||
WHITE = "#e6edf3"
|
||||
|
||||
config.background_color = BG
|
||||
|
||||
|
||||
# ─────────────────────────────────────────────
|
||||
# Helper: section title card
|
||||
# ─────────────────────────────────────────────
|
||||
def title_card(scene: Scene, title: str, subtitle: str = ""):
|
||||
bg = Rectangle(width=14, height=8, fill_color=BG, fill_opacity=1, stroke_width=0)
|
||||
bar = Line(LEFT * 6, RIGHT * 6, color=ACCENT, stroke_width=3)
|
||||
t = Text(title, font="JetBrains Mono", color=WHITE, font_size=52, weight=BOLD)
|
||||
s = Text(subtitle, font="JetBrains Mono", color=GRAY, font_size=28) if subtitle else VMobject()
|
||||
t.move_to(UP * 0.4)
|
||||
s.next_to(t, DOWN, buff=0.4)
|
||||
bar.next_to(t, UP, buff=0.55)
|
||||
grp = VGroup(bg, bar, t, s)
|
||||
scene.play(FadeIn(bar), Write(t), FadeIn(s), run_time=1.4)
|
||||
scene.wait(1.5)
|
||||
scene.play(FadeOut(grp), run_time=0.6)
|
||||
|
||||
|
||||
# ─────────────────────────────────────────────
|
||||
# 1. Intro
|
||||
# ─────────────────────────────────────────────
|
||||
class S01_Intro(Scene):
|
||||
def construct(self):
|
||||
# Animated headline
|
||||
headline = Text("From C to Machine Code", font="JetBrains Mono",
|
||||
color=ACCENT, font_size=56, weight=BOLD)
|
||||
sub = Text("What Actually Runs", font="JetBrains Mono",
|
||||
color=WHITE, font_size=34)
|
||||
byline = Text("mockingspectre", font="JetBrains Mono",
|
||||
color=GRAY, font_size=22)
|
||||
|
||||
headline.move_to(UP * 1.2)
|
||||
sub.next_to(headline, DOWN, buff=0.5)
|
||||
byline.next_to(sub, DOWN, buff=0.7)
|
||||
|
||||
accent_line = Line(LEFT * 3.5, RIGHT * 3.5, color=ACCENT, stroke_width=2)
|
||||
accent_line.next_to(sub, DOWN, buff=0.3)
|
||||
|
||||
self.play(Write(headline), run_time=1.6)
|
||||
self.play(FadeIn(sub, shift=UP * 0.3), run_time=0.9)
|
||||
self.play(GrowFromCenter(accent_line), run_time=0.6)
|
||||
self.play(FadeIn(byline), run_time=0.7)
|
||||
self.wait(2.5)
|
||||
|
||||
# C → ASM → Binary flow diagram
|
||||
c_box = self._box("C Source", GREEN, LEFT * 4.5)
|
||||
asm_box = self._box("Assembly", ORANGE, ORIGIN)
|
||||
bin_box = self._box("Machine\nCode", RED, RIGHT * 4.5)
|
||||
|
||||
arr1 = Arrow(c_box.get_right(), asm_box.get_left(), color=ACCENT, buff=0.15)
|
||||
arr2 = Arrow(asm_box.get_right(), bin_box.get_left(), color=ACCENT, buff=0.15)
|
||||
lbl1 = Text("GCC compiler", font="JetBrains Mono", color=GRAY, font_size=18).next_to(arr1, UP, buff=0.1)
|
||||
lbl2 = Text("assemble", font="JetBrains Mono", color=GRAY, font_size=18).next_to(arr2, UP, buff=0.1)
|
||||
|
||||
self.play(FadeOut(headline, sub, accent_line, byline), run_time=0.5)
|
||||
self.play(FadeIn(c_box), run_time=0.5)
|
||||
self.play(GrowArrow(arr1), FadeIn(lbl1), run_time=0.7)
|
||||
self.play(FadeIn(asm_box), run_time=0.5)
|
||||
self.play(GrowArrow(arr2), FadeIn(lbl2), run_time=0.7)
|
||||
self.play(FadeIn(bin_box), run_time=0.5)
|
||||
self.wait(2.5)
|
||||
self.play(*[FadeOut(m) for m in self.mobjects])
|
||||
|
||||
@staticmethod
|
||||
def _box(label, color, pos):
|
||||
rect = RoundedRectangle(corner_radius=0.2, width=2.6, height=1.1,
|
||||
fill_color=color, fill_opacity=0.15,
|
||||
stroke_color=color, stroke_width=2)
|
||||
txt = Text(label, font="JetBrains Mono", color=color, font_size=24)
|
||||
grp = VGroup(rect, txt).move_to(pos)
|
||||
return grp
|
||||
|
||||
|
||||
# ─────────────────────────────────────────────
|
||||
# 2. Hello World: C → Assembly walkthrough
|
||||
# ─────────────────────────────────────────────
|
||||
class S02_HelloWorld(Scene):
|
||||
def construct(self):
|
||||
title_card(self, "Hello World", "C → Assembly")
|
||||
|
||||
# Left: C code
|
||||
c_src = [
|
||||
("#include <stdio.h>", GRAY),
|
||||
("", WHITE),
|
||||
("int main(){", WHITE),
|
||||
(' printf("hello world\\n");', GREEN),
|
||||
(" return 0;", WHITE),
|
||||
("}", WHITE),
|
||||
]
|
||||
c_lines = VGroup(*[
|
||||
Text(line, font="JetBrains Mono", color=col, font_size=20)
|
||||
for line, col in c_src
|
||||
])
|
||||
c_lines.arrange(DOWN, aligned_edge=LEFT, buff=0.18)
|
||||
c_bg = BackgroundRectangle(c_lines, color="#161b22", fill_opacity=1,
|
||||
buff=0.25, corner_radius=0.15)
|
||||
c_code = VGroup(c_bg, c_lines).shift(LEFT * 3.4 + UP * 0.5)
|
||||
|
||||
c_label = Text("hello.c", font="JetBrains Mono", color=GREEN, font_size=22
|
||||
).next_to(c_code, UP, buff=0.2)
|
||||
|
||||
self.play(FadeIn(c_label), FadeIn(c_code), run_time=1.0)
|
||||
self.wait(0.8)
|
||||
|
||||
# Command
|
||||
cmd_txt = Text("gcc -o hello hello.c && objdump -d -M intel hello",
|
||||
font="JetBrains Mono", color=ORANGE, font_size=17
|
||||
).shift(DOWN * 2.8)
|
||||
self.play(Write(cmd_txt), run_time=1.2)
|
||||
self.wait(0.5)
|
||||
|
||||
# Right: ASM output
|
||||
asm_lines = [
|
||||
("1139:", "55", "push rbp"),
|
||||
("113a:", "48 89 e5", "mov rbp, rsp"),
|
||||
("113d:", "48 8d 05 c0 0e", "lea rax, [rip+0xec0]"),
|
||||
("1144:", "48 89 c7", "mov rdi, rax"),
|
||||
("1147:", "e8 e4 fe ff ff", "call puts@plt"),
|
||||
("114c:", "b8 00 00 00 00", "mov eax, 0x0"),
|
||||
("1151:", "5d", "pop rbp"),
|
||||
("1152:", "c3", "ret"),
|
||||
]
|
||||
asm_group = self._asm_block(asm_lines).shift(RIGHT * 3.1 + UP * 0.5)
|
||||
asm_label = Text("objdump output", font="JetBrains Mono",
|
||||
color=ORANGE, font_size=22).next_to(asm_group, UP, buff=0.2)
|
||||
|
||||
self.play(FadeIn(asm_label), FadeIn(asm_group), run_time=1.0)
|
||||
self.wait(0.5)
|
||||
|
||||
# Annotate key lines — asm_group[0]=bg, asm_group[1]=VGroup of rows
|
||||
rows = asm_group[1]
|
||||
note = Text("rdi ← pointer to \"hello world\"",
|
||||
font="JetBrains Mono", color=ACCENT, font_size=19
|
||||
).next_to(asm_group, DOWN, buff=0.25)
|
||||
self.play(rows[3].animate.set_color(ACCENT),
|
||||
rows[4].animate.set_color(PURPLE),
|
||||
Write(note), run_time=1.0)
|
||||
self.wait(2.5)
|
||||
self.play(*[FadeOut(m) for m in self.mobjects])
|
||||
|
||||
@staticmethod
|
||||
def _asm_block(lines):
|
||||
rows = VGroup()
|
||||
for addr, hex_b, mnemonic in lines:
|
||||
row = Text(f"{addr:<8} {hex_b:<20} {mnemonic}",
|
||||
font="JetBrains Mono", color=WHITE, font_size=17)
|
||||
rows.add(row)
|
||||
rows.arrange(DOWN, aligned_edge=LEFT, buff=0.18)
|
||||
bg = BackgroundRectangle(rows, color="#161b22", fill_opacity=1,
|
||||
buff=0.2, corner_radius=0.15)
|
||||
return VGroup(bg, rows)
|
||||
|
||||
|
||||
# ─────────────────────────────────────────────
|
||||
# 3. Registers
|
||||
# ─────────────────────────────────────────────
|
||||
class S03_Registers(Scene):
|
||||
def construct(self):
|
||||
title_card(self, "Registers", "The CPU's Workbench")
|
||||
|
||||
# Register diagram: rax broken into sub-registers
|
||||
regs = [
|
||||
("rax (64-bit / 8 bytes)", ACCENT, 4.8),
|
||||
("eax (32-bit / 4 bytes)", GREEN, 3.2),
|
||||
("ax (16-bit / 2 bytes)", ORANGE, 1.9),
|
||||
("al ( 8-bit / 1 byte )", RED, 0.95),
|
||||
]
|
||||
bars = VGroup()
|
||||
labels = VGroup()
|
||||
for name, color, width in regs:
|
||||
bar = Rectangle(width=width, height=0.52,
|
||||
fill_color=color, fill_opacity=0.25,
|
||||
stroke_color=color, stroke_width=2)
|
||||
lbl = Text(name, font="JetBrains Mono", color=color, font_size=19)
|
||||
lbl.next_to(bar, RIGHT, buff=0.25)
|
||||
bars.add(bar)
|
||||
labels.add(lbl)
|
||||
|
||||
for i, bar in enumerate(bars):
|
||||
bar.align_to(bars[0], LEFT)
|
||||
group = VGroup(*[VGroup(bars[i], labels[i]) for i in range(len(bars))])
|
||||
group.arrange(DOWN, aligned_edge=LEFT, buff=0.22).shift(LEFT * 1 + UP * 0.5)
|
||||
|
||||
self.play(LaggedStart(*[FadeIn(g) for g in group], lag_ratio=0.3), run_time=1.6)
|
||||
self.wait(1.0)
|
||||
|
||||
caption = Text("Smaller aliases point into the same physical register",
|
||||
font="JetBrains Mono", color=GRAY, font_size=21
|
||||
).shift(DOWN * 2.6)
|
||||
self.play(Write(caption))
|
||||
self.wait(1.5)
|
||||
self.play(FadeOut(group, caption))
|
||||
|
||||
# Calling convention diagram
|
||||
title_card(self, "Calling Convention", "Argument passing in x64 Linux")
|
||||
|
||||
args = [
|
||||
("1st arg", "rdi", ACCENT),
|
||||
("2nd arg", "rsi", GREEN),
|
||||
("3rd arg", "rdx", ORANGE),
|
||||
("4th arg", "rcx", PURPLE),
|
||||
("5th arg", "r8", RED),
|
||||
("6th arg", "r9", GRAY),
|
||||
]
|
||||
cols = VGroup()
|
||||
for label, reg, color in args:
|
||||
arg_t = Text(label, font="JetBrains Mono", color=WHITE, font_size=22)
|
||||
arr = Arrow(LEFT * 0.1, RIGHT * 0.9, color=color, buff=0)
|
||||
reg_t = Text(reg, font="JetBrains Mono", color=color,
|
||||
font_size=26, weight=BOLD)
|
||||
row = VGroup(arg_t, arr, reg_t).arrange(RIGHT, buff=0.3)
|
||||
cols.add(row)
|
||||
cols.arrange(DOWN, buff=0.28).shift(UP * 0.3)
|
||||
|
||||
ret_row = Text("return value → rax", font="JetBrains Mono",
|
||||
color=ACCENT, font_size=24).next_to(cols, DOWN, buff=0.5)
|
||||
|
||||
self.play(LaggedStart(*[FadeIn(r) for r in cols], lag_ratio=0.22), run_time=1.8)
|
||||
self.play(Write(ret_row))
|
||||
self.wait(2.5)
|
||||
self.play(*[FadeOut(m) for m in self.mobjects])
|
||||
|
||||
|
||||
# ─────────────────────────────────────────────
|
||||
# 4. The Stack
|
||||
# ─────────────────────────────────────────────
|
||||
class S04_Stack(Scene):
|
||||
def construct(self):
|
||||
title_card(self, "The Stack", "LIFO — Last In, First Out")
|
||||
|
||||
# Animated stack push/pop
|
||||
stack_slots = VGroup()
|
||||
slot_labels = []
|
||||
N = 6
|
||||
for i in range(N):
|
||||
rect = Rectangle(width=3.2, height=0.72,
|
||||
fill_color="#161b22", fill_opacity=1,
|
||||
stroke_color=GRAY, stroke_width=1.5)
|
||||
stack_slots.add(rect)
|
||||
stack_slots.arrange(DOWN, buff=0).shift(LEFT * 3 + UP * 0.5)
|
||||
|
||||
self.play(FadeIn(stack_slots))
|
||||
|
||||
# Labels: lower address at top
|
||||
addr_labels = VGroup()
|
||||
for i, slot in enumerate(stack_slots):
|
||||
a = Text(f"0x...{(0x28 - i*8):02x}", font="JetBrains Mono",
|
||||
color=GRAY, font_size=16)
|
||||
a.next_to(slot, RIGHT, buff=0.15)
|
||||
addr_labels.add(a)
|
||||
self.play(FadeIn(addr_labels))
|
||||
|
||||
# rsp / rbp pointers
|
||||
rbp_ptr = Arrow(RIGHT * 0.8, stack_slots[-1].get_right() + LEFT * 0.01,
|
||||
color=ORANGE, buff=0.05)
|
||||
rbp_lbl = Text("rbp", font="JetBrains Mono", color=ORANGE,
|
||||
font_size=22, weight=BOLD).next_to(rbp_ptr, RIGHT, buff=0.1)
|
||||
rsp_ptr = Arrow(RIGHT * 0.8, stack_slots[-1].get_right() + LEFT * 0.01,
|
||||
color=ACCENT, buff=0.05)
|
||||
rsp_lbl = Text("rsp", font="JetBrains Mono", color=ACCENT,
|
||||
font_size=22, weight=BOLD).next_to(rsp_ptr, RIGHT, buff=0.1)
|
||||
|
||||
self.play(FadeIn(rbp_ptr, rbp_lbl))
|
||||
|
||||
# Push simulation: fill slots from bottom up
|
||||
push_values = ["saved rbp", "local: x=5", "saved rip", "arg 1", "arg 2"]
|
||||
colors_ = [ORANGE, GREEN, RED, ACCENT, PURPLE]
|
||||
current_top = N - 1
|
||||
|
||||
for val, col in zip(push_values, colors_):
|
||||
slot = stack_slots[current_top]
|
||||
fill = Rectangle(width=3.2, height=0.72,
|
||||
fill_color=col, fill_opacity=0.22,
|
||||
stroke_color=col, stroke_width=1.5)
|
||||
fill.move_to(slot)
|
||||
txt = Text(val, font="JetBrains Mono", color=col, font_size=18)
|
||||
txt.move_to(slot)
|
||||
rsp_ptr.put_start_and_end_on(
|
||||
RIGHT * 0.8, stack_slots[current_top].get_right() + LEFT * 0.01)
|
||||
rsp_lbl.next_to(rsp_ptr, RIGHT, buff=0.1)
|
||||
if current_top == N - 1:
|
||||
self.play(FadeIn(rsp_ptr, rsp_lbl))
|
||||
self.play(FadeIn(fill), Write(txt), run_time=0.55)
|
||||
current_top -= 1
|
||||
if current_top >= 0:
|
||||
new_end = stack_slots[current_top].get_right() + LEFT * 0.01
|
||||
self.play(rsp_ptr.animate.put_start_and_end_on(RIGHT * 0.8, new_end),
|
||||
rsp_lbl.animate.next_to(rsp_ptr, RIGHT, buff=0.1),
|
||||
run_time=0.4)
|
||||
|
||||
caption = Text("Stack grows toward lower addresses",
|
||||
font="JetBrains Mono", color=GRAY, font_size=20
|
||||
).shift(DOWN * 3.1)
|
||||
self.play(Write(caption))
|
||||
self.wait(2.5)
|
||||
|
||||
# Show the C code + ASM side by side
|
||||
self.play(*[FadeOut(m) for m in self.mobjects])
|
||||
title_card(self, "Stack in Assembly", "sub rsp allocates space")
|
||||
|
||||
asm_lines = [
|
||||
("1139:", "55", "push rbp"),
|
||||
("113a:", "48 89 e5", "mov rbp, rsp"),
|
||||
("113d:", "48 83 ec 10", "sub rsp, 0x10 ; allocate locals"),
|
||||
("1141:", "c7 45 fc 05…", "mov DWORD PTR [rbp-0x4], 0x5"),
|
||||
("1152:", "e8 d9 fe ff ff", "call puts@plt"),
|
||||
("1157:", "b8 00 00 00 00", "mov eax, 0x0"),
|
||||
("115c:", "c9", "leave"),
|
||||
("115d:", "c3", "ret"),
|
||||
]
|
||||
asm_group = S02_HelloWorld._asm_block(asm_lines).scale(0.95).shift(UP * 0.3)
|
||||
self.play(FadeIn(asm_group))
|
||||
|
||||
# Highlight sub rsp
|
||||
rows = asm_group.submobjects[1]
|
||||
self.play(rows[2].animate.set_color(ACCENT), run_time=0.5)
|
||||
note = Text("Reserves 16 bytes on the stack for local variable x",
|
||||
font="JetBrains Mono", color=ACCENT, font_size=20
|
||||
).shift(DOWN * 2.8)
|
||||
self.play(Write(note))
|
||||
self.wait(2)
|
||||
self.play(*[FadeOut(m) for m in self.mobjects])
|
||||
|
||||
|
||||
# ─────────────────────────────────────────────
|
||||
# 5. The Heap
|
||||
# ─────────────────────────────────────────────
|
||||
class S05_Heap(Scene):
|
||||
def construct(self):
|
||||
title_card(self, "The Heap", "Dynamic Memory & malloc/free")
|
||||
|
||||
# Memory layout diagram
|
||||
segments = [
|
||||
("Stack ↓", ORANGE, 1.2),
|
||||
(" ... ", BG, 0.5),
|
||||
("Heap ↑", GREEN, 1.2),
|
||||
(".bss", PURPLE, 0.55),
|
||||
(".data", PURPLE, 0.55),
|
||||
(".text", ACCENT, 0.55),
|
||||
]
|
||||
layout = VGroup()
|
||||
for label, color, h in segments:
|
||||
rect = Rectangle(width=3.8, height=h,
|
||||
fill_color=color, fill_opacity=0.18,
|
||||
stroke_color=color if color != BG else GRAY,
|
||||
stroke_width=1.5)
|
||||
lbl = Text(label, font="JetBrains Mono", color=color if color != BG else GRAY,
|
||||
font_size=22)
|
||||
lbl.move_to(rect)
|
||||
layout.add(VGroup(rect, lbl))
|
||||
layout.arrange(DOWN, buff=0).shift(LEFT * 3.5)
|
||||
|
||||
low_lbl = Text("Low Address", font="JetBrains Mono", color=GRAY, font_size=17
|
||||
).next_to(layout, DOWN, buff=0.2)
|
||||
high_lbl = Text("High Address", font="JetBrains Mono", color=GRAY, font_size=17
|
||||
).next_to(layout, UP, buff=0.2)
|
||||
self.play(FadeIn(layout), Write(low_lbl), Write(high_lbl), run_time=1.2)
|
||||
self.wait(0.6)
|
||||
|
||||
# malloc/free sequence on the right
|
||||
steps = [
|
||||
("char *buf = malloc(64);", GREEN, "allocate 64 bytes on heap"),
|
||||
("strcpy(buf, \"hello\");", ORANGE, "write data into buffer"),
|
||||
("free(buf);", RED, "return memory to allocator"),
|
||||
]
|
||||
step_group = VGroup()
|
||||
for code, color, desc in steps:
|
||||
code_t = Text(code, font="JetBrains Mono", color=color, font_size=19)
|
||||
desc_t = Text(desc, font="JetBrains Mono", color=GRAY, font_size=16)
|
||||
desc_t.next_to(code_t, DOWN, buff=0.12)
|
||||
step_group.add(VGroup(code_t, desc_t))
|
||||
step_group.arrange(DOWN, buff=0.5).shift(RIGHT * 2.2 + UP * 0.3)
|
||||
|
||||
for step in step_group:
|
||||
self.play(FadeIn(step, shift=RIGHT * 0.3), run_time=0.7)
|
||||
self.wait(0.6)
|
||||
|
||||
# Vulnerability callout
|
||||
vuln_box = RoundedRectangle(corner_radius=0.2, width=6.5, height=1.8,
|
||||
fill_color=RED, fill_opacity=0.1,
|
||||
stroke_color=RED, stroke_width=2)
|
||||
vuln_box.shift(DOWN * 2.8)
|
||||
vuln_txt = Text(
|
||||
"Forget free → Memory Leak\n"
|
||||
"free + reuse → Use-After-Free\n"
|
||||
"Overflow 64 bytes → Heap Overflow",
|
||||
font="JetBrains Mono", color=RED, font_size=17, line_spacing=1.3)
|
||||
vuln_txt.move_to(vuln_box)
|
||||
self.play(FadeIn(vuln_box), Write(vuln_txt), run_time=1.2)
|
||||
self.wait(2.5)
|
||||
self.play(*[FadeOut(m) for m in self.mobjects])
|
||||
|
||||
|
||||
# ─────────────────────────────────────────────
|
||||
# 6. Instruction Set
|
||||
# ─────────────────────────────────────────────
|
||||
class S06_Instructions(Scene):
|
||||
def construct(self):
|
||||
title_card(self, "CPU Instructions", "mov · lea · push · call · ret")
|
||||
|
||||
categories = [
|
||||
("Data Movement", [
|
||||
("mov rax, rdx", "copy rdx into rax"),
|
||||
("mov rax, [rdx]", "dereference: load value at addr rdx"),
|
||||
("lea rdi, [rbx+0x10]","load address rbx+0x10 into rdi"),
|
||||
], ACCENT),
|
||||
("Arithmetic / Logic", [
|
||||
("add rax, 0x4", "rax = rax + 4"),
|
||||
("sub rsp, 0x10", "grow stack by 16 bytes"),
|
||||
("xor rax, rax", "zero rax (optimised)"),
|
||||
], GREEN),
|
||||
("Stack", [
|
||||
("push rbp", "decrement rsp; write rbp to [rsp]"),
|
||||
("pop rbp", "read [rsp] into rbp; increment rsp"),
|
||||
], ORANGE),
|
||||
("Control Flow", [
|
||||
("call 0x401234", "push rip; jump to function"),
|
||||
("ret", "pop saved rip; resume caller"),
|
||||
("jmp 0x401234", "unconditional jump"),
|
||||
("jz / jnz", "jump if Zero Flag set / not set"),
|
||||
], PURPLE),
|
||||
]
|
||||
|
||||
for cat_name, instructions, color in categories:
|
||||
self.play(*[FadeOut(m) for m in self.mobjects], run_time=0.3)
|
||||
hdr = Text(cat_name, font="JetBrains Mono", color=color,
|
||||
font_size=34, weight=BOLD).shift(UP * 3)
|
||||
self.play(Write(hdr))
|
||||
|
||||
rows = VGroup()
|
||||
for instr, desc in instructions:
|
||||
instr_t = Text(instr, font="JetBrains Mono", color=color, font_size=24)
|
||||
desc_t = Text(f" → {desc}", font="JetBrains Mono",
|
||||
color=WHITE, font_size=20)
|
||||
row = VGroup(instr_t, desc_t).arrange(RIGHT, buff=0.3)
|
||||
rows.add(row)
|
||||
rows.arrange(DOWN, aligned_edge=LEFT, buff=0.4).shift(UP * 0.4)
|
||||
self.play(LaggedStart(*[FadeIn(r, shift=LEFT * 0.3) for r in rows],
|
||||
lag_ratio=0.25), run_time=1.2)
|
||||
self.wait(2.0)
|
||||
|
||||
self.play(*[FadeOut(m) for m in self.mobjects])
|
||||
|
||||
|
||||
# ─────────────────────────────────────────────
|
||||
# 7. CPU Flags
|
||||
# ─────────────────────────────────────────────
|
||||
class S07_Flags(Scene):
|
||||
def construct(self):
|
||||
title_card(self, "CPU Flags", "EFLAGS register")
|
||||
|
||||
# 16-bit flag register visual
|
||||
bits = list(range(15, -1, -1))
|
||||
important = {0: ("CF", RED), 2: ("PF", GRAY), 6: ("ZF", ACCENT),
|
||||
7: ("SF", ORANGE), 11: ("OF", PURPLE)}
|
||||
|
||||
cells = VGroup()
|
||||
for b in bits:
|
||||
color = important.get(b, ("", GRAY))[1] if b in important else GRAY
|
||||
rect = Square(side_length=0.55,
|
||||
fill_color=color, fill_opacity=0.18,
|
||||
stroke_color=color, stroke_width=1.5)
|
||||
bit_n = Text(str(b), font="JetBrains Mono",
|
||||
color=color, font_size=13).move_to(rect)
|
||||
cells.add(VGroup(rect, bit_n))
|
||||
cells.arrange(RIGHT, buff=0.04).shift(UP * 1.8)
|
||||
self.play(FadeIn(cells), run_time=1.0)
|
||||
|
||||
# Flag abbreviations below important bits
|
||||
for b, (abbr, color) in important.items():
|
||||
idx = 15 - b
|
||||
cell = cells[idx]
|
||||
lbl = Text(abbr, font="JetBrains Mono", color=color, font_size=18,
|
||||
weight=BOLD)
|
||||
lbl.next_to(cell, DOWN, buff=0.15)
|
||||
self.play(FadeIn(lbl), run_time=0.3)
|
||||
|
||||
self.wait(0.5)
|
||||
|
||||
# cmp / jz example
|
||||
example = VGroup(
|
||||
Text("cmp rax, 0x5 ; sets ZF=1 if rax == 5",
|
||||
font="JetBrains Mono", color=WHITE, font_size=21),
|
||||
Text("jz target ; jumps only if ZF=1",
|
||||
font="JetBrains Mono", color=ACCENT, font_size=21),
|
||||
).arrange(DOWN, aligned_edge=LEFT, buff=0.3).shift(DOWN * 0.4)
|
||||
|
||||
bg = BackgroundRectangle(example, color="#161b22", fill_opacity=1,
|
||||
buff=0.25, corner_radius=0.15)
|
||||
self.play(FadeIn(bg), FadeIn(example), run_time=1.0)
|
||||
|
||||
# Animate ZF cell lighting up
|
||||
zf_idx = 15 - 6
|
||||
zf_cell_rect = cells[zf_idx][0]
|
||||
self.play(zf_cell_rect.animate.set_fill(ACCENT, opacity=0.75), run_time=0.7)
|
||||
self.wait(0.5)
|
||||
self.play(zf_cell_rect.animate.set_fill(ACCENT, opacity=0.18), run_time=0.4)
|
||||
|
||||
self.wait(2.0)
|
||||
self.play(*[FadeOut(m) for m in self.mobjects])
|
||||
|
||||
|
||||
# ─────────────────────────────────────────────
|
||||
# 8. Outro
|
||||
# ─────────────────────────────────────────────
|
||||
class S08_Outro(Scene):
|
||||
def construct(self):
|
||||
recap_items = [
|
||||
"C compiles to assembly, which becomes machine code",
|
||||
"Registers: rip, rsp, rbp, argument registers",
|
||||
"Calling convention: rdi → rsi → rdx → rcx → r8 → r9",
|
||||
"Stack: LIFO, managed by rsp/rbp",
|
||||
"Heap: dynamic memory via malloc/free",
|
||||
"Instructions: mov, lea, push/pop, call/ret, jz/jnz",
|
||||
"Flags register drives conditional branching",
|
||||
]
|
||||
|
||||
title = Text("Recap", font="JetBrains Mono", color=ACCENT,
|
||||
font_size=44, weight=BOLD).shift(UP * 3.1)
|
||||
self.play(Write(title))
|
||||
|
||||
items_grp = VGroup()
|
||||
for txt in recap_items:
|
||||
bullet = Text(f"• {txt}", font="JetBrains Mono",
|
||||
color=WHITE, font_size=20)
|
||||
items_grp.add(bullet)
|
||||
items_grp.arrange(DOWN, aligned_edge=LEFT, buff=0.28).shift(UP * 0.5)
|
||||
|
||||
self.play(LaggedStart(*[FadeIn(i, shift=LEFT * 0.2) for i in items_grp],
|
||||
lag_ratio=0.18), run_time=2.5)
|
||||
self.wait(1.5)
|
||||
|
||||
next_lbl = Text("Next: ELF Binary Structure",
|
||||
font="JetBrains Mono", color=ORANGE, font_size=28,
|
||||
weight=BOLD).shift(DOWN * 2.8)
|
||||
self.play(Write(next_lbl))
|
||||
self.wait(1.0)
|
||||
|
||||
support = Text("buymeacoffee.com/mockingspectre",
|
||||
font="JetBrains Mono", color=GRAY, font_size=18
|
||||
).shift(DOWN * 3.5)
|
||||
self.play(FadeIn(support))
|
||||
self.wait(3.0)
|
||||
self.play(FadeOut(*self.mobjects))
|
||||
|
||||
|
||||
# ─────────────────────────────────────────────
|
||||
# Full video: concatenate all scenes
|
||||
# ─────────────────────────────────────────────
|
||||
class FullVideo(S01_Intro, S02_HelloWorld, S03_Registers,
|
||||
S04_Stack, S05_Heap, S06_Instructions,
|
||||
S07_Flags, S08_Outro):
|
||||
"""Render all scenes back-to-back as a single video file."""
|
||||
|
||||
def construct(self):
|
||||
S01_Intro.construct(self)
|
||||
S02_HelloWorld.construct(self)
|
||||
S03_Registers.construct(self)
|
||||
S04_Stack.construct(self)
|
||||
S05_Heap.construct(self)
|
||||
S06_Instructions.construct(self)
|
||||
S07_Flags.construct(self)
|
||||
S08_Outro.construct(self)
|
||||
@@ -1,9 +0,0 @@
|
||||
[project]
|
||||
name = "manimations"
|
||||
version = "0.1.0"
|
||||
description = "Add your description here"
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.13"
|
||||
dependencies = [
|
||||
"manim>=0.20.1",
|
||||
]
|
||||
@@ -1,718 +0,0 @@
|
||||
version = 1
|
||||
revision = 3
|
||||
requires-python = ">=3.13"
|
||||
|
||||
[[package]]
|
||||
name = "audioop-lts"
|
||||
version = "0.2.2"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/38/53/946db57842a50b2da2e0c1e34bd37f36f5aadba1a929a3971c5d7841dbca/audioop_lts-0.2.2.tar.gz", hash = "sha256:64d0c62d88e67b98a1a5e71987b7aa7b5bcffc7dcee65b635823dbdd0a8dbbd0", size = 30686, upload-time = "2025-08-05T16:43:17.409Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/de/d4/94d277ca941de5a507b07f0b592f199c22454eeaec8f008a286b3fbbacd6/audioop_lts-0.2.2-cp313-abi3-macosx_10_13_universal2.whl", hash = "sha256:fd3d4602dc64914d462924a08c1a9816435a2155d74f325853c1f1ac3b2d9800", size = 46523, upload-time = "2025-08-05T16:42:20.836Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f8/5a/656d1c2da4b555920ce4177167bfeb8623d98765594af59702c8873f60ec/audioop_lts-0.2.2-cp313-abi3-macosx_10_13_x86_64.whl", hash = "sha256:550c114a8df0aafe9a05442a1162dfc8fec37e9af1d625ae6060fed6e756f303", size = 27455, upload-time = "2025-08-05T16:42:22.283Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/1b/83/ea581e364ce7b0d41456fb79d6ee0ad482beda61faf0cab20cbd4c63a541/audioop_lts-0.2.2-cp313-abi3-macosx_11_0_arm64.whl", hash = "sha256:9a13dc409f2564de15dd68be65b462ba0dde01b19663720c68c1140c782d1d75", size = 26997, upload-time = "2025-08-05T16:42:23.849Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b8/3b/e8964210b5e216e5041593b7d33e97ee65967f17c282e8510d19c666dab4/audioop_lts-0.2.2-cp313-abi3-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:51c916108c56aa6e426ce611946f901badac950ee2ddaf302b7ed35d9958970d", size = 85844, upload-time = "2025-08-05T16:42:25.208Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c7/2e/0a1c52faf10d51def20531a59ce4c706cb7952323b11709e10de324d6493/audioop_lts-0.2.2-cp313-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:47eba38322370347b1c47024defbd36374a211e8dd5b0dcbce7b34fdb6f8847b", size = 85056, upload-time = "2025-08-05T16:42:26.559Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/75/e8/cd95eef479656cb75ab05dfece8c1f8c395d17a7c651d88f8e6e291a63ab/audioop_lts-0.2.2-cp313-abi3-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ba7c3a7e5f23e215cb271516197030c32aef2e754252c4c70a50aaff7031a2c8", size = 93892, upload-time = "2025-08-05T16:42:27.902Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5c/1e/a0c42570b74f83efa5cca34905b3eef03f7ab09fe5637015df538a7f3345/audioop_lts-0.2.2-cp313-abi3-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:def246fe9e180626731b26e89816e79aae2276f825420a07b4a647abaa84becc", size = 96660, upload-time = "2025-08-05T16:42:28.9Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/50/d5/8a0ae607ca07dbb34027bac8db805498ee7bfecc05fd2c148cc1ed7646e7/audioop_lts-0.2.2-cp313-abi3-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e160bf9df356d841bb6c180eeeea1834085464626dc1b68fa4e1d59070affdc3", size = 79143, upload-time = "2025-08-05T16:42:29.929Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/12/17/0d28c46179e7910bfb0bb62760ccb33edb5de973052cb2230b662c14ca2e/audioop_lts-0.2.2-cp313-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:4b4cd51a57b698b2d06cb9993b7ac8dfe89a3b2878e96bc7948e9f19ff51dba6", size = 84313, upload-time = "2025-08-05T16:42:30.949Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/84/ba/bd5d3806641564f2024e97ca98ea8f8811d4e01d9b9f9831474bc9e14f9e/audioop_lts-0.2.2-cp313-abi3-musllinux_1_2_ppc64le.whl", hash = "sha256:4a53aa7c16a60a6857e6b0b165261436396ef7293f8b5c9c828a3a203147ed4a", size = 93044, upload-time = "2025-08-05T16:42:31.959Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f9/5e/435ce8d5642f1f7679540d1e73c1c42d933331c0976eb397d1717d7f01a3/audioop_lts-0.2.2-cp313-abi3-musllinux_1_2_riscv64.whl", hash = "sha256:3fc38008969796f0f689f1453722a0f463da1b8a6fbee11987830bfbb664f623", size = 78766, upload-time = "2025-08-05T16:42:33.302Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ae/3b/b909e76b606cbfd53875693ec8c156e93e15a1366a012f0b7e4fb52d3c34/audioop_lts-0.2.2-cp313-abi3-musllinux_1_2_s390x.whl", hash = "sha256:15ab25dd3e620790f40e9ead897f91e79c0d3ce65fe193c8ed6c26cffdd24be7", size = 87640, upload-time = "2025-08-05T16:42:34.854Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/30/e7/8f1603b4572d79b775f2140d7952f200f5e6c62904585d08a01f0a70393a/audioop_lts-0.2.2-cp313-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:03f061a1915538fd96272bac9551841859dbb2e3bf73ebe4a23ef043766f5449", size = 86052, upload-time = "2025-08-05T16:42:35.839Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b5/96/c37846df657ccdda62ba1ae2b6534fa90e2e1b1742ca8dcf8ebd38c53801/audioop_lts-0.2.2-cp313-abi3-win32.whl", hash = "sha256:3bcddaaf6cc5935a300a8387c99f7a7fbbe212a11568ec6cf6e4bc458c048636", size = 26185, upload-time = "2025-08-05T16:42:37.04Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/34/a5/9d78fdb5b844a83da8a71226c7bdae7cc638861085fff7a1d707cb4823fa/audioop_lts-0.2.2-cp313-abi3-win_amd64.whl", hash = "sha256:a2c2a947fae7d1062ef08c4e369e0ba2086049a5e598fda41122535557012e9e", size = 30503, upload-time = "2025-08-05T16:42:38.427Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/34/25/20d8fde083123e90c61b51afb547bb0ea7e77bab50d98c0ab243d02a0e43/audioop_lts-0.2.2-cp313-abi3-win_arm64.whl", hash = "sha256:5f93a5db13927a37d2d09637ccca4b2b6b48c19cd9eda7b17a2e9f77edee6a6f", size = 24173, upload-time = "2025-08-05T16:42:39.704Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/58/a7/0a764f77b5c4ac58dc13c01a580f5d32ae8c74c92020b961556a43e26d02/audioop_lts-0.2.2-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:73f80bf4cd5d2ca7814da30a120de1f9408ee0619cc75da87d0641273d202a09", size = 47096, upload-time = "2025-08-05T16:42:40.684Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/aa/ed/ebebedde1a18848b085ad0fa54b66ceb95f1f94a3fc04f1cd1b5ccb0ed42/audioop_lts-0.2.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:106753a83a25ee4d6f473f2be6b0966fc1c9af7e0017192f5531a3e7463dce58", size = 27748, upload-time = "2025-08-05T16:42:41.992Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/cb/6e/11ca8c21af79f15dbb1c7f8017952ee8c810c438ce4e2b25638dfef2b02c/audioop_lts-0.2.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:fbdd522624141e40948ab3e8cdae6e04c748d78710e9f0f8d4dae2750831de19", size = 27329, upload-time = "2025-08-05T16:42:42.987Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/84/52/0022f93d56d85eec5da6b9da6a958a1ef09e80c39f2cc0a590c6af81dcbb/audioop_lts-0.2.2-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:143fad0311e8209ece30a8dbddab3b65ab419cbe8c0dde6e8828da25999be911", size = 92407, upload-time = "2025-08-05T16:42:44.336Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/87/1d/48a889855e67be8718adbc7a01f3c01d5743c325453a5e81cf3717664aad/audioop_lts-0.2.2-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:dfbbc74ec68a0fd08cfec1f4b5e8cca3d3cd7de5501b01c4b5d209995033cde9", size = 91811, upload-time = "2025-08-05T16:42:45.325Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/98/a6/94b7213190e8077547ffae75e13ed05edc488653c85aa5c41472c297d295/audioop_lts-0.2.2-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:cfcac6aa6f42397471e4943e0feb2244549db5c5d01efcd02725b96af417f3fe", size = 100470, upload-time = "2025-08-05T16:42:46.468Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e9/e9/78450d7cb921ede0cfc33426d3a8023a3bda755883c95c868ee36db8d48d/audioop_lts-0.2.2-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:752d76472d9804ac60f0078c79cdae8b956f293177acd2316cd1e15149aee132", size = 103878, upload-time = "2025-08-05T16:42:47.576Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/4f/e2/cd5439aad4f3e34ae1ee852025dc6aa8f67a82b97641e390bf7bd9891d3e/audioop_lts-0.2.2-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:83c381767e2cc10e93e40281a04852facc4cd9334550e0f392f72d1c0a9c5753", size = 84867, upload-time = "2025-08-05T16:42:49.003Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/68/4b/9d853e9076c43ebba0d411e8d2aa19061083349ac695a7d082540bad64d0/audioop_lts-0.2.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:c0022283e9556e0f3643b7c3c03f05063ca72b3063291834cca43234f20c60bb", size = 90001, upload-time = "2025-08-05T16:42:50.038Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/58/26/4bae7f9d2f116ed5593989d0e521d679b0d583973d203384679323d8fa85/audioop_lts-0.2.2-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:a2d4f1513d63c795e82948e1305f31a6d530626e5f9f2605408b300ae6095093", size = 99046, upload-time = "2025-08-05T16:42:51.111Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b2/67/a9f4fb3e250dda9e9046f8866e9fa7d52664f8985e445c6b4ad6dfb55641/audioop_lts-0.2.2-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:c9c8e68d8b4a56fda8c025e538e639f8c5953f5073886b596c93ec9b620055e7", size = 84788, upload-time = "2025-08-05T16:42:52.198Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/70/f7/3de86562db0121956148bcb0fe5b506615e3bcf6e63c4357a612b910765a/audioop_lts-0.2.2-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:96f19de485a2925314f5020e85911fb447ff5fbef56e8c7c6927851b95533a1c", size = 94472, upload-time = "2025-08-05T16:42:53.59Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f1/32/fd772bf9078ae1001207d2df1eef3da05bea611a87dd0e8217989b2848fa/audioop_lts-0.2.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:e541c3ef484852ef36545f66209444c48b28661e864ccadb29daddb6a4b8e5f5", size = 92279, upload-time = "2025-08-05T16:42:54.632Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/4f/41/affea7181592ab0ab560044632571a38edaf9130b84928177823fbf3176a/audioop_lts-0.2.2-cp313-cp313t-win32.whl", hash = "sha256:d5e73fa573e273e4f2e5ff96f9043858a5e9311e94ffefd88a3186a910c70917", size = 26568, upload-time = "2025-08-05T16:42:55.627Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/28/2b/0372842877016641db8fc54d5c88596b542eec2f8f6c20a36fb6612bf9ee/audioop_lts-0.2.2-cp313-cp313t-win_amd64.whl", hash = "sha256:9191d68659eda01e448188f60364c7763a7ca6653ed3f87ebb165822153a8547", size = 30942, upload-time = "2025-08-05T16:42:56.674Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ee/ca/baf2b9cc7e96c179bb4a54f30fcd83e6ecb340031bde68f486403f943768/audioop_lts-0.2.2-cp313-cp313t-win_arm64.whl", hash = "sha256:c174e322bb5783c099aaf87faeb240c8d210686b04bd61dfd05a8e5a83d88969", size = 24603, upload-time = "2025-08-05T16:42:57.571Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5c/73/413b5a2804091e2c7d5def1d618e4837f1cb82464e230f827226278556b7/audioop_lts-0.2.2-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:f9ee9b52f5f857fbaf9d605a360884f034c92c1c23021fb90b2e39b8e64bede6", size = 47104, upload-time = "2025-08-05T16:42:58.518Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ae/8c/daa3308dc6593944410c2c68306a5e217f5c05b70a12e70228e7dd42dc5c/audioop_lts-0.2.2-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:49ee1a41738a23e98d98b937a0638357a2477bc99e61b0f768a8f654f45d9b7a", size = 27754, upload-time = "2025-08-05T16:43:00.132Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/4e/86/c2e0f627168fcf61781a8f72cab06b228fe1da4b9fa4ab39cfb791b5836b/audioop_lts-0.2.2-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:5b00be98ccd0fc123dcfad31d50030d25fcf31488cde9e61692029cd7394733b", size = 27332, upload-time = "2025-08-05T16:43:01.666Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c7/bd/35dce665255434f54e5307de39e31912a6f902d4572da7c37582809de14f/audioop_lts-0.2.2-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:a6d2e0f9f7a69403e388894d4ca5ada5c47230716a03f2847cfc7bd1ecb589d6", size = 92396, upload-time = "2025-08-05T16:43:02.991Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/2d/d2/deeb9f51def1437b3afa35aeb729d577c04bcd89394cb56f9239a9f50b6f/audioop_lts-0.2.2-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f9b0b8a03ef474f56d1a842af1a2e01398b8f7654009823c6d9e0ecff4d5cfbf", size = 91811, upload-time = "2025-08-05T16:43:04.096Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/76/3b/09f8b35b227cee28cc8231e296a82759ed80c1a08e349811d69773c48426/audioop_lts-0.2.2-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:2b267b70747d82125f1a021506565bdc5609a2b24bcb4773c16d79d2bb260bbd", size = 100483, upload-time = "2025-08-05T16:43:05.085Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/0b/15/05b48a935cf3b130c248bfdbdea71ce6437f5394ee8533e0edd7cfd93d5e/audioop_lts-0.2.2-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:0337d658f9b81f4cd0fdb1f47635070cc084871a3d4646d9de74fdf4e7c3d24a", size = 103885, upload-time = "2025-08-05T16:43:06.197Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/83/80/186b7fce6d35b68d3d739f228dc31d60b3412105854edb975aa155a58339/audioop_lts-0.2.2-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:167d3b62586faef8b6b2275c3218796b12621a60e43f7e9d5845d627b9c9b80e", size = 84899, upload-time = "2025-08-05T16:43:07.291Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/49/89/c78cc5ac6cb5828f17514fb12966e299c850bc885e80f8ad94e38d450886/audioop_lts-0.2.2-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:0d9385e96f9f6da847f4d571ce3cb15b5091140edf3db97276872647ce37efd7", size = 89998, upload-time = "2025-08-05T16:43:08.335Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/4c/4b/6401888d0c010e586c2ca50fce4c903d70a6bb55928b16cfbdfd957a13da/audioop_lts-0.2.2-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:48159d96962674eccdca9a3df280e864e8ac75e40a577cc97c5c42667ffabfc5", size = 99046, upload-time = "2025-08-05T16:43:09.367Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/de/f8/c874ca9bb447dae0e2ef2e231f6c4c2b0c39e31ae684d2420b0f9e97ee68/audioop_lts-0.2.2-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:8fefe5868cd082db1186f2837d64cfbfa78b548ea0d0543e9b28935ccce81ce9", size = 84843, upload-time = "2025-08-05T16:43:10.749Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/3e/c0/0323e66f3daebc13fd46b36b30c3be47e3fc4257eae44f1e77eb828c703f/audioop_lts-0.2.2-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:58cf54380c3884fb49fdd37dfb7a772632b6701d28edd3e2904743c5e1773602", size = 94490, upload-time = "2025-08-05T16:43:12.131Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/98/6b/acc7734ac02d95ab791c10c3f17ffa3584ccb9ac5c18fd771c638ed6d1f5/audioop_lts-0.2.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:088327f00488cdeed296edd9215ca159f3a5a5034741465789cad403fcf4bec0", size = 92297, upload-time = "2025-08-05T16:43:13.139Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/13/c3/c3dc3f564ce6877ecd2a05f8d751b9b27a8c320c2533a98b0c86349778d0/audioop_lts-0.2.2-cp314-cp314t-win32.whl", hash = "sha256:068aa17a38b4e0e7de771c62c60bbca2455924b67a8814f3b0dee92b5820c0b3", size = 27331, upload-time = "2025-08-05T16:43:14.19Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/72/bb/b4608537e9ffcb86449091939d52d24a055216a36a8bf66b936af8c3e7ac/audioop_lts-0.2.2-cp314-cp314t-win_amd64.whl", hash = "sha256:a5bf613e96f49712073de86f20dbdd4014ca18efd4d34ed18c75bd808337851b", size = 31697, upload-time = "2025-08-05T16:43:15.193Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f6/22/91616fe707a5c5510de2cac9b046a30defe7007ba8a0c04f9c08f27df312/audioop_lts-0.2.2-cp314-cp314t-win_arm64.whl", hash = "sha256:b492c3b040153e68b9fdaff5913305aaaba5bb433d8a7f73d5cf6a64ed3cc1dd", size = 25206, upload-time = "2025-08-05T16:43:16.444Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "av"
|
||||
version = "17.0.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/b2/eb/abca886df3a091bc406feb5ff71b4c4f426beaae6b71b9697264ce8c7211/av-17.0.0.tar.gz", hash = "sha256:c53685df73775a8763c375c7b2d62a6cb149d992a26a4b098204da42ade8c3df", size = 4410769, upload-time = "2026-03-14T14:38:45.868Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/b1/fb/55e3b5b5d1fc61466292f26fbcbabafa2642f378dc48875f8f554591e1a4/av-17.0.0-cp311-abi3-macosx_11_0_x86_64.whl", hash = "sha256:ed4013fac77c309a4a68141dcf6148f1821bb1073a36d4289379762a6372f711", size = 23238424, upload-time = "2026-03-14T14:38:05.856Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/52/03/9ace1acc08bc9ae38c14bf3a4b1360e995e4d999d1d33c2cbd7c9e77582a/av-17.0.0-cp311-abi3-macosx_14_0_arm64.whl", hash = "sha256:e44b6c83e9f3be9f79ee87d0b77a27cea9a9cd67bd630362c86b7e56a748dfbb", size = 18709043, upload-time = "2026-03-14T14:38:08.288Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/00/c0/637721f3cd5bb8bd16105a1a08efd781fc12f449931bdb3a4d0cfd63fa55/av-17.0.0-cp311-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:b440da6ac47da0629d509316f24bcd858f33158dbdd0f1b7293d71e99beb26de", size = 34018780, upload-time = "2026-03-14T14:38:10.45Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d2/59/d19bc3257dd985d55337d7f0414c019414b97e16cd3690ebf9941a847543/av-17.0.0-cp311-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:1060cba85f97f4a337311169d92c0b5e143452cfa5ca0e65fa499d7955e8592e", size = 36358757, upload-time = "2026-03-14T14:38:13.092Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/52/6c/a1f4f2677bae6f2ade7a8a18e90ebdcf70690c9b1c4e40e118aa30fa313f/av-17.0.0-cp311-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:deda202e6021cfc7ba3e816897760ec5431309d59a4da1f75df3c0e9413d71e7", size = 35195281, upload-time = "2026-03-14T14:38:15.789Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/90/ea/52b0fc6f69432c7bf3f5fbe6f707113650aa40a1a05b9096ffc2bba4f77d/av-17.0.0-cp311-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:ffaf266a1a9c2148072de0a4b5ae98061465178d2cfaa69ee089761149342974", size = 37444817, upload-time = "2026-03-14T14:38:18.563Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/34/ad/d2172966282cb8f146c13b6be7416efefde74186460c5e1708ddfc13dba6/av-17.0.0-cp311-abi3-win_amd64.whl", hash = "sha256:45a35a40b2875bf2f98de7c952d74d960f92f319734e6d28e03b4c62a49e6f49", size = 28888553, upload-time = "2026-03-14T14:38:21.223Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b0/bb/c5a4c4172c514d631fb506e6366b503576b8c7f29809cf42aca73e28ff01/av-17.0.0-cp311-abi3-win_arm64.whl", hash = "sha256:3d32e9b5c5bbcb872a0b6917b352a1db8a42142237826c9b49a36d5dbd9e9c26", size = 21916910, upload-time = "2026-03-14T14:38:23.706Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/7f/8e/c40ac08e63f79387c59f6ecc38f47d4c942b549130eee579ec1a91f6a291/av-17.0.0-cp314-cp314t-macosx_11_0_x86_64.whl", hash = "sha256:d13250fb4b4522e9a6bec32da082556d5f257110ea223758151375748d9bbe25", size = 23483029, upload-time = "2026-03-14T14:38:25.758Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a9/fb/b4419494bfc249163ec393c613966d66db7e95c76da3345711cd115a79df/av-17.0.0-cp314-cp314t-macosx_14_0_arm64.whl", hash = "sha256:dbb56aa3b7ae72451d1bf6e9d37c7d83d39b97af712f73583ff419fbf08fc237", size = 18920446, upload-time = "2026-03-14T14:38:27.905Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/30/62/c2306d91602ddad2c56106f21dcb334fd51d5ea2e952f7fa025bb8aa39fc/av-17.0.0-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:a213ac9e83b7ab12c2e9f277a09cac8e9d85cf0883efdab7a87a60e2e4e48879", size = 37477266, upload-time = "2026-03-14T14:38:30.404Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/28/cd/c8510a9607886785c0b3ca019d503e888c3757529be42a7287fe2bfa92d5/av-17.0.0-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:e15c88bb0921f9435bcc5a27a0863dba571a80ad5e1389c4fcf2073833bb4a74", size = 39572988, upload-time = "2026-03-14T14:38:32.984Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/7d/2d/207d9361e25b5abec9be335bbab4df6b6b838e2214be4b374f4cfb285427/av-17.0.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:096cfd1e9fc896506726c7c42aaf9b370e78c2f257cde4d6ddb6c889bfcc49ec", size = 38399591, upload-time = "2026-03-14T14:38:35.465Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/73/ca/307740c6aa2980966bf11383ffcb04bacc5b13f3d268ab4cfb274ad6f793/av-17.0.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:3649ab3d2c7f58049ded1a36e100c0d8fd529cf258f41dd88678ba824034d8c9", size = 40590681, upload-time = "2026-03-14T14:38:38.269Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/35/f2/6fdb26d0651adf409864cb2a0d60da107e467d3d1aabc94b234ead54324a/av-17.0.0-cp314-cp314t-win_amd64.whl", hash = "sha256:e5002271ab2135b551d980c2db8f3299d452e3b9d3633f24f6bb57fffe91cd10", size = 29216337, upload-time = "2026-03-14T14:38:40.83Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/41/0a/0896b829a39b5669a2d811e1a79598de661693685cd62b31f11d0c18e65b/av-17.0.0-cp314-cp314t-win_arm64.whl", hash = "sha256:dba98603fc4665b4f750de86fbaf6c0cfaece970671a9b529e0e3d1711e8367e", size = 22071058, upload-time = "2026-03-14T14:38:43.663Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "beautifulsoup4"
|
||||
version = "4.14.3"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "soupsieve" },
|
||||
{ name = "typing-extensions" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/c3/b0/1c6a16426d389813b48d95e26898aff79abbde42ad353958ad95cc8c9b21/beautifulsoup4-4.14.3.tar.gz", hash = "sha256:6292b1c5186d356bba669ef9f7f051757099565ad9ada5dd630bd9de5fa7fb86", size = 627737, upload-time = "2025-11-30T15:08:26.084Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/1a/39/47f9197bdd44df24d67ac8893641e16f386c984a0619ef2ee4c51fbbc019/beautifulsoup4-4.14.3-py3-none-any.whl", hash = "sha256:0918bfe44902e6ad8d57732ba310582e98da931428d231a5ecb9e7c703a735bb", size = 107721, upload-time = "2025-11-30T15:08:24.087Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "click"
|
||||
version = "8.3.2"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "colorama", marker = "sys_platform == 'win32'" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/57/75/31212c6bf2503fdf920d87fee5d7a86a2e3bcf444984126f13d8e4016804/click-8.3.2.tar.gz", hash = "sha256:14162b8b3b3550a7d479eafa77dfd3c38d9dc8951f6f69c78913a8f9a7540fd5", size = 302856, upload-time = "2026-04-03T19:14:45.118Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/e4/20/71885d8b97d4f3dde17b1fdb92dbd4908b00541c5a3379787137285f602e/click-8.3.2-py3-none-any.whl", hash = "sha256:1924d2c27c5653561cd2cae4548d1406039cb79b858b747cfea24924bbc1616d", size = 108379, upload-time = "2026-04-03T19:14:43.505Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cloup"
|
||||
version = "3.0.9"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "click" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/f9/64/7f0a66021ff81d51859c66adc13f3c71f0306c2f8dfb9877a0694cbada05/cloup-3.0.9.tar.gz", hash = "sha256:519f524d3c64040e49a0866b5fc0bfd6af3eac0d3d6a4b2b50b33ab0247db2d7", size = 229896, upload-time = "2026-04-04T03:53:54.182Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/77/15/435bb5a24e3a2dc8c26afedab0c6f0cf4291c66fb99509c168c38eb81135/cloup-3.0.9-py2.py3-none-any.whl", hash = "sha256:c761ef4e975454335d50c0e1eb83595a932735aac06e8955b3ced774bc62ae7b", size = 54724, upload-time = "2026-04-04T03:53:52.909Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "colorama"
|
||||
version = "0.4.6"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697, upload-time = "2022-10-25T02:36:22.414Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cython"
|
||||
version = "3.2.4"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/91/85/7574c9cd44b69a27210444b6650f6477f56c75fee1b70d7672d3e4166167/cython-3.2.4.tar.gz", hash = "sha256:84226ecd313b233da27dc2eb3601b4f222b8209c3a7216d8733b031da1dc64e6", size = 3280291, upload-time = "2026-01-04T14:14:14.473Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/18/b5/1cfca43b7d20a0fdb1eac67313d6bb6b18d18897f82dd0f17436bdd2ba7f/cython-3.2.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:28e8075087a59756f2d059273184b8b639fe0f16cf17470bd91c39921bc154e0", size = 2960506, upload-time = "2026-01-04T14:15:16.733Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ee/d7/3bda3efce0c5c6ce79cc21285dbe6f60369c20364e112f5a506ee8a1b067/cython-3.2.4-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:d4b4fd5332ab093131fa6172e8362f16adef3eac3179fd24bbdc392531cb82fa", size = 2971496, upload-time = "2026-01-04T14:15:25.038Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/0a/8b/fd393f0923c82be4ec0db712fffb2ff0a7a131707b842c99bf24b549274d/cython-3.2.4-cp39-abi3-macosx_10_9_x86_64.whl", hash = "sha256:36bf3f5eb56d5281aafabecbaa6ed288bc11db87547bba4e1e52943ae6961ccf", size = 2875622, upload-time = "2026-01-04T14:15:39.749Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ff/fa/d3c15189f7c52aaefbaea76fb012119b04b9013f4bf446cb4eb4c26c4e6b/cython-3.2.4-py3-none-any.whl", hash = "sha256:732fc93bc33ae4b14f6afaca663b916c2fdd5dcbfad7114e17fb2434eeaea45c", size = 1257078, upload-time = "2026-01-04T14:14:12.373Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "decorator"
|
||||
version = "5.2.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/43/fa/6d96a0978d19e17b68d634497769987b16c8f4cd0a7a05048bec693caa6b/decorator-5.2.1.tar.gz", hash = "sha256:65f266143752f734b0a7cc83c46f4618af75b8c5911b00ccb61d0ac9b6da0360", size = 56711, upload-time = "2025-02-24T04:41:34.073Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/4e/8c/f3147f5c4b73e7550fe5f9352eaa956ae838d5c51eb58e7a25b9f3e2643b/decorator-5.2.1-py3-none-any.whl", hash = "sha256:d316bb415a2d9e2d2b3abcc4084c6502fc09240e292cd76a76afc106a1c8e04a", size = 9190, upload-time = "2025-02-24T04:41:32.565Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "glcontext"
|
||||
version = "3.0.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/3a/80/8238a0e6e972292061176141c1028b5e670aa8c94cf4c2f819bd730d314e/glcontext-3.0.0.tar.gz", hash = "sha256:57168edcd38df2fc0d70c318edf6f7e59091fba1cd3dadb289d0aa50449211ef", size = 16422, upload-time = "2024-08-10T20:01:20.004Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/12/be/0ef6a6710164fde818040238b041b02a082a2b9d210f18632ab2354d863e/glcontext-3.0.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:5bd37089570d3cdb01c6c0b315c49ce8a4dcdab2c431f5ba9f37a8b633cebfdf", size = 9366, upload-time = "2024-08-10T20:00:30.531Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b9/d7/c3220898d72fbf938660ba5789c19cf245d21b45802a5d86cbcc67d66413/glcontext-3.0.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:857fd83e60f15580afd369dfb651a10d84a70ec35995622d253551bfb3ff9477", size = 9735, upload-time = "2024-08-10T20:00:31.708Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/74/c1/2d57062d2f2f6e55c58b12bdeab2a39b209f959df32039d099ecdfe96bf7/glcontext-3.0.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:93fda9b378ce6d91f366e83e71ebdafdd167280a9834d1d6341ce6457c4e42ed", size = 50166, upload-time = "2024-08-10T20:00:32.627Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/03/4d/7fee00c76d678b06529e939ab6f3e3190af30208fe2e984526899026a437/glcontext-3.0.0-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:89ad50d34aa62f03f6aaf6ae39fc27afd1b0eaefb0281aac51f686dc5672d473", size = 51186, upload-time = "2024-08-10T20:00:33.718Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f0/58/dc9a56192b889587e51ea511804bad5dec816de81ce16831db9fe19d5c40/glcontext-3.0.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:2634d5e9647a6d7b0c5a5c0c57e91ac98aa79759bffb42459af4374b049fab01", size = 44658, upload-time = "2024-08-10T20:00:35.232Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/aa/ed/acb12e67589deaa96ad29d6994c2b9383afd18700f4f2a42ff342628aac5/glcontext-3.0.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:0140c5df37cb48271527355062d35589dc3e1e7e73b51adf9962ed5048115f69", size = 46882, upload-time = "2024-08-10T20:00:36.33Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e0/6d/033ba23466d596c945f5f31f5c4e50cba3bc6664fdee58f6ceab54b76f4b/glcontext-3.0.0-cp313-cp313-win32.whl", hash = "sha256:6678e0552b516fa8fe62f500ef2b953bec991e82a003be2a9840d16556d03d2e", size = 12220, upload-time = "2024-08-10T20:00:37.874Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/53/b4/f0e0860526b8661ec6ae2b25a15b61100e551f57f488613c564752173a56/glcontext-3.0.0-cp313-cp313-win_amd64.whl", hash = "sha256:18aa4b1df50e8c8ea39bd0f775f39bcc987521f92c4ed019ec7d70078471354d", size = 12971, upload-time = "2024-08-10T20:00:39.233Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "isosurfaces"
|
||||
version = "0.1.2"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "numpy" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/da/cf/bd7e70bb7b8dfd77afdc79aba8d83afd4a9263f045861cd4ddd34b7f6a12/isosurfaces-0.1.2.tar.gz", hash = "sha256:fa51ebe864ea9355b26830e27fdd6a41d5a58b419fa8d4b47e3b8b80718d6e21", size = 11348, upload-time = "2024-02-26T00:20:52.066Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/b1/68/d5e9e6e0d6e43107d8393d2ee3d231dbb597bf93052c6f3117b313724980/isosurfaces-0.1.2-py3-none-any.whl", hash = "sha256:525a49ba93f4dbc35303cd2faf30976af0f99d9274cfa2787aec016b8ef96c64", size = 11649, upload-time = "2024-02-26T00:20:41.308Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "manim"
|
||||
version = "0.20.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "audioop-lts" },
|
||||
{ name = "av" },
|
||||
{ name = "beautifulsoup4" },
|
||||
{ name = "click" },
|
||||
{ name = "cloup" },
|
||||
{ name = "decorator" },
|
||||
{ name = "isosurfaces" },
|
||||
{ name = "manimpango" },
|
||||
{ name = "mapbox-earcut" },
|
||||
{ name = "moderngl" },
|
||||
{ name = "moderngl-window" },
|
||||
{ name = "networkx" },
|
||||
{ name = "numpy" },
|
||||
{ name = "pillow" },
|
||||
{ name = "pycairo" },
|
||||
{ name = "pydub" },
|
||||
{ name = "pygments" },
|
||||
{ name = "rich" },
|
||||
{ name = "scipy" },
|
||||
{ name = "screeninfo" },
|
||||
{ name = "skia-pathops" },
|
||||
{ name = "srt" },
|
||||
{ name = "svgelements" },
|
||||
{ name = "tqdm" },
|
||||
{ name = "typing-extensions" },
|
||||
{ name = "watchdog" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/dc/3b/ad54ce02f3e95d17d016cb1254708ae3795b60d5661f3b2085655940a565/manim-0.20.1.tar.gz", hash = "sha256:1e9747fb2fc1bde58ad09bcbd77d141793ce4b61811726a7fce537193d92e16b", size = 553537, upload-time = "2026-02-27T07:32:53.54Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/4b/74/7a54f81bbb3016036662c5497edc89c5d053a8ab1e8f7c8faaca5d43b174/manim-0.20.1-py3-none-any.whl", hash = "sha256:2c76784716aef88630eace2762645e1eb25f236fe750cb1b3c4fdd3558de49e1", size = 652109, upload-time = "2026-02-27T07:32:55.066Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "manimations"
|
||||
version = "0.1.0"
|
||||
source = { virtual = "." }
|
||||
dependencies = [
|
||||
{ name = "manim" },
|
||||
]
|
||||
|
||||
[package.metadata]
|
||||
requires-dist = [{ name = "manim", specifier = ">=0.20.1" }]
|
||||
|
||||
[[package]]
|
||||
name = "manimpango"
|
||||
version = "0.6.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/47/55/d360e73eb4d04b102cef399ddebcba486a9b6c1977a26fe710beffd52e95/manimpango-0.6.1.tar.gz", hash = "sha256:59a00bbf8e99dab5f94341087c88e609fe946e79724627429cf59da84cbd40bf", size = 4080834, upload-time = "2025-10-23T06:04:48.564Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/23/ee/01cd6b3087a5ead9483add3023f46c135bddd7773d506b771b44bbe0830b/manimpango-0.6.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:79aafe6373cb31dcdd1ee505407ec2bea18e74aed877f93dcd27ec9d88584472", size = 7751685, upload-time = "2025-10-23T06:04:28.457Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/70/93/905ac20a9190655870131940dadb5121645cf8a23e6ea0f04be7f4604f2e/manimpango-0.6.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:1049bda27ca504d24b48bec21756f4d8a3310ea7bc690167c54d05e97b8f7639", size = 7062629, upload-time = "2025-10-23T06:04:30.059Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/76/88/b2de7d2d3a0331cf79992f8c6da0f0abd873d4ec9f024cad5992f1cf7a6d/manimpango-0.6.1-cp313-cp313-win32.whl", hash = "sha256:8da8238147b96737b36725b0fc386dc1dd7901516dfd7e73b2e7d34cd5d934f1", size = 3626705, upload-time = "2025-10-23T06:04:31.527Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/3b/ed/a7a57491b26e8fb85ac0be9c39b53a6690f3c39beaf06d3715cb6916932b/manimpango-0.6.1-cp313-cp313-win_amd64.whl", hash = "sha256:e90d6b926d0e673ce624963d44cc28c55a368b6074108ab885a43305baeae26c", size = 4203874, upload-time = "2025-10-23T06:04:32.981Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f1/c0/318410215b409465a237c126a3e1f612c432d33b037b2f997870df327434/manimpango-0.6.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:318d14087901ee27ed6d0cfef0335aed57db217f8de831c8ca4e4c52b7805b45", size = 7751895, upload-time = "2025-10-23T06:04:34.874Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d1/83/f0a05e3e6312ca9673bc8b470c6a743cf2d0bd7f08b218efc993226e72e4/manimpango-0.6.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:ffe2f8353857f0ca9a16894430d871051da450bc2d19beb969cf8b57b032f580", size = 7063387, upload-time = "2025-10-23T06:04:36.877Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/13/76/0748323341647e8c338bd7af6fb527ffdc43d676003b57743740bdfcffcc/manimpango-0.6.1-cp314-cp314-win32.whl", hash = "sha256:c294ab801c8ffc217342dfeff7aeca97cbea86cd8b4e6e8c9a8d7da020b820e1", size = 3737933, upload-time = "2025-10-23T06:04:38.775Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/2b/e9/42b995549cfd137780045e44b3bfba2cb1247b18bd2fb9f97079048e78ac/manimpango-0.6.1-cp314-cp314-win_amd64.whl", hash = "sha256:d8b0ee675eb30bbb67097cecb2be469847c3ccf574291f2bd43360caeb5f62ed", size = 4357908, upload-time = "2025-10-23T06:04:40.641Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mapbox-earcut"
|
||||
version = "2.0.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "numpy" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/bc/7b/bbf6b00488662be5d2eb7a188222c264b6f713bac10dc4a77bf37a4cb4b6/mapbox_earcut-2.0.0.tar.gz", hash = "sha256:81eab6b86cf99551deb698b98e3f7502c57900e5c479df15e1bdaf1a57f0f9d6", size = 39934, upload-time = "2025-11-16T18:41:27.251Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/8b/7c/c5dd5b255b9828ba5df729e62fdd470a322c938f07ef392ca03c0592bb3a/mapbox_earcut-2.0.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:582329a81bd36cf0f82e443c395bcb8cfdb10caddafec76acaebac7c20bf1c31", size = 55619, upload-time = "2025-11-16T18:40:44.44Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/1a/3f/03f23eac9831e7d0d8da3d6993695a9a3724659c94e9997f6b7aaccc199d/mapbox_earcut-2.0.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:d2ac5f610b3e44a3a0c4df06b5552d503b4f1c2c409eeca20dbe05112bd60955", size = 52023, upload-time = "2025-11-16T18:40:45.857Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/39/f3/a92ccee494b3e437e4bd81ecd358e39d231dc90af010d6c43930506c10ad/mapbox_earcut-2.0.0-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:58cc88513b87734b243d86f0d3fb87e96e0a78d9abd8fd615c55f766dd63f949", size = 56357, upload-time = "2025-11-16T18:40:47.27Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/03/30/e54ececd0403a5495c340b693075abec92a6d17dc44283b6cb059534f7ed/mapbox_earcut-2.0.0-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:40218d887798451932f3c335992834aa807c35cd497c6e0733470fdbd77f9521", size = 59215, upload-time = "2025-11-16T18:40:48.682Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6e/e1/8fbff13a074c1fbf702b30ce7ec4d878bc664d659c1c2b1697831f4ea3a8/mapbox_earcut-2.0.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:39fa5cfa0e855b028ec9b0200c88ebfa252448f343ce2f67b6fc07fe1f22a3ae", size = 152304, upload-time = "2025-11-16T18:40:49.85Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b9/d5/c757030b3cb3a9f2278ded6f7312d2b9d3761db6f3da8d395f7f7303dd66/mapbox_earcut-2.0.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:476b558473b8a43f238d46e819bc0f830c427842ec5feb19e23b4dcac8ad2455", size = 157270, upload-time = "2025-11-16T18:40:51.093Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/96/63/589c6decb1f032d8811f1066da552f0a718830f592e6d6539fa4c3c766b8/mapbox_earcut-2.0.0-cp313-cp313-win32.whl", hash = "sha256:8c2d125c182acbc490b39503c0dec4f937bae180d0849a26bcea0ee4a76024bd", size = 51207, upload-time = "2025-11-16T18:40:52.285Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/76/75/a79a6020c46d4f07731e88ec5cc9324f6b43343aba835def1dc0bf59fecf/mapbox_earcut-2.0.0-cp313-cp313-win_amd64.whl", hash = "sha256:e049e6a37c228d7a9cb2f54ae405aa21d35c5175d849530fb32064ddb38ad5ab", size = 56416, upload-time = "2025-11-16T18:40:53.474Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ce/5f/83e878c2b3e9e6db1f60b598a2cc5ed4c2b5bc8d281575c964869414a159/mapbox_earcut-2.0.0-cp313-cp313-win_arm64.whl", hash = "sha256:8a833d73d63d4b6291bbd8b4d2f551e87f663282cdc547ecbbd9b423849ee996", size = 50103, upload-time = "2025-11-16T18:40:54.954Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/96/fc/f1b74324c83f510213ff91eb8b1d2697ad5a12418c5fba966e80f1104a5f/mapbox_earcut-2.0.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:ad1dc141797037b7d4c9d8d2e52b9665b36294913a8ec31008b282d1a95b9bdc", size = 55728, upload-time = "2025-11-16T18:40:56.098Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/7b/59/053c04e29c4bd22157d3b6255f1e5c19c46cb7a594c4314298bdcbca723f/mapbox_earcut-2.0.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:0f0f5c6f5ed8ffdce8efe6a003ba598089d0ee07eabd41868db183be50484f9f", size = 52063, upload-time = "2025-11-16T18:40:57.227Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a6/77/acc2d553c3bb8c769535a280545bb7d9608141e90511a2e6215a54611776/mapbox_earcut-2.0.0-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:82cd92775f37fd1e4b8464c5e74a00e87130eecc55ee3df2492b8ca2bdf6ef3e", size = 56522, upload-time = "2025-11-16T18:40:58.349Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/1a/f5/627dd6defd3c1a2b3069e9e27482aa04d268c841735e576c1e22848a34f6/mapbox_earcut-2.0.0-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:626ffc1310e0cc8910283e4ac3139e5fb0458f18f2c4874162f66159951933ff", size = 59204, upload-time = "2025-11-16T18:41:00.095Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/4a/3e/819185542ab095ba1244ad65ececb3edcde6fd0111248a0f9318d695bfcf/mapbox_earcut-2.0.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:ea951d764a356cad95b23fef950d8aa3b44b933795ad09d977fea7d4dbe377c3", size = 152550, upload-time = "2025-11-16T18:41:01.233Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a9/ad/85e0f815e4774b90ad6761bce55c80d13ee21b2a24014b0be0d5010b0049/mapbox_earcut-2.0.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:df1f217624abb5e02ecabcbd84369de970b8d8bc1e4e7c164c1cfcaddad76ca3", size = 157322, upload-time = "2025-11-16T18:41:02.866Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/27/4c/0f56369e7a000d2f3177d17baf34263559b206ae524fcd0c4c5d1d960dab/mapbox_earcut-2.0.0-cp314-cp314-win32.whl", hash = "sha256:6fa61307d38b50fc9bd5449c00dbae46d270a32b372c6fc3b8af4b85c85746e4", size = 52916, upload-time = "2025-11-16T18:41:04.122Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c2/9d/8c557dd9b3d9fe2344f5bd5ff3bb0b2a42ed6addb7e43ca4358051743b04/mapbox_earcut-2.0.0-cp314-cp314-win_amd64.whl", hash = "sha256:0da20ed3c81b240450118773bcedfac34e70a56998f66147222c46f4356fff67", size = 57713, upload-time = "2025-11-16T18:41:05.204Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/3b/ec/678c5553938d3a29d02dd41dd898672267f054afc4e2821958dee6ec86ce/mapbox_earcut-2.0.0-cp314-cp314-win_arm64.whl", hash = "sha256:847e74bd5878e4c64793dc100f9288f5443f87c55c3fe391fd90509029136ff6", size = 51872, upload-time = "2025-11-16T18:41:06.323Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/18/37/94f2d973669cbfef811e536713fe56ec012ba74e5f8795a832337b1866a3/mapbox_earcut-2.0.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:ddc9e7175fc903185c64afbbf91febee56b50787dd0962fce2bfb4f20cf80d27", size = 56447, upload-time = "2025-11-16T18:41:07.443Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c9/1c/e0afcc82659cc1727a7e59c4f9e9880bbc3f048a4a5325772b44d4a91dfd/mapbox_earcut-2.0.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:6dc8a7568066af9a858018d6d92b7e77e164578f9fcd79093f1cbe4ec203461b", size = 53154, upload-time = "2025-11-16T18:41:08.618Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6c/2d/9845281c8c35da2bea733b8c2df5b9fe694e73e7b05fe8a1d4c3c439a1bc/mapbox_earcut-2.0.0-cp314-cp314t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6abc5340edd9b433ab2dab2ee033082a199d5c51cce445124626c0040ec0d81b", size = 56285, upload-time = "2025-11-16T18:41:09.728Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/97/8e/eeea762a519490662b8f480e2b35bf03701b0bcc5a446b62a4c5a1500b06/mapbox_earcut-2.0.0-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:df7afdd8078a9aa28f469d9242531d304e09a4b14e514f048e021a949f3777b4", size = 58601, upload-time = "2025-11-16T18:41:10.872Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b9/67/932f80aa6af9bc1a317b6119052c74f327d81e00b457003a049e324b810c/mapbox_earcut-2.0.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:1a286f73e612a46cafd6d6c843365265090517af16823e2f37277c13cd8b6f09", size = 154924, upload-time = "2025-11-16T18:41:12.104Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/87/38/5db4a91f9f90cbb447be61da5468a2955fad3a840ae4c7dbde789b09d45a/mapbox_earcut-2.0.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:8d081fe1d00dc553e3e68c02fc395324aad0d8ed955f3ff59289264c9b21ace4", size = 159194, upload-time = "2025-11-16T18:41:13.364Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6b/03/de3843b13fe854a010fb2f8b25551d4d5fe1c879ff2e7c8d7d8d7d735a8e/mapbox_earcut-2.0.0-cp314-cp314t-win32.whl", hash = "sha256:13049ca96431bbc7ef7fd7780dd1872209ca11a5c1977f7aa91a1b574a8af863", size = 54143, upload-time = "2025-11-16T18:41:14.564Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/9a/89/fbdee5a56ba51df9be6098b5428636ad75aa994e98d8bec6113d5cba401e/mapbox_earcut-2.0.0-cp314-cp314t-win_amd64.whl", hash = "sha256:6ace78e4fdba3b8cbb7768d44d77a981698305862a07f94bbb6f5cc16659adb4", size = 60833, upload-time = "2025-11-16T18:41:15.694Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "markdown-it-py"
|
||||
version = "4.0.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "mdurl" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/5b/f5/4ec618ed16cc4f8fb3b701563655a69816155e79e24a17b651541804721d/markdown_it_py-4.0.0.tar.gz", hash = "sha256:cb0a2b4aa34f932c007117b194e945bd74e0ec24133ceb5bac59009cda1cb9f3", size = 73070, upload-time = "2025-08-11T12:57:52.854Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/94/54/e7d793b573f298e1c9013b8c4dade17d481164aa517d1d7148619c2cedbf/markdown_it_py-4.0.0-py3-none-any.whl", hash = "sha256:87327c59b172c5011896038353a81343b6754500a08cd7a4973bb48c6d578147", size = 87321, upload-time = "2025-08-11T12:57:51.923Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mdurl"
|
||||
version = "0.1.2"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/d6/54/cfe61301667036ec958cb99bd3efefba235e65cdeb9c84d24a8293ba1d90/mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba", size = 8729, upload-time = "2022-08-14T12:40:10.846Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979, upload-time = "2022-08-14T12:40:09.779Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "moderngl"
|
||||
version = "5.12.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "glcontext" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/da/52/540e2f8c45060bb2709f56eb5a44ae828dfcc97ccecb342c1a7deb467889/moderngl-5.12.0.tar.gz", hash = "sha256:52936a98ccb2f2e1d6e3cb18528b2919f6831e7e3f924e788b5873badce5129b", size = 193232, upload-time = "2024-10-17T12:36:28.002Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/39/13/cf493bdc3cb4f7a6b4fb357e683404dc8a97d19f53d501e4afdd679538e2/moderngl-5.12.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f6efb432f5164f871471d1da36e3a4be9dc3efd7a1e48d0ac6b751e556af5d02", size = 112118, upload-time = "2024-10-17T12:37:14.892Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a9/1f/1d84bba5f42fb19ce240d08d5434fe8e2f34341e68bb9fa89336b6cbdcfc/moderngl-5.12.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:9b09d8d15b2eaab41c8646a664429ec86af225fa25096758497cd212489d2e1e", size = 109371, upload-time = "2024-10-17T12:37:15.992Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/be/ae/bda0b95878e2b36eac66f64d88c08e6c8ea759607f7d40e843a21c2f4f32/moderngl-5.12.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:071042dd4846e58cbe204cf49341b62cd209fdcb6d48018feb5a61c66707fcb2", size = 296206, upload-time = "2024-10-17T12:37:17.204Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/28/bc/93dc73251bcdb9c0f6f5c9a1d97ec2134672c307c68e6106948eab1f73d4/moderngl-5.12.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:91db8302ac7f5d7a82a967388677e1378ff078f1e16d05da37ce77f4633b93b1", size = 270443, upload-time = "2024-10-17T12:37:18.44Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/2e/a1/bd72c788b16c2392d3e1ebb570e56d7f871eaa1854f57917c0f131acb365/moderngl-5.12.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:51971d65ec96a212a814350c8b324ae0754353e1b61826d1a06aa2d060df170e", size = 1345675, upload-time = "2024-10-17T12:37:20.077Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b2/ec/6aff8fa267d9f80e4d32b7a606fdf9f0563103441a7dbaa4f53e272a4ada/moderngl-5.12.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:d56827360c19e831e986243b5daaf6a51006f1ec0d5372084ad446308763d19f", size = 1274906, upload-time = "2024-10-17T12:37:22.372Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/9f/4d/dc3ff763c125080e71b1095875f5dcc80949402019abc073bdfdbed1f4c2/moderngl-5.12.0-cp313-cp313-win32.whl", hash = "sha256:caa432c12b138a6c9571719075c4d103bdc2504cd31aeda38a00ad10fcf268cb", size = 101215, upload-time = "2024-10-17T12:37:23.833Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/2c/8b/0a264732e0ee49fca109e98ec28f4d0c326ffc31466aa6e9668e8961aabb/moderngl-5.12.0-cp313-cp313-win_amd64.whl", hash = "sha256:e34d1cd38f7998258f76a08bb5e87f351ec653b7ea1928b2711f8719c10cefd1", size = 108514, upload-time = "2024-10-17T12:37:25.304Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "moderngl-window"
|
||||
version = "3.1.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "moderngl" },
|
||||
{ name = "numpy" },
|
||||
{ name = "pillow" },
|
||||
{ name = "pyglet" },
|
||||
{ name = "pyglm" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/90/02/92e235891300c901f59647112a0267a07454f58aeb2041aa44f6b85f9cb3/moderngl_window-3.1.1.tar.gz", hash = "sha256:29c2827505f87399f3461d480b2778910fddeebe44ea803301215cf212a6c1bc", size = 353495, upload-time = "2025-01-19T10:07:56.133Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/23/41/d3503f07de8ad3597165f88b07e1064629f82e65385c4307875b2f6b137f/moderngl_window-3.1.1-py3-none-any.whl", hash = "sha256:e3b3ac2b4e23afcbfdac1971318a4db893bed3ba6a8fbde3367b1226af39b2e5", size = 382381, upload-time = "2025-01-19T10:07:53.606Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "networkx"
|
||||
version = "3.6.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/6a/51/63fe664f3908c97be9d2e4f1158eb633317598cfa6e1fc14af5383f17512/networkx-3.6.1.tar.gz", hash = "sha256:26b7c357accc0c8cde558ad486283728b65b6a95d85ee1cd66bafab4c8168509", size = 2517025, upload-time = "2025-12-08T17:02:39.908Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/9e/c9/b2622292ea83fbb4ec318f5b9ab867d0a28ab43c5717bb85b0a5f6b3b0a4/networkx-3.6.1-py3-none-any.whl", hash = "sha256:d47fbf302e7d9cbbb9e2555a0d267983d2aa476bac30e90dfbe5669bd57f3762", size = 2068504, upload-time = "2025-12-08T17:02:38.159Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "numpy"
|
||||
version = "2.4.4"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/d7/9f/b8cef5bffa569759033adda9481211426f12f53299629b410340795c2514/numpy-2.4.4.tar.gz", hash = "sha256:2d390634c5182175533585cc89f3608a4682ccb173cc9bb940b2881c8d6f8fa0", size = 20731587, upload-time = "2026-03-29T13:22:01.298Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/14/1d/d0a583ce4fefcc3308806a749a536c201ed6b5ad6e1322e227ee4848979d/numpy-2.4.4-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:08f2e31ed5e6f04b118e49821397f12767934cfdd12a1ce86a058f91e004ee50", size = 16684933, upload-time = "2026-03-29T13:19:22.47Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c1/62/2b7a48fbb745d344742c0277f01286dead15f3f68e4f359fbfcf7b48f70f/numpy-2.4.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:e823b8b6edc81e747526f70f71a9c0a07ac4e7ad13020aa736bb7c9d67196115", size = 14694532, upload-time = "2026-03-29T13:19:25.581Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e5/87/499737bfba066b4a3bebff24a8f1c5b2dee410b209bc6668c9be692580f0/numpy-2.4.4-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:4a19d9dba1a76618dd86b164d608566f393f8ec6ac7c44f0cc879011c45e65af", size = 5199661, upload-time = "2026-03-29T13:19:28.31Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/cd/da/464d551604320d1491bc345efed99b4b7034143a85787aab78d5691d5a0e/numpy-2.4.4-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:d2a8490669bfe99a233298348acc2d824d496dee0e66e31b66a6022c2ad74a5c", size = 6547539, upload-time = "2026-03-29T13:19:30.97Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/7d/90/8d23e3b0dafd024bf31bdec225b3bb5c2dbfa6912f8a53b8659f21216cbf/numpy-2.4.4-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:45dbed2ab436a9e826e302fcdcbe9133f9b0006e5af7168afb8963a6520da103", size = 15668806, upload-time = "2026-03-29T13:19:33.887Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d1/73/a9d864e42a01896bb5974475438f16086be9ba1f0d19d0bb7a07427c4a8b/numpy-2.4.4-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c901b15172510173f5cb310eae652908340f8dede90fff9e3bf6c0d8dfd92f83", size = 16632682, upload-time = "2026-03-29T13:19:37.336Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/34/fb/14570d65c3bde4e202a031210475ae9cde9b7686a2e7dc97ee67d2833b35/numpy-2.4.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:99d838547ace2c4aace6c4f76e879ddfe02bb58a80c1549928477862b7a6d6ed", size = 17019810, upload-time = "2026-03-29T13:19:40.963Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/8a/77/2ba9d87081fd41f6d640c83f26fb7351e536b7ce6dd9061b6af5904e8e46/numpy-2.4.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:0aec54fd785890ecca25a6003fd9a5aed47ad607bbac5cd64f836ad8666f4959", size = 18357394, upload-time = "2026-03-29T13:19:44.859Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a2/23/52666c9a41708b0853fa3b1a12c90da38c507a3074883823126d4e9d5b30/numpy-2.4.4-cp313-cp313-win32.whl", hash = "sha256:07077278157d02f65c43b1b26a3886bce886f95d20aabd11f87932750dfb14ed", size = 5959556, upload-time = "2026-03-29T13:19:47.661Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/57/fb/48649b4971cde70d817cf97a2a2fdc0b4d8308569f1dd2f2611959d2e0cf/numpy-2.4.4-cp313-cp313-win_amd64.whl", hash = "sha256:5c70f1cc1c4efbe316a572e2d8b9b9cc44e89b95f79ca3331553fbb63716e2bf", size = 12317311, upload-time = "2026-03-29T13:19:50.67Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ba/d8/11490cddd564eb4de97b4579ef6bfe6a736cc07e94c1598590ae25415e01/numpy-2.4.4-cp313-cp313-win_arm64.whl", hash = "sha256:ef4059d6e5152fa1a39f888e344c73fdc926e1b2dd58c771d67b0acfbf2aa67d", size = 10222060, upload-time = "2026-03-29T13:19:54.229Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/99/5d/dab4339177a905aad3e2221c915b35202f1ec30d750dd2e5e9d9a72b804b/numpy-2.4.4-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:4bbc7f303d125971f60ec0aaad5e12c62d0d2c925f0ab1273debd0e4ba37aba5", size = 14822302, upload-time = "2026-03-29T13:19:57.585Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/eb/e4/0564a65e7d3d97562ed6f9b0fd0fb0a6f559ee444092f105938b50043876/numpy-2.4.4-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:4d6d57903571f86180eb98f8f0c839fa9ebbfb031356d87f1361be91e433f5b7", size = 5327407, upload-time = "2026-03-29T13:20:00.601Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/29/8d/35a3a6ce5ad371afa58b4700f1c820f8f279948cca32524e0a695b0ded83/numpy-2.4.4-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:4636de7fd195197b7535f231b5de9e4b36d2c440b6e566d2e4e4746e6af0ca93", size = 6647631, upload-time = "2026-03-29T13:20:02.855Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f4/da/477731acbd5a58a946c736edfdabb2ac5b34c3d08d1ba1a7b437fa0884df/numpy-2.4.4-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ad2e2ef14e0b04e544ea2fa0a36463f847f113d314aa02e5b402fdf910ef309e", size = 15727691, upload-time = "2026-03-29T13:20:06.004Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e6/db/338535d9b152beabeb511579598418ba0212ce77cf9718edd70262cc4370/numpy-2.4.4-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5a285b3b96f951841799528cd1f4f01cd70e7e0204b4abebac9463eecfcf2a40", size = 16681241, upload-time = "2026-03-29T13:20:09.417Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e2/a9/ad248e8f58beb7a0219b413c9c7d8151c5d285f7f946c3e26695bdbbe2df/numpy-2.4.4-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:f8474c4241bc18b750be2abea9d7a9ec84f46ef861dbacf86a4f6e043401f79e", size = 17085767, upload-time = "2026-03-29T13:20:13.126Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b5/1a/3b88ccd3694681356f70da841630e4725a7264d6a885c8d442a697e1146b/numpy-2.4.4-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:4e874c976154687c1f71715b034739b45c7711bec81db01914770373d125e392", size = 18403169, upload-time = "2026-03-29T13:20:17.096Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c2/c9/fcfd5d0639222c6eac7f304829b04892ef51c96a75d479214d77e3ce6e33/numpy-2.4.4-cp313-cp313t-win32.whl", hash = "sha256:9c585a1790d5436a5374bac930dad6ed244c046ed91b2b2a3634eb2971d21008", size = 6083477, upload-time = "2026-03-29T13:20:20.195Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d5/e3/3938a61d1c538aaec8ed6fd6323f57b0c2d2d2219512434c5c878db76553/numpy-2.4.4-cp313-cp313t-win_amd64.whl", hash = "sha256:93e15038125dc1e5345d9b5b68aa7f996ec33b98118d18c6ca0d0b7d6198b7e8", size = 12457487, upload-time = "2026-03-29T13:20:22.946Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/97/6a/7e345032cc60501721ef94e0e30b60f6b0bd601f9174ebd36389a2b86d40/numpy-2.4.4-cp313-cp313t-win_arm64.whl", hash = "sha256:0dfd3f9d3adbe2920b68b5cd3d51444e13a10792ec7154cd0a2f6e74d4ab3233", size = 10292002, upload-time = "2026-03-29T13:20:25.909Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6e/06/c54062f85f673dd5c04cbe2f14c3acb8c8b95e3384869bb8cc9bff8cb9df/numpy-2.4.4-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:f169b9a863d34f5d11b8698ead99febeaa17a13ca044961aa8e2662a6c7766a0", size = 16684353, upload-time = "2026-03-29T13:20:29.504Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/4c/39/8a320264a84404c74cc7e79715de85d6130fa07a0898f67fb5cd5bd79908/numpy-2.4.4-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:2483e4584a1cb3092da4470b38866634bafb223cbcd551ee047633fd2584599a", size = 14704914, upload-time = "2026-03-29T13:20:33.547Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/91/fb/287076b2614e1d1044235f50f03748f31fa287e3dbe6abeb35cdfa351eca/numpy-2.4.4-cp314-cp314-macosx_14_0_arm64.whl", hash = "sha256:2d19e6e2095506d1736b7d80595e0f252d76b89f5e715c35e06e937679ea7d7a", size = 5210005, upload-time = "2026-03-29T13:20:36.45Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/63/eb/fcc338595309910de6ecabfcef2419a9ce24399680bfb149421fa2df1280/numpy-2.4.4-cp314-cp314-macosx_14_0_x86_64.whl", hash = "sha256:6a246d5914aa1c820c9443ddcee9c02bec3e203b0c080349533fae17727dfd1b", size = 6544974, upload-time = "2026-03-29T13:20:39.014Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/44/5d/e7e9044032a716cdfaa3fba27a8e874bf1c5f1912a1ddd4ed071bf8a14a6/numpy-2.4.4-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:989824e9faf85f96ec9c7761cd8d29c531ad857bfa1daa930cba85baaecf1a9a", size = 15684591, upload-time = "2026-03-29T13:20:42.146Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/98/7c/21252050676612625449b4807d6b695b9ce8a7c9e1c197ee6216c8a65c7c/numpy-2.4.4-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:27a8d92cd10f1382a67d7cf4db7ce18341b66438bdd9f691d7b0e48d104c2a9d", size = 16637700, upload-time = "2026-03-29T13:20:46.204Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b1/29/56d2bbef9465db24ef25393383d761a1af4f446a1df9b8cded4fe3a5a5d7/numpy-2.4.4-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:e44319a2953c738205bf3354537979eaa3998ed673395b964c1176083dd46252", size = 17035781, upload-time = "2026-03-29T13:20:50.242Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e3/2b/a35a6d7589d21f44cea7d0a98de5ddcbb3d421b2622a5c96b1edf18707c3/numpy-2.4.4-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:e892aff75639bbef0d2a2cfd55535510df26ff92f63c92cd84ef8d4ba5a5557f", size = 18362959, upload-time = "2026-03-29T13:20:54.019Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/64/c9/d52ec581f2390e0f5f85cbfd80fb83d965fc15e9f0e1aec2195faa142cde/numpy-2.4.4-cp314-cp314-win32.whl", hash = "sha256:1378871da56ca8943c2ba674530924bb8ca40cd228358a3b5f302ad60cf875fc", size = 6008768, upload-time = "2026-03-29T13:20:56.912Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/fa/22/4cc31a62a6c7b74a8730e31a4274c5dc80e005751e277a2ce38e675e4923/numpy-2.4.4-cp314-cp314-win_amd64.whl", hash = "sha256:715d1c092715954784bc79e1174fc2a90093dc4dc84ea15eb14dad8abdcdeb74", size = 12449181, upload-time = "2026-03-29T13:20:59.548Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/70/2e/14cda6f4d8e396c612d1bf97f22958e92148801d7e4f110cabebdc0eef4b/numpy-2.4.4-cp314-cp314-win_arm64.whl", hash = "sha256:2c194dd721e54ecad9ad387c1d35e63dce5c4450c6dc7dd5611283dda239aabb", size = 10496035, upload-time = "2026-03-29T13:21:02.524Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b1/e8/8fed8c8d848d7ecea092dc3469643f9d10bc3a134a815a3b033da1d2039b/numpy-2.4.4-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:2aa0613a5177c264ff5921051a5719d20095ea586ca88cc802c5c218d1c67d3e", size = 14824958, upload-time = "2026-03-29T13:21:05.671Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/05/1a/d8007a5138c179c2bf33ef44503e83d70434d2642877ee8fbb230e7c0548/numpy-2.4.4-cp314-cp314t-macosx_14_0_arm64.whl", hash = "sha256:42c16925aa5a02362f986765f9ebabf20de75cdefdca827d14315c568dcab113", size = 5330020, upload-time = "2026-03-29T13:21:08.635Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/99/64/ffb99ac6ae93faf117bcbd5c7ba48a7f45364a33e8e458545d3633615dda/numpy-2.4.4-cp314-cp314t-macosx_14_0_x86_64.whl", hash = "sha256:874f200b2a981c647340f841730fc3a2b54c9d940566a3c4149099591e2c4c3d", size = 6650758, upload-time = "2026-03-29T13:21:10.949Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6e/6e/795cc078b78a384052e73b2f6281ff7a700e9bf53bcce2ee579d4f6dd879/numpy-2.4.4-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c9b39d38a9bd2ae1becd7eac1303d031c5c110ad31f2b319c6e7d98b135c934d", size = 15729948, upload-time = "2026-03-29T13:21:14.047Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5f/86/2acbda8cc2af5f3d7bfc791192863b9e3e19674da7b5e533fded124d1299/numpy-2.4.4-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b268594bccac7d7cf5844c7732e3f20c50921d94e36d7ec9b79e9857694b1b2f", size = 16679325, upload-time = "2026-03-29T13:21:17.561Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/bc/59/cafd83018f4aa55e0ac6fa92aa066c0a1877b77a615ceff1711c260ffae8/numpy-2.4.4-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:ac6b31e35612a26483e20750126d30d0941f949426974cace8e6b5c58a3657b0", size = 17084883, upload-time = "2026-03-29T13:21:21.106Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f0/85/a42548db84e65ece46ab2caea3d3f78b416a47af387fcbb47ec28e660dc2/numpy-2.4.4-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:8e3ed142f2728df44263aaf5fb1f5b0b99f4070c553a0d7f033be65338329150", size = 18403474, upload-time = "2026-03-29T13:21:24.828Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ed/ad/483d9e262f4b831000062e5d8a45e342166ec8aaa1195264982bca267e62/numpy-2.4.4-cp314-cp314t-win32.whl", hash = "sha256:dddbbd259598d7240b18c9d87c56a9d2fb3b02fe266f49a7c101532e78c1d871", size = 6155500, upload-time = "2026-03-29T13:21:28.205Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c7/03/2fc4e14c7bd4ff2964b74ba90ecb8552540b6315f201df70f137faa5c589/numpy-2.4.4-cp314-cp314t-win_amd64.whl", hash = "sha256:a7164afb23be6e37ad90b2f10426149fd75aee07ca55653d2aa41e66c4ef697e", size = 12637755, upload-time = "2026-03-29T13:21:31.107Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/58/78/548fb8e07b1a341746bfbecb32f2c268470f45fa028aacdbd10d9bc73aab/numpy-2.4.4-cp314-cp314t-win_arm64.whl", hash = "sha256:ba203255017337d39f89bdd58417f03c4426f12beed0440cfd933cb15f8669c7", size = 10566643, upload-time = "2026-03-29T13:21:34.339Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pillow"
|
||||
version = "12.2.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/8c/21/c2bcdd5906101a30244eaffc1b6e6ce71a31bd0742a01eb89e660ebfac2d/pillow-12.2.0.tar.gz", hash = "sha256:a830b1a40919539d07806aa58e1b114df53ddd43213d9c8b75847eee6c0182b5", size = 46987819, upload-time = "2026-04-01T14:46:17.687Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/4a/01/53d10cf0dbad820a8db274d259a37ba50b88b24768ddccec07355382d5ad/pillow-12.2.0-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:8297651f5b5679c19968abefd6bb84d95fe30ef712eb1b2d9b2d31ca61267f4c", size = 4100837, upload-time = "2026-04-01T14:43:41.506Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/0f/98/f3a6657ecb698c937f6c76ee564882945f29b79bad496abcba0e84659ec5/pillow-12.2.0-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:50d8520da2a6ce0af445fa6d648c4273c3eeefbc32d7ce049f22e8b5c3daecc2", size = 4176528, upload-time = "2026-04-01T14:43:43.773Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/69/bc/8986948f05e3ea490b8442ea1c1d4d990b24a7e43d8a51b2c7d8b1dced36/pillow-12.2.0-cp313-cp313-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:766cef22385fa1091258ad7e6216792b156dc16d8d3fa607e7545b2b72061f1c", size = 3640401, upload-time = "2026-04-01T14:43:45.87Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/34/46/6c717baadcd62bc8ed51d238d521ab651eaa74838291bda1f86fe1f864c9/pillow-12.2.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:5d2fd0fa6b5d9d1de415060363433f28da8b1526c1c129020435e186794b3795", size = 5308094, upload-time = "2026-04-01T14:43:48.438Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/71/43/905a14a8b17fdb1ccb58d282454490662d2cb89a6bfec26af6d3520da5ec/pillow-12.2.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:56b25336f502b6ed02e889f4ece894a72612fe885889a6e8c4c80239ff6e5f5f", size = 4695402, upload-time = "2026-04-01T14:43:51.292Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/73/dd/42107efcb777b16fa0393317eac58f5b5cf30e8392e266e76e51cff28c3d/pillow-12.2.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:f1c943e96e85df3d3478f7b691f229887e143f81fedab9b20205349ab04d73ed", size = 6280005, upload-time = "2026-04-01T14:43:54.242Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a8/68/b93e09e5e8549019e61acf49f65b1a8530765a7f812c77a7461bca7e4494/pillow-12.2.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:03f6fab9219220f041c74aeaa2939ff0062bd5c364ba9ce037197f4c6d498cd9", size = 8090669, upload-time = "2026-04-01T14:43:57.335Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/4b/6e/3ccb54ce8ec4ddd1accd2d89004308b7b0b21c4ac3d20fa70af4760a4330/pillow-12.2.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5cdfebd752ec52bf5bb4e35d9c64b40826bc5b40a13df7c3cda20a2c03a0f5ed", size = 6395194, upload-time = "2026-04-01T14:43:59.864Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/67/ee/21d4e8536afd1a328f01b359b4d3997b291ffd35a237c877b331c1c3b71c/pillow-12.2.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:eedf4b74eda2b5a4b2b2fb4c006d6295df3bf29e459e198c90ea48e130dc75c3", size = 7082423, upload-time = "2026-04-01T14:44:02.74Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/78/5f/e9f86ab0146464e8c133fe85df987ed9e77e08b29d8d35f9f9f4d6f917ba/pillow-12.2.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:00a2865911330191c0b818c59103b58a5e697cae67042366970a6b6f1b20b7f9", size = 6505667, upload-time = "2026-04-01T14:44:05.381Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ed/1e/409007f56a2fdce61584fd3acbc2bbc259857d555196cedcadc68c015c82/pillow-12.2.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:1e1757442ed87f4912397c6d35a0db6a7b52592156014706f17658ff58bbf795", size = 7208580, upload-time = "2026-04-01T14:44:08.39Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/23/c4/7349421080b12fb35414607b8871e9534546c128a11965fd4a7002ccfbee/pillow-12.2.0-cp313-cp313-win32.whl", hash = "sha256:144748b3af2d1b358d41286056d0003f47cb339b8c43a9ea42f5fea4d8c66b6e", size = 6375896, upload-time = "2026-04-01T14:44:11.197Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/3f/82/8a3739a5e470b3c6cbb1d21d315800d8e16bff503d1f16b03a4ec3212786/pillow-12.2.0-cp313-cp313-win_amd64.whl", hash = "sha256:390ede346628ccc626e5730107cde16c42d3836b89662a115a921f28440e6a3b", size = 7081266, upload-time = "2026-04-01T14:44:13.947Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c3/25/f968f618a062574294592f668218f8af564830ccebdd1fa6200f598e65c5/pillow-12.2.0-cp313-cp313-win_arm64.whl", hash = "sha256:8023abc91fba39036dbce14a7d6535632f99c0b857807cbbbf21ecc9f4717f06", size = 2463508, upload-time = "2026-04-01T14:44:16.312Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/4d/a4/b342930964e3cb4dce5038ae34b0eab4653334995336cd486c5a8c25a00c/pillow-12.2.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:042db20a421b9bafecc4b84a8b6e444686bd9d836c7fd24542db3e7df7baad9b", size = 5309927, upload-time = "2026-04-01T14:44:18.89Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/9f/de/23198e0a65a9cf06123f5435a5d95cea62a635697f8f03d134d3f3a96151/pillow-12.2.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:dd025009355c926a84a612fecf58bb315a3f6814b17ead51a8e48d3823d9087f", size = 4698624, upload-time = "2026-04-01T14:44:21.115Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/01/a6/1265e977f17d93ea37aa28aa81bad4fa597933879fac2520d24e021c8da3/pillow-12.2.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:88ddbc66737e277852913bd1e07c150cc7bb124539f94c4e2df5344494e0a612", size = 6321252, upload-time = "2026-04-01T14:44:23.663Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/3c/83/5982eb4a285967baa70340320be9f88e57665a387e3a53a7f0db8231a0cd/pillow-12.2.0-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d362d1878f00c142b7e1a16e6e5e780f02be8195123f164edf7eddd911eefe7c", size = 8126550, upload-time = "2026-04-01T14:44:26.772Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/4e/48/6ffc514adce69f6050d0753b1a18fd920fce8cac87620d5a31231b04bfc5/pillow-12.2.0-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2c727a6d53cb0018aadd8018c2b938376af27914a68a492f59dfcaca650d5eea", size = 6433114, upload-time = "2026-04-01T14:44:29.615Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/36/a3/f9a77144231fb8d40ee27107b4463e205fa4677e2ca2548e14da5cf18dce/pillow-12.2.0-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:efd8c21c98c5cc60653bcb311bef2ce0401642b7ce9d09e03a7da87c878289d4", size = 7115667, upload-time = "2026-04-01T14:44:32.773Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c1/fc/ac4ee3041e7d5a565e1c4fd72a113f03b6394cc72ab7089d27608f8aaccb/pillow-12.2.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:9f08483a632889536b8139663db60f6724bfcb443c96f1b18855860d7d5c0fd4", size = 6538966, upload-time = "2026-04-01T14:44:35.252Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c0/a8/27fb307055087f3668f6d0a8ccb636e7431d56ed0750e07a60547b1e083e/pillow-12.2.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:dac8d77255a37e81a2efcbd1fc05f1c15ee82200e6c240d7e127e25e365c39ea", size = 7238241, upload-time = "2026-04-01T14:44:37.875Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ad/4b/926ab182c07fccae9fcb120043464e1ff1564775ec8864f21a0ebce6ac25/pillow-12.2.0-cp313-cp313t-win32.whl", hash = "sha256:ee3120ae9dff32f121610bb08e4313be87e03efeadfc6c0d18f89127e24d0c24", size = 6379592, upload-time = "2026-04-01T14:44:40.336Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c2/c4/f9e476451a098181b30050cc4c9a3556b64c02cf6497ea421ac047e89e4b/pillow-12.2.0-cp313-cp313t-win_amd64.whl", hash = "sha256:325ca0528c6788d2a6c3d40e3568639398137346c3d6e66bb61db96b96511c98", size = 7085542, upload-time = "2026-04-01T14:44:43.251Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/00/a4/285f12aeacbe2d6dc36c407dfbbe9e96d4a80b0fb710a337f6d2ad978c75/pillow-12.2.0-cp313-cp313t-win_arm64.whl", hash = "sha256:2e5a76d03a6c6dcef67edabda7a52494afa4035021a79c8558e14af25313d453", size = 2465765, upload-time = "2026-04-01T14:44:45.996Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/bf/98/4595daa2365416a86cb0d495248a393dfc84e96d62ad080c8546256cb9c0/pillow-12.2.0-cp314-cp314-ios_13_0_arm64_iphoneos.whl", hash = "sha256:3adc9215e8be0448ed6e814966ecf3d9952f0ea40eb14e89a102b87f450660d8", size = 4100848, upload-time = "2026-04-01T14:44:48.48Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/0b/79/40184d464cf89f6663e18dfcf7ca21aae2491fff1a16127681bf1fa9b8cf/pillow-12.2.0-cp314-cp314-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:6a9adfc6d24b10f89588096364cc726174118c62130c817c2837c60cf08a392b", size = 4176515, upload-time = "2026-04-01T14:44:51.353Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b0/63/703f86fd4c422a9cf722833670f4f71418fb116b2853ff7da722ea43f184/pillow-12.2.0-cp314-cp314-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:6a6e67ea2e6feda684ed370f9a1c52e7a243631c025ba42149a2cc5934dec295", size = 3640159, upload-time = "2026-04-01T14:44:53.588Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/71/e0/fb22f797187d0be2270f83500aab851536101b254bfa1eae10795709d283/pillow-12.2.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:2bb4a8d594eacdfc59d9e5ad972aa8afdd48d584ffd5f13a937a664c3e7db0ed", size = 5312185, upload-time = "2026-04-01T14:44:56.039Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ba/8c/1a9e46228571de18f8e28f16fabdfc20212a5d019f3e3303452b3f0a580d/pillow-12.2.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:80b2da48193b2f33ed0c32c38140f9d3186583ce7d516526d462645fd98660ae", size = 4695386, upload-time = "2026-04-01T14:44:58.663Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/70/62/98f6b7f0c88b9addd0e87c217ded307b36be024d4ff8869a812b241d1345/pillow-12.2.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:22db17c68434de69d8ecfc2fe821569195c0c373b25cccb9cbdacf2c6e53c601", size = 6280384, upload-time = "2026-04-01T14:45:01.5Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5e/03/688747d2e91cfbe0e64f316cd2e8005698f76ada3130d0194664174fa5de/pillow-12.2.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:7b14cc0106cd9aecda615dd6903840a058b4700fcb817687d0ee4fc8b6e389be", size = 8091599, upload-time = "2026-04-01T14:45:04.5Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f6/35/577e22b936fcdd66537329b33af0b4ccfefaeabd8aec04b266528cddb33c/pillow-12.2.0-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8cbeb542b2ebc6fcdacabf8aca8c1a97c9b3ad3927d46b8723f9d4f033288a0f", size = 6396021, upload-time = "2026-04-01T14:45:07.117Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/11/8d/d2532ad2a603ca2b93ad9f5135732124e57811d0168155852f37fbce2458/pillow-12.2.0-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4bfd07bc812fbd20395212969e41931001fd59eb55a60658b0e5710872e95286", size = 7083360, upload-time = "2026-04-01T14:45:09.763Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5e/26/d325f9f56c7e039034897e7380e9cc202b1e368bfd04d4cbe6a441f02885/pillow-12.2.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:9aba9a17b623ef750a4d11b742cbafffeb48a869821252b30ee21b5e91392c50", size = 6507628, upload-time = "2026-04-01T14:45:12.378Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5f/f7/769d5632ffb0988f1c5e7660b3e731e30f7f8ec4318e94d0a5d674eb65a4/pillow-12.2.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:deede7c263feb25dba4e82ea23058a235dcc2fe1f6021025dc71f2b618e26104", size = 7209321, upload-time = "2026-04-01T14:45:15.122Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6a/7a/c253e3c645cd47f1aceea6a8bacdba9991bf45bb7dfe927f7c893e89c93c/pillow-12.2.0-cp314-cp314-win32.whl", hash = "sha256:632ff19b2778e43162304d50da0181ce24ac5bb8180122cbe1bf4673428328c7", size = 6479723, upload-time = "2026-04-01T14:45:17.797Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/cd/8b/601e6566b957ca50e28725cb6c355c59c2c8609751efbecd980db44e0349/pillow-12.2.0-cp314-cp314-win_amd64.whl", hash = "sha256:4e6c62e9d237e9b65fac06857d511e90d8461a32adcc1b9065ea0c0fa3a28150", size = 7217400, upload-time = "2026-04-01T14:45:20.529Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d6/94/220e46c73065c3e2951bb91c11a1fb636c8c9ad427ac3ce7d7f3359b9b2f/pillow-12.2.0-cp314-cp314-win_arm64.whl", hash = "sha256:b1c1fbd8a5a1af3412a0810d060a78b5136ec0836c8a4ef9aa11807f2a22f4e1", size = 2554835, upload-time = "2026-04-01T14:45:23.162Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b6/ab/1b426a3974cb0e7da5c29ccff4807871d48110933a57207b5a676cccc155/pillow-12.2.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:57850958fe9c751670e49b2cecf6294acc99e562531f4bd317fa5ddee2068463", size = 5314225, upload-time = "2026-04-01T14:45:25.637Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/19/1e/dce46f371be2438eecfee2a1960ee2a243bbe5e961890146d2dee1ff0f12/pillow-12.2.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:d5d38f1411c0ed9f97bcb49b7bd59b6b7c314e0e27420e34d99d844b9ce3b6f3", size = 4698541, upload-time = "2026-04-01T14:45:28.355Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/55/c3/7fbecf70adb3a0c33b77a300dc52e424dc22ad8cdc06557a2e49523b703d/pillow-12.2.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:5c0a9f29ca8e79f09de89293f82fc9b0270bb4af1d58bc98f540cc4aedf03166", size = 6322251, upload-time = "2026-04-01T14:45:30.924Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/1c/3c/7fbc17cfb7e4fe0ef1642e0abc17fc6c94c9f7a16be41498e12e2ba60408/pillow-12.2.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:1610dd6c61621ae1cf811bef44d77e149ce3f7b95afe66a4512f8c59f25d9ebe", size = 8127807, upload-time = "2026-04-01T14:45:33.908Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ff/c3/a8ae14d6defd2e448493ff512fae903b1e9bd40b72efb6ec55ce0048c8ce/pillow-12.2.0-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0a34329707af4f73cf1782a36cd2289c0368880654a2c11f027bcee9052d35dd", size = 6433935, upload-time = "2026-04-01T14:45:36.623Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6e/32/2880fb3a074847ac159d8f902cb43278a61e85f681661e7419e6596803ed/pillow-12.2.0-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8e9c4f5b3c546fa3458a29ab22646c1c6c787ea8f5ef51300e5a60300736905e", size = 7116720, upload-time = "2026-04-01T14:45:39.258Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/46/87/495cc9c30e0129501643f24d320076f4cc54f718341df18cc70ec94c44e1/pillow-12.2.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:fb043ee2f06b41473269765c2feae53fc2e2fbf96e5e22ca94fb5ad677856f06", size = 6540498, upload-time = "2026-04-01T14:45:41.879Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/18/53/773f5edca692009d883a72211b60fdaf8871cbef075eaa9d577f0a2f989e/pillow-12.2.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:f278f034eb75b4e8a13a54a876cc4a5ab39173d2cdd93a638e1b467fc545ac43", size = 7239413, upload-time = "2026-04-01T14:45:44.705Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c9/e4/4b64a97d71b2a83158134abbb2f5bd3f8a2ea691361282f010998f339ec7/pillow-12.2.0-cp314-cp314t-win32.whl", hash = "sha256:6bb77b2dcb06b20f9f4b4a8454caa581cd4dd0643a08bacf821216a16d9c8354", size = 6482084, upload-time = "2026-04-01T14:45:47.568Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ba/13/306d275efd3a3453f72114b7431c877d10b1154014c1ebbedd067770d629/pillow-12.2.0-cp314-cp314t-win_amd64.whl", hash = "sha256:6562ace0d3fb5f20ed7290f1f929cae41b25ae29528f2af1722966a0a02e2aa1", size = 7225152, upload-time = "2026-04-01T14:45:50.032Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ff/6e/cf826fae916b8658848d7b9f38d88da6396895c676e8086fc0988073aaf8/pillow-12.2.0-cp314-cp314t-win_arm64.whl", hash = "sha256:aa88ccfe4e32d362816319ed727a004423aab09c5cea43c01a4b435643fa34eb", size = 2556579, upload-time = "2026-04-01T14:45:52.529Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pycairo"
|
||||
version = "1.29.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/22/d9/1728840a22a4ef8a8f479b9156aa2943cd98c3907accd3849fb0d5f82bfd/pycairo-1.29.0.tar.gz", hash = "sha256:f3f7fde97325cae80224c09f12564ef58d0d0f655da0e3b040f5807bd5bd3142", size = 665871, upload-time = "2025-11-11T19:13:01.584Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/f0/21/3f477dc318dd4e84a5ae6301e67284199d7e5a2384f3063714041086b65d/pycairo-1.29.0-cp313-cp313-win32.whl", hash = "sha256:3eb382a4141591807073274522f7aecab9e8fa2f14feafd11ac03a13a58141d7", size = 750949, upload-time = "2025-11-11T19:12:12.198Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/43/34/7d27a333c558d6ac16dbc12a35061d389735e99e494ee4effa4ec6d99bed/pycairo-1.29.0-cp313-cp313-win_amd64.whl", hash = "sha256:91114e4b3fbf4287c2b0788f83e1f566ce031bda49cf1c3c3c19c3e986e95c38", size = 844149, upload-time = "2025-11-11T19:12:19.171Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/15/43/e782131e23df69e5c8e631a016ed84f94bbc4981bf6411079f57af730a23/pycairo-1.29.0-cp313-cp313-win_arm64.whl", hash = "sha256:09b7f69a5ff6881e151354ea092137b97b0b1f0b2ab4eb81c92a02cc4a08e335", size = 693595, upload-time = "2025-11-11T19:12:23.445Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/2d/fa/87eaeeb9d53344c769839d7b2854db7ff2cd596211e00dd1b702eeb1838f/pycairo-1.29.0-cp314-cp314-win32.whl", hash = "sha256:69e2a7968a3fbb839736257bae153f547bca787113cc8d21e9e08ca4526e0b6b", size = 767198, upload-time = "2025-11-11T19:12:42.336Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/3c/90/3564d0f64d0a00926ab863dc3c4a129b1065133128e96900772e1c4421f8/pycairo-1.29.0-cp314-cp314-win_amd64.whl", hash = "sha256:e91243437a21cc4c67c401eff4433eadc45745275fa3ade1a0d877e50ffb90da", size = 871579, upload-time = "2025-11-11T19:12:48.982Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5e/91/93632b6ba12ad69c61991e3208bde88486fdfc152be8cfdd13444e9bc650/pycairo-1.29.0-cp314-cp314-win_arm64.whl", hash = "sha256:b72200ea0e5f73ae4c788cd2028a750062221385eb0e6d8f1ecc714d0b4fdf82", size = 719537, upload-time = "2025-11-11T19:12:55.016Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/93/23/37053c039f8d3b9b5017af9bc64d27b680c48a898d48b72e6d6583cf0155/pycairo-1.29.0-cp314-cp314t-win_amd64.whl", hash = "sha256:5e45fce6185f553e79e4ef1722b8e98e6cde9900dbc48cb2637a9ccba86f627a", size = 874015, upload-time = "2025-11-11T19:12:28.47Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d7/54/123f6239685f5f3f2edc123f1e38d2eefacebee18cf3c532d2f4bd51d0ef/pycairo-1.29.0-cp314-cp314t-win_arm64.whl", hash = "sha256:caba0837a4b40d47c8dfb0f24cccc12c7831e3dd450837f2a356c75f21ce5a15", size = 721404, upload-time = "2025-11-11T19:12:36.919Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pydub"
|
||||
version = "0.25.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/fe/9a/e6bca0eed82db26562c73b5076539a4a08d3cffd19c3cc5913a3e61145fd/pydub-0.25.1.tar.gz", hash = "sha256:980a33ce9949cab2a569606b65674d748ecbca4f0796887fd6f46173a7b0d30f", size = 38326, upload-time = "2021-03-10T02:09:54.659Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/a6/53/d78dc063216e62fc55f6b2eebb447f6a4b0a59f55c8406376f76bf959b08/pydub-0.25.1-py2.py3-none-any.whl", hash = "sha256:65617e33033874b59d87db603aa1ed450633288aefead953b30bded59cb599a6", size = 32327, upload-time = "2021-03-10T02:09:53.503Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pyglet"
|
||||
version = "2.1.14"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/e8/a6/ffd78b2d05a820ced85baa11210b8e5d0db0d951767021150be0a231df00/pyglet-2.1.14.tar.gz", hash = "sha256:feb3fba05a85f50f793688d88ddfbcdc57044d971f2d8d2107eb7578eb4af51e", size = 6595146, upload-time = "2026-04-05T08:24:35.549Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/ae/d4/789d34a4674a4ccc0b65ad54d0f963f873d39000c3ebed0880574d5437e5/pyglet-2.1.14-py3-none-any.whl", hash = "sha256:70febf03f206607103e1f9806527019c589002626937aecdca4d095ce0a4b9b0", size = 1032928, upload-time = "2026-04-05T08:24:29.068Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pyglm"
|
||||
version = "2.8.3"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/41/8b/bdaf7b9cacecd28f7b4c6fc2d7d136824c506ad38cfdb37a05ea7ec88694/pyglm-2.8.3.tar.gz", hash = "sha256:161781ea4d1267f796b645f85ebff53aeb8ee4f13b4e993c04d64c96d286e534", size = 584038, upload-time = "2025-11-26T12:12:59.47Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/2d/22/ee11dff20adfc6aac3e0482ed275843e0b9854dbc2e812ab56cdacbed8d6/pyglm-2.8.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:7a6d07b6b73e55a36e1b6daa63acb53f4912f2ddf88f434af4cc70441435aef8", size = 1608547, upload-time = "2025-11-26T12:11:46.426Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/1e/5f/10c4cd636c3e6c63328a476f84bb03501d8016f12053c3a82ba588fc61ce/pyglm-2.8.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:eaf6241f7c3ff169575e11da78f4439422517e42558961332db4cd09e9599267", size = 1362651, upload-time = "2025-11-26T12:11:47.555Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ff/70/2c7fe768900ee9d0f87e7a89375fa7d83b5b0a8f0eee8d0ad06b22a96e37/pyglm-2.8.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:e1ec0dfb8f2c848c4ee6330c70a1ca9333004776c8e5ec76096e0b67c739f688", size = 12157160, upload-time = "2025-11-26T12:11:49.042Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b0/a6/befefccf1c8a0a66f09a7a1a1d324a3f988cb5e6b634026280518e5a83cd/pyglm-2.8.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:3eea9093210afb946769c84fe31f17a9f73696a1161ee84fb42e9255f8c5cc8a", size = 12787899, upload-time = "2025-11-26T12:11:50.946Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/7c/d2/5475d0791b585ae26dc0d690862a0e1e6fda243552a1718628dd937e5543/pyglm-2.8.3-cp313-cp313-manylinux_2_34_aarch64.whl", hash = "sha256:0c652650912dbd88994fa02ec9dba2f3b35dc3995427b6ae8056ae542d5a060a", size = 10886936, upload-time = "2025-11-26T12:11:53.628Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e1/a1/035068410f60ed53007e0488af96f7e4634b679e9156d1090e70732b2159/pyglm-2.8.3-cp313-cp313-manylinux_2_34_x86_64.whl", hash = "sha256:e3bdda68f75ad270e66b0fc7a1883749489cca14c44cbe22bac038fa170a8a1c", size = 11711601, upload-time = "2025-11-26T12:11:55.367Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b5/e6/286d1879eae87199f086136b08c70a3bff27880417f98dadc0cbcdb65e50/pyglm-2.8.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:08f8b1bd0d80ce396ee9cd5d3d4c7aeb4bbfa2a54dc73413924e3c9982412528", size = 11939755, upload-time = "2025-11-26T12:11:57.23Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/72/58/f40f109ac025bb18412db78e6e73ffc20a17b6b495de90352f5aabfb9982/pyglm-2.8.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:12fa61feefa5a255097d0887415bce9dd72c1dd5e5a8c6577121ee5348336a16", size = 12774242, upload-time = "2025-11-26T12:11:59.051Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/17/fd/71b44ee5ac341e9979731a7b868e237f3775e140a9481cea79bae7abb83c/pyglm-2.8.3-cp313-cp313-win_amd64.whl", hash = "sha256:33118ef1d678ab573546757dee7f0a1ca2fba8e8d7760c9fe6320fe0cfa3deb7", size = 1663010, upload-time = "2025-11-26T12:12:00.914Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/fa/1e/9b8ba9d4627585797d8bda952412c93a4c09b70cb25e64756a52accddc1e/pyglm-2.8.3-cp313-cp313-win_arm64.whl", hash = "sha256:73ff3785dfc4ce017626d7ab56d6711a7119c29e2e71294efed73810c1d307f9", size = 1239893, upload-time = "2025-11-26T12:12:02.032Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/65/fe/494d7dce3fcaf0123e787320b4a558d8fe733d6d0e23b7fe51e687f88dc2/pyglm-2.8.3-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:b312012458d0537b3d84f24f4ba51fd3930df7a0773fc643e36f8df27b807c7a", size = 1610593, upload-time = "2025-11-26T12:12:03.136Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/27/c0/37cced4a1b29957a29baebc1f0034be5d5419adf12da4b99140c56152cdb/pyglm-2.8.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:3249bfe5352e18cc777fac591665679a99f270e1ff27cd11dc349af07684f007", size = 1366295, upload-time = "2025-11-26T12:12:04.176Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a7/ba/186176d1c3e26196ae4bec4b228bdbb1304576f2038a7f1635070923ee48/pyglm-2.8.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:cb8ea0d6721c763a26eacde59b2c9165719050dcf49c99a2857f6e1e5a5f30bb", size = 12140715, upload-time = "2025-11-26T12:12:05.429Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/eb/3e/8d9f307649e9b79b34ae51303e46e7012cc2550d60e6dd00ea8d3d8c9cf2/pyglm-2.8.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:83effb89e2cf6dd79cf9ebecf2f9fbda3d25a92b61af264de3cadad408911de6", size = 12764551, upload-time = "2025-11-26T12:12:07.403Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/4c/d6/2481433abe537d7019d9ce75eba86b57e1731e3e0352fd1ac7f31f4d1883/pyglm-2.8.3-cp314-cp314-manylinux_2_34_aarch64.whl", hash = "sha256:e958d65ed55f2716fd8a3a2ef872cc52893ea7300d7feec62dccb27ec25fbc2f", size = 10869966, upload-time = "2025-11-26T12:12:09.198Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/fe/bf/3c78a9718e1d26c5b6ec468a584eb30cd797c46b6edd08e79cb1d67e8bf0/pyglm-2.8.3-cp314-cp314-manylinux_2_34_x86_64.whl", hash = "sha256:ec7cc14d2eb9f46a18012ee7c1a164e0395b058ceb6e341bf6d986316b698574", size = 11693025, upload-time = "2025-11-26T12:12:10.948Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d3/0d/00ef293153b6ca7e56d1be6facbd9d0a8e331d0c6d3114f47f2cf2913eda/pyglm-2.8.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:4beb0ada21e7641a577f274496451befcde79965467ef4027bd933334b3de39b", size = 11920727, upload-time = "2025-11-26T12:12:12.845Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/4e/10/d8ecf9b5ac3b6fc1b179b33dfbd087b8f4d4b12bab99b5794f569a15a99a/pyglm-2.8.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:77878c1b8c713b9e39fe32f870d82e20c864da3b11a3b875eca06c270b04cdbe", size = 12759345, upload-time = "2025-11-26T12:12:14.705Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a1/d1/cc1f75ee77fd2f9bcb122bc7f3a628710fe3f0bc517333fa9f38268a7065/pyglm-2.8.3-cp314-cp314-win_amd64.whl", hash = "sha256:15c77bc46ff69d945565309e13ca99c4a001d6a941a80c45f26fbdec80fa16c4", size = 1710524, upload-time = "2025-11-26T12:12:16.486Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/35/51/74c0a3107567dc769c06b6c04c7bc828f33792e089036c637334b7e4c573/pyglm-2.8.3-cp314-cp314-win_arm64.whl", hash = "sha256:2b16ec33bd43c514502bae8de2b319d168259090e101e1cde79cd0a7d33e1185", size = 1271521, upload-time = "2025-11-26T12:12:17.611Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/32/8e/867045b54da8257b21c71c0255ba7a231c251aae4b5f26b12eb50b651cc7/pyglm-2.8.3-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:6a1f1ab8debc06e0fdedb3f4285ded4bec38bf075652c393039838504767e6cf", size = 1633871, upload-time = "2025-11-26T12:12:18.791Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/93/f5/81bb8b52e132dc1ecc87b7ffb50c714b4fd2f71f98b801dd376e036f942b/pyglm-2.8.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:a7835d18747ab9f8e736e343cc35bee0a514f18add282f1fc8035945fcf9d9bd", size = 1387757, upload-time = "2025-11-26T12:12:20.497Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/32/40/8581283c00e2a18a6bb20a9192e25a792b605c53dee1c3abb8871eb0d3ca/pyglm-2.8.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:af3ddee3d150bbef68ee7338ccd3e0710b75b08121b8efd52d786b0d2b6731be", size = 12724921, upload-time = "2025-11-26T12:12:21.802Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a0/0e/bc3c03038da822d1a66c38e166d4c89b6bdab846e576ac226442813af7f4/pyglm-2.8.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:0a76c8eaba0c58f5738e87be5efcd16c4e75540fe6ebfdf15c236a799a61358e", size = 13317946, upload-time = "2025-11-26T12:12:23.947Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/3b/21/b1f52dc73d610e36aa3ccf3ef61634530e6f97c2ca809a057839bf578667/pyglm-2.8.3-cp314-cp314t-manylinux_2_34_aarch64.whl", hash = "sha256:879ee9ab3c8ab47b1de59fe7e593eda854b8349f274ca60f057b83f3a405b84d", size = 11371582, upload-time = "2025-11-26T12:12:25.768Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/16/aa/e03cc7a2daceb1bbdf98780a991a323e4078254584cf6664984a626ecfe1/pyglm-2.8.3-cp314-cp314t-manylinux_2_34_x86_64.whl", hash = "sha256:3e37c15b6c3e08f960b34ff9ec42e73469dfd868aec214e8a347da6c9d0245d6", size = 12192848, upload-time = "2025-11-26T12:12:28.606Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/69/07/be893aee24a9a8b5400feda4d032fad9d281047d4379aa9f5ef4bea1f6a4/pyglm-2.8.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:bd34a8670debef4a55bc756b14cbe8b0a4daa49f8f6850c86c5e11d20554927f", size = 12414214, upload-time = "2025-11-26T12:12:30.438Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/0c/06/6bb4e8a09f7dd2bf8dc1f4cc5edc938fc1247a1b2770833515fb418fc695/pyglm-2.8.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:699f852e0335b79d0b664ba1c2d02cb4689256cda786e7780e821f60b0824c46", size = 13237516, upload-time = "2025-11-26T12:12:32.412Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/2b/5c/7f15edd05020540748dad8f5eae0a07ed7f14f699bff530172b8850bd998/pyglm-2.8.3-cp314-cp314t-win_amd64.whl", hash = "sha256:78caadaf9cc2ddea1c55b0d44fa8032f35c9f821a6f152b72422e5657d38f01d", size = 1764614, upload-time = "2025-11-26T12:12:34.498Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a7/f9/8bc8d010503a250319c55d2ceec5f90b0e807c7f85d581638c5ecd0a81de/pyglm-2.8.3-cp314-cp314t-win_arm64.whl", hash = "sha256:69400ad1852ca0972e4d9cbef9d9510941d4b81dc0fffebc5ac796a85440a119", size = 1292992, upload-time = "2025-11-26T12:12:35.681Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pygments"
|
||||
version = "2.20.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/c3/b2/bc9c9196916376152d655522fdcebac55e66de6603a76a02bca1b6414f6c/pygments-2.20.0.tar.gz", hash = "sha256:6757cd03768053ff99f3039c1a36d6c0aa0b263438fcab17520b30a303a82b5f", size = 4955991, upload-time = "2026-03-29T13:29:33.898Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/f4/7e/a72dd26f3b0f4f2bf1dd8923c85f7ceb43172af56d63c7383eb62b332364/pygments-2.20.0-py3-none-any.whl", hash = "sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176", size = 1231151, upload-time = "2026-03-29T13:29:30.038Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pyobjc-core"
|
||||
version = "12.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/b8/b6/d5612eb40be4fd5ef88c259339e6313f46ba67577a95d86c3470b951fce0/pyobjc_core-12.1.tar.gz", hash = "sha256:2bb3903f5387f72422145e1466b3ac3f7f0ef2e9960afa9bcd8961c5cbf8bd21", size = 1000532, upload-time = "2025-11-14T10:08:28.292Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/f4/d2/29e5e536adc07bc3d33dd09f3f7cf844bf7b4981820dc2a91dd810f3c782/pyobjc_core-12.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:01c0cf500596f03e21c23aef9b5f326b9fb1f8f118cf0d8b66749b6cf4cbb37a", size = 677370, upload-time = "2025-11-14T09:33:05.273Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/1b/f0/4b4ed8924cd04e425f2a07269943018d43949afad1c348c3ed4d9d032787/pyobjc_core-12.1-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:177aaca84bb369a483e4961186704f64b2697708046745f8167e818d968c88fc", size = 719586, upload-time = "2025-11-14T09:33:53.302Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/25/98/9f4ed07162de69603144ff480be35cd021808faa7f730d082b92f7ebf2b5/pyobjc_core-12.1-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:844515f5d86395b979d02152576e7dee9cc679acc0b32dc626ef5bda315eaa43", size = 670164, upload-time = "2025-11-14T09:34:37.458Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/62/50/dc076965c96c7f0de25c0a32b7f8aa98133ed244deaeeacfc758783f1f30/pyobjc_core-12.1-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:453b191df1a4b80e756445b935491b974714456ae2cbae816840bd96f86db882", size = 712204, upload-time = "2025-11-14T09:35:24.148Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pyobjc-framework-cocoa"
|
||||
version = "12.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "pyobjc-core" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/02/a3/16ca9a15e77c061a9250afbae2eae26f2e1579eb8ca9462ae2d2c71e1169/pyobjc_framework_cocoa-12.1.tar.gz", hash = "sha256:5556c87db95711b985d5efdaaf01c917ddd41d148b1e52a0c66b1a2e2c5c1640", size = 2772191, upload-time = "2025-11-14T10:13:02.069Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/ad/31/0c2e734165abb46215797bd830c4bdcb780b699854b15f2b6240515edcc6/pyobjc_framework_cocoa-12.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:5a3dcd491cacc2f5a197142b3c556d8aafa3963011110102a093349017705118", size = 384689, upload-time = "2025-11-14T09:41:41.478Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/23/3b/b9f61be7b9f9b4e0a6db18b3c35c4c4d589f2d04e963e2174d38c6555a92/pyobjc_framework_cocoa-12.1-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:914b74328c22d8ca261d78c23ef2befc29776e0b85555973927b338c5734ca44", size = 388843, upload-time = "2025-11-14T09:42:05.719Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/59/bb/f777cc9e775fc7dae77b569254570fe46eb842516b3e4fe383ab49eab598/pyobjc_framework_cocoa-12.1-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:03342a60fc0015bcdf9b93ac0b4f457d3938e9ef761b28df9564c91a14f0129a", size = 384932, upload-time = "2025-11-14T09:42:29.771Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/58/27/b457b7b37089cad692c8aada90119162dfb4c4a16f513b79a8b2b022b33b/pyobjc_framework_cocoa-12.1-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:6ba1dc1bfa4da42d04e93d2363491275fb2e2be5c20790e561c8a9e09b8cf2cc", size = 388970, upload-time = "2025-11-14T09:42:53.964Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rich"
|
||||
version = "14.3.3"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "markdown-it-py" },
|
||||
{ name = "pygments" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/b3/c6/f3b320c27991c46f43ee9d856302c70dc2d0fb2dba4842ff739d5f46b393/rich-14.3.3.tar.gz", hash = "sha256:b8daa0b9e4eef54dd8cf7c86c03713f53241884e814f4e2f5fb342fe520f639b", size = 230582, upload-time = "2026-02-19T17:23:12.474Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/14/25/b208c5683343959b670dc001595f2f3737e051da617f66c31f7c4fa93abc/rich-14.3.3-py3-none-any.whl", hash = "sha256:793431c1f8619afa7d3b52b2cdec859562b950ea0d4b6b505397612db8d5362d", size = 310458, upload-time = "2026-02-19T17:23:13.732Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "scipy"
|
||||
version = "1.17.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "numpy" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/7a/97/5a3609c4f8d58b039179648e62dd220f89864f56f7357f5d4f45c29eb2cc/scipy-1.17.1.tar.gz", hash = "sha256:95d8e012d8cb8816c226aef832200b1d45109ed4464303e997c5b13122b297c0", size = 30573822, upload-time = "2026-02-23T00:26:24.851Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/76/27/07ee1b57b65e92645f219b37148a7e7928b82e2b5dbeccecb4dff7c64f0b/scipy-1.17.1-cp313-cp313-macosx_10_14_x86_64.whl", hash = "sha256:5e3c5c011904115f88a39308379c17f91546f77c1667cea98739fe0fccea804c", size = 31590199, upload-time = "2026-02-23T00:19:17.192Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ec/ae/db19f8ab842e9b724bf5dbb7db29302a91f1e55bc4d04b1025d6d605a2c5/scipy-1.17.1-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:6fac755ca3d2c3edcb22f479fceaa241704111414831ddd3bc6056e18516892f", size = 28154001, upload-time = "2026-02-23T00:19:22.241Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5b/58/3ce96251560107b381cbd6e8413c483bbb1228a6b919fa8652b0d4090e7f/scipy-1.17.1-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:7ff200bf9d24f2e4d5dc6ee8c3ac64d739d3a89e2326ba68aaf6c4a2b838fd7d", size = 20325719, upload-time = "2026-02-23T00:19:26.329Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b2/83/15087d945e0e4d48ce2377498abf5ad171ae013232ae31d06f336e64c999/scipy-1.17.1-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:4b400bdc6f79fa02a4d86640310dde87a21fba0c979efff5248908c6f15fad1b", size = 22683595, upload-time = "2026-02-23T00:19:30.304Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b4/e0/e58fbde4a1a594c8be8114eb4aac1a55bcd6587047efc18a61eb1f5c0d30/scipy-1.17.1-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2b64ca7d4aee0102a97f3ba22124052b4bd2152522355073580bf4845e2550b6", size = 32896429, upload-time = "2026-02-23T00:19:35.536Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f5/5f/f17563f28ff03c7b6799c50d01d5d856a1d55f2676f537ca8d28c7f627cd/scipy-1.17.1-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:581b2264fc0aa555f3f435a5944da7504ea3a065d7029ad60e7c3d1ae09c5464", size = 35203952, upload-time = "2026-02-23T00:19:42.259Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/8d/a5/9afd17de24f657fdfe4df9a3f1ea049b39aef7c06000c13db1530d81ccca/scipy-1.17.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:beeda3d4ae615106d7094f7e7cef6218392e4465cc95d25f900bebabfded0950", size = 34979063, upload-time = "2026-02-23T00:19:47.547Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/8b/13/88b1d2384b424bf7c924f2038c1c409f8d88bb2a8d49d097861dd64a57b2/scipy-1.17.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6609bc224e9568f65064cfa72edc0f24ee6655b47575954ec6339534b2798369", size = 37598449, upload-time = "2026-02-23T00:19:53.238Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/35/e5/d6d0e51fc888f692a35134336866341c08655d92614f492c6860dc45bb2c/scipy-1.17.1-cp313-cp313-win_amd64.whl", hash = "sha256:37425bc9175607b0268f493d79a292c39f9d001a357bebb6b88fdfaff13f6448", size = 36510943, upload-time = "2026-02-23T00:20:50.89Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/2a/fd/3be73c564e2a01e690e19cc618811540ba5354c67c8680dce3281123fb79/scipy-1.17.1-cp313-cp313-win_arm64.whl", hash = "sha256:5cf36e801231b6a2059bf354720274b7558746f3b1a4efb43fcf557ccd484a87", size = 24545621, upload-time = "2026-02-23T00:20:55.871Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6f/6b/17787db8b8114933a66f9dcc479a8272e4b4da75fe03b0c282f7b0ade8cd/scipy-1.17.1-cp313-cp313t-macosx_10_14_x86_64.whl", hash = "sha256:d59c30000a16d8edc7e64152e30220bfbd724c9bbb08368c054e24c651314f0a", size = 31936708, upload-time = "2026-02-23T00:19:58.694Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/38/2e/524405c2b6392765ab1e2b722a41d5da33dc5c7b7278184a8ad29b6cb206/scipy-1.17.1-cp313-cp313t-macosx_12_0_arm64.whl", hash = "sha256:010f4333c96c9bb1a4516269e33cb5917b08ef2166d5556ca2fd9f082a9e6ea0", size = 28570135, upload-time = "2026-02-23T00:20:03.934Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/fd/c3/5bd7199f4ea8556c0c8e39f04ccb014ac37d1468e6cfa6a95c6b3562b76e/scipy-1.17.1-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:2ceb2d3e01c5f1d83c4189737a42d9cb2fc38a6eeed225e7515eef71ad301dce", size = 20741977, upload-time = "2026-02-23T00:20:07.935Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d9/b8/8ccd9b766ad14c78386599708eb745f6b44f08400a5fd0ade7cf89b6fc93/scipy-1.17.1-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:844e165636711ef41f80b4103ed234181646b98a53c8f05da12ca5ca289134f6", size = 23029601, upload-time = "2026-02-23T00:20:12.161Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6d/a0/3cb6f4d2fb3e17428ad2880333cac878909ad1a89f678527b5328b93c1d4/scipy-1.17.1-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:158dd96d2207e21c966063e1635b1063cd7787b627b6f07305315dd73d9c679e", size = 33019667, upload-time = "2026-02-23T00:20:17.208Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f3/c3/2d834a5ac7bf3a0c806ad1508efc02dda3c8c61472a56132d7894c312dea/scipy-1.17.1-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:74cbb80d93260fe2ffa334efa24cb8f2f0f622a9b9febf8b483c0b865bfb3475", size = 35264159, upload-time = "2026-02-23T00:20:23.087Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/4d/77/d3ed4becfdbd217c52062fafe35a72388d1bd82c2d0ba5ca19d6fcc93e11/scipy-1.17.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:dbc12c9f3d185f5c737d801da555fb74b3dcfa1a50b66a1a93e09190f41fab50", size = 35102771, upload-time = "2026-02-23T00:20:28.636Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/bd/12/d19da97efde68ca1ee5538bb261d5d2c062f0c055575128f11a2730e3ac1/scipy-1.17.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:94055a11dfebe37c656e70317e1996dc197e1a15bbcc351bcdd4610e128fe1ca", size = 37665910, upload-time = "2026-02-23T00:20:34.743Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/06/1c/1172a88d507a4baaf72c5a09bb6c018fe2ae0ab622e5830b703a46cc9e44/scipy-1.17.1-cp313-cp313t-win_amd64.whl", hash = "sha256:e30bdeaa5deed6bc27b4cc490823cd0347d7dae09119b8803ae576ea0ce52e4c", size = 36562980, upload-time = "2026-02-23T00:20:40.575Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/70/b0/eb757336e5a76dfa7911f63252e3b7d1de00935d7705cf772db5b45ec238/scipy-1.17.1-cp313-cp313t-win_arm64.whl", hash = "sha256:a720477885a9d2411f94a93d16f9d89bad0f28ca23c3f8daa521e2dcc3f44d49", size = 24856543, upload-time = "2026-02-23T00:20:45.313Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/cf/83/333afb452af6f0fd70414dc04f898647ee1423979ce02efa75c3b0f2c28e/scipy-1.17.1-cp314-cp314-macosx_10_14_x86_64.whl", hash = "sha256:a48a72c77a310327f6a3a920092fa2b8fd03d7deaa60f093038f22d98e096717", size = 31584510, upload-time = "2026-02-23T00:21:01.015Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ed/a6/d05a85fd51daeb2e4ea71d102f15b34fedca8e931af02594193ae4fd25f7/scipy-1.17.1-cp314-cp314-macosx_12_0_arm64.whl", hash = "sha256:45abad819184f07240d8a696117a7aacd39787af9e0b719d00285549ed19a1e9", size = 28170131, upload-time = "2026-02-23T00:21:05.888Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/db/7b/8624a203326675d7746a254083a187398090a179335b2e4a20e2ddc46e83/scipy-1.17.1-cp314-cp314-macosx_14_0_arm64.whl", hash = "sha256:3fd1fcdab3ea951b610dc4cef356d416d5802991e7e32b5254828d342f7b7e0b", size = 20342032, upload-time = "2026-02-23T00:21:09.904Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c9/35/2c342897c00775d688d8ff3987aced3426858fd89d5a0e26e020b660b301/scipy-1.17.1-cp314-cp314-macosx_14_0_x86_64.whl", hash = "sha256:7bdf2da170b67fdf10bca777614b1c7d96ae3ca5794fd9587dce41eb2966e866", size = 22678766, upload-time = "2026-02-23T00:21:14.313Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ef/f2/7cdb8eb308a1a6ae1e19f945913c82c23c0c442a462a46480ce487fdc0ac/scipy-1.17.1-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:adb2642e060a6549c343603a3851ba76ef0b74cc8c079a9a58121c7ec9fe2350", size = 32957007, upload-time = "2026-02-23T00:21:19.663Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/0b/2e/7eea398450457ecb54e18e9d10110993fa65561c4f3add5e8eccd2b9cd41/scipy-1.17.1-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:eee2cfda04c00a857206a4330f0c5e3e56535494e30ca445eb19ec624ae75118", size = 35221333, upload-time = "2026-02-23T00:21:25.278Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d9/77/5b8509d03b77f093a0d52e606d3c4f79e8b06d1d38c441dacb1e26cacf46/scipy-1.17.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:d2650c1fb97e184d12d8ba010493ee7b322864f7d3d00d3f9bb97d9c21de4068", size = 35042066, upload-time = "2026-02-23T00:21:31.358Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f9/df/18f80fb99df40b4070328d5ae5c596f2f00fffb50167e31439e932f29e7d/scipy-1.17.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:08b900519463543aa604a06bec02461558a6e1cef8fdbb8098f77a48a83c8118", size = 37612763, upload-time = "2026-02-23T00:21:37.247Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/4b/39/f0e8ea762a764a9dc52aa7dabcfad51a354819de1f0d4652b6a1122424d6/scipy-1.17.1-cp314-cp314-win_amd64.whl", hash = "sha256:3877ac408e14da24a6196de0ddcace62092bfc12a83823e92e49e40747e52c19", size = 37290984, upload-time = "2026-02-23T00:22:35.023Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/7c/56/fe201e3b0f93d1a8bcf75d3379affd228a63d7e2d80ab45467a74b494947/scipy-1.17.1-cp314-cp314-win_arm64.whl", hash = "sha256:f8885db0bc2bffa59d5c1b72fad7a6a92d3e80e7257f967dd81abb553a90d293", size = 25192877, upload-time = "2026-02-23T00:22:39.798Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/96/ad/f8c414e121f82e02d76f310f16db9899c4fcde36710329502a6b2a3c0392/scipy-1.17.1-cp314-cp314t-macosx_10_14_x86_64.whl", hash = "sha256:1cc682cea2ae55524432f3cdff9e9a3be743d52a7443d0cba9017c23c87ae2f6", size = 31949750, upload-time = "2026-02-23T00:21:42.289Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/7c/b0/c741e8865d61b67c81e255f4f0a832846c064e426636cd7de84e74d209be/scipy-1.17.1-cp314-cp314t-macosx_12_0_arm64.whl", hash = "sha256:2040ad4d1795a0ae89bfc7e8429677f365d45aa9fd5e4587cf1ea737f927b4a1", size = 28585858, upload-time = "2026-02-23T00:21:47.706Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ed/1b/3985219c6177866628fa7c2595bfd23f193ceebbe472c98a08824b9466ff/scipy-1.17.1-cp314-cp314t-macosx_14_0_arm64.whl", hash = "sha256:131f5aaea57602008f9822e2115029b55d4b5f7c070287699fe45c661d051e39", size = 20757723, upload-time = "2026-02-23T00:21:52.039Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c0/19/2a04aa25050d656d6f7b9e7b685cc83d6957fb101665bfd9369ca6534563/scipy-1.17.1-cp314-cp314t-macosx_14_0_x86_64.whl", hash = "sha256:9cdc1a2fcfd5c52cfb3045feb399f7b3ce822abdde3a193a6b9a60b3cb5854ca", size = 23043098, upload-time = "2026-02-23T00:21:56.185Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/86/f1/3383beb9b5d0dbddd030335bf8a8b32d4317185efe495374f134d8be6cce/scipy-1.17.1-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6e3dcd57ab780c741fde8dc68619de988b966db759a3c3152e8e9142c26295ad", size = 33030397, upload-time = "2026-02-23T00:22:01.404Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/41/68/8f21e8a65a5a03f25a79165ec9d2b28c00e66dc80546cf5eb803aeeff35b/scipy-1.17.1-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a9956e4d4f4a301ebf6cde39850333a6b6110799d470dbbb1e25326ac447f52a", size = 35281163, upload-time = "2026-02-23T00:22:07.024Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/84/8d/c8a5e19479554007a5632ed7529e665c315ae7492b4f946b0deb39870e39/scipy-1.17.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:a4328d245944d09fd639771de275701ccadf5f781ba0ff092ad141e017eccda4", size = 35116291, upload-time = "2026-02-23T00:22:12.585Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/52/52/e57eceff0e342a1f50e274264ed47497b59e6a4e3118808ee58ddda7b74a/scipy-1.17.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:a77cbd07b940d326d39a1d1b37817e2ee4d79cb30e7338f3d0cddffae70fcaa2", size = 37682317, upload-time = "2026-02-23T00:22:18.513Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/11/2f/b29eafe4a3fbc3d6de9662b36e028d5f039e72d345e05c250e121a230dd4/scipy-1.17.1-cp314-cp314t-win_amd64.whl", hash = "sha256:eb092099205ef62cd1782b006658db09e2fed75bffcae7cc0d44052d8aa0f484", size = 37345327, upload-time = "2026-02-23T00:22:24.442Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/07/39/338d9219c4e87f3e708f18857ecd24d22a0c3094752393319553096b98af/scipy-1.17.1-cp314-cp314t-win_arm64.whl", hash = "sha256:200e1050faffacc162be6a486a984a0497866ec54149a01270adc8a59b7c7d21", size = 25489165, upload-time = "2026-02-23T00:22:29.563Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "screeninfo"
|
||||
version = "0.8.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "cython", marker = "sys_platform == 'darwin'" },
|
||||
{ name = "pyobjc-framework-cocoa", marker = "sys_platform == 'darwin'" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/ec/bb/e69e5e628d43f118e0af4fc063c20058faa8635c95a1296764acc8167e27/screeninfo-0.8.1.tar.gz", hash = "sha256:9983076bcc7e34402a1a9e4d7dabf3729411fd2abb3f3b4be7eba73519cd2ed1", size = 10666, upload-time = "2022-09-09T11:35:23.419Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/6e/bf/c5205d480307bef660e56544b9e3d7ff687da776abb30c9cb3f330887570/screeninfo-0.8.1-py3-none-any.whl", hash = "sha256:e97d6b173856edcfa3bd282f81deb528188aff14b11ec3e195584e7641be733c", size = 12907, upload-time = "2022-09-09T11:35:21.351Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "skia-pathops"
|
||||
version = "0.9.2"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/4a/f6/ab37d6fa21f25965d4ad059745c76f13ddfb92a2c06a842a42ad77961c24/skia_pathops-0.9.2.tar.gz", hash = "sha256:4b6d8459f6f4a69282cb26fca0c2bb0b321cc58a9bf9cc6579a52a391edc0319", size = 65115346, upload-time = "2026-02-16T10:30:22.753Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/75/10/45af3ea2dee706a340601da315e450c449f76aaa18651cfe2677b0c65161/skia_pathops-0.9.2-cp310-abi3-macosx_10_9_universal2.whl", hash = "sha256:c7a925b919c050df1e0545d26a69b64d9c8e1959e4dca73b06df088bf01d30f0", size = 2897494, upload-time = "2026-02-16T10:30:00.265Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b4/20/711d733b252696aedd78175e0f60acd42299de680d5a50a2750b96578841/skia_pathops-0.9.2-cp310-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d94c18a60b1e56910240a65dcc841cca37067f6432a4881d20baff17b6d77915", size = 3300314, upload-time = "2026-02-16T10:30:02.53Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/95/47/bccbdb7ee12bbcc43c1051f9fd6933d16e3ffc8f20263155bd03709bde9e/skia_pathops-0.9.2-cp310-abi3-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:70b28883f209a0df84da14e980e7a07c55ed93b913955694d90ddef2f29a261b", size = 2999370, upload-time = "2026-02-16T10:30:04.445Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5e/55/d5a1925d61ab683aaf08a3a80749371991f82fdeb53e3dbeae0046ce80ac/skia_pathops-0.9.2-cp310-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:8122e50e03472657781c951f3019d9b85d9b1cbc93ebac635b673f99b18895b6", size = 3955374, upload-time = "2026-02-16T10:30:06.308Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/36/49/c81e1a551726b8153c7a600b041e4480ac85db13985b7b260a01d85e0a6c/skia_pathops-0.9.2-cp310-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:f8c72c70e57dd6655f880ae63642ff26753bb888f4c6411709a12cc10bee005e", size = 4316667, upload-time = "2026-02-16T10:30:08.326Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/bb/b4/484ba09325c75d4470578b3f16bfe5a30cc348ece2566df59702c487084c/skia_pathops-0.9.2-cp310-abi3-win32.whl", hash = "sha256:3b9ef6629d2c8cb8604a7e22d4d2fe2c0160788b9792145a2cf0f968ec245751", size = 1450912, upload-time = "2026-02-16T10:30:09.762Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ff/96/bd1bfaf5335242a86d8af940ff2124861e9bc6a5520cf96fda374fd10945/skia_pathops-0.9.2-cp310-abi3-win_amd64.whl", hash = "sha256:9ae72d801b5f4c5dbb937fb25476a12fa2da70860f28dd637da2b529dbd8271c", size = 1782901, upload-time = "2026-02-16T10:30:11.546Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "soupsieve"
|
||||
version = "2.8.3"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/7b/ae/2d9c981590ed9999a0d91755b47fc74f74de286b0f5cee14c9269041e6c4/soupsieve-2.8.3.tar.gz", hash = "sha256:3267f1eeea4251fb42728b6dfb746edc9acaffc4a45b27e19450b676586e8349", size = 118627, upload-time = "2026-01-20T04:27:02.457Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/46/2c/1462b1d0a634697ae9e55b3cecdcb64788e8b7d63f54d923fcd0bb140aed/soupsieve-2.8.3-py3-none-any.whl", hash = "sha256:ed64f2ba4eebeab06cc4962affce381647455978ffc1e36bb79a545b91f45a95", size = 37016, upload-time = "2026-01-20T04:27:01.012Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "srt"
|
||||
version = "3.5.3"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/66/b7/4a1bc231e0681ebf339337b0cd05b91dc6a0d701fa852bb812e244b7a030/srt-3.5.3.tar.gz", hash = "sha256:4884315043a4f0740fd1f878ed6caa376ac06d70e135f306a6dc44632eed0cc0", size = 28296, upload-time = "2023-03-28T02:35:44.007Z" }
|
||||
|
||||
[[package]]
|
||||
name = "svgelements"
|
||||
version = "1.9.6"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/5d/29/1c93c94a2289675ba2ff898612f9c9a03f46d69f253bdf4da0dfc08a599d/svgelements-1.9.6.tar.gz", hash = "sha256:7c02ad6404cd3d1771fd50e40fbfc0550b0893933466f86a6eb815f3ba3f37f7", size = 162145, upload-time = "2023-08-17T02:01:51.822Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/48/2c/6c9bb53db56c8a12a736d2158a8b842a5993b96daabc29d90a098e840280/svgelements-1.9.6-py2.py3-none-any.whl", hash = "sha256:8a5cf2cc066d98e713d5b875b1d6e5eeb9b92e855e835ebd7caab2713ae1dcad", size = 137856, upload-time = "2023-08-17T02:01:48.76Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tqdm"
|
||||
version = "4.67.3"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "colorama", marker = "sys_platform == 'win32'" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/09/a9/6ba95a270c6f1fbcd8dac228323f2777d886cb206987444e4bce66338dd4/tqdm-4.67.3.tar.gz", hash = "sha256:7d825f03f89244ef73f1d4ce193cb1774a8179fd96f31d7e1dcde62092b960bb", size = 169598, upload-time = "2026-02-03T17:35:53.048Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/16/e1/3079a9ff9b8e11b846c6ac5c8b5bfb7ff225eee721825310c91b3b50304f/tqdm-4.67.3-py3-none-any.whl", hash = "sha256:ee1e4c0e59148062281c49d80b25b67771a127c85fc9676d3be5f243206826bf", size = 78374, upload-time = "2026-02-03T17:35:50.982Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "typing-extensions"
|
||||
version = "4.15.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/72/94/1a15dd82efb362ac84269196e94cf00f187f7ed21c242792a923cdb1c61f/typing_extensions-4.15.0.tar.gz", hash = "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466", size = 109391, upload-time = "2025-08-25T13:49:26.313Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548", size = 44614, upload-time = "2025-08-25T13:49:24.86Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "watchdog"
|
||||
version = "6.0.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/db/7d/7f3d619e951c88ed75c6037b246ddcf2d322812ee8ea189be89511721d54/watchdog-6.0.0.tar.gz", hash = "sha256:9ddf7c82fda3ae8e24decda1338ede66e1c99883db93711d8fb941eaa2d8c282", size = 131220, upload-time = "2024-11-01T14:07:13.037Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/68/98/b0345cabdce2041a01293ba483333582891a3bd5769b08eceb0d406056ef/watchdog-6.0.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:490ab2ef84f11129844c23fb14ecf30ef3d8a6abafd3754a6f75ca1e6654136c", size = 96480, upload-time = "2024-11-01T14:06:42.952Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/85/83/cdf13902c626b28eedef7ec4f10745c52aad8a8fe7eb04ed7b1f111ca20e/watchdog-6.0.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:76aae96b00ae814b181bb25b1b98076d5fc84e8a53cd8885a318b42b6d3a5134", size = 88451, upload-time = "2024-11-01T14:06:45.084Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/fe/c4/225c87bae08c8b9ec99030cd48ae9c4eca050a59bf5c2255853e18c87b50/watchdog-6.0.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a175f755fc2279e0b7312c0035d52e27211a5bc39719dd529625b1930917345b", size = 89057, upload-time = "2024-11-01T14:06:47.324Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a9/c7/ca4bf3e518cb57a686b2feb4f55a1892fd9a3dd13f470fca14e00f80ea36/watchdog-6.0.0-py3-none-manylinux2014_aarch64.whl", hash = "sha256:7607498efa04a3542ae3e05e64da8202e58159aa1fa4acddf7678d34a35d4f13", size = 79079, upload-time = "2024-11-01T14:06:59.472Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5c/51/d46dc9332f9a647593c947b4b88e2381c8dfc0942d15b8edc0310fa4abb1/watchdog-6.0.0-py3-none-manylinux2014_armv7l.whl", hash = "sha256:9041567ee8953024c83343288ccc458fd0a2d811d6a0fd68c4c22609e3490379", size = 79078, upload-time = "2024-11-01T14:07:01.431Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d4/57/04edbf5e169cd318d5f07b4766fee38e825d64b6913ca157ca32d1a42267/watchdog-6.0.0-py3-none-manylinux2014_i686.whl", hash = "sha256:82dc3e3143c7e38ec49d61af98d6558288c415eac98486a5c581726e0737c00e", size = 79076, upload-time = "2024-11-01T14:07:02.568Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ab/cc/da8422b300e13cb187d2203f20b9253e91058aaf7db65b74142013478e66/watchdog-6.0.0-py3-none-manylinux2014_ppc64.whl", hash = "sha256:212ac9b8bf1161dc91bd09c048048a95ca3a4c4f5e5d4a7d1b1a7d5752a7f96f", size = 79077, upload-time = "2024-11-01T14:07:03.893Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/2c/3b/b8964e04ae1a025c44ba8e4291f86e97fac443bca31de8bd98d3263d2fcf/watchdog-6.0.0-py3-none-manylinux2014_ppc64le.whl", hash = "sha256:e3df4cbb9a450c6d49318f6d14f4bbc80d763fa587ba46ec86f99f9e6876bb26", size = 79078, upload-time = "2024-11-01T14:07:05.189Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/62/ae/a696eb424bedff7407801c257d4b1afda455fe40821a2be430e173660e81/watchdog-6.0.0-py3-none-manylinux2014_s390x.whl", hash = "sha256:2cce7cfc2008eb51feb6aab51251fd79b85d9894e98ba847408f662b3395ca3c", size = 79077, upload-time = "2024-11-01T14:07:06.376Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b5/e8/dbf020b4d98251a9860752a094d09a65e1b436ad181faf929983f697048f/watchdog-6.0.0-py3-none-manylinux2014_x86_64.whl", hash = "sha256:20ffe5b202af80ab4266dcd3e91aae72bf2da48c0d33bdb15c66658e685e94e2", size = 79078, upload-time = "2024-11-01T14:07:07.547Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/07/f6/d0e5b343768e8bcb4cda79f0f2f55051bf26177ecd5651f84c07567461cf/watchdog-6.0.0-py3-none-win32.whl", hash = "sha256:07df1fdd701c5d4c8e55ef6cf55b8f0120fe1aef7ef39a1c6fc6bc2e606d517a", size = 79065, upload-time = "2024-11-01T14:07:09.525Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/db/d9/c495884c6e548fce18a8f40568ff120bc3a4b7b99813081c8ac0c936fa64/watchdog-6.0.0-py3-none-win_amd64.whl", hash = "sha256:cbafb470cf848d93b5d013e2ecb245d4aa1c8fd0504e863ccefa32445359d680", size = 79070, upload-time = "2024-11-01T14:07:10.686Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/33/e8/e40370e6d74ddba47f002a32919d91310d6074130fe4e17dabcafc15cbf1/watchdog-6.0.0-py3-none-win_ia64.whl", hash = "sha256:a1914259fa9e1454315171103c6a30961236f508b9b623eae470268bbcc6a22f", size = 79067, upload-time = "2024-11-01T14:07:11.845Z" },
|
||||
]
|
||||
@@ -1,50 +0,0 @@
|
||||
// 404 — Document Not Found
|
||||
.notfound-wrap {
|
||||
min-height: 60dvh;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 3rem 0;
|
||||
}
|
||||
|
||||
.case-notice {
|
||||
max-width: 480px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.case-notice-ref {
|
||||
font-family: var(--font-mono);
|
||||
font-size: 0.75rem;
|
||||
letter-spacing: 0.1em;
|
||||
text-transform: uppercase;
|
||||
color: var(--accent-color);
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
|
||||
.case-notice-title {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.case-notice-body {
|
||||
color: var(--text-muted);
|
||||
max-width: none;
|
||||
}
|
||||
|
||||
.case-notice-links {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
gap: 1.5rem;
|
||||
margin-top: 2rem;
|
||||
padding-top: 1.5rem;
|
||||
border-top: 1px solid var(--border-color);
|
||||
font-family: var(--font-mono);
|
||||
font-size: 0.9rem;
|
||||
|
||||
a {
|
||||
color: var(--text-color);
|
||||
|
||||
&:hover {
|
||||
color: var(--accent-color);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,611 +0,0 @@
|
||||
// Article details and content styling
|
||||
|
||||
.reading-progress-container {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 3px;
|
||||
background-color: transparent;
|
||||
z-index: 1000;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.reading-progress-bar {
|
||||
height: 100%;
|
||||
width: 0%;
|
||||
background-color: var(--accent-color);
|
||||
transition: width 0.1s cubic-bezier(0.25, 0.8, 0.25, 1);
|
||||
}
|
||||
|
||||
// Post Detail
|
||||
.post-detail {
|
||||
max-width: 800px;
|
||||
margin: 0 auto;
|
||||
padding-top: 4rem;
|
||||
}
|
||||
|
||||
.post-header {
|
||||
margin-bottom: 4rem;
|
||||
}
|
||||
|
||||
.post-title {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.post-meta {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
gap: 0.4rem 0.75rem;
|
||||
color: var(--text-muted);
|
||||
font-size: 0.9rem;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.post-meta-item {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.35rem;
|
||||
}
|
||||
|
||||
.post-meta-label {
|
||||
font-style: normal;
|
||||
font-size: 0.75rem;
|
||||
font-family: var(--font-mono);
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.06em;
|
||||
color: var(--accent-color);
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
.post-meta-sep {
|
||||
color: var(--border-color);
|
||||
font-style: normal;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.post-meta-updated time {
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
// Heading anchor links
|
||||
.post-body {
|
||||
h2,
|
||||
h3 {
|
||||
position: relative;
|
||||
|
||||
.heading-anchor {
|
||||
display: inline-block;
|
||||
margin-left: 0.5em;
|
||||
color: var(--accent-color);
|
||||
font-family: var(--font-mono);
|
||||
font-weight: 400;
|
||||
font-size: 0.75em;
|
||||
opacity: 0;
|
||||
text-decoration: none;
|
||||
vertical-align: middle;
|
||||
transition: opacity 0.15s ease;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
&:hover .heading-anchor {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ──────────────────────────────────────────
|
||||
// Series Navigation Box
|
||||
// ──────────────────────────────────────────
|
||||
.series-nav {
|
||||
background: var(--surface-color);
|
||||
border: 1px solid var(--border-color);
|
||||
border-left: 3px solid var(--accent-color);
|
||||
padding: 1.25rem 1.5rem;
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
.series-nav-header {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
flex-wrap: wrap;
|
||||
gap: 0.4rem 0.75rem;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.series-nav-eyebrow {
|
||||
font-family: var(--font-mono);
|
||||
font-size: 0.7rem;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.1em;
|
||||
color: var(--accent-color);
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
.series-nav-title {
|
||||
font-weight: 600;
|
||||
font-size: 0.95rem;
|
||||
color: var(--heading-color, var(--text-color));
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.series-nav-badge {
|
||||
font-family: var(--font-mono);
|
||||
font-size: 0.75rem;
|
||||
color: var(--text-muted);
|
||||
background: var(--bg-color);
|
||||
border: 1px solid var(--border-color);
|
||||
padding: 0.1em 0.6em;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.series-nav-list {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.4rem;
|
||||
}
|
||||
|
||||
.series-nav-item {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
gap: 0.75rem;
|
||||
|
||||
&.is-current {
|
||||
.series-nav-index {
|
||||
color: var(--accent-color);
|
||||
}
|
||||
.series-nav-label {
|
||||
color: var(--text-color);
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.series-nav-index {
|
||||
font-family: var(--font-mono);
|
||||
font-size: 0.7rem;
|
||||
color: var(--text-muted);
|
||||
opacity: 0.6;
|
||||
flex-shrink: 0;
|
||||
width: 1.5ch;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.series-nav-label {
|
||||
font-size: 0.9rem;
|
||||
color: var(--text-muted);
|
||||
text-decoration: none;
|
||||
|
||||
&:hover {
|
||||
color: var(--accent-color);
|
||||
}
|
||||
}
|
||||
|
||||
.post-toc {
|
||||
background: var(--surface-color);
|
||||
border: 1px solid var(--border-color);
|
||||
padding: 1.5rem;
|
||||
margin-bottom: 3rem;
|
||||
|
||||
summary {
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
list-style: none; /* Hide default arrow */
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
|
||||
&::before {
|
||||
content: '↓';
|
||||
color: var(--accent-color);
|
||||
transition: transform 0.2s ease;
|
||||
}
|
||||
}
|
||||
|
||||
&[open] summary::before {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
ul {
|
||||
margin-top: 1rem;
|
||||
margin-bottom: 0;
|
||||
list-style-type: none;
|
||||
padding-left: 1rem;
|
||||
}
|
||||
|
||||
li {
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
a {
|
||||
color: var(--text-muted);
|
||||
font-size: 0.95em;
|
||||
&:hover {
|
||||
color: var(--accent-color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.post-tags-share {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 2rem;
|
||||
margin-top: 4rem;
|
||||
|
||||
@media (min-width: 640px) {
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
|
||||
.post-tags {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.social-share {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
gap: 0.75rem;
|
||||
|
||||
.share-label {
|
||||
font-weight: 500;
|
||||
color: var(--text-color);
|
||||
margin-right: 0.25rem;
|
||||
}
|
||||
|
||||
.share-btn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
border-radius: 50%;
|
||||
background: var(--surface-color);
|
||||
border: 1px solid var(--border-color);
|
||||
color: var(--text-muted);
|
||||
transition: var(--transition-smooth);
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
color: var(--bg-color);
|
||||
transform: translateY(-2px);
|
||||
border-color: transparent;
|
||||
|
||||
&.x {
|
||||
background: #000000;
|
||||
color: #ffffff;
|
||||
}
|
||||
&.bluesky {
|
||||
background: #0285ff;
|
||||
}
|
||||
&.linkedin {
|
||||
background: #0077b5;
|
||||
}
|
||||
&.reddit {
|
||||
background: #ff4500;
|
||||
}
|
||||
&.hackernews {
|
||||
background: #ff6600;
|
||||
}
|
||||
&.email {
|
||||
background: #6b7280;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.post-nav {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 1.5rem;
|
||||
margin-top: 3rem;
|
||||
padding-top: 2rem;
|
||||
border-top: 1px solid var(--border-color);
|
||||
}
|
||||
|
||||
.post-nav-link {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.35rem;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
max-width: 34ch;
|
||||
}
|
||||
|
||||
.post-nav-label {
|
||||
color: var(--accent-color);
|
||||
font-size: 0.9rem;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.post-nav-title {
|
||||
font-size: 1rem;
|
||||
line-height: 1.35;
|
||||
color: var(--text-muted);
|
||||
transition: color 0.2s ease;
|
||||
}
|
||||
|
||||
.post-nav-link:hover .post-nav-title,
|
||||
.post-nav-link:hover .post-nav-label {
|
||||
color: var(--accent-color);
|
||||
}
|
||||
|
||||
@media (max-width: 640px) {
|
||||
.post-nav-title {
|
||||
font-size: 0.95rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 900px) {
|
||||
.post-nav {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
gap: 2rem;
|
||||
align-items: start;
|
||||
}
|
||||
|
||||
.post-nav-prev {
|
||||
justify-self: start;
|
||||
align-items: flex-start;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.post-nav-next {
|
||||
justify-self: end;
|
||||
align-items: flex-end;
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
|
||||
// ──────────────────────────────────────────
|
||||
// Sidebar TOC Layout
|
||||
// ──────────────────────────────────────────
|
||||
|
||||
.post-layout {
|
||||
display: contents;
|
||||
|
||||
@media (min-width: 1200px) {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 800px) 240px;
|
||||
gap: 3rem;
|
||||
align-items: start;
|
||||
max-width: 1100px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 1200px) {
|
||||
.post-detail {
|
||||
max-width: none;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
// Hide inline TOC — sidebar takes over
|
||||
.post-toc {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
.post-toc-sidebar {
|
||||
display: none;
|
||||
|
||||
@media (min-width: 1200px) {
|
||||
display: block;
|
||||
position: sticky;
|
||||
top: 5.5rem;
|
||||
max-height: calc(100vh - 7rem);
|
||||
overflow-y: auto;
|
||||
padding-top: 4rem; // align with article content start
|
||||
scrollbar-width: thin;
|
||||
scrollbar-color: var(--border-color) transparent;
|
||||
|
||||
&::-webkit-scrollbar {
|
||||
width: 4px;
|
||||
}
|
||||
&::-webkit-scrollbar-track {
|
||||
background: transparent;
|
||||
}
|
||||
&::-webkit-scrollbar-thumb {
|
||||
background: var(--border-color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.toc-nav {
|
||||
ul {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
|
||||
// Nested level (h2 children)
|
||||
ul {
|
||||
padding-left: 1rem;
|
||||
margin-top: 0.25rem;
|
||||
}
|
||||
}
|
||||
|
||||
li {
|
||||
margin-bottom: 0.35rem;
|
||||
}
|
||||
|
||||
a {
|
||||
display: block;
|
||||
color: var(--text-muted);
|
||||
font-size: 0.85rem;
|
||||
line-height: 1.4;
|
||||
padding: 0.2rem 0;
|
||||
border-left: 2px solid transparent;
|
||||
padding-left: 0.75rem;
|
||||
transition:
|
||||
color 0.2s ease,
|
||||
border-color 0.2s ease;
|
||||
text-decoration: none;
|
||||
|
||||
&:hover {
|
||||
color: var(--accent-color);
|
||||
}
|
||||
|
||||
&.toc-active {
|
||||
color: var(--accent-color);
|
||||
border-left-color: var(--accent-color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.toc-sidebar-title {
|
||||
font-size: 0.75rem;
|
||||
font-family: var(--font-mono);
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.1em;
|
||||
color: var(--text-muted);
|
||||
margin: 0 0 1rem 0;
|
||||
padding-left: 0.75rem;
|
||||
}
|
||||
|
||||
// ──────────────────────────────────────────
|
||||
// Media Wrappers (YouTube, etc)
|
||||
// ──────────────────────────────────────────
|
||||
.youtube-wrapper {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
aspect-ratio: 16 / 9;
|
||||
overflow: hidden;
|
||||
border: 1px solid var(--border-color);
|
||||
margin: 2rem 0;
|
||||
background: #000;
|
||||
|
||||
iframe {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border: 0;
|
||||
}
|
||||
}
|
||||
|
||||
// ──────────────────────────────────────────
|
||||
// Callouts / Admonitions
|
||||
// ──────────────────────────────────────────
|
||||
.callout {
|
||||
margin: 2rem 0;
|
||||
padding: 1.25rem 1.5rem;
|
||||
border-left: 4px solid var(--callout-color, var(--border-color));
|
||||
background: var(--surface-color);
|
||||
color: var(--text-color);
|
||||
font-size: 0.95rem;
|
||||
line-height: 1.6;
|
||||
|
||||
.callout-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
margin-bottom: 0.5rem;
|
||||
font-weight: 600;
|
||||
color: var(--callout-color, var(--heading-color));
|
||||
}
|
||||
|
||||
.callout-icon {
|
||||
width: 1.25rem;
|
||||
height: 1.25rem;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.callout-title {
|
||||
font-family: var(--font-mono);
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.05em;
|
||||
font-size: 0.85rem;
|
||||
}
|
||||
|
||||
.callout-content {
|
||||
> :first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
> :last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Variants
|
||||
&.callout-note {
|
||||
--callout-color: #3b82f6; // Blue
|
||||
background: rgba(59, 130, 246, 0.05);
|
||||
}
|
||||
|
||||
&.callout-warning {
|
||||
--callout-color: #f59e0b; // Amber
|
||||
background: rgba(245, 158, 11, 0.05);
|
||||
}
|
||||
|
||||
&.callout-tip {
|
||||
--callout-color: #16a34a; // Green
|
||||
background: rgba(22, 163, 74, 0.05);
|
||||
}
|
||||
|
||||
&.callout-danger {
|
||||
--callout-color: #ef4444; // Red
|
||||
background: rgba(239, 68, 68, 0.05);
|
||||
}
|
||||
}
|
||||
|
||||
.comments {
|
||||
margin-top: 4rem;
|
||||
}
|
||||
|
||||
// ──────────────────────────────────────────
|
||||
// Related Posts
|
||||
// ──────────────────────────────────────────
|
||||
.related-posts-section {
|
||||
margin-top: 4rem;
|
||||
padding-top: 2rem;
|
||||
border-top: 1px solid var(--border-color);
|
||||
|
||||
h3 {
|
||||
margin-bottom: 2rem;
|
||||
font-size: 1.5rem;
|
||||
color: var(--heading-color);
|
||||
letter-spacing: -0.02em;
|
||||
}
|
||||
|
||||
.related-posts-grid {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr;
|
||||
gap: 2rem;
|
||||
|
||||
@media (min-width: 768px) {
|
||||
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
|
||||
gap: 2.5rem;
|
||||
}
|
||||
|
||||
// Override some constraints from feed-page cards when inside the grid
|
||||
.feed-item {
|
||||
border-bottom: none !important;
|
||||
padding-bottom: 0 !important;
|
||||
background: var(--surface-color);
|
||||
border: 1px solid var(--border-color);
|
||||
padding: 1.5rem !important;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
transition: var(--transition-smooth);
|
||||
|
||||
&:hover {
|
||||
border-color: var(--accent-color);
|
||||
}
|
||||
|
||||
.item-snippet {
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,304 +0,0 @@
|
||||
// Post Feed Page Container
|
||||
.feed-page {
|
||||
max-width: 800px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
// Post Feed
|
||||
.post-feed {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin-top: 1rem;
|
||||
}
|
||||
|
||||
.post-feed .feed-item {
|
||||
padding: 2rem 0;
|
||||
border-bottom: 1px solid var(--border-color);
|
||||
|
||||
&:first-child {
|
||||
padding-top: 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Homepage "View all posts" CTA
|
||||
.view-all-posts {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin-top: 3rem;
|
||||
}
|
||||
|
||||
.btn-view-all {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
padding: 0.6rem 1.5rem;
|
||||
border: 1px solid var(--accent-color);
|
||||
border-radius: 2px;
|
||||
font-family: var(--font-mono);
|
||||
font-size: 0.875rem;
|
||||
color: var(--accent-color);
|
||||
background: transparent;
|
||||
text-decoration: none;
|
||||
transition: var(--transition-smooth);
|
||||
letter-spacing: 0.04em;
|
||||
|
||||
&::after {
|
||||
content: '→';
|
||||
transition: transform 0.2s ease;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background: var(--accent-color);
|
||||
color: var(--bg-color);
|
||||
|
||||
&::after {
|
||||
transform: translateX(4px);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.feed-item {
|
||||
display: block;
|
||||
}
|
||||
|
||||
// Homepage post list (post-card.html) — a numbered index of entries
|
||||
.feed-heading {
|
||||
font-size: 1.1rem;
|
||||
margin: 0 0 1.5rem;
|
||||
}
|
||||
|
||||
.post-feed-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.feed-item.card {
|
||||
display: flex;
|
||||
gap: 1.25rem;
|
||||
border-bottom: 1px solid var(--border-color);
|
||||
padding: 2rem 0;
|
||||
|
||||
&:first-child {
|
||||
padding-top: 0;
|
||||
}
|
||||
|
||||
.item-title {
|
||||
font-size: 1.25rem;
|
||||
margin-bottom: 0.5rem;
|
||||
font-weight: 600;
|
||||
|
||||
a {
|
||||
transition: color 0.2s ease;
|
||||
}
|
||||
}
|
||||
|
||||
&:hover .item-title a {
|
||||
color: var(--accent-color);
|
||||
}
|
||||
}
|
||||
|
||||
.item-index {
|
||||
font-family: var(--font-mono);
|
||||
font-size: 0.85rem;
|
||||
color: var(--text-muted);
|
||||
padding-top: 0.3rem;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.item-body {
|
||||
min-width: 0;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.item-meta {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.35rem;
|
||||
font-size: 0.85rem;
|
||||
color: var(--text-muted);
|
||||
margin-bottom: 1rem;
|
||||
font-family: var(--font-mono);
|
||||
}
|
||||
|
||||
.item-meta-sep {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.item-snippet {
|
||||
color: var(--text-color);
|
||||
opacity: 0.9;
|
||||
margin-bottom: 1rem;
|
||||
|
||||
p {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.item-footer {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
gap: 0.75rem;
|
||||
font-size: 0.85rem;
|
||||
}
|
||||
|
||||
.item-readmore {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.35rem;
|
||||
color: var(--accent-color);
|
||||
|
||||
.readmore-arrow {
|
||||
transition: transform 0.2s ease;
|
||||
}
|
||||
|
||||
&:hover .readmore-arrow {
|
||||
transform: translateX(4px);
|
||||
}
|
||||
}
|
||||
|
||||
.item-tags {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 0.4rem;
|
||||
}
|
||||
|
||||
.item-link {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.item-date-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
margin-bottom: 0.25rem;
|
||||
}
|
||||
|
||||
.item-date {
|
||||
font-family: var(--font-mono);
|
||||
font-size: 0.85rem;
|
||||
color: var(--text-muted);
|
||||
font-variant-numeric: tabular-nums;
|
||||
letter-spacing: 0.05em;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.item-reading-time {
|
||||
color: var(--text-muted);
|
||||
font-size: 0.85rem;
|
||||
font-family: var(--font-mono);
|
||||
}
|
||||
|
||||
.item-title {
|
||||
margin: 0;
|
||||
font-size: clamp(1.5rem, 2vw, 2rem);
|
||||
transition: color 0.2s ease;
|
||||
}
|
||||
|
||||
.item-link:hover .item-title {
|
||||
color: var(--accent-color);
|
||||
}
|
||||
|
||||
.item-desc {
|
||||
margin: 0;
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
// ──────────────────────────────────────────
|
||||
// Pagination
|
||||
// ──────────────────────────────────────────
|
||||
.pagination {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 0.5rem;
|
||||
margin-top: 5rem;
|
||||
padding-top: 2rem;
|
||||
border-top: 1px solid var(--border-color);
|
||||
font-family: var(--font-mono);
|
||||
}
|
||||
|
||||
.pagination-pages {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.25rem;
|
||||
}
|
||||
|
||||
// Shared base for arrows + numbers
|
||||
.pagination-arrow,
|
||||
.pagination-num {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-width: 2.25rem;
|
||||
height: 2.25rem;
|
||||
padding: 0 0.5rem;
|
||||
border-radius: 2px;
|
||||
border: 1px solid var(--border-color);
|
||||
background: var(--surface-color);
|
||||
color: var(--text-muted);
|
||||
font-size: 0.875rem;
|
||||
text-decoration: none;
|
||||
transition: var(--transition-smooth);
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
|
||||
&:hover {
|
||||
border-color: var(--accent-color);
|
||||
color: var(--accent-color);
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
}
|
||||
|
||||
// Active / current page
|
||||
.pagination-num.is-current {
|
||||
background: var(--accent-color);
|
||||
border-color: var(--accent-color);
|
||||
color: #fff;
|
||||
font-weight: 600;
|
||||
cursor: default;
|
||||
pointer-events: none;
|
||||
|
||||
&:hover {
|
||||
transform: none;
|
||||
}
|
||||
}
|
||||
|
||||
// Disabled arrow (no prev/next page)
|
||||
.pagination-arrow.is-disabled {
|
||||
opacity: 0.3;
|
||||
cursor: not-allowed;
|
||||
pointer-events: none;
|
||||
|
||||
&:hover {
|
||||
border-color: var(--border-color);
|
||||
color: var(--text-muted);
|
||||
transform: none;
|
||||
}
|
||||
}
|
||||
|
||||
// Ellipsis gap marker
|
||||
.pagination-ellipsis {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-width: 2.25rem;
|
||||
height: 2.25rem;
|
||||
color: var(--text-muted);
|
||||
font-size: 0.875rem;
|
||||
letter-spacing: 0.05em;
|
||||
}
|
||||
|
||||
// "Page N of M" helper text
|
||||
.pagination-meta {
|
||||
text-align: center;
|
||||
margin-top: 1rem;
|
||||
margin-bottom: 0;
|
||||
font-size: 0.8rem;
|
||||
color: var(--text-muted);
|
||||
font-family: var(--font-mono);
|
||||
letter-spacing: 0.05em;
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
// Footer
|
||||
.site-footer {
|
||||
padding: 2rem 0 3rem;
|
||||
border-top: 3px solid var(--text-color);
|
||||
color: var(--text-muted);
|
||||
font-size: 0.85rem;
|
||||
font-family: var(--font-mono);
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
@@ -1,183 +0,0 @@
|
||||
// Component: Header
|
||||
.site-header {
|
||||
padding: 1.25rem 0;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 50;
|
||||
background-color: var(--bg-color);
|
||||
border-bottom: 2px solid var(--text-color);
|
||||
}
|
||||
|
||||
.nav-container {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
// Right side wrapper (links + controls)
|
||||
.nav-right {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
// Always-visible icon controls
|
||||
.nav-controls {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.search-toggle {
|
||||
background: none;
|
||||
border: none;
|
||||
color: var(--text-color);
|
||||
cursor: pointer;
|
||||
padding: 0.35rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 50%;
|
||||
transition: var(--transition-smooth);
|
||||
&:hover {
|
||||
color: var(--accent-color);
|
||||
}
|
||||
}
|
||||
|
||||
// Hamburger button — hidden on desktop, shown on mobile
|
||||
.nav-toggle {
|
||||
display: none;
|
||||
background: none;
|
||||
border: none;
|
||||
color: var(--text-color);
|
||||
cursor: pointer;
|
||||
padding: 0.25rem;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
.close-icon {
|
||||
display: none;
|
||||
}
|
||||
|
||||
&[aria-expanded='true'] {
|
||||
.hamburger-icon {
|
||||
display: none;
|
||||
}
|
||||
.close-icon {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 640px) {
|
||||
.nav-toggle {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
// Hide the site name when the menu is open
|
||||
.nav-container:has(#nav-toggle[aria-expanded='true']) .brand-link {
|
||||
display: none;
|
||||
}
|
||||
|
||||
// Make nav-right fill the full width so menu items span the container
|
||||
.nav-container:has(#nav-toggle[aria-expanded='true']) .nav-right {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.nav-right {
|
||||
flex-wrap: wrap;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.nav-links {
|
||||
display: flex !important;
|
||||
flex-direction: column !important;
|
||||
align-items: flex-start !important;
|
||||
gap: 0 !important;
|
||||
width: 100%;
|
||||
order: 10; // push below nav-controls
|
||||
padding: 0;
|
||||
margin-top: 0;
|
||||
border-top: 1px solid transparent;
|
||||
max-height: 0;
|
||||
opacity: 0;
|
||||
overflow: hidden;
|
||||
transition:
|
||||
max-height 0.3s cubic-bezier(0.16, 1, 0.3, 1),
|
||||
opacity 0.2s ease;
|
||||
|
||||
&.is-open {
|
||||
padding: 1rem 0;
|
||||
margin-top: 0.5rem;
|
||||
border-top-color: var(--border-color);
|
||||
max-height: 320px;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.nav-item {
|
||||
width: 100%;
|
||||
padding: 0.75rem 0;
|
||||
font-size: 1rem;
|
||||
border-bottom: 1px solid var(--border-color);
|
||||
&::after {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Brand reads like a running header on a printed document — quiet,
|
||||
// small, letter-spaced — not competing with the masthead title below it.
|
||||
.brand-text {
|
||||
font-family: var(--font-mono);
|
||||
font-weight: 600;
|
||||
font-size: 0.8rem;
|
||||
letter-spacing: 0.08em;
|
||||
text-transform: uppercase;
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
.brand-link:hover .brand-text {
|
||||
color: var(--accent-color);
|
||||
}
|
||||
|
||||
.nav-links {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 1.75rem;
|
||||
}
|
||||
|
||||
.nav-item {
|
||||
font-family: var(--font-mono);
|
||||
font-weight: 500;
|
||||
font-size: 0.8rem;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.06em;
|
||||
color: var(--text-color);
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.nav-item::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 2px;
|
||||
bottom: -4px;
|
||||
left: 0;
|
||||
background-color: var(--accent-color);
|
||||
transform: scaleX(0);
|
||||
transform-origin: left;
|
||||
transition: transform 0.3s cubic-bezier(0.16, 1, 0.3, 1);
|
||||
}
|
||||
|
||||
.nav-item:hover::after {
|
||||
transform: scaleX(1);
|
||||
}
|
||||
|
||||
.nav-item.is-active {
|
||||
color: var(--accent-color);
|
||||
|
||||
&::after {
|
||||
transform: scaleX(1);
|
||||
}
|
||||
}
|
||||
@@ -1,70 +0,0 @@
|
||||
// Hero Section
|
||||
.hero {
|
||||
padding: 8rem 0 6rem 0;
|
||||
max-width: 800px;
|
||||
}
|
||||
|
||||
.hero-compact {
|
||||
padding-bottom: 2rem;
|
||||
}
|
||||
|
||||
.hero-title {
|
||||
color: var(--text-color);
|
||||
}
|
||||
|
||||
.hero-subtitle {
|
||||
font-size: clamp(1.1rem, 1.5vw, 1.3rem);
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
// Homepage masthead — spans the full width of .site-container, matching the navbar
|
||||
.masthead {
|
||||
padding: 4rem 0 3rem;
|
||||
}
|
||||
|
||||
.masthead-kicker {
|
||||
font-family: var(--font-mono);
|
||||
font-size: 0.8rem;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.08em;
|
||||
color: var(--accent-color);
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.masthead-title {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
// Colophon-style contact line — quiet, small, middot-separated
|
||||
.masthead-links {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
row-gap: 0.4rem;
|
||||
margin-top: 2rem;
|
||||
font-family: var(--font-mono);
|
||||
font-size: 0.8rem;
|
||||
letter-spacing: 0.02em;
|
||||
|
||||
a {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.4rem;
|
||||
color: var(--text-muted);
|
||||
transition: var(--transition-smooth);
|
||||
|
||||
svg {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
color: var(--accent-color);
|
||||
}
|
||||
|
||||
&:not(:last-child)::after {
|
||||
content: '·';
|
||||
margin: 0 0.75rem;
|
||||
color: var(--text-muted);
|
||||
opacity: 0.5;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
// Layout Constraints
|
||||
.site-container {
|
||||
width: 100%;
|
||||
max-width: 1400px;
|
||||
margin: 0 auto;
|
||||
padding: 0 5vw;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-height: 100dvh;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
// Constrain all media & tables to their container
|
||||
img,
|
||||
video,
|
||||
iframe,
|
||||
table,
|
||||
svg {
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
table {
|
||||
display: block;
|
||||
overflow-x: auto;
|
||||
@media (max-width: 640px) {
|
||||
scrollbar-width: none;
|
||||
&::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Main Content
|
||||
.main-content {
|
||||
flex-grow: 1;
|
||||
padding-bottom: 5rem;
|
||||
}
|
||||
@@ -1,107 +0,0 @@
|
||||
// Archive & Tags list pages
|
||||
|
||||
.list-page-header {
|
||||
margin-bottom: 3rem;
|
||||
}
|
||||
|
||||
.list-page-title {
|
||||
font-size: clamp(2.5rem, 5vw, 4.5rem);
|
||||
}
|
||||
|
||||
.term-hash {
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
.tag-description {
|
||||
max-width: 65ch;
|
||||
margin: 0.75rem 0 0;
|
||||
color: var(--text-muted);
|
||||
font-size: 1.05rem;
|
||||
}
|
||||
|
||||
.archive-list {
|
||||
max-width: 65ch;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.archive-year {
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
.archive-year-title {
|
||||
font-size: 1.5rem;
|
||||
margin-top: 2rem;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.archive-items {
|
||||
list-style: none;
|
||||
padding-left: 0;
|
||||
margin: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.75rem;
|
||||
}
|
||||
|
||||
.archive-item {
|
||||
display: flex;
|
||||
gap: 1rem;
|
||||
align-items: baseline;
|
||||
}
|
||||
|
||||
.archive-date {
|
||||
font-family: var(--font-mono);
|
||||
color: var(--text-muted);
|
||||
font-size: 0.95rem;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.archive-link {
|
||||
color: var(--accent-color);
|
||||
font-weight: 500;
|
||||
font-size: 1.05rem;
|
||||
}
|
||||
|
||||
// Tags index
|
||||
.tags-page {
|
||||
max-width: 65ch;
|
||||
margin: 0 auto;
|
||||
padding-top: 4rem;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.tags-page-header {
|
||||
margin-bottom: 3rem;
|
||||
}
|
||||
|
||||
.page-title {
|
||||
font-size: 2rem;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.tags-container {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 2rem;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.tag-link {
|
||||
font-size: 1.1rem;
|
||||
color: var(--text-color);
|
||||
font-weight: 400;
|
||||
display: inline-flex;
|
||||
align-items: flex-start;
|
||||
|
||||
&:hover {
|
||||
color: var(--accent-color);
|
||||
}
|
||||
}
|
||||
|
||||
.tag-count {
|
||||
font-size: 0.7em;
|
||||
color: var(--text-muted);
|
||||
margin-left: 0.15rem;
|
||||
margin-top: 0.1rem;
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
// Global Reset & Base
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
html {
|
||||
font-family: var(--font-sans);
|
||||
font-size: clamp(1rem, 0.9rem + 0.5vw, 1.125rem);
|
||||
background-color: var(--bg-color);
|
||||
color: var(--text-color);
|
||||
scroll-behavior: smooth;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
transition:
|
||||
background-color 0.3s ease,
|
||||
color 0.3s ease;
|
||||
|
||||
// Firefox
|
||||
scrollbar-width: thin;
|
||||
scrollbar-color: var(--scrollbar-thumb) var(--scrollbar-track);
|
||||
}
|
||||
|
||||
// Webkit
|
||||
::-webkit-scrollbar {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-track {
|
||||
background: var(--scrollbar-track);
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
background: var(--scrollbar-thumb);
|
||||
border-radius: 0; // hard edges = terminal feel
|
||||
border: 1px solid var(--scrollbar-track);
|
||||
|
||||
&:hover {
|
||||
background: var(--scrollbar-thumb-hover);
|
||||
}
|
||||
}
|
||||
|
||||
body {
|
||||
line-height: 1.7;
|
||||
min-height: 100dvh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow-wrap: break-word; // break long words instead of overflowing
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
a {
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
transition: var(--transition-smooth);
|
||||
}
|
||||
@@ -1,64 +0,0 @@
|
||||
// Scroll to Top Floating Button
|
||||
.scroll-to-top {
|
||||
position: fixed;
|
||||
bottom: 2rem;
|
||||
right: 2rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 3rem;
|
||||
height: 3rem;
|
||||
border-radius: 2px;
|
||||
background: var(--bg-color);
|
||||
color: var(--accent-color);
|
||||
border: 1px solid var(--accent-color);
|
||||
cursor: pointer;
|
||||
z-index: 100;
|
||||
|
||||
// Hidden state by default
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
transform: translateY(1rem);
|
||||
transition:
|
||||
transform 0.3s cubic-bezier(0.25, 0.8, 0.25, 1),
|
||||
opacity 0.3s cubic-bezier(0.25, 0.8, 0.25, 1),
|
||||
visibility 0.3s cubic-bezier(0.25, 0.8, 0.25, 1),
|
||||
box-shadow 0.2s ease-out;
|
||||
|
||||
// Visible state triggered by JS
|
||||
&.visible {
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
@media (hover: hover) {
|
||||
&:hover {
|
||||
background: var(--accent-color);
|
||||
color: var(--bg-color);
|
||||
transform: translateY(-0.25rem);
|
||||
box-shadow: 0 4px 12px color-mix(in srgb, var(--accent-color) 20%, transparent);
|
||||
}
|
||||
|
||||
&:hover svg {
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
}
|
||||
|
||||
&:focus-visible {
|
||||
outline: 2px solid var(--accent-color);
|
||||
outline-offset: 4px;
|
||||
}
|
||||
|
||||
svg {
|
||||
transition: transform 0.2s ease;
|
||||
}
|
||||
|
||||
// Responsive padding for mobile devices
|
||||
@media (max-width: 768px) {
|
||||
bottom: 1.5rem;
|
||||
right: 1.5rem;
|
||||
width: 2.75rem;
|
||||
height: 2.75rem;
|
||||
}
|
||||
}
|
||||
@@ -1,149 +0,0 @@
|
||||
// Search Modal Styles
|
||||
.search-overlay {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
z-index: 10000;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: flex-start;
|
||||
padding-top: 10vh;
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
transition:
|
||||
opacity 0.2s ease,
|
||||
visibility 0.2s ease;
|
||||
|
||||
&.active {
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
|
||||
.search-modal {
|
||||
transform: translateY(0) scale(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.search-modal {
|
||||
width: 90%;
|
||||
max-width: 600px;
|
||||
background: var(--bg-color);
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: 2px;
|
||||
box-shadow: 0 12px 32px var(--shadow-color);
|
||||
transform: translateY(-20px) scale(0.98);
|
||||
transition: transform 0.2s cubic-bezier(0.175, 0.885, 0.32, 1.275);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.search-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 1rem 1.25rem;
|
||||
border-bottom: 1px solid var(--border-color);
|
||||
background: var(--surface-color);
|
||||
|
||||
svg {
|
||||
color: var(--text-muted);
|
||||
margin-right: 0.75rem;
|
||||
}
|
||||
}
|
||||
|
||||
#search-input {
|
||||
flex: 1;
|
||||
background: transparent;
|
||||
border: none;
|
||||
color: var(--text-color);
|
||||
font-family: var(--font-mono);
|
||||
font-size: 1rem;
|
||||
outline: none;
|
||||
|
||||
&::placeholder {
|
||||
color: var(--text-muted);
|
||||
}
|
||||
}
|
||||
|
||||
.search-footer {
|
||||
padding: 0.5rem 1.25rem;
|
||||
background: var(--surface-color);
|
||||
border-top: 1px solid var(--border-color);
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
font-size: 0.75rem;
|
||||
color: var(--text-muted);
|
||||
|
||||
kbd {
|
||||
background: var(--bg-color);
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: 4px;
|
||||
padding: 0.1rem 0.3rem;
|
||||
font-family: var(--font-mono);
|
||||
font-size: 0.7rem;
|
||||
margin: 0 0.2rem;
|
||||
}
|
||||
}
|
||||
|
||||
.search-results {
|
||||
max-height: 50vh;
|
||||
overflow-y: auto;
|
||||
padding: 0.5rem;
|
||||
|
||||
// Custom scrollbar
|
||||
&::-webkit-scrollbar {
|
||||
width: 8px;
|
||||
}
|
||||
&::-webkit-scrollbar-track {
|
||||
background: transparent;
|
||||
}
|
||||
&::-webkit-scrollbar-thumb {
|
||||
background-color: var(--border-color);
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.search-result-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 0.75rem 1rem;
|
||||
border-radius: 2px;
|
||||
text-decoration: none;
|
||||
color: var(--text-color);
|
||||
transition: background-color 0.15s ease;
|
||||
border-left: 2px solid transparent;
|
||||
|
||||
&:hover,
|
||||
&.selected {
|
||||
background-color: var(--surface-color);
|
||||
border-left-color: var(--accent-color);
|
||||
}
|
||||
|
||||
.result-title {
|
||||
font-weight: 500;
|
||||
color: var(--accent-color);
|
||||
margin-bottom: 0.25rem;
|
||||
}
|
||||
|
||||
.result-summary {
|
||||
font-size: 0.85rem;
|
||||
color: var(--text-muted);
|
||||
line-height: 1.4;
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 2;
|
||||
line-clamp: 2;
|
||||
-webkit-box-orient: vertical;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
.no-results {
|
||||
padding: 2rem;
|
||||
text-align: center;
|
||||
color: var(--text-muted);
|
||||
font-style: italic;
|
||||
}
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
// Component: Theme Toggle
|
||||
.theme-toggle {
|
||||
background: none;
|
||||
border: none;
|
||||
color: var(--text-color);
|
||||
cursor: pointer;
|
||||
padding: 0.5rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 50%;
|
||||
transition: var(--transition-smooth);
|
||||
|
||||
svg {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
html.dark .sun-icon {
|
||||
display: block;
|
||||
}
|
||||
html.dark .moon-icon {
|
||||
display: none;
|
||||
}
|
||||
html:not(.dark) .sun-icon {
|
||||
display: none;
|
||||
}
|
||||
html:not(.dark) .moon-icon {
|
||||
display: block;
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
/*
|
||||
* Cross-Document View Transitions
|
||||
* Enabled via <meta name="view-transition" content="same-origin" />
|
||||
*/
|
||||
|
||||
// Disable default CSS transitions on the whole page during a view transition
|
||||
// so they don't fight with the View Transition API animation.
|
||||
html::view-transition-group(*) {
|
||||
animation-duration: 0.3s;
|
||||
animation-timing-function: cubic-bezier(0.22, 1, 0.36, 1);
|
||||
}
|
||||
|
||||
// Custom animation for the old page leaving
|
||||
@keyframes fade-out-scale {
|
||||
from {
|
||||
opacity: 1;
|
||||
transform: scale(1);
|
||||
}
|
||||
to {
|
||||
opacity: 0;
|
||||
transform: scale(0.98);
|
||||
}
|
||||
}
|
||||
|
||||
// Custom animation for the new page entering
|
||||
@keyframes fade-in-scale {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: scale(1.02);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
// Apply the custom animations to the root view transition pseudo-elements
|
||||
html::view-transition-old(root) {
|
||||
animation: fade-out-scale 0.25s cubic-bezier(0.4, 0, 1, 1) both;
|
||||
}
|
||||
|
||||
html::view-transition-new(root) {
|
||||
animation: fade-in-scale 0.35s cubic-bezier(0, 0, 0.2, 1) both;
|
||||
// Delay slightly so the old page fades down first before the new one pops over
|
||||
animation-delay: 0.05s;
|
||||
}
|
||||
|
||||
// Respect user preference for reduced motion
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
html::view-transition-group(*),
|
||||
html::view-transition-old(*),
|
||||
html::view-transition-new(*) {
|
||||
animation: none !important;
|
||||
}
|
||||
}
|
||||
@@ -1,195 +0,0 @@
|
||||
// Typography Scale (Fluid)
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6 {
|
||||
font-family: var(--font-display);
|
||||
font-weight: 700;
|
||||
line-height: 1.15;
|
||||
letter-spacing: -0.01em;
|
||||
margin-top: 2em;
|
||||
margin-bottom: 0.75em;
|
||||
overflow-wrap: break-word;
|
||||
word-break: break-word;
|
||||
text-wrap: balance;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: clamp(1.75rem, 5vw, 4.5rem);
|
||||
margin-top: 0;
|
||||
}
|
||||
h2 {
|
||||
font-size: clamp(1.35rem, 3vw, 2.5rem);
|
||||
}
|
||||
h3 {
|
||||
font-size: clamp(1.2rem, 2vw, 1.8rem);
|
||||
}
|
||||
h4 {
|
||||
font-size: clamp(1.05rem, 1.5vw, 1.3rem);
|
||||
}
|
||||
h5 {
|
||||
font-size: clamp(1rem, 1.25vw, 1.15rem);
|
||||
}
|
||||
h6 {
|
||||
font-size: clamp(0.9rem, 1vw, 1rem);
|
||||
}
|
||||
|
||||
p,
|
||||
ul,
|
||||
ol,
|
||||
figure,
|
||||
blockquote,
|
||||
pre,
|
||||
table {
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
|
||||
hr {
|
||||
border: none;
|
||||
border-top: 1px solid var(--border-color);
|
||||
margin: 2rem 0;
|
||||
}
|
||||
|
||||
p {
|
||||
max-width: 65ch; // Optimal reading width
|
||||
text-wrap: pretty;
|
||||
}
|
||||
|
||||
// Footnotes
|
||||
.footnote-reference {
|
||||
font-size: 0.75em;
|
||||
vertical-align: super;
|
||||
line-height: 0;
|
||||
|
||||
a {
|
||||
color: var(--accent-color);
|
||||
font-family: var(--font-mono);
|
||||
padding: 0 0.15em;
|
||||
|
||||
&:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.footnote-definition {
|
||||
display: flex;
|
||||
gap: 0.75rem;
|
||||
margin-bottom: 0.75rem;
|
||||
font-size: 0.875rem;
|
||||
color: var(--text-muted);
|
||||
border-left: 2px solid var(--border-color);
|
||||
padding-left: 1rem;
|
||||
|
||||
p {
|
||||
margin: 0;
|
||||
max-width: none;
|
||||
}
|
||||
}
|
||||
|
||||
.footnote-definition-label {
|
||||
flex-shrink: 0;
|
||||
font-family: var(--font-mono);
|
||||
color: var(--accent-color);
|
||||
font-size: 0.8em;
|
||||
margin-top: 0.1em;
|
||||
}
|
||||
|
||||
.footnote-backref {
|
||||
font-family: var(--font-mono);
|
||||
color: var(--accent-color);
|
||||
font-size: 0.9em;
|
||||
text-decoration: none;
|
||||
opacity: 0.7;
|
||||
transition: opacity 0.2s ease;
|
||||
|
||||
&:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
code,
|
||||
pre {
|
||||
font-family: var(--font-mono);
|
||||
font-size: 0.9em;
|
||||
font-feature-settings:
|
||||
'liga' 1,
|
||||
'calt' 1;
|
||||
font-variant-ligatures: contextual;
|
||||
}
|
||||
|
||||
.code-block-wrapper {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
pre {
|
||||
padding: 1.25rem;
|
||||
border-radius: 2px;
|
||||
overflow-x: auto;
|
||||
max-width: 100%;
|
||||
border: 1px solid var(--border-color);
|
||||
background: #282828; // Gruvbox Dark bg0 (matches [markdown.highlighting] theme)
|
||||
// Scrollbars visible on desktop, hidden on mobile
|
||||
@media (max-width: 640px) {
|
||||
scrollbar-width: none;
|
||||
&::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
font-size: 0.82em;
|
||||
}
|
||||
}
|
||||
|
||||
.copy-code-btn {
|
||||
position: absolute;
|
||||
top: 0.5rem;
|
||||
right: 0.5rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
background: rgba(235, 219, 178, 0.1);
|
||||
color: #ebdbb2;
|
||||
border: 1px solid rgba(235, 219, 178, 0.2);
|
||||
border-radius: 2px;
|
||||
cursor: pointer;
|
||||
opacity: 1;
|
||||
transition:
|
||||
background 0.2s ease,
|
||||
color 0.2s ease;
|
||||
|
||||
svg {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background: rgba(235, 219, 178, 0.2);
|
||||
color: #fbf1c7;
|
||||
}
|
||||
|
||||
&.copied {
|
||||
background: var(--accent-color);
|
||||
border-color: var(--accent-color);
|
||||
color: var(--bg-color);
|
||||
}
|
||||
}
|
||||
|
||||
// Button is always visible, no hover-to-reveal needed
|
||||
|
||||
code {
|
||||
background: var(--surface-color);
|
||||
padding: 0.2em 0.4em;
|
||||
border-radius: 2px;
|
||||
color: var(--accent-color);
|
||||
border: 1px solid var(--border-color);
|
||||
}
|
||||
|
||||
pre code {
|
||||
background: transparent;
|
||||
color: inherit;
|
||||
padding: 0;
|
||||
border: none;
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
// Tag chip — a small filed label, shared by post-card and post-tags
|
||||
.tag {
|
||||
display: inline-block;
|
||||
background: var(--surface-color);
|
||||
border: 1px solid var(--border-color);
|
||||
padding: 0.2rem 0.6rem;
|
||||
border-radius: 2px;
|
||||
font-size: 0.8rem;
|
||||
font-family: var(--font-mono);
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.03em;
|
||||
color: var(--text-muted);
|
||||
transition: var(--transition-smooth);
|
||||
|
||||
&:hover {
|
||||
color: var(--accent-color);
|
||||
border-color: var(--accent-color);
|
||||
}
|
||||
}
|
||||
|
||||
// Heavy hairline rule — the site's one recurring structural device
|
||||
// (masthead, between list entries, above case-reference blocks)
|
||||
.rule {
|
||||
border: none;
|
||||
border-top: 3px solid var(--text-color);
|
||||
}
|
||||
|
||||
// Utilities / Interactions
|
||||
.hover-scale {
|
||||
transition: transform 140ms ease-out;
|
||||
|
||||
&:hover {
|
||||
transform: scale(1.02);
|
||||
}
|
||||
|
||||
&:active {
|
||||
transform: scale(0.98);
|
||||
}
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
// Design Variables — "Case File": a declassified incident-report aesthetic.
|
||||
// One accent only; flat colors + hairline borders, no gradients or glass blur.
|
||||
:root {
|
||||
--bg-color: #e9e9e2; // paper (cool bone, not warm cream)
|
||||
--surface-color: #dedecf; // slightly recessed paper — cards, code blocks
|
||||
--text-color: #17181c; // ink
|
||||
--text-muted: #68675f; // faded ink
|
||||
--accent-color: #b42318; // classified-stamp red
|
||||
--accent-hover: #8e1b12;
|
||||
--border-color: rgba(23, 24, 28, 0.16);
|
||||
--shadow-color: rgba(23, 24, 28, 0.08);
|
||||
|
||||
--font-sans: 'Source Serif 4', Georgia, serif; // body copy
|
||||
--font-display: 'IBM Plex Serif', Georgia, serif; // headings, masthead
|
||||
--font-mono: 'JetBrains Mono', monospace; // case-reference lines, tags, code
|
||||
|
||||
--transition-smooth:
|
||||
transform 0.2s cubic-bezier(0.16, 1, 0.3, 1),
|
||||
color 0.2s cubic-bezier(0.16, 1, 0.3, 1),
|
||||
background-color 0.2s cubic-bezier(0.16, 1, 0.3, 1),
|
||||
border-color 0.2s cubic-bezier(0.16, 1, 0.3, 1);
|
||||
|
||||
--scrollbar-track: #dedecf;
|
||||
--scrollbar-thumb: #b0afa2;
|
||||
--scrollbar-thumb-hover: #b42318;
|
||||
}
|
||||
|
||||
// Dark mode — same document, read at night
|
||||
html.dark {
|
||||
--bg-color: #131311;
|
||||
--surface-color: #1b1a17;
|
||||
--text-color: #e9e7de;
|
||||
--text-muted: #8b8a80;
|
||||
--accent-color: #ff5a46;
|
||||
--accent-hover: #ff7c6b;
|
||||
--border-color: rgba(233, 231, 222, 0.14);
|
||||
--shadow-color: rgba(0, 0, 0, 0.5);
|
||||
|
||||
--scrollbar-track: #1b1a17;
|
||||
--scrollbar-thumb: #3a382f;
|
||||
--scrollbar-thumb-hover: #ff5a46;
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
// Main SCSS entry point
|
||||
// Organized by feature and section for maintainability
|
||||
|
||||
@import 'variables';
|
||||
@import 'reset';
|
||||
@import 'typography';
|
||||
@import 'layout';
|
||||
@import 'header';
|
||||
@import 'theme';
|
||||
@import 'hero';
|
||||
@import 'feed';
|
||||
@import 'lists';
|
||||
@import 'article';
|
||||
@import 'footer';
|
||||
@import 'search';
|
||||
@import 'transitions';
|
||||
@import 'utilities';
|
||||
@import 'scroll-top';
|
||||
@import '404';
|
||||
@@ -1,13 +0,0 @@
|
||||
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
|
||||
mDMEalcjtBYJKwYBBAHaRw8BAQdA55X1mRCKw9DA35kCAy+7Z30ye0rUHWBZsl7O
|
||||
Wmar+RS0IklhbiBBbmR3YXRpIDxhbmR3YXRpaWFuQGdtYWlsLmNvbT6IkwQTFgoA
|
||||
OxYhBK1YqreiDYUjy/WaeR8g/tCqBbDaBQJqVyO0AhsDBQsJCAcCAiICBhUKCQgL
|
||||
AgQWAgMBAh4HAheAAAoJEB8g/tCqBbDace8BAN1SpkEMSYll+XupKHiaIUwnhm4N
|
||||
eS79G1i+345Gl6CyAQDjgn+3rzG6sexjKh+10EKiy5omsQEGzUW03s7gS0T1Drg4
|
||||
BGpXI7QSCisGAQQBl1UBBQEBB0CXofBIYYXG2+dZqgllhsbkNPF4qlyfPgbRW+zb
|
||||
7Kw3IAMBCAeIeAQYFgoAIBYhBK1YqreiDYUjy/WaeR8g/tCqBbDaBQJqVyO0AhsM
|
||||
AAoJEB8g/tCqBbDauMkA/RG4iqtPZOI3DQzFJYu7SnxaD81vdP0LyTLKDQkynySu
|
||||
AQDrlWyF8LRlad4iX1yQPCuOV0aUpTNq5kPlWurtX99/BQ==
|
||||
=uKsS
|
||||
-----END PGP PUBLIC KEY BLOCK-----
|
||||
@@ -1,17 +0,0 @@
|
||||
-----BEGIN PGP SIGNED MESSAGE-----
|
||||
Hash: SHA512
|
||||
|
||||
Contact: mailto:[email protected]
|
||||
Expires: 2027-07-16T00:00:00.000Z
|
||||
Encryption: https://andwati.com/.well-known/pgp-key.txt
|
||||
Encryption: https://keys.openpgp.org/vks/v1/by-fingerprint/AD58AAB7A20D8523CBF59A791F20FED0AA05B0DA
|
||||
Encryption: https://keyserver.ubuntu.com/pks/lookup?op=get&search=0xAD58AAB7A20D8523CBF59A791F20FED0AA05B0DA
|
||||
Preferred-Languages: en
|
||||
Canonical: https://andwati.com/.well-known/security.txt
|
||||
-----BEGIN PGP SIGNATURE-----
|
||||
|
||||
iHUEARYKAB0WIQStWKq3og2FI8v1mnkfIP7QqgWw2gUCaljXlQAKCRAfIP7QqgWw
|
||||
2qAoAP0Q7Cc0YsP2dvV7fqDlqcnjuJepQQSTZBz7ehkPyjGV5gEA3K9ZqQmuI2ea
|
||||
KKADWxuKTTY43PBmuV9rMqLm8ZOPlAY=
|
||||
=NUkY
|
||||
-----END PGP SIGNATURE-----
|
||||
|
Before Width: | Height: | Size: 4.6 KiB |
@@ -1,75 +0,0 @@
|
||||
/* IBM Plex Serif — display/headings */
|
||||
@font-face {
|
||||
font-family: 'IBM Plex Serif';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-display: swap;
|
||||
src: url('../fonts/ibm-plex-serif/ibm-plex-serif-v20-latin-regular.woff2') format('woff2');
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'IBM Plex Serif';
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
font-display: swap;
|
||||
src: url('../fonts/ibm-plex-serif/ibm-plex-serif-v20-latin-600.woff2') format('woff2');
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'IBM Plex Serif';
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
font-display: swap;
|
||||
src: url('../fonts/ibm-plex-serif/ibm-plex-serif-v20-latin-700.woff2') format('woff2');
|
||||
}
|
||||
|
||||
/* Source Serif 4 — body copy */
|
||||
@font-face {
|
||||
font-family: 'Source Serif 4';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-display: swap;
|
||||
src: url('../fonts/source-serif-4/source-serif-4-v14-latin-regular.woff2') format('woff2');
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'Source Serif 4';
|
||||
font-style: italic;
|
||||
font-weight: 400;
|
||||
font-display: swap;
|
||||
src: url('../fonts/source-serif-4/source-serif-4-v14-latin-italic.woff2') format('woff2');
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'Source Serif 4';
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
font-display: swap;
|
||||
src: url('../fonts/source-serif-4/source-serif-4-v14-latin-600.woff2') format('woff2');
|
||||
}
|
||||
|
||||
/* JetBrains Mono (official release — full ligature support) — case-reference lines, tags, code */
|
||||
@font-face {
|
||||
font-family: 'JetBrains Mono';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-display: swap;
|
||||
src: url('../fonts/jetbrains-mono/JetBrainsMono-Regular.woff2') format('woff2');
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'JetBrains Mono';
|
||||
font-style: italic;
|
||||
font-weight: 400;
|
||||
font-display: swap;
|
||||
src: url('../fonts/jetbrains-mono/JetBrainsMono-Italic.woff2') format('woff2');
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'JetBrains Mono';
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
font-display: swap;
|
||||
src: url('../fonts/jetbrains-mono/JetBrainsMono-Bold.woff2') format('woff2');
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'JetBrains Mono';
|
||||
font-style: italic;
|
||||
font-weight: 700;
|
||||
font-display: swap;
|
||||
src: url('../fonts/jetbrains-mono/JetBrainsMono-BoldItalic.woff2') format('woff2');
|
||||
}
|
||||
|
Before Width: | Height: | Size: 2.9 KiB |
|
Before Width: | Height: | Size: 8.5 KiB |
|
Before Width: | Height: | Size: 521 B |
|
Before Width: | Height: | Size: 5.3 KiB |
|
Before Width: | Height: | Size: 953 B |
|
Before Width: | Height: | Size: 7.8 KiB |
|
Before Width: | Height: | Size: 356 KiB |
|
Before Width: | Height: | Size: 24 KiB |
|
Before Width: | Height: | Size: 36 KiB |
|
Before Width: | Height: | Size: 29 KiB |
|
Before Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 24 KiB |
|
Before Width: | Height: | Size: 38 KiB |
|
Before Width: | Height: | Size: 28 KiB |
|
Before Width: | Height: | Size: 34 KiB |
|
Before Width: | Height: | Size: 25 KiB |
|
Before Width: | Height: | Size: 35 KiB |
|
Before Width: | Height: | Size: 27 KiB |
|
Before Width: | Height: | Size: 38 KiB |
|
Before Width: | Height: | Size: 37 KiB |
|
Before Width: | Height: | Size: 30 KiB |
|
Before Width: | Height: | Size: 38 KiB |
|
Before Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 37 KiB |
|
Before Width: | Height: | Size: 21 KiB |
|
Before Width: | Height: | Size: 39 KiB |
@@ -1,73 +0,0 @@
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
// Select all <pre> elements that contain code blocks
|
||||
const preBlocks = document.querySelectorAll('pre');
|
||||
|
||||
const copyIcon =
|
||||
'<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect width="8" height="4" x="8" y="2" rx="1" ry="1"/><path d="M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"/></svg>';
|
||||
const checkIcon =
|
||||
'<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5"/></svg>';
|
||||
|
||||
preBlocks.forEach((pre) => {
|
||||
// Wrap the <pre> so the button can sit outside its horizontal
|
||||
// scroll container — a child of pre would scroll along with the code.
|
||||
const wrapper = document.createElement('div');
|
||||
wrapper.className = 'code-block-wrapper';
|
||||
pre.parentNode.insertBefore(wrapper, pre);
|
||||
wrapper.appendChild(pre);
|
||||
|
||||
// Create the copy button
|
||||
const button = document.createElement('button');
|
||||
button.innerHTML = copyIcon;
|
||||
button.className = 'copy-code-btn';
|
||||
button.setAttribute('aria-label', 'Copy code');
|
||||
button.setAttribute('title', 'Copy code');
|
||||
|
||||
wrapper.appendChild(button);
|
||||
|
||||
button.addEventListener('click', async () => {
|
||||
// Find the <code> element within the <pre>
|
||||
const code = pre.querySelector('code');
|
||||
if (!code) return;
|
||||
|
||||
// Get the text content, removing any leading/trailing whitespace
|
||||
const text = code.innerText;
|
||||
|
||||
try {
|
||||
if (navigator.clipboard && window.isSecureContext) {
|
||||
// Modern Async Clipboard API
|
||||
await navigator.clipboard.writeText(text);
|
||||
} else {
|
||||
// Fallback for insecure contexts (like local network IPs via HTTP)
|
||||
const textArea = document.createElement('textarea');
|
||||
textArea.value = text;
|
||||
|
||||
// Move outside the screen to make it invisible
|
||||
textArea.style.position = 'absolute';
|
||||
textArea.style.left = '-999999px';
|
||||
|
||||
document.body.appendChild(textArea);
|
||||
textArea.select();
|
||||
|
||||
document.execCommand('copy');
|
||||
textArea.remove();
|
||||
}
|
||||
|
||||
// Add visual feedback
|
||||
button.innerHTML = checkIcon;
|
||||
button.classList.add('copied');
|
||||
button.setAttribute('aria-label', 'Copied');
|
||||
button.setAttribute('title', 'Copied!');
|
||||
|
||||
// Revert back after 2 seconds
|
||||
setTimeout(() => {
|
||||
button.innerHTML = copyIcon;
|
||||
button.classList.remove('copied');
|
||||
button.setAttribute('aria-label', 'Copy code');
|
||||
button.setAttribute('title', 'Copy code');
|
||||
}, 2000);
|
||||
} catch (err) {
|
||||
console.error('Failed to copy code: ', err);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,32 +0,0 @@
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
const refs = document.querySelectorAll('sup.footnote-reference');
|
||||
if (!refs.length) return;
|
||||
|
||||
refs.forEach(function (sup) {
|
||||
const a = sup.querySelector('a');
|
||||
if (!a) return;
|
||||
|
||||
const targetId = a.getAttribute('href').replace(/^#/, '');
|
||||
const refId = 'fnref-' + targetId;
|
||||
sup.id = refId;
|
||||
|
||||
const def = document.getElementById(targetId);
|
||||
if (!def) return;
|
||||
|
||||
// Append ↩ to the last <p> inside the definition
|
||||
const paras = def.querySelectorAll('p');
|
||||
const lastPara = paras[paras.length - 1];
|
||||
if (!lastPara) return;
|
||||
|
||||
const backlink = document.createElement('a');
|
||||
backlink.href = '#' + refId;
|
||||
backlink.className = 'footnote-backref';
|
||||
backlink.setAttribute('aria-label', 'Back to reference');
|
||||
backlink.textContent = '↩';
|
||||
|
||||
lastPara.appendChild(document.createTextNode('\u00a0'));
|
||||
lastPara.appendChild(backlink);
|
||||
});
|
||||
})();
|
||||
@@ -1,13 +0,0 @@
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
document.querySelectorAll('.post-body h2[id], .post-body h3[id]').forEach(function (heading) {
|
||||
var a = document.createElement('a');
|
||||
a.href = '#' + heading.id;
|
||||
a.className = 'heading-anchor';
|
||||
a.setAttribute('aria-label', 'Link to this section');
|
||||
a.setAttribute('tabindex', '-1');
|
||||
a.textContent = '#';
|
||||
heading.appendChild(a);
|
||||
});
|
||||
})();
|
||||
@@ -1,170 +0,0 @@
|
||||
!(function (e, t) {
|
||||
'object' == typeof exports && 'object' == typeof module
|
||||
? (module.exports = t(require('katex')))
|
||||
: 'function' == typeof define && define.amd
|
||||
? define(['katex'], t)
|
||||
: 'object' == typeof exports
|
||||
? (exports.renderMathInElement = t(require('katex')))
|
||||
: (e.renderMathInElement = t(e.katex));
|
||||
})('undefined' != typeof self ? self : this, function (e) {
|
||||
return (function () {
|
||||
'use strict';
|
||||
var t = {
|
||||
771: function (t) {
|
||||
t.exports = e;
|
||||
},
|
||||
},
|
||||
r = {};
|
||||
function n(e) {
|
||||
var i = r[e];
|
||||
if (void 0 !== i) return i.exports;
|
||||
var a = (r[e] = { exports: {} });
|
||||
return (t[e](a, a.exports, n), a.exports);
|
||||
}
|
||||
((n.n = function (e) {
|
||||
var t =
|
||||
e && e.__esModule
|
||||
? function () {
|
||||
return e.default;
|
||||
}
|
||||
: function () {
|
||||
return e;
|
||||
};
|
||||
return (n.d(t, { a: t }), t);
|
||||
}),
|
||||
(n.d = function (e, t) {
|
||||
for (var r in t)
|
||||
n.o(t, r) && !n.o(e, r) && Object.defineProperty(e, r, { enumerable: !0, get: t[r] });
|
||||
}),
|
||||
(n.o = function (e, t) {
|
||||
return Object.prototype.hasOwnProperty.call(e, t);
|
||||
}));
|
||||
var i = {};
|
||||
return (
|
||||
(function () {
|
||||
n.d(i, {
|
||||
default: function () {
|
||||
return s;
|
||||
},
|
||||
});
|
||||
var e = n(771),
|
||||
t = n.n(e),
|
||||
r = function (e, t, r) {
|
||||
for (var n = r, i = 0, a = e.length; n < t.length; ) {
|
||||
var o = t[n];
|
||||
if (i <= 0 && t.slice(n, n + a) === e) return n;
|
||||
('\\' === o ? n++ : '{' === o ? i++ : '}' === o && i--, n++);
|
||||
}
|
||||
return -1;
|
||||
},
|
||||
a = /^\\begin{/,
|
||||
o = function (e, t) {
|
||||
for (
|
||||
var n,
|
||||
i = [],
|
||||
o = new RegExp(
|
||||
'(' +
|
||||
t
|
||||
.map(function (e) {
|
||||
return e.left.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&');
|
||||
})
|
||||
.join('|') +
|
||||
')',
|
||||
);
|
||||
-1 !== (n = e.search(o));
|
||||
) {
|
||||
n > 0 && (i.push({ type: 'text', data: e.slice(0, n) }), (e = e.slice(n)));
|
||||
var l = t.findIndex(function (t) {
|
||||
return e.startsWith(t.left);
|
||||
});
|
||||
if (-1 === (n = r(t[l].right, e, t[l].left.length))) break;
|
||||
var d = e.slice(0, n + t[l].right.length),
|
||||
s = a.test(d) ? d : e.slice(t[l].left.length, n);
|
||||
(i.push({ type: 'math', data: s, rawData: d, display: t[l].display }),
|
||||
(e = e.slice(n + t[l].right.length)));
|
||||
}
|
||||
return ('' !== e && i.push({ type: 'text', data: e }), i);
|
||||
},
|
||||
l = function (e, r) {
|
||||
var n = o(e, r.delimiters);
|
||||
if (1 === n.length && 'text' === n[0].type) return null;
|
||||
for (var i = document.createDocumentFragment(), a = 0; a < n.length; a++)
|
||||
if ('text' === n[a].type) i.appendChild(document.createTextNode(n[a].data));
|
||||
else {
|
||||
var l = document.createElement('span'),
|
||||
d = n[a].data;
|
||||
r.displayMode = n[a].display;
|
||||
try {
|
||||
(r.preProcess && (d = r.preProcess(d)), t().render(d, l, r));
|
||||
} catch (e) {
|
||||
if (!(e instanceof t().ParseError)) throw e;
|
||||
(r.errorCallback(
|
||||
'KaTeX auto-render: Failed to parse `' + n[a].data + '` with ',
|
||||
e,
|
||||
),
|
||||
i.appendChild(document.createTextNode(n[a].rawData)));
|
||||
continue;
|
||||
}
|
||||
i.appendChild(l);
|
||||
}
|
||||
return i;
|
||||
},
|
||||
d = function e(t, r) {
|
||||
for (var n = 0; n < t.childNodes.length; n++) {
|
||||
var i = t.childNodes[n];
|
||||
if (3 === i.nodeType) {
|
||||
for (
|
||||
var a = i.textContent, o = i.nextSibling, d = 0;
|
||||
o && o.nodeType === Node.TEXT_NODE;
|
||||
)
|
||||
((a += o.textContent), (o = o.nextSibling), d++);
|
||||
var s = l(a, r);
|
||||
if (s) {
|
||||
for (var f = 0; f < d; f++) i.nextSibling.remove();
|
||||
((n += s.childNodes.length - 1), t.replaceChild(s, i));
|
||||
} else n += d;
|
||||
} else
|
||||
1 === i.nodeType &&
|
||||
(function () {
|
||||
var t = ' ' + i.className + ' ';
|
||||
-1 === r.ignoredTags.indexOf(i.nodeName.toLowerCase()) &&
|
||||
r.ignoredClasses.every(function (e) {
|
||||
return -1 === t.indexOf(' ' + e + ' ');
|
||||
}) &&
|
||||
e(i, r);
|
||||
})();
|
||||
}
|
||||
},
|
||||
s = function (e, t) {
|
||||
if (!e) throw new Error('No element provided to render');
|
||||
var r = {};
|
||||
for (var n in t) t.hasOwnProperty(n) && (r[n] = t[n]);
|
||||
((r.delimiters = r.delimiters || [
|
||||
{ left: '$$', right: '$$', display: !0 },
|
||||
{ left: '\\(', right: '\\)', display: !1 },
|
||||
{ left: '\\begin{equation}', right: '\\end{equation}', display: !0 },
|
||||
{ left: '\\begin{align}', right: '\\end{align}', display: !0 },
|
||||
{ left: '\\begin{alignat}', right: '\\end{alignat}', display: !0 },
|
||||
{ left: '\\begin{gather}', right: '\\end{gather}', display: !0 },
|
||||
{ left: '\\begin{CD}', right: '\\end{CD}', display: !0 },
|
||||
{ left: '\\[', right: '\\]', display: !0 },
|
||||
]),
|
||||
(r.ignoredTags = r.ignoredTags || [
|
||||
'script',
|
||||
'noscript',
|
||||
'style',
|
||||
'textarea',
|
||||
'pre',
|
||||
'code',
|
||||
'option',
|
||||
]),
|
||||
(r.ignoredClasses = r.ignoredClasses || []),
|
||||
(r.errorCallback = r.errorCallback || console.error),
|
||||
(r.macros = r.macros || {}),
|
||||
d(e, r));
|
||||
};
|
||||
})(),
|
||||
(i = i.default)
|
||||
);
|
||||
})();
|
||||
});
|
||||
@@ -1,34 +0,0 @@
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
const progressBar = document.getElementById('reading-progress-bar');
|
||||
if (!progressBar) return;
|
||||
|
||||
const updateProgress = () => {
|
||||
// Calculate how far the user has scrolled down the page
|
||||
const scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
|
||||
|
||||
// Calculate the total scrollable height
|
||||
const scrollHeight = document.documentElement.scrollHeight || document.body.scrollHeight;
|
||||
const clientHeight = document.documentElement.clientHeight || window.innerHeight;
|
||||
|
||||
const windowHeight = scrollHeight - clientHeight;
|
||||
|
||||
// Calculate percentage and update width
|
||||
const scrollPercentage = windowHeight > 0 ? (scrollTop / windowHeight) * 100 : 0;
|
||||
progressBar.style.width = scrollPercentage + '%';
|
||||
};
|
||||
|
||||
// Update initially in case the user refreshes midway down the page
|
||||
updateProgress();
|
||||
|
||||
// Throttle the scroll event listener a tiny bit for performance
|
||||
let isTicking = false;
|
||||
window.addEventListener('scroll', () => {
|
||||
if (!isTicking) {
|
||||
window.requestAnimationFrame(() => {
|
||||
updateProgress();
|
||||
isTicking = false;
|
||||
});
|
||||
isTicking = true;
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -1,34 +0,0 @@
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
const scrollToTopBtn = document.getElementById('scroll-to-top');
|
||||
|
||||
if (!scrollToTopBtn) return;
|
||||
|
||||
// Show button when scrolled down 400px
|
||||
const toggleVisibility = () => {
|
||||
if (window.scrollY > 400) {
|
||||
scrollToTopBtn.classList.add('visible');
|
||||
} else {
|
||||
scrollToTopBtn.classList.remove('visible');
|
||||
}
|
||||
};
|
||||
|
||||
// Smooth scroll to top when clicked
|
||||
scrollToTopBtn.addEventListener('click', () => {
|
||||
window.scrollTo({
|
||||
top: 0,
|
||||
behavior: 'smooth',
|
||||
});
|
||||
});
|
||||
|
||||
// Throttle the scroll event listener a tiny bit for performance
|
||||
let isTicking = false;
|
||||
window.addEventListener('scroll', () => {
|
||||
if (!isTicking) {
|
||||
window.requestAnimationFrame(() => {
|
||||
toggleVisibility();
|
||||
isTicking = false;
|
||||
});
|
||||
isTicking = true;
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -1,223 +0,0 @@
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
const searchToggleBtn = document.querySelector('.search-toggle');
|
||||
if (!searchToggleBtn) return;
|
||||
|
||||
// Check if elasticlunr is available
|
||||
if (typeof elasticlunr === 'undefined') {
|
||||
console.warn('Elasticlunr not loaded. Search will not work.');
|
||||
return;
|
||||
}
|
||||
|
||||
// Modal elements
|
||||
const overlay = document.getElementById('search-overlay');
|
||||
const input = document.getElementById('search-input');
|
||||
const resultsContainer = document.getElementById('search-results');
|
||||
|
||||
if (!overlay || !input || !resultsContainer) return;
|
||||
|
||||
let index = null;
|
||||
let isIndexLoading = false;
|
||||
let selectedIndex = -1;
|
||||
let resultItems = [];
|
||||
|
||||
// Initialize search index (loaded lazily on first open)
|
||||
const initSearch = async () => {
|
||||
if (index || isIndexLoading) return;
|
||||
isIndexLoading = true;
|
||||
|
||||
try {
|
||||
// Fetch the Zola-generated index
|
||||
const response = await fetch('/search_index.en.js');
|
||||
const jsText = await response.text();
|
||||
|
||||
// The file defines `window.searchIndex = {...}`
|
||||
// We use a safe evaluation approach if it's purely assignment
|
||||
// Or just append it as a script tag
|
||||
const script = document.createElement('script');
|
||||
script.innerHTML = jsText;
|
||||
document.body.appendChild(script);
|
||||
|
||||
// Wait for it to parse
|
||||
setTimeout(() => {
|
||||
if (window.searchIndex) {
|
||||
index = elasticlunr.Index.load(window.searchIndex);
|
||||
// Search immediately if there's text
|
||||
if (input.value.trim().length > 0) {
|
||||
performSearch();
|
||||
}
|
||||
}
|
||||
}, 50);
|
||||
} catch (e) {
|
||||
console.error('Failed to load search index:', e);
|
||||
}
|
||||
};
|
||||
|
||||
// Open Modal
|
||||
const openSearch = () => {
|
||||
overlay.classList.add('active');
|
||||
|
||||
// Slight delay ensures the browser focuses the input after the display transition starts
|
||||
setTimeout(() => {
|
||||
input.focus();
|
||||
}, 50);
|
||||
|
||||
initSearch();
|
||||
document.body.style.overflow = 'hidden'; // Prevent background scrolling
|
||||
};
|
||||
|
||||
// Close Modal
|
||||
const closeSearch = () => {
|
||||
overlay.classList.remove('active');
|
||||
input.value = '';
|
||||
resultsContainer.innerHTML = '';
|
||||
document.body.style.overflow = '';
|
||||
selectedIndex = -1;
|
||||
resultItems = [];
|
||||
};
|
||||
|
||||
// Bind Toggle Button
|
||||
searchToggleBtn.addEventListener('click', (e) => {
|
||||
e.preventDefault();
|
||||
if (overlay.classList.contains('active')) {
|
||||
closeSearch();
|
||||
} else {
|
||||
openSearch();
|
||||
}
|
||||
});
|
||||
|
||||
// Close on overlay click
|
||||
overlay.addEventListener('click', (e) => {
|
||||
if (e.target === overlay) closeSearch();
|
||||
});
|
||||
|
||||
// Handle Keyboard Shortcuts
|
||||
document.addEventListener('keydown', (e) => {
|
||||
// Ctrl+K -> Open Search
|
||||
if ((e.ctrlKey || e.metaKey) && e.key === 'k') {
|
||||
e.preventDefault();
|
||||
openSearch();
|
||||
}
|
||||
|
||||
if (!overlay.classList.contains('active')) return;
|
||||
|
||||
// Escape -> Close Search
|
||||
if (e.key === 'Escape') {
|
||||
closeSearch();
|
||||
}
|
||||
|
||||
// Arrow Navigation
|
||||
if (e.key === 'ArrowDown' || e.key === 'ArrowUp') {
|
||||
e.preventDefault();
|
||||
if (resultItems.length === 0) return;
|
||||
|
||||
if (e.key === 'ArrowDown') {
|
||||
selectedIndex = (selectedIndex + 1) % resultItems.length;
|
||||
} else {
|
||||
selectedIndex = (selectedIndex - 1 + resultItems.length) % resultItems.length;
|
||||
}
|
||||
|
||||
updateSelection();
|
||||
}
|
||||
|
||||
// Enter -> Navigate to selected
|
||||
if (e.key === 'Enter') {
|
||||
e.preventDefault();
|
||||
if (selectedIndex >= 0 && resultItems[selectedIndex]) {
|
||||
window.location.href = resultItems[selectedIndex].href;
|
||||
} else if (resultItems.length > 0) {
|
||||
// Default to first item if none selected
|
||||
window.location.href = resultItems[0].href;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const updateSelection = () => {
|
||||
resultItems.forEach((el, i) => {
|
||||
if (i === selectedIndex) {
|
||||
el.classList.add('selected');
|
||||
el.scrollIntoView({ block: 'nearest' });
|
||||
} else {
|
||||
el.classList.remove('selected');
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// Perform the Search
|
||||
const performSearch = () => {
|
||||
if (!index) {
|
||||
resultsContainer.innerHTML = '<div class="no-results">Loading search index...</div>';
|
||||
return;
|
||||
}
|
||||
|
||||
const query = input.value.trim();
|
||||
if (query.length === 0) {
|
||||
resultsContainer.innerHTML = '';
|
||||
selectedIndex = -1;
|
||||
resultItems = [];
|
||||
return;
|
||||
}
|
||||
|
||||
const options = {
|
||||
bool: 'OR',
|
||||
expand: true,
|
||||
};
|
||||
|
||||
const results = index.search(query, options);
|
||||
|
||||
if (results.length === 0) {
|
||||
resultsContainer.innerHTML = `<div class="no-results">No results found for "${query}"</div>`;
|
||||
selectedIndex = -1;
|
||||
resultItems = [];
|
||||
return;
|
||||
}
|
||||
|
||||
// Build HTML
|
||||
let html = '';
|
||||
results.forEach((res) => {
|
||||
// The doc is stored inside the index.documentStore
|
||||
// For Zola + elasticlunr, res.ref IS the URL.
|
||||
const url = res.ref;
|
||||
const doc = index.documentStore.docs[res.ref];
|
||||
|
||||
if (!doc) return;
|
||||
|
||||
// Truncate summary if needed
|
||||
let body = doc.body || '';
|
||||
if (body.length > 150) {
|
||||
body = body.substring(0, 150) + '...';
|
||||
}
|
||||
|
||||
const title = doc.title || url;
|
||||
|
||||
html += `
|
||||
<a href="${url}" class="search-result-item">
|
||||
<div class="result-title">${title}</div>
|
||||
<div class="result-summary">${body}</div>
|
||||
</a>
|
||||
`;
|
||||
});
|
||||
|
||||
resultsContainer.innerHTML = html;
|
||||
|
||||
// Cache DOM elements for keyboard navigation
|
||||
resultItems = Array.from(resultsContainer.querySelectorAll('.search-result-item'));
|
||||
selectedIndex = -1; // Reset selection on new search
|
||||
|
||||
// Mouse hover updates selection index
|
||||
resultItems.forEach((item, i) => {
|
||||
item.addEventListener('mouseenter', () => {
|
||||
selectedIndex = i;
|
||||
updateSelection();
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
// Debounce the input
|
||||
let debounceTimer;
|
||||
input.addEventListener('input', () => {
|
||||
clearTimeout(debounceTimer);
|
||||
debounceTimer = setTimeout(() => {
|
||||
performSearch();
|
||||
}, 150);
|
||||
});
|
||||
});
|
||||
@@ -1,81 +0,0 @@
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
const themeToggleBtn = document.getElementById('theme-toggle');
|
||||
const htmlElement = document.documentElement;
|
||||
|
||||
const applyTheme = (theme) => {
|
||||
if (theme === 'dark') {
|
||||
htmlElement.classList.add('dark');
|
||||
} else {
|
||||
htmlElement.classList.remove('dark');
|
||||
}
|
||||
localStorage.setItem('theme', theme);
|
||||
};
|
||||
|
||||
// Check local storage for theme preference
|
||||
const currentTheme = localStorage.getItem('theme');
|
||||
if (currentTheme === 'dark' || currentTheme === 'light') {
|
||||
applyTheme(currentTheme);
|
||||
} else {
|
||||
// Fallback to system preference
|
||||
const prefersDarkScheme = window.matchMedia('(prefers-color-scheme: dark)');
|
||||
applyTheme(prefersDarkScheme.matches ? 'dark' : 'light');
|
||||
}
|
||||
|
||||
// Toggle theme on click
|
||||
if (themeToggleBtn) {
|
||||
themeToggleBtn.addEventListener('click', () => {
|
||||
const nextTheme = htmlElement.classList.contains('dark') ? 'light' : 'dark';
|
||||
applyTheme(nextTheme);
|
||||
});
|
||||
}
|
||||
|
||||
// Mobile nav toggle
|
||||
const navToggle = document.getElementById('nav-toggle');
|
||||
const navLinks = document.getElementById('nav-links');
|
||||
|
||||
if (navToggle && navLinks) {
|
||||
navToggle.addEventListener('click', () => {
|
||||
const isOpen = navLinks.classList.toggle('is-open');
|
||||
navToggle.setAttribute('aria-expanded', isOpen);
|
||||
});
|
||||
|
||||
// Close nav when a link is clicked
|
||||
navLinks.querySelectorAll('.nav-item').forEach((link) => {
|
||||
link.addEventListener('click', () => {
|
||||
navLinks.classList.remove('is-open');
|
||||
navToggle.setAttribute('aria-expanded', 'false');
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Sync Utterances (comments iframe) theme with the site theme.
|
||||
// The iframe only reads its initial `theme` attribute once, so later
|
||||
// changes must go through postMessage per the utterances protocol.
|
||||
const syncUtterancesTheme = () => {
|
||||
const commentsEl = document.getElementById('comments');
|
||||
const frame = document.querySelector('.utterances-frame');
|
||||
if (!commentsEl || !frame) return;
|
||||
const theme = htmlElement.classList.contains('dark')
|
||||
? commentsEl.dataset.utterancesThemeDark
|
||||
: commentsEl.dataset.utterancesThemeLight;
|
||||
// The iframe briefly shares our origin before it navigates to utteranc.es,
|
||||
// so posting with that targetOrigin throws until the navigation completes.
|
||||
try {
|
||||
frame.contentWindow.postMessage({ type: 'set-theme', theme }, 'https://utteranc.es');
|
||||
} catch (e) {
|
||||
// Ignore: frame hasn't navigated to utteranc.es yet.
|
||||
}
|
||||
};
|
||||
new MutationObserver(syncUtterancesTheme).observe(htmlElement, {
|
||||
attributes: true,
|
||||
attributeFilter: ['class'],
|
||||
});
|
||||
// The iframe loads asynchronously, so poll briefly until it's mounted.
|
||||
let utterancesTries = 0;
|
||||
const utterancesPoll = setInterval(() => {
|
||||
if (document.querySelector('.utterances-frame') || ++utterancesTries > 20) {
|
||||
clearInterval(utterancesPoll);
|
||||
syncUtterancesTheme();
|
||||
}
|
||||
}, 250);
|
||||
});
|
||||
@@ -1,59 +0,0 @@
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
const sidebar = document.querySelector('.post-toc-sidebar');
|
||||
if (!sidebar) return;
|
||||
|
||||
const links = Array.from(sidebar.querySelectorAll('a[data-toc-id]'));
|
||||
if (!links.length) return;
|
||||
|
||||
const headingIds = links.map((a) => a.dataset.tocId);
|
||||
const headings = headingIds.map((id) => document.getElementById(id)).filter(Boolean);
|
||||
|
||||
let activeId = null;
|
||||
|
||||
function setActive(id) {
|
||||
if (id === activeId) return;
|
||||
activeId = id;
|
||||
links.forEach((a) => {
|
||||
if (a.dataset.tocId === id) {
|
||||
a.classList.add('toc-active');
|
||||
} else {
|
||||
a.classList.remove('toc-active');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
const observer = new IntersectionObserver(
|
||||
(entries) => {
|
||||
// Find the topmost visible heading
|
||||
const visible = headings.filter((h) => {
|
||||
const rect = h.getBoundingClientRect();
|
||||
return rect.top >= 0 && rect.top < window.innerHeight * 0.6;
|
||||
});
|
||||
|
||||
if (visible.length > 0) {
|
||||
setActive(visible[0].id);
|
||||
} else {
|
||||
// If scrolled past all headings, keep last active
|
||||
const above = headings.filter((h) => h.getBoundingClientRect().top < 0);
|
||||
if (above.length > 0) {
|
||||
setActive(above[above.length - 1].id);
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
rootMargin: '-10% 0px -60% 0px',
|
||||
threshold: 0,
|
||||
},
|
||||
);
|
||||
|
||||
headings.forEach((h) => observer.observe(h));
|
||||
|
||||
// Set initial active on load
|
||||
const firstVisible = headings.find((h) => {
|
||||
const rect = h.getBoundingClientRect();
|
||||
return rect.top >= 0;
|
||||
});
|
||||
if (firstVisible) setActive(firstVisible.id);
|
||||
})();
|
||||
@@ -1,41 +0,0 @@
|
||||
# andwati.com
|
||||
|
||||
> Ian Andwati's personal blog about mathematics, computer science, binary exploitation, reverse engineering, capture-the-flag competitions, offensive security, Linux, and software development.
|
||||
|
||||
This site contains articles in English, often with commands, code samples, worked explanations, and material aimed at readers learning by doing.
|
||||
|
||||
## Main pages
|
||||
|
||||
- [Home](https://andwati.com/): Introduction and latest articles.
|
||||
- [About](https://andwati.com/about/): About the author and contact information.
|
||||
- [Posts](https://andwati.com/posts/): All published articles.
|
||||
- [Tags](https://andwati.com/tags/): Articles grouped by topic.
|
||||
- [Archive](https://andwati.com/archive/): Chronological article archive.
|
||||
|
||||
## Published articles
|
||||
|
||||
- [Self-Hosting Gitea and Automating GitHub Mirrors](https://andwati.com/posts/self-hosting-gitea-and-mirroring-github/): Self-Hosting Gitea and Automating GitHub Mirrors (and Everything Cloudflare Broke Along the Way)
|
||||
- [The One Thing Nobody Tells You About WiFi Hotspots on Arch Linux](https://andwati.com/posts/wifi-hotspot-arch/): A minimal Arch install is great until NetworkManager silently fails to find a binary you didn't know you needed
|
||||
- [From C to Machine Code: What Actually Runs](https://andwati.com/posts/from-c-to-machine-code/): Before diving into how to break a program, we need to understand what the computer is actually executing
|
||||
- [The Single Byte That Kills Your Exploit: Understanding Endianness](https://andwati.com/posts/the-single-byte-that-kills-your-exploit-understanding-endianness/): Problem: Computers speak different languages, like people
|
||||
- [What is pwn?](https://andwati.com/posts/what-is-pwn/): No not that one
|
||||
- [ScriptCTF 2025 Writeup](https://andwati.com/posts/scriptctf2025/): ScriptCTF 2025 Writeup
|
||||
- [mmuctf 2025 writeup](https://andwati.com/posts/mmuctf2025/): mmuctf 2025 challenges writeup
|
||||
- [cognitive inertia](https://andwati.com/posts/inertia/): inertia
|
||||
- [Export default and module.exports in Javascript](https://andwati.com/posts/javascript-exporting-modules/): Modules are the building blocks of modern JavaScript applications, allowing for the encapsulation of code into reusable components. Two primary systems govern the exportation of these modules: export default in ES6 and module.exports in CommonJS.
|
||||
- [Setting up Obsidian sync in Windows](https://andwati.com/posts/obsidian-sync/): Syncing Obsidian in Windows with Windows Task Scheduler with git
|
||||
- [A Fresh Coat Of Paint](https://andwati.com/posts/a-fresh-coat-of-paint/): Migrating to Zola
|
||||
- [What say you?](https://andwati.com/posts/utterances-comments/): Adding a comment system by utterances
|
||||
- [Subresource Integrity](https://andwati.com/posts/subresource-integrity/): Understanding Subresource Integrity
|
||||
- [Install PostgreSQL on Arch | Manjaro | Garuda Linux](https://andwati.com/posts/install-postgresql-15-on-arch-manjaro-garuda-linux/): Getting PostgreSQL up and running on Arch Linux-based distros
|
||||
- [Semantic Versioning(SemVer) and Conventional Commits](https://andwati.com/posts/semantic-version-and-conventional-commits/): Adopting best practices in your git and build workflows.
|
||||
- [Integrating Netlify CMS](https://andwati.com/posts/integrating-netlify/): Integrating netlify cms
|
||||
- [Django Secret Key Tutorial](https://andwati.com/posts/generate-django-secret-key/): Managing secrets
|
||||
- [Hello World](https://andwati.com/posts/hello-world/): Hello world
|
||||
- [Configure Vue.js app With Tailwind CSS](https://andwati.com/posts/vuejs-tailwind/): Tailwindcss in vuejs
|
||||
|
||||
## Feeds and discovery
|
||||
|
||||
- [RSS feed](https://andwati.com/rss.xml): Full site feed in RSS format.
|
||||
- [JSON feed](https://andwati.com/feed.json): Full site feed in JSON format.
|
||||
- [Sitemap](https://andwati.com/sitemap.xml): Machine-readable index of public pages.
|
||||
@@ -1,174 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:atom="http://www.w3.org/2005/Atom">
|
||||
<xsl:output method="html" version="1.0" encoding="UTF-8" indent="yes"/>
|
||||
<xsl:template match="/">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
|
||||
<head>
|
||||
<title><xsl:value-of select="/rss/channel/title"/> — RSS Feed</title>
|
||||
<meta charset="utf-8"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1"/>
|
||||
<style>
|
||||
:root {
|
||||
--bg-color: #e9e9e2;
|
||||
--surface-color: #dedecf;
|
||||
--text-color: #17181c;
|
||||
--text-muted: #68675f;
|
||||
--accent-color: #b42318;
|
||||
--accent-hover: #8e1b12;
|
||||
--border-color: rgba(23, 24, 28, 0.16);
|
||||
|
||||
--font-sans: Georgia, 'Source Serif 4', serif;
|
||||
--font-display: Georgia, 'IBM Plex Serif', serif;
|
||||
--font-mono: ui-monospace, 'JetBrains Mono', 'SFMono-Regular', Menlo, monospace;
|
||||
}
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
--bg-color: #131311;
|
||||
--surface-color: #1b1a17;
|
||||
--text-color: #e9e7de;
|
||||
--text-muted: #8b8a80;
|
||||
--accent-color: #ff5a46;
|
||||
--accent-hover: #ff7c6b;
|
||||
--border-color: rgba(233, 231, 222, 0.14);
|
||||
}
|
||||
}
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
body {
|
||||
font-family: var(--font-sans);
|
||||
background-color: var(--bg-color);
|
||||
color: var(--text-color);
|
||||
line-height: 1.6;
|
||||
margin: 0;
|
||||
padding: 3rem 1.5rem;
|
||||
}
|
||||
.wrap {
|
||||
max-width: 720px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
a {
|
||||
color: var(--accent-color);
|
||||
text-decoration: none;
|
||||
}
|
||||
a:hover {
|
||||
color: var(--accent-hover);
|
||||
text-decoration: underline;
|
||||
}
|
||||
.header {
|
||||
margin-bottom: 2.5rem;
|
||||
padding-bottom: 2rem;
|
||||
border-bottom: 1px solid var(--border-color);
|
||||
}
|
||||
.header h1 {
|
||||
font-family: var(--font-display);
|
||||
font-size: 2rem;
|
||||
font-weight: 700;
|
||||
margin: 0 0 0.5rem 0;
|
||||
color: var(--text-color);
|
||||
}
|
||||
.header p {
|
||||
font-size: 1.05rem;
|
||||
margin: 0;
|
||||
color: var(--text-muted);
|
||||
}
|
||||
.notice {
|
||||
background: var(--surface-color);
|
||||
padding: 1rem 1.25rem;
|
||||
border-left: 4px solid var(--accent-color);
|
||||
margin-bottom: 2.5rem;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
.notice strong {
|
||||
font-family: var(--font-mono);
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.05em;
|
||||
font-size: 0.8rem;
|
||||
display: block;
|
||||
margin-bottom: 0.35rem;
|
||||
color: var(--accent-color);
|
||||
}
|
||||
.item {
|
||||
padding: 1.75rem 0;
|
||||
border-bottom: 1px solid var(--border-color);
|
||||
}
|
||||
.item:first-child {
|
||||
padding-top: 0;
|
||||
}
|
||||
.item .meta {
|
||||
font-family: var(--font-mono);
|
||||
font-size: 0.8rem;
|
||||
letter-spacing: 0.05em;
|
||||
text-transform: uppercase;
|
||||
color: var(--text-muted);
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
.item h2 {
|
||||
font-family: var(--font-display);
|
||||
font-size: 1.4rem;
|
||||
font-weight: 700;
|
||||
margin: 0 0 0.5rem 0;
|
||||
}
|
||||
.item h2 a {
|
||||
color: var(--text-color);
|
||||
}
|
||||
.item h2 a:hover {
|
||||
color: var(--accent-color);
|
||||
text-decoration: none;
|
||||
}
|
||||
.item .excerpt {
|
||||
color: var(--text-muted);
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
.btn {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.35rem;
|
||||
padding: 0.4rem 0.9rem;
|
||||
border: 1px solid var(--accent-color);
|
||||
border-radius: 2px;
|
||||
font-family: var(--font-mono);
|
||||
font-size: 0.8rem;
|
||||
letter-spacing: 0.03em;
|
||||
color: var(--accent-color);
|
||||
}
|
||||
.btn:hover {
|
||||
background: var(--accent-color);
|
||||
color: var(--bg-color);
|
||||
text-decoration: none;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="wrap">
|
||||
<div class="header">
|
||||
<h1><xsl:value-of select="/rss/channel/title"/></h1>
|
||||
<p><xsl:value-of select="/rss/channel/description"/></p>
|
||||
</div>
|
||||
|
||||
<div class="notice">
|
||||
<strong>RSS Feed</strong>
|
||||
This is a feed, not a normal web page. Copy the URL from your address bar into a feed reader to subscribe.
|
||||
</div>
|
||||
|
||||
<div class="items">
|
||||
<xsl:for-each select="/rss/channel/item">
|
||||
<div class="item">
|
||||
<div class="meta">Published <xsl:value-of select="pubDate"/></div>
|
||||
<h2>
|
||||
<a href="{link}">
|
||||
<xsl:value-of select="title"/>
|
||||
</a>
|
||||
</h2>
|
||||
<div class="excerpt">
|
||||
<xsl:value-of select="substring(description, 1, 220)"/>…
|
||||
</div>
|
||||
<a href="{link}" class="btn">Read article →</a>
|
||||
</div>
|
||||
</xsl:for-each>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
</xsl:template>
|
||||
</xsl:stylesheet>
|
||||
@@ -1,12 +0,0 @@
|
||||
{
|
||||
"name": "Thoughts and Musings",
|
||||
"short_name": "andwati.com",
|
||||
"icons": [
|
||||
{ "src": "/images/favicon-192x192.png", "sizes": "192x192", "type": "image/png" },
|
||||
{ "src": "/images/favicon-512x512.png", "sizes": "512x512", "type": "image/png" }
|
||||
],
|
||||
"theme_color": "#131311",
|
||||
"background_color": "#131311",
|
||||
"display": "standalone",
|
||||
"start_url": "/"
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}404 — {{ config.extra.notfound_title | default(value="Document Not Found") }} | {{ config.title }}{% endblock title %}
|
||||
{% block description %}{{ config.extra.notfound_body | default(value="The page you requested could not be found.") }}{% endblock description %}
|
||||
|
||||
{% block content %}
|
||||
<div class="notfound-wrap">
|
||||
<div class="case-notice">
|
||||
<p class="case-notice-ref">{{ config.extra.notfound_status | default(value="Status: Not Found") }}</p>
|
||||
<h1 class="case-notice-title">{{ config.extra.notfound_title | default(value="Document Not Found") }}</h1>
|
||||
<p class="case-notice-body">
|
||||
{{ config.extra.notfound_body | default(value="This page couldn't be located in the archive. It may have been moved, renamed, or never filed.") }}
|
||||
</p>
|
||||
<div class="case-notice-links">
|
||||
<a href="{{ get_url(path="") }}">Home</a>
|
||||
<a href="{{ get_url(path="/posts") }}">Posts</a>
|
||||
<a href="{{ get_url(path="/tags") }}">Tags</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock content %}
|
||||
@@ -1,41 +0,0 @@
|
||||
{% extends "base.html" %} {% block title %}{{ section.title }} | {{ config.title }}{% endblock title
|
||||
%} {% block description %}Chronological archive of every post on {{ config.title }}.{% endblock
|
||||
description %} {% block canonical %}{{ section.permalink }}{% endblock canonical %} {% block og_title
|
||||
%}{{ section.title }} | {{ config.title }}{% endblock og_title %} {% block og_description %}Chronological
|
||||
archive of every post on {{ config.title }}.{% endblock og_description %} {% block og_url %}{{
|
||||
section.permalink }}{% endblock og_url %} {% block head %}
|
||||
<!-- SEO: BreadcrumbList JSON-LD -->
|
||||
<script type="application/ld+json">
|
||||
{
|
||||
"@context": "https://schema.org",
|
||||
"@type": "BreadcrumbList",
|
||||
"itemListElement": [
|
||||
{ "@type": "ListItem", "position": 1, "name": "Home", "item": "{{ config.base_url | safe }}/" },
|
||||
{ "@type": "ListItem", "position": 2, "name": {{ section.title | json_encode | safe }}, "item": "{{ section.permalink | safe }}" }
|
||||
]
|
||||
}
|
||||
</script>
|
||||
{% endblock head %} {% block content %}
|
||||
<div class="post-detail">
|
||||
<header class="post-header list-page-header">
|
||||
<h1 class="post-title list-page-title">{{ config.extra.archive_page_title | default(value="Archive") }}</h1>
|
||||
</header>
|
||||
|
||||
<div class="archive-list">
|
||||
{% set section = get_section(path="posts/_index.md") %} {% for year, posts in section.pages |
|
||||
sort(attribute="date") | reverse | group_by(attribute="year") %}
|
||||
<div class="archive-year">
|
||||
<h2 class="archive-year-title">{{ year }}</h2>
|
||||
<ul class="archive-items">
|
||||
{% for post in posts %}
|
||||
<li class="archive-item hover-scale">
|
||||
<time datetime="{{ post.date }}" class="archive-date">{{ post.date | date(format="%d-%b") }}</time>
|
||||
<a href="{{ post.permalink }}" class="archive-link">{{ post.title }}</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock content %}
|
||||
@@ -1,160 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>{% block title %}{{ config.title }}{% endblock title %}</title>
|
||||
<meta name="description" content="{% block description %}{{ config.description }}{% endblock description %}">
|
||||
<meta name="view-transition" content="same-origin">
|
||||
|
||||
<!-- Favicon -->
|
||||
<link rel="icon" href="/favicon.ico" sizes="any">
|
||||
<link rel="icon" type="image/png" sizes="32x32" href="/images/favicon-32x32.png">
|
||||
<link rel="icon" type="image/png" sizes="16x16" href="/images/favicon-16x16.png">
|
||||
<link rel="apple-touch-icon" href="/apple-touch-icon.png">
|
||||
<link rel="manifest" href="/site.webmanifest">
|
||||
<meta name="theme-color" content="#131311">
|
||||
|
||||
{% if config.extra.google_site_verification %}
|
||||
<meta name="google-site-verification" content="{{ config.extra.google_site_verification }}">
|
||||
{% endif %}
|
||||
|
||||
<!-- Canonical URL -->
|
||||
<link rel="canonical" href="{% block canonical %}{{ config.base_url }}/{% endblock canonical %}">
|
||||
|
||||
<!-- Open Graph -->
|
||||
<meta property="og:site_name" content="{{ config.title }}">
|
||||
<meta property="og:title" content="{% block og_title %}{{ config.title }}{% endblock og_title %}">
|
||||
<meta property="og:description" content="{% block og_description %}{{ config.description }}{% endblock og_description %}">
|
||||
<meta property="og:url" content="{% block og_url %}{{ config.base_url }}/{% endblock og_url %}">
|
||||
<meta property="og:type" content="{% block og_type %}website{% endblock og_type %}">
|
||||
<meta property="og:locale" content="en_US">
|
||||
<meta property="og:image" content="{% block og_image %}{{ config.base_url }}/images/og-image.png{% endblock og_image %}">
|
||||
<meta property="og:image:width" content="1200">
|
||||
<meta property="og:image:height" content="630">
|
||||
<meta property="og:image:alt" content="{{ config.title }} — {{ config.description }}">
|
||||
{% block og_extra %}{% endblock og_extra %}
|
||||
|
||||
<!-- Twitter Card -->
|
||||
<meta name="twitter:card" content="summary_large_image">
|
||||
<meta name="twitter:site" content="{{ config.extra.twitter_handle | default(value="@andwati_") }}">
|
||||
<meta name="twitter:title" content="{% block twitter_title %}{{ config.title }}{% endblock twitter_title %}">
|
||||
<meta name="twitter:description" content="{% block twitter_description %}{{ config.description }}{% endblock twitter_description %}">
|
||||
<meta name="twitter:image" content="{% block twitter_image %}{{ config.base_url }}/images/og-image.png{% endblock twitter_image %}">
|
||||
{% block twitter_extra %}{% endblock twitter_extra %}
|
||||
|
||||
<!-- Theme initializer (runs before paint to avoid flash) -->
|
||||
<script>
|
||||
(function() {
|
||||
try {
|
||||
var storedTheme = localStorage.getItem('theme');
|
||||
var prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
|
||||
var shouldUseDark = storedTheme ? storedTheme === 'dark' : prefersDark;
|
||||
if (shouldUseDark) {
|
||||
document.documentElement.classList.add('dark');
|
||||
} else {
|
||||
document.documentElement.classList.remove('dark');
|
||||
}
|
||||
} catch (e) {
|
||||
document.documentElement.classList.add('dark');
|
||||
}
|
||||
})();
|
||||
</script>
|
||||
|
||||
<!-- SEO: WebSite + Person JSON-LD (sitewide graph) -->
|
||||
<script type="application/ld+json">
|
||||
{
|
||||
"@context": "https://schema.org",
|
||||
"@graph": [
|
||||
{
|
||||
"@type": "WebSite",
|
||||
"@id": "{{ config.base_url | safe }}/#website",
|
||||
"url": "{{ config.base_url | safe }}/",
|
||||
"name": {{ config.title | json_encode | safe }},
|
||||
"description": {{ config.description | json_encode | safe }},
|
||||
"inLanguage": "en-US"
|
||||
},
|
||||
{
|
||||
"@type": "Person",
|
||||
"@id": "{{ config.base_url | safe }}/#author",
|
||||
"name": {{ config.extra.author | json_encode | safe }},
|
||||
"url": "{{ config.base_url | safe }}/about/",
|
||||
"sameAs": [
|
||||
{% if config.extra.github_url %}"{{ config.extra.github_url | safe }}"{% if config.extra.twitter_url or config.extra.youtube_url %},{% endif %}{% endif %}
|
||||
{% if config.extra.twitter_url %}"{{ config.extra.twitter_url | safe }}"{% if config.extra.youtube_url %},{% endif %}{% endif %}
|
||||
{% if config.extra.youtube_url %}"{{ config.extra.youtube_url | safe }}"{% endif %}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
</script>
|
||||
|
||||
{% if config.extra.google_analytics %}
|
||||
<!-- Google Analytics -->
|
||||
<script async src="https://www.googletagmanager.com/gtag/js?id={{ config.extra.google_analytics }}"></script>
|
||||
<script>
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
function gtag(){dataLayer.push(arguments);}
|
||||
gtag('js', new Date());
|
||||
gtag('config', '{{ config.extra.google_analytics }}', { anonymize_ip: true });
|
||||
</script>
|
||||
{% endif %}
|
||||
|
||||
{% block head %}{% endblock head %}
|
||||
|
||||
<!-- Font preloads (eliminate FOUT on first paint) -->
|
||||
<link rel="preload" href="{{ get_url(path="fonts/source-serif-4/source-serif-4-v14-latin-regular.woff2") }}" as="font" type="font/woff2" crossorigin>
|
||||
<link rel="preload" href="{{ get_url(path="fonts/ibm-plex-serif/ibm-plex-serif-v20-latin-700.woff2") }}" as="font" type="font/woff2" crossorigin>
|
||||
|
||||
<!-- CSS -->
|
||||
<link rel="stylesheet" href="{{ get_url(path="main.css") }}">
|
||||
|
||||
<!-- Fonts (self-hosted) -->
|
||||
<link rel="stylesheet" href="{{ get_url(path="css/fonts.css") }}">
|
||||
|
||||
<!-- RSS Feed -->
|
||||
<link rel="alternate" type="application/rss+xml" title="{{ config.title }} RSS Feed" href="{{ get_url(path="rss.xml") }}">
|
||||
|
||||
</head>
|
||||
<body class="smooth-scroll">
|
||||
<div class="site-container">
|
||||
{% include "partials/header.html" %}
|
||||
|
||||
<main class="main-content">
|
||||
{% block content %}{% endblock content %}
|
||||
</main>
|
||||
|
||||
{% include "partials/footer.html" %}
|
||||
</div>
|
||||
<button id="scroll-to-top" class="scroll-to-top" aria-label="Scroll to top">
|
||||
<svg viewBox="0 0 24 24" width="24" height="24" stroke="currentColor" stroke-width="2" fill="none" stroke-linecap="round" stroke-linejoin="round">
|
||||
<polyline points="18 15 12 9 6 15"></polyline>
|
||||
</svg>
|
||||
</button>
|
||||
<!-- Search Modal Overlay -->
|
||||
<div id="search-overlay" class="search-overlay" aria-hidden="true">
|
||||
<div class="search-modal" role="dialog" aria-modal="true" aria-label="Search posts">
|
||||
<div class="search-header">
|
||||
<svg viewBox="0 0 24 24" width="18" height="18" stroke="currentColor" stroke-width="2" fill="none" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="8"></circle><line x1="21" y1="21" x2="16.65" y2="16.65"></line></svg>
|
||||
<input type="text" id="search-input" placeholder="{{ config.extra.search_placeholder | default(value="Search posts...") }}" autocomplete="off">
|
||||
</div>
|
||||
<div id="search-results" class="search-results"></div>
|
||||
<div class="search-footer">
|
||||
<span>Navigate: <kbd>↑</kbd> <kbd>↓</kbd></span>
|
||||
<span>Select: <kbd>Enter</kbd></span>
|
||||
<span>Close: <kbd>ESC</kbd></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Global Scripts -->
|
||||
<script defer src="{{ get_url(path="js/theme.js") }}"></script>
|
||||
<script defer src="{{ get_url(path="js/scroll-top.js") }}"></script>
|
||||
<script defer src="{{ get_url(path="js/copy-code.js") }}"></script>
|
||||
<!-- Search Scripts -->
|
||||
<script defer src="{{ get_url(path="js/elasticlunr.min.js") }}"></script>
|
||||
<script defer src="{{ get_url(path="js/search.js") }}"></script>
|
||||
|
||||
{% block scripts %}{% endblock scripts %}
|
||||
</body>
|
||||
</html>
|
||||