diff --git a/html/about.html b/html/about.html index 519c7fe..5d30967 100644 --- a/html/about.html +++ b/html/about.html @@ -1,7 +1,7 @@ - + About @@ -193,13 +193,8 @@ - - - + - - - @@ -226,7 +221,7 @@ If you have any comments about this page, you can email me at:
Proudly built using org-mode.
All code on this website is licensed GPLv3 unless otherwise indicated.

-[Valid RSS]
+[Valid RSS]
diff --git a/html/art/index.html b/html/art/index.html index a2ecbb7..536aea9 100644 --- a/html/art/index.html +++ b/html/art/index.html @@ -1,7 +1,7 @@ - + Akk0's Art @@ -193,13 +193,8 @@ - - - + - - - @@ -216,7 +211,7 @@
-
+
lone_rider.png
Figure 1: Lone Rider, 2024. I made this to get some of the anxiety out of my system while taking motorcycle lessons.
@@ -229,7 +224,7 @@ If you have any comments about this page, you can email me at:
Proudly built using org-mode.
All code on this website is licensed GPLv3 unless otherwise indicated.

-[Valid RSS]
+[Valid RSS]
diff --git a/html/events/index.html b/html/events/index.html index 7ac3e34..508835f 100644 --- a/html/events/index.html +++ b/html/events/index.html @@ -1,7 +1,7 @@ - + Events and Trips @@ -193,13 +193,8 @@ - - - + - - - @@ -215,33 +210,33 @@
-
-

Events and Trips

-
+
+

Events and Trips

+

Here I keep some memoirs of (mostly music) events I’ve helped organized, participated in, or attended; I’m putting trips I’ve gone on here as well.

-
-

Co-organized

-
+
+

Co-organized

+
-
-

Premier Impact

-
+
+

Premier Impact

+

A doujin music event in Paris which I helped organize!

-
-

Participated or Support Crew

-
+
+

Participated or Support Crew

+
-
-

Millennium Strike WROC.WAV + Wrocław trip

-
+
+

Millennium Strike WROC.WAV + Wrocław trip

+

I sorta-kinda was support crew here. Also includes general notes on my trip to the beautiful city of Wrocław, Poland.

@@ -257,7 +252,7 @@ If you have any comments about this page, you can email me at:
Proudly built using org-mode.
All code on this website is licensed GPLv3 unless otherwise indicated.

-[Valid RSS]
+[Valid RSS]
diff --git a/html/events/premier_impact.html b/html/events/premier_impact.html index 3a44ff4..1bfcae3 100644 --- a/html/events/premier_impact.html +++ b/html/events/premier_impact.html @@ -1,7 +1,7 @@ - + Premier Impact Retrospective @@ -193,13 +193,8 @@ - - - + - - - @@ -215,20 +210,20 @@
-
-

Premier Impact Retrospective

-
+
+

Premier Impact Retrospective

+
-
-

Introduction

-
+
+

Introduction

+

This is a retrospective on Premier Impact, a music event we held on the 10th of May 2025.

-
+
premier_impact_poster.png
Figure 1: Event poster. I participated under the alias “Sakka”.
@@ -236,13 +231,13 @@ This is a retrospective on Premier I
-
-

Organisation

-
+
+

Organisation

+
-
-

Context

-
+
+

Context

+

A bit of context that’ll help illustrate some of the organisational difficulties involved in the event:

@@ -259,9 +254,9 @@ The observant reader might notice that this is a bit of a tight squeeze; it coul

-
-

Motivation, Branding & Concept

-
+
+

Motivation, Branding & Concept

+

The event theme was doujin music and generally J-core/breakcore/anison, though in practice we gave DJs complete free reign as to what to play and the event was better characterized as “we invite our friends to play good music”; it’s perhaps best understood in relationship to other similar events2. These events are already common elsewhere, but not aren’t yet established in France, despite there clearly existing a sizeable audience for them — our aim was thus to start putting this on the map here in Paris.

@@ -275,9 +270,9 @@ For the poster we ended up borrowing a lot from the -

Searching for a Venue

-
+
+

Searching for a Venue

+

Since this was our first event3 we went into this without existing contacts and without a confirmed audience. Largely because of this4 we mostly committed to finding a venue that would let us host the event for free.

@@ -315,7 +310,7 @@ One place that was open to talks with us was the awesome -
+
spot13_1.jpg
@@ -323,7 +318,7 @@ One place that was open to talks with us was the awesome
-
+
spot13_2.jpg
@@ -348,17 +343,17 @@ At the time we seriously considered the logistics of this — with less tha

-
-

Finding a Venue

-
+
+

Finding a Venue

+

We originally got a reply from Les Amarres on April 4th, so we were in communication with both them and Spot 13 in parallel, but we only got confirmation they’d be available on April 15th. They let us hold the event in their venue for free, so accepting immediately was a no-brainer. They even gave our staff free drinks and meals11!

-
-

Staff and Promotion

-
+
+

Staff and Promotion

+

Only now that we had a venue we ready to formally invite guest DJs and start putting publicity out. Promo went out on April 24th, less than 2.5 weeks until the event.

@@ -369,16 +364,16 @@ I want to give massive thanks to Ed for agreeing to take over the slot that my s
-
-

Event Day

-
+
+

Event Day

+
-
-

The Venue; Setting Up

-
+
+

The Venue; Setting Up

+
-
+
pi_les_amaress.jpg
Figure 2: The venue, Les Amarres.
@@ -391,7 +386,7 @@ We arrived at the venue 2 hours early, and we needed every minute of that time,
-
+
pi_empty.jpg
Figure 3: … like this.
@@ -408,7 +403,7 @@ Anyhow, the place was a maze — from what I hear Apt drew a little map to
-
+
pi_setup.jpg
Figure 4: All set up. The big subwoofer in the corner took four men to carry up the stairs; on the way back down after the event we used the elevator we had then learned exists.
@@ -420,12 +415,12 @@ A big shout out to Shiz for actually knowing what he was doing and setting up al

-
-

The Event

-
+
+

The Event

+
-
+
pi_party.jpg
Figure 5: Ravers. This picture is in the midst of the TECHNICAL DIFFICULTIES of next section.
@@ -437,9 +432,9 @@ The event was, by all means, a smashing success. Being a free event it&rs

-
-

TECHNICAL DIFFICULTIES; Our Act

-
+
+

TECHNICAL DIFFICULTIES; Our Act

+

Those that were present around the end of the event might have seen Apt and I frantically faffing about with two DJ controllers, three laptops and a bass guitar. We ran into two kinds of technical issues during our set.

@@ -470,9 +465,9 @@ The GK-3B is pretty expensive so we had bought it with the intention of using it
-
-

Closing Words

-
+
+

Closing Words

+

Looking critically, behind the scenes—and to some extend unfortunately also on the stage—this was an organisational mess. Some of this definitely could’ve been prevented – Apt and I take full responsibility for the original error of failing to secure a venue in time. Other hecticness in the planning wasn’t really preventable—there’s a reason this post opens with a description of our schedule—but will be avoided in the future. It was a learning experience for sure.

@@ -510,7 +505,7 @@ And You, The Reader, for bearing with my doubtlessly excessive wordiness.
-
+
pi_congratulations.png
Figure 6: And to all children, congratulations.
@@ -519,8 +514,8 @@ And You, The Reader, for bearing with my doubtlessly excessive wordiness.
-
-

Set Rerecordings

+
+

Set Rerecordings

@@ -561,7 +556,7 @@ If you have any comments about this page, you can email me at:
Proudly built using org-mode.
All code on this website is licensed GPLv3 unless otherwise indicated.

-[Valid RSS]
+[Valid RSS]
diff --git a/html/events/wroclaw.html b/html/events/wroclaw.html index 4bdf849..b1e696c 100644 --- a/html/events/wroclaw.html +++ b/html/events/wroclaw.html @@ -1,7 +1,7 @@ - + Wrocław/Millennium Strike @@ -193,13 +193,8 @@ - - - + - - - @@ -215,20 +210,20 @@
-
-

Wrocław/Millennium Strike WROC.WAV

-
+
+

Wrocław/Millennium Strike WROC.WAV

+
-
-

Arriving

-
+
+

Arriving

+

Alex, apt-get, mercury.lamp, pachy and myself were in Wrocław1, Poland between April 30th and May <END DATE> for Millennium Strike Live WROC.WAV where apt and merc were performing (B2B, under alias Re;iwa Diabolik). Shout out to pachy for finding time and money to join us last minute; I am very very glad he was able to be there, it wouldn’t have been the same without him.

-
+
wroclaw_boys.jpg
Figure 1: Quake III was a good game.
@@ -245,7 +240,7 @@ We had a bunch of gear to transport and were trying to limit luggage charges, so
-
+
wroc_bags.jpg
Figure 2: Finding suitable bags.
@@ -254,7 +249,7 @@ We had a bunch of gear to transport and were trying to limit luggage charges, so
-
+
poland_plane.jpg
Figure 3: Poland from above.
@@ -262,16 +257,16 @@ We had a bunch of gear to transport and were trying to limit luggage charges, so
-
-

Setcrafting

-
+
+

Setcrafting

+

Basically all the time in Wrocław before the event was spent on… actually preparing the set, which hadn’t really been started yet, so we were mostly inside the hotel — this had much to do with apt and I being busy preparing for Premier Impact and everyone just generally being busy. Alex, pachy and I were technically free, but I was also trying to make stuff happen for Premier Impact still, and we all kinda hung around for moral support.

-
+
setcrafting_wroc.jpg
Figure 4: Cowboy Bebop at his computer Setcrafting.
@@ -279,12 +274,12 @@ Basically all the time in Wrocław before the event was spent on… actuall
-
-

The Event

-
+
+

The Event

+
-
+
milstrike_wroc.jpg
Figure 5: Event poster.
@@ -297,7 +292,7 @@ The venue for the event was a club called Transformator. Pretty cool place, good
-
+
transformator_backstage.jpg
Figure 6: Backstage at Transformator
@@ -310,7 +305,7 @@ The itself event was a lot of fun. Nothing much particular to say, other than th
-
+
milstrike_merc.jpg
Figure 7: Merc is always so photogenic.
@@ -322,24 +317,24 @@ Unfortunately as the event was winding down (in the early morning, I think aroun

-
-

Wrocław

-
+
+

Wrocław

+
-
-

Pleasant Surprise

-
+
+

Pleasant Surprise

+

With us primarily being there for the event and it being a really busy period, I don’t think any of us had really read up on the city very much. Safe to say we were all very pleasantly surprised! Wrocław is an absolutely lovely city; real student town energy with lots of young people, very warm hospitality and a very homely, casual atmosphere in restaurants as well.

-
-

Food and Drink

-
+
+

Food and Drink

+
-
+
poland_food.jpg
Figure 8: Delicious.
@@ -355,9 +350,9 @@ Food prices were maybe about half what you’d find in an equivalent western

-
-

Architecture, Cityscape

-
+
+

Architecture, Cityscape

+

Wrocław has really cool architecture, a pretty eclectic mix of styles and old and new stuff. Lots of old defensive works that I believe were built after the Mongol invasion. Quoting Wikipedia:

@@ -378,7 +373,7 @@ Lots of beautiful brickwork which is a style of architecture I have not encounte
-
+
wroc_architecture1.jpg
@@ -391,7 +386,7 @@ There was something very familiar about the layout of the city and the style of
-
+
wroc_architecture2.jpg
@@ -403,7 +398,7 @@ The streets are broad, well-maintained and very clean. There’s good public
-
+
wroc_architecture4.jpg
@@ -415,7 +410,7 @@ The nighttime atmosphere was very pleasant as well, perhaps owning to the high s
-
+
wroc_street.jpg
@@ -427,7 +422,7 @@ We were there at the same time as the largest guitar festival in the world. Guit
-
+
wroc_guitars.jpg
Figure 9: That’s a lot of guitars. We didn’t really have the time to hang around unfortunately, and as you can see it was very busy anyhow.
@@ -435,16 +430,16 @@ We were there at the same time as the largest guitar festival in the world. Guit
-
-

People, History and Closing Notes

-
+
+

People, History and Closing Notes

+

Overall Wrocławians made a strong impression on me as warm, hospitable, humorous and headstrong people. Wrocław had a very active anti-communist resistance that they are very proud of, and they’ve kept that history very alive, both visibly in the city scape but also in their endearing fashion sense.

-
+
wroc_dwarf.jpg
Figure 10: The Wrocław Dwarves that abound in the cityscape are emblematic of the resistence. Their appearance traces directly from Dutch kabouters, so they were a strangely familiar sight.
@@ -488,7 +483,7 @@ If you have any comments about this page, you can email me at:
Proudly built using org-mode.
All code on this website is licensed GPLv3 unless otherwise indicated.

-[Valid RSS]
+[Valid RSS]
diff --git a/html/friends.html b/html/friends.html index 806b6e4..2e12eec 100644 --- a/html/friends.html +++ b/html/friends.html @@ -1,7 +1,7 @@ - + Friends @@ -193,13 +193,8 @@ - - - + - - - @@ -231,7 +226,7 @@ If you have any comments about this page, you can email me at:
Proudly built using org-mode.
All code on this website is licensed GPLv3 unless otherwise indicated.

-[Valid RSS]
+[Valid RSS]
diff --git a/html/index.html b/html/index.html index 7d06669..0af86ae 100644 --- a/html/index.html +++ b/html/index.html @@ -1,7 +1,7 @@ - + Index @@ -193,13 +193,8 @@ - - - + - - - @@ -215,9 +210,9 @@
-
-

Hello There!

-
+
+

Hello There!

+

Welcome to my website! I’m akk0. I blog about Emacs, programming, meditation, otaku stuff, and other things that interest me. You can view the full list of pages on the sitemap.

@@ -230,23 +225,24 @@ This site launched recently and is still under construction; please pardon the d Here’s this week’s journal!

-
-

Pro Tips

-
+
+

Pro Tips

+
  • You can fold and unfold sections by clicking the headline. Try it!
  • Click on any cell with a dotted outline in the habit tracker to see my journal entry for it. The currently selected cell will be highlighted in pink.
-
-

Habits

-
+
+

Habits

+

-Today is Monday, 10th November. +Today is Thursday, 20th November.

+ @@ -255,27 +251,7 @@ Here’s this week’s journal! - - - - - - - - - - - @@ -287,7 +263,7 @@ Here’s this week’s journal! data-status="YES">● - @@ -309,35 +285,35 @@ Here’s this week’s journal! data-status="YES">● - + + + + + + + + + + - - - - - - - - - - + + + + + + + + + + - - - - - - - - - - - @@ -439,29 +415,29 @@ Here’s this week’s journal! data-status="YES">● + + + + + + + + + + - - - - - - - - - - - + + + + + + + + + + - - - - - - - - - - + + + + + + + + + + - - - - - - - - - - - - @@ -628,29 +604,29 @@ Here’s this week’s journal! data-status="NO">× + + + + + + + + + + - - - - - - - - - - + + + + + + + + + + - - - - - - - - - - - @@ -752,21 +728,40 @@ Here’s this week’s journal! data-status="YES">● - + + + + + + + + + +
Blogging ×× ×
Meditation journal! data-status="YES">● ×××
French ××× ××
Engineering×× journal! data-status="YES">● ×
Exercise journal! data-status="YES">● ×
Drawing ×××× × ××××××
Reading journal! data-status="NO">× ×××××
Social ×
- -Key: -Unknown | -× No | -● Yes | -♦ Excellent | -♣ Freed Up +Key: +Unknown | +× No | +● Yes | +♦ Excellent | +♣ Freed Up
-
-
+
+
This section intentionally left blank.
@@ -775,13 +770,13 @@ Here’s this week’s journal!
- diff --git a/html/journal/index.html b/html/journal/index.html index 3ecaa2f..442f992 100644 --- a/html/journal/index.html +++ b/html/journal/index.html @@ -1,7 +1,7 @@ - + Journal @@ -193,13 +193,8 @@ - - - + - - - @@ -223,7 +218,7 @@ If you have any comments about this page, you can email me at:
Proudly built using org-mode.
All code on this website is licensed GPLv3 unless otherwise indicated.

-[Valid RSS]
+[Valid RSS]
diff --git a/html/journal/template.html b/html/journal/template.html index dc4f6c1..9185f56 100644 --- a/html/journal/template.html +++ b/html/journal/template.html @@ -1,7 +1,7 @@ - + Journal Week XX, YYYY @@ -193,13 +193,8 @@ - - - + - - - @@ -220,22 +215,22 @@ Previous | Index

-
-

Journal Week XX, YYYY

-
+
+

Journal Week XX, YYYY

+
-
-

Monday, ZZth MMMM

-
+
+

Monday, ZZth MMMM

+

NO Journal

-
-

Habits   autocollapse

-
+
+

Habits   autocollapse

+
NO Meditation
@@ -283,7 +278,7 @@ If you have any comments about this page, you can email me at:
Proudly built using org-mode.
All code on this website is licensed GPLv3 unless otherwise indicated.

-[Valid RSS]
+[Valid RSS]
diff --git a/html/journal/w27-2025-30.06-06.07-journal.html b/html/journal/w27-2025-30.06-06.07-journal.html index c269fe9..07948be 100644 --- a/html/journal/w27-2025-30.06-06.07-journal.html +++ b/html/journal/w27-2025-30.06-06.07-journal.html @@ -1,7 +1,7 @@ - + Journal Week 27 2025 @@ -193,13 +193,8 @@ - - - + - - - @@ -215,52 +210,52 @@
-
-

Journal Week 27, 2025 (June 30 to July 06)

-
+
+

Journal Week 27, 2025 (June 30 to July 06)

+
-
-

Thursday, July 3rd

-
+
+

Thursday, July 3rd

+
-
-

Dailies

-
+
+

Dailies

+
-
-
DONE Meditation
-
+
+
DONE Meditation
+

Only about 10 minutes, in the park. It’s been a while, so I’ll slowly build up to 30 mins of good practice a day again and just try to hang there for a few months. Might pick up a Brightmind subscription again, though I can’t afford to pay for one right now.

-
-
DONE Walk 5000 steps
-
+
+
DONE Walk 5000 steps
+

Just shy of 12000 on the pedometer, getting to the park and around the neighborhood.

-
-
DONE Runescape
-
+
+
DONE Runescape
+

Completed The Feud on the GIM. Just questing up a bit still, trying to get Agility XP in as well as working up towards fairy rings.

-
-

Journal

-
+
+

Journal

+

First day back from holiday visiting my family. Today I repaired the bedroom shelf, installed a longer duct on the portable AC so it can be used in the bedroom more easily as well as installed the AC-window-thing. The longer duct works alright, you can tell the little AC is a little underpowered for a duct that long and it’s leaking some heat.

-
+
duct_taped.jpg
Figure 1: Duct, taped.
@@ -279,48 +274,48 @@ Things learned today:
-
-

Friday, July 4th

-
+
+

Friday, July 4th

+
-
-

Daillies

-
+
+

Daillies

+
-
-
DONE Meditation
-
+
+
DONE Meditation
+

~20 minutes breath meditation

-
-
DONE Walk 5000 steps
-
+
+
DONE Walk 5000 steps
+

Slightly north of 12k steps.

-
-
CANCELLED Runescape
-
+
+
CANCELLED Runescape
+

Just didn’t have the time today!

-
-

Journal

-
+
+

Journal

+

Didn’t sleep very well so I ended up staying in bed until 11 or so today. Exercise-heavy day; spent close to an hour in the gym and swam for ~30 minutes. For lunch I made stir fried vegetables with a lot of tofu, flavored with laoganma, doubanjiang and ground sichuan pepper — I like this recipe, especially given that I’m trying to eat more protein. I highly recommend laoganma, it goes well with a lot of things, by the way​~.

-
+
cat_teto.jpg
Figure 2: Picture of the Day!
@@ -335,7 +330,7 @@ We ended up buying the Huion Kamvas for €70, including pen, stand and cables & -
+
osrs_huion.jpg
Figure 3: This also gives me a (small) secondary monitor for the first time in half a year, which is something I’ve really missed.
@@ -346,7 +341,7 @@ I finally got around to hanging up the canvas print of my picture my mom got me!

-
+
canvas_framed_bedroom.jpg
Figure 4: Here you can also see the shelf I talked about yesterday — the little triangles at the bottom are not load-bearing and don’t attach to the wall (there’s metal angle brackets screwed into the concrete wall for that) but do serve to stabilize it.
@@ -358,7 +353,7 @@ Also, in the process of setting up the tablet I opened up Krita and rediscovered

-
+
lone_rider.png
Figure 5: Lone Rider, 2024.
@@ -370,35 +365,35 @@ Accordingly, I’ve added an art section to
-
-

Saturday, July 5th

-
+
+

Saturday, July 5th

+
-
-

Dailies

-
+
+

Dailies

+
-
-
DONE Meditation
-
+
+
DONE Meditation
+

~25 minutes walking meditation.

-
-
DONE Walk 5000 steps
-
+
+
DONE Walk 5000 steps
+

13.7k

-
-
DONE Runescape
-
+
+
DONE Runescape
+
-
+
rs_quest_doti.png
@@ -409,11 +404,11 @@ This reward feels kind of overpowered, though I guess it still doesn’t com
-
-

Journal

-
+
+

Journal

+
-
+
japan_expo_aura.jpg
Figure 6: Two gentlemen “giving aura”, as the kids say.
@@ -424,14 +419,14 @@ Japan Expo today! I’m glad we got to go in the end despite complaining abo

-
+
japan_expo_loot_2025.jpg
Figure 7: Loot.
-
+
laptop_stickers_june_2025.jpg
Figure 8: Glad to add some more color to my laptop stickers. Sticker credit: Progress (logo), Suzu (logo), apt-get (untz), Sauce (possum).
@@ -442,78 +437,78 @@ Always feels good to support local small artisans. It’s interesting to see

-
+
je2025cosp1.jpg
-
+
je2025cosp2.jpg
-
+
je2025cosp3.jpg
-
+
je2025cosp4.jpg
-
+
je2025cosp5.jpg
-
+
je2025cosp6.jpg
-
+
je2025cosp7.jpg
-
-

TODO Credit sauce properly

+
+

TODO Credit sauce properly

-
-

TODO Align cosplays

+
+

TODO Align cosplays

-
-

Sunday, July 6th

-
+
+

Sunday, July 6th

+
-
-

Dailies

-
+
+

Dailies

+
-
-
DONE Meditation
-
+
+
DONE Meditation
+

12 min breath.

-
-
DONE Walk 5000 steps
-
+
+
DONE Walk 5000 steps
+

The weather was horrid today, so only barely.

-
-
DONE Runescape
-
+
+
DONE Runescape
+
-
+
osrs_stats_w27.png
Figure 9: Stats as of today.
@@ -525,15 +520,15 @@ Next up is The Dig Site, then Elemental Workshop I & II
-
-

Journal

-
+
+

Journal

+
-
-
Market
-
+
+
Market
+
-
+
market_pierogi.jpg
@@ -544,11 +539,11 @@ These pierogi are alright, but I miss the ones in -
Mahoako
-
+
+
Mahoako
+
-
+
baiser_sorry.jpg
@@ -558,9 +553,9 @@ I’ve been reading
-
Hover notes2
-
+
+
Hover notes2
+

Today I added support for footnotes3! The hover functionality requires a bit of JS, but the footnotes themselves should work just fine without JS.

@@ -589,7 +584,7 @@ If you have any comments about this page, you can email me at:
Proudly built using org-mode.
All code on this website is licensed GPLv3 unless otherwise indicated.

-[Valid RSS]
+[Valid RSS]
diff --git a/html/journal/w28-2025.html b/html/journal/w28-2025.html index 1c0cea4..592911e 100644 --- a/html/journal/w28-2025.html +++ b/html/journal/w28-2025.html @@ -1,7 +1,7 @@ - + Akk0's journal, week 28, 2025 @@ -193,13 +193,8 @@ - - - + - - - @@ -215,21 +210,21 @@
-
-

Journal Week 28, 2025 (July 7 to 13) (suspended early)

-
+
+

Journal Week 28, 2025 (July 7 to 13) (suspended early)

+
-
-

Monday, July 7

-
+
+

Monday, July 7

+
-
-

Dailies

-
+
+

Dailies

+
-
-
DONE Exercise
-
+
+
DONE Exercise
+
  • Stationary bike 40 min/16km
  • Cable Fly machine 3x6x40kg
  • @@ -247,51 +242,51 @@ Whew, that was an intense day.
-
-
DONE Meditation
-
+
+
DONE Meditation
+

Bit of walking meditation on the way to the pool, maybe ~15 mins.

-
-
DONE Runescape
-
+
+
DONE Runescape
+

Completed Dig Site and both Elemental Workshop​s last night. Next up is Woodcutting for Lost City. I was gonna be smart and have my GIM buddy help me skip the WC requirement on Fremennik Isles for the 10k XP but he’s busy, so I guess soon will be my first bit of actual training in quite a while.

-
-
DONE French
-
+
+
DONE French
+

Gonna add this to the rotation and mark it “done” for today though I mostly thought about it on a meta level. Tomorrow I’ll try and write up a bit of it and set up a bit of a study plan.

-
-

Journal

-
+
+

Journal

+

Mostly been preoccupied with exercise today, so not much to report.

-
-

Tuesday, July 8th

-
+
+

Tuesday, July 8th

+
-
-

Dailies

-
+
+

Dailies

+
-
-
DONE Exercise
-
+
+
DONE Exercise
+
  • Stationary bike 18km
  • The uhh abdominal back and forth thing (my baka-ass didn’t note what it’s called), 4x10x35kg
  • @@ -301,46 +296,46 @@ Mostly been preoccupied with exercise today, so not much to report.
-
-
DONE Meditation
-
+
+
DONE Meditation
+

Mainly daily life practice/morality stuff, but good stuff at that so I’ll count it – plus the exercise bike has been rather meditative.

-
-
DONE Runescape
-
+
+
DONE Runescape
+

Completed Lost City. Forestry is good new content, I love it! My bf is making fun of what qualifies as “content” to runescape players, ww.

-
-
CANCELLED French
-
+
+
CANCELLED French
+

FOrgor

-
-

Journal

-
+
+

Journal

+
-
-
Exercise
-
+
+
Exercise
+

Another heavy exercise day! I feel good, the mind is sharp, but the body definitely needs a lot of recovery on days like this and energy comes in starts and stops. Next two days are rest days, at least! Honestly mixed feelings on rest days, they’re necessary but I’ve actually been really enjoying pushing the body ww. I’m surprised how quickly the body is adapting to the exercise load, but that’s being a man in his 20s for ya.

-
-
Career
-
+
+
Career
+

It’s not much of a surprise, but I got word that I got rejected for all the MSc programmes I applied to. It’s a shame — there’s only a handful of English-taught compsci Master’s programmes around here, and unlike in my home country they have very limited availability and are highly selective (in my home country getting into an MSc is essentially a rubber stamp if you have a BSc, so academic record is pretty mediocre).

@@ -364,60 +359,60 @@ I’ve started more seriously considering a career for the good cause, worki
-
-

Wednesday, July 9th

-
+
+

Wednesday, July 9th

+
-
-

Dailies

-
+
+

Dailies

+
-
-
DONE Exercise
-
+
+
DONE Exercise
+

Not sure how many steps but I walked to the park and back (my phone was dead).

-
-
DONE Meditation
-
+
+
DONE Meditation
+

Breath meditation in the park, and walking meditation on the way back.

-
-
DONE Runescape
-
+
+
DONE Runescape
+

Completed Restless Ghost and Lost City.

-
-
CANCELLED French
-
+
+
CANCELLED French
+

Just kinda slipped through in all the commotion.

-
-

Journal

-
+
+

Journal

+
-
-
Ultraman
-
+
+
Ultraman
+

Meet Ultraman, the latest member of the family:

-
+
ultraman.jpg
Figure 1: Named in honor of the lady who in Tokyo told us in quiet confidence that Ultraman is her son. Don’t worry, I cleaned him up again after this!
@@ -432,9 +427,9 @@ I really hope he recovers well.

-
-
Master’s
-
+
+
Master’s
+

I’ve sent an appeal email regarding my rejection from the Master’s programmes I applied to at IP Paris. I’ve reproduced the email on this blog because I think the information contained within is interesting and because I think it’s a good letter.

@@ -442,10 +437,10 @@ I’ve sent an appeal email rega
-
-

Thursday, July 10th

-
-
+
+

Thursday, July 10th

+
+

Q: How is Ultraman doing?

@@ -470,7 +465,7 @@ If you have any comments about this page, you can email me at:
Proudly built using org-mode.
All code on this website is licensed GPLv3 unless otherwise indicated.

-[Valid RSS]
+[Valid RSS]
diff --git a/html/journal/w29-2025.html b/html/journal/w29-2025.html index c0cf9f8..a741d07 100644 --- a/html/journal/w29-2025.html +++ b/html/journal/w29-2025.html @@ -1,7 +1,7 @@ - + Journal Week 29, 2025 (July 14 to 20) @@ -193,13 +193,8 @@ - - - + - - - @@ -215,20 +210,20 @@
-
-

Journal Week 28, 2025 (July 14 to 20)

-
+
+

Journal Week 28, 2025 (July 14 to 20)

+
-
-

Thursday - Thursday, July 10th - 17th

-
+
+

Thursday - Thursday, July 10th - 17th

+

Just kinda lumping these together as I left a bit of a hiatus in the journaling and let things slip a little bit, mostly a consequence of working too hard the week prior.

-
-

Thursday, July 10th

-
+
+

Thursday, July 10th

+

As alluded to in last week’s journal, Ultraman passed away around midnight. He was recovering strength fast throughout the day, but started going backwards fast starting from around 6PM, ultimately passing away some six hours later. I will write up his full story.

@@ -238,17 +233,17 @@ Other than that, Thursday was a normal day.

-
-

Friday - Sunday

-
+
+

Friday - Sunday

+

I took friday off and then spent the weekend doing normal weekend things. I needed some recovery; been going at it too hard with exercise.

-
-

Monday

-
+
+

Monday

+

Bastille day! We threw a bit of a party at home and had fun. The Eiffel Tower fireworks/drone show was very beautiful this year. I was also very impressed by the Indonesian division at the military parade.

@@ -270,26 +265,26 @@ Bastille day! We threw a bit of a party at home and had fun. The Eiffel Tower fi
-
-

Tue - Wed

-
+
+

Tue - Wed

+

Spent most of Tuesday just resting since I went a bit too hard on Monday and stayed up too late. Wednesday I was feeling a lot of physical malaise but I managed to drag myself to the pool and felt better after that. I definitely notice a couple days of unhealthy living and lack of exercise.

-
-

Thu

-
+
+

Thu

+

Put everything back into order, cleaned the house, did a lot of exercise. Also worked on the blog a lot. Goal is to officially launch the blog on the 27th, now.

-
-

Friday, July 18th

-
+
+

Friday, July 18th

+

Back to full power today. Gonna leave the daily logs off until next week.

@@ -299,23 +294,23 @@ Lot of exercise — gonna stay with machines for another week and then move

-
-

Saturday, July 19th

-
+
+

Saturday, July 19th

+

Exhausted from yesterday’s exercise hehe. Dusted off the EMPTYHEAD today, going through the code and explaining it to my co-dev-to-be. Looking forward to picking this back up — more to follow soon. Restful Saturday otherwise.

-
-

TODO Link EMPTYHEAD

+
+

TODO Link EMPTYHEAD

-
-

Sunday, July 20th

-
+
+

Sunday, July 20th

+
-
+
end_sky_day_2025.jpg
Figure 1: Happy End Sky Day!
@@ -327,19 +322,19 @@ Went to see some gardens/greenhouses today, otherwise a restful Sunday as well.

-
+
greenhouse07251.jpg
-
+
greenhouse07252.jpg
-
+
greenhouse07253.jpg
@@ -354,7 +349,7 @@ If you have any comments about this page, you can email me at:
Proudly built using org-mode.
All code on this website is licensed GPLv3 unless otherwise indicated.

-[Valid RSS]
+[Valid RSS]
diff --git a/html/journal/w30-2025.html b/html/journal/w30-2025.html index 152b1d6..8fffffe 100644 --- a/html/journal/w30-2025.html +++ b/html/journal/w30-2025.html @@ -1,7 +1,7 @@ - + Journal Week 30, 2025 @@ -193,13 +193,8 @@ - - - + - - - @@ -215,29 +210,29 @@
-
-

Journal Week 30, 2025 (July 21 to 27)

-
+
+

Journal Week 30, 2025 (July 21 to 27)

+
-
-

Monday, July 21st

-
+
+

Monday, July 21st

+

Restless legs syndrome caused me to not sleep all night, so it was a bit of a struggle day for a while. I did drag myself to the gym and used the stationary bike for a full hour — quite impressed with myself!

-
+
stationary_bike_1hr.jpg
-
-

Tuesday, July 22nd

-
+
+

Tuesday, July 22nd

+

I actually slept well today, thank god.

@@ -247,9 +242,9 @@ I wrote a post about my travels to Wrocław

-
-

Wednesday, July 23rd.

-
+
+

Wednesday, July 23rd.

+

Started writing a retrospective about Premier Impact.

@@ -264,7 +259,7 @@ If you have any comments about this page, you can email me at:
Proudly built using org-mode.
All code on this website is licensed GPLv3 unless otherwise indicated.

-[Valid RSS]
+[Valid RSS]
diff --git a/html/journal/w31-2025.html b/html/journal/w31-2025.html index a4ec7ab..c799ba2 100644 --- a/html/journal/w31-2025.html +++ b/html/journal/w31-2025.html @@ -1,7 +1,7 @@ - + Journal Week 31, 2025 @@ -193,13 +193,8 @@ - - - + - - - @@ -215,77 +210,77 @@
-
-

Journal Week 31, 2025 (July 28 to August 3)

-
+
+

Journal Week 31, 2025 (July 28 to August 3)

+
-
-

Wednesday, July 30th

-
+
+

Wednesday, July 30th

+
-
-

Daily Planning

-
+
+

Daily Planning

+
-
-
DONE Call grandparents
+
+
DONE Call grandparents
-
-
DONE Look for work
+
+
DONE Look for work
-
-
TODO 2 pages Le Petit Prince
+
+
TODO 2 pages Le Petit Prince
-
-
DONE Clean house
+
+
DONE Clean house
-
-
DONE Finish writing Premier Impact retrospective
+
+
DONE Finish writing Premier Impact retrospective
-
-
TODO Start graphic redesign website
+
+
TODO Start graphic redesign website
-
-
DONE Clean browser tabs
+
+
DONE Clean browser tabs
-
-
DONE Set up hobby desk
+
+
DONE Set up hobby desk
-
-
DONE Motorcycle ride
+
+
DONE Motorcycle ride
-
-

Journal

-
+
+

Journal

+

Busy day today. Haven’t kept up with journaling for a few days – must be the poor sleep. I finished the Premier Impact retrospective today. Tried looking for work but my LinkedIn account, which I made yesterday, got blocked due to suspicious behaviour; still did a bunch of planning. I got a 3D printer (Creality Ender 3 V3 SE) yesterday — amazing product, very fun, will write more soon. RIP Ozzy Osbourne, Hulk Hogan and Shunsaku Tamiya.

-
-

Thursday, July 31st

-
+
+

Thursday, July 31st

+
-
-

Daily Planning

-
+
+

Daily Planning

+
-
-
DONE 3 pages Le Petit Prince
+
+
DONE 3 pages Le Petit Prince
-
-
TODO Graphic redesign of website
+
+
TODO Graphic redesign of website
-
-
TODO Continue Honeycomb Storage Wall
+
+
TODO Continue Honeycomb Storage Wall
-
-
TODO Write a blog post
+
+
TODO Write a blog post
-
-
TODO Look for workies
+
+
TODO Look for workies
@@ -298,7 +293,7 @@ If you have any comments about this page, you can email me at:
Proudly built using org-mode.
All code on this website is licensed GPLv3 unless otherwise indicated.

-[Valid RSS]
+[Valid RSS]
diff --git a/html/journal/w41-2025.html b/html/journal/w41-2025.html index 89a788f..4b6734f 100644 --- a/html/journal/w41-2025.html +++ b/html/journal/w41-2025.html @@ -1,7 +1,7 @@ - + Journaly Week 41, 2025 @@ -193,13 +193,8 @@ - - - + - - - @@ -215,82 +210,82 @@
-
-

Journal Week 41, 2025 (5 – 12 October)

-
+
+

Journal Week 41, 2025 (5 – 12 October)

+
-
-

Wednesday, 8th October

-
+
+

Wednesday, 8th October

+
-
-

Daily Planning

-
+
+

Daily Planning

+
-
-
DONE Walkie
+
+
DONE Walkie
-
-
DONE Call mom
+
+
DONE Call mom
-
-
DONE Work on bloggie
+
+
DONE Work on bloggie
-
-
TODO Get started on Category Theory bookie
+
+
TODO Get started on Category Theory bookie
-
-
TODO Earn my sticker
+
+
TODO Earn my sticker
-
-
TODO Groceries
+
+
TODO Groceries
-
-
DONE Meditate
+
+
DONE Meditate
-
-

Journal

-
+
+

Journal

+

Phew it’s been a few weeks. It’s the end of the “guy occasionally mumbles to himself in the corner” era of this website… Webbieweb.org is close enough to “launched” that select people are already getting links to it now. The domain is new and so is the design.

-
-

Thursday, 9th October

-
+
+

Thursday, 9th October

+
-
-

Daily Planning

-
+
+

Daily Planning

+
-
-
DONE Earn my sticker (French)
+
+
DONE Earn my sticker (French)
-
-
TODO 3D Printy
+
+
TODO 3D Printy
-
-
TODO Write one bloggie page
+
+
TODO Write one bloggie page
-
-
TODO Start Category Theory
+
+
TODO Start Category Theory
-
-
DONE Exercise
+
+
DONE Exercise
-
-
DONE Development
+
+
DONE Development
-
-
DONE Meditate
+
+
DONE Meditate
-
-

Journal

-
+
+

Journal

+

Sleep rhythm is pretty stabilized right now. Feeling kinda sick; feverish. Working on picking good habits back up.

@@ -318,7 +313,7 @@ If you have any comments about this page, you can email me at:
Proudly built using org-mode.
All code on this website is licensed GPLv3 unless otherwise indicated.

-[Valid RSS]
+[Valid RSS]
diff --git a/html/journal/w42-2025.html b/html/journal/w42-2025.html index bd1c4ed..9ee3063 100644 --- a/html/journal/w42-2025.html +++ b/html/journal/w42-2025.html @@ -1,7 +1,7 @@ - + Journal Week 42, 2025 @@ -193,13 +193,8 @@ - - - + - - - @@ -215,13 +210,13 @@
-
-

Journal Week 42, 2025

-
+
+

Journal Week 42, 2025

+
-
-

Thursday, 16th October

-
+
+

Thursday, 16th October

+

YES Exercise

@@ -254,9 +249,9 @@
-
-

Friday, 17th October

-
+
+

Friday, 17th October

+

EXCELLENT Exercise

@@ -294,9 +289,9 @@
-
-

Sunday, 19th October

-
+
+

Sunday, 19th October

+

YES Exercise

@@ -343,7 +338,7 @@ If you have any comments about this page, you can email me at:
Proudly built using org-mode.
All code on this website is licensed GPLv3 unless otherwise indicated.

-[Valid RSS]
+[Valid RSS]
diff --git a/html/journal/w43-2025.html b/html/journal/w43-2025.html index 133ebff..df91267 100644 --- a/html/journal/w43-2025.html +++ b/html/journal/w43-2025.html @@ -1,7 +1,7 @@ - + Journal Week 43, 2025 @@ -193,13 +193,8 @@ - - - + - - - @@ -220,21 +215,21 @@ Previous | Index | Next

-
-

Journal Week 43, 2025

-
+
+

Journal Week 43, 2025

+
-
-

Thursday, 23th October

-
+
+

Thursday, 23th October

+

EXCELLENT Journal

-
-
Four Fields
-
+
+
Four Fields
+

I’ve been feeling as though I’ve been bootlooping for a while now… like there’s never enough momentum to really get the habits I’m trying to build online. Especially with work-hunting and French studies this is starting to become a real problem.

@@ -258,12 +253,12 @@ In principle this system should ensure that I can constrain myself to thinking a

-
-
Cleaning House
-
+
+
Cleaning House
+
-
+
yes_chad_tabs.png
Figure 1: I’m not fucking around.
@@ -276,9 +271,9 @@ Got rid of over 1500 tabs. Good riddance. I’m sure whatever was in there w
-
-

Habits   autocollapse

-
+
+

Habits   autocollapse

+
YES Meditation
@@ -329,9 +324,9 @@ Resumed reading After the Ecstasy, the Laundry.
-
-

Friday, 24th October

-
+
+

Friday, 24th October

+

YES Journal

@@ -341,9 +336,9 @@ Luminous.

-
-

Habits   autocollapse

-
+
+

Habits   autocollapse

+
YES Meditation
@@ -382,9 +377,9 @@ Luminous.
-
-

Saturday, 25th October

-
+
+

Saturday, 25th October

+

YES Journal

@@ -398,9 +393,9 @@ Went to the forest and farm today. First time printing PETG with the 3D printer

-
-

Habits   autocollapse

-
+
+

Habits   autocollapse

+
YES Meditation
@@ -412,7 +407,7 @@ Went to the forest and farm today. First time printing PETG with the 3D printer
-
+
drawing-25102025.jpg
@@ -455,7 +450,7 @@ If you have any comments about this page, you can email me at:
Proudly built using org-mode.
All code on this website is licensed GPLv3 unless otherwise indicated.

-[Valid RSS]
+[Valid RSS]
diff --git a/html/journal/w44-2025.html b/html/journal/w44-2025.html index 703099f..22a2a5e 100644 --- a/html/journal/w44-2025.html +++ b/html/journal/w44-2025.html @@ -1,7 +1,7 @@ - + Journal Week 44, 2025 @@ -193,13 +193,8 @@ - - - + - - - @@ -220,13 +215,13 @@ Previous | Index | Next

-
-

Journal Week 44, 2025

-
+
+

Journal Week 44, 2025

+
-
-

Monday, 27th October

-
+
+

Monday, 27th October

+

YES Journal

@@ -236,9 +231,9 @@ Slow day today. Mondays are dangerous! Played a lot of Minecraft which was fun.

-
-

Habits   autocollapse

-
+
+

Habits   autocollapse

+
NO Meditation
@@ -277,9 +272,9 @@ Slow day today. Mondays are dangerous! Played a lot of Minecraft which was fun.
-
-

Tuesday, 28th October

-
+
+

Tuesday, 28th October

+

YES Journal

@@ -289,9 +284,9 @@ Did a lot of cleaning in the house today, as well as a trip to the hardware stor

-
-

Habits   autocollapse

-
+
+

Habits   autocollapse

+
NO Meditation
@@ -333,17 +328,17 @@ Didn’t have much stamina at the gym, but I’m very glad I still went.
-
-

Wednesday, 29th October

-
+
+

Wednesday, 29th October

+

YES Journal

-
-
Home Makeover
-
+
+
Home Makeover
+

Today I moved the desk around so that it faces into the living room instead of into the wall. I am not exaggerating when I say this took 5 full hours, mostly because of all the cleaning and especially cable management involved. The new setup has a lot of significant advantages:

@@ -359,7 +354,7 @@ Today I moved the desk around so that it faces into the living room instead of i
-
+
2025.10-desk.jpg
Figure 1: New living room situation.
@@ -368,7 +363,7 @@ Today I moved the desk around so that it faces into the living room instead of i
-
+
2025.10-cables.jpg
Figure 2: This is only a part of the cable management.
@@ -376,9 +371,9 @@ Today I moved the desk around so that it faces into the living room instead of i
-
-
Dutch Elections
-
+
+
Dutch Elections
+

It was election day in NL today. I really don’t follow Dutch politics much anymore, but my view in summary:

@@ -393,9 +388,9 @@ Overall the results feel like somewhat of a return to sanity but also just a ret

-
-
Pinko Shit
-
+
+
Pinko Shit
+

I continue to think that there would be a large support base for the Left, if only they would:

@@ -411,18 +406,18 @@ I always feel like the left constantly struggles to express itself through any f

-
-
Eepy
-
+
+
Eepy
+

Other than that I slept in very late and used up all my energy cleaning, so I left quite a few things undone.

-
-

Habits   autocollapse

-
+
+

Habits   autocollapse

+
NO Meditation
@@ -461,9 +456,9 @@ Other than that I slept in very late and used up all my energy cleaning, so I le
-
-

Friday, 31st October

-
+
+

Friday, 31st October

+

YES Journal

@@ -473,9 +468,9 @@ Picked up EMPTYHEAD development again.

-
-

Habits   autocollapse

-
+
+

Habits   autocollapse

+
NO Meditation
@@ -523,7 +518,7 @@ If you have any comments about this page, you can email me at:
Proudly built using org-mode.
All code on this website is licensed GPLv3 unless otherwise indicated.

-[Valid RSS]
+[Valid RSS]
diff --git a/html/journal/w45-2025.html b/html/journal/w45-2025.html index cfcab54..a61b62c 100644 --- a/html/journal/w45-2025.html +++ b/html/journal/w45-2025.html @@ -1,7 +1,7 @@ - + Journal Week 45, 2025 @@ -193,13 +193,8 @@ - - - + - - - @@ -220,13 +215,13 @@ Previous | Index | Next

-
-

Journal Week 45, 2025

-
+
+

Journal Week 45, 2025

+
-
-

Thursday, 6th November   journal

-
+
+

Thursday, 6th November   journal

+

YES Journal   jentry

@@ -240,9 +235,9 @@ Went to see TEKE::TEKE li

-
-

Habits   autocollapse habits

-
+
+

Habits   autocollapse habits

+
NO Meditation
@@ -281,9 +276,9 @@ Went to see TEKE::TEKE li
-
-

Friday, 7th November   journal

-
+
+

Friday, 7th November   journal

+

YES Journal   jentry

@@ -293,9 +288,9 @@ Tired, so tired.

-
-

Habits   autocollapse habits

-
+
+

Habits   autocollapse habits

+
NO Meditation
@@ -334,9 +329,9 @@ Tired, so tired.
-
-

Saturday, 8th November   journal

-
+
+

Saturday, 8th November   journal

+

YES Journal   jentry

@@ -354,9 +349,9 @@ Today I finished After the Ecstacy, the Laundry.

-
-

Habits   autocollapse habits

-
+
+

Habits   autocollapse habits

+
YES Meditation
@@ -395,9 +390,9 @@ Today I finished After the Ecstacy, the Laundry.
-
-

Sunday, 9th November   journal

-
+
+

Sunday, 9th November   journal

+

YES Journal   jentry

@@ -406,16 +401,16 @@ Today I finished After the Ecstacy, the Laundry. Bunch more chores today. Leather buttons on my old wool coat fell off and I fixed them with superglue. I ripped out my old1 guitar’s crusty wiring and hardwired one of the pickups in the interim until I get around to rewiring it:

-
+
-
+
2025.11-guitar-old.jpg
Figure 1: Before (crusty and broken).
-
+
2025.11-guitar-new.jpg
Figure 2: After.
@@ -436,9 +431,9 @@ New bugs unlocked:
-
-

Habits   autocollapse habits

-
+
+

Habits   autocollapse habits

+
YES Meditation
@@ -494,7 +489,7 @@ If you have any comments about this page, you can email me at:
Proudly built using org-mode.
All code on this website is licensed GPLv3 unless otherwise indicated.

-[Valid RSS]
+[Valid RSS]
diff --git a/html/journal/w46-2025.html b/html/journal/w46-2025.html index c5ef653..55c010f 100644 --- a/html/journal/w46-2025.html +++ b/html/journal/w46-2025.html @@ -1,7 +1,7 @@ - + Journal Week 46, 2025 @@ -193,13 +193,8 @@ - - - + - - - @@ -217,16 +212,16 @@
-
-

Journal Week 46, 2025

-
+
+

Journal Week 46, 2025

+
-
-

Monday, 10th November   journal

-
+
+

Monday, 10th November   journal

+

YES Journal   jentry

@@ -256,9 +251,9 @@ I want to start writing my Summer 2025 Anime Retrospective soon. I have my thoug

-
-

Habits   autocollapse habits

-
+
+

Habits   autocollapse habits

+
YES Meditation
@@ -271,7 +266,7 @@ I want to start writing my Summer 2025 Anime Retrospective soon. I have my thoug
-
NO Engineering
+
YES Engineering
@@ -281,7 +276,264 @@ I want to start writing my Summer 2025 Anime Retrospective soon. I have my thoug
-
NO Social
+
YES Social
+
+
+
+
+
YES Exercise
+
+
+
+
+
NO Reading
+
+
+
+
+
+
+

Tuesday, 11th November   journal

+
+
+
+

YES Journal   jentry

+
+

+Happy St. Martin’s/End of WWI! +

+ +

+Trying to sell our dry herb vaporizer — cutting down weed consumption to once-every-few-months tier, and I notice I get much less full-spectrum effects vaporizing vs just smoking leading me to consume more — but leboncoin took down our listing because something something drug paraphernalia. Nevermind that the product is legally for sale here, nevermind that there’s legitimate non-drug uses for it, nevermind that the exact same product is for sale in other listings on leboncoin… of course contacting support for this kind of thing is pointless. Solveable problem but so much ado about nothing. On the flipside, we managed to sell our Roland GI-10 that we got for our Premier Impact show. We bought it for €100 and sold it for €50, which I guess is alright for such an obsolete low-volume item. +

+ +

+This website now runs off Redbean (formerly lighttpd) — one reason being that lighttpd’s documentation is an unworkable mess (we were configuring caching) and another reason being that redbean is awesome. Justine is awesome. On that note, CSS/JS should now be cached for a day while HTML should be uncached, I hope (HTTP caching is confusing). +

+ +

+Starting to get serious about practicing the electronic drum kit that’s been standing in the corner for the past year and a half +

+
+ +
+2025.11-drums.jpg + +
Figure 1: Tweaking the ergonomics on this thing is a lot of work.
+
+
+ +

+I’ve started looking into the Linux FOSS music production stack again… provisional conclusions: +

+
    +
  • Zrythm looks promising and afaict the backend is good, but the V1 frontend is unusably slow, with V2 in active development with a full GUI rewrite (GTK→QT) but still far from production-ready; +
      +
    • Side note: seems like almost nobody is writing major GUIs in GTK anymore, which is understandable given how dogshit GTK has become…
    • +
  • +
  • Ardour is still Ardour, as far as I can tell it’s a good DAW but just not designed for a MIDI-heavy workflow;
  • +
  • LMMS seems to be under very active development (26 PRs last month according to their forums) but they haven’t cut so much as an alpha release since 2020… Very strange, though I get the impression they are working towards a release;
  • +
  • Right now a primarily No-DAW stack still seems the most viable.
  • +
+ +

+I’m gonna give Ubuntu Studio another whirl tomorrow. +

+ +

+Still getting less-than-ideal sleep with a lot of nightmares, though it feels like things are starting to normalize a bit again, and at least my circadian rhythm is fine. +

+
+
+
+

Habits   autocollapse habits

+
+
+
+
NO Meditation
+
+
+
+
+
NO Drawing
+
+
+
+
+
YES Engineering
+
+
+
+
+
YES French
+
+
+
+
+
YES Social
+
+
+
+
+
YES Exercise
+
+
+
+
+
NO Reading
+
+
+
+
+
+
+

Friday, 14th November   journal

+
+
+
+

YES Journal   jentry

+
+

+Been pretty dead for a couple days… sleep issues. I’ll try and be a bit more dilligent about always adding the journal entries, at least. +

+ +

+Started making a lot of refactors to the website. +

+
+
+
+

Habits   autocollapse habits

+
+
+
+
YES Meditation
+
+
+
+
+
NO Drawing
+
+
+
+
+
EXCELLENT Engineering
+
+
+
+
+
YES French
+
+
+
+
+
YES Social
+
+
+
+
+
YES Exercise
+
+
+
+
+
NO Reading
+
+
+
+
+
+
+

Saturday, 15th November   journal

+
+
+
+

YES Journal   jentry

+
+

+Good gym session today. Worked on formatting my Anki cards. Read about the Three Kingdoms period. Not much else to say. +

+
+
+
+

Habits   autocollapse habits

+
+
+
+
YES Meditation
+
+
+
+
+
NO Drawing
+
+
+
+
+
FREED Engineering
+
+
+
+
+
EXCELLENT French
+
+
+
+
+
YES Social
+
+
+
+
+
EXCELLENT Exercise
+
+
+
+
+
YES Reading
+
+
+
+
+
+
+

Sunday, 16th November   journal

+
+
+
+

YES Journal   jentry

+
+

+Two hours of drums practice today! Started feeling somewhat lethargic after that. Did a bunch of work reorganizing Hydrus. +

+
+
+
+

Habits   autocollapse habits

+
+
+
+
NO Meditation
+
+
+
+
+
NO Drawing
+
+
+
+
+
FREED Engineering
+
+
+
+
+
NO French
+
+
+
+
+
YES Social
@@ -300,13 +552,13 @@ I want to start writing my Summer 2025 Anime Retrospective soon. I have my thoug
- diff --git a/html/journal/w47-2025.html b/html/journal/w47-2025.html new file mode 100644 index 0000000..014cdb9 --- /dev/null +++ b/html/journal/w47-2025.html @@ -0,0 +1,298 @@ + + + + + + +Journal Week 47, 2025 + + + + + + + + + + + +
+ +
+
+
+

+Previous | Index +

+
+
+

Journal Week 47, 2025

+
+
+
+

Thursday, 20th November 2025

+
+
+
+

NO Journal

+
+

+Oof I have not been good about updating the journal again. +

+
+
+
Daily Planning
+
+
+
    +
  • TODO Rework “looking for work” page
  • +
  • TODO Rework habits??
  • +
  • TODO Get akk0{at}webbieweb{dot}org email working again
  • +
+
+
+
+

Habits   autocollapse

+
+
+
+
NO Meditation
+
+
+
+
+
NO Drawing
+
+
+
+
+
NO Engineering
+
+
+
+
+
NO French
+
+
+
+
+
NO Social
+
+
+
+
+
NO Exercise
+
+
+
+
+
NO Reading
+
+
+
+
+
+
+
+
+ +
+ + diff --git a/html/links/index.html b/html/links/index.html index 2cb5157..ab17553 100644 --- a/html/links/index.html +++ b/html/links/index.html @@ -1,7 +1,7 @@ - + Links @@ -193,13 +193,8 @@ - - - + - - - @@ -215,13 +210,13 @@
-
-

Links

-
+
+

Links

+
-
-

2025

-
+
+

2025

+
@@ -236,7 +231,7 @@ If you have any comments about this page, you can email me at:
Proudly built using org-mode.
All code on this website is licensed GPLv3 unless otherwise indicated.

-[Valid RSS]
+[Valid RSS]
diff --git a/html/links/w27-2025-30.06-06.07-links.html b/html/links/w27-2025-30.06-06.07-links.html index 187bd77..ca5d74b 100644 --- a/html/links/w27-2025-30.06-06.07-links.html +++ b/html/links/w27-2025-30.06-06.07-links.html @@ -1,7 +1,7 @@ - + Links for week 27, 2025 (June 30 to July 06) @@ -193,13 +193,8 @@ - - - + - - - @@ -215,12 +210,12 @@
-
-

Links for week 27, 2025 (June 30 to July 06)

-
+
+

Links for week 27, 2025 (June 30 to July 06)

+
-
@@ -231,7 +226,7 @@ If you have any comments about this page, you can email me at:
Proudly built using org-mode.
All code on this website is licensed GPLv3 unless otherwise indicated.

-[Valid RSS]
+[Valid RSS]
diff --git a/html/other/ip_paris_appeal.html b/html/other/ip_paris_appeal.html index 8fa4d7f..1474375 100644 --- a/html/other/ip_paris_appeal.html +++ b/html/other/ip_paris_appeal.html @@ -1,7 +1,7 @@ - + Appeal Regarding Rejection for Computer Science MSc Programmes at IP Paris @@ -193,13 +193,8 @@ - - - + - - - @@ -215,9 +210,9 @@
-
-

Appeal Regarding Rejection for Computer Science MSc Programmes at IP Paris

-
+
+

Appeal Regarding Rejection for Computer Science MSc Programmes at IP Paris

+

Dear esteemed President of the Institut Polytechnique de Paris,

@@ -291,7 +286,7 @@ If you have any comments about this page, you can email me at:
Proudly built using org-mode.
All code on this website is licensed GPLv3 unless otherwise indicated.

-[Valid RSS]
+[Valid RSS]
diff --git a/html/other/ultraman.html b/html/other/ultraman.html index d3e4233..abacf3e 100644 --- a/html/other/ultraman.html +++ b/html/other/ultraman.html @@ -1,7 +1,7 @@ - + The Story of Ultraman @@ -193,13 +193,8 @@ - - - + - - - @@ -215,8 +210,8 @@
-
-

The Story of Ultraman

+
+

The Story of Ultraman

@@ -226,7 +221,7 @@ If you have any comments about this page, you can email me at:
Proudly built using org-mode.
All code on this website is licensed GPLv3 unless otherwise indicated.

-[Valid RSS]
+[Valid RSS]
diff --git a/html/posts/blog-tech.html b/html/posts/blog-tech.html index 6871b3d..283cfba 100644 --- a/html/posts/blog-tech.html +++ b/html/posts/blog-tech.html @@ -1,7 +1,7 @@ - + How This Blog Works @@ -193,13 +193,8 @@ - - - + - - - @@ -215,8 +210,8 @@
-
-

How This Blog Works

+
+

How This Blog Works

@@ -226,7 +221,7 @@ If you have any comments about this page, you can email me at:
Proudly built using org-mode.
All code on this website is licensed GPLv3 unless otherwise indicated.

-[Valid RSS]
+[Valid RSS]
diff --git a/html/posts/fiction/index.html b/html/posts/fiction/index.html index 18e909b..b832c4d 100644 --- a/html/posts/fiction/index.html +++ b/html/posts/fiction/index.html @@ -1,7 +1,7 @@ - + Fiction @@ -193,13 +193,8 @@ - - - + - - - @@ -215,8 +210,8 @@
-
-

Fiction

+
+

Fiction

@@ -226,7 +221,7 @@ If you have any comments about this page, you can email me at:
Proudly built using org-mode.
All code on this website is licensed GPLv3 unless otherwise indicated.

-[Valid RSS]
+[Valid RSS]
diff --git a/html/posts/fiction/jesus.html b/html/posts/fiction/jesus.html index e96aa38..148c446 100644 --- a/html/posts/fiction/jesus.html +++ b/html/posts/fiction/jesus.html @@ -1,7 +1,7 @@ - + A West Coast Gospel @@ -193,13 +193,8 @@ - - - + - - - @@ -215,13 +210,13 @@
-
-

todo title

-
+
+

todo title

+
-
-

I

-
+
+

I

+

Sacramento, California, 2355. Jesus Salvador Rodriguez was a teacher and healer. Working two jobs was hard work, but he liked the extra income, hoping the size of his palestial two-bedroom apartment would help attract a mate. Long ago, before the Singularity, there had been many jobs; now it was down to just two. There were healers, who worked in healthcare administration, and teachers, who worked in college administration. Rumors had it that somewhere out there the Digital Nomads yet roamed, traversing the galaxy in a bid to get ever further away from California. Scientific concensus dismissed these rumors as a hoax, holding that the universe held nil but Earth and Paperclip.

@@ -231,9 +226,9 @@ Naively reasoning one would suggest that, with nanobots supporting one’s e

-
-

II

-
+
+

II

+

It was Thursday afternoon, and Jesus was at work. When not? Long ago, there had been the matter between Working From Home and Living In The Office, and the office had won. Everyone was, of course, well aware of the irony of living at the office for the sole purpose of renting an apartment, this being the subject of a centuries-old comedic tradition. A tale as old as time; so as the peacock shows its fitness by painting a target of auspicious technicolor plumes on its own back, so must humans do retarded shit to get laid.

@@ -255,9 +250,9 @@ He finished his meal and went back inside, making his way past the office and to

-
-

III

-
+
+

III

+

SPIDER!!!. Now that I have your attention, SPIDER!!!. It’d bit him. It shouldn’t have been there. After months of negotiation, a deal’d been reached. Clippy, the universe. Humans, the Earth. Spiders, Australia. This was not Australia. Thus the Tripartite Partition Treaty designated the spider as an enemy combatant, overruling the California Bill of Animal Rights’ prohibition on killing insects. Jesus shot at it with his web. Web? Web! Spider silk! Strong as steel, tough as kevlar, a wonderful material. Extremely illegal, as it was not listed on the California State Whitelist Allowlist of Materials Known Not To Cause Cancer (Superintelligence offered to provide a much longer list, but since the bulk of chemicals is not carcinogenic, the list would’ve required Randian amounts of paper to print and this was deemed environmentally unfriendly).

@@ -271,9 +266,9 @@ Enfin, since carcinogenic compounds were considered Schedule I drugs (the era of

-
-

IV, or as Uccello Knew It, IIII

-
+
+

IV, or as Uccello Knew It, IIII

+

Skirt. Crop top. Boots; leather. Jacket; leather. Socks - long, green; nails, too. Victoria. And her guitar. Not the kind that goes pling plong. The kind that makes an onomatopoeia befitting very aggressive electric guitar playing. She looked like a relic. Fashion from when old was new again in her great-great-great-grandmother’s days. Loved to smoke the ganja. Everyone smoked, as cannabis consumption had been made compulsory in California, but she really enjoyed it.

@@ -299,9 +294,9 @@ Jesus’ apartment. Wanna come in, have a smoke?

-
-

V

-
+
+

V

+

Before the cloud had left her black lips, she’d already pinched the pegs of her axe - she carried it with her everywhere - and started tuning it. Looking down, blushing, wanting to look at anything but Jesus. Cute. Cutecutecutecutecutecute, he thought. The damn guitar obscures her belly, he thought. She, on her part, thought something perhaps best transliterated as asodifhweofnoqfc. She was no good with this kind of thing. She couldn’t deal with emotions using words. She’d rather play than speak; her fingers outskilled her tongue.

@@ -319,17 +314,17 @@ Jesus felt for her. He wanted to hear it. He wanted all of her, the song of her

-
-

VI

-
+
+

VI

+

Jesús webbed.

-
-

notes

-
+
+

notes

+

something something violin string it’s a sexual metaphor @@ -349,7 +344,7 @@ If you have any comments about this page, you can email me at:
Proudly built using org-mode.
All code on this website is licensed GPLv3 unless otherwise indicated.

-[Valid RSS]
+[Valid RSS]

diff --git a/html/posts/framework.html b/html/posts/framework.html index fe0578d..0e786cb 100644 --- a/html/posts/framework.html +++ b/html/posts/framework.html @@ -1,7 +1,7 @@ - + Framework Laptop Review @@ -193,13 +193,8 @@ - - - + - - - @@ -215,13 +210,13 @@
-
-

My Experience with the Framework Laptop

-
+
+

My Experience with the Framework Laptop

+
-
-

Ordering

-
+
+

Ordering

+

I’d been eyeing the Framework laptop since somewhere in October 2021, but the EU release got delayed and they were very hesitant to give time estimates. I only managed to get my hands on it in late February, and I ended up having to have it delivered to France. I understand the difficulty of setting up logistics especially these days, but I broke my previous laptop and being stuck in limbo like this was not fun.

@@ -232,13 +227,13 @@ I asked their customer service to make a small change to the delivery address, b

-
-

Set-up

-
+
+

Set-up

+
-
-

Hardware

-
+
+

Hardware

+

I got the DIY edition with the (lowest-end) i5-1135G7 CPU, 2x16GB RAM. I brought my own 1TB SSD. The higher spec CPUs didn’t seem worth the money to me. The RAM is probably overkill.

@@ -265,9 +260,9 @@ The more you look at it, the nicer it gets!

-
-

Software

-
+
+

Software

+

I installed Gentoo GNU+Linux on the laptop, just like I have on my desktop. I used an Ubuntu live CD as the install medium together with the Gentoo stage3 tarball, and it worked well. I didn’t really have to jump through any laptop-specific hoops, it was a very nice experience. I did use the dist-kernel rather than configuring my own.

@@ -276,9 +271,9 @@ I installed Gentoo GNU+Linux on the laptop, just like I have on my desktop. I us The laptop held up well during compiling. It’s not as fast as a desktop of course, but compile times are not limiting. I’ve put this thing through bootstrapping GCC for a cross-compilation toolchain, which is just about the biggest compile job I’ve ran, and it wasn’t that painful.

-
-
Display scaling
-
+
+
Display scaling
+

Simply setting Xft.dpi: 192 in .Xresources was enough for the vast majority of applications to use 2x scaling, which looks very good on this display. This is on X11 obviously; I don’t use Wayland.

@@ -288,33 +283,33 @@ The odd application requires its own scaling setting. Rofi requires setting
-
-
Display manager
-
+
+
Display manager
+

I used SDDM which works very well. I wanted to go for something a bit fancier looking, and this delivers. I don’t usually use things in the whole QT ecosystem, so it’s refreshing.

-
-
Hibernate/suspend-to-disk
-
+
+
Hibernate/suspend-to-disk
+

This required setting up a swap file and setting a kernel command line parameter to refer to it, but it was easy to do. It works well. I’ve observed the laptop auto-hibernating when the battery runs out, but it doesn’t do this reliably, so I should probably configure it myself.

-
-
Guake-like transient terminal
-
+
+
Guake-like transient terminal
+

-Using some fish scripts, bspwm, picom and xst I rigged up a transient, transparent terminal to use for quick shell jobs. I used the scripts and config file in Appendix A to do this. The implementation is a bit hacky, and it’s not impossible to break, but it serves my purposes well (and more important, it was fun to make)! +Using some fish scripts, bspwm, picom and xst I rigged up a transient, transparent terminal to use for quick shell jobs. I used the scripts and config file in Appendix A to do this. The implementation is a bit hacky, and it’s not impossible to break, but it serves my purposes well (and more important, it was fun to make)!

-
-
Wallpaper-setting script
-
+
+
Wallpaper-setting script
+

I wrote a script to set a random wallpaper.

@@ -325,11 +320,11 @@ I wrote a script to set a random wallpaper.
-
-
Lockscreen
-
+
+
Lockscreen
+

-I hacked together some pretty crappy code to lock the screen using i3lock, with my wallpaper composed with a little lock icon as the background. Very overengineered. +I hacked together some pretty crappy code to lock the screen using i3lock, with my wallpaper composed with a little lock icon as the background. Very overengineered.

@@ -342,33 +337,33 @@ Is there a better lockscreen out there that will let me set my own image as the

-
-
TODO
-
+
+
TODO
+
    -
  • Battery level notifications
  • -
  • sleep-then-hibernate
  • -
  • Battery tuning
  • +
  • Battery level notifications
  • +
  • sleep-then-hibernate
  • +
  • Battery tuning
-
-

Impressions

-
+
+

Impressions

+
-
-
Build Quality
-
+
+
Build Quality
+

The laptop is made of aluminium and feels solid but light. The screen does seem pretty flimsy, though. I probably wouldn’t want to drop this thing. It looks sleek and elegant, but pretty muted.

-
-
Screen
-
+
+
Screen
+

This is my first time ever using a high-DPI screen, and I’m very impressed by it. Text looks unbelievably crisp and pleasant to read. I was somewhat worried about the linux high DPI situation, but I am having no issues whatsoever.

@@ -382,51 +377,51 @@ The brightness goes up quite high, but colours feel somewhat washed out at high

-
-
Keyboard
-
+
+
Keyboard
+

Framework seems to advertise their keyboard as having particularly deep travel, but it mostly just feels like any chiclet keyboard to me. Not a bad chiclet keyboard, but not that great, either. The layout is fine, but it makes me miss the thinkpad.

-
-
Touchpad
-
+
+
Touchpad
+

I’ve never had a decent touchpad before, so I was pleasantly surprised. I expected to miss the trackpoint on the thinkpad a lot, but this is fine, though it’s still a step down. Pinch to zoom doesn’t work very well, but I don’t use that functionality a lot. I miss having dedicated mouse buttons; the clicking functionality on this touchpad works fine for me, but it’s hard not to mess up left/middle/right click. That’s a good incentive for me to practice relying on the mouse less, though. There’s plenty of work being done on the Linux touchpad experience software-side, too. It’s a nice time to be a linux laptop user!

-
-
Battery
-
+
+
Battery
+

With the disclaimer that I haven’t tested very intensely and I haven’t tuned power settings very much.
I seem to get about 6.5 hours of real-world use time when using Emacs and doing light web browsing. I don’t have a good benchmark for more intensive tasks, but compiling does hit the battery pretty hard. All in all I’m very happy with it, getting decent battery life on Linux is hard. It might be worth eventually buying a power bank for it though, for travel~

-
-
Expansion cards/ports
-
+
+
Expansion cards/ports
+

The little expansion cards are one of Framework’s big marketing things. I think they’re pretty neat, though I don’t always quite understand the way people talk about them, as “dongle killers”. I would find hotswapping these about equally obnoxious as carrying dongles. The idea of aftermarket expansion cards is interesting, though - these are low level, high bandwidth ports, with I think similar capabilities to the ExpressCard ports on old business laptops, but more modern with a USB-C port. I’m looking forward to the USB4 era!

-
-
Performance
-
+
+
Performance
+

So far I haven’t felt limited by performance at all, the experience has been really snappy. I haven’t thrown particularly difficult things at it, though, but that’s fine - most of what I do on a laptop is reading, web browsing, and text editing. I played some Factorio on it and that seemed fine, but using the touchpad felt limiting so I didn’t play very much.

-
-

Closing words

-
+
+

Closing words

+

Getting this laptop set up has been really fun! It’s a good opportunity to take stock of where we’re at. On the hardware side, I am very impressed that it’s now possible to make a laptop that’s this user-servicable, this well-specced and still not that expensive. It’s a reminder of how much better things could be.

@@ -441,9 +436,9 @@ Personally, I’m getting a rare chance to critically examine all the little
-
-

Appendix A: Transient Terminal Sources

-
+
+

Appendix A: Transient Terminal Sources

+

togglescratch

@@ -512,9 +507,9 @@ opacity-rule=["90:name = 'scratchterminal'"];
-
-

Appendix B: lock.py

-
+
+

Appendix B: lock.py

+
#!/usr/bin/python3
 import os
@@ -547,7 +542,7 @@ If you have any comments about this page, you can email me at: 
Proudly built using org-mode.
All code on this website is licensed GPLv3 unless otherwise indicated.

-[Valid RSS]
+[Valid RSS]
diff --git a/html/posts/index.html b/html/posts/index.html index e587213..113a713 100644 --- a/html/posts/index.html +++ b/html/posts/index.html @@ -1,7 +1,7 @@ - + Posts @@ -193,13 +193,8 @@ - - - + - - - @@ -215,8 +210,8 @@
-
-

Posts

+
+

Posts

@@ -226,7 +221,7 @@ If you have any comments about this page, you can email me at:
Proudly built using org-mode.
All code on this website is licensed GPLv3 unless otherwise indicated.

-[Valid RSS]
+[Valid RSS]
diff --git a/html/projects/blog.html b/html/projects/blog.html index b8eeb75..611ddc0 100644 --- a/html/projects/blog.html +++ b/html/projects/blog.html @@ -1,7 +1,7 @@ - + Blog Project @@ -193,13 +193,8 @@ - - - + - - - @@ -215,111 +210,111 @@
-
-

TODO Source Exposure

-
+
+

TODO Source Exposure

+

Every page should have a button that takes you to the org-mode source for that page, using the beautifully named org-org-export-to-org.

-
-

TODO Comment Section

-
+
+

TODO Comment Section

+
- -
-

TODO Feeds

-
+
+

TODO Feeds

+
-
-

TODO RSS

+
+

TODO RSS

-
-

TODO Email?

+
+

TODO Email?

-
-

TODO Multiple frontends dispatch

+
+

TODO Multiple frontends dispatch

-
-

TODO Custom emojis

+
+

TODO Custom emojis

-
-

TODO Port esquemadorg.js to CLJS and get rid of JQuery dependency

+
+

TODO Port esquemadorg.js to CLJS and get rid of JQuery dependency

-
-

TODO “Last Modified” implementation is a bit janky and I don’t remember exactly how it works

+
+

TODO “Last Modified” implementation is a bit janky and I don’t remember exactly how it works

-
-

TODO Rewrite all JS to CLJS

+
+

TODO Rewrite all JS to CLJS

-
-

TODO Naming a section “footnotes” will cause org-mode to interpret it as the footnotes section when exporting (causing it to be hidden)

+
+

TODO Naming a section “footnotes” will cause org-mode to interpret it as the footnotes section when exporting (causing it to be hidden)

-
-

TODO Tangle CSS and (CL)JS from org file

+
+

TODO Tangle CSS and (CL)JS from org file

-
-

TODO Reorganize static/ dir

+
+

TODO Reorganize static/ dir

-
-

TODO Write Ultraman page

+
+

TODO Write Ultraman page

-
-

TODO Automatically remove EXIF data from static images

+
+

TODO Automatically remove EXIF data from static images

-
-

TODO !! OLD HTML FILES STILL DON’T AUTO CLEAR WHEN CORRESPONDING ORG FILE IS REMOVED !!

+
+

TODO !! OLD HTML FILES STILL DON’T AUTO CLEAR WHEN CORRESPONDING ORG FILE IS REMOVED !!

-
-

TODO Put DJ sets on bloggie

+
+

TODO Put DJ sets on bloggie

-
-

TODO Fix background flash

+
+

TODO Fix background flash

-
-

TODO click images to expand

+
+

TODO click images to expand

-
-

TODO general mobile review

+
+

TODO general mobile review

-
-

TODO add badges

+
+

TODO add badges

-
-

TODO floating TOC if viewport is big enough

+
+

TODO floating TOC if viewport is big enough

-
-

TODO Fill in missing index pages

+
+

TODO Fill in missing index pages

-
-

TODO Auto template only applies to posts/ subdirectory

+
+

TODO Auto template only applies to posts/ subdirectory

-
-

TODO optimize fonts

+
+

TODO optimize fonts

-
-

TODO web caching

+
+

TODO web caching

-
-

TODO org-mode export caching

+
+

TODO org-mode export caching

-
-

TODO front page habit table thing

-
+
+

TODO front page habit table thing

+
-
-

TODO relative links do not work here!!

+
+

TODO relative links do not work here!!

-
-

TODO caching problems

+
+

TODO caching problems

-
-

TODO footnote thing doesn’t render the same as in the actual page

+
+

TODO footnote thing doesn’t render the same as in the actual page

@@ -330,7 +325,7 @@ If you have any comments about this page, you can email me at:
Proudly built using org-mode.
All code on this website is licensed GPLv3 unless otherwise indicated.

-[Valid RSS]
+[Valid RSS]
diff --git a/html/projects/emptyhead/index.html b/html/projects/emptyhead/index.html index ba7d959..c3e6690 100644 --- a/html/projects/emptyhead/index.html +++ b/html/projects/emptyhead/index.html @@ -1,7 +1,7 @@ - + @@ -193,13 +193,8 @@ - - - + - - - @@ -223,7 +218,7 @@ If you have any comments about this page, you can email me at:
Proudly built using org-mode.
All code on this website is licensed GPLv3 unless otherwise indicated.

-[Valid RSS]
+[Valid RSS]
diff --git a/html/projects/emptyhead/todo.html b/html/projects/emptyhead/todo.html index fbcffee..d60033a 100644 --- a/html/projects/emptyhead/todo.html +++ b/html/projects/emptyhead/todo.html @@ -1,7 +1,7 @@ - + EMPTYHEAD TODO @@ -193,13 +193,8 @@ - - - + - - - @@ -215,8 +210,8 @@
-
-

TODO fill this in

+
+

TODO fill this in

@@ -226,7 +221,7 @@ If you have any comments about this page, you can email me at:
Proudly built using org-mode.
All code on this website is licensed GPLv3 unless otherwise indicated.

-[Valid RSS]
+[Valid RSS]
diff --git a/html/projects/index.html b/html/projects/index.html index deaf34c..dac9ec3 100644 --- a/html/projects/index.html +++ b/html/projects/index.html @@ -1,7 +1,7 @@ - + Projects Index @@ -193,13 +193,8 @@ - - - + - - - @@ -215,24 +210,24 @@
-
-

Projects Index

-
+
+

Projects Index

+

Here’s a list of projects I maintain or am currently working on.

-
-

TO-DOs for this website

+ -
-

The EMPTYHEAD

+ - @@ -243,7 +238,7 @@ If you have any comments about this page, you can email me at:
Proudly built using org-mode.
All code on this website is licensed GPLv3 unless otherwise indicated.

-[Valid RSS]
+[Valid RSS]
diff --git a/html/projects/tenma/index.html b/html/projects/tenma/index.html index c475484..d74195e 100644 --- a/html/projects/tenma/index.html +++ b/html/projects/tenma/index.html @@ -1,7 +1,7 @@ - + Tenma Readme @@ -193,13 +193,8 @@ - - - + - - - @@ -215,16 +210,16 @@
-
-

Opening tenma up to friends

-
+
+

Opening tenma up to friends

+

Our server/intranet Tenma is currently underutilized, and it would be nice/fun/useful to open it up to select other people. This would only be available to friends, not a public service.

-
-

Tenma Specs

-
+
+

Tenma Specs

+
  • Storage: 2×12TB in RAID 1
  • CPU: Ryzen 7 3700X (16 threads @ 3.6GHz)
  • @@ -233,69 +228,69 @@ Our server/intranet Tenma is currently underutilized, and it would be nice/fun/u
-
-

Things that Tenma can provide

-
+
+

Things that Tenma can provide

+
-
-

Storage

-
+
+

Storage

+

As of 23-06-2025, 4.6TB free space. Could start by reserving 1TB, which would provide enough storage for 20×50GB for guests users, which would be plenty for a long time. Tenma also hosts a copyparty instance that could be opened to the public to some extent or another.

-
-

Bandwidth/hosting

-
+
+

Bandwidth/hosting

+

Tenma has full web hosting infrastructure set up (hosting this blog among other things), so that would be easy to extend to other people as well.

-
-

VPS

-
+
+

VPS

+

In line with the previous 2 points; compute resources are currently underutilized.

-
-

Intranet

-
+
+

Intranet

+

Tenma runs a Wireguard VPN network. You can use this to, for instance, access services between two connected devices without having to open them up to the wider internet.

-
-

DNS Server

-
+
+

DNS Server

+

Tenma runs a fully resolving DNS server, with some local entries for devices on the VPN network. This should probably be automated in some way, and the service should be augmented with DNSSEC before opening.

-
-

Git

-
+
+

Git

+

Tenma has a Gitea instance

-
-

Livestreaming

-
+
+

Livestreaming

+

Tenma has infrastructure proven capable of restreaming 1080p video and high quality audio to at least ~100 people although this is CPU intensive and requires activating a high bandwidth restreaming VPS that is usually kept disabled to save costs.

-
-

Other things

-
+
+

Other things

+

Some other services that currently run on Tenma or have run there before:

@@ -308,9 +303,9 @@ Some other services that currently run on Tenma or have run there before:
-
-

Considerations

-
+
+

Considerations

+
  • This would require Tenma’s internal documentation to be updated, adapted and publicized.
  • Security :teto:
  • @@ -326,7 +321,7 @@ If you have any comments about this page, you can email me at:
    Proudly built using org-mode.
    All code on this website is licensed GPLv3 unless otherwise indicated.

    -[Valid RSS]
    +[Valid RSS]
diff --git a/html/projects/webbiewebworld/index.html b/html/projects/webbiewebworld/index.html index 700a1ea..e8aff6e 100644 --- a/html/projects/webbiewebworld/index.html +++ b/html/projects/webbiewebworld/index.html @@ -1,7 +1,7 @@ - + WebbieWebWorld TODO @@ -193,13 +193,8 @@ - - - + - - - @@ -215,8 +210,8 @@
-
-

TODO fill this in

+
+

TODO fill this in

@@ -226,7 +221,7 @@ If you have any comments about this page, you can email me at:
Proudly built using org-mode.
All code on this website is licensed GPLv3 unless otherwise indicated.

-[Valid RSS]
+[Valid RSS]
diff --git a/html/sitemap.html b/html/sitemap.html index ad19e48..771bd37 100644 --- a/html/sitemap.html +++ b/html/sitemap.html @@ -1,7 +1,7 @@ - + Sitemap for project pages @@ -193,13 +193,8 @@ - - - + - - - @@ -216,6 +211,7 @@
- diff --git a/html/source.html b/html/source.html new file mode 100644 index 0000000..d6706bc --- /dev/null +++ b/html/source.html @@ -0,0 +1,1567 @@ + + + + + + +Webbieweb.org Sources + + + + + + + + + + + +
+ +
+
+
+

Webbieweb.org Literate Sources   h4left h5left h3underline

+
+
+
+

Introduction

+
+

+These are the literate sources of webbieweb.org. The code blocks here constitute the actual sources; therefore, this document is guaranteed to be up to date. +

+ +

+This page is self-contained; the only dependency is ox-publish. The following directory structure is expected: +

+
+.
+|-- html                ;; Export destination; you can copy this dir to any static file host and host the website that way.
+|-- org                 ;; Org-mode sources; these will get compiled and the output copied to html/.
+    `-- source.org      ;; This file.
+|-- static              ;; Images, videos, CSS files, fonts etc will be copied unchanged to html/static.
+`-- util
+    |-- head.html       ;; Contains HTML <head>; will be prepended to every output file.
+    |-- postamble.html  ;; Navbar; will be prepended to <body> of every output file.
+    `-- preamble.html   ;; Footer; as above.
+
+
+

+(Apologies for the misalignment, I don’t know why that happens.) +

+
+
+
+
+

Export Commands

+
+

+Load this file up in Emacs and hit C-c C-c on the code block below to export changes to HTML. +

+
+
<<blog-scaffolding>>
+(blog/publish)
+(org-babel-tangle)
+
+
+ +

+The one below will ignore caching; necessary in some situations, for instance: changes under util/. +

+
+
<<blog-scaffolding>>
+(blog/force-publish)
+(org-babel-tangle)
+
+
+
+
+
+

Elisp

+
+
+
+

Basic Settings/Scaffolding   autocollapse

+
+
+
(require 'ox-publish)
+
+<<no-sitemap>>
+
+(defun blog/get-util (x)
+  (with-temp-buffer
+    (insert-file-contents (concat "../util/" x))
+    (buffer-string)))
+
+(setq org-html-metadata-timestamp-format "%Y-%m-%d")
+
+(defun blog/spec ()
+  "Return project settings for use with `org-publish-project-alist'."
+  (let* ((html-head (blog/get-util "head.html"))
+         (html-preamble (blog/get-util "preamble.html"))
+         (html-postamble (blog/get-util "postamble.html")))
+
+
+    `(("pages"
+       :base-directory "."
+       :base-extension "org"
+       :recursive t
+       :publishing-directory "../html"
+       :publishing-function org-html-publish-to-html
+
+       :html-doctype "html5"
+       :html-html5-fancy t
+
+       :html-viewport ((width "100%")
+                       (initial-scale "0.7")
+                       (minimum-scale "")
+                       (maximum-scale "")
+                       (user-scalable ""))
+
+       :language "en"
+       :section-numbers nil
+
+       :with-toc nil
+       :with-date t
+       :with-title nil
+       :with-author nil
+
+       :auto-sitemap t
+
+       :sitemap-sort-files anti-chronologically
+       :sitemap-format-entry blog/sitemap-format-entry
+
+       :sitemap-function
+       blog/sitemap-function
+
+
+       :headline-levels 4
+       :html-head ,html-head
+
+       :html-preamble ,html-preamble
+       :html-postamble
+       (lambda (p)
+         (let* ((timestamp-format  (plist-get p :html-metadata-timestamp-format))
+                (date (org-export-data (org-export-get-date p timestamp-format)
+                                       p))
+                (file (plist-get p :input-file))
+                (modified (format-time-string
+                           timestamp-format
+                           (and file (file-attribute-modification-time
+                                      (file-attributes file))))))
+           (concat
+            "<div id='footer'>"
+            (when (not (string-blank-p (format "%s" date)))
+              (format "<div id='publish-date'>Published: %s</div>" date))
+            (format "<div id='modified-date'>Last modified: %s</div>" modified)
+            ,html-postamble
+            "</div>"))))
+
+      ("static"
+       :base-directory "../static"
+       :base-extension "css\\|txt\\|jpg\\|gif\\|png\\|ttf\\|js\\|mp4\\|webm"
+       :recursive t
+       :publishing-directory  "../html/static"
+       :publishing-function org-publish-attachment)
+
+      ("RSS"
+       :base-directory "../RSS"
+       :base-extension "xml"
+       :publishing-directory "../html"
+       :publishing-function org-publish-attachment)
+
+      ("blog" :components ("pages" "static" "RSS")))))
+
+(defun blog/publish ()
+  (setq org-publish-project-alist (blog/spec))
+  (org-publish-all))
+
+(defun blog/force-publish ()
+  (setq org-publish-project-alist (blog/spec))
+  (org-publish-remove-all-timestamps)
+  (org-publish-all))
+
+
+
+
+
+
+

Features

+
+
+
+

Sitemap   autocollapse

+
+

+Files with #+FILETAGS: :no-sitemap: at the top will be excluded from the sitemap. Every directory dir/ will link to dir/index.org, with index.org being removed as a child entry. +

+
+
(defun blog/sitemap-format-entry
+    (entry style project)
+  ;; Blank out entries with :no_sitemap:
+  (let* ((tags (org-publish-find-property entry :filetags project))
+         (skip (member "no_sitemap" tags)))
+
+    (cond
+     (skip "")
+
+     ((not (directory-name-p entry))
+      (format
+       "[[file:%s][%s]]\n"
+       entry
+       (org-publish-find-title entry project)))
+
+     ;; Link index to top level
+     ((eq style 'tree)
+      (format
+       "[[file:%sindex.org][%s]]\n"
+       entry
+       (capitalize (file-name-nondirectory (directory-file-name entry)))))
+
+     (t entry))))
+
+
+;; Remove blank entries from sitemap
+(defun blog/sitemap-function
+    (title lst)
+  (let* ((sitemap (org-publish-sitemap-default title lst)))
+    (replace-regexp-in-string "^[ \t]*-[ \t]*\n" "" sitemap)))
+
+
+
+
+
+
+

Tag-based Section Control   autocollapse

+
+

+Org-mode headers support tags: +

+
+
* Header :foo:
+    Sample text
+
+
+ +

+Which will compile into something like: +

+
+
<div id="outline-container-orgf43334f" class="outline-5">
+  <h5 id="orgf43334f" style="cursor: pointer;">Header
+    <span class="tag">
+      <span class="foo">foo</span>
+    </span>
+  </h5>
+  <div class="outline-text-5" id="text-orgf43334f">
+    <p> Sample text </p>
+  </div>
+</div>
+
+
+ +

+We can use these tags to granularly control styling and JS features per header. +We will hide the tags themselves: +

+ +
+
.tag { display: none; }
+
+
+
+
+
+

Header Styling Tags   autocollapse

+
+

+Tags for granular styling. This page has :h4left:h5left:h3underline: at the top level. +

+
+
div:has(* .tag .h4left) h4 {
+    text-align: left;
+}
+
+div:has(* .tag .h5left) h5 {
+    text-align: left;
+}
+
+div:has(* .tag .h3underline) h3 {
+    text-decoration: underline;
+}
+
+
+
+
+
+

Journal   autocollapse

+
+

+Here’s a template for the journal files, as reference for what follows: +

+
+
+
Template   autocollapse
+
+
+
#+FILETAGS: :no_sitemap:
+#+TODO: NO(n) | YES(y) EXCELLENT(e) FREED(f)
+#+title: Journal Week XX, YYYY
+#+BEGIN_CENTER
+Previous | Index
+#+END_CENTER
+* Journal Week XX, YYYY
+** Monday, ZZth MMMM
+:PROPERTIES:
+:DAILIES-YEAR: YYYY
+:DAILIES-DAY: DDD
+:END:
+*** NO Journal
+:PROPERTIES:
+:CUSTOM_ID: dailies-blogging
+:END:
+*** Habits :autocollapse:
+**** NO Meditation
+:PROPERTIES:
+:CUSTOM_ID: dailies-meditation
+:END:
+**** NO Drawing
+:PROPERTIES:
+:CUSTOM_ID: dailies-drawing
+:END:
+**** NO Engineering
+:PROPERTIES:
+:CUSTOM_ID: dailies-engineering
+:END:
+**** NO French
+:PROPERTIES:
+:CUSTOM_ID: dailies-french
+:END:
+**** NO Social
+:PROPERTIES:
+:CUSTOM_ID: dailies-social
+:END:
+**** NO Exercise
+:PROPERTIES:
+:CUSTOM_ID: dailies-exercise
+:END:
+**** NO Reading
+:PROPERTIES:
+:CUSTOM_ID: dailies-reading
+:END:
+
+
+
+
+
+
Styling
+
+
+
div:has(h3 .tag .journal) {
+    border: none;
+    box-shadow: none;
+}
+
+div:has(> h3 .tag .journal)::after {
+    content: '~ ❦ ~';
+    display: block;
+    text-align: center;
+    padding-top: 0.2rem;
+    padding-bottom: 0.2rem;
+    color: var(--grey4);
+    font-size: 2rem;
+}
+
+h3:has(.tag .journal) {
+    text-align: left;
+}
+
+h4:has(.tag .jentry) {
+    display: none;
+}
+
+h4:has(.tag .habits) {
+    text-align: left;
+}
+
+
+
+
+
+
+

Habit Tracker   autocollapse

+
+

+Implements the habit tracking table on the front page. Habits are extracted from journal entries and rendered into a table, including a “streak” heatmap and the ability to click cells to see the corresponding entry. +

+
+
+
Elisp   autocollapse
+
+
+
(defun akk0/org-to-html (org-string)
+  "Convert ORG-STRING to HTML."
+  (with-temp-buffer
+    (insert org-string)
+    (org-mode)
+    (org-export-as 'html nil nil t nil)))
+
+(defun akk0/sort-habits (habit-alist)
+  "Sort habit-alist by a predefined order of custom-ids."
+  (let ((order '("dailies-blogging" "dailies-meditation" "dailies-french"  "dailies-engineering"
+                 "dailies-exercise" "dailies-drawing" "dailies-reading" "dailies-social")))
+    (sort (copy-sequence habit-alist)
+          (lambda (a b)
+            (let ((pos-a (or (cl-position (car a) order :test #'equal) 999))
+                  (pos-b (or (cl-position (car b) order :test #'equal) 999)))
+              (< pos-a pos-b))))))
+
+
+(defun akk0/extract-habits (file)
+  "Extract habits with date context from FILE.
+Returns a list of plists with :custom-id, :todo-state, :date, :day-of-year."
+  (with-temp-buffer
+    (insert-file-contents file)
+    (org-mode)
+    (let (results)
+      (org-element-map (org-element-parse-buffer) 'headline
+        (lambda (hl)
+          (let ((custom-id (org-element-property :CUSTOM_ID hl))
+                (todo-state (org-element-property :todo-keyword hl)))
+            (when (and custom-id todo-state)
+              ;; Get parent properties for context
+              (let* ((parent (org-element-property :parent hl))
+                     (day-of-year (or (org-element-property :DAILIES-DAY parent)
+                                     (let ((grandparent (org-element-property :parent parent)))
+                                       (when grandparent
+                                         (org-element-property :DAILIES-DAY grandparent)))))
+                     (body (org-element-interpret-data
+                            (org-element-contents hl))))
+                (push (list :custom-id custom-id
+                            :todo-state todo-state
+                            :day-of-year day-of-year
+                            :file file
+                            :body body)
+                      results))))))
+      (nreverse results))))
+
+(defun akk0/extract-all-habits (files)
+  (mapcan #'akk0/extract-habits files))
+
+(setq akk0/journal-files
+      (directory-files "./journal/" t "^w.*\\.org$"))
+
+(defun akk0/habits-alist (habits)
+  "Transform HABITS list into nested alists: custom-id → day-of-year → habit-data."
+  (let (result)
+    (dolist (habit habits)
+      (let* ((custom-id (plist-get habit :custom-id))
+             (day-of-year (plist-get habit :day-of-year))
+             (todo-state (plist-get habit :todo-state))
+             (body (plist-get habit :body))
+             ;; Get the alist for this custom-id
+             (inner-alist (alist-get custom-id result nil nil #'equal))
+             ;; Store full data instead of just todo-state
+             (habit-data (list :todo-state todo-state :body body :day-of-year day-of-year))
+             ;; Update the inner alist
+             (updated-inner (cons (cons day-of-year habit-data) inner-alist)))
+        ;; Update result
+        (setf (alist-get custom-id result nil nil #'equal) updated-inner)))
+    result))
+
+
+(setq habit-alist (akk0/habits-alist (akk0/extract-all-habits akk0/journal-files)))
+
+(defun akk0/get-habit-history (habit-alist custom-id day-number days-back window-size)
+  (let* ((inner-alist (alist-get custom-id habit-alist nil nil #'equal))
+         (result nil)
+         (all-states nil)
+         (score-for-state (lambda (state)
+                            (cond ((equal state "NO") -1)
+                                  ((equal state "YES") 1)
+                                  ((equal state "EXCELLENT") 2)
+                                  (t 0)))))
+    (dotimes (i days-back)
+      (let* ((current-day (+ (- day-number days-back) i 1))
+             (current-day-str (number-to-string current-day))
+             (habit-data (alist-get current-day-str inner-alist nil nil #'equal))
+             (todo-state (if habit-data
+                            (plist-get habit-data :todo-state)
+                          "NODATA"))
+             (body (if habit-data
+                      (plist-get habit-data :body)
+                    ""))
+
+             (doy (if habit-data
+                      (plist-get habit-data :day-of-year)
+                    ""))
+             )
+        (push todo-state all-states)
+        (let* ((window-states (seq-take all-states window-size))
+               (rolling-score (apply #'+ (mapcar score-for-state window-states))))
+          (push (list :todo-state todo-state
+                     :score (max 1 (min 5 (/ (+ rolling-score 5) 2)))
+                     :body body
+                     :doy doy)
+                result))))
+    (nreverse result)))
+
+(defun akk0/habits-to-html-table (habit-alist day-number days-back window-size)
+  "Generate HTML table of habits with rolling scores.
+Rows are custom-ids, columns are days."
+  (let ((color-map '(("NODATA" . "grey")
+                     ("YES" . "green")
+                     ("NO" . "red")
+                     ("FREED" . "purple")
+                     ("EXCELLENT" . "blue")))
+        (symbol-map '(("NODATA" . "")
+                     ("YES" . "●")
+                     ("NO" . "×")
+                     ("FREED" . "♣")
+                     ("EXCELLENT" . "♦")))
+
+        (sorted-habits (akk0/sort-habits habit-alist))
+        (html ""))
+    ;; Start table
+    (setq html (concat html "<table style='margin-left: auto; margin-right:auto; margin-bottom: 0.8rem;'>\n"))
+
+    ;; Header row with day numbers
+    (setq html (concat html "  <tr>\n    <th></th>\n"))
+    (dotimes (i days-back)
+      (let ((day (+ (- day-number days-back) i 1)))
+        (setq html (concat
+                    html
+                    (cond ((= day day-number) "<th>●</th>")
+                          ((= 0 (% (- day day-number) 7)) "<th>○</th>")
+                          (t "<th />"))))))
+    (setq html (concat html "  </tr>\n"))
+
+
+    ;; Data rows - one per habit
+    (dolist (entry sorted-habits)
+      (let* ((custom-id (car entry))
+             (history (akk0/get-habit-history habit-alist custom-id day-number days-back window-size)))
+        (setq html (concat html (format "  <tr>\n    <td style='padding-right: 20px; padding-top: 5px; padding-bottom: 5px;'><i>%s</i></td>\n" (capitalize (string-remove-prefix "dailies-" custom-id)))))
+
+        ;; Cell for each day
+        (dolist (day-data history)
+          (let* ((todo-state (plist-get day-data :todo-state))
+                 (score (plist-get day-data :score))
+                 (body (plist-get day-data :body))
+                 (doy (plist-get day-data :doy))
+                 (body-html (if (and body (not (string-empty-p body)))
+                               (akk0/org-to-html body)
+                             ""))
+                 (color (alist-get todo-state color-map nil nil #'equal))
+                 (symbol (alist-get todo-state symbol-map nil nil #'equal))
+                 (class (format "habit-brightness-%d" score))
+                 (style-var (format "--%s%d" color score))
+                 (escaped-body (replace-regexp-in-string "\"" "&quot;"
+                                 (replace-regexp-in-string "\n" "&#10;" body-html)))
+                 )
+            (setq html (concat html (format "    <td class=\"%s habit-cell\" style=\"background-color:var(%s)\" data-body=\"%s\" onclick=\"showHabitPopup(this)\" data-doy=\"%s\" data-activity=\"%s\"
+            data-status=\"%s\">%s</td>\n"
+                                            class style-var
+                                            escaped-body
+                                            doy
+                                            custom-id
+                                            todo-state
+                                            symbol)))))
+
+        (setq html (concat html "  </tr>\n"))))
+
+    (setq html (concat html "</table>\n"))
+
+    ;; Legend and expansion section
+    (setq html (concat html "<span class='center'><b>Key:</b>
+<span style='color: var(--grey3);'>Unknown</span> |
+<span style='color: var(--red3);'>× No</span> |
+<span style='color: var(--green3);'>● Yes</span> |
+<span style='color: var(--blue3);'>♦ Excellent</span> |
+<span style='color: var(--purple3);'>♣ Freed Up</span>
+</span>
+<hr />
+<div class='habit-popup' id='habitPopup'>
+  <div class='habit-popup-content' id='habitPopupContent'>
+    <span class='center'><i>This section intentionally left blank.</i></span>
+  </div>
+</div>
+"))
+
+    html))
+
+(akk0/habits-to-html-table habit-alist (string-to-number (format-time-string "%j")) 30 5)
+
+
+
+
+
+
Expansion Section   autocollapse
+
+

+A bit of JS for enabling the expanding of entries. +

+
+
function formatDayOfYear(dayOfYear, year) {
+  const date = new Date(year, 0, dayOfYear);
+
+  return date.toLocaleDateString('en-GB', {
+    day: 'numeric',
+    month: 'short',
+    year: 'numeric'
+  });
+}
+
+let selectedCell = null;
+
+function showHabitPopup(cell) {
+  var bodyHtml = cell.getAttribute('data-body');
+  var doy = cell.getAttribute('data-doy');
+  var activity = cell.getAttribute('data-activity');
+  var status = cell.getAttribute('data-status');
+  activity = activity.replace(/^dailies-/, '').replace(/^./, c => c.toUpperCase())
+
+  if (!bodyHtml) bodyHtml = "<span class='center'><i>This section intentionally left blank.</i></span>"
+
+  bodyHtml = `<h3><span class="grid ${status}">${activity}</span> — ${formatDayOfYear(parseInt(doy), 2025)}</h3> ${bodyHtml}`
+
+  document.getElementById('habitPopupContent').innerHTML = bodyHtml;
+
+  if (selectedCell) {
+    selectedCell.classList.remove('habitgrid-selected');
+  }
+
+  cell.classList.add('habitgrid-selected');
+  selectedCell = cell;
+  enableFootnotes();
+}
+
+
+
+
+
+
CSS   autocollapse
+
+

+Color habit entries based on their completion status: +

+
+
.done.YES, .todo.NO, .done.EXCELLENT, .done.FREED {
+    display: none;
+}
+
+h2:has(.done.YES), h3:has(.done.YES), h4:has(.done.YES), h5:has(.done.YES), .grid.YES {
+    color: var(--green3);
+}
+
+h2:has(.todo.NO), h3:has(.todo.NO), h4:has(.todo.NO), h5:has(.todo.NO), .grid.NO {
+    color: var(--red3);
+}
+
+h2:has(.done.EXCELLENT), h3:has(.done.EXCELLENT), h4:has(.done.EXCELLENT), h5:has(.done.EXCELLENT), .grid.EXCELLENT {
+    color: var(--blue3);
+}
+
+h2:has(.done.FREED), h3:has(.done.FREED), h4:has(.done.FREED), h5:has(.done.FREED), .grid.FREED {
+    color: var(--purple3);
+}
+
+
+ +

+Style the cells, set legible text color, outline clickable: +

+
+
.habit-cell {
+    text-align: center;
+    vertical-align: middle;
+    width: 20px;
+    height: 20px;
+    cursor: pointer;
+    user-select: none;
+}
+
+.habit-cell.habit-brightness-1 { color: var(--grey5); outline-color: var(--grey5) !important; }
+.habit-cell.habit-brightness-2 { color: var(--grey5); outline-color: var(--grey5) !important; }
+.habit-cell.habit-brightness-3 { color: var(--grey5); outline-color: var(--grey5) !important; }
+.habit-cell.habit-brightness-4 { color: var(--grey2); outline-color: var(--grey5) !important; }
+.habit-cell.habit-brightness-5 { color: var(--grey3); outline-color: var(--grey5) !important; }
+
+.habit-cell:not([data-body=""]) {
+    outline: dotted 2px;
+    outline-offset: -2px;
+}
+.habitgrid-selected {
+    outline: solid 2px var(--purple5) !important;
+    outline-offset: -2px;
+}
+
+
+
+
+
+
+

Header Collapsing   autocollapse

+
+

+Sections can be expanded and collapsed by clicking on their headers; this will assign .orgjq-expanded and .orgjq-contracted CSS classes as appropriate. Headers with the :autocollapse: tag will be collapsed by default (like this section). +

+
+
.orgjq-expanded p {
+    margin-top: 0;
+    padding-bottom: 1.5rem;
+    margin-bottom: 0;
+}
+
+.orgjq-contracted > div {
+    display: none;
+}
+
+.orgjq-contracted h2, .orgjq-contracted h3, .orgjq-contracted h4, orgjq-contracted h5 {
+    padding-top: 0.3rem !important;
+    padding-bottom: 0.3rem !important;
+}
+
+.orgjq-contracted > :first-child::before {
+    content: '⮞ ';
+}
+
+.orgjq-expanded > h4:has(.tag .autocollapse)::before {
+    content: '⮟ ';
+}
+
+
+ +
+
function isHideable(div_obj) {
+  // Ignore for TOC since it is handled differently
+  if (div_obj.id === "text-table-of-contents") return false;
+  if (div_obj.id === "table-of-contents") return false;
+  // No point in hiding top level
+  if (div_obj.classList.contains("outline-2")) return false;
+  if (div_obj.classList.contains("outline-text-2")) return false;
+  return true;
+}
+
+function orgjqHide(div_obj) {
+  if (!isHideable(div_obj)) return;
+  const parent = div_obj.parentElement;
+  parent.classList.remove("orgjq-expanded");
+  parent.classList.add("orgjq-contracted");
+}
+
+function orgjqShow(div_obj) {
+  const parent = div_obj.parentElement;
+  parent.classList.remove("orgjq-contracted");
+  parent.classList.add("orgjq-expanded");
+}
+
+function orgjqToggle(div_obj) {
+  const parent = div_obj.parentElement;
+  if (parent.classList.contains("orgjq-expanded")) {
+    orgjqHide(div_obj);
+  } else {
+    orgjqShow(div_obj);
+  }
+}
+
+function orgjqEnable() {
+  // Called once e.g. the first time the page is loaded
+  // handle the click event for each header
+  for (let i = 2; i <= 7; ++i) {
+    const headers = document.querySelectorAll(`h${i}`);
+    headers.forEach(header => {
+      header.style.cursor = "pointer";
+      header.addEventListener('click', function() {
+        // Get the first div sibling after the header
+        const parent = this.parentElement;
+        const divs = parent.querySelectorAll(':scope > div');
+        if (divs.length > 0) {
+          orgjqToggle(divs[0]);
+        }
+      });
+    });
+  }
+
+  // Mark everything as open...
+  for (let i = 2; i <= 7; ++i) {
+    const headers = document.querySelectorAll(`h${i}`);
+    headers.forEach(header => {
+      const parent = header.parentElement;
+      parent.classList.remove("orgjq-contracted");
+      parent.classList.add("orgjq-expanded");
+    });
+  }
+
+  // ... except TOC ...
+  const toc = document.querySelector("div#table-of-contents");
+  if (toc) {
+    toc.classList.remove("orgjq-expanded");
+    toc.classList.add("orgjq-contracted");
+  }
+  // ... and autocollapse.
+  const autocollapse = document.querySelectorAll(".autocollapse");
+  autocollapse.forEach(element => {
+    const grandparent = element.parentElement?.parentElement;
+    if (grandparent) {
+      orgjqHide(grandparent);
+    }
+  });
+}
+
+// Run when DOM is loaded
+if (document.readyState === 'loading') {
+  document.addEventListener('DOMContentLoaded', orgjqEnable);
+} else {
+  orgjqEnable();
+}
+
+
+
+
+
+

Hover Notes   autocollapse

+
+

+Turns org-mode footnotes ([fn::Like this]) into hover-notes1. +

+
+
function enableFootnotes() {
+  const footnoteRefs = document.querySelectorAll('.footref')
+
+  footnoteRefs.forEach(ref => {
+    const footnoteId = ref.href.split('#')[1]
+    ref.setAttribute('data-footnote-id', footnoteId)
+    ref.href = 'javascript:void(0)';
+
+    ref.addEventListener('mouseenter', function() {
+      // Find footnote element
+      const footnoteId = this.getAttribute('data-footnote-id')
+
+      const footnoteElement = document.getElementById(footnoteId).parentElement.nextElementSibling.children[0]
+
+      if (footnoteElement) {
+        // Create tooltip container
+        const tooltip = document.createElement('div');
+        tooltip.className = 'footnote-tooltip'
+        tooltip.innerHTML = footnoteElement.innerHTML
+
+        // Position tooltip
+        const rect = this.getBoundingClientRect();
+        tooltip.style.position = 'absolute'
+        tooltip.style.top = (rect.bottom + window.scrollY + 5) + 'px'
+        tooltip.style.left = rect.left + 'px'
+
+        // Add to page
+        document.body.appendChild(tooltip)
+
+        // Store reference for cleanup
+        this._tooltip = tooltip
+      }
+    });
+
+    ref.addEventListener('mouseleave', function() {
+      // Remove tooltip
+      if (this._tooltip) {
+        this._tooltip.remove()
+        this._tooltip = null
+      }
+    });
+  });
+
+  // Hide footnotes section
+  document.querySelector("#footnotes").style.display='none'
+}
+
+document.addEventListener('DOMContentLoaded', enableFootnotes);
+
+
+
+
+
+
+

Appearance

+
+
+
+

Global   autocollapse

+
+
+
+
Variables
+
+
+
:root {
+    --site-width: 1000px;
+    --vert-content-margin: 0.3rem;
+
+    --font-size: 1.2rem;
+    --line-height: 1.6rem;
+    --font-family: "Source Serif Pro";
+
+    --scale: 2;
+}
+
+
+
+
+
+
Color Variables
+
+
+
:root {
+    --green1: #123218;
+    --green2: #254f1b;
+    --green3: #356c22;
+    --green4: #5e8e40;
+    --green5: #85aa5f;
+
+    --blue1: #1b2459;
+    --blue2: #153a79;
+    --blue3: #2f5394;
+    --blue4: #417eaf;
+    --blue5: #69a8c6;
+
+    --purple1: #2e1e58;
+    --purple2: #493281;
+    --purple3: #6a45a6;
+    --purple4: #855aa3;
+    --purple5: #9b77b5;
+
+    --red1: #4b1313;
+    --red2: #682017;
+    --red3: #84301c;
+    --red4: #9c4830;
+    --red5: #c46849;
+
+    --grey1: #202124;
+    --grey2: #33333b;
+    --grey3: #605b66;
+    --grey4: #a79fa7;
+    --grey5: #c5bcbc;
+
+    --accent1: var(--purple4);
+    --link: var(--blue3);
+    --black: var(--grey1);
+    --grey: var(--grey3);
+    --background: var(--grey5);
+    --background-tooltip: var(--grey5);
+}
+
+
+
+
+
+
Background image
+
+
+
body::before,
+body::after {
+    content: '';
+    position: fixed;
+    top: 0;
+    height: 100vh;
+    width: 50%;
+    background-image: url('/static/images/background.png');
+    background-repeat: no-repeat;
+    z-index: -1;
+
+    image-rendering: pixelated; /* For Chrome/Safari */
+    image-rendering: -moz-crisp-edges; /* For Firefox */
+    image-rendering: crisp-edges; /* Fallback */
+
+    background-size: calc(960px * var(--scale)) calc(1080px * var(--scale));
+}
+
+body::before {
+    left: 0;
+    background-position: top right;
+}
+
+body::after {
+    right: 0;
+    background-position: top right;
+    /* Flip the right side horizontally */
+    transform: scaleX(-1);
+}
+
+
+
+
    +
  • TODO This is a weird approach and has some issues
    +
    +
      +
    • White line in center in some setups
    • +
    • Crunchy lines depending on DPI
    • +
    +
    +
  • +
+
+
+
Fonts
+
+
+
body {
+    font-family: var(--font-family);
+    font-size: var(--font-size);
+    line-height: var(--line-height);
+    word-spacing: 0.25ch;
+    font-weight: 400;
+}
+
+
+
+
+
+
Header/Content/Footer blocks
+
+
+
#content, #header, #footer {
+    min-width: 500px;
+    max-width: min(var(--site-width), 90vw);
+    margin: 0 auto;
+    padding: 5px 25px;
+
+    border: 2px double var(--grey1);
+    margin-bottom: 1.2rem;
+    background-color: var(--background);
+}
+
+#header {
+    display: flex;
+}
+
+#content, #footer {
+    box-shadow: 7px 7px 7px var(--grey1);
+}
+
+#footer {
+    padding-top: 1rem;
+    padding-bottom: 1rem;
+}
+
+#header a, #header a:visited{
+    color: var(--purple2);
+}
+
+#header hr {
+    margin-bottom: var(--vert-content-margin);
+}
+
+#footer hr {
+    margin-top: var(--vert-content-margin);
+}
+
+#content h2, #content h3, #content h4, #content h5 {
+    margin-bottom: 1rem;
+    margin-top: 0.5rem;
+    margin-left: 0.5rem;
+}
+
+#content h2 {
+    margin-top: 1rem;
+}
+
+#content h3, #content h4 {
+    padding-top: 0.5rem;
+    padding-bottom: 0.5rem;
+}
+
+#content h5 {
+    padding-top: 0.3rem;
+    padding-bottom: 0.3rem;
+}
+
+
+
+
+
+
+
+

Colors   autocollapse

+
+
+
+
Color Assignments
+
+
+
body {
+    color: var(--black);
+    background-color: var(--background);
+}
+
+
+
+
+
+
+
Syntax Highlighting
+
+
+
pre                                      {background-color:var(--grey1); color:var(--grey5);}
+pre span.org-builtin                     {color:var(--blue4);font-weight:bold;}
+pre span.org-string                      {color:var(--green4);}
+pre span.org-keyword                     {color:var(--purple5);font-weight:bold;}
+pre span.org-variable-name               {color:var(--green5);font-style:italic;}
+pre span.org-function-name               {color:var(--blue5);}
+pre span.org-type                        {color:var(--purple4);}
+pre span.org-preprocessor                {color:var(--grey5);font-weight:bold;}
+pre span.org-constant                    {color:var(--red5);}
+pre span.org-comment-delimiter           {color:var(--grey3);}
+pre span.org-comment                     {color:var(--grey3);font-style:italic}
+pre span.org-outshine-level-1            {color:var(--grey5);font-style:italic}
+pre span.org-outshine-level-2            {color:var(--grey5);font-style:italic}
+pre span.org-outshine-level-3            {color:var(--grey5);font-style:italic}
+pre span.org-outshine-level-4            {color:var(--grey5);font-style:italic}
+pre span.org-outshine-level-5            {color:var(--grey5);font-style:italic}
+pre span.org-outshine-level-6            {color:var(--grey5);font-style:italic}
+pre span.org-outshine-level-7            {color:var(--grey5);font-style:italic}
+pre span.org-outshine-level-8            {color:var(--grey5);font-style:italic}
+pre span.org-outshine-level-9            {color:var(--grey5);font-style:italic}
+pre span.org-rainbow-delimiters-depth-1  {color:var(--grey4);}
+pre span.org-rainbow-delimiters-depth-2  {color:var(--blue4);}
+pre span.org-rainbow-delimiters-depth-3  {color:var(--green4);}
+pre span.org-rainbow-delimiters-depth-4  {color:var(--red4);}
+pre span.org-rainbow-delimiters-depth-5  {color:var(--purple4);}
+pre span.org-rainbow-delimiters-depth-6  {color:var(--blue4);}
+pre span.org-rainbow-delimiters-depth-7  {color:var(--green4);}
+pre span.org-rainbow-delimiters-depth-8  {color:var(--red4);}
+pre span.org-rainbow-delimiters-depth-9  {color:var(--purple4);}
+pre span.org-sh-quoted-exec              {color:var(--purple3);}
+pre span.org-doc                         {color:var(--green5);font-style:italic;}
+pre span.org-css-selector                {color:var(--blue5);font-weight:bold;}
+pre span.org-css-property                {color:var(--purple4); font-weight: bold;}
+
+
+
+
+
+
+

General CSS   autocollapse

+
+
+
+
Et Cetera
+
+
+
hr {
+    border: 0;
+    border-top: 2px dotted var(--black);
+}
+
+a, a:visited {
+    color: var(--link);
+    text-decoration: none;
+}
+
+.figure-number {
+    display: none;
+}
+
+.caption {
+    padding-top: 0.5rem;
+    font-style: italic;
+}
+
+.outline-3, .outline-4, .outline-5 {
+    padding-left: 0.6rem;
+    border-radius: 0.2em;
+    margin: 0.7rem;
+}
+
+.outline-text-3, .outline-text-4, .outline-text-5 {
+    margin: 0.3rem 1rem 0.5rem 0.5rem;
+}
+
+h2 {
+    line-height: 1.5rem;
+    text-align: center;
+}
+
+h3, h4, h5 {
+    text-align: center;
+}
+
+.section-number-1, .section-number-2, .section-number-3, .section-number-4 { display: none; }
+
+
+
+
+
+
Utility Classes
+
+
+
.center {
+    display: block;
+    margin-left: auto;
+    margin-right: auto;
+    text-align: center;
+}
+
+.navbar-link {
+    margin-right: 5px;
+    margin-left: 5px;
+}
+
+.center, div.center {
+    text-align: center;
+    margin-left: auto;
+    margin-right: auto;
+}
+
+.center figure,
+.center figcaption,
+div.center figure,
+div.center figcaption {
+    text-align: center;
+    margin-left: auto;
+    margin-right: auto;
+}
+
+.multi-img {
+    display: flex;
+    justify-content: center;
+    text-align: center;
+    margin: 20px;
+    gap: 20px;
+}
+
+.multi-img figure { margin: 0px; }
+
+.poetry {
+    padding-top: 4rem;
+    padding-bottom: 4rem;
+    text-align: center;
+}
+
+
+
+
+
+
+

Elements   autocollapse

+
+
+
+
Looking for Work
+
+
+
#looking-for-work {
+    background-color: var(--red2);
+    color: var(--grey5);
+    padding: 5px 25px;
+    margin-left: auto;
+    margin-top: -0.32rem;
+    margin-bottom: -0.32rem;
+    margin-right: -1.55rem;
+    border: 2px double var(--purple5);
+}
+
+#looking-for-work a, #looking-for-work a:visited {
+    color: var(--blue5) !important;
+}
+
+
+
+
+
+
Code Blocks
+
+
+
.src, .example {
+    font-family: "monospace";
+    font-size: 1rem;
+}
+
+
+
+
+
+
Publish/modified Date
+
+
+
#publish-date, #modified-date {
+    font-style: italic;
+}
+
+
+
+
+
+
Table of Contents
+
+
+
#table-of-contents {
+    z-index: 1;
+    margin-top: 105px;
+    margin-right: 5%;
+    font-size: calc(var(--font-size) * 0.8);
+    position: fixed;
+    right: 0em;
+    top: 0em;
+    background: var(--background-toc);
+    text-align: right;
+    min-height: 3rem;
+
+    box-shadow: 0 0 0.5em var(--shadow-toc);
+    -webkit-box-shadow: 0 0 0.5em var(--shadow-toc);
+    -moz-box-shadow: 0 0 0.5em var(--shadow-toc);
+    -webkit-border-bottom-left-radius: 5px;
+    -moz-border-radius-bottomleft: 5px;
+    /* ensure doesn't flow off the screen when expanded */
+    max-height: 80%;
+    overflow: auto;
+}
+#table-of-contents h2 {
+    font-size: 13pt;
+    max-width: 9em;
+    border: 0;
+    font-weight: normal;
+    margin-top: 0.75em;
+    margin-bottom: 0.75em;
+    padding-left: 0.5em;
+    padding-right: 0.5em;
+    padding-top: 0.05em;
+    padding-bottom: 0.05em; }
+#table-of-contents #text-table-of-contents {
+    display: none;
+    text-align: left; }
+#table-of-contents:hover #text-table-of-contents {
+    display: block;
+    padding: 0.5em;
+    margin-top: -1.5em;
+    padding-right: 20px;
+}
+
+#table-of-contents {
+    display: none;
+}
+
+
+
+
+
+
To-Dos
+
+
+
.TODO { color: var(--red3); }
+.DONE { color: var(--green3); }
+
+
+
+
+
+
+
+
+

Footnotes:

+
+ +
1

Like this

+ + +
+
+
+ +
+ + diff --git a/html/static/collapse.css b/html/static/collapse.css deleted file mode 100644 index e834c7a..0000000 --- a/html/static/collapse.css +++ /dev/null @@ -1,3 +0,0 @@ -.orgjq-contracted > div { - display: none; -} diff --git a/html/static/custom.css b/html/static/custom.css deleted file mode 100644 index d996870..0000000 --- a/html/static/custom.css +++ /dev/null @@ -1,230 +0,0 @@ -.poetry { - padding-top: 4rem; - padding-bottom: 4rem; - text-align: center; -} - - -.figure-number { - display: none; -} - -.center, div.center { - text-align: center; - margin-left: auto; - margin-right: auto; -} - -.center figure, -.center figcaption, -div.center figure, -div.center figcaption { - text-align: center; - margin-left: auto; - margin-right: auto; -} - -.multi-img { - display: flex; - justify-content: center; - text-align: center; - margin: 20px; - gap: 20px; -} - -.multi-img figure { margin: 0px; } - -.caption { - padding-top: 0.5rem; - font-style: italic; -} - -.outline-3, .outline-4, .outline-5 { - padding-left: 0.6rem; - border-radius: 0.2em; - margin: 0.7rem; - - #box-shadow: 1px 1px 1px var(--grey2); - #border: 1px solid var(--grey4); -} - -.outline-text-3, .outline-text-4, .outline-text-5 { - margin: 0.3rem 1rem 0.5rem 0.5rem; -} -/* -.outline-3 { - border-left: 1px inset var(--red5); -} - -.outline-4 { - border-left: 1px inset var(--purple3); -} - -.outline-5 { - border-left: 1px inset var(--blue4); -} - */ - -/* -.outline-5::after { - content: "⇜"; - display: block; - text-align: right; - margin-top: -2.0rem; -} - */ - - -.orgjq-expanded p { - margin-top: 0; -} - -/* -.outline-3.orgjq-contracted h3::before { - content: "🡒 "; -} - -.outline-4.orgjq-contracted h4::before { - content: "⤳ "; -} - -.outline-5 h5::before { - content: "⇝ "; -} - */ - -#content h2, #content h3, #content h4, #content h5 { - margin-bottom: 1rem; - margin-top: 0.5rem; - margin-left: 0.5rem; -} - -#content h3 { - padding-top: 0.5rem; - padding-bottom: 0.5rem; -} - -#content h4 { - padding-top: 0.5rem; - padding-bottom: 0.5rem; -} - -#content h5 { - padding-top: 0.3rem; - padding-bottom: 0.3rem; -} - -.orgjq-contracted h2, .orgjq-contracted h3, .orgjq-contracted h4, orgjq-contracted h5 { - padding-top: 0.3rem !important; - padding-bottom: 0.3rem !important; -} - -#content h2 { - margin-top: 1rem; -} - -.orgjq-expanded p { - padding-bottom: 1.5rem; - margin-bottom: 0; -} - -#content, #footer { - box-shadow: 7px 7px 7px var(--grey1); -} - -h2 { - line-height: 1.5rem; - text-align: center; -} - -h3, h4, h5 { - text-align: center; -} - -#table-of-contents { - display: none; -} - -.done.YES, .todo.NO, .done.EXCELLENT, .done.FREED { - display: none; -} - -h2:has(.done.YES), h3:has(.done.YES), h4:has(.done.YES), h5:has(.done.YES), .grid.YES { - color: var(--green3); -} - -h2:has(.todo.NO), h3:has(.todo.NO), h4:has(.todo.NO), h5:has(.todo.NO), .grid.NO { - color: var(--red3); -} - -h2:has(.done.EXCELLENT), h3:has(.done.EXCELLENT), h4:has(.done.EXCELLENT), h5:has(.done.EXCELLENT), .grid.EXCELLENT { - color: var(--blue3); -} - -h2:has(.done.FREED), h3:has(.done.FREED), h4:has(.done.FREED), h5:has(.done.FREED), .grid.FREED { - color: var(--purpl3); -} - -.tag { display: none; } - -.habit-cell { - text-align: center; - vertical-align: middle; - width: 20px; - height: 10px; - cursor: pointer; - user-select: none; -} - - -.habit-cell.habit-brightness-1 { color: var(--grey5); outline-color: var(--grey5) !important; } -.habit-cell.habit-brightness-2 { color: var(--grey5); outline-color: var(--grey5) !important; } -.habit-cell.habit-brightness-3 { color: var(--grey5); outline-color: var(--grey5) !important; } -.habit-cell.habit-brightness-4 { color: var(--grey2); outline-color: var(--grey5) !important; } -.habit-cell.habit-brightness-5 { color: var(--grey3); outline-color: var(--grey5) !important; } - -.habit-cell:not([data-body=""]) { - outline: dotted 2px; - outline-offset: -2px; -} -.habitgrid-selected { - outline: solid 2px var(--purple5) !important; - outline-offset: -2px; -} - -.section-number-1, .section-number-2, .section-number-3, .section-number-4 { display: none; } - -div:has(h3 .tag .journal) { - border: none; - box-shadow: none; -} - -div:has(> h3 .tag .journal)::after { - content: '~ ❦ ~'; - display: block; - text-align: center; - padding-top: 0.2rem; - padding-bottom: 0.2rem; - color: var(--grey4); - font-size: 2rem; -} - -h3:has(.tag .journal) { - text-align: left; -} - -h4:has(.tag .jentry) { - display: none; -} - -h4:has(.tag .habits) { - text-align: left; -} - -.orgjq-expanded > h4:has(.tag .habits)::before { - content: '⮟ '; -} - -.orgjq-contracted > :first-child::before { - content: '⮞ '; -} diff --git a/html/static/esquemadorg.js b/html/static/esquemadorg.js index 21200f8..6b85735 100644 --- a/html/static/esquemadorg.js +++ b/html/static/esquemadorg.js @@ -1,281 +1,88 @@ -// Adapted from: -// -// esquemadorg.js -// -// m3.2010 Daniel Clemente Laboreo. http://www.danielclemente.com/ -// -// Initially based on org-info-jq from Sebastian Rose (2009): http://github.com/SebastianRose/org-info-js/blob/master/org-info-jq.js -// -// Released under the GNU General Public License version 3 -// see: http://www.gnu.org/licenses/ -// - - -var HOW_TO_HIDE = 'hide'; - function isHideable(div_obj) { try { - // Ignore for TOC since it is handled differently - if (div_obj.id == "text-table-of-contents") return false; - if (div_obj.id == "table-of-contents") return false; - // No point in hiding top level - if (div_obj.classList.contains("outline-2")) return false; - if (div_obj.classList.contains("outline-text-2")) return false; + // Ignore for TOC since it is handled differently + if (div_obj.id === "text-table-of-contents") return false; + if (div_obj.id === "table-of-contents") return false; + // No point in hiding top level + if (div_obj.classList.contains("outline-2")) return false; + if (div_obj.classList.contains("outline-text-2")) return false; } catch (e) { - console.log(div_obj) - console.log(e) + console.log(div_obj); + console.log(e); } - - return true + return true; } -function scrollSmoothlyToObj(obj,id) { - // This line comes from: *** Anchor Slider by Cedric Dugas *** Http://www.position-absolute.com *** Thanks! - $("html:not(:animated),body:not(:animated)").animate({ scrollTop: obj.offset().top}, 1100, function() { - window.location.hash = id; - }); -} - -function focusSection(id_anchor){ - // anchor: the id (text, without '#') of the h2/h3/h4/h5/h6/h7 which is to be made visible (together with its parents). The page will also scroll to focus that section - - var anchor1='#'+id_anchor; - var anchor2='*[id=' + id_anchor + ']'; // this is equivalent to $("#id"), which strangely seems not to work - var obj_anchor=$(anchor2); - - // Remove any other highlighted section which was the target of a previous link. - // It does nothing if it's the first click - $("div.orgjq-targeted").removeClass("orgjq-targeted"); - // Now highlight the target section and its parents. You may Use .css("background","orange") to test - obj_anchor.parents("div.orgjq-contracted").addClass("orgjq-targeted"); - // Expand its parents so that the target section is connected to the root of the tree - obj_anchor.parents("div.orgjq-contracted").each( - function() { - $(this).removeClass("orgjq-contracted").addClass("orgjq-expanded"); - $(this).children("div").show(); - } - ); - // move the browser focus to that section - scrollSmoothlyToObj(obj_anchor,anchor1); -} - - function hideForOrg_whenclicked(div_obj) { - if (!isHideable(div_obj[0])) return; - - div_obj.parent().removeClass("orgjq-expanded").addClass("orgjq-contracted"); - if(HOW_TO_HIDE=='hide'){ - //div_obj.nextAll().hide("fast"); // "normal" es más lento - //div_obj.hide(); - } else if(HOW_TO_HIDE=='shrink'){ - //div_obj.css("zoom","0.25"); - // div_obj.nextAll().css("zoom","0.25"); - div_obj.css("font-size","50%"); - div_obj.nextAll().css("font-size","50%"); - } else if(HOW_TO_HIDE=='opacity'){ - div_obj.css("opacity","0.5"); - div_obj.nextAll().css("opacity","0.5"); - } else if(HOW_TO_HIDE=='scrollbar'){ - div_obj.parent().css({"height":"100px","overflow-y":"auto","opacity":"0.3"}); - } else { - console.error("Not impl."); - } - + if (!isHideable(div_obj)) return; + const parent = div_obj.parentElement; + parent.classList.remove("orgjq-expanded"); + parent.classList.add("orgjq-contracted"); } + function showForOrg_whenclicked(div_obj) { - div_obj.parent().removeClass("orgjq-contracted").addClass("orgjq-expanded"); - if(HOW_TO_HIDE=='hide'){ - div_obj.parents().show("normal"); - div_obj.nextAll().show("normal");div_obj.show(); - } else if(HOW_TO_HIDE=='shrink'){ - //div_obj.css("zoom","1"); - // div_obj.nextAll().css("zoom","1"); - div_obj.css("font-size","100%"); - div_obj.nextAll().css("font-size","100%"); - } else if(HOW_TO_HIDE=='opacity'){ - div_obj.css("opacity","1"); - div_obj.nextAll().css("opacity","1"); - } else if(HOW_TO_HIDE=='scrollbar'){ - div_obj.parents().css({"height":"auto","min-height":"100px","overflow-y":"inherit","opacity":"1"}); - } else { - console.error("Not impl."); - } + const parent = div_obj.parentElement; + parent.classList.remove("orgjq-contracted"); + parent.classList.add("orgjq-expanded"); } + function toggleForOrg_whenclicked(div_obj) { - if(div_obj.parent().hasClass("orgjq-expanded")) - hideForOrg_whenclicked(div_obj); - else - showForOrg_whenclicked(div_obj); -} - -// faster methods than calling the individual methods in a loop -function close_all_sections() { - //$('.orgjq-expanded').removeClass("orgjq-expanded").addClass("orgjq-contracted"); - - for(var i=2;i<=7;++i) { - let divs = $(".outline-text-"+i) - divs.each(idx => { - if (isHideable(divs[idx])) { - $("#" + divs[idx].id).parent().removeClass("orgjs-expanded").addClass("orgjq-contracted"); - $("#" + divs[idx].id).hide() - } - }) - } - - // inside the h2 headers, all (now unseen) headers are also contracted - for(var i=2;i<=7;++i) { - $("h"+i).each( - function(){ - if (isHideable($(this).parent()[0])) { - $(this).parent().removeClass("orgjq-expanded").addClass("orgjq-contracted"); - $(this).next("div").nextAll().hide();$(this).next("div").hide(); - } - }); - } - -} -function open_all_sections() { - $('div#content .orgjq-contracted').not("#table-of-contents").removeClass("orgjq-contracted").addClass("orgjq-expanded"); - $('div#content').find(":hidden").not("#table-of-contents div").show(); -} - -function disable_global_outlining() { - // not really used anymore - - // affect only the main (first level) sections - var org= $("div#table-of-contents, div#content>div[id^='outline-container-']"); - //test: org.css({border: "2px solid red"}); - - // show everything (all sections, …) - org.find(":hidden").show(); - - // remove classes and thus colors - $(".orgjq-contracted").removeClass("orgjq-contracted"); - $(".orgjq-expanded").removeClass("orgjq-expanded"); - $(".orgjq-targeted").removeClass("orgjq-targeted"); - - // headers are not clickable - org.find("h1,h2,h3,h4,h5,h6,h7").css({cursor: "default"}).unbind("click"); - // links to sections no longer highlight the target - $("a[href^='#']").unbind('click'); - // hide expand link - $("div#outline-container-1 >h2 >a.expandAll").remove(); - - - // information - alert("He cambiado al estilo tradicional: todo seguido. Si quieres volver a usar el esquemado con cabeceras clicables, recarga la página"); + const parent = div_obj.parentElement; + if (parent.classList.contains("orgjq-expanded")) { + hideForOrg_whenclicked(div_obj); + } else { + showForOrg_whenclicked(div_obj); + } } function enable_global_outlining() { - // Called once e.g. the first time the page is loaded + // Called once e.g. the first time the page is loaded + // handle the click event for each header + for (let i = 2; i <= 7; ++i) { + const headers = document.querySelectorAll(`h${i}`); + headers.forEach(header => { + header.style.cursor = "pointer"; + header.addEventListener('click', function() { + // Get the first div sibling after the header + const parent = this.parentElement; + const divs = parent.querySelectorAll(':scope > div'); + if (divs.length > 0) { + toggleForOrg_whenclicked(divs[0]); + } + }); + }); + } - // handle the click event for each header - for(var i=2;i<=7;++i) { - $("h"+i).each( - function(){ - $(this).css({cursor: "pointer"}); - $(this).bind('click', function(){ toggleForOrg_whenclicked( $(this).parent().children("div").eq(0) ); }); - }); - } + // alternatively: mark everything as open + for (let i = 2; i <= 7; ++i) { + const headers = document.querySelectorAll(`h${i}`); + headers.forEach(header => { + const parent = header.parentElement; + parent.classList.remove("orgjq-contracted"); + parent.classList.add("orgjq-expanded"); + }); + } - /* - // add link to deactive outlining. I wanted 2 links, „expand all“ and „contract all“, but the second one isn't of much use (and reloading the page does the same) - // otros posibles nombres: "(expandir completamente)" - var expAll_link = $( document.createElement('a') ).text("(ver todo seguido, sin esquemado)").addClass("expandAll").click(disable_global_outlining); - $( $("div.outline-2")[0] ).find(">h2") .append(expAll_link); - */ + // except TOC + const toc = document.querySelector("div#table-of-contents"); + if (toc) { + toc.classList.remove("orgjq-expanded"); + toc.classList.add("orgjq-contracted"); + } - - /* - // start with contracted TOC and headers ← m5.2017: disabled because it has a huge penalty towards Google (hidden content won't be indexed) - - if(HOW_TO_HIDE=='hide'){ - $("#text-table-of-contents").hide(); - } else { - console.error("Not impl."); - } - for(var i=2;i<=7;++i) { - $(".outline-text-"+i).parent().addClass("orgjq-contracted"); - if(HOW_TO_HIDE=='hide'){ - ///// $(".outline-text-"+i).hide(); - $(".outline-text-"+i).hide(); - } else if(HOW_TO_HIDE=='scrollbar'){ - //$(".outline-text-"+i).css({"height":"100px","overflow-y":"auto","opacity":"0.3"}); - // $(".outline-text-"+i).parent().css({"height":"100px","overflow-y":"auto","opacity":"0.3"}); - // console.error("nada"); - } else { - console.error("Not impl."); - } - } - - // inside the h2 headers, all (now unseen) headers are also contracted - for(var i=2;i<=7;++i) { - $("h"+i).each( - function(){ - $(this).parent().removeClass("orgjq-expanded").addClass("orgjq-contracted"); - if(HOW_TO_HIDE=='hide'){ - $(this).next("div").nextAll().hide();$(this).next("div").hide(); - } else if(HOW_TO_HIDE=='scrollbar'){ - // $(this).next("div").nextAll().css({"height":"100px","overflow-y":"auto","opacity":"0.3"}); - $(this).next("div").nextAll().css({"height":"100px","overflow-y":"auto","opacity":"0.3"}); - // console.error("nada2."); - } else { - console.error("Not impl."); - } - - }); - } - */ - - // alternatively: mark everything as open - for(var i=2;i<=7;++i) { - $("h"+i).each( - function(){ - $(this).parent().removeClass("orgjq-contracted").addClass("orgjq-expanded"); - }); - } - // except TOC - $("div#table-of-contents").removeClass("orgjq-expanded").addClass("orgjq-contracted"); - - - // Hide default-hidden categories - $(".orgjq-contract-default").each( - function(){ - hideForOrg_whenclicked($(this)) + const autocollapse = document.querySelectorAll(".autocollapse"); + autocollapse.forEach(element => { + const grandparent = element.parentElement?.parentElement; + if (grandparent) { + hideForOrg_whenclicked(grandparent); } - ); - - - // If provided #fragment in URL, we must locate and open the corresponding header and its parents - var url = document.location.toString(); - if (url.match('#')) { // the URL contains an anchor - var id_anchor = url.split('#')[1]; - focusSection(id_anchor); - } - - - // internal links to anchors, e.g. , should also expand the destination section before scrolling there - //Test: $("a[href^='#']").css("border","2px dotted red"); - $("a[href^='#']").each(function(){ - var caller=this; - $(caller).click(function (event) { - var href=$(caller).attr("href"); - var id_href=href.substr(1); - focusSection(id_href); - return false; - }); - - }); - - $(".autocollapse").each(function(){ - hideForOrg_whenclicked($(this).parent().parent()); - console.log("DSFDFS") - }) - - // the page is now ready to be used - + }); } -// Code starts here - -$(document).ready(enable_global_outlining); +// Run when DOM is fully loaded +if (document.readyState === 'loading') { + document.addEventListener('DOMContentLoaded', enable_global_outlining); +} else { + // DOM is already loaded + enable_global_outlining(); +} diff --git a/html/static/footnote.css b/html/static/footnote.css deleted file mode 100644 index 6368212..0000000 --- a/html/static/footnote.css +++ /dev/null @@ -1,11 +0,0 @@ -.footnote-tooltip { - position: 'absolute'; - z-index: 1000; - background-color: var(--background-tooltip); - border: 1px solid var(--accent1); - border-radius: = 4px; - padding: 8px 12px; - max-width: 300px; - font-size: calc(var(--font-size) * 0.9); - box-shadow: 1px 1px 1px var(--grey2); -} diff --git a/html/static/footnote.js b/html/static/footnote.js index 856e8d5..8b4f57e 100644 --- a/html/static/footnote.js +++ b/html/static/footnote.js @@ -1,6 +1,38 @@ -document.addEventListener('DOMContentLoaded', function() { - console.log("🦶🦶🦶🦶🦶 FOOTNOTES LOADED 🦶🦶🦶🦶🦶🦶") +function formatDayOfYear(dayOfYear, year) { + const date = new Date(year, 0, dayOfYear); + return date.toLocaleDateString('en-GB', { + day: 'numeric', + month: 'short', + year: 'numeric' + }); +} + +let selectedCell = null; + +function showHabitPopup(cell) { + var bodyHtml = cell.getAttribute('data-body'); + var doy = cell.getAttribute('data-doy'); + var activity = cell.getAttribute('data-activity'); + var status = cell.getAttribute('data-status'); + activity = activity.replace(/^dailies-/, '').replace(/^./, c => c.toUpperCase()) + + if (!bodyHtml) bodyHtml = "This section intentionally left blank." + + bodyHtml = `

${activity} — ${formatDayOfYear(parseInt(doy), 2025)}

${bodyHtml}` + + document.getElementById('habitPopupContent').innerHTML = bodyHtml; + + if (selectedCell) { + selectedCell.classList.remove('habitgrid-selected'); + } + + cell.classList.add('habitgrid-selected'); + selectedCell = cell; + enableFootnotes(); +} + +function enableFootnotes() { const footnoteRefs = document.querySelectorAll('.footref') footnoteRefs.forEach(ref => { @@ -45,37 +77,6 @@ document.addEventListener('DOMContentLoaded', function() { // Hide footnotes section document.querySelector("#footnotes").style.display='none' -}); - -function formatDayOfYear(dayOfYear, year) { - const date = new Date(year, 0, dayOfYear); - - return date.toLocaleDateString('en-GB', { - day: 'numeric', - month: 'short', - year: 'numeric' - }); } -let selectedCell = null; - -function showHabitPopup(cell) { - var bodyHtml = cell.getAttribute('data-body'); - var doy = cell.getAttribute('data-doy'); - var activity = cell.getAttribute('data-activity'); - var status = cell.getAttribute('data-status'); - activity = activity.replace(/^dailies-/, '').replace(/^./, c => c.toUpperCase()) - - if (!bodyHtml) bodyHtml = "This section intentionally left blank." - - bodyHtml = `

${activity} — ${formatDayOfYear(parseInt(doy), 2025)}

${bodyHtml}` - - document.getElementById('habitPopupContent').innerHTML = bodyHtml; - - if (selectedCell) { - selectedCell.classList.remove('habitgrid-selected'); - } - - cell.classList.add('habitgrid-selected'); - selectedCell = cell; -} +document.addEventListener('DOMContentLoaded', enableFootnotes); diff --git a/html/static/hide.js b/html/static/hide.js new file mode 100644 index 0000000..9a9ca5a --- /dev/null +++ b/html/static/hide.js @@ -0,0 +1,82 @@ +function isHideable(div_obj) { + // Ignore for TOC since it is handled differently + if (div_obj.id === "text-table-of-contents") return false; + if (div_obj.id === "table-of-contents") return false; + // No point in hiding top level + if (div_obj.classList.contains("outline-2")) return false; + if (div_obj.classList.contains("outline-text-2")) return false; + return true; +} + +function orgjqHide(div_obj) { + if (!isHideable(div_obj)) return; + const parent = div_obj.parentElement; + parent.classList.remove("orgjq-expanded"); + parent.classList.add("orgjq-contracted"); +} + +function orgjqShow(div_obj) { + const parent = div_obj.parentElement; + parent.classList.remove("orgjq-contracted"); + parent.classList.add("orgjq-expanded"); +} + +function orgjqToggle(div_obj) { + const parent = div_obj.parentElement; + if (parent.classList.contains("orgjq-expanded")) { + orgjqHide(div_obj); + } else { + orgjqShow(div_obj); + } +} + +function orgjqEnable() { + // Called once e.g. the first time the page is loaded + // handle the click event for each header + for (let i = 2; i <= 7; ++i) { + const headers = document.querySelectorAll(`h${i}`); + headers.forEach(header => { + header.style.cursor = "pointer"; + header.addEventListener('click', function() { + // Get the first div sibling after the header + const parent = this.parentElement; + const divs = parent.querySelectorAll(':scope > div'); + if (divs.length > 0) { + orgjqToggle(divs[0]); + } + }); + }); + } + + // Mark everything as open... + for (let i = 2; i <= 7; ++i) { + const headers = document.querySelectorAll(`h${i}`); + headers.forEach(header => { + const parent = header.parentElement; + parent.classList.remove("orgjq-contracted"); + parent.classList.add("orgjq-expanded"); + }); + } + + // ... except TOC ... + const toc = document.querySelector("div#table-of-contents"); + if (toc) { + toc.classList.remove("orgjq-expanded"); + toc.classList.add("orgjq-contracted"); + } + // ... and autocollapse. + const autocollapse = document.querySelectorAll(".autocollapse"); + autocollapse.forEach(element => { + const grandparent = element.parentElement?.parentElement; + if (grandparent) { + orgjqHide(grandparent); + } + }); +} + +// Run when DOM is loaded +if (document.readyState === 'loading') { + document.addEventListener('DOMContentLoaded', orgjqEnable); +} else { + orgjqEnable(); +} diff --git a/html/static/images/journal/2025.11-drums.jpg b/html/static/images/journal/2025.11-drums.jpg new file mode 100644 index 0000000..181bfbc Binary files /dev/null and b/html/static/images/journal/2025.11-drums.jpg differ diff --git a/html/static/style.css b/html/static/style.css index 8017c5d..7041da0 100644 --- a/html/static/style.css +++ b/html/static/style.css @@ -1,261 +1,271 @@ +.tag { display: none; } + +div:has(* .tag .h4left) h4 { + text-align: left; +} + +div:has(* .tag .h5left) h5 { + text-align: left; +} + +div:has(* .tag .h3underline) h3 { + text-decoration: underline; +} + +div:has(h3 .tag .journal) { + border: none; + box-shadow: none; +} + +div:has(> h3 .tag .journal)::after { + content: '~ ❦ ~'; + display: block; + text-align: center; + padding-top: 0.2rem; + padding-bottom: 0.2rem; + color: var(--grey4); + font-size: 2rem; +} + +h3:has(.tag .journal) { + text-align: left; +} + +h4:has(.tag .jentry) { + display: none; +} + +h4:has(.tag .habits) { + text-align: left; +} + +.done.YES, .todo.NO, .done.EXCELLENT, .done.FREED { + display: none; +} + +h2:has(.done.YES), h3:has(.done.YES), h4:has(.done.YES), h5:has(.done.YES), .grid.YES { + color: var(--green3); +} + +h2:has(.todo.NO), h3:has(.todo.NO), h4:has(.todo.NO), h5:has(.todo.NO), .grid.NO { + color: var(--red3); +} + +h2:has(.done.EXCELLENT), h3:has(.done.EXCELLENT), h4:has(.done.EXCELLENT), h5:has(.done.EXCELLENT), .grid.EXCELLENT { + color: var(--blue3); +} + +h2:has(.done.FREED), h3:has(.done.FREED), h4:has(.done.FREED), h5:has(.done.FREED), .grid.FREED { + color: var(--purple3); +} + +.habit-cell { + text-align: center; + vertical-align: middle; + width: 20px; + height: 20px; + cursor: pointer; + user-select: none; +} + +.habit-cell.habit-brightness-1 { color: var(--grey5); outline-color: var(--grey5) !important; } +.habit-cell.habit-brightness-2 { color: var(--grey5); outline-color: var(--grey5) !important; } +.habit-cell.habit-brightness-3 { color: var(--grey5); outline-color: var(--grey5) !important; } +.habit-cell.habit-brightness-4 { color: var(--grey2); outline-color: var(--grey5) !important; } +.habit-cell.habit-brightness-5 { color: var(--grey3); outline-color: var(--grey5) !important; } + +.habit-cell:not([data-body=""]) { + outline: dotted 2px; + outline-offset: -2px; +} +.habitgrid-selected { + outline: solid 2px var(--purple5) !important; + outline-offset: -2px; +} + +.orgjq-expanded p { + margin-top: 0; + padding-bottom: 1.5rem; + margin-bottom: 0; +} + +.orgjq-contracted > div { + display: none; +} + +.orgjq-contracted h2, .orgjq-contracted h3, .orgjq-contracted h4, orgjq-contracted h5 { + padding-top: 0.3rem !important; + padding-bottom: 0.3rem !important; +} + +.orgjq-contracted > :first-child::before { + content: '⮞ '; +} + +.orgjq-expanded > h4:has(.tag .autocollapse)::before { + content: '⮟ '; +} :root { - --green1: #123218; - --green2: #254f1b; - --green3: #356c22; - --green4: #5e8e40; - --green5: #85aa5f; + --site-width: 1000px; + --vert-content-margin: 0.3rem; - --blue1: #1b2459; - --blue2: #153a79; - --blue3: #2f5394; - --blue4: #417eaf; - --blue5: #69a8c6; + --font-size: 1.2rem; + --line-height: 1.6rem; + --font-family: "Source Serif Pro"; - --purple1: #2e1e58; - --purple2: #493281; - --purple3: #6a45a6; - --purple4: #855aa3; - --purple5: #9b77b5; - - --red1: #4b1313; - --red2: #682017; - --red3: #84301c; - --red4: #9c4830; - --red5: #c46849; - - --grey1: #202124; - --grey2: #33333b; - --grey3: #605b66; - --grey4: #a79fa7; - --grey5: #c5bcbc; - - --site-width: 1000px; - --vert-content-margin: 0.3rem; - --accent1: var(--purple4); - --link: var(--blue3); - --black: var(--grey1); - --grey: var(--grey3); - --background: var(--grey5); - --background-tooltip: var(--grey5); - - --font-size: 1.2rem; - --line-height: 1.6rem; - --font-family: "Source Serif Pro"; - - --scale: 2; -} - -/* -@media (min-height: 1081px) { - :root { --scale: 2; - } } -@media (min-height: 2161px) { - :root { - --scale: 3; - } -} +:root { + --green1: #123218; + --green2: #254f1b; + --green3: #356c22; + --green4: #5e8e40; + --green5: #85aa5f; -@media (min-height: 3241px) { - :root { - --scale: 4; - } + --blue1: #1b2459; + --blue2: #153a79; + --blue3: #2f5394; + --blue4: #417eaf; + --blue5: #69a8c6; + + --purple1: #2e1e58; + --purple2: #493281; + --purple3: #6a45a6; + --purple4: #855aa3; + --purple5: #9b77b5; + + --red1: #4b1313; + --red2: #682017; + --red3: #84301c; + --red4: #9c4830; + --red5: #c46849; + + --grey1: #202124; + --grey2: #33333b; + --grey3: #605b66; + --grey4: #a79fa7; + --grey5: #c5bcbc; + + --accent1: var(--purple4); + --link: var(--blue3); + --black: var(--grey1); + --grey: var(--grey3); + --background: var(--grey5); + --background-tooltip: var(--grey5); } - */ body::before, body::after { - content: ''; - position: fixed; - top: 0; - height: 100vh; - width: 50%; - background-image: url('/static/images/background.png'); - background-repeat: no-repeat; - z-index: -1; + content: ''; + position: fixed; + top: 0; + height: 100vh; + width: 50%; + background-image: url('/static/images/background.png'); + background-repeat: no-repeat; + z-index: -1; - image-rendering: pixelated; /* For Chrome/Safari */ - image-rendering: -moz-crisp-edges; /* For Firefox */ - image-rendering: crisp-edges; /* Fallback */ + image-rendering: pixelated; /* For Chrome/Safari */ + image-rendering: -moz-crisp-edges; /* For Firefox */ + image-rendering: crisp-edges; /* Fallback */ - background-size: calc(960px * var(--scale)) calc(1080px * var(--scale)); + background-size: calc(960px * var(--scale)) calc(1080px * var(--scale)); } body::before { - left: 0; - background-position: top right; + left: 0; + background-position: top right; } body::after { - right: 0; - background-position: top right; - /* Flip the right side horizontally */ - transform: scaleX(-1); + right: 0; + background-position: top right; + /* Flip the right side horizontally */ + transform: scaleX(-1); } body { -// text-align: justify; - font-family: var(--font-family); - font-size: var(--font-size); - line-height: var(--line-height); - color: var(--black); - background-color: var(--background); - color: var(--grey1); - word-spacing: 0.25ch; - font-weight: 400; + font-family: var(--font-family); + font-size: var(--font-size); + line-height: var(--line-height); + word-spacing: 0.25ch; + font-weight: 400; } #content, #header, #footer { - min-width: 500px; - max-width: min(var(--site-width), 90vw); - margin: 0 auto; - padding: 5px 25px; + min-width: 500px; + max-width: min(var(--site-width), 90vw); + margin: 0 auto; + padding: 5px 25px; - background-color: var(--background); - border: 2px double var(--grey1); - margin-bottom: 1.2rem; + border: 2px double var(--grey1); + margin-bottom: 1.2rem; + background-color: var(--background); } #header { - display: flex; + display: flex; } -#looking-for-work { - background-color: var(--red2); - color: var(--grey5); - padding: 5px 25px; - margin-left: auto; - margin-top: -0.32rem; - margin-bottom: -0.32rem; - margin-right: -1.55rem; - border: 2px double var(--purple5); +#content, #footer { + box-shadow: 7px 7px 7px var(--grey1); } -#looking-for-work a, #looking-for-work a:visited { - color: var(--blue5) !important; -} - - #footer { -padding-top: 1rem; -padding-bottom: 1rem; -} - -code { - font-size: calc(var(--font-size) * 0.9); -} - -hr { - border: 0; - border-top: 2px dotted var(--black); -} - -.center { - display: block; - margin-left: auto; - margin-right: auto; - text-align: center; -} - -.navbar-link { - margin-right: 5px; - margin-left: 5px; -} - -a, a:visited { - color: var(--link); - text-decoration: none; + padding-top: 1rem; + padding-bottom: 1rem; } #header a, #header a:visited{ - color: var(--purple2); -} - -#content h2, #content h3, #content h4, #content h5 { - margin-bottom: 0.2rem; - margin-top: 0.5rem; -} - -#content h2 { - margin-top: 1rem; + color: var(--purple2); } #header hr { - margin-bottom: var(--vert-content-margin); + margin-bottom: var(--vert-content-margin); } #footer hr { - margin-top: var(--vert-content-margin); + margin-top: var(--vert-content-margin); } -#publish-date, #modified-date { - font-style: italic; +#content h2, #content h3, #content h4, #content h5 { + margin-bottom: 1rem; + margin-top: 0.5rem; + margin-left: 0.5rem; } -.src, .example { - font-family: "monospace"; - font-size: 1rem; +#content h2 { + margin-top: 1rem; } -/* TOC */ - -#table-of-contents { - z-index: 1; - margin-top: 105px; - margin-right: 5%; - font-size: calc(var(--font-size) * 0.8); - position: fixed; - right: 0em; - top: 0em; - background: var(--background-toc); - text-align: right; - min-height: 3rem; - - box-shadow: 0 0 0.5em var(--shadow-toc); - -webkit-box-shadow: 0 0 0.5em var(--shadow-toc); - -moz-box-shadow: 0 0 0.5em var(--shadow-toc); - -webkit-border-bottom-left-radius: 5px; - -moz-border-radius-bottomleft: 5px; - /* ensure doesn't flow off the screen when expanded */ - max-height: 80%; - overflow: auto; - +#content h3, #content h4 { + padding-top: 0.5rem; + padding-bottom: 0.5rem; } -#table-of-contents h2 { - font-size: 13pt; - max-width: 9em; - border: 0; - font-weight: normal; - margin-top: 0.75em; - margin-bottom: 0.75em; - padding-left: 0.5em; - padding-right: 0.5em; - padding-top: 0.05em; - padding-bottom: 0.05em; } -#table-of-contents #text-table-of-contents { - display: none; - text-align: left; } -#table-of-contents:hover #text-table-of-contents { - display: block; - padding: 0.5em; - margin-top: -1.5em; - padding-right: 20px; + +#content h5 { + padding-top: 0.3rem; + padding-bottom: 0.3rem; +} + +body { + color: var(--black); + background-color: var(--background); } pre {background-color:var(--grey1); color:var(--grey5);} pre span.org-builtin {color:var(--blue4);font-weight:bold;} pre span.org-string {color:var(--green4);} -pre span.org-keyword {color:var(--blue4);} -pre span.org-variable-name {color:var(--purple5);} +pre span.org-keyword {color:var(--purple5);font-weight:bold;} +pre span.org-variable-name {color:var(--green5);font-style:italic;} pre span.org-function-name {color:var(--blue5);} -pre span.org-type {color:var(--purple3);} +pre span.org-type {color:var(--purple4);} pre span.org-preprocessor {color:var(--grey5);font-weight:bold;} -pre span.org-constant {color:var(--red2);} -pre span.org-comment-delimiter {color:var(--grey5);} -pre span.org-comment {color:var(--grey5);font-style:italic} +pre span.org-constant {color:var(--red5);} +pre span.org-comment-delimiter {color:var(--grey3);} +pre span.org-comment {color:var(--grey3);font-style:italic} pre span.org-outshine-level-1 {color:var(--grey5);font-style:italic} pre span.org-outshine-level-2 {color:var(--grey5);font-style:italic} pre span.org-outshine-level-3 {color:var(--grey5);font-style:italic} @@ -266,15 +276,171 @@ pre span.org-outshine-level-7 {color:var(--grey5);font-style:italic} pre span.org-outshine-level-8 {color:var(--grey5);font-style:italic} pre span.org-outshine-level-9 {color:var(--grey5);font-style:italic} pre span.org-rainbow-delimiters-depth-1 {color:var(--grey4);} -pre span.org-rainbow-delimiters-depth-2 {color:var(--blue1);} -pre span.org-rainbow-delimiters-depth-3 {color:var(--green1);} -pre span.org-rainbow-delimiters-depth-4 {color:var(--red1);} -pre span.org-rainbow-delimiters-depth-5 {color:var(--purple1);} +pre span.org-rainbow-delimiters-depth-2 {color:var(--blue4);} +pre span.org-rainbow-delimiters-depth-3 {color:var(--green4);} +pre span.org-rainbow-delimiters-depth-4 {color:var(--red4);} +pre span.org-rainbow-delimiters-depth-5 {color:var(--purple4);} pre span.org-rainbow-delimiters-depth-6 {color:var(--blue4);} -pre span.org-rainbow-delimiters-depth-7 {color:var(--green3);} -pre span.org-rainbow-delimiters-depth-8 {color:var(--red3);} -pre span.org-rainbow-delimiters-depth-9 {color:var(--purple3);} -pre span.org-sh-quoted-exec {color:var(--purple2);} +pre span.org-rainbow-delimiters-depth-7 {color:var(--green4);} +pre span.org-rainbow-delimiters-depth-8 {color:var(--red4);} +pre span.org-rainbow-delimiters-depth-9 {color:var(--purple4);} +pre span.org-sh-quoted-exec {color:var(--purple3);} +pre span.org-doc {color:var(--green5);font-style:italic;} +pre span.org-css-selector {color:var(--blue5);font-weight:bold;} +pre span.org-css-property {color:var(--purple4); font-weight: bold;} + +hr { + border: 0; + border-top: 2px dotted var(--black); +} + +a, a:visited { + color: var(--link); + text-decoration: none; +} + +.figure-number { + display: none; +} + +.caption { + padding-top: 0.5rem; + font-style: italic; +} + +.outline-3, .outline-4, .outline-5 { + padding-left: 0.6rem; + border-radius: 0.2em; + margin: 0.7rem; +} + +.outline-text-3, .outline-text-4, .outline-text-5 { + margin: 0.3rem 1rem 0.5rem 0.5rem; +} + +h2 { + line-height: 1.5rem; + text-align: center; +} + +h3, h4, h5 { + text-align: center; +} + +.section-number-1, .section-number-2, .section-number-3, .section-number-4 { display: none; } + +.center { + display: block; + margin-left: auto; + margin-right: auto; + text-align: center; +} + +.navbar-link { + margin-right: 5px; + margin-left: 5px; +} + +.center, div.center { + text-align: center; + margin-left: auto; + margin-right: auto; +} + +.center figure, +.center figcaption, +div.center figure, +div.center figcaption { + text-align: center; + margin-left: auto; + margin-right: auto; +} + +.multi-img { + display: flex; + justify-content: center; + text-align: center; + margin: 20px; + gap: 20px; +} + +.multi-img figure { margin: 0px; } + +.poetry { + padding-top: 4rem; + padding-bottom: 4rem; + text-align: center; +} + +#looking-for-work { + background-color: var(--red2); + color: var(--grey5); + padding: 5px 25px; + margin-left: auto; + margin-top: -0.32rem; + margin-bottom: -0.32rem; + margin-right: -1.55rem; + border: 2px double var(--purple5); +} + +#looking-for-work a, #looking-for-work a:visited { + color: var(--blue5) !important; +} + +.src, .example { + font-family: "monospace"; + font-size: 1rem; +} + +#publish-date, #modified-date { + font-style: italic; +} + +#table-of-contents { + z-index: 1; + margin-top: 105px; + margin-right: 5%; + font-size: calc(var(--font-size) * 0.8); + position: fixed; + right: 0em; + top: 0em; + background: var(--background-toc); + text-align: right; + min-height: 3rem; + + box-shadow: 0 0 0.5em var(--shadow-toc); + -webkit-box-shadow: 0 0 0.5em var(--shadow-toc); + -moz-box-shadow: 0 0 0.5em var(--shadow-toc); + -webkit-border-bottom-left-radius: 5px; + -moz-border-radius-bottomleft: 5px; + /* ensure doesn't flow off the screen when expanded */ + max-height: 80%; + overflow: auto; +} +#table-of-contents h2 { + font-size: 13pt; + max-width: 9em; + border: 0; + font-weight: normal; + margin-top: 0.75em; + margin-bottom: 0.75em; + padding-left: 0.5em; + padding-right: 0.5em; + padding-top: 0.05em; + padding-bottom: 0.05em; } +#table-of-contents #text-table-of-contents { + display: none; + text-align: left; } +#table-of-contents:hover #text-table-of-contents { + display: block; + padding: 0.5em; + margin-top: -1.5em; + padding-right: 20px; +} + +#table-of-contents { + display: none; +} .TODO { color: var(--red3); } .DONE { color: var(--green3); } diff --git a/html/todo.html b/html/todo.html index 9650382..5526dff 100644 --- a/html/todo.html +++ b/html/todo.html @@ -1,7 +1,7 @@ - + To Do @@ -193,13 +193,8 @@ - - - + - - - @@ -215,111 +210,111 @@
-
-

New phone

-
+
+

New phone

+
-
-

TODO Import contacts

+
+

TODO Import contacts

-
-

TODO Deeper Tenma integrations

+
+

TODO Deeper Tenma integrations

-
-

Tenma Infrastructure

-
+
+

Tenma Infrastructure

+
-
-

TODO Prepare Tenma to open her up to other users.

+
+

TODO Prepare Tenma to open her up to other users.

-
-

TODO Deeper copyparty integration

-
+
+

TODO Deeper copyparty integration

+
-
-

TODO Screenshot service

+
+

TODO Screenshot service

-
-

Life/houshold things

-
+
+

Life/houshold things

+
-
-

TODO Adopt a cat

+
+

TODO Adopt a cat

-
-

TODO Have wisdom teeth pulled

+
+

TODO Have wisdom teeth pulled

-
-

TODO Health checkup

+
+

TODO Health checkup

-
-

TODO Put plants in the house

+
+

TODO Put plants in the house

-
-

Blog

-
+
+

Blog

+
-
-

See blog.org

+
+

See blog.org

-
-

Design Documents

-
+
+

Design Documents

+
-
-

WebbieWebWorld

+ -
-

EMPTYHEAD

+ -
-

VDP

+
+

VDP

-
-

Other

-
+
+

Other

+
-
-

TODO Exercise playlists

+
+

TODO Exercise playlists

-
-

TODO Create Friends webring page on the blog

+
+

TODO Create Friends webring page on the blog

-
-

TODO Keyboards blog page

+
+

TODO Keyboards blog page

-
-

TODO custom emacs theme

+
+

TODO custom emacs theme

-
-

TODO Learn about ATProto

+
+

TODO Learn about ATProto

-
-

TODO Process Genius Ideas

+
+

TODO Process Genius Ideas

-
-

TODO Cancel Amazon Prime

+
+

TODO Cancel Amazon Prime

-
-

TODO Compile Compsci Resources page

+
+

TODO Compile Compsci Resources page

-
-

TODO Tell the keyboard guy I’ve moved house

+
+

TODO Tell the keyboard guy I’ve moved house

-
-

TODO Look into live coding music setup

+
+

TODO Look into live coding music setup

-
-

TODO Make Runescape video

+
+

TODO Make Runescape video

-
-

TODO Create looking for work journey page

+
+

TODO Create looking for work journey page

@@ -330,7 +325,7 @@ If you have any comments about this page, you can email me at:
Proudly built using org-mode.
All code on this website is licensed GPLv3 unless otherwise indicated.

-[Valid RSS]
+[Valid RSS]
diff --git a/html/work/crypto_contracting_reflections.html b/html/work/crypto_contracting_reflections.html index f1b4039..7485d9d 100644 --- a/html/work/crypto_contracting_reflections.html +++ b/html/work/crypto_contracting_reflections.html @@ -1,7 +1,7 @@ - + Reflections on Independent Contracting in the Cryptocurrency Sector (2021-2022) @@ -193,13 +193,8 @@ - - - + - - - @@ -215,25 +210,25 @@
-
-

TODO This page is unfinished

+
+

TODO This page is unfinished

-
-

Reflections on Independent Contracting in the Cryptocurrency Sector (2021-2022)

-
+
+

Reflections on Independent Contracting in the Cryptocurrency Sector (2021-2022)

+
-
-

Introduction

-
+
+

Introduction

+

This is a reflective article on the time I spent working as a software contractor in the cryptocurrency sector between 2021 and 2022 (maybe 10 months total?). I did a variety of things including full-stack web development, blockchain integrations, as well as some smart contract development and general consulting.

-
-

Background

-
+
+

Background

+

This period was around the tail end of my passing interest/involvement in the cryptocurrency phenomenon, a time period that roughly spans from 2016 until the end of this gig in early 2022. I was interested in the technology, but wasn’t actively building on it until 2021 and being 23 years old and living off student loans I didn’t hold a significant financial stake in cryptocurrency. My connection to the wider crypto1 ran primarily through a good friend, and it was this friend that recruited me to this gig.

@@ -259,28 +254,28 @@ Given its central importance to the story I suppose I must detail exactly how mu

-
-

The Work

-
+
+

The Work

+
-
-

VW

+
+

VW

-
-

EW

+
+

EW

-
-

CM

+
+

CM

-
-

Quitting

+
+

Quitting

-
-

Spending the Money

+
+

Spending the Money

-
-

Lessons Learned

+
+

Lessons Learned

@@ -301,7 +296,7 @@ If you have any comments about this page, you can email me at:
Proudly built using org-mode.
All code on this website is licensed GPLv3 unless otherwise indicated.

-[Valid RSS]
+[Valid RSS]
diff --git a/html/work/eris_retrospective.html b/html/work/eris_retrospective.html index 181f99b..fefcfb1 100644 --- a/html/work/eris_retrospective.html +++ b/html/work/eris_retrospective.html @@ -1,7 +1,7 @@ - + Eris Retrospective @@ -193,13 +193,8 @@ - - - + - - - @@ -215,8 +210,8 @@
-
-

TODO

+
+

TODO

@@ -226,7 +221,7 @@ If you have any comments about this page, you can email me at:
Proudly built using org-mode.
All code on this website is licensed GPLv3 unless otherwise indicated.

-[Valid RSS]
+[Valid RSS]
diff --git a/html/work/index.html b/html/work/index.html index fb4f732..583e3bf 100644 --- a/html/work/index.html +++ b/html/work/index.html @@ -1,7 +1,7 @@ - + Work Index @@ -193,13 +193,8 @@ - - - + - - - @@ -215,31 +210,31 @@
-
-

Work Index

-
+
+

Work Index

+

Here I keep various documents relating to my professional life.

-
-

I am looking for work! Here are the services I offer.

+
+

I am looking for work! Here are the services I offer.

-
-

Here’s my portfolio.

+
+

Here’s my portfolio.

-
-

Memoirs about work I did in the past

-
+
+

Memoirs about work I did in the past

+
-
-

Toshokan.moe

+ - @@ -251,7 +246,7 @@ If you have any comments about this page, you can email me at:
Proudly built using org-mode.
All code on this website is licensed GPLv3 unless otherwise indicated.

-[Valid RSS]
+[Valid RSS]
diff --git a/html/work/looking_for_work.html b/html/work/looking_for_work.html index bc1b242..c7050e6 100644 --- a/html/work/looking_for_work.html +++ b/html/work/looking_for_work.html @@ -1,7 +1,7 @@ - + Looking for Work @@ -193,13 +193,8 @@ - - - + - - - @@ -215,15 +210,15 @@
-
-

Looking for Work

-
+
+

Looking for Work

+
-
-

About Me

-
+
+

About Me

+

-I’m Akk0, long-term enthusiast software developer, sysadmin, freelancer and this website’s webmaster. I’ve been at this computer thing for a while — my first dist-upgrade was Linux Mint 15 “Olivia” in 2013 — and I am currently actively looking for work on a freelance, contract or part-time basis, full remote or partially on-site in the Paris area1; I also accept full-time offers. +I’m Akk0, long-term enthusiast software developer, sysadmin, freelancer and this website’s webmaster. I’ve been at this computer thing for a while — my first dist-upgrade was Linux Mint 15 “Olivia” in 2013 — and I am currently actively looking for work on a freelance, contract or part-time basis, full remote or partially on-site in the Paris area1. I am also open to regular full-time positions at interesting copmanies.

@@ -231,9 +226,9 @@ In order to rapidly build connections and get the ball rolling, I am currently o

-
-

Services Offered

-
+
+

Services Offered

+

My specialisation is in end-to-end, start to finish software development; taking software from idea to specification and through implementation to clean, finished, deployed and of course well-documented product. The independence and flexibility on which I pride myself can be put to many uses, however, and jobs I would love to do for example include:

@@ -258,17 +253,17 @@ I especially love working with small businesses and individuals, as well as empo

-
-

Two Hours Free!

-
+
+

Two Hours Free!

+

As an offer of goodwill, I am currently offering up to 2 hours of work entirely free, with no obligations, no strings attached; simply contact me using the contact information below. Time starts from the moment I start reading your email and includes communication time, so try to be detailed!

-
-

Contact Me

-
+
+

Contact Me

+

To inquire further, contact me at akk0 {at} webbieweb {dot} org and tell me:

@@ -283,9 +278,9 @@ I am of course more than willing to jump on a call to discuss or just to prove I

-
-

Qualifications and Accomplishments

-
+
+

Qualifications and Accomplishments

+

Main page: portfolio; under construction.

@@ -338,13 +333,13 @@ This is in addition to numerous minor programs, contracts, data science/scientif
- diff --git a/html/work/portfolio.html b/html/work/portfolio.html index 181cc8d..318856a 100644 --- a/html/work/portfolio.html +++ b/html/work/portfolio.html @@ -1,7 +1,7 @@ - + Portfolio @@ -193,13 +193,8 @@ - - - + - - - @@ -215,8 +210,8 @@
-
-

TODO Portfolio

+
+

TODO Portfolio

@@ -226,7 +221,7 @@ If you have any comments about this page, you can email me at:
Proudly built using org-mode.
All code on this website is licensed GPLv3 unless otherwise indicated.

-[Valid RSS]
+[Valid RSS]
diff --git a/html/work/toshokan_retrospective.html b/html/work/toshokan_retrospective.html index 1bd01e2..23b486b 100644 --- a/html/work/toshokan_retrospective.html +++ b/html/work/toshokan_retrospective.html @@ -1,7 +1,7 @@ - + Toshokan Retrospective @@ -193,13 +193,8 @@ - - - + - - - @@ -215,8 +210,8 @@
-
-

TODO

+
+

TODO

@@ -226,7 +221,7 @@ If you have any comments about this page, you can email me at:
Proudly built using org-mode.
All code on this website is licensed GPLv3 unless otherwise indicated.

-[Valid RSS]
+[Valid RSS]
diff --git a/notes.org b/notes.org deleted file mode 100644 index 64702cc..0000000 --- a/notes.org +++ /dev/null @@ -1,8 +0,0 @@ -#+title: Notes - -* Jesus -First pass eiditing -Victoria tongue piercing -victoria backstory -jesus biblical references -afterword diff --git a/org/index.org b/org/index.org index 3192549..5349ce0 100644 --- a/org/index.org +++ b/org/index.org @@ -12,200 +12,7 @@ Here's this week's [[./journal/w46-2025.org][journal]]! ** Habits #+BEGIN_CENTER -/Today is Monday, 10th November./ +/Today is Thursday, 20th November./ #+END_CENTER -#+BEGIN_SRC emacs-lisp :exports results :results value html :cache no -(defun akk0/org-to-html (org-string) - "Convert ORG-STRING to HTML." - (with-temp-buffer - (insert org-string) - (org-mode) - (org-export-as 'html nil nil t nil))) -(defun akk0/sort-habits (habit-alist) - "Sort habit-alist by a predefined order of custom-ids." - (let ((order '("dailies-blogging" "dailies-meditation" "dailies-french" "dailies-engineering" - "dailies-exercise" "dailies-drawing" "dailies-reading" "dailies-social"))) - (sort (copy-sequence habit-alist) - (lambda (a b) - (let ((pos-a (or (cl-position (car a) order :test #'equal) 999)) - (pos-b (or (cl-position (car b) order :test #'equal) 999))) - (< pos-a pos-b)))))) - - -(defun akk0/extract-habits (file) - "Extract habits with date context from FILE. -Returns a list of plists with :custom-id, :todo-state, :date, :day-of-year." - (with-temp-buffer - (insert-file-contents file) - (org-mode) - (let (results) - (org-element-map (org-element-parse-buffer) 'headline - (lambda (hl) - (let ((custom-id (org-element-property :CUSTOM_ID hl)) - (todo-state (org-element-property :todo-keyword hl))) - (when (and custom-id todo-state) - ;; Get parent properties for context - (let* ((parent (org-element-property :parent hl)) - (day-of-year (or (org-element-property :DAILIES-DAY parent) - (let ((grandparent (org-element-property :parent parent))) - (when grandparent - (org-element-property :DAILIES-DAY grandparent))))) - (body (org-element-interpret-data - (org-element-contents hl)))) - (push (list :custom-id custom-id - :todo-state todo-state - :day-of-year day-of-year - :file file - :body body) - results)))))) - (nreverse results)))) - -(defun akk0/extract-all-habits (files) - (mapcan #'akk0/extract-habits files)) - -(setq akk0/journal-files - (directory-files "~/Blog/org/journal/" t "^w.*\\.org$")) - -(defun akk0/habits-alist (habits) - "Transform HABITS list into nested alists: custom-id → day-of-year → habit-data." - (let (result) - (dolist (habit habits) - (let* ((custom-id (plist-get habit :custom-id)) - (day-of-year (plist-get habit :day-of-year)) - (todo-state (plist-get habit :todo-state)) - (body (plist-get habit :body)) - ;; Get the alist for this custom-id - (inner-alist (alist-get custom-id result nil nil #'equal)) - ;; Store full data instead of just todo-state - (habit-data (list :todo-state todo-state :body body :day-of-year day-of-year)) - ;; Update the inner alist - (updated-inner (cons (cons day-of-year habit-data) inner-alist))) - ;; Update result - (setf (alist-get custom-id result nil nil #'equal) updated-inner))) - result)) - - -(setq habit-alist (akk0/habits-alist (akk0/extract-all-habits akk0/journal-files))) - -(defun akk0/get-habit-history (habit-alist custom-id day-number days-back window-size) - (let* ((inner-alist (alist-get custom-id habit-alist nil nil #'equal)) - (result nil) - (all-states nil) - (score-for-state (lambda (state) - (cond ((equal state "NO") -1) - ((equal state "YES") 1) - ((equal state "EXCELLENT") 2) - (t 0))))) - (dotimes (i days-back) - (let* ((current-day (+ (- day-number days-back) i 1)) - (current-day-str (number-to-string current-day)) - (habit-data (alist-get current-day-str inner-alist nil nil #'equal)) - (todo-state (if habit-data - (plist-get habit-data :todo-state) - "NODATA")) - (body (if habit-data - (plist-get habit-data :body) - "")) - - (doy (if habit-data - (plist-get habit-data :day-of-year) - "")) - ) - (push todo-state all-states) - (let* ((window-states (seq-take all-states window-size)) - (rolling-score (apply #'+ (mapcar score-for-state window-states)))) - (push (list :todo-state todo-state - :score (max 1 (min 5 (/ (+ rolling-score 5) 2))) - :body body - :doy doy) - result)))) - (nreverse result))) - -(defun akk0/habits-to-html-table (habit-alist day-number days-back window-size) - "Generate HTML table of habits with rolling scores. -Rows are custom-ids, columns are days." - (let ((color-map '(("NODATA" . "grey") - ("YES" . "green") - ("NO" . "red") - ("FREED" . "purple") - ("EXCELLENT" . "blue"))) - (symbol-map '(("NODATA" . "") - ("YES" . "●") - ("NO" . "×") - ("FREED" . "♣") - ("EXCELLENT" . "♦"))) - - (sorted-habits (akk0/sort-habits habit-alist)) - (html "")) - ;; Start table - (setq html (concat html "\n")) - - ;; Header row with day numbers - (setq html (concat html " \n \n")) - (dotimes (i days-back) - (let ((day (+ (- day-number days-back) i 1))) - (setq html (concat - html - (cond ((= day day-number) "") - ((= 0 (% (- day day-number) 7)) "") - (t "\n")) - - - ;; Data rows - one per habit - (dolist (entry sorted-habits) - (let* ((custom-id (car entry)) - (history (akk0/get-habit-history habit-alist custom-id day-number days-back window-size))) - (setq html (concat html (format " \n \n" (capitalize (string-remove-prefix "dailies-" custom-id))))) - - ;; Cell for each day - (dolist (day-data history) - (let* ((todo-state (plist-get day-data :todo-state)) - (score (plist-get day-data :score)) - (body (plist-get day-data :body)) - (doy (plist-get day-data :doy)) - (body-html (if (and body (not (string-empty-p body))) - (akk0/org-to-html body) - "")) - (color (alist-get todo-state color-map nil nil #'equal)) - (symbol (alist-get todo-state symbol-map nil nil #'equal)) - (class (format "habit-brightness-%d" score)) - (style-var (format "--%s%d" color score)) - (escaped-body (replace-regexp-in-string "\"" """ - (replace-regexp-in-string "\n" " " body-html))) - ) - (setq html (concat html (format " \n" - class style-var - escaped-body - doy - custom-id - todo-state - symbol))))) - - (setq html (concat html " \n")))) - - ;; End table - (setq html (concat html "
")))))) - (setq html (concat html "
%s%s
\n")) - - html)) - -(akk0/habits-to-html-table habit-alist 314 30 5) -#+END_SRC - -#+BEGIN_EXPORT html -Key: -Unknown | -× No | -● Yes | -♦ Excellent | -♣ Freed Up - -
-
-
- This section intentionally left blank. -
-
-#+END_EXPORT +#+CALL: source.org:habit-tracker() :results value html :exports results diff --git a/org/journal/w46-2025.org b/org/journal/w46-2025.org index 1acef2f..d681399 100644 --- a/org/journal/w46-2025.org +++ b/org/journal/w46-2025.org @@ -1,7 +1,7 @@ #+TODO: NO(n) | YES(y) EXCELLENT(e) FREED(f) #+title: Journal Week 46, 2025 #+BEGIN_CENTER -[[./w45-2025.org][Previous]] | [[./index.org][Index]] +[[./w45-2025.org][Previous]] | [[./index.org][Index]] | [[./w47-2025.org][Next]] #+END_CENTER * Journal Week 46, 2025 ** Monday, 10th November :journal: @@ -33,7 +33,7 @@ I want to start writing my Summer 2025 Anime Retrospective soon. I have my thoug :PROPERTIES: :CUSTOM_ID: dailies-drawing :END: -**** NO Engineering +**** YES Engineering :PROPERTIES: :CUSTOM_ID: dailies-engineering :END: @@ -41,7 +41,191 @@ I want to start writing my Summer 2025 Anime Retrospective soon. I have my thoug :PROPERTIES: :CUSTOM_ID: dailies-french :END: -**** NO Social +**** YES Social +:PROPERTIES: +:CUSTOM_ID: dailies-social +:END: +**** YES Exercise +:PROPERTIES: +:CUSTOM_ID: dailies-exercise +:END: +**** NO Reading +:PROPERTIES: +:CUSTOM_ID: dailies-reading +:END: + +** Tuesday, 11th November :journal: +:PROPERTIES: +:DAILIES-YEAR: 2025 +:DAILIES-DAY: 315 +:END: +*** YES Journal :jentry: +:PROPERTIES: +:CUSTOM_ID: dailies-blogging +:END: +Happy St. Martin's/End of WWI! + +Trying to sell our dry herb vaporizer --- cutting down weed consumption to once-every-few-months tier, and I notice I get much less full-spectrum effects vaporizing vs just smoking leading me to consume more --- but leboncoin took down our listing because something something drug paraphernalia. Nevermind that the product is legally for sale here, nevermind that there's legitimate non-drug uses for it, nevermind that the exact same product is for sale in other listings on leboncoin... of course contacting support for this kind of thing is pointless. Solveable problem but so much ado about nothing. On the flipside, we managed to sell our Roland GI-10 that we got for our [[../events/premier_impact.org][Premier Impact]] show. We bought it for €100 and sold it for €50, which I guess is alright for such an obsolete low-volume item. + +This website now runs off [[https://redbean.dev/][Redbean]] (formerly lighttpd) --- one reason being that lighttpd's documentation is an unworkable mess (we were configuring caching) and another reason being that redbean is awesome. [[https://justine.lol/][Justine]] is awesome. On that note, CSS/JS /should/ now be cached for a day while HTML /should/ be uncached, I hope (HTTP caching is confusing). + +Starting to get serious about practicing the electronic drum kit that's been standing in the corner for the past year and a half +#+BEGIN_CENTER +#+ATTR_HTML: :width 100% +#+CAPTION: /Tweaking the ergonomics on this thing is a lot of work./ +[[../../static/images/journal/2025.11-drums.jpg]] +#+END_CENTER + +I've started looking into the Linux FOSS music production stack again... provisional conclusions: +- *Zrythm* looks promising and afaict the backend is good, but the V1 frontend is unusably slow, with V2 in active development with a full GUI rewrite (GTK→QT) but still far from production-ready; + + Side note: seems like almost nobody is writing major GUIs in GTK anymore, which is understandable given how dogshit GTK has become... +- *Ardour* is still Ardour, as far as I can tell it's a good DAW but just not designed for a MIDI-heavy workflow; +- *LMMS* seems to be under very active development (26 PRs last month according to their forums) but they haven't cut so much as an alpha release since 2020... Very strange, though I get the impression they /are/ working towards a release; +- Right now a primarily *No-DAW* stack still seems the most viable. + +I'm gonna give [[https://ubuntustudio.org/][Ubuntu Studio]] another whirl tomorrow. + +Still getting less-than-ideal sleep with a lot of nightmares, though it feels like things are starting to normalize a bit again, and at least my circadian rhythm is fine. + +*** Habits :autocollapse:habits: +**** NO Meditation +:PROPERTIES: +:CUSTOM_ID: dailies-meditation +:END: +**** NO Drawing +:PROPERTIES: +:CUSTOM_ID: dailies-drawing +:END: +**** YES Engineering +:PROPERTIES: +:CUSTOM_ID: dailies-engineering +:END: +**** YES French +:PROPERTIES: +:CUSTOM_ID: dailies-french +:END: +**** YES Social +:PROPERTIES: +:CUSTOM_ID: dailies-social +:END: +**** YES Exercise +:PROPERTIES: +:CUSTOM_ID: dailies-exercise +:END: +**** NO Reading +:PROPERTIES: +:CUSTOM_ID: dailies-reading +:END: + +** Friday, 14th November :journal: +:PROPERTIES: +:DAILIES-YEAR: 2025 +:DAILIES-DAY: 318 +:END: +*** YES Journal :jentry: +:PROPERTIES: +:CUSTOM_ID: dailies-blogging +:END: +Been pretty dead for a couple days... sleep issues. I'll try and be a bit more dilligent about always adding the journal entries, at least. + +Started making a lot of refactors to the website. +*** Habits :autocollapse:habits: +**** YES Meditation +:PROPERTIES: +:CUSTOM_ID: dailies-meditation +:END: +**** NO Drawing +:PROPERTIES: +:CUSTOM_ID: dailies-drawing +:END: +**** EXCELLENT Engineering +:PROPERTIES: +:CUSTOM_ID: dailies-engineering +:END: +**** YES French +:PROPERTIES: +:CUSTOM_ID: dailies-french +:END: +**** YES Social +:PROPERTIES: +:CUSTOM_ID: dailies-social +:END: +**** YES Exercise +:PROPERTIES: +:CUSTOM_ID: dailies-exercise +:END: +**** NO Reading +:PROPERTIES: +:CUSTOM_ID: dailies-reading +:END: + +** Saturday, 15th November :journal: +:PROPERTIES: +:DAILIES-YEAR: 2025 +:DAILIES-DAY: 319 +:END: +*** YES Journal :jentry: +:PROPERTIES: +:CUSTOM_ID: dailies-blogging +:END: +Good gym session today. Worked on formatting my Anki cards. Read about the Three Kingdoms period. Not much else to say. +*** Habits :autocollapse:habits: +**** YES Meditation +:PROPERTIES: +:CUSTOM_ID: dailies-meditation +:END: +**** NO Drawing +:PROPERTIES: +:CUSTOM_ID: dailies-drawing +:END: +**** FREED Engineering +:PROPERTIES: +:CUSTOM_ID: dailies-engineering +:END: +**** EXCELLENT French +:PROPERTIES: +:CUSTOM_ID: dailies-french +:END: +**** YES Social +:PROPERTIES: +:CUSTOM_ID: dailies-social +:END: +**** EXCELLENT Exercise +:PROPERTIES: +:CUSTOM_ID: dailies-exercise +:END: +**** YES Reading +:PROPERTIES: +:CUSTOM_ID: dailies-reading +:END: +** Sunday, 16th November :journal: +:PROPERTIES: +:DAILIES-YEAR: 2025 +:DAILIES-DAY: 320 +:END: +*** YES Journal :jentry: +:PROPERTIES: +:CUSTOM_ID: dailies-blogging +:END: +Two hours of drums practice today! Started feeling somewhat lethargic after that. Did a bunch of work reorganizing Hydrus. +*** Habits :autocollapse:habits: +**** NO Meditation +:PROPERTIES: +:CUSTOM_ID: dailies-meditation +:END: +**** NO Drawing +:PROPERTIES: +:CUSTOM_ID: dailies-drawing +:END: +**** FREED Engineering +:PROPERTIES: +:CUSTOM_ID: dailies-engineering +:END: +**** NO French +:PROPERTIES: +:CUSTOM_ID: dailies-french +:END: +**** YES Social :PROPERTIES: :CUSTOM_ID: dailies-social :END: diff --git a/org/journal/w47-2025.org b/org/journal/w47-2025.org new file mode 100644 index 0000000..5572862 --- /dev/null +++ b/org/journal/w47-2025.org @@ -0,0 +1,54 @@ +#+TODO: NO(n) | YES(y) EXCELLENT(e) FREED(f) +#+TODO: TODO | DONE(d) CANCELLED(c) +#+title: Journal Week 47, 2025 +#+BEGIN_CENTER +[[./w46-2025.org][Previous]] | [[./index.org][Index]] +#+END_CENTER +* Journal Week 47, 2025 +** Thursday, 20th November 2025 +:PROPERTIES: +:DAILIES-YEAR: 2025 +:DAILIES-DAY: 324 +:END: +*** NO Journal +:PROPERTIES: +:CUSTOM_ID: dailies-blogging +:END: +Oof I have not been good about updating the journal again. + +**** Daily Planning +***** TODO Rework "looking for work" page +***** TODO Rework habits?? +***** TODO Get akk0{at}webbieweb{dot}org email working again + + + +*** Habits :autocollapse: +**** NO Meditation +:PROPERTIES: +:CUSTOM_ID: dailies-meditation +:END: +**** NO Drawing +:PROPERTIES: +:CUSTOM_ID: dailies-drawing +:END: +**** NO Engineering +:PROPERTIES: +:CUSTOM_ID: dailies-engineering +:END: +**** NO French +:PROPERTIES: +:CUSTOM_ID: dailies-french +:END: +**** NO Social +:PROPERTIES: +:CUSTOM_ID: dailies-social +:END: +**** NO Exercise +:PROPERTIES: +:CUSTOM_ID: dailies-exercise +:END: +**** NO Reading +:PROPERTIES: +:CUSTOM_ID: dailies-reading +:END: diff --git a/org/sitemap.org b/org/sitemap.org index 230046c..e628c45 100644 --- a/org/sitemap.org +++ b/org/sitemap.org @@ -1,11 +1,13 @@ #+TITLE: Sitemap for project pages +- [[file:source.org][Webbieweb.org Sources]] - [[file:index.org][Index]] - [[file:todo.org][To Do]] - [[file:about.org][About]] - [[file:friends.org][Friends]] - [[file:journal/index.org][Journal]] + - [[file:journal/w47-2025.org][Journal Week 47, 2025]] - [[file:journal/w46-2025.org][Journal Week 46, 2025]] - [[file:journal/w41-2025.org][Journaly Week 41, 2025]] - [[file:journal/w44-2025.org][Journal Week 44, 2025]] @@ -33,10 +35,10 @@ - [[file:events/wroclaw.org][Wrocław/Millennium Strike]] - [[file:work/index.org][Work]] + - [[file:work/looking_for_work.org][Looking for Work]] - [[file:work/portfolio.org][Portfolio]] - [[file:work/toshokan_retrospective.org][Toshokan Retrospective]] - [[file:work/eris_retrospective.org][Eris Retrospective]] - - [[file:work/looking_for_work.org][Looking for Work]] - [[file:work/crypto_contracting_reflections.org][Reflections on Independent Contracting in the Cryptocurrency Sector (2021-2022)]] - [[file:other/index.org][Other]] diff --git a/org/source.org b/org/source.org new file mode 100644 index 0000000..f93dc10 --- /dev/null +++ b/org/source.org @@ -0,0 +1,1093 @@ +#+title: Webbieweb.org Sources +* Webbieweb.org Literate Sources :h4left:h5left:h3underline: +** Introduction +These are the [[https://en.wikipedia.org/wiki/Literate_programming][literate]] sources of /webbieweb.org/. The code blocks here constitute the actual sources; therefore, this document is guaranteed to be up to date. + +This page is self-contained; the only dependency is =ox-publish=. The following directory structure is expected: +#+BEGIN_EXAMPLE +. +|-- html ;; Export destination; you can copy this dir to any static file host and host the website that way. +|-- org ;; Org-mode sources; these will get compiled and the output copied to html/. + `-- source.org ;; This file. +|-- static ;; Images, videos, CSS files, fonts etc will be copied unchanged to html/static. +`-- util + |-- head.html ;; Contains HTML ; will be prepended to every output file. + |-- postamble.html ;; Navbar; will be prepended to of every output file. + `-- preamble.html ;; Footer; as above. +#+END_EXAMPLE +#+BEGIN_CENTER +(Apologies for the misalignment, I don't know why that happens.) +#+END_CENTER + +** Export Commands +Load this file up in Emacs and hit C-c C-c on the code block below to export changes to HTML. +#+NAME: blog-publish +#+BEGIN_SRC emacs-lisp :noweb no-export :results silent +<> +(blog/publish) +(org-babel-tangle) +#+END_SRC + +The one below will ignore caching; necessary in some situations, for instance: changes under =util/=. +#+name: force-publish +#+BEGIN_SRC emacs-lisp :noweb no-export :results silent +<> +(blog/force-publish) +(org-babel-tangle) +#+END_SRC +** Elisp +*** Basic Settings/Scaffolding :autocollapse: +#+NAME: blog-scaffolding +#+BEGIN_SRC emacs-lisp :results output :noweb no-export +(require 'ox-publish) + +<> + +(defun blog/get-util (x) + (with-temp-buffer + (insert-file-contents (concat "../util/" x)) + (buffer-string))) + +(setq org-html-metadata-timestamp-format "%Y-%m-%d") + +(defun blog/spec () + "Return project settings for use with `org-publish-project-alist'." + (let* ((html-head (blog/get-util "head.html")) + (html-preamble (blog/get-util "preamble.html")) + (html-postamble (blog/get-util "postamble.html"))) + + + `(("pages" + :base-directory "." + :base-extension "org" + :recursive t + :publishing-directory "../html" + :publishing-function org-html-publish-to-html + + :html-doctype "html5" + :html-html5-fancy t + + :html-viewport ((width "100%") + (initial-scale "0.7") + (minimum-scale "") + (maximum-scale "") + (user-scalable "")) + + :language "en" + :section-numbers nil + + :with-toc nil + :with-date t + :with-title nil + :with-author nil + + :auto-sitemap t + + :sitemap-sort-files anti-chronologically + :sitemap-format-entry blog/sitemap-format-entry + + :sitemap-function + blog/sitemap-function + + + :headline-levels 4 + :html-head ,html-head + + :html-preamble ,html-preamble + :html-postamble + (lambda (p) + (let* ((timestamp-format (plist-get p :html-metadata-timestamp-format)) + (date (org-export-data (org-export-get-date p timestamp-format) + p)) + (file (plist-get p :input-file)) + (modified (format-time-string + timestamp-format + (and file (file-attribute-modification-time + (file-attributes file)))))) + (concat + "")))) + + ("static" + :base-directory "../static" + :base-extension "css\\|txt\\|jpg\\|gif\\|png\\|ttf\\|js\\|mp4\\|webm" + :recursive t + :publishing-directory "../html/static" + :publishing-function org-publish-attachment) + + ("RSS" + :base-directory "../RSS" + :base-extension "xml" + :publishing-directory "../html" + :publishing-function org-publish-attachment) + + ("blog" :components ("pages" "static" "RSS"))))) + +(defun blog/publish () + (setq org-publish-project-alist (blog/spec)) + (org-publish-all)) + +(defun blog/force-publish () + (setq org-publish-project-alist (blog/spec)) + (org-publish-remove-all-timestamps) + (org-publish-all)) +#+END_SRC + +** Features +*** Sitemap :autocollapse: +Files with =#+FILETAGS: :no-sitemap:= at the top will be excluded from [[./sitemap.org][the sitemap]]. Every directory =dir/= will link to =dir/index.org=, with =index.org= being removed as a child entry. +#+NAME: no-sitemap +#+BEGIN_SRC emacs-lisp +(defun blog/sitemap-format-entry + (entry style project) + ;; Blank out entries with :no_sitemap: + (let* ((tags (org-publish-find-property entry :filetags project)) + (skip (member "no_sitemap" tags))) + + (cond + (skip "") + + ((not (directory-name-p entry)) + (format + "[[file:%s][%s]]\n" + entry + (org-publish-find-title entry project))) + + ;; Link index to top level + ((eq style 'tree) + (format + "[[file:%sindex.org][%s]]\n" + entry + (capitalize (file-name-nondirectory (directory-file-name entry))))) + + (t entry)))) + + +;; Remove blank entries from sitemap +(defun blog/sitemap-function + (title lst) + (let* ((sitemap (org-publish-sitemap-default title lst))) + (replace-regexp-in-string "^[ \t]*-[ \t]*\n" "" sitemap))) + +#+END_SRC + +*** Tag-based Section Control :autocollapse: +Org-mode headers support tags: +#+BEGIN_SRC org +,* Header :foo: + Sample text +#+END_SRC + +Which will compile into something like: +#+BEGIN_SRC html +
+
Header + + foo + +
+
+

Sample text

+
+
+#+END_SRC + +We can use these tags to granularly control styling and JS features per header. +We will hide the tags themselves: + +#+BEGIN_SRC css :tangle ../html/static/style.css +.tag { display: none; } +#+END_SRC + +*** Header Styling Tags :autocollapse: +Tags for granular styling. This page has =:h4left:h5left:h3underline:= at the top level. +#+BEGIN_SRC css :tangle ../html/static/style.css +div:has(* .tag .h4left) h4 { + text-align: left; +} + +div:has(* .tag .h5left) h5 { + text-align: left; +} + +div:has(* .tag .h3underline) h3 { + text-decoration: underline; +} +#+END_SRC + +*** Journal :autocollapse: +Here's a template for the journal files, as reference for what follows: +**** Template :autocollapse: +#+INCLUDE: "./journal/template.org" src org + +**** Styling +#+BEGIN_SRC css :tangle ../html/static/style.css +div:has(h3 .tag .journal) { + border: none; + box-shadow: none; +} + +div:has(> h3 .tag .journal)::after { + content: '~ ❦ ~'; + display: block; + text-align: center; + padding-top: 0.2rem; + padding-bottom: 0.2rem; + color: var(--grey4); + font-size: 2rem; +} + +h3:has(.tag .journal) { + text-align: left; +} + +h4:has(.tag .jentry) { + display: none; +} + +h4:has(.tag .habits) { + text-align: left; +} +#+END_SRC +*** Habit Tracker :autocollapse: +Implements the habit tracking table on the [[./index.org][front page]]. Habits are extracted from journal entries and rendered into a table, including a "streak" heatmap and the ability to click cells to see the corresponding entry. + +**** Elisp :autocollapse: +#+NAME: habit-tracker +#+BEGIN_SRC emacs-lisp :results silent +(defun akk0/org-to-html (org-string) + "Convert ORG-STRING to HTML." + (with-temp-buffer + (insert org-string) + (org-mode) + (org-export-as 'html nil nil t nil))) + +(defun akk0/sort-habits (habit-alist) + "Sort habit-alist by a predefined order of custom-ids." + (let ((order '("dailies-blogging" "dailies-meditation" "dailies-french" "dailies-engineering" + "dailies-exercise" "dailies-drawing" "dailies-reading" "dailies-social"))) + (sort (copy-sequence habit-alist) + (lambda (a b) + (let ((pos-a (or (cl-position (car a) order :test #'equal) 999)) + (pos-b (or (cl-position (car b) order :test #'equal) 999))) + (< pos-a pos-b)))))) + + +(defun akk0/extract-habits (file) + "Extract habits with date context from FILE. +Returns a list of plists with :custom-id, :todo-state, :date, :day-of-year." + (with-temp-buffer + (insert-file-contents file) + (org-mode) + (let (results) + (org-element-map (org-element-parse-buffer) 'headline + (lambda (hl) + (let ((custom-id (org-element-property :CUSTOM_ID hl)) + (todo-state (org-element-property :todo-keyword hl))) + (when (and custom-id todo-state) + ;; Get parent properties for context + (let* ((parent (org-element-property :parent hl)) + (day-of-year (or (org-element-property :DAILIES-DAY parent) + (let ((grandparent (org-element-property :parent parent))) + (when grandparent + (org-element-property :DAILIES-DAY grandparent))))) + (body (org-element-interpret-data + (org-element-contents hl)))) + (push (list :custom-id custom-id + :todo-state todo-state + :day-of-year day-of-year + :file file + :body body) + results)))))) + (nreverse results)))) + +(defun akk0/extract-all-habits (files) + (mapcan #'akk0/extract-habits files)) + +(setq akk0/journal-files + (directory-files "./journal/" t "^w.*\\.org$")) + +(defun akk0/habits-alist (habits) + "Transform HABITS list into nested alists: custom-id → day-of-year → habit-data." + (let (result) + (dolist (habit habits) + (let* ((custom-id (plist-get habit :custom-id)) + (day-of-year (plist-get habit :day-of-year)) + (todo-state (plist-get habit :todo-state)) + (body (plist-get habit :body)) + ;; Get the alist for this custom-id + (inner-alist (alist-get custom-id result nil nil #'equal)) + ;; Store full data instead of just todo-state + (habit-data (list :todo-state todo-state :body body :day-of-year day-of-year)) + ;; Update the inner alist + (updated-inner (cons (cons day-of-year habit-data) inner-alist))) + ;; Update result + (setf (alist-get custom-id result nil nil #'equal) updated-inner))) + result)) + + +(setq habit-alist (akk0/habits-alist (akk0/extract-all-habits akk0/journal-files))) + +(defun akk0/get-habit-history (habit-alist custom-id day-number days-back window-size) + (let* ((inner-alist (alist-get custom-id habit-alist nil nil #'equal)) + (result nil) + (all-states nil) + (score-for-state (lambda (state) + (cond ((equal state "NO") -1) + ((equal state "YES") 1) + ((equal state "EXCELLENT") 2) + (t 0))))) + (dotimes (i days-back) + (let* ((current-day (+ (- day-number days-back) i 1)) + (current-day-str (number-to-string current-day)) + (habit-data (alist-get current-day-str inner-alist nil nil #'equal)) + (todo-state (if habit-data + (plist-get habit-data :todo-state) + "NODATA")) + (body (if habit-data + (plist-get habit-data :body) + "")) + + (doy (if habit-data + (plist-get habit-data :day-of-year) + "")) + ) + (push todo-state all-states) + (let* ((window-states (seq-take all-states window-size)) + (rolling-score (apply #'+ (mapcar score-for-state window-states)))) + (push (list :todo-state todo-state + :score (max 1 (min 5 (/ (+ rolling-score 5) 2))) + :body body + :doy doy) + result)))) + (nreverse result))) + +(defun akk0/habits-to-html-table (habit-alist day-number days-back window-size) + "Generate HTML table of habits with rolling scores. +Rows are custom-ids, columns are days." + (let ((color-map '(("NODATA" . "grey") + ("YES" . "green") + ("NO" . "red") + ("FREED" . "purple") + ("EXCELLENT" . "blue"))) + (symbol-map '(("NODATA" . "") + ("YES" . "●") + ("NO" . "×") + ("FREED" . "♣") + ("EXCELLENT" . "♦"))) + + (sorted-habits (akk0/sort-habits habit-alist)) + (html "")) + ;; Start table + (setq html (concat html "\n")) + + ;; Header row with day numbers + (setq html (concat html " \n \n")) + (dotimes (i days-back) + (let ((day (+ (- day-number days-back) i 1))) + (setq html (concat + html + (cond ((= day day-number) "") + ((= 0 (% (- day day-number) 7)) "") + (t "\n")) + + + ;; Data rows - one per habit + (dolist (entry sorted-habits) + (let* ((custom-id (car entry)) + (history (akk0/get-habit-history habit-alist custom-id day-number days-back window-size))) + (setq html (concat html (format " \n \n" (capitalize (string-remove-prefix "dailies-" custom-id))))) + + ;; Cell for each day + (dolist (day-data history) + (let* ((todo-state (plist-get day-data :todo-state)) + (score (plist-get day-data :score)) + (body (plist-get day-data :body)) + (doy (plist-get day-data :doy)) + (body-html (if (and body (not (string-empty-p body))) + (akk0/org-to-html body) + "")) + (color (alist-get todo-state color-map nil nil #'equal)) + (symbol (alist-get todo-state symbol-map nil nil #'equal)) + (class (format "habit-brightness-%d" score)) + (style-var (format "--%s%d" color score)) + (escaped-body (replace-regexp-in-string "\"" """ + (replace-regexp-in-string "\n" " " body-html))) + ) + (setq html (concat html (format " \n" + class style-var + escaped-body + doy + custom-id + todo-state + symbol))))) + + (setq html (concat html " \n")))) + + (setq html (concat html "
")))))) + (setq html (concat html "
%s%s
\n")) + + ;; Legend and expansion section + (setq html (concat html "Key: +Unknown | +× No | +● Yes | +♦ Excellent | +♣ Freed Up + +
+
+
+ This section intentionally left blank. +
+
+")) + + html)) + +(akk0/habits-to-html-table habit-alist (string-to-number (format-time-string "%j")) 30 5) +#+END_SRC + +**** Expansion Section :autocollapse: +A bit of JS for enabling the expanding of entries. +#+BEGIN_SRC javascript :tangle ../html/static/footnote.js +function formatDayOfYear(dayOfYear, year) { + const date = new Date(year, 0, dayOfYear); + + return date.toLocaleDateString('en-GB', { + day: 'numeric', + month: 'short', + year: 'numeric' + }); +} + +let selectedCell = null; + +function showHabitPopup(cell) { + var bodyHtml = cell.getAttribute('data-body'); + var doy = cell.getAttribute('data-doy'); + var activity = cell.getAttribute('data-activity'); + var status = cell.getAttribute('data-status'); + activity = activity.replace(/^dailies-/, '').replace(/^./, c => c.toUpperCase()) + + if (!bodyHtml) bodyHtml = "This section intentionally left blank." + + bodyHtml = `

${activity} — ${formatDayOfYear(parseInt(doy), 2025)}

${bodyHtml}` + + document.getElementById('habitPopupContent').innerHTML = bodyHtml; + + if (selectedCell) { + selectedCell.classList.remove('habitgrid-selected'); + } + + cell.classList.add('habitgrid-selected'); + selectedCell = cell; + enableFootnotes(); +} +#+END_SRC +**** CSS :autocollapse: +Color habit entries based on their completion status: +#+BEGIN_SRC css :tangle ../html/static/style.css +.done.YES, .todo.NO, .done.EXCELLENT, .done.FREED { + display: none; +} + +h2:has(.done.YES), h3:has(.done.YES), h4:has(.done.YES), h5:has(.done.YES), .grid.YES { + color: var(--green3); +} + +h2:has(.todo.NO), h3:has(.todo.NO), h4:has(.todo.NO), h5:has(.todo.NO), .grid.NO { + color: var(--red3); +} + +h2:has(.done.EXCELLENT), h3:has(.done.EXCELLENT), h4:has(.done.EXCELLENT), h5:has(.done.EXCELLENT), .grid.EXCELLENT { + color: var(--blue3); +} + +h2:has(.done.FREED), h3:has(.done.FREED), h4:has(.done.FREED), h5:has(.done.FREED), .grid.FREED { + color: var(--purple3); +} +#+END_SRC + +Style the cells, set legible text color, outline clickable: +#+BEGIN_SRC css :tangle ../html/static/style.css +.habit-cell { + text-align: center; + vertical-align: middle; + width: 20px; + height: 20px; + cursor: pointer; + user-select: none; +} + +.habit-cell.habit-brightness-1 { color: var(--grey5); outline-color: var(--grey5) !important; } +.habit-cell.habit-brightness-2 { color: var(--grey5); outline-color: var(--grey5) !important; } +.habit-cell.habit-brightness-3 { color: var(--grey5); outline-color: var(--grey5) !important; } +.habit-cell.habit-brightness-4 { color: var(--grey2); outline-color: var(--grey5) !important; } +.habit-cell.habit-brightness-5 { color: var(--grey3); outline-color: var(--grey5) !important; } + +.habit-cell:not([data-body=""]) { + outline: dotted 2px; + outline-offset: -2px; +} +.habitgrid-selected { + outline: solid 2px var(--purple5) !important; + outline-offset: -2px; +} +#+END_SRC + + + +*** Header Collapsing :autocollapse: +Sections can be expanded and collapsed by clicking on their headers; this will assign =.orgjq-expanded= and =.orgjq-contracted= CSS classes as appropriate. Headers with the =:autocollapse:= tag will be collapsed by default (like this section). +#+BEGIN_SRC css :tangle ../html/static/style.css +.orgjq-expanded p { + margin-top: 0; + padding-bottom: 1.5rem; + margin-bottom: 0; +} + +.orgjq-contracted > div { + display: none; +} + +.orgjq-contracted h2, .orgjq-contracted h3, .orgjq-contracted h4, orgjq-contracted h5 { + padding-top: 0.3rem !important; + padding-bottom: 0.3rem !important; +} + +.orgjq-contracted > :first-child::before { + content: '⮞ '; +} + +.orgjq-expanded > h4:has(.tag .autocollapse)::before { + content: '⮟ '; +} +#+END_SRC + +#+BEGIN_SRC javascript :tangle ../html/static/hide.js +function isHideable(div_obj) { + // Ignore for TOC since it is handled differently + if (div_obj.id === "text-table-of-contents") return false; + if (div_obj.id === "table-of-contents") return false; + // No point in hiding top level + if (div_obj.classList.contains("outline-2")) return false; + if (div_obj.classList.contains("outline-text-2")) return false; + return true; +} + +function orgjqHide(div_obj) { + if (!isHideable(div_obj)) return; + const parent = div_obj.parentElement; + parent.classList.remove("orgjq-expanded"); + parent.classList.add("orgjq-contracted"); +} + +function orgjqShow(div_obj) { + const parent = div_obj.parentElement; + parent.classList.remove("orgjq-contracted"); + parent.classList.add("orgjq-expanded"); +} + +function orgjqToggle(div_obj) { + const parent = div_obj.parentElement; + if (parent.classList.contains("orgjq-expanded")) { + orgjqHide(div_obj); + } else { + orgjqShow(div_obj); + } +} + +function orgjqEnable() { + // Called once e.g. the first time the page is loaded + // handle the click event for each header + for (let i = 2; i <= 7; ++i) { + const headers = document.querySelectorAll(`h${i}`); + headers.forEach(header => { + header.style.cursor = "pointer"; + header.addEventListener('click', function() { + // Get the first div sibling after the header + const parent = this.parentElement; + const divs = parent.querySelectorAll(':scope > div'); + if (divs.length > 0) { + orgjqToggle(divs[0]); + } + }); + }); + } + + // Mark everything as open... + for (let i = 2; i <= 7; ++i) { + const headers = document.querySelectorAll(`h${i}`); + headers.forEach(header => { + const parent = header.parentElement; + parent.classList.remove("orgjq-contracted"); + parent.classList.add("orgjq-expanded"); + }); + } + + // ... except TOC ... + const toc = document.querySelector("div#table-of-contents"); + if (toc) { + toc.classList.remove("orgjq-expanded"); + toc.classList.add("orgjq-contracted"); + } + // ... and autocollapse. + const autocollapse = document.querySelectorAll(".autocollapse"); + autocollapse.forEach(element => { + const grandparent = element.parentElement?.parentElement; + if (grandparent) { + orgjqHide(grandparent); + } + }); +} + +// Run when DOM is loaded +if (document.readyState === 'loading') { + document.addEventListener('DOMContentLoaded', orgjqEnable); +} else { + orgjqEnable(); +} +#+END_SRC +*** Hover Notes :autocollapse: +Turns org-mode footnotes (=[fn::Like this]=) into hover-notes[fn::Like this]. +#+BEGIN_SRC javascript :tangle ../html/static/footnote.js +function enableFootnotes() { + const footnoteRefs = document.querySelectorAll('.footref') + + footnoteRefs.forEach(ref => { + const footnoteId = ref.href.split('#')[1] + ref.setAttribute('data-footnote-id', footnoteId) + ref.href = 'javascript:void(0)'; + + ref.addEventListener('mouseenter', function() { + // Find footnote element + const footnoteId = this.getAttribute('data-footnote-id') + + const footnoteElement = document.getElementById(footnoteId).parentElement.nextElementSibling.children[0] + + if (footnoteElement) { + // Create tooltip container + const tooltip = document.createElement('div'); + tooltip.className = 'footnote-tooltip' + tooltip.innerHTML = footnoteElement.innerHTML + + // Position tooltip + const rect = this.getBoundingClientRect(); + tooltip.style.position = 'absolute' + tooltip.style.top = (rect.bottom + window.scrollY + 5) + 'px' + tooltip.style.left = rect.left + 'px' + + // Add to page + document.body.appendChild(tooltip) + + // Store reference for cleanup + this._tooltip = tooltip + } + }); + + ref.addEventListener('mouseleave', function() { + // Remove tooltip + if (this._tooltip) { + this._tooltip.remove() + this._tooltip = null + } + }); + }); + + // Hide footnotes section + document.querySelector("#footnotes").style.display='none' +} + +document.addEventListener('DOMContentLoaded', enableFootnotes); +#+END_SRC + + +** Appearance +*** Global :autocollapse: +**** Variables +#+BEGIN_SRC css :tangle ../html/static/style.css +:root { + --site-width: 1000px; + --vert-content-margin: 0.3rem; + + --font-size: 1.2rem; + --line-height: 1.6rem; + --font-family: "Source Serif Pro"; + + --scale: 2; +} +#+END_SRC +**** Color Variables +#+BEGIN_SRC css :tangle ../html/static/style.css +:root { + --green1: #123218; + --green2: #254f1b; + --green3: #356c22; + --green4: #5e8e40; + --green5: #85aa5f; + + --blue1: #1b2459; + --blue2: #153a79; + --blue3: #2f5394; + --blue4: #417eaf; + --blue5: #69a8c6; + + --purple1: #2e1e58; + --purple2: #493281; + --purple3: #6a45a6; + --purple4: #855aa3; + --purple5: #9b77b5; + + --red1: #4b1313; + --red2: #682017; + --red3: #84301c; + --red4: #9c4830; + --red5: #c46849; + + --grey1: #202124; + --grey2: #33333b; + --grey3: #605b66; + --grey4: #a79fa7; + --grey5: #c5bcbc; + + --accent1: var(--purple4); + --link: var(--blue3); + --black: var(--grey1); + --grey: var(--grey3); + --background: var(--grey5); + --background-tooltip: var(--grey5); +} +#+END_SRC +**** Background image +#+BEGIN_SRC css :tangle ../html/static/style.css +body::before, +body::after { + content: ''; + position: fixed; + top: 0; + height: 100vh; + width: 50%; + background-image: url('/static/images/background.png'); + background-repeat: no-repeat; + z-index: -1; + + image-rendering: pixelated; /* For Chrome/Safari */ + image-rendering: -moz-crisp-edges; /* For Firefox */ + image-rendering: crisp-edges; /* Fallback */ + + background-size: calc(960px * var(--scale)) calc(1080px * var(--scale)); +} + +body::before { + left: 0; + background-position: top right; +} + +body::after { + right: 0; + background-position: top right; + /* Flip the right side horizontally */ + transform: scaleX(-1); +} +#+END_SRC + +***** TODO This is a weird approach and has some issues +- White line in center in some setups +- Crunchy lines depending on DPI + +**** Fonts +#+BEGIN_SRC css :tangle ../html/static/style.css +body { + font-family: var(--font-family); + font-size: var(--font-size); + line-height: var(--line-height); + word-spacing: 0.25ch; + font-weight: 400; +} +#+END_SRC + +**** Header/Content/Footer blocks +#+BEGIN_SRC css :tangle ../html/static/style.css +#content, #header, #footer { + min-width: 500px; + max-width: min(var(--site-width), 90vw); + margin: 0 auto; + padding: 5px 25px; + + border: 2px double var(--grey1); + margin-bottom: 1.2rem; + background-color: var(--background); +} + +#header { + display: flex; +} + +#content, #footer { + box-shadow: 7px 7px 7px var(--grey1); +} + +#footer { + padding-top: 1rem; + padding-bottom: 1rem; +} + +#header a, #header a:visited{ + color: var(--purple2); +} + +#header hr { + margin-bottom: var(--vert-content-margin); +} + +#footer hr { + margin-top: var(--vert-content-margin); +} + +#content h2, #content h3, #content h4, #content h5 { + margin-bottom: 1rem; + margin-top: 0.5rem; + margin-left: 0.5rem; +} + +#content h2 { + margin-top: 1rem; +} + +#content h3, #content h4 { + padding-top: 0.5rem; + padding-bottom: 0.5rem; +} + +#content h5 { + padding-top: 0.3rem; + padding-bottom: 0.3rem; +} + +#+END_SRC +*** Colors :autocollapse: +**** Color Assignments +#+BEGIN_SRC css :tangle ../html/static/style.css +body { + color: var(--black); + background-color: var(--background); +} + +#+END_SRC +**** Syntax Highlighting +#+BEGIN_SRC css :tangle ../html/static/style.css +pre {background-color:var(--grey1); color:var(--grey5);} +pre span.org-builtin {color:var(--blue4);font-weight:bold;} +pre span.org-string {color:var(--green4);} +pre span.org-keyword {color:var(--purple5);font-weight:bold;} +pre span.org-variable-name {color:var(--green5);font-style:italic;} +pre span.org-function-name {color:var(--blue5);} +pre span.org-type {color:var(--purple4);} +pre span.org-preprocessor {color:var(--grey5);font-weight:bold;} +pre span.org-constant {color:var(--red5);} +pre span.org-comment-delimiter {color:var(--grey3);} +pre span.org-comment {color:var(--grey3);font-style:italic} +pre span.org-outshine-level-1 {color:var(--grey5);font-style:italic} +pre span.org-outshine-level-2 {color:var(--grey5);font-style:italic} +pre span.org-outshine-level-3 {color:var(--grey5);font-style:italic} +pre span.org-outshine-level-4 {color:var(--grey5);font-style:italic} +pre span.org-outshine-level-5 {color:var(--grey5);font-style:italic} +pre span.org-outshine-level-6 {color:var(--grey5);font-style:italic} +pre span.org-outshine-level-7 {color:var(--grey5);font-style:italic} +pre span.org-outshine-level-8 {color:var(--grey5);font-style:italic} +pre span.org-outshine-level-9 {color:var(--grey5);font-style:italic} +pre span.org-rainbow-delimiters-depth-1 {color:var(--grey4);} +pre span.org-rainbow-delimiters-depth-2 {color:var(--blue4);} +pre span.org-rainbow-delimiters-depth-3 {color:var(--green4);} +pre span.org-rainbow-delimiters-depth-4 {color:var(--red4);} +pre span.org-rainbow-delimiters-depth-5 {color:var(--purple4);} +pre span.org-rainbow-delimiters-depth-6 {color:var(--blue4);} +pre span.org-rainbow-delimiters-depth-7 {color:var(--green4);} +pre span.org-rainbow-delimiters-depth-8 {color:var(--red4);} +pre span.org-rainbow-delimiters-depth-9 {color:var(--purple4);} +pre span.org-sh-quoted-exec {color:var(--purple3);} +pre span.org-doc {color:var(--green5);font-style:italic;} +pre span.org-css-selector {color:var(--blue5);font-weight:bold;} +pre span.org-css-property {color:var(--purple4); font-weight: bold;} +#+END_SRC + +*** General CSS :autocollapse: +**** Et Cetera +#+BEGIN_SRC css :tangle ../html/static/style.css +hr { + border: 0; + border-top: 2px dotted var(--black); +} + +a, a:visited { + color: var(--link); + text-decoration: none; +} + +.figure-number { + display: none; +} + +.caption { + padding-top: 0.5rem; + font-style: italic; +} + +.outline-3, .outline-4, .outline-5 { + padding-left: 0.6rem; + border-radius: 0.2em; + margin: 0.7rem; +} + +.outline-text-3, .outline-text-4, .outline-text-5 { + margin: 0.3rem 1rem 0.5rem 0.5rem; +} + +h2 { + line-height: 1.5rem; + text-align: center; +} + +h3, h4, h5 { + text-align: center; +} + +.section-number-1, .section-number-2, .section-number-3, .section-number-4 { display: none; } +#+END_SRC + +**** Utility Classes +#+BEGIN_SRC css :tangle ../html/static/style.css +.center { + display: block; + margin-left: auto; + margin-right: auto; + text-align: center; +} + +.navbar-link { + margin-right: 5px; + margin-left: 5px; +} + +.center, div.center { + text-align: center; + margin-left: auto; + margin-right: auto; +} + +.center figure, +.center figcaption, +div.center figure, +div.center figcaption { + text-align: center; + margin-left: auto; + margin-right: auto; +} + +.multi-img { + display: flex; + justify-content: center; + text-align: center; + margin: 20px; + gap: 20px; +} + +.multi-img figure { margin: 0px; } + +.poetry { + padding-top: 4rem; + padding-bottom: 4rem; + text-align: center; +} +#+END_SRC + +*** Elements :autocollapse: +**** Looking for Work +#+BEGIN_SRC css :tangle ../html/static/style.css +#looking-for-work { + background-color: var(--red2); + color: var(--grey5); + padding: 5px 25px; + margin-left: auto; + margin-top: -0.32rem; + margin-bottom: -0.32rem; + margin-right: -1.55rem; + border: 2px double var(--purple5); +} + +#looking-for-work a, #looking-for-work a:visited { + color: var(--blue5) !important; +} +#+END_SRC +**** Code Blocks +#+BEGIN_SRC css :tangle ../html/static/style.css +.src, .example { + font-family: "monospace"; + font-size: 1rem; +} +#+END_SRC +**** Publish/modified Date +#+BEGIN_SRC css :tangle ../html/static/style.css +#publish-date, #modified-date { + font-style: italic; +} +#+END_SRC +**** Table of Contents +#+BEGIN_SRC css :tangle ../html/static/style.css +#table-of-contents { + z-index: 1; + margin-top: 105px; + margin-right: 5%; + font-size: calc(var(--font-size) * 0.8); + position: fixed; + right: 0em; + top: 0em; + background: var(--background-toc); + text-align: right; + min-height: 3rem; + + box-shadow: 0 0 0.5em var(--shadow-toc); + -webkit-box-shadow: 0 0 0.5em var(--shadow-toc); + -moz-box-shadow: 0 0 0.5em var(--shadow-toc); + -webkit-border-bottom-left-radius: 5px; + -moz-border-radius-bottomleft: 5px; + /* ensure doesn't flow off the screen when expanded */ + max-height: 80%; + overflow: auto; +} +#table-of-contents h2 { + font-size: 13pt; + max-width: 9em; + border: 0; + font-weight: normal; + margin-top: 0.75em; + margin-bottom: 0.75em; + padding-left: 0.5em; + padding-right: 0.5em; + padding-top: 0.05em; + padding-bottom: 0.05em; } +#table-of-contents #text-table-of-contents { + display: none; + text-align: left; } +#table-of-contents:hover #text-table-of-contents { + display: block; + padding: 0.5em; + margin-top: -1.5em; + padding-right: 20px; +} + +#table-of-contents { + display: none; +} +#+END_SRC +**** To-Dos +#+BEGIN_SRC css :tangle ../html/static/style.css +.TODO { color: var(--red3); } +.DONE { color: var(--green3); } +#+END_SRC diff --git a/org/work/looking_for_work.org b/org/work/looking_for_work.org index ac0c94a..c22e7a0 100644 --- a/org/work/looking_for_work.org +++ b/org/work/looking_for_work.org @@ -1,7 +1,7 @@ #+title: Looking for Work * Looking for Work ** About Me -I'm Akk0, long-term enthusiast software developer, sysadmin, freelancer and this website's webmaster. I've been at this computer thing for a while --- my first =dist-upgrade= was Linux Mint 15 "Olivia" in 2013 --- and I am currently actively looking for work on a freelance, contract or part-time basis, full remote or partially on-site in the Paris area[fn::Although do mind that my French skills albeit improving are still rather minimal.]; I also accept full-time offers. +I'm Akk0, long-term enthusiast software developer, sysadmin, freelancer and this website's webmaster. I've been at this computer thing for a while --- my first =dist-upgrade= was Linux Mint 15 "Olivia" in 2013 --- and I am currently actively looking for work on a freelance, contract or part-time basis, full remote or partially on-site in the Paris area[fn::Although do mind that my French skills albeit improving are still rather minimal.]. I am also open to regular full-time positions at interesting copmanies. In order to rapidly build connections and get the ball rolling, I am currently offering my skills at a low, flat rate of /€30 per hour./ Additionally, I am offering *2 hours* of /no strings attached free labour/ to anyone reading this /for free/ --- please do keep reading! ** Services Offered diff --git a/static/collapse.css b/static/collapse.css deleted file mode 100644 index e834c7a..0000000 --- a/static/collapse.css +++ /dev/null @@ -1,3 +0,0 @@ -.orgjq-contracted > div { - display: none; -} diff --git a/static/custom.css b/static/custom.css deleted file mode 100644 index d996870..0000000 --- a/static/custom.css +++ /dev/null @@ -1,230 +0,0 @@ -.poetry { - padding-top: 4rem; - padding-bottom: 4rem; - text-align: center; -} - - -.figure-number { - display: none; -} - -.center, div.center { - text-align: center; - margin-left: auto; - margin-right: auto; -} - -.center figure, -.center figcaption, -div.center figure, -div.center figcaption { - text-align: center; - margin-left: auto; - margin-right: auto; -} - -.multi-img { - display: flex; - justify-content: center; - text-align: center; - margin: 20px; - gap: 20px; -} - -.multi-img figure { margin: 0px; } - -.caption { - padding-top: 0.5rem; - font-style: italic; -} - -.outline-3, .outline-4, .outline-5 { - padding-left: 0.6rem; - border-radius: 0.2em; - margin: 0.7rem; - - #box-shadow: 1px 1px 1px var(--grey2); - #border: 1px solid var(--grey4); -} - -.outline-text-3, .outline-text-4, .outline-text-5 { - margin: 0.3rem 1rem 0.5rem 0.5rem; -} -/* -.outline-3 { - border-left: 1px inset var(--red5); -} - -.outline-4 { - border-left: 1px inset var(--purple3); -} - -.outline-5 { - border-left: 1px inset var(--blue4); -} - */ - -/* -.outline-5::after { - content: "⇜"; - display: block; - text-align: right; - margin-top: -2.0rem; -} - */ - - -.orgjq-expanded p { - margin-top: 0; -} - -/* -.outline-3.orgjq-contracted h3::before { - content: "🡒 "; -} - -.outline-4.orgjq-contracted h4::before { - content: "⤳ "; -} - -.outline-5 h5::before { - content: "⇝ "; -} - */ - -#content h2, #content h3, #content h4, #content h5 { - margin-bottom: 1rem; - margin-top: 0.5rem; - margin-left: 0.5rem; -} - -#content h3 { - padding-top: 0.5rem; - padding-bottom: 0.5rem; -} - -#content h4 { - padding-top: 0.5rem; - padding-bottom: 0.5rem; -} - -#content h5 { - padding-top: 0.3rem; - padding-bottom: 0.3rem; -} - -.orgjq-contracted h2, .orgjq-contracted h3, .orgjq-contracted h4, orgjq-contracted h5 { - padding-top: 0.3rem !important; - padding-bottom: 0.3rem !important; -} - -#content h2 { - margin-top: 1rem; -} - -.orgjq-expanded p { - padding-bottom: 1.5rem; - margin-bottom: 0; -} - -#content, #footer { - box-shadow: 7px 7px 7px var(--grey1); -} - -h2 { - line-height: 1.5rem; - text-align: center; -} - -h3, h4, h5 { - text-align: center; -} - -#table-of-contents { - display: none; -} - -.done.YES, .todo.NO, .done.EXCELLENT, .done.FREED { - display: none; -} - -h2:has(.done.YES), h3:has(.done.YES), h4:has(.done.YES), h5:has(.done.YES), .grid.YES { - color: var(--green3); -} - -h2:has(.todo.NO), h3:has(.todo.NO), h4:has(.todo.NO), h5:has(.todo.NO), .grid.NO { - color: var(--red3); -} - -h2:has(.done.EXCELLENT), h3:has(.done.EXCELLENT), h4:has(.done.EXCELLENT), h5:has(.done.EXCELLENT), .grid.EXCELLENT { - color: var(--blue3); -} - -h2:has(.done.FREED), h3:has(.done.FREED), h4:has(.done.FREED), h5:has(.done.FREED), .grid.FREED { - color: var(--purpl3); -} - -.tag { display: none; } - -.habit-cell { - text-align: center; - vertical-align: middle; - width: 20px; - height: 10px; - cursor: pointer; - user-select: none; -} - - -.habit-cell.habit-brightness-1 { color: var(--grey5); outline-color: var(--grey5) !important; } -.habit-cell.habit-brightness-2 { color: var(--grey5); outline-color: var(--grey5) !important; } -.habit-cell.habit-brightness-3 { color: var(--grey5); outline-color: var(--grey5) !important; } -.habit-cell.habit-brightness-4 { color: var(--grey2); outline-color: var(--grey5) !important; } -.habit-cell.habit-brightness-5 { color: var(--grey3); outline-color: var(--grey5) !important; } - -.habit-cell:not([data-body=""]) { - outline: dotted 2px; - outline-offset: -2px; -} -.habitgrid-selected { - outline: solid 2px var(--purple5) !important; - outline-offset: -2px; -} - -.section-number-1, .section-number-2, .section-number-3, .section-number-4 { display: none; } - -div:has(h3 .tag .journal) { - border: none; - box-shadow: none; -} - -div:has(> h3 .tag .journal)::after { - content: '~ ❦ ~'; - display: block; - text-align: center; - padding-top: 0.2rem; - padding-bottom: 0.2rem; - color: var(--grey4); - font-size: 2rem; -} - -h3:has(.tag .journal) { - text-align: left; -} - -h4:has(.tag .jentry) { - display: none; -} - -h4:has(.tag .habits) { - text-align: left; -} - -.orgjq-expanded > h4:has(.tag .habits)::before { - content: '⮟ '; -} - -.orgjq-contracted > :first-child::before { - content: '⮞ '; -} diff --git a/static/esquemadorg.js b/static/esquemadorg.js deleted file mode 100644 index 21200f8..0000000 --- a/static/esquemadorg.js +++ /dev/null @@ -1,281 +0,0 @@ -// Adapted from: -// -// esquemadorg.js -// -// m3.2010 Daniel Clemente Laboreo. http://www.danielclemente.com/ -// -// Initially based on org-info-jq from Sebastian Rose (2009): http://github.com/SebastianRose/org-info-js/blob/master/org-info-jq.js -// -// Released under the GNU General Public License version 3 -// see: http://www.gnu.org/licenses/ -// - - -var HOW_TO_HIDE = 'hide'; - -function isHideable(div_obj) { - try { - // Ignore for TOC since it is handled differently - if (div_obj.id == "text-table-of-contents") return false; - if (div_obj.id == "table-of-contents") return false; - // No point in hiding top level - if (div_obj.classList.contains("outline-2")) return false; - if (div_obj.classList.contains("outline-text-2")) return false; - } catch (e) { - console.log(div_obj) - console.log(e) - } - - return true -} - -function scrollSmoothlyToObj(obj,id) { - // This line comes from: *** Anchor Slider by Cedric Dugas *** Http://www.position-absolute.com *** Thanks! - $("html:not(:animated),body:not(:animated)").animate({ scrollTop: obj.offset().top}, 1100, function() { - window.location.hash = id; - }); -} - -function focusSection(id_anchor){ - // anchor: the id (text, without '#') of the h2/h3/h4/h5/h6/h7 which is to be made visible (together with its parents). The page will also scroll to focus that section - - var anchor1='#'+id_anchor; - var anchor2='*[id=' + id_anchor + ']'; // this is equivalent to $("#id"), which strangely seems not to work - var obj_anchor=$(anchor2); - - // Remove any other highlighted section which was the target of a previous link. - // It does nothing if it's the first click - $("div.orgjq-targeted").removeClass("orgjq-targeted"); - // Now highlight the target section and its parents. You may Use .css("background","orange") to test - obj_anchor.parents("div.orgjq-contracted").addClass("orgjq-targeted"); - // Expand its parents so that the target section is connected to the root of the tree - obj_anchor.parents("div.orgjq-contracted").each( - function() { - $(this).removeClass("orgjq-contracted").addClass("orgjq-expanded"); - $(this).children("div").show(); - } - ); - // move the browser focus to that section - scrollSmoothlyToObj(obj_anchor,anchor1); -} - - -function hideForOrg_whenclicked(div_obj) { - if (!isHideable(div_obj[0])) return; - - div_obj.parent().removeClass("orgjq-expanded").addClass("orgjq-contracted"); - if(HOW_TO_HIDE=='hide'){ - //div_obj.nextAll().hide("fast"); // "normal" es más lento - //div_obj.hide(); - } else if(HOW_TO_HIDE=='shrink'){ - //div_obj.css("zoom","0.25"); - // div_obj.nextAll().css("zoom","0.25"); - div_obj.css("font-size","50%"); - div_obj.nextAll().css("font-size","50%"); - } else if(HOW_TO_HIDE=='opacity'){ - div_obj.css("opacity","0.5"); - div_obj.nextAll().css("opacity","0.5"); - } else if(HOW_TO_HIDE=='scrollbar'){ - div_obj.parent().css({"height":"100px","overflow-y":"auto","opacity":"0.3"}); - } else { - console.error("Not impl."); - } - -} -function showForOrg_whenclicked(div_obj) { - div_obj.parent().removeClass("orgjq-contracted").addClass("orgjq-expanded"); - if(HOW_TO_HIDE=='hide'){ - div_obj.parents().show("normal"); - div_obj.nextAll().show("normal");div_obj.show(); - } else if(HOW_TO_HIDE=='shrink'){ - //div_obj.css("zoom","1"); - // div_obj.nextAll().css("zoom","1"); - div_obj.css("font-size","100%"); - div_obj.nextAll().css("font-size","100%"); - } else if(HOW_TO_HIDE=='opacity'){ - div_obj.css("opacity","1"); - div_obj.nextAll().css("opacity","1"); - } else if(HOW_TO_HIDE=='scrollbar'){ - div_obj.parents().css({"height":"auto","min-height":"100px","overflow-y":"inherit","opacity":"1"}); - } else { - console.error("Not impl."); - } -} -function toggleForOrg_whenclicked(div_obj) { - if(div_obj.parent().hasClass("orgjq-expanded")) - hideForOrg_whenclicked(div_obj); - else - showForOrg_whenclicked(div_obj); -} - -// faster methods than calling the individual methods in a loop -function close_all_sections() { - //$('.orgjq-expanded').removeClass("orgjq-expanded").addClass("orgjq-contracted"); - - for(var i=2;i<=7;++i) { - let divs = $(".outline-text-"+i) - divs.each(idx => { - if (isHideable(divs[idx])) { - $("#" + divs[idx].id).parent().removeClass("orgjs-expanded").addClass("orgjq-contracted"); - $("#" + divs[idx].id).hide() - } - }) - } - - // inside the h2 headers, all (now unseen) headers are also contracted - for(var i=2;i<=7;++i) { - $("h"+i).each( - function(){ - if (isHideable($(this).parent()[0])) { - $(this).parent().removeClass("orgjq-expanded").addClass("orgjq-contracted"); - $(this).next("div").nextAll().hide();$(this).next("div").hide(); - } - }); - } - -} -function open_all_sections() { - $('div#content .orgjq-contracted').not("#table-of-contents").removeClass("orgjq-contracted").addClass("orgjq-expanded"); - $('div#content').find(":hidden").not("#table-of-contents div").show(); -} - -function disable_global_outlining() { - // not really used anymore - - // affect only the main (first level) sections - var org= $("div#table-of-contents, div#content>div[id^='outline-container-']"); - //test: org.css({border: "2px solid red"}); - - // show everything (all sections, …) - org.find(":hidden").show(); - - // remove classes and thus colors - $(".orgjq-contracted").removeClass("orgjq-contracted"); - $(".orgjq-expanded").removeClass("orgjq-expanded"); - $(".orgjq-targeted").removeClass("orgjq-targeted"); - - // headers are not clickable - org.find("h1,h2,h3,h4,h5,h6,h7").css({cursor: "default"}).unbind("click"); - // links to sections no longer highlight the target - $("a[href^='#']").unbind('click'); - // hide expand link - $("div#outline-container-1 >h2 >a.expandAll").remove(); - - - // information - alert("He cambiado al estilo tradicional: todo seguido. Si quieres volver a usar el esquemado con cabeceras clicables, recarga la página"); -} - -function enable_global_outlining() { - // Called once e.g. the first time the page is loaded - - // handle the click event for each header - for(var i=2;i<=7;++i) { - $("h"+i).each( - function(){ - $(this).css({cursor: "pointer"}); - $(this).bind('click', function(){ toggleForOrg_whenclicked( $(this).parent().children("div").eq(0) ); }); - }); - } - - /* - // add link to deactive outlining. I wanted 2 links, „expand all“ and „contract all“, but the second one isn't of much use (and reloading the page does the same) - // otros posibles nombres: "(expandir completamente)" - var expAll_link = $( document.createElement('a') ).text("(ver todo seguido, sin esquemado)").addClass("expandAll").click(disable_global_outlining); - $( $("div.outline-2")[0] ).find(">h2") .append(expAll_link); - */ - - - /* - // start with contracted TOC and headers ← m5.2017: disabled because it has a huge penalty towards Google (hidden content won't be indexed) - - if(HOW_TO_HIDE=='hide'){ - $("#text-table-of-contents").hide(); - } else { - console.error("Not impl."); - } - for(var i=2;i<=7;++i) { - $(".outline-text-"+i).parent().addClass("orgjq-contracted"); - if(HOW_TO_HIDE=='hide'){ - ///// $(".outline-text-"+i).hide(); - $(".outline-text-"+i).hide(); - } else if(HOW_TO_HIDE=='scrollbar'){ - //$(".outline-text-"+i).css({"height":"100px","overflow-y":"auto","opacity":"0.3"}); - // $(".outline-text-"+i).parent().css({"height":"100px","overflow-y":"auto","opacity":"0.3"}); - // console.error("nada"); - } else { - console.error("Not impl."); - } - } - - // inside the h2 headers, all (now unseen) headers are also contracted - for(var i=2;i<=7;++i) { - $("h"+i).each( - function(){ - $(this).parent().removeClass("orgjq-expanded").addClass("orgjq-contracted"); - if(HOW_TO_HIDE=='hide'){ - $(this).next("div").nextAll().hide();$(this).next("div").hide(); - } else if(HOW_TO_HIDE=='scrollbar'){ - // $(this).next("div").nextAll().css({"height":"100px","overflow-y":"auto","opacity":"0.3"}); - $(this).next("div").nextAll().css({"height":"100px","overflow-y":"auto","opacity":"0.3"}); - // console.error("nada2."); - } else { - console.error("Not impl."); - } - - }); - } - */ - - // alternatively: mark everything as open - for(var i=2;i<=7;++i) { - $("h"+i).each( - function(){ - $(this).parent().removeClass("orgjq-contracted").addClass("orgjq-expanded"); - }); - } - // except TOC - $("div#table-of-contents").removeClass("orgjq-expanded").addClass("orgjq-contracted"); - - - // Hide default-hidden categories - $(".orgjq-contract-default").each( - function(){ - hideForOrg_whenclicked($(this)) - } - ); - - - // If provided #fragment in URL, we must locate and open the corresponding header and its parents - var url = document.location.toString(); - if (url.match('#')) { // the URL contains an anchor - var id_anchor = url.split('#')[1]; - focusSection(id_anchor); - } - - - // internal links to anchors, e.g. , should also expand the destination section before scrolling there - //Test: $("a[href^='#']").css("border","2px dotted red"); - $("a[href^='#']").each(function(){ - var caller=this; - $(caller).click(function (event) { - var href=$(caller).attr("href"); - var id_href=href.substr(1); - focusSection(id_href); - return false; - }); - - }); - - $(".autocollapse").each(function(){ - hideForOrg_whenclicked($(this).parent().parent()); - console.log("DSFDFS") - }) - - // the page is now ready to be used - -} - -// Code starts here - -$(document).ready(enable_global_outlining); diff --git a/static/footnote.css b/static/footnote.css deleted file mode 100644 index 6368212..0000000 --- a/static/footnote.css +++ /dev/null @@ -1,11 +0,0 @@ -.footnote-tooltip { - position: 'absolute'; - z-index: 1000; - background-color: var(--background-tooltip); - border: 1px solid var(--accent1); - border-radius: = 4px; - padding: 8px 12px; - max-width: 300px; - font-size: calc(var(--font-size) * 0.9); - box-shadow: 1px 1px 1px var(--grey2); -} diff --git a/static/footnote.js b/static/footnote.js deleted file mode 100644 index 856e8d5..0000000 --- a/static/footnote.js +++ /dev/null @@ -1,81 +0,0 @@ -document.addEventListener('DOMContentLoaded', function() { - console.log("🦶🦶🦶🦶🦶 FOOTNOTES LOADED 🦶🦶🦶🦶🦶🦶") - - const footnoteRefs = document.querySelectorAll('.footref') - - footnoteRefs.forEach(ref => { - const footnoteId = ref.href.split('#')[1] - ref.setAttribute('data-footnote-id', footnoteId) - ref.href = 'javascript:void(0)'; - - ref.addEventListener('mouseenter', function() { - // Find footnote element - const footnoteId = this.getAttribute('data-footnote-id') - - const footnoteElement = document.getElementById(footnoteId).parentElement.nextElementSibling.children[0] - - if (footnoteElement) { - // Create tooltip container - const tooltip = document.createElement('div'); - tooltip.className = 'footnote-tooltip' - tooltip.innerHTML = footnoteElement.innerHTML - - // Position tooltip - const rect = this.getBoundingClientRect(); - tooltip.style.position = 'absolute' - tooltip.style.top = (rect.bottom + window.scrollY + 5) + 'px' - tooltip.style.left = rect.left + 'px' - - // Add to page - document.body.appendChild(tooltip) - - // Store reference for cleanup - this._tooltip = tooltip - } - }); - - ref.addEventListener('mouseleave', function() { - // Remove tooltip - if (this._tooltip) { - this._tooltip.remove() - this._tooltip = null - } - }); - }); - - // Hide footnotes section - document.querySelector("#footnotes").style.display='none' -}); - -function formatDayOfYear(dayOfYear, year) { - const date = new Date(year, 0, dayOfYear); - - return date.toLocaleDateString('en-GB', { - day: 'numeric', - month: 'short', - year: 'numeric' - }); -} - -let selectedCell = null; - -function showHabitPopup(cell) { - var bodyHtml = cell.getAttribute('data-body'); - var doy = cell.getAttribute('data-doy'); - var activity = cell.getAttribute('data-activity'); - var status = cell.getAttribute('data-status'); - activity = activity.replace(/^dailies-/, '').replace(/^./, c => c.toUpperCase()) - - if (!bodyHtml) bodyHtml = "This section intentionally left blank." - - bodyHtml = `

${activity} — ${formatDayOfYear(parseInt(doy), 2025)}

${bodyHtml}` - - document.getElementById('habitPopupContent').innerHTML = bodyHtml; - - if (selectedCell) { - selectedCell.classList.remove('habitgrid-selected'); - } - - cell.classList.add('habitgrid-selected'); - selectedCell = cell; -} diff --git a/static/images/journal/2025.11-drums.jpg b/static/images/journal/2025.11-drums.jpg new file mode 100644 index 0000000..181bfbc Binary files /dev/null and b/static/images/journal/2025.11-drums.jpg differ diff --git a/static/jquery-3.6.4.slim.min.js b/static/jquery-3.6.4.slim.min.js deleted file mode 100644 index aead5d2..0000000 --- a/static/jquery-3.6.4.slim.min.js +++ /dev/null @@ -1,2 +0,0 @@ -/*! jQuery v3.6.4 -ajax,-ajax/jsonp,-ajax/load,-ajax/script,-ajax/var/location,-ajax/var/nonce,-ajax/var/rquery,-ajax/xhr,-manipulation/_evalUrl,-deprecated/ajax-event-alias,-effects,-effects/animatedSelector,-effects/Tween | (c) OpenJS Foundation and other contributors | jquery.org/license */ -!function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(g,e){"use strict";var t=[],r=Object.getPrototypeOf,s=t.slice,v=t.flat?function(e){return t.flat.call(e)}:function(e){return t.concat.apply([],e)},u=t.push,i=t.indexOf,n={},o=n.toString,y=n.hasOwnProperty,a=y.toString,l=a.call(Object),m={},b=function(e){return"function"==typeof e&&"number"!=typeof e.nodeType&&"function"!=typeof e.item},x=function(e){return null!=e&&e===e.window},w=g.document,c={type:!0,src:!0,nonce:!0,noModule:!0};function C(e,t,n){var r,i,o=(n=n||w).createElement("script");if(o.text=e,t)for(r in c)(i=t[r]||t.getAttribute&&t.getAttribute(r))&&o.setAttribute(r,i);n.head.appendChild(o).parentNode.removeChild(o)}function T(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?n[o.call(e)]||"object":typeof e}var f="3.6.4 -ajax,-ajax/jsonp,-ajax/load,-ajax/script,-ajax/var/location,-ajax/var/nonce,-ajax/var/rquery,-ajax/xhr,-manipulation/_evalUrl,-deprecated/ajax-event-alias,-effects,-effects/animatedSelector,-effects/Tween",E=function(e,t){return new E.fn.init(e,t)};function d(e){var t=!!e&&"length"in e&&e.length,n=T(e);return!b(e)&&!x(e)&&("array"===n||0===t||"number"==typeof t&&0+~]|"+R+")"+R+"*"),U=new RegExp(R+"|>"),V=new RegExp(W),X=new RegExp("^"+B+"$"),Q={ID:new RegExp("^#("+B+")"),CLASS:new RegExp("^\\.("+B+")"),TAG:new RegExp("^("+B+"|[*])"),ATTR:new RegExp("^"+M),PSEUDO:new RegExp("^"+W),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+R+"*(even|odd|(([+-]|)(\\d*)n|)"+R+"*(?:([+-]|)"+R+"*(\\d+)|))"+R+"*\\)|)","i"),bool:new RegExp("^(?:"+I+")$","i"),needsContext:new RegExp("^"+R+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+R+"*((?:-\\d)?\\d*)"+R+"*\\)|)(?=[^-]|$)","i")},Y=/HTML$/i,G=/^(?:input|select|textarea|button)$/i,K=/^h\d$/i,J=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ee=/[+~]/,te=new RegExp("\\\\[\\da-fA-F]{1,6}"+R+"?|\\\\([^\\r\\n\\f])","g"),ne=function(e,t){var n="0x"+e.slice(1)-65536;return t||(n<0?String.fromCharCode(n+65536):String.fromCharCode(n>>10|55296,1023&n|56320))},re=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ie=function(e,t){return t?"\0"===e?"\ufffd":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e},oe=function(){C()},ae=xe(function(e){return!0===e.disabled&&"fieldset"===e.nodeName.toLowerCase()},{dir:"parentNode",next:"legend"});try{O.apply(t=P.call(d.childNodes),d.childNodes),t[d.childNodes.length].nodeType}catch(e){O={apply:t.length?function(e,t){q.apply(e,P.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function se(t,e,n,r){var i,o,a,s,u,l,c,f=e&&e.ownerDocument,d=e?e.nodeType:9;if(n=n||[],"string"!=typeof t||!t||1!==d&&9!==d&&11!==d)return n;if(!r&&(C(e),e=e||T,E)){if(11!==d&&(u=Z.exec(t)))if(i=u[1]){if(9===d){if(!(a=e.getElementById(i)))return n;if(a.id===i)return n.push(a),n}else if(f&&(a=f.getElementById(i))&&y(e,a)&&a.id===i)return n.push(a),n}else{if(u[2])return O.apply(n,e.getElementsByTagName(t)),n;if((i=u[3])&&p.getElementsByClassName&&e.getElementsByClassName)return O.apply(n,e.getElementsByClassName(i)),n}if(p.qsa&&!k[t+" "]&&(!v||!v.test(t))&&(1!==d||"object"!==e.nodeName.toLowerCase())){if(c=t,f=e,1===d&&(U.test(t)||_.test(t))){(f=ee.test(t)&&ye(e.parentNode)||e)===e&&p.scope||((s=e.getAttribute("id"))?s=s.replace(re,ie):e.setAttribute("id",s=A)),o=(l=h(t)).length;while(o--)l[o]=(s?"#"+s:":scope")+" "+be(l[o]);c=l.join(",")}try{return O.apply(n,f.querySelectorAll(c)),n}catch(e){k(t,!0)}finally{s===A&&e.removeAttribute("id")}}}return g(t.replace($,"$1"),e,n,r)}function ue(){var r=[];return function e(t,n){return r.push(t+" ")>x.cacheLength&&delete e[r.shift()],e[t+" "]=n}}function le(e){return e[A]=!0,e}function ce(e){var t=T.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function fe(e,t){var n=e.split("|"),r=n.length;while(r--)x.attrHandle[n[r]]=t}function de(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function pe(t){return function(e){return"input"===e.nodeName.toLowerCase()&&e.type===t}}function he(n){return function(e){var t=e.nodeName.toLowerCase();return("input"===t||"button"===t)&&e.type===n}}function ge(t){return function(e){return"form"in e?e.parentNode&&!1===e.disabled?"label"in e?"label"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&ae(e)===t:e.disabled===t:"label"in e&&e.disabled===t}}function ve(a){return le(function(o){return o=+o,le(function(e,t){var n,r=a([],e.length,o),i=r.length;while(i--)e[n=r[i]]&&(e[n]=!(t[n]=e[n]))})})}function ye(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}for(e in p=se.support={},i=se.isXML=function(e){var t=e&&e.namespaceURI,n=e&&(e.ownerDocument||e).documentElement;return!Y.test(t||n&&n.nodeName||"HTML")},C=se.setDocument=function(e){var t,n,r=e?e.ownerDocument||e:d;return r!=T&&9===r.nodeType&&r.documentElement&&(a=(T=r).documentElement,E=!i(T),d!=T&&(n=T.defaultView)&&n.top!==n&&(n.addEventListener?n.addEventListener("unload",oe,!1):n.attachEvent&&n.attachEvent("onunload",oe)),p.scope=ce(function(e){return a.appendChild(e).appendChild(T.createElement("div")),"undefined"!=typeof e.querySelectorAll&&!e.querySelectorAll(":scope fieldset div").length}),p.cssHas=ce(function(){try{return T.querySelector(":has(*,:jqfake)"),!1}catch(e){return!0}}),p.attributes=ce(function(e){return e.className="i",!e.getAttribute("className")}),p.getElementsByTagName=ce(function(e){return e.appendChild(T.createComment("")),!e.getElementsByTagName("*").length}),p.getElementsByClassName=J.test(T.getElementsByClassName),p.getById=ce(function(e){return a.appendChild(e).id=A,!T.getElementsByName||!T.getElementsByName(A).length}),p.getById?(x.filter.ID=function(e){var t=e.replace(te,ne);return function(e){return e.getAttribute("id")===t}},x.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n=t.getElementById(e);return n?[n]:[]}}):(x.filter.ID=function(e){var n=e.replace(te,ne);return function(e){var t="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return t&&t.value===n}},x.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),x.find.TAG=p.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):p.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},x.find.CLASS=p.getElementsByClassName&&function(e,t){if("undefined"!=typeof t.getElementsByClassName&&E)return t.getElementsByClassName(e)},s=[],v=[],(p.qsa=J.test(T.querySelectorAll))&&(ce(function(e){var t;a.appendChild(e).innerHTML="
",e.querySelectorAll("[msallowcapture^='']").length&&v.push("[*^$]="+R+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||v.push("\\["+R+"*(?:value|"+I+")"),e.querySelectorAll("[id~="+A+"-]").length||v.push("~="),(t=T.createElement("input")).setAttribute("name",""),e.appendChild(t),e.querySelectorAll("[name='']").length||v.push("\\["+R+"*name"+R+"*="+R+"*(?:''|\"\")"),e.querySelectorAll(":checked").length||v.push(":checked"),e.querySelectorAll("a#"+A+"+*").length||v.push(".#.+[+~]"),e.querySelectorAll("\\\f"),v.push("[\\r\\n\\f]")}),ce(function(e){e.innerHTML="";var t=T.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&v.push("name"+R+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&v.push(":enabled",":disabled"),a.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&v.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),v.push(",.*:")})),(p.matchesSelector=J.test(c=a.matches||a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.msMatchesSelector))&&ce(function(e){p.disconnectedMatch=c.call(e,"*"),c.call(e,"[s!='']:x"),s.push("!=",W)}),p.cssHas||v.push(":has"),v=v.length&&new RegExp(v.join("|")),s=s.length&&new RegExp(s.join("|")),t=J.test(a.compareDocumentPosition),y=t||J.test(a.contains)?function(e,t){var n=9===e.nodeType&&e.documentElement||e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},D=t?function(e,t){if(e===t)return l=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)==(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!p.sortDetached&&t.compareDocumentPosition(e)===n?e==T||e.ownerDocument==d&&y(d,e)?-1:t==T||t.ownerDocument==d&&y(d,t)?1:u?H(u,e)-H(u,t):0:4&n?-1:1)}:function(e,t){if(e===t)return l=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,a=[e],s=[t];if(!i||!o)return e==T?-1:t==T?1:i?-1:o?1:u?H(u,e)-H(u,t):0;if(i===o)return de(e,t);n=e;while(n=n.parentNode)a.unshift(n);n=t;while(n=n.parentNode)s.unshift(n);while(a[r]===s[r])r++;return r?de(a[r],s[r]):a[r]==d?-1:s[r]==d?1:0}),T},se.matches=function(e,t){return se(e,null,null,t)},se.matchesSelector=function(e,t){if(C(e),p.matchesSelector&&E&&!k[t+" "]&&(!s||!s.test(t))&&(!v||!v.test(t)))try{var n=c.call(e,t);if(n||p.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){k(t,!0)}return 0":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(te,ne),e[3]=(e[3]||e[4]||e[5]||"").replace(te,ne),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||se.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&se.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return Q.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&V.test(n)&&(t=h(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(te,ne).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=m[e+" "];return t||(t=new RegExp("(^|"+R+")"+e+"("+R+"|$)"))&&m(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(n,r,i){return function(e){var t=se.attr(e,n);return null==t?"!="===r:!r||(t+="","="===r?t===i:"!="===r?t!==i:"^="===r?i&&0===t.indexOf(i):"*="===r?i&&-1:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function D(e,n,r){return b(n)?E.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?E.grep(e,function(e){return e===n!==r}):"string"!=typeof n?E.grep(e,function(e){return-1)[^>]*|#([\w-]+))$/;(E.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||L,"string"==typeof e){if(!(r="<"===e[0]&&">"===e[e.length-1]&&3<=e.length?[null,e,null]:j.exec(e))||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof E?t[0]:t,E.merge(this,E.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:w,!0)),k.test(r[1])&&E.isPlainObject(t))for(r in t)b(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(i=w.getElementById(r[2]))&&(this[0]=i,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):b(e)?void 0!==n.ready?n.ready(e):e(E):E.makeArray(e,this)}).prototype=E.fn,L=E(w);var q=/^(?:parents|prev(?:Until|All))/,O={children:!0,contents:!0,next:!0,prev:!0};function P(e,t){while((e=e[t])&&1!==e.nodeType);return e}E.fn.extend({has:function(e){var t=E(e,this),n=t.length;return this.filter(function(){for(var e=0;e\x20\t\r\n\f]*)/i,pe=/^$|^module$|\/(?:java|ecma)script/i;le=w.createDocumentFragment().appendChild(w.createElement("div")),(ce=w.createElement("input")).setAttribute("type","radio"),ce.setAttribute("checked","checked"),ce.setAttribute("name","t"),le.appendChild(ce),m.checkClone=le.cloneNode(!0).cloneNode(!0).lastChild.checked,le.innerHTML="",m.noCloneChecked=!!le.cloneNode(!0).lastChild.defaultValue,le.innerHTML="",m.option=!!le.lastChild;var he={thead:[1,"","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};function ge(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&S(e,t)?E.merge([e],n):n}function ve(e,t){for(var n=0,r=e.length;n",""]);var ye=/<|&#?\w+;/;function me(e,t,n,r,i){for(var o,a,s,u,l,c,f=t.createDocumentFragment(),d=[],p=0,h=e.length;p\s*$/g;function ke(e,t){return S(e,"table")&&S(11!==t.nodeType?t:t.firstChild,"tr")&&E(e).children("tbody")[0]||e}function De(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function Le(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function je(e,t){var n,r,i,o,a,s;if(1===t.nodeType){if(Y.hasData(e)&&(s=Y.get(e).events))for(i in Y.remove(t,"handle events"),s)for(n=0,r=s[i].length;n
",2===ft.childNodes.length),E.parseHTML=function(e,t,n){return"string"!=typeof e?[]:("boolean"==typeof t&&(n=t,t=!1),t||(m.createHTMLDocument?((r=(t=w.implementation.createHTMLDocument("")).createElement("base")).href=w.location.href,t.head.appendChild(r)):t=w),o=!n&&[],(i=k.exec(e))?[t.createElement(i[1])]:(i=me([e],t,o),o&&o.length&&E(o).remove(),E.merge([],i.childNodes)));var r,i,o},E.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l=E.css(e,"position"),c=E(e),f={};"static"===l&&(e.style.position="relative"),s=c.offset(),o=E.css(e,"top"),u=E.css(e,"left"),("absolute"===l||"fixed"===l)&&-1<(o+u).indexOf("auto")?(a=(r=c.position()).top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),b(t)&&(t=t.call(e,n,E.extend({},s))),null!=t.top&&(f.top=t.top-s.top+a),null!=t.left&&(f.left=t.left-s.left+i),"using"in t?t.using.call(e,f):c.css(f)}},E.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){E.offset.setOffset(this,t,e)});var e,n,r=this[0];return r?r.getClientRects().length?(e=r.getBoundingClientRect(),n=r.ownerDocument.defaultView,{top:e.top+n.pageYOffset,left:e.left+n.pageXOffset}):{top:0,left:0}:void 0},position:function(){if(this[0]){var e,t,n,r=this[0],i={top:0,left:0};if("fixed"===E.css(r,"position"))t=r.getBoundingClientRect();else{t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;while(e&&(e===n.body||e===n.documentElement)&&"static"===E.css(e,"position"))e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=E(e).offset()).top+=E.css(e,"borderTopWidth",!0),i.left+=E.css(e,"borderLeftWidth",!0))}return{top:t.top-i.top-E.css(r,"marginTop",!0),left:t.left-i.left-E.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent;while(e&&"static"===E.css(e,"position"))e=e.offsetParent;return e||re})}}),E.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(t,i){var o="pageYOffset"===i;E.fn[t]=function(e){return $(this,function(e,t,n){var r;if(x(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n)return r?r[i]:e[t];r?r.scrollTo(o?r.pageXOffset:n,o?n:r.pageYOffset):e[t]=n},t,e,arguments.length)}}),E.each(["top","left"],function(e,n){E.cssHooks[n]=$e(m.pixelPosition,function(e,t){if(t)return t=Fe(e,n),Pe.test(t)?E(e).position()[n]+"px":t})}),E.each({Height:"height",Width:"width"},function(a,s){E.each({padding:"inner"+a,content:s,"":"outer"+a},function(r,o){E.fn[o]=function(e,t){var n=arguments.length&&(r||"boolean"!=typeof e),i=r||(!0===e||!0===t?"margin":"border");return $(this,function(e,t,n){var r;return x(e)?0===o.indexOf("outer")?e["inner"+a]:e.document.documentElement["client"+a]:9===e.nodeType?(r=e.documentElement,Math.max(e.body["scroll"+a],r["scroll"+a],e.body["offset"+a],r["offset"+a],r["client"+a])):void 0===n?E.css(e,t,i):E.style(e,t,n,i)},s,n?e:void 0,n)}})}),E.fn.extend({bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)},hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}}),E.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,n){E.fn[n]=function(e,t){return 0 - - - + - - - diff --git a/util/postamble.html b/util/postamble.html index 8171a36..474ba4d 100644 --- a/util/postamble.html +++ b/util/postamble.html @@ -4,4 +4,4 @@ If you have any comments about this page, you can email me at:
Proudly built using org-mode.
All code on this website is licensed GPLv3 unless otherwise indicated.

-[Valid RSS]
+[Valid RSS]