Compare commits
47 Commits
Author | SHA1 | Date |
---|---|---|
yequari | 22764b7276 | |
yequari | 5528ea7e2d | |
yequari | f26b00da35 | |
yequari | 68177b871a | |
yequari | 63adc1d843 | |
yequari | 89d9a825e4 | |
yequari | a26b816e28 | |
yequari | ef773f34f3 | |
yequari | 05e90297c7 | |
yequari | d7077c187d | |
yequari | ec87e4ab7d | |
yequari | 817b436d97 | |
yequari | b16340d390 | |
yequari | fc6b91d142 | |
yequari | 70b818d95b | |
yequari | 2901a05633 | |
yequari | f8eeb0f218 | |
yequari | 5eef7f70e4 | |
yequari | 87a106d0db | |
yequari | ed7d9e997b | |
yequari | ca61bc4409 | |
yequari | a04e051187 | |
yequari | 6caf33024d | |
yequari | b584bdfce8 | |
yequari | aab9a63c5d | |
yequari | 903fc49fd6 | |
yequari | c1e92e0a7d | |
yequari | 0b482c3c61 | |
yequari | 6eb86ef064 | |
yequari | 78887ab15e | |
yequari | fc3049a56f | |
yequari | a4500393d4 | |
yequari | 8780e7fd79 | |
yequari | 3c78e4a1f0 | |
yequari | 346b7599ee | |
yequari | 02ab34f4fc | |
yequari | 415e5af441 | |
yequari | 9456849d2c | |
yequari | 7aab161136 | |
yequari | bb021ab88c | |
yequari | 9b337ea6f9 | |
yequari | d6899677d1 | |
yequari | 90c04ab544 | |
yequari | f441717d5f | |
yequari | 64660aa631 | |
yequari | 462710757c | |
yequari | cff78b723d |
28
config.yaml
|
@ -2,8 +2,11 @@ baseURL: http://yequari.com/
|
|||
languageCode: en-us
|
||||
title: yequari.com
|
||||
theme: dreamcast
|
||||
enableGitInfo: true
|
||||
params:
|
||||
about: "I write code and occasionally blog posts."
|
||||
# about: "I write code and occasionally blog posts."
|
||||
webmentions: https://webmention.io/yequari.com/webmention
|
||||
pingbacks: https://webmention.io/yequari.com/xmlrpc
|
||||
taxonomies:
|
||||
category: categories
|
||||
tag: tags
|
||||
|
@ -24,30 +27,43 @@ menu:
|
|||
- name: Projects
|
||||
pageRef: /projects
|
||||
weight: 30
|
||||
- name: Notes
|
||||
pageRef: /notes
|
||||
weight: 40
|
||||
- name: Now
|
||||
pageRef: /now
|
||||
weight: 40
|
||||
weight: 50
|
||||
- name: Links
|
||||
pageRef: /links
|
||||
weight: 50
|
||||
weight: 60
|
||||
social:
|
||||
- name: yequari@retro.pizza
|
||||
- name: Mastodon
|
||||
params:
|
||||
rel: external
|
||||
icon: aero-mastodon.svg
|
||||
class: masto
|
||||
url: https://retro.pizza/@yequari
|
||||
weight: 10
|
||||
- name: rss feed
|
||||
- name: RSS
|
||||
params:
|
||||
icon: aero-rss.svg
|
||||
class: rss
|
||||
url: /blog/index.xml
|
||||
weight: 5
|
||||
- name: yequari@32bit.cafe
|
||||
- name: Email
|
||||
params:
|
||||
icon: aero-email-2.svg
|
||||
rel: external
|
||||
class: email
|
||||
url: mailto:yequari@32bit.cafe
|
||||
weight: 30
|
||||
- name: XMPP
|
||||
params:
|
||||
rel: external
|
||||
icon: aero-chat.svg
|
||||
url: xmpp:yequari@omg.lol
|
||||
weight: 40
|
||||
caches:
|
||||
getresource:
|
||||
dir: :cacheDir/:project
|
||||
maxAge: 0
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
---
|
||||
title: yequari.com
|
||||
---
|
||||
# hello
|
||||
|
||||
I'm yequari, welcome to my homepage! I am a software developer, interested in the small web and systems programming. My hobbies include games of all kinds, coding, and collecting Transformers figures. On this site I write about the web, programming, games, and random thoughts I have.
|
||||
# Hello
|
||||
|
||||
Welcome to my homepage! I program and tinker with computers. This site is a collection of notes, ramblings, things I like, and more. My hobbies include video games, TTRPGs, and collecting Transformers figures.
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
---
|
||||
title: "Building a Website is a Marathon, Not a Sprint"
|
||||
date: 2024-05-06T16:58:43-07:00
|
||||
year: "2024"
|
||||
categories:
|
||||
- Internet
|
||||
tags:
|
||||
- WeblogPoMo2024
|
||||
---
|
||||
|
||||
When I first created my website just over two years ago, I spent a lot of time fretting over what exactly to put on it. The common answer of "anything you want!" wasn't helpful because I didn't actually know what I wanted.
|
||||
|
||||
Spending time browsing others' personal sites and chatting with their webmasters gave me inspiration for new pages to build and new topics to blog about. After two years, I am learning what I want to put on my website. I enjoy blogging and sharing the things that I know and the things that I like. As a result, I've published more blog posts, created my links page, my /now page, and just yesterday, published a bunch of notes I've taken as I learn more about computers and web development. Coming soon will be a page to share music I've discovered recently.
|
||||
|
||||
It took me a long time to get here, and that's okay. Personal websites are about expressing yourself, sometimes it takes times to figure out who you are and what you value, and even longer to properly express that. It is a long journey with no end goal, an infinite path with innumerable unforeseen turns. As I grow, my website grows alongside me.
|
|
@ -0,0 +1,11 @@
|
|||
---
|
||||
title: "Busy Weekend"
|
||||
date: 2024-05-05T19:17:55-07:00
|
||||
year: "2024"
|
||||
categories:
|
||||
- Life
|
||||
tags:
|
||||
- WeblogPoMo2024
|
||||
---
|
||||
|
||||
Though I didn't have any big plans this weekend, I kept myself busy around the house. I mailed some packages, did the grocery shopping, prepared some meals for the week, rearranged my kitchen, cleared out some expired food, and cleaned up my desk. It feels very good to be this productive.
|
|
@ -0,0 +1,11 @@
|
|||
---
|
||||
title: "Clearing My Game Backlog"
|
||||
date: 2024-05-02T07:54:51-07:00
|
||||
year: "2024"
|
||||
categories:
|
||||
- Gaming
|
||||
tags:
|
||||
- WeblogPoMo2024
|
||||
---
|
||||
|
||||
I love video games. Or, at least, I think I do. I don't finish very many of them. I either play them for a few hours and forget to come back or I hyperfocus and get like 75% through the story but lose interest before getting to the end. This summer, I'd like to make progress on my backlog of unplayed games. I'll start with Baldur's Gate 3 and Cyberpunk 2077. These both fall into the 75% category and I last played them recently enough that I won't be completely lost with what's going on in the story. After that I'll dig into some indie games, stuff like Hades, Hyper Light Drifter, Hotline Miami 1 + 2, because they are shorter to complete and do a lot of interesting things. Then I get back into AAA games and beat one beginning to end, just to prove to myself that I can. I'm thinking one of Persona 5 Royal, Spider-Man, Ghost of Tsushima or Final Fantasy VII Remake. A challenge I face with this goal is that a lot of first-person and third-person games trigger my motion sickness, so I can only really play for an hour at a time until a build up a tolerance to them (which I lose if I don't play for a few days). Usually I stick to top-down games like strategy and simulation games to get around this, but I *really* want to play these games, so I will try my best to persevere.
|
|
@ -0,0 +1,41 @@
|
|||
---
|
||||
title: "Customizing Vim"
|
||||
date: 2024-05-07T16:22:42-07:00
|
||||
year: "2024"
|
||||
categories:
|
||||
- Tech
|
||||
tags:
|
||||
- WeblogPoMo2024
|
||||
---
|
||||
I've been using vim (specifically neovim) for over a year, I really enjoy how customizable it is, though up until today, I've only customized it through plugins made by other people. Today I wrote two Lua functions to streamline my workflow. I'm not very familiar with Lua but it was quite easy to pick up.
|
||||
|
||||
First is a function to split my window so it would have two side by side, and a smaller one at the bottom, which gets turned into a terminal.
|
||||
|
||||
```lua
|
||||
local createcodeenv = function ()
|
||||
vim.cmd('split')
|
||||
vim.cmd('wincmd j')
|
||||
local win = vim.api.nvim_get_current_win()
|
||||
local height = vim.api.nvim_win_get_height(win)
|
||||
vim.api.nvim_win_set_height(win, height - 15)
|
||||
vim.cmd('term')
|
||||
vim.cmd('wincmd k')
|
||||
vim.cmd('vsplit')
|
||||
win = vim.api.nvim_get_current_win()
|
||||
local buf = vim.api.nvim_get_current_buf()
|
||||
vim.api.nvim_win_set_buf(win, buf)
|
||||
end
|
||||
vim.api.nvim_create_user_command('CodeEnv', createcodeenv, {})
|
||||
```
|
||||
|
||||
Second is a function to bind writing a file and returning to Netrw (the file explorer) to one command, :We.
|
||||
|
||||
```lua
|
||||
local writeGoToNetrw = function()
|
||||
vim.cmd('w')
|
||||
vim.cmd('Ex')
|
||||
end
|
||||
vim.api.nvim_create_user_command('We', writeGoToNetrw, {})
|
||||
```
|
||||
|
||||
Both of these were things I did manually basically every time I used vim. Defining custom commands to make them easier was a fun learning experience, I look forward to learning more about customizing vim.
|
|
@ -0,0 +1,22 @@
|
|||
---
|
||||
title: "Dedicated Instant Messaging was Better"
|
||||
date: 2024-04-23T18:00:35-07:00
|
||||
year: "2024"
|
||||
reply_to:
|
||||
url: https://flamedfury.com/posts/instant-messaging/
|
||||
author: flamedfury
|
||||
title: Instant Messaging
|
||||
subtitle: This didn't start out as a rant about Discord, but it sure ended that way.
|
||||
categories:
|
||||
- Internet
|
||||
tags:
|
||||
- social media
|
||||
---
|
||||
|
||||
fLaMEd's post about instant messaging programs got me thinking about my own IM journey. I'm too young to really have experienced the peak AIM and MSN days, but I did use MSN/Windows Live Messenger in the late 00s to keep up with some online friends I had met through various forums. Eventually, I moved to Skype as that is what all my IRL friends were on at the time. I was also on Curse Voice for the brief time it existed, mostly for voice calls during League of Legends matches. As Skype started dying out, I moved over to Discord in 2016, which made me a pretty early adopter.
|
||||
|
||||
I really miss the simplicity of dedicated IM services. While Discord *is* a messaging platform, it feels more like a social network. DMs feel like a secondary feature on Discord, and I absolutely dread receiving them. I don't like that anyone, in any server we share, can DM me simply because we both exist in the same space. Or that anyone in any server we share can see what I'm up to with rich presence. I understand this is configurable, and that there have been improvements like separating DMs from strangers into "Message Requests", but my options are basically to allow everyone to message me and view my activity, or to allow no one, neither of which are what I want. On top of all this, each Discord update just makes the service worse to use as the company scrambles to find ways to monetize the platform.
|
||||
|
||||
So I'm giving XMPP a try again. I've used it on and off over the past 5 years or so, and it never really stuck, since I didn't really have anyone on there to chat with. But now that I've been spending time in the indie web community, I'm finding it more useful and more fun. I spent some time setting up [ejabberd](https://www.ejabberd.im/index.html) on a VPS so that I could use one of my really dumb vanity domains for my handle. It was a pain but I got there eventually. What is appealing to me about XMPP is that 1) I get to vet the people who want to DM me, before they have messaged me, 2) Because it is separate from Discord, if I don't feel up to chatting 1-on-1, I can just close my client, and not completely close myself off from my Discord servers, and 3) Conversations are more intentional: since XMPP is purely a chat protocol, the people that use it are there to chat with others, and there are few scammers, spambots, etc.
|
||||
|
||||
I'm looking forward to getting more acquainted with the protocol and chatting with some new people on there! If you want to chat on XMPP, feel free to add me via the link in the sidebar!
|
|
@ -0,0 +1,11 @@
|
|||
---
|
||||
title: "Doing New Things Is Scary"
|
||||
date: 2024-05-03T17:40:04-07:00
|
||||
year: "2024"
|
||||
categories:
|
||||
- Life
|
||||
tags:
|
||||
- WeblogPoMo2024
|
||||
---
|
||||
|
||||
I've been looking at gigs on Upwork to try and bring in some extra cash and bolster my experience. Some of these jobs seem braindead easy but I'm still so afraid to apply for them. Logically, I know that if something goes wrong nothing bad really happens, but the fact that something *could* go wrong terrifies me. I guess I just don't want to disappoint people. My browser currently has a half-filled out proposal for a job. It would take me a couple hours to complete. I just need to submit it.
|
|
@ -0,0 +1,35 @@
|
|||
---
|
||||
title: "Happy (Belated) JS Naked Day"
|
||||
date: 2024-04-26T17:12:11-07:00
|
||||
year: "2024"
|
||||
subtitle: Woah three blog posts in a week(ish) is unheard of
|
||||
categories:
|
||||
- Internet
|
||||
tags:
|
||||
- smallweb
|
||||
- web development
|
||||
---
|
||||
|
||||
[JS Naked Day](https://js-naked-day.org/) happened this week, and as usual, I'm fashionably late. I decided to permanently remove a significant portion of the JavaScript from my site as it was affecting load times. There wasn't a whole lot of JavaScript to begin with, which made this pretty easy to implement. What I did have was the following:
|
||||
|
||||
## 1. A script to randomly select from an array of quotes to display in the sidebar on each page load
|
||||
|
||||
I just removed this as I just wasn't finding it amusing anymore. Maybe it will return later, who knows? Certainly not me.
|
||||
|
||||
## 2. A script to change the avatar frame color in the sidebar
|
||||
|
||||
I had originally implemented this using Hugo's templates, as I described in my post [Recreating the Windows Live Messenger Avatar in CSS](/blog/2024/02/windows-live-avatar-css), but opted for JavaScript instead because I wouldn't need to constantly rebuild my site. I had said rebuilding periodically was a waste of compute time, which was kind of bullshit because instead I was wasting the compute time of every visitor on every page load. So now I've gone back to the template approach, and build my website periodically every hour, unless I push out an update before then. Previously this was done with a bash script, but I rewrote it in python to separate the build step from the updating from git step so that I could do each at different intervals.
|
||||
|
||||
## 3. Status.cafe widget
|
||||
|
||||
I love status.cafe, it's a really easy way to get some dynamic content on your static website. The downside of this is that every page load is hitting m15o's servers twice: first to grab the linked JavaScript file and then to run it and grab a second json file with the actual status information. This took about 1.1s to complete from beginning to end, again, *on every page load*. To speed things up, I hacked together a partial template in Hugo that downloads the json file directly on build, using Hugo's [resources.GetRemote](https://gohugo.io/functions/resources/getremote/) function.
|
||||
|
||||
## 4. Webmentions.js
|
||||
|
||||
Webmentions.js is just a way to display webmentions that you've received. Which is pretty handy, except I receive almost zero webmentions. The ones I do receive often come from Mastodon via [Brid.gy](https://brid.gy/), which I've come to realize is [problematic from a privacy standpoint](https://brainbaking.com/post/2023/05/why-i-retired-my-webmention-server/). I'm going to remove my webmention support for a lot of the reasons listed in this post, which mirrors my experience with them. The places I get reactions to the stuff I write on my website are the places where I go and manually post links, usually Mastodon and the [32bit cafe](https://discourse.32bit.cafe), and it's just easier to reply to people on there. There's no real reason to syndicate those replies on my site. If I really care about adding webmention support again, I can probably find a way to do it during the website build rather than live via JavaScript.
|
||||
|
||||
## 5. tinylytics
|
||||
|
||||
This is the only JavaScript file I'm keeping. I really like the simplicity of tinylytics. I get to see what pages are most popular and an overall viewcount, and it's not at all intrusive. It loads behind the scenes on each page so it does not affect load times, and if you were to block JavaScript it does not lessen the user experience at all.
|
||||
|
||||
I'm not opposed to using JavaScript, but the cool stuff I was doing with it could be just as easily done with my static site generator. JavaScript may make a return to my website if I find something else cool to do with it, but for now I will just enjoy the super fast load times!
|
|
@ -0,0 +1,9 @@
|
|||
---
|
||||
title: "Here We Are Again"
|
||||
date: 2024-11-06T17:59:53-07:00
|
||||
year: "2024"
|
||||
categories:
|
||||
- politics
|
||||
---
|
||||
|
||||
The results of last night's election are disappointing, angering, and horrifying. But they are not shocking. I've seen lots of talk about how stupid and racist and sexist the general American populace is to be able to vote the way the did. I don't think that is accurate. Of course, there is no doubt which candidate the racists and sexists voted for. However, in a society where we all feel forced to choose the lesser of two evils, I can't be surprised that many felt differently than me as to which candidate that actually was. The federal government has failed working people over and over for decades and continues to do so to this day. In this situation, when one party tells you everything is going great, actually, but the other tells you you are right to be upset and presents a simple solution, no matter how ill-informed or hateful it is, this is the natural result. The Democratic party will not learn this lesson, though, just like they didn't in 2016. We must take care of each other now, because no one will do it for us, especially not another establishment politician with a D next to their name.
|
|
@ -0,0 +1,12 @@
|
|||
---
|
||||
title: "Intentional Computing"
|
||||
date: 2024-09-10T21:48:07-07:00
|
||||
---
|
||||
|
||||
I've been using Arch Linux (btw) since the beginning of this year. It is a barebones distro, meaning you have to install every package you are going to use yourself. While not the most fun exercise in the world, it made me think about what software I need to make my computer usable. Beyond the necessary stuff like wi-fi drivers, I was forced to choose what I wanted my computing experience to be like. Rather than being given a default desktop environment and a suite of software I could opt-out of if I cared to, I instead had to deliberately opt-in to the desktop experience, text editor, and web browser.
|
||||
|
||||
It is certainly less convenient to do things this way. However, I'm coming to believe in the importance of [ritual and inconvenience in life](https://discourse.32bit.cafe/t/the-importance-of-inconvenience/1250/14). While I truly do understand the desire to follow the path of least resistance to get to a result (I am a programmer, after all), following that path for everything robs you of the experience of the journey. Doing things the hard way opens up your mind to different perspectives, takes you down paths that would otherwise go unexplored, and presents new opportunities for discovery. Setting up a usable Arch installation from scratch lets me take a moment to appreciate the immense amount of software that has built up the computing features I take for granted. Manually managing my music library and copying a selection of files to an mp3 player lets me think about what I love about certain songs, albums, and artists and how my tastes have changed over the years.
|
||||
|
||||
Tech is becoming increasingly focused on pushing us to passively consume content, whether on social media or one of a million streaming service, and making it harder to do anything else. We have incredibly powerful computers in our pockets, but the path of least resistance is to use them to check Twitter/Bluesky/Mastodon, because every other path is made to be difficult. [Using your phone to write totally sucks](https://jenson.org/text/), using it to draw requires a stylus and a lot of patience. Programming on it is totally impractical, and even if you do get around the barriers, good luck running any code on the device itself. It is more difficult to use your phone to write notes and doodle than a simple notepad, despite outclassing it by several orders of magnitude in both cost and compute power. The duopoly of phone operating systems means this is unlikely to change, unless mobile Linux somehow becomes usable during my lifetime.
|
||||
|
||||
All this is to say that computers are powerful tools that empower us to learn and be creative and build skills, and I aim to be more intentional in using my computer in this way. Sometimes my intention *is* entertainment, of course, but I want to choose that to be the case, instead of it being pushed on me by the software my computer runs.
|
|
@ -0,0 +1,11 @@
|
|||
---
|
||||
title: "Intermittent Fasting"
|
||||
date: 2024-05-01T07:23:19-07:00
|
||||
year: "2024"
|
||||
categories:
|
||||
- life
|
||||
tags:
|
||||
- WeblogPoMo2024
|
||||
---
|
||||
|
||||
I've started doing intermittent fasting to help achieve my [fitness goals](/fitness). It's only been a week so far but I'm liking how it's making me be more intentional about my eating habits. My eating hours are from 11am to 7pm, so I basically get two full meals and some snacks. I thought the hard part would be waiting until 11am to eat, but it's actually pretty easy (probably all the coffee helping there), then when I do eat breakfast I can put more thought into it than when I'm half awake. What is actually hard is not being able to eat after 7pm. I eat dinner around 6 but by 9:30 or so I'm starting to get hungry again. Maybe the solution to this is just going to bed earlier. I imagine it will get easier as my body gets used to the new schedule and I figure out exactly how much I need to eat in those 8 hours.
|
|
@ -0,0 +1,20 @@
|
|||
---
|
||||
title: "Music Discovery Is Weird"
|
||||
date: 2024-04-19T23:01:49-07:00
|
||||
year: "2024"
|
||||
subtitle: "Algorithms suck, except when they don't"
|
||||
categories:
|
||||
- Life
|
||||
tags:
|
||||
- music
|
||||
---
|
||||
|
||||
As a teenager, the music I listened to was music my dad shared with me, music my friends would play when we would hang out, or music from video games and movies I liked. I remember spending time on Pandora creating stations based off my favorites in hopes I could find something similar I liked. I would discover a few songs this way but otherwise didn't have much luck. As a result, I find I just listen to the same stuff over and over again, but there is so much music out there, I want to find more! But how?
|
||||
|
||||
I'm going to sound like such a zoomer here, but how did people discover music in the past? As I understand it, you would hear new songs (and albums! imagine!) on the radio and this would be the primary way of music discovery. You would also check out albums that were curated by a local record store. Tower Records was everywhere, apparently. This is so hard for me to wrap my head around. Radio is and has always been useless to me, it is a constant stream of ads broken up by either a classic rock song or a top 40 pop song here and there. Independent stations are good but are few and far between. Record stores are niche, targeted at vinyl and CD collectors, instead of targeting the general public like they did in the past. Not to mention physical media is expensive, so it's a risk to just buy an album you think looks cool without hearing it first. For this reason I do think music streaming is convenient, but from what I hear from the older generations, buying a random record and going home to listen to it without any idea of what is on it was an experience™.
|
||||
|
||||
These days, for music of which I haven't obtained mp3s through definitely legal means, I use Spotify and YouTube. Spotify's radio feature is total garbage. I have found some music I liked through it, but it frequently cycles through the same tracks. Its like each song is strictly categorized into one extremely narrow microgenre, then when you listen to radio based on that song, it will play *only* other songs from that extremely narrow microgenre. Maybe other people have more success with it and I just listen to stuff that Spotify categorizes as niche, but you'd think with how much music exists it could still do better than the same 25 songs every time. There are also recommendations on the home page but it's usually things like "here's a new album from a band you listen to" or "listen to these artists you listen to all the time" or "here's something popular but completely irrelevant to your tastes"
|
||||
|
||||
YouTube's algorithm is actually what I've had the most success with for music discovery. First, there are a million YouTube channels that are dedicated to albums of specific genres and subgenres from artists that aren't particularly well known. For example, recently I've been listening to albums on [666MrDoom](https://www.youtube.com/@666MrDoom) and [Rob Hammer](https://www.youtube.com/@Rob.DOOM.Hammer). I've found channels like these to be great resources for finding new music, and the more I listen to them, the more I get recommendations for other similar albums. I also get more random recommendations on my homepage, usually J-pop/City Pop or various "internet genres" like vaporwave or modern breakcore. Overall, YouTube has recommended me the most variety of albums and genres, it seems to remember that I like a wide variety of music, rather than focusing solely on my most recent fixation, as Spotify tends to do.
|
||||
|
||||
Of course, there are other ways to discover music, Reddit has a million music subreddits, music forums and blogs are still around, YouTubers/content creators give recommendations, not to mention the classic, word of mouth. They are all more effective than algorithms, but introduce a intermediate step between wanting to listen to something new and putting your headphones on and listening. It's easy to get lost in this step, through choice paralysis, or by diving too deep into rabbit holes, and that is what makes algorithms attractive: they just play something.
|
|
@ -0,0 +1,13 @@
|
|||
---
|
||||
title: "No More Firefox"
|
||||
date: 2024-09-19T13:03:43-07:00
|
||||
year: "2024"
|
||||
---
|
||||
|
||||
Mozilla is seemingly allergic to making good decisions, as shown by two recent (anti-)features it has brought to Firefox. First, is an AccuWeather widget on the new tab screen, enabled by default. On the surface, this seems mundane, but in order for this to work, Firefox is sending your "approximate" location to AccuWeather servers periodically in the background, [even if you disable the widget](https://digipres.club/@ryanfb/113125332270103817). This is the browser that tries to market itself as the go-to browser for privacy control.
|
||||
|
||||
![](mozilla_homepage.png)
|
||||
|
||||
Next, is Mozilla's [experimental integration with AI chatbot](https://blog.nightly.mozilla.org/2024/06/24/experimenting-with-ai-services-in-nightly/). Why? Who is asking for this? What telemetry data is being sent to the integrated services? Who knows! At least this one, in contrast to the weather widget, is opt-in, but regardless it shows how out of touch Mozilla is with its userbase. Firefox's *only* defining feature is that **it is not Chrome**, so following in Chrome's footsteps in implementing AI integration is a head-scratcher.
|
||||
|
||||
I have been using Firefox forever, and it makes me sad that it just gets worse and worse and worse. I'm not sure how much longer it (and by extension the Gecko rendering engine) will be around, since it is only allowed to exist because of Google donating money to avoid antitrust action. For now, I'll be switching to LibreWolf, a Firefox fork that actually delivers on the privacy promise. Hopefully Servo takes off well enough to be used as a daily driver sometime soon.
|
After Width: | Height: | Size: 70 KiB |
|
@ -0,0 +1,17 @@
|
|||
---
|
||||
title: "On LibreWolf"
|
||||
date: 2024-10-01T22:11:03-07:00
|
||||
year: "2024"
|
||||
---
|
||||
|
||||
As I mentioned in my [previous post](/blog/2024/09/no-more-firefox/), I've been using LibreWolf as my daily driver browser. It's been about two weeks since then, and I had some thoughts.
|
||||
|
||||
I originally tried to compile LibreWolf myself, which is how I found out 16GB of RAM is not enough to compile a web browser. I found this interesting since I was able to compile [Floorp](https://floorp.app/en) just fine a while back. Have browsers really gotten so complex over the past decade to require that much memory just to compile? Anyway, I just ended up installing the binary from the AUR and got up and running.
|
||||
|
||||
One thing I really like is that new tab page is completely blank, except for a search bar. It helps me break the close reddit->new tab->open reddit cycle and generally just reduces distractions. I know this was configurable in Firefox, but having to set it up on every install meant I just stopped caring to do it after a while.
|
||||
|
||||
Something I wish was possible is whitelisting certain sites to be able to use WebGL (and other things disabled by default as anti-fingerprinting measures), I can be pretty sure my self-hosted apps aren't fingerprinting me. I ended up disabling all of these measures because of this.
|
||||
|
||||
Finally, I've really enjoyed not being logged in to everything all the time. Obviously clearing cookies is configurable on Firefox, but doing it by default is not something I thought I would enjoy. When I want to go waste time on Reddit or YouTube, logging in every time is too much of hassle so I just go back to what I was doing. It's a nice incentive to browse the smallweb instead!
|
||||
|
||||
Overall, it's been a pretty pleasant experience, and I was surprised that I actually found benefits to LibreWolf over Firefox, I was expecting the two experiences to match pretty closely.
|
|
@ -0,0 +1,13 @@
|
|||
---
|
||||
title: "Thinking About Databases"
|
||||
date: 2024-05-08T21:31:35-07:00
|
||||
year: "2024"
|
||||
categories:
|
||||
- Tech
|
||||
tags:
|
||||
- WeblogPoMo2024
|
||||
---
|
||||
|
||||
Let's say you're running a web service where users can add other users as friends. How do you store each user's friends list in the database? The simplest solution would be to use one large table called "friends" with each row being an entry on one user's friends list. How well does that perform if you scale up to millions of users? Are indexes applicable to speed things up here? Is there a better way to represent this data in the database?
|
||||
|
||||
I'm not super well-versed on database design so this is something I will be researching.
|
|
@ -0,0 +1,12 @@
|
|||
---
|
||||
title: "X-Men 97"
|
||||
date: 2024-05-04T18:54:13-07:00
|
||||
year: "2024"
|
||||
categories:
|
||||
- Life
|
||||
tags:
|
||||
- WeblogPoMo2024
|
||||
---
|
||||
|
||||
I've been keeping up with X-Men 97 weekly, it's such a good show. I love that it has a pretty serious plot but also keeps some of that Saturday morning cartoon charm. The weekly release schedule is so nice, I love spending the week leading up to the next episode hypothesizing with my partner about what will happen next. It's also gotten me into the X-Men more in general, I've been watching the original 90s cartoon in between episodes, and I think I'll pick up some comics as well!
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
---
|
||||
title: Arch Linux Secure Boot
|
||||
date: 2024-05-06T00:00:00-07:00
|
||||
tags:
|
||||
- Linux
|
||||
---
|
||||
I needed to enable Secure Boot so that I could play League of Legends with Riot's Vanguard Anti Cheat. It seemed complex at first but was actually easier than I expected. The Arch Wiki is both helpful and confusing here, it provides a bunch of different ways to do this, but doesn't always do a great job of differentiating them as logically separate processes.
|
||||
|
||||
My basic understanding of Secure Boot is that when your computer first loads up, it loads the motherboard firmware, which then boots a bootloader. I remember from my OS classes that historically, the bootloader is 512 bytes, specifically the first 512 bytes on the boot disk. The bootloader can be anything, the computer will just run it because of its location in storage, which means malicious actors could run any arbitrary code there and compromise the system. Secure boot mitigates this by only allowing cryptographically signed bootloaders to run. The process outlined here is to sign our bootloaders so that Secure Boot will allow them to run. We are doing this by using our own keys (see [Assisted process with sbctl](https://wiki.archlinux.org/title/Unified_Extensible_Firmware_Interface/Secure_Boot#Assisted_process_with_sbctl)), rather than using a pre-signed boot loader. Note that "firmware" here refers to the motherboard firmware, commonly referred to as "the BIOS"
|
||||
|
||||
0. Reboot into firmware and set secure boot mode to Setup mode. What this really means is clearing any keys that currently exist.
|
||||
1. Install `sbctl` and run `sbtcl status` to verify Setup mode is enabled
|
||||
2. Create custom keys `sbctl create-keys`
|
||||
3. Enroll your keys `sbctl enroll-keys -m`. the `-m` means to enroll Microsoft's keys as well. You almost always want this, even if you're not dual-booting with Windows because some firmware is still signed with Microsoft's keys
|
||||
4. Check boot files that need signing `sbctl verify`
|
||||
5. Sign the files `sbctl sign -s /boot/vmlinuz-linux`
|
||||
1. If you have a lot of files, the command given in the wiki works great `sbctl verify | sed 's/✗ /sbctl sign -s /e'`, this assumes that every file listed in `sbctl verify` starts with `/boot`
|
||||
6. Make sure all files are signed `sbctl verify`
|
||||
7. Reboot into firmware and turn on Secure Boot
|
||||
1. In my Asus ROG motherboard's firmware, the setting is in Boot -> Secure Boot and the options are "Windows UEFI" or "Other OS" which are unclear. Windows UEFI turns Secure Boot on.
|
||||
8. Reboot again and run `sbctl status` to verify Secure Boot is on
|
|
@ -0,0 +1,27 @@
|
|||
---
|
||||
title: Example Systemd Service
|
||||
date: 2024-05-06T00:00:00-07:00
|
||||
slug: systemd-example
|
||||
tags:
|
||||
- Linux
|
||||
---
|
||||
|
||||
System units go in `/etc/systemd/system`
|
||||
User units go in `$HOME/.config/systemd/user`
|
||||
|
||||
```
|
||||
[Unit]
|
||||
Description=Webring test service
|
||||
After=network.target
|
||||
StartLimitIntervalSec=0
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
Restart=always
|
||||
RestartSec=1
|
||||
WorkingDir=/code/webring
|
||||
ExecStart=/code/webring/webring --dsn /code/webring/webring.db --addr :8000
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
```
|
|
@ -0,0 +1,39 @@
|
|||
---
|
||||
title: Example .desktop File
|
||||
date: 2024-05-06T00:00:00-07:00
|
||||
slug: desktop-file-example
|
||||
tags:
|
||||
- Linux
|
||||
---
|
||||
Example
|
||||
|
||||
```
|
||||
[Desktop Entry]
|
||||
|
||||
# The type as listed above
|
||||
Type=Application
|
||||
|
||||
# The version of the desktop entry specification to which this file complies
|
||||
Version=1.0
|
||||
|
||||
# The name of the application
|
||||
Name=jMemorize
|
||||
|
||||
# A comment which can/will be used as a tooltip
|
||||
Comment=Flash card based learning tool
|
||||
|
||||
# The path to the folder in which the executable is run
|
||||
Path=/opt/jmemorise
|
||||
|
||||
# The executable of the application, possibly with arguments.
|
||||
Exec=jmemorize
|
||||
|
||||
# The name of the icon that will be used to display this entry
|
||||
Icon=jmemorize
|
||||
|
||||
# Describes whether this application needs to be run in a terminal or not
|
||||
Terminal=false
|
||||
|
||||
# Describes the categories in which this entry should be shown
|
||||
Categories=Education;Languages;Java;
|
||||
```
|
|
@ -0,0 +1,55 @@
|
|||
---
|
||||
title: Retrieving status.cafe Updates During Hugo Builds
|
||||
date: 2024-05-06T00:00:00-07:00
|
||||
slug: hugo-build-status-cafe
|
||||
tags:
|
||||
- Hugo
|
||||
- Web Development
|
||||
---
|
||||
|
||||
status.cafe provides you with a JavaScript snippet to include your status on your site. I don't update my status super often, so I don't need to be hitting m15o's servers on every page load. To get around this, I wanted to see if I could update my status as a build step in Hugo.
|
||||
|
||||
This is the script status.cafe provides:
|
||||
```js
|
||||
document.writeln('<div id="statuscafe"><div id="statuscafe-username"></div><div id="statuscafe-content"></div></div>');
|
||||
fetch("https://status.cafe/users/yequari/status.json")
|
||||
.then( r => r.json() )
|
||||
.then( r => {
|
||||
if (!r.content.length) {
|
||||
document.getElementById("statuscafe-content").innerHTML = "No status yet."
|
||||
return
|
||||
}
|
||||
document.getElementById("statuscafe-username").innerHTML = '<a href="https://status.cafe/users/yequari" target="_blank">' + r.author + '</a> ' + r.face + ' ' + r.timeAgo
|
||||
document.getElementById("statuscafe-content").innerHTML = r.content
|
||||
})
|
||||
|
||||
```
|
||||
|
||||
This takes just over a second to fully load. Fetching the above script takes 478ms, then running the script fetches a json file, which takes 680ms. Now this is asynchronous, which means a user is not waiting on this for the rest of the page to load, but it is noticeable that the status pops in later than everything else. The entire page loads in 1.22s
|
||||
|
||||
Here is the same functionality written as a hugo template
|
||||
```go-html-template
|
||||
{{ $data := dict }}
|
||||
{{ $url := "https://status.cafe/users/yequari/status.json" }}
|
||||
{{ with resources.GetRemote $url }}
|
||||
{{ with .Err }}
|
||||
{{ errorf "%s" . }}
|
||||
{{ else }}
|
||||
<div id="statuscafe">
|
||||
{{ $data = .Content | transform.Unmarshal }}
|
||||
{{ $length := len $data.content }}
|
||||
{{ if eq $length 0 }}
|
||||
No status
|
||||
{{ else }}
|
||||
<div id="statuscafe-username">
|
||||
<a href="https://status.cafe/users/yequari" target="_blank">{{ $data.author }}</a> {{ $data.face }} {{ $data.timeAgo }}
|
||||
</div>
|
||||
<div id="statuscafe-content">
|
||||
{{ $data.content }}
|
||||
</div>
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
{{ else }}
|
||||
{{ errorf "Unable to get remote resource %q" $url }}
|
||||
{{ end }}
|
||||
```
|
|
@ -0,0 +1,28 @@
|
|||
---
|
||||
title: Vim Tips
|
||||
date: 2024-05-06T00:00:00-07:00
|
||||
slug: vim-tips
|
||||
tags:
|
||||
- Linux
|
||||
---
|
||||
## General Tips
|
||||
- `vim -p file1 file2` to open multiple files as tabs
|
||||
- `:qa` to quit out of all open buffers
|
||||
- `:Ex` to return to netrw (file explorer)
|
||||
## Terminals
|
||||
- `:term` to open a terminal in current window
|
||||
- Use `i` to enter insert mode and type into the shell
|
||||
- `<C-\><C-n>` to return to normal mode to allow scrolling or switching windows
|
||||
- I've remapped this to `<C-space>`
|
||||
## Windows
|
||||
- `<C-w>` prefixes all window commands
|
||||
- `<C-w>` + `h,j,k,l` to focus window to left, bottom, up, right, respectively
|
||||
- `<C-w>s` to split current window horizontally, equivalent to `:split`
|
||||
- `<C-w>v` to split current window vertically, equivalent to `:vs`
|
||||
## Registers
|
||||
- `"c` before a command, where `c` is the register to store the text
|
||||
- Use capital letter to append to the register, e.g. `"C`
|
||||
## Macros
|
||||
- Press `qc` to start recording, where `c` is the register to store the macro
|
||||
- Stop recording with `q`
|
||||
- Replay the macro with `@c`
|
|
@ -1,8 +1,9 @@
|
|||
---
|
||||
title: Dockerized ZNC
|
||||
date: "2022-11-07T14:18:30-07:00"
|
||||
categories:
|
||||
- tech
|
||||
tags:
|
||||
- Linux
|
||||
- Self-Hosting
|
||||
---
|
||||
|
||||
# Setting Up ZNC with Docker
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
---
|
||||
title: League on Linux
|
||||
date: "2022-11-06T14:18:30-07:00"
|
||||
categories:
|
||||
- tech
|
||||
- gaming
|
||||
tags:
|
||||
- Linux
|
||||
---
|
||||
|
||||
# League of Legends on Linux
|
||||
|
|
|
@ -6,8 +6,8 @@ date: 2023-04-17T15:00:46-07:00
|
|||
|
||||
One day this page will pull some info from APIs to create a more interesting page but for now I just manually update it as needed.
|
||||
|
||||
**Games I'm playing**: Cyberpunk 2077, Honkai Star Rail, Baldur's Gate 3
|
||||
**Games I'm playing**: Octopath Traveler, Vampire Survivors
|
||||
|
||||
**Shows I'm watching**: Nothing currently
|
||||
|
||||
**Music I'm listening to**: Kyuss, Tool, Cyberpunk 2077 Soundtrack, 100 gecs, King Crimson, breakcore
|
||||
**Music I'm listening to**: Sleep, Kyuss, Brant Bjork, Queens of the Stone Age, Monster Magnet
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
title: "Projects"
|
||||
date: 2023-10-09T14:21:12-07:00
|
||||
---
|
||||
# Projects
|
||||
|
||||
Here are some projects I'm currently working on or have worked on in the past.
|
||||
|
||||
|
@ -11,21 +10,13 @@ Here are some projects I'm currently working on or have worked on in the past.
|
|||
I run a few services for the amazing folks over at the [32-Bit Cafe](https://32bit.cafe).
|
||||
|
||||
- [RSS reader](https://rss.32bit.cafe): an instance of the FreshRSS feed reader to provide an easy to use entry point for community members looking to get started with RSS.
|
||||
- ~~Discussion boards: An instance of postmill used to share interesting links and resources to the community.~~
|
||||
- ~~Discuss bot: A Discord bot that sends new posts from the discussion boards to a channel in the Discord server.~~
|
||||
- [Discourse instance](https://discourse.32bit.cafe): The postmill instance has been phased out in favor of a Discourse forum. It has been awesome building this up with everyone and seeing the enthusiasm for a second primary space for the community.
|
||||
- [32bit.cafe Discourse](https://discourse.32bit.cafe): The postmill instance has been phased out in favor of a Discourse forum. It has been awesome building this up with everyone and seeing the enthusiasm for a second primary space for the community.
|
||||
|
||||
## Websites
|
||||
|
||||
- This website
|
||||
- [yequari's emporium of excellent toys](https://yeet.marigold.town): One day I will catalog my toy collection here
|
||||
- [webweav.ing tools](https://webweav.ing): Currently there is only an RSS feed generator but I intend to add several other tools to help smooth out some pain points of webmastery.
|
||||
|
||||
## Software
|
||||
|
||||
- [SeekerBot](/projects/seekerbot): A Discord bot to keep track of trading card game matches taking place online.
|
||||
- [powerlinx](/projects/powerlinx): A static site generator.
|
||||
- [Pynex](/projects/pynex): A terminal browser for m15o's nex protocol.
|
||||
- [lox-interpreter](/projects/lox-interpreter): Source code as I'm working through Robert Nystrom's excellent *Crafting Interpeters*.
|
||||
- [yqsh](/projects/yqsh): A toy shell written in C to learn Linux systems programming.
|
||||
- [weatherbar](/projects/weatherbar): A cli application to get current weather conditions, for use in status bar programs like i3bar, waybar, etc.
|
||||
|
|
After Width: | Height: | Size: 64 KiB |
After Width: | Height: | Size: 39 KiB |
After Width: | Height: | Size: 70 KiB |
After Width: | Height: | Size: 98 KiB |
After Width: | Height: | Size: 57 KiB |
After Width: | Height: | Size: 51 KiB |
After Width: | Height: | Size: 111 KiB |
After Width: | Height: | Size: 191 KiB |
|
@ -0,0 +1,60 @@
|
|||
---
|
||||
title: "Store Exclusives"
|
||||
date: 2024-08-11T08:53:54-07:00
|
||||
year: "2024"
|
||||
---
|
||||
|
||||
# Transformers 00s Store Exclusives
|
||||
|
||||
> *This page was created as an entry into the [32-Bit Cafe's Codejam #5](https://32bit.cafe/~xandra/events/codejam5/). While not necessarily a "complicated topic", it is a topic I can ramble on about for hours.*
|
||||
|
||||
The early- to mid-2000s period of the Transformers franchise had an interesting product strategy, one that Hasbro seemed to shift away from following the success of the first live-action movie. This era was the one I grew up with, so I wanted to dive into one aspect of the toyline I find particularly interesting about this period: retailer exclusive toys.
|
||||
|
||||
## Some History
|
||||
|
||||
Retailers will request exclusives from Hasbro as a way to draw customers into the store. The idea being if you go in for a specific exclusive toy, maybe you'll spend more money in the store other items while you're there, rather than getting them from a competitor. Kmart of all places actually had the first retailer-exclusive Transformers toys in 1989, which were the inner robots of the Classic Pretender toys: Bumblebee, Grimlock, Jazz, and Starscream. There were very few retailer exclusives after that until KB Toys got an entire subline named Machine Wars in 1997, containing toys made from cancelled Generation 2 molds or late Generation 1 molds that were exclusive to Europe. There were a few scattered exclusives since then in the Beast Wars and Beast Machine lines, but It wasn't until Robots in Disguise in 2001 that retailer exclusive mainline toys became a common practice.
|
||||
|
||||
## Exclusives for Everyone
|
||||
|
||||
Following the success of the Robots in Disguise line, the large toy retailers of the time, Target, Walmart, Toys R Us, and KB Toys, began selling their own exclusive figures. These stores generally got pretty normal figures as exclusives, mostly repaints or value packs of mainline figures. Toys R Us got a lot of collector-oriented releases, including reissues of Generation 1 toys in the Commemerative Series line. Membership retailers Costco and Sam's Club also got some exclusives for the holiday season, which ended up being the weirder exclusive releases.
|
||||
|
||||
### Kmart
|
||||
|
||||
Kmart was largely excluded from exclusives during this time, however they did get some, including an odd "Battle for the Matrix" multipack in the Transformers Armada line, containing "Powerlinx" Optimus Prime and "Powerlinx" Jetfire, along with a large assortment of Mini-cons. For context, by the second year of the Armada toyline, Hasbro was running out of toys to release to keep up with demand, so they repainted a bunch of first-year toys to represent "powered up" versions of the characters, and slapped "Powerlinx" in front of their name. Despite this labelling, neither "Powerlinx" figure in this multipack is actually the Powerlinx version released to all the retailers. Jetfire is exactly the same as the original figure, and Optimus Prime is almost the same as his original figure, except his red parts are painted gold for some reason. It...doesn't look great. To add to the confustion, it would have been possible to find the real mainline Powerlinx Optimus Prime and Jetfire next to this multipack. Wild.
|
||||
|
||||
![Armada Optimus Prime, but red is now gold](images/800px-Armada-optimus-prime-gold-kmart.jpg "That's gold, Jerry! Gold!")
|
||||
|
||||
### Sam's Club
|
||||
|
||||
Sam's Club got 3 exclusives in this period, the first two in 2003 were repainted Robots in Disguise Optimus Prime and Ultra Magnus, under the Transformers Universe line. Ultra Magnus is mostly unchanged from his mainline 2001 release, except for some darker blues in his color scheme. Optimus Prime, though, is repainted in an awesome bright yellow color scheme. Why? Who knows. It is such an odd choice and I love it. Even weirder, is that Prime's die-cast chest is still painted red, a jarring contrast from everything else turning yellow.
|
||||
|
||||
![Robots in Disguise 2001 Optimus Prime but he's yellow](images/Universe2003toy-OptimusPrimeSuper.jpg "When life gives you lemons")
|
||||
|
||||
The next year, Sam's Club offered an exclusive two-pack of Prowl and Starscream, which were repaints of Armada Red Alert and Armada Starscream, and included their Mini-cons. The Starscream is a fairly minor repaint, keeping a similar color scheme but with black wings and darker greys. Prowl, however, is sporting a blue and white color scheme, made to look more like Energon Prowl. I actually like this deco a lot, though I wonder why the choice was to repaint Red Alert instead of one of the million Autobot cars.
|
||||
|
||||
![](images/Energon-toy_2-pack_Starscream.jpg)
|
||||
![](images/Energon-toy_2-pack_Prowl.jpg)
|
||||
|
||||
### Costco
|
||||
|
||||
Costco got a few exclusives, the most notable one is a 2004 multipack of Armada Optimus Prime and Overload, repainted in a black, yellow, and maroon color scheme. It is very similar to the [Universe Optimus Primal](https://tfwiki.net/wiki/Optimus_Primal_(BW)/toys#Universe_.282003.29) figure. I actually like this color scheme a lot, it's pretty unique as far as Optimus Prime decos go.
|
||||
|
||||
![](images/Energon_Costco_OptimusPrimeOverload.jpg)
|
||||
|
||||
The following year, Costco sold a multipack of the Sam's Club versions of Robots in Disguise Optimus Prime and Ultra Magnus, except Optimus is back to being red. Interestingly, the box uses the artwork for Cybertron Optimus Prime, even though the toys don't look much alike, and box art for Ultra Magnus in the Cybertron style was specifically created for this release. I remember being somewhat disappointed about getting this set for Christmas that year because it wasn't Cybertron Optimus Prime, but I came around on them pretty quickly.
|
||||
|
||||
![](images/Cybertrontoy_ridprime_magnus_2pack.jpg)
|
||||
|
||||
In 2006, Costco got a multipack of Cybertron Optimus Prime and Wing Saber with an extra DVD included. The toys were repackaged without any modification from the mainline, which actually makes it somewhat unique among the other exclusives of the time. I was very excited about getting this one for Christmas.
|
||||
|
||||
![](images/Cybertrontoy_prime_wingsaber_2pack.jpg)
|
||||
|
||||
## Conclusion
|
||||
|
||||
While exclusives have certainly not gone away, after the franchise *exploded* following the release of the first live-action movie, the way exclusives were done changed. Of course we still got random repaints, but these tended to be minor characters. Hasbro became much more deliberate in its releases of big ticket toys like Optimus Prime, avoiding wacky repaints and instead going for more grounded color schemes, usually for a more "screen accurate" look, such as with Premium Edition releases.
|
||||
|
||||
## More info
|
||||
|
||||
- [Exclusives - TFWiki](https://tfwiki.net/wiki/Exclusive)
|
||||
- Images sourced from the characters' respective pages on TFWiki
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
- "Futzing around with iPods"
|
||||
- "Building a CD collection"
|
||||
- "Improving my physical fitness"
|
|
@ -0,0 +1,10 @@
|
|||
{{- $u := urls.Parse .Destination -}}
|
||||
<a href="{{ .Destination | safeURL }}"
|
||||
{{- with .Title }} title="{{ . }}"{{ end -}}
|
||||
{{- if $u.IsAbs }} rel="external"{{ end -}}
|
||||
>
|
||||
{{- with .Text | safeHTML }}{{ . }}{{ end -}}
|
||||
</a>{{- if $u.IsAbs }}🔗{{ end -}}
|
||||
{{- /* chomp trailing newline */ -}}
|
||||
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
{{ define "main" }}
|
||||
<h1>{{ .Title }}</h1>
|
||||
<section class="content posts h-feed hfeed">
|
||||
{{ range .Paginator.Pages.ByPublishDate.Reverse }}
|
||||
<article class="h-entry">
|
||||
<h2><a class="title u-url p-name" href="{{ .RelPermalink }}">{{ .Title }}</a></h2>
|
||||
{{ partial "post-header.html" .}}
|
||||
{{ if .Params.Subtitle }}<p class="subtitle">{{ .Params.Subtitle }}</p>{{ end }}
|
||||
<p class="summary">
|
||||
{{ .Summary }}{{ if .Truncated }}...{{ end }}
|
||||
</p>
|
||||
</article>
|
||||
{{ end }}
|
||||
</section>
|
||||
{{ template "_internal/pagination.html" . }}
|
||||
{{ end }}
|
||||
{{ define "sidebar" }}
|
||||
<!-- {{- partial "blog-sidebar.html" . -}} -->
|
||||
<!-- <h3>See Posts From</h3> -->
|
||||
<!-- {{- partial "posts-by-year.html" . -}} -->
|
||||
<!-- {{- partial "sidebar.html" . -}} -->
|
||||
{{ end }}
|
|
@ -0,0 +1,20 @@
|
|||
{{ define "main" }}
|
||||
<div class="index-wrapper">
|
||||
<div class="box index-content">
|
||||
{{ .Content }}
|
||||
</div>
|
||||
<div class="box index-blog">
|
||||
{{- partial "index-latest-blogs.html" . -}}
|
||||
</div>
|
||||
<div class="box index-social">
|
||||
{{- partial "index-socials.html" . -}}
|
||||
</div>
|
||||
<!-- <div class="box index-banners"> -->
|
||||
<!-- </div> -->
|
||||
<div class="box index-recent">
|
||||
{{- partial "index-now.html" . -}}
|
||||
</div>
|
||||
<!-- <div class="box index-bookmarks"> -->
|
||||
<!-- </div> -->
|
||||
</div>
|
||||
{{ end }}
|
|
@ -6,11 +6,6 @@
|
|||
{{ partial "linklist.html" . }}
|
||||
{{ end }}
|
||||
</div>
|
||||
<div class="links-column">
|
||||
{{ range $.Site.Data.links.middle }}
|
||||
{{ partial "linklist.html" . }}
|
||||
{{ end }}
|
||||
</div>
|
||||
<div class="links-column">
|
||||
{{ range $.Site.Data.links.right }}
|
||||
{{ partial "linklist.html" . }}
|
||||
|
@ -18,3 +13,5 @@
|
|||
</div>
|
||||
</div>
|
||||
{{ end }}
|
||||
{{ define "sidebar" }}
|
||||
{{ end }}
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
{{ define "main" }}
|
||||
<h1>{{ .Title }}</h1>
|
||||
{{ .Content }}
|
||||
<section class="content posts h-feed hfeed">
|
||||
<ul>
|
||||
<li class="note-item"><h2>Title</h2><h2>Tags</h2></li>
|
||||
{{ range (where .Site.RegularPages.ByTitle "Section" "notes") }}
|
||||
<li class="note-item">
|
||||
<a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a>
|
||||
{{ $taxonomy := "tags" }}
|
||||
{{ with .GetTerms $taxonomy }}
|
||||
<span>
|
||||
{{ range $k, $_ := . -}}
|
||||
{{ if $k }}, {{ end }}
|
||||
<a class="tag" href="{{ .RelPermalink }}">{{ .LinkTitle }}</a>
|
||||
{{- end }}
|
||||
{{ end }}
|
||||
</span>
|
||||
</li>
|
||||
{{ end }}
|
||||
</ul>
|
||||
</section>
|
||||
{{ end }}
|
|
@ -0,0 +1,11 @@
|
|||
{{ define "main" }}
|
||||
<h1 class="p-name">{{ .Title }}</h1>
|
||||
<section class="content">
|
||||
<article class="h-entry">
|
||||
{{ partial "tags.html" .}}
|
||||
<div class="e-content">
|
||||
{{ .Content }}
|
||||
</div>
|
||||
</article>
|
||||
</section>
|
||||
{{ end }}
|
|
@ -0,0 +1,8 @@
|
|||
<html>
|
||||
<head>
|
||||
<title></title>
|
||||
</head>
|
||||
<body>
|
||||
{{ .Content }}
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,13 @@
|
|||
{{ range first 1 (where .Site.RegularPages.ByDate.Reverse "Section" "blog") }}
|
||||
{{ $d1 := time.ParseDuration "-168h" }}
|
||||
{{ $t1 := time.Now.Add $d1 }}
|
||||
{{ $t2 := time.AsTime .PublishDate }}
|
||||
{{ if $t2.After $t1 }}
|
||||
<div id="avatar-frame" class="online">
|
||||
{{ else }}
|
||||
<div id="avatar-frame" class="busy">
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
<span class="gloss"></span>
|
||||
<img class="u-photo avatar" src="/images/avatar.jpg">
|
||||
</div>
|
|
@ -0,0 +1,4 @@
|
|||
<section class="sidebar">
|
||||
<h3> See Posts From </h3>
|
||||
{{- partial "posts-by-year.html" . -}}
|
||||
</section>
|
|
@ -0,0 +1,2 @@
|
|||
<link rel="stylesheet" href="/css/main.css">
|
||||
<link rel="stylesheet" href="/css/custom.css">
|
|
@ -0,0 +1,11 @@
|
|||
<p>
|
||||
<button class="hidden" value="dark mode" id="theme-toggle">Button</button>
|
||||
</p>
|
||||
<p>
|
||||
Site updated
|
||||
<time datetime="{{ .Site.Lastmod.Format "2006-01-02 15:04:05 -0700" }}">{{ .Site.Lastmod.Format "January 2, 2006" }}</time>.
|
||||
{{ $pageLastmod := .Lastmod }}
|
||||
{{ with .GitInfo }}
|
||||
Page version <a href="https://git.32bit.cafe/yequari/yequari.com/commit/{{.Hash}}"><code>{{ .AbbreviatedHash }}</code></a>.
|
||||
{{ end }}
|
||||
</p>
|
|
@ -0,0 +1,4 @@
|
|||
<div class="profile h-card">
|
||||
<a class="sitetitle u-url" rel="me" href="{{ .Site.BaseURL }}"><h1><span class="p-name">{{ .Site.Title }}</span></h1></a>
|
||||
{{- partial "avatar.html" . -}}
|
||||
</div>
|
|
@ -0,0 +1 @@
|
|||
<h3>Read These Articles</h3>
|
|
@ -0,0 +1,9 @@
|
|||
<h3>Latest Blog Posts</h3>
|
||||
<ul>
|
||||
{{ range first 3 (where .Site.RegularPages.ByDate.Reverse "Section" "blog") }}
|
||||
<li>
|
||||
<time class="dt-published" datetime="{{ .PublishDate }}">{{ .PublishDate.Format "01/02/06" }}</time>
|
||||
<a class="title u-url p-name" href="{{ .RelPermalink }}">{{ .Title }}</a>
|
||||
</li>
|
||||
{{ end }}
|
||||
</ul>
|
|
@ -0,0 +1,12 @@
|
|||
<h3>Check Out These Sites</h3>
|
||||
<div id="index-links">
|
||||
<a href="#"><img src="/images/link-banners/manatee_banner2.png"></a>
|
||||
<a href="#"><img src="/images/link-banners/isthisloss.png"></a>
|
||||
<a href="#"><img src="/images/link-banners/iusearchbtw.png"></a>
|
||||
<a href="#"><img src="/images/link-banners/poweredbymozilla.png"></a>
|
||||
<a href="#"><img src="/images/link-banners/yqbanner.png"></a>
|
||||
<a href="#"><img src="/images/link-banners/sendmeawebmention.png"></a>
|
||||
</div>
|
||||
<p>
|
||||
<a href="/links">/links</a> =>
|
||||
</p>
|
|
@ -0,0 +1,6 @@
|
|||
<h3>What I'm Up To</h3>
|
||||
<ul>
|
||||
{{ range .Site.Data.now }}
|
||||
<li>{{ . | markdownify }}</li>
|
||||
{{ end }}
|
||||
</ul>
|
|
@ -0,0 +1,16 @@
|
|||
<h3>Socials</h3>
|
||||
<ul class="social">
|
||||
{{ range site.Menus.social }}
|
||||
<li class="social">
|
||||
<img class="social" src="/icons/{{.Params.icon}}">
|
||||
{{ if .URL }}
|
||||
<a rel="me" href="{{ .URL | safeURL }}">
|
||||
{{ .Name }}
|
||||
<!-- <span class="social {{.Params.class}}"></span> -->
|
||||
</a>
|
||||
{{ else }}
|
||||
{{ .Name }}
|
||||
{{ end }}
|
||||
</li>
|
||||
{{ end }}
|
||||
</ul>
|
|
@ -4,7 +4,11 @@
|
|||
<li>
|
||||
<details>
|
||||
<summary>
|
||||
<a target="_blank" href="{{ .url }}" >{{ .name }}</a>
|
||||
{{ .name }}
|
||||
<p>
|
||||
{{ $u := urls.Parse .url }}
|
||||
🔗<a target="_blank" href="{{ .url }}" >{{ $u.Hostname }}</a>
|
||||
</p>
|
||||
</summary>
|
||||
{{ .description }}
|
||||
</details>
|
||||
|
|
|
@ -1,34 +1,26 @@
|
|||
<section>
|
||||
<div id="avatar-frame" class="online">
|
||||
<span class="gloss"></span>
|
||||
<img class="u-photo" width="100px" src="/images/avatar.jpg">
|
||||
</div>
|
||||
</section>
|
||||
<section>
|
||||
<h1>current status</h1>
|
||||
<div id="statuscafe"><div id="statuscafe-username"></div><div id="statuscafe-content"></div></div><script src="https://status.cafe/current-status.js?name=yequari" defer></script>
|
||||
</section>
|
||||
<section>
|
||||
<h1>Social</h1>
|
||||
<ul class="social">
|
||||
{{ range site.Menus.social }}
|
||||
<li class="social">
|
||||
<img class="social" src="/icons/{{.Params.icon}}">
|
||||
{{ if .URL }}
|
||||
<a rel="me" href="{{ .URL }}">
|
||||
{{ .Name }}
|
||||
<!-- <span class="social {{.Params.class}}"></span> -->
|
||||
</a>
|
||||
{{ else }}
|
||||
{{ .Name }}
|
||||
{{ end }}
|
||||
</li>
|
||||
{{ end }}
|
||||
</ul>
|
||||
</section>
|
||||
<section>
|
||||
<h1><span class="lowercase">yequari</span> says...</h1>
|
||||
<div id="quote">
|
||||
<p id="subtitle">.</p>
|
||||
</div>
|
||||
<section class="sidebar">
|
||||
<section>
|
||||
<!-- <div id="avatar-frame" class="online"> -->
|
||||
<!-- <span class="gloss"></span> -->
|
||||
<!-- <img class="u-photo" width="100px" src="/images/avatar.jpg"> -->
|
||||
<!-- </div> -->
|
||||
{{ partial "avatar.html" . }}
|
||||
<!-- <p class="about-me"> -->
|
||||
<!-- I'm yequari. I like programming, tabletop games, and the Transformers. -->
|
||||
<!-- </p> -->
|
||||
</section>
|
||||
<section>
|
||||
<!-- <div id="statuscafe"><div id="statuscafe-username"></div><div id="statuscafe-content"></div></div><script src="https://status.cafe/current-status.js?name=yequari" defer></script> -->
|
||||
{{ partial "statuscafe.html" .}}
|
||||
</section>
|
||||
<section>
|
||||
<!-- <h1>Social</h1> -->
|
||||
{{ partial "index-socials.html" .}}
|
||||
</section>
|
||||
<!-- <section> -->
|
||||
<!-- <h1>Quote of the Day</h1> -->
|
||||
<!-- <div id="quote"> -->
|
||||
<!-- <p id="subtitle">.</p> -->
|
||||
<!-- </div> -->
|
||||
<!-- </section> -->
|
||||
</section>
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
{{ $data := dict }}
|
||||
{{ $url := "https://status.cafe/users/yequari/status.json" }}
|
||||
{{ with resources.GetRemote $url }}
|
||||
{{ with .Err }}
|
||||
{{ errorf "%s" . }}
|
||||
{{ else }}
|
||||
<div id="statuscafe">
|
||||
{{ $data = .Content | transform.Unmarshal }}
|
||||
{{ $length := len $data.content }}
|
||||
{{ if eq $length 0 }}
|
||||
No status
|
||||
{{ else }}
|
||||
{{ $timestrs := strings.Split $data.timeAgo " " }}
|
||||
{{ $timeamt := index $timestrs 0 }}
|
||||
{{ $timeunit := index $timestrs 1 }}
|
||||
{{ $timeunit = strings.Substr $timeunit 0 1 }}
|
||||
{{ $url = "https://status.cafe/users/yequari/badge.png" }}
|
||||
{{ with resources.GetRemote $url}}
|
||||
<div id="statuscafe-username">
|
||||
<a href="https://status.cafe/users/yequari"><img src="{{ .RelPermalink }}" alt="Status Cafe Profile"/></a>
|
||||
</div>
|
||||
{{ end }}
|
||||
<div id="statuscafe-timeago">
|
||||
🕗{{ $timeamt }}{{ $timeunit }}
|
||||
</div>
|
||||
<div id="statuscafe-content">
|
||||
<p>
|
||||
{{ htmlUnescape $data.content }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
{{ else }}
|
||||
{{ errorf "Unable to get remote resource %q" $url }}
|
||||
{{ end }}
|
|
@ -1,4 +1,5 @@
|
|||
{{ define "main" }}
|
||||
<h1>{{ .Title }}</h1>
|
||||
<section class="content">
|
||||
{{ .Content }}
|
||||
</section>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{{ define "main" }}
|
||||
<h1>{{ .Title }}</h1>
|
||||
<section class="content">
|
||||
<h1>{{ .Title }}</h1>
|
||||
{{ .Content }}
|
||||
</section>
|
||||
{{ end }}
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
{{ define "main" }}
|
||||
<article>
|
||||
{{ .Content }}
|
||||
</article>
|
||||
{{ end }}
|
|
@ -0,0 +1,193 @@
|
|||
:root {
|
||||
--avatar-width: 50px;
|
||||
--avatar-padding: calc(var(--avatar-width) / 10);
|
||||
}
|
||||
|
||||
#avatar-frame {
|
||||
width: fit-content;
|
||||
max-height: var(--avatar-width);
|
||||
margin: 0.5vh 0;
|
||||
padding: var(--avatar-padding);
|
||||
border: 1px solid #cccccf;
|
||||
border-radius: 15%/23%;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#avatar-frame img {
|
||||
max-width: var(--avatar-width);
|
||||
border: 1px solid grey;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.online {
|
||||
background: linear-gradient(#D6FFDB00 0%, #D6FFDB 30%, #66FF00 100%);
|
||||
box-shadow: 0 5px 10px #66FF00;
|
||||
}
|
||||
|
||||
.busy {
|
||||
background: linear-gradient(#FF9A0000 0%, #D8820055 30%, #fca30d 100%);
|
||||
box-shadow: 0 5px 10px #fca30d;
|
||||
}
|
||||
|
||||
.gloss {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
/* background: red; */
|
||||
background: radial-gradient(ellipse 200% 120% at 50% 0%, rgba(255,255,255,0.25) 0%, rgba(255,255,255,0.25) 50%,
|
||||
rgba(255,255,255,0) 51%);
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 10;
|
||||
border-radius: 15%/23%;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.index-wrapper {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(10, 10% [col-start]);
|
||||
grid-template-rows: 50% 50%;
|
||||
grid-template-areas:
|
||||
"content content content content content content recent recent recent recent"
|
||||
"interests interests interests interests blog blog blog blog social social";
|
||||
}
|
||||
|
||||
.box {
|
||||
/* border: 1px dotted black; */
|
||||
padding: 2vh;
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
|
||||
li.note-item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.index-content {
|
||||
grid-area: content;
|
||||
}
|
||||
|
||||
.index-social {
|
||||
grid-area: social;
|
||||
}
|
||||
|
||||
.index-blog {
|
||||
grid-area: blog;
|
||||
}
|
||||
|
||||
.index-banners {
|
||||
grid-row: 3 / 4;
|
||||
grid-column: 1 / span 5;
|
||||
}
|
||||
|
||||
.index-recent {
|
||||
grid-area: recent;
|
||||
}
|
||||
|
||||
.index-bookmarks {
|
||||
grid-row: 3 / 4;
|
||||
grid-column: 6 / span 5;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 500px) {
|
||||
.index-wrapper {
|
||||
display: flex;
|
||||
flex-flow: row wrap;
|
||||
}
|
||||
}
|
||||
|
||||
#statuscafe {
|
||||
display: flex;
|
||||
flex-flow: row wrap;
|
||||
justify-content: space-between;
|
||||
border: 1px solid #CCCCCC;
|
||||
}
|
||||
|
||||
#statuscafe p {
|
||||
line-height: 1.5;
|
||||
margin: 5px 0;
|
||||
color: var(--secondary-text);
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
#statuscafe #statuscafe-timeago {
|
||||
flex: 1 1 50%;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
#statuscafe #statuscafe-username {
|
||||
flex: 1 1 50%;
|
||||
}
|
||||
|
||||
#statuscafe #statuscafe-content {
|
||||
flex: 1 1 100%;
|
||||
}
|
||||
|
||||
/*
|
||||
* Links page
|
||||
*/
|
||||
|
||||
#links-main {
|
||||
display: flex;
|
||||
flex-flow: row wrap;
|
||||
align-items: flex-start;
|
||||
justify-content: space-between;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
#links-main ul {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
#links-main li {
|
||||
padding: 7px 0;
|
||||
list-style-type: none;
|
||||
}
|
||||
|
||||
.link-list details {
|
||||
border: 1px dotted var(--pewter-blue);
|
||||
padding: 0.7em 0.7em;
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
|
||||
.link-list details[open] {
|
||||
/* padding: 0.5em; */
|
||||
}
|
||||
|
||||
.link-list details[open] summary {
|
||||
border-bottom: 1px dotted var(--pewter-blue);
|
||||
padding-bottom: 0.5em;
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
|
||||
.link-list summary p {
|
||||
line-height: 1;
|
||||
/* margin: -0.5em -0.5em 0; */
|
||||
/* padding: 0.5em; */
|
||||
}
|
||||
|
||||
.links-column {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex: 1 3 20%;
|
||||
overflow-wrap: break-word;
|
||||
}
|
||||
|
||||
.links-column h2 {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* webmention box */
|
||||
|
||||
.send-webmention {
|
||||
margin: 55px 25px;
|
||||
max-width: fit-content;
|
||||
border: 1px dotted var(--primary-text);
|
||||
padding: 0 20px 20px;
|
||||
}
|
||||
|
||||
.send-webmention p {
|
||||
font-size: 1.3rem;
|
||||
}
|
||||
|
||||
#webmentions img { max-height: 1.2em; margin-right: -1ex; }
|
|
@ -0,0 +1,146 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="47.99622mm"
|
||||
height="45.001984mm"
|
||||
viewBox="0 0 47.99622 45.001984"
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1">
|
||||
<linearGradient
|
||||
id="linearGradient12">
|
||||
<stop
|
||||
style="stop-color:#ffffff;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop12" />
|
||||
<stop
|
||||
style="stop-color:#d3d3d3;stop-opacity:0.74959087;"
|
||||
offset="1"
|
||||
id="stop13" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient7">
|
||||
<stop
|
||||
style="stop-color:#ffffff;stop-opacity:0.55925357;"
|
||||
offset="0"
|
||||
id="stop7" />
|
||||
<stop
|
||||
style="stop-color:#ffffff;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop8" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient4">
|
||||
<stop
|
||||
style="stop-color:#6584e9;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop4" />
|
||||
<stop
|
||||
style="stop-color:#1569ff;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop5" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
xlink:href="#linearGradient4"
|
||||
id="linearGradient5"
|
||||
x1="118.96619"
|
||||
y1="86.680702"
|
||||
x2="118.80185"
|
||||
y2="137.54486"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<radialGradient
|
||||
xlink:href="#linearGradient12"
|
||||
id="radialGradient13"
|
||||
cx="113.40607"
|
||||
cy="90.053154"
|
||||
fx="113.40607"
|
||||
fy="90.053154"
|
||||
r="10.769611"
|
||||
gradientTransform="matrix(2.410187,0.00186119,-8.2100529e-4,1.0631985,-159.84984,9.8383068)"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<radialGradient
|
||||
xlink:href="#linearGradient12"
|
||||
id="radialGradient14"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(2.410187,0.00186119,-8.2100529e-4,1.0631985,-159.84984,9.8383068)"
|
||||
cx="113.40607"
|
||||
cy="90.053154"
|
||||
fx="113.40607"
|
||||
fy="90.053154"
|
||||
r="10.769611" />
|
||||
<radialGradient
|
||||
xlink:href="#linearGradient12"
|
||||
id="radialGradient15"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(2.410187,0.00186119,-8.2100529e-4,1.0631985,-159.84984,9.8383068)"
|
||||
cx="113.40607"
|
||||
cy="90.053154"
|
||||
fx="113.40607"
|
||||
fy="90.053154"
|
||||
r="10.769611" />
|
||||
<radialGradient
|
||||
xlink:href="#linearGradient12"
|
||||
id="radialGradient16"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(2.410187,0.00186119,-8.2100529e-4,1.0631985,-159.84984,9.8383068)"
|
||||
cx="113.40607"
|
||||
cy="90.053154"
|
||||
fx="113.40607"
|
||||
fy="90.053154"
|
||||
r="10.769611" />
|
||||
<radialGradient
|
||||
xlink:href="#linearGradient7"
|
||||
id="radialGradient17"
|
||||
cx="119.09299"
|
||||
cy="106.36999"
|
||||
fx="119.09299"
|
||||
fy="106.36999"
|
||||
r="24.955069"
|
||||
gradientTransform="matrix(1.8154139,-0.00721497,0.00502929,1.0822886,-97.645043,-7.8937874)"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
</defs>
|
||||
<g
|
||||
id="layer1"
|
||||
transform="translate(-89.355382,-85.372261)">
|
||||
<g
|
||||
id="g8"
|
||||
transform="matrix(0.95707953,0,0,1.0349057,-0.60521845,-11.619623)">
|
||||
<path
|
||||
id="path2"
|
||||
style="fill:url(#linearGradient5);fill-opacity:1;stroke:#989898;stroke-width:0.1;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 119.06922,93.770504 a 25.024202,21.197483 0 0 0 -25.024314,21.197156 25.024202,21.197483 0 0 0 8.022244,15.49983 c -1.42633,1.39866 -3.505935,3.50077 -6.564969,6.67453 5.795189,-0.55329 9.886849,-1.88272 12.612669,-3.15072 a 25.024202,21.197483 0 0 0 10.95437,2.17403 25.024202,21.197483 0 0 0 25.02431,-21.19767 25.024202,21.197483 0 0 0 -25.02431,-21.197156 z" />
|
||||
<path
|
||||
id="path7"
|
||||
style="opacity:0.808671;mix-blend-mode:overlay;fill:url(#radialGradient17);fill-opacity:1;stroke:none;stroke-width:0.1;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 119.06922,93.770504 a 25.024202,21.197483 0 0 0 -24.931297,20.093346 35.77681,16.883101 0 0 0 25.596367,5.10563 35.77681,16.883101 0 0 0 24.31377,-4.53771 25.024202,21.197483 0 0 0 -24.97884,-20.661266 z" />
|
||||
</g>
|
||||
<g
|
||||
id="g12"
|
||||
style="fill:url(#radialGradient13)"
|
||||
transform="matrix(1.449171,0,0,1.449171,-50.899935,-50.482378)">
|
||||
<circle
|
||||
style="opacity:0.808671;fill:url(#radialGradient14);fill-opacity:1;stroke:#b7b7b7;stroke-width:0.1;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="path9"
|
||||
cx="105.4355"
|
||||
cy="111.32723"
|
||||
r="2.7512231" />
|
||||
<circle
|
||||
style="opacity:0.808671;fill:url(#radialGradient15);fill-opacity:1;stroke:#b7b7b7;stroke-width:0.1;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="circle10"
|
||||
cx="121.37228"
|
||||
cy="111.32723"
|
||||
r="2.7512231" />
|
||||
<circle
|
||||
style="opacity:0.808671;fill:url(#radialGradient16);fill-opacity:1;stroke:#b7b7b7;stroke-width:0.1;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="circle11"
|
||||
cx="113.4469"
|
||||
cy="111.32723"
|
||||
r="2.7512231" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 5.1 KiB |
After Width: | Height: | Size: 210 KiB |
|
@ -6,20 +6,19 @@
|
|||
<header>
|
||||
{{- partial "header.html" . -}}
|
||||
</header>
|
||||
<nav>
|
||||
<nav id="main-navbar">
|
||||
{{- partial "nav.html" . -}}
|
||||
</nav>
|
||||
<div class="main-sidebar">
|
||||
<section class="sidebar">
|
||||
{{- partial "sidebar.html" . -}}
|
||||
</section>
|
||||
{{- block "sidebar" . }}
|
||||
{{ end }}
|
||||
<main>
|
||||
{{- block "main" . }}{{- end }}
|
||||
</main>
|
||||
</div>
|
||||
<footer>
|
||||
{{- partial "footer.html" . -}}
|
||||
</footer>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{{ define "main" }}
|
||||
<h1>{{ .Title }}</h1>
|
||||
<section class="content posts h-feed hfeed">
|
||||
<h1>{{ .Title }}</h1>
|
||||
{{ range .Pages }}
|
||||
<article class="h-entry">
|
||||
<h2><a class="title u-url p-name" href="{{ .RelPermalink }}">{{ .Title }}</a></h2>
|
||||
|
@ -12,3 +12,5 @@
|
|||
{{ end }}
|
||||
</section>
|
||||
{{ end }}
|
||||
{{ define "sidebar" }}
|
||||
{{ end }}
|
||||
|
|
|
@ -0,0 +1,71 @@
|
|||
{{- /* Deprecate site.Author.email in favor of site.Params.author.email */}}
|
||||
{{- $authorEmail := "" }}
|
||||
{{- with site.Params.author }}
|
||||
{{- if reflect.IsMap . }}
|
||||
{{- with .email }}
|
||||
{{- $authorEmail = . }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- else }}
|
||||
{{- with site.Author.email }}
|
||||
{{- $authorEmail = . }}
|
||||
{{- warnf "The author key in site configuration is deprecated. Use params.author.email instead." }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{- /* Deprecate site.Author.name in favor of site.Params.author.name */}}
|
||||
{{- $authorName := "" }}
|
||||
{{- with site.Params.author }}
|
||||
{{- if reflect.IsMap . }}
|
||||
{{- with .name }}
|
||||
{{- $authorName = . }}
|
||||
{{- end }}
|
||||
{{- else }}
|
||||
{{- $authorName = . }}
|
||||
{{- end }}
|
||||
{{- else }}
|
||||
{{- with site.Author.name }}
|
||||
{{- $authorName = . }}
|
||||
{{- warnf "The author key in site configuration is deprecated. Use params.author.name instead." }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{- $pctx := . }}
|
||||
{{- if .IsHome }}{{ $pctx = .Site }}{{ end }}
|
||||
{{- $pages := slice }}
|
||||
{{- if or $.IsHome $.IsSection }}
|
||||
{{- $pages = $pctx.RegularPages }}
|
||||
{{- else }}
|
||||
{{- $pages = $pctx.Pages }}
|
||||
{{- end }}
|
||||
{{- $limit := .Site.Config.Services.RSS.Limit }}
|
||||
{{- if ge $limit 1 }}
|
||||
{{- $pages = $pages | first $limit }}
|
||||
{{- end }}
|
||||
{{- printf "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\"?>" | safeHTML }}
|
||||
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
|
||||
<channel>
|
||||
<title>{{ if eq .Title .Site.Title }}{{ .Site.Title }}{{ else }}{{ with .Title }}{{ . }} on {{ end }}{{ .Site.Title }}{{ end }}</title>
|
||||
<link>{{ .Permalink }}</link>
|
||||
<description>Recent content {{ if ne .Title .Site.Title }}{{ with .Title }}in {{ . }} {{ end }}{{ end }}on {{ .Site.Title }}</description>
|
||||
<generator>Hugo {{ hugo.Version }}</generator>
|
||||
<language>{{ site.Language.LanguageCode }}</language>{{ with $authorEmail }}
|
||||
<managingEditor>{{.}}{{ with $authorName }} ({{ . }}){{ end }}</managingEditor>{{ end }}{{ with $authorEmail }}
|
||||
<webMaster>{{ . }}{{ with $authorName }} ({{ . }}){{ end }}</webMaster>{{ end }}{{ with .Site.Copyright }}
|
||||
<copyright>{{ . }}</copyright>{{ end }}{{ if not .Date.IsZero }}
|
||||
<lastBuildDate>{{ (index $pages.ByLastmod.Reverse 0).Lastmod.Format "Mon, 02 Jan 2006 15:04:05 -0700" | safeHTML }}</lastBuildDate>{{ end }}
|
||||
{{- with .OutputFormats.Get "RSS" }}
|
||||
{{ printf "<atom:link href=%q rel=\"self\" type=%q />" .Permalink .MediaType | safeHTML }}
|
||||
{{- end }}
|
||||
{{- range $pages }}
|
||||
<item>
|
||||
<title>{{ .Title }}</title>
|
||||
<link>{{ .Permalink }}</link>
|
||||
<pubDate>{{ .PublishDate.Format "Mon, 02 Jan 2006 15:04:05 -0700" | safeHTML }}</pubDate>
|
||||
{{- with $authorEmail }}<author>{{ . }}{{ with $authorName }} ({{ . }}){{ end }}</author>{{ end }}
|
||||
<guid>{{ .Permalink }}</guid>
|
||||
<description>{{ .Content | transform.XMLEscape | safeHTML }}</description>
|
||||
</item>
|
||||
{{- end }}
|
||||
</channel>
|
||||
</rss>
|
|
@ -1,3 +1,5 @@
|
|||
{{ define "main" }}
|
||||
{{ .Content }}
|
||||
{{ end }}
|
||||
{{ define "sidebar" }}
|
||||
{{ end }}
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
{{ define "main" }}
|
||||
<h1>{{ .Title }}</h1>
|
||||
<section class="content posts h-feed hfeed">
|
||||
<h1>{{ .Title }}</h1>
|
||||
{{ range .Paginator.Pages.ByPublishDate.Reverse }}
|
||||
<article class="h-entry">
|
||||
<h2><a class="title u-url p-name" href="{{ .RelPermalink }}">{{ .Title }}</a></h2>
|
||||
{{ partial "post-header.html" .}}
|
||||
<h2><a class="title u-url p-name" href="{{ .RelPermalink }}">{{ .Title }}</a></h2>
|
||||
{{ if .Params.Subtitle }}<p class="subtitle">{{ .Params.Subtitle }}</p>{{ end }}
|
||||
<p class="summary">
|
||||
{{ .Summary }}{{ if .Truncated }}...{{ end }}
|
||||
</p>
|
||||
|
@ -12,6 +13,4 @@
|
|||
{{ end }}
|
||||
</section>
|
||||
{{ template "_internal/pagination.html" . }}
|
||||
<h3>See Posts From</h3>
|
||||
{{- partial "posts-by-year.html" . -}}
|
||||
{{ end }}
|
||||
|
|
|
@ -8,8 +8,11 @@
|
|||
<a class="u-url permalink hidden" href={{ .RelPermalink }}>Permalink</a>
|
||||
<div class="e-content">
|
||||
<h1 class="p-name">{{ .Title }}</h1>
|
||||
{{ if .Params.Subtitle }}<p class="subtitle">{{ .Params.Subtitle }}</p>{{ end }}
|
||||
{{ if .Params.toc }}<aside>{{ .TableOfContents }}</aside>{{ end }}
|
||||
{{ .Content }}
|
||||
</div>
|
||||
</article>
|
||||
{{ partial "webmentions.html" }}
|
||||
{{ end }}
|
||||
{{ define "sidebar" }}
|
||||
{{ end }}
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
{{ define "main" }}
|
||||
{{ .Content }}
|
||||
<h2>Latest Blog Posts</h2>
|
||||
<ul>
|
||||
{{ range first 3 (where .Site.RegularPages.ByDate.Reverse "Section" "blog") }}
|
||||
<article>
|
||||
<h3 class="index"><a class="title u-url p-name" href="{{ .RelPermalink }}">{{ .Title }}</a></h3>
|
||||
{{ partial "post-header.html" .}}
|
||||
</article>
|
||||
<li><a class="title u-url p-name" href="{{ .RelPermalink }}">{{ .Title }}</a></li>
|
||||
{{ end }}
|
||||
</ul>
|
||||
{{ end }}
|
||||
{{ define "sidebar" }}
|
||||
{{- partial "sidebar.html" . -}}
|
||||
{{ end }}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
{{ $taxonomy := "categories" }}
|
||||
{{ with .GetTerms $taxonomy }}
|
||||
in
|
||||
{{ range $k, $_ := . -}}
|
||||
{{ if $k }}, {{ end }}
|
||||
<a class="category" href="{{ .RelPermalink }}">{{ .LinkTitle }}</a>
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
<link rel="stylesheet" href="/css/main.css">
|
|
@ -1,6 +0,0 @@
|
|||
<p class="hidden">
|
||||
{{ range first 1 (where .Site.RegularPages.ByDate.Reverse "Section" "blog") }}
|
||||
Last updated <time id="last-update" datetime="{{ .PublishDate.Format "2006-01-02 15:04:05 -0700" }}">{{ .PublishDate.Format "January 2, 2006" }}</time>.
|
||||
{{ end }}
|
||||
<script src="https://tinylytics.app/embed/ig7D4Y9LSxprgCWfj5e8.js" defer></script>
|
||||
</p>
|
|
@ -2,16 +2,17 @@
|
|||
<meta name="viewport" content="width=device-width">
|
||||
<meta charset="utf-8">
|
||||
<meta property="og:type" content="website">
|
||||
<meta property="og:url" content="https://yequari.com/">
|
||||
<meta property="og:url" content="{{ .Page.Permalink }}">
|
||||
<meta property="og:title" content="{{ .Page.Title }}">
|
||||
<meta property="og:site_name" content="{{ .Site.Title }}">
|
||||
<meta property="og:description" content="{{ .Site.Params.About }}">
|
||||
<meta property="og:image" content="{{ .Site.Params.OgImage }}">
|
||||
<title>{{ .Page.Title }}</title>
|
||||
<link rel="stylesheet" href="/css/main.css">
|
||||
{{ partial "css.html" . }}
|
||||
<link rel="icon" type="image/png" href="/favicon.png">
|
||||
<script src="/js/avatar.js" defer></script>
|
||||
<script src="/js/quotes.js" defer></script>
|
||||
<link rel="webmention" href="https://webmention.io/yequari.com/webmention" />
|
||||
<link rel="pingback" href="https://webmention.io/yequari.com/xmlrpc" />
|
||||
<script src="/js/webmention.js" async></script>
|
||||
<link rel="webmention" href="{{ .Site.Params.Webmentions }}" />
|
||||
<link rel="pingback" href="{{ .Site.Params.Pingbacks }}" />
|
||||
<script src="/js/main.js" defer></script>
|
||||
{{ range .AlternativeOutputFormats -}}
|
||||
{{ printf `<link rel="%s" type="%s" href="%s" title="%s" />` .Rel .MediaType.Type .Permalink $.Site.Title | safeHTML }}
|
||||
{{ end -}}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
<div class="metadata">
|
||||
<div>
|
||||
<time class="dt-published" datetime="{{ .PublishDate }}">{{ .PublishDate.Format "Mon, Jan 2, 2006" }}</time>
|
||||
in {{ partial "categories.html" .}}
|
||||
<time class="dt-published" datetime="{{ .PublishDate }}">{{ .PublishDate.Format "Mon, Jan 2, 2006" }}</time> {{ partial "categories.html" .}}
|
||||
</div>
|
||||
<div>
|
||||
{{ partial "tags.html" .}}
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
<ul>
|
||||
{{ range $index,$element := .Site.Taxonomies.year -}}
|
||||
{{if ne $index "2022"}},{{end}}
|
||||
<a href="{{ .Page.Permalink }}">{{ .Page.Title }}</a>
|
||||
<!-- {{if ne $index "2022"}},{{end}} -->
|
||||
<li><a href="{{ .Page.Permalink }}">{{ .Page.Title }}</a></li>
|
||||
{{- end -}}
|
||||
</ul>
|
||||
|
|
|
@ -2,6 +2,6 @@
|
|||
{{ with .GetTerms $taxonomy }}
|
||||
{{ range $k, $_ := . -}}
|
||||
{{ if $k }}, {{ end }}
|
||||
<a class="tag" href="{{ .RelPermalink }}">#{{ .LinkTitle }}</a>
|
||||
<a class="tag" href="{{ .RelPermalink }}">{{ .LinkTitle }}</a>
|
||||
{{- end }}
|
||||
{{ end }}
|
||||
|
|
|
@ -1,86 +1,70 @@
|
|||
@import url(https://fonts.bunny.net/css?family=ibm-plex-mono:400|noto-sans:400,500,600,700|m-plus-1:400,500,600,700|audiowide:400);
|
||||
@import url(https://fonts.bunny.net/css?family=ibm-plex-mono:400|noto-sans:400,500,600,700|m-plus-1:400,500,600,700|audiowide:400|koulen:400|catamaran:400,700);
|
||||
/* CSS HEX */
|
||||
:root {
|
||||
--jet: #353535ff;
|
||||
--chinese-red: #aa3322ff;
|
||||
--pale-silver: #c4bbafff;
|
||||
--space-cadet: #292640ff;
|
||||
--xiketic: #0f101aff;
|
||||
--blue-ryb: #4056f4ff;
|
||||
--raisin-black: #241e1edd;
|
||||
--dim-gray: #756b6bff;
|
||||
--pewter-blue: #93A8ACff;
|
||||
--heading-1: 2.75rem;
|
||||
--heading-2: 2.25rem;
|
||||
--heading-3: 1.75rem;
|
||||
--heading-4: 1.25rem;
|
||||
--heading-5: 0.75rem;
|
||||
--heading-6: 0.25rem;
|
||||
}
|
||||
|
||||
--celestial-blue: #5299D3;
|
||||
--white-smoke: #F1EDEE;
|
||||
--midnight-blue: #18206F;
|
||||
--penn-blue: #17255A;
|
||||
--eerie-black: #172121;
|
||||
--vista-blue: #8EA4D2;
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
--main-bg: linear-gradient(#28164B, 70%, #825ECA );
|
||||
--content-bg: #1A181B;
|
||||
--primary-text: #DCCBFF;
|
||||
--secondary-text: #B89AF5;
|
||||
--header: #825ECA;
|
||||
--nav-link: #B89AF5;
|
||||
--primary-link: #B89AF5;
|
||||
--primary-link-hover: #E3D5FF;
|
||||
--secondary-link: #E3D5FF;
|
||||
--secondary-link-hover: #B89AF5;
|
||||
--ternary-link: #B89AF5;
|
||||
--ternary-link-hover: #E3D5FF;
|
||||
--link-shadow: #00000088;
|
||||
--shadow: #00000088;
|
||||
--nav-spotlight: radial-gradient(
|
||||
circle at center,
|
||||
rgba(255, 255, 255, 0.1) 0%,
|
||||
rgba(255, 255, 255, 0.05) 25%,
|
||||
rgba(255, 255, 255, 0) 40%
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
--dark-purple: #331832;
|
||||
--fairy-tale: #FFC6D9;
|
||||
--english-violet: #694D75;
|
||||
--platinum: #D0DDD7;
|
||||
--non-photo-blue: #8AC6D0;
|
||||
|
||||
--night: #121113;
|
||||
--tea-green: #E2F1AF;
|
||||
--anti-flash-white: #EEF0F2;
|
||||
--zaffre: #0D21A1;
|
||||
--saffron: #EEC643;
|
||||
--purple: #7B1E7A;
|
||||
--raspberry-rose: #B33F62;
|
||||
--tufts-blue: #3C91E6;
|
||||
--pale-purple: #F3E0EC;
|
||||
--timberwolf: #DDCECD;
|
||||
--isabelline: #EEE5E5;
|
||||
--verdigris: #28AFB0;
|
||||
--fandango: #AF4D98;
|
||||
--risd-blue: #4242FF;
|
||||
|
||||
--charcoal: #364958;
|
||||
--cornflower-blue: #758BFD;
|
||||
--tropical-indigo: #9D8DF1;
|
||||
|
||||
/* solarized dark colors */
|
||||
--base00: #657b83;
|
||||
--base01: #586e75;
|
||||
--base02: #073642;
|
||||
--base03: #002b36;
|
||||
--base0: #839496;
|
||||
--base1: #93a1a1;
|
||||
--base2: #eee8d5;
|
||||
--base3: #fdf6e3;
|
||||
|
||||
--yellow: #b58900;
|
||||
--orange: #cb4b16;
|
||||
--red: #dc322f;
|
||||
--magenta: #d33682;
|
||||
--violet: #6c71c4;
|
||||
--blue: #268bd2;
|
||||
--cyan: #2aa198;
|
||||
--green: #859900;
|
||||
|
||||
--main-bg: var(--dark-purple);
|
||||
--content-bg: var(--isabelline);
|
||||
--primary-text: var(--night);
|
||||
--secondary-text: var(--charcoal);
|
||||
--nav-link: var(--fairy-tale);
|
||||
--primary-link: var(--risd-blue);
|
||||
--primary-link-hover: var(--chinese-red);
|
||||
--secondary-link: var(--verdigris);
|
||||
--secondary-link-hover: var(--tropical-indigo);
|
||||
--ternary-link: var(--zaffre);
|
||||
--ternary-link-hover: var(--chinese-red);
|
||||
@media (prefers-color-scheme: light) {
|
||||
:root {
|
||||
--main-bg: linear-gradient(#918EF4, #6F9CEB);
|
||||
--content-bg: #98B9F2;
|
||||
--primary-text: #141B41;
|
||||
--secondary-text: #141B41;
|
||||
--header: #141B41;
|
||||
--nav-link: #141B41;
|
||||
--primary-link: #306BAC;
|
||||
--primary-link-hover: #141B41;
|
||||
--secondary-link: #306BAC;
|
||||
--secondary-link-hover: #141B41;
|
||||
--ternary-link: #141B41;
|
||||
--ternary-link-hover: #306BAC;
|
||||
--link-shadow: #00000000;
|
||||
--shadow: #132B40AA;
|
||||
--nav-spotlight: radial-gradient(
|
||||
circle at center,
|
||||
rgba(255, 255, 255, 0.1) 0%,
|
||||
rgba(255, 255, 255, 0.05) 25%,
|
||||
rgba(255, 255, 255, 0) 40%
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
body {
|
||||
background: fixed no-repeat url('/images/waves.svg') #00c2f6;
|
||||
background: fixed no-repeat url('/images/waves-nobg.svg'), fixed no-repeat var(--main-bg);
|
||||
background-size: cover;
|
||||
color: var(--primary-text);
|
||||
font-size: 16px;
|
||||
font-family: 'Noto Sans', sans-serif;
|
||||
font-size: medium;
|
||||
font-family: 'Catamaran', serif;
|
||||
scrollbar-width: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
|
@ -92,14 +76,44 @@ body::-webkit-scrollbar {
|
|||
|
||||
h1,h2,h3,h4,h5,h6 {
|
||||
color: var(--secondary-text);
|
||||
font-family: 'M PLUS 1', sans-serif;
|
||||
text-transform: capitalize;
|
||||
font-family: 'Koulen', sans-serif;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: var(--heading-1);
|
||||
}
|
||||
h2 {
|
||||
font-size: var(--heading-2);
|
||||
}
|
||||
h3 {
|
||||
font-size: var(--heading-3);
|
||||
}
|
||||
h5 {
|
||||
font-size: var(--heading-5);
|
||||
}
|
||||
h6 {
|
||||
font-size: var(--heading-6);
|
||||
}
|
||||
|
||||
p {
|
||||
font-size: 1.1rem;
|
||||
line-height: 1.8;
|
||||
}
|
||||
|
||||
p.subtitle {
|
||||
color: var(--secondary-text);
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
p.about {
|
||||
line-height: 0;
|
||||
color: var(--fairy-tale);
|
||||
}
|
||||
|
||||
p.context {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
a:link, a:visited {
|
||||
color: var(--primary-link);
|
||||
}
|
||||
|
@ -109,21 +123,30 @@ a:hover, a:active {
|
|||
text-decoration: underline;
|
||||
}
|
||||
|
||||
a.tag {
|
||||
article a.title:link, article a.title:visited {
|
||||
color: var(--secondary-link);
|
||||
}
|
||||
|
||||
article a.title:hover, article a.title:active {
|
||||
color: var(--secondary-link-hover);
|
||||
}
|
||||
|
||||
a.tag {
|
||||
color: var(--primary-link);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a.tag:hover, a.tag:active {
|
||||
color: var(--secondary-link-hover);
|
||||
color: var(--primary-link-hover);
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
a.category {
|
||||
color: var(--ternary-link)
|
||||
color: var(--primary-link)
|
||||
}
|
||||
|
||||
a.category:hover, a.category:active {
|
||||
color: var(--ternary-link-hover)
|
||||
color: var(--primary-link-hover)
|
||||
}
|
||||
|
||||
a.permalink {
|
||||
|
@ -137,7 +160,7 @@ a.summary {
|
|||
header h1 {
|
||||
font-family: 'Audiowide', display;
|
||||
/* font-size: 1rem; */
|
||||
color: var(--fairy-tale);
|
||||
color: var(--header);
|
||||
display: inline;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
@ -149,13 +172,17 @@ ul.social {
|
|||
}
|
||||
|
||||
li.social {
|
||||
padding: 0;
|
||||
padding: 5px 0;
|
||||
}
|
||||
|
||||
img.social {
|
||||
width: 16px;
|
||||
}
|
||||
|
||||
header {
|
||||
font-family: 'Noto Sans', sans-serif;
|
||||
}
|
||||
|
||||
header a.sitetitle {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
@ -165,105 +192,160 @@ header .profile {
|
|||
flex-flow: row wrap;
|
||||
justify-content: space-between;
|
||||
margin: 10px;
|
||||
text-shadow: 3px 3px 5px var(--link-shadow);
|
||||
}
|
||||
|
||||
header .profile img {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
p.about {
|
||||
line-height: 0;
|
||||
color: var(--fairy-tale);
|
||||
}
|
||||
|
||||
p.context {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.wrapper {
|
||||
max-width: 980px;
|
||||
max-width: 1024px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
nav {
|
||||
nav#main-navbar {
|
||||
/* From https://css.glass */
|
||||
background: rgba(255, 255, 255, 0.13);
|
||||
border-radius: 16px;
|
||||
box-shadow: 0 4px 30px rgba(0, 0, 0, 0.1);
|
||||
box-shadow: 3px 3px 5px var(--shadow);
|
||||
backdrop-filter: blur(5px);
|
||||
-webkit-backdrop-filter: blur(5px);
|
||||
border: 1px solid rgba(255, 255, 255, 0.3);
|
||||
|
||||
text-align: center;
|
||||
padding: 0;
|
||||
border-radius: 15px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
nav ul {
|
||||
nav#main-navbar ul {
|
||||
list-style-type: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border-radius: 15px;
|
||||
}
|
||||
|
||||
nav li {
|
||||
display: inline;
|
||||
nav#main-navbar li {
|
||||
display: inline-block;
|
||||
border-radius: 15px;
|
||||
transition: box-shadow 0.3s;
|
||||
}
|
||||
|
||||
nav li a {
|
||||
nav#main-navbar li:hover,
|
||||
nav#main-navbar li:active {
|
||||
animation: 0.2s ease-in 1 forwards spotlight;
|
||||
outline: 1px solid rgba(255, 255, 255, 0.2);
|
||||
background-clip: border-box;
|
||||
box-shadow: 0 0 15px rgba(255, 255, 255, 0.5);
|
||||
}
|
||||
|
||||
nav#main-navbar li a {
|
||||
display: inline-block;
|
||||
padding: 20px;
|
||||
/* font-size: 1.1rem; */
|
||||
transition: box-shadow 0.3s;
|
||||
font-size: 1.1rem;
|
||||
|
||||
text-transform: uppercase;
|
||||
font-family: "Noto Sans", sans-serif;
|
||||
font-weight: 500;
|
||||
border-radius: 15px;
|
||||
text-shadow: 1px 1px 3px var(--link-shadow);
|
||||
}
|
||||
|
||||
nav li a:link, nav li a:visited {
|
||||
nav#main-navbar li a:link,
|
||||
nav#main-navbar li a:visited {
|
||||
color: var(--nav-link);
|
||||
text-decoration: none;
|
||||
border-left: 1px solid rgba(255, 255, 255, 0);
|
||||
border-right: 1px solid rgba(255, 255, 255, 0);
|
||||
}
|
||||
|
||||
nav li a:hover, nav li a:active {
|
||||
animation: 0.2s ease-in 1 forwards gradient;
|
||||
outline: 1px solid rgba(255, 255, 255, 0.3);
|
||||
box-shadow: 0 0 10px white;
|
||||
nav#main-navbar li a:hover,
|
||||
nav#main-navbar li a:active {
|
||||
background: radial-gradient(
|
||||
ellipse 425% 100% at top,
|
||||
rgba(255, 255, 255, 0.25) 0%,
|
||||
rgba(255, 255, 255, 0.05) 30%,
|
||||
rgba(255, 255, 255, 0) 32%
|
||||
);
|
||||
/* background: linear-gradient(
|
||||
rgba(255, 255, 255, 0.13) 0%,
|
||||
rgba(255, 255, 255, 0.1) 30%,
|
||||
rgba(255, 255, 255, 0) 31%
|
||||
); */
|
||||
border-left: 1px solid rgba(255, 255, 255, 0.05);
|
||||
border-right: 1px solid rgba(255, 255, 255, 0.05);
|
||||
text-shadow: 1px 1px 3px var(--link-shadow);
|
||||
}
|
||||
|
||||
@keyframes gradient {
|
||||
@keyframes spotlight {
|
||||
0% {
|
||||
background: radial-gradient(circle at 50% 100%, rgba(255,255,255,0) 0%, rgba(255,255,255,0.00) 10%, rgba(255,255,255,0) 20%), linear-gradient(rgba(255,255,255,0.13) 0%, rgba(255,255,255,0.1) 40%, rgba(255,255,255,0.0) 41%);
|
||||
background: radial-gradient(
|
||||
circle at 50% 100%,
|
||||
rgba(255, 255, 255, 0) 0%,
|
||||
rgba(255, 255, 255, 0) 10%,
|
||||
rgba(255, 255, 255, 0) 20%
|
||||
);
|
||||
}
|
||||
20% {
|
||||
background: radial-gradient(circle at 50% 100%, rgba(255,255,255,0.1) 0%, rgba(255,255,255,0.05) 20%, rgba(255,255,255,0) 30%), linear-gradient(rgba(255,255,255,0.13) 0%, rgba(255,255,255,0.2) 30%, rgba(255,255,255,0.13) 31%);
|
||||
background: radial-gradient(
|
||||
circle at 50% 100%,
|
||||
rgba(255, 255, 255, 0.05) 0%,
|
||||
rgba(255, 255, 255, 0.03) 20%,
|
||||
rgba(255, 255, 255, 0) 30%
|
||||
);
|
||||
}
|
||||
40% {
|
||||
background: radial-gradient(circle at 50% 100%, rgba(255,255,255,0.2) 0%, rgba(255,255,255,0.1) 25%, rgba(255,255,255,0) 35%), linear-gradient(rgba(255,255,255,0.13) 0%, rgba(255,255,255,0.2) 30%, rgba(255,255,255,0.13) 31%);
|
||||
background: radial-gradient(
|
||||
circle at 50% 100%,
|
||||
rgba(255, 255, 255, 0.1) 0%,
|
||||
rgba(255, 255, 255, 0.07) 25%,
|
||||
rgba(255, 255, 255, 0) 45%
|
||||
);
|
||||
}
|
||||
60% {
|
||||
background: radial-gradient(circle at 50% 100%, rgba(255,255,255,0.25) 0%, rgba(255,255,255,0.15) 25%, rgba(255,255,255,0) 45%), linear-gradient(rgba(255,255,255,0.13) 0%, rgba(255,255,255,0.2) 30%, rgba(255,255,255,0.13) 31%);
|
||||
background: radial-gradient(
|
||||
circle at 50% 100%,
|
||||
rgba(255, 255, 255, 0.15) 0%,
|
||||
rgba(255, 255, 255, 0.13) 25%,
|
||||
rgba(255, 255, 255, 0) 50%
|
||||
);
|
||||
}
|
||||
80% {
|
||||
background: radial-gradient(circle at 50% 100%, rgba(255,255,255,0.30) 0%, rgba(255,255,255,0.20) 25%, rgba(255,255,255,0) 50%), linear-gradient(rgba(255,255,255,0.13) 0%, rgba(255,255,255,0.2) 30%, rgba(255,255,255,0.13) 31%);
|
||||
background: radial-gradient(
|
||||
circle at 50% 100%,
|
||||
rgba(255, 255, 255, 0.2) 0%,
|
||||
rgba(255, 255, 255, 0.15) 25%,
|
||||
rgba(255, 255, 255, 0) 50%
|
||||
);
|
||||
}
|
||||
100% {
|
||||
background: radial-gradient(circle at 50% 100%, rgba(255,255,255,0.35) 0%, rgba(255,255,255,0.25) 25%, rgba(255,255,255,0) 50%), linear-gradient(rgba(255,255,255,0.13) 0%, rgba(255,255,255,0.2) 30%, rgba(255,255,255,0.13) 31%);
|
||||
background: radial-gradient(
|
||||
circle at 50% 100%,
|
||||
rgba(255, 255, 255, 0.2) 0%,
|
||||
rgba(255, 255, 255, 0.15) 25%,
|
||||
rgba(255, 255, 255, 0) 50%
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.main-sidebar {
|
||||
background-color: var(--content-bg);
|
||||
border-radius: 15px;
|
||||
z-index: 1;
|
||||
display: flex;
|
||||
flex-flow: row wrap-reverse;
|
||||
box-shadow: 10px 5px 5px #00000066;
|
||||
padding: 30px;
|
||||
flex-flow: row wrap;
|
||||
box-shadow: 3px 3px 5px var(--shadow);
|
||||
padding: 0;
|
||||
margin-bottom: 10vh;
|
||||
}
|
||||
|
||||
.sidebar {
|
||||
flex: 0 1 20%;
|
||||
border-right: 1px solid black;
|
||||
padding: 15px 15px 15px 0;
|
||||
border-right: 1px solid #c7c7c7;
|
||||
padding: 30px 25px;
|
||||
}
|
||||
|
||||
.sidebar h1 {
|
||||
|
@ -271,59 +353,22 @@ nav li a:hover, nav li a:active {
|
|||
padding-bottom: 5px;
|
||||
}
|
||||
|
||||
.sidebar #avatar-frame {
|
||||
width: fit-content;
|
||||
height: 100px;
|
||||
margin: 0 auto;
|
||||
padding: 8px 8px;
|
||||
border: 1px solid #cccccf;
|
||||
border-radius: 16px/24px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.sidebar #avatar-frame img {
|
||||
max-width: 100px;
|
||||
border: 1px solid grey;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.online {
|
||||
background: linear-gradient(#D6FFDB00 0%, #D6FFDB 30%, #66FF00 100%);
|
||||
box-shadow: 0 5px 10px #66FF00;
|
||||
}
|
||||
|
||||
.busy {
|
||||
background: linear-gradient(#FF9A0000 0%, #D8820055 30%, #fca30d 100%);
|
||||
box-shadow: 0 5px 10px #fca30d;
|
||||
}
|
||||
|
||||
.gloss {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
/* background: red; */
|
||||
background: radial-gradient(ellipse 200px 140px at 50% 0%, rgba(255,255,255,0.25) 0%, rgba(255,255,255,0.25) 50%,
|
||||
rgba(255,255,255,0) 51%);
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 10;
|
||||
border-radius: 16px/24px;
|
||||
pointer-events: none;
|
||||
.sidebar p.about-me {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
main {
|
||||
flex: 1 3 70%;
|
||||
padding: 15px 15px 15px 30px;
|
||||
padding: 2vh 4vw;
|
||||
}
|
||||
|
||||
main li {
|
||||
padding: 0.2em 0;
|
||||
}
|
||||
|
||||
|
||||
article p.context {
|
||||
margin-top: -25px;
|
||||
padding-left: 25px;
|
||||
margin-top: 0;
|
||||
padding-left: 1vw;
|
||||
}
|
||||
|
||||
article p {
|
||||
|
@ -332,9 +377,9 @@ article p {
|
|||
|
||||
article img {
|
||||
display: block;
|
||||
max-width: 400px;
|
||||
width: 85%;
|
||||
object-fit: scale-down;
|
||||
margin: 8px auto;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
article figcaption {
|
||||
|
@ -359,21 +404,10 @@ blockquote {
|
|||
border-left: 3px solid #ccc;
|
||||
}
|
||||
|
||||
code {
|
||||
background-color: black;
|
||||
overflow-x: scroll;
|
||||
padding: 0 5px;
|
||||
color: white;
|
||||
font-family: 'IBM Plex Mono', monospace;
|
||||
}
|
||||
|
||||
pre {
|
||||
}
|
||||
|
||||
pre code{
|
||||
padding: 15px;
|
||||
display: block;
|
||||
max-width: 640px;
|
||||
white-space: pre-wrap;
|
||||
word-wrap: break-word;
|
||||
padding: 1vh 2vw;
|
||||
}
|
||||
|
||||
ul.pagination {
|
||||
|
@ -387,24 +421,43 @@ li.page-item {
|
|||
}
|
||||
|
||||
footer {
|
||||
padding: 0 0 15px 0px;
|
||||
/* border-top: 1px dotted var(--secondary-text); */
|
||||
text-align: center;
|
||||
color: var(--secondary-text);
|
||||
flex: 1 1 100%;
|
||||
}
|
||||
|
||||
footer p {
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
|
||||
footer a, footer a:link, footer a:visited {
|
||||
color: var(--ternary-link);
|
||||
text-decoration: underline dotted;
|
||||
}
|
||||
|
||||
footer a:hover, footer a:active {
|
||||
color: var(--ternary-link-hover);
|
||||
}
|
||||
|
||||
#theme-toggle {
|
||||
background: var(--content-bg);
|
||||
color: var(--primary-text);
|
||||
border: 1px solid var(--ternary-link);
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
#theme-toggle:active {
|
||||
border: 1px solid var(--ternary-link-hover);
|
||||
}
|
||||
|
||||
.metadata {
|
||||
display: flex;
|
||||
flex-flow: row;
|
||||
justify-content: space-between;
|
||||
margin-top: 1vh;
|
||||
}
|
||||
|
||||
h3.index {
|
||||
margin-bottom: 10px;
|
||||
/* margin: 10px 0; */
|
||||
}
|
||||
|
||||
#webmentions img { max-height: 1.2em; margin-right: -1ex; }
|
||||
|
||||
.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
@ -416,83 +469,3 @@ h3.index {
|
|||
.lowercase {
|
||||
text-transform: lowercase;
|
||||
}
|
||||
|
||||
/* Index page blog posts */
|
||||
.title-date {
|
||||
display: flex;
|
||||
flex-flow: row;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Links page
|
||||
*/
|
||||
|
||||
#links-main {
|
||||
display: flex;
|
||||
flex-flow: row wrap;
|
||||
align-items: flex-start;
|
||||
justify-content: space-between;
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
#links-main ul {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
#links-main li {
|
||||
padding: 7px 0;
|
||||
list-style-type: none;
|
||||
}
|
||||
|
||||
.link-list details {
|
||||
border: 1px dotted var(--pewter-blue);
|
||||
padding: 0.7em 0.7em;
|
||||
}
|
||||
|
||||
.link-list details[open] {
|
||||
/* padding: 0.5em; */
|
||||
}
|
||||
|
||||
.link-list details[open] summary {
|
||||
border-bottom: 1px dotted var(--pewter-blue);
|
||||
padding-bottom: 0.5em;
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
|
||||
.link-list summary {
|
||||
/* margin: -0.5em -0.5em 0; */
|
||||
/* padding: 0.5em; */
|
||||
}
|
||||
|
||||
.links-column {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex: 1 3 10%;
|
||||
overflow-wrap: break-word;
|
||||
}
|
||||
|
||||
/* webmention box */
|
||||
|
||||
.send-webmention {
|
||||
margin: 55px 25px;
|
||||
max-width: fit-content;
|
||||
border: 1px dotted var(--primary-text);
|
||||
padding: 0 20px 20px;
|
||||
}
|
||||
|
||||
.send-webmention p {
|
||||
font-size: 1.3rem;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 700px) {
|
||||
.sidebar {
|
||||
border: none;
|
||||
}
|
||||
|
||||
article img {
|
||||
max-width: 200px;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,133 @@
|
|||
const root = document.querySelector(':root');
|
||||
const themeToggle = document.getElementById('theme-toggle');
|
||||
const mainNavbar = document.querySelector('#main-navbar ul');
|
||||
let mouseX = 0;
|
||||
let mouseY = 0;
|
||||
let navX = 0;
|
||||
let navY = 0;
|
||||
let navW = 0;
|
||||
let navH = 0;
|
||||
let navOffsetX = 0;
|
||||
let navOffsetY = 0;
|
||||
|
||||
const darkMode = {
|
||||
mainBg: "linear-gradient(#28164B, 70%, #825ECA )",
|
||||
contentBg: "#1A181B",
|
||||
primaryText: "#DCCBFF",
|
||||
secondaryText: "#B89AF5",
|
||||
header: "#825ECA",
|
||||
navLink: "#B89AF5",
|
||||
primaryLink: "#B89AF5",
|
||||
primaryLinkHover: "#E3D5FF",
|
||||
secondaryLink: "#E3D5FF",
|
||||
secondaryLinkHover: "#B89AF5",
|
||||
ternaryLink: "#B89AF5",
|
||||
ternaryLinkHover: "#E3D5FF",
|
||||
linkShadow: "#00000088",
|
||||
shadow: "#00000088",
|
||||
navSpotlight: `radial-gradient(
|
||||
circle at center,
|
||||
rgba(220, 203, 255, 0.05) 0%,
|
||||
rgba(220, 203, 255, 0.03) 25%,
|
||||
rgba(220, 203, 255, 0) 40%
|
||||
)`
|
||||
}
|
||||
|
||||
const lightMode = {
|
||||
// mainBg: "linear-gradient(#0045df, #00d4ff)",
|
||||
mainBg: "linear-gradient(#918EF4, #6F9CEB)",
|
||||
contentBg: "#98B9F2",
|
||||
primaryText: "#141B41",
|
||||
secondaryText: "#141B41",
|
||||
header: "#141B41",
|
||||
navLink: "#141B41",
|
||||
primaryLink: "#306BAC",
|
||||
primaryLinkHover: "#141B41",
|
||||
secondaryLink: "#306BAC",
|
||||
secondaryLinkHover: "#141B41",
|
||||
ternaryLink: "#141B41",
|
||||
ternaryLinkHover: "#306BAC",
|
||||
linkShadow: "#00000000",
|
||||
shadow: "#132B40AA",
|
||||
navSpotlight: `radial-gradient(
|
||||
circle at center,
|
||||
rgba(255, 255, 255, 0.1) 0%,
|
||||
rgba(255, 255, 255, 0.05) 25%,
|
||||
rgba(255, 255, 255, 0) 40%
|
||||
)`
|
||||
}
|
||||
|
||||
const applyTheme = (theme) => {
|
||||
root.style.setProperty("--main-bg", theme.mainBg);
|
||||
root.style.setProperty("--content-bg", theme.contentBg);
|
||||
root.style.setProperty("--primary-text", theme.primaryText);
|
||||
root.style.setProperty("--secondary-text", theme.secondaryText);
|
||||
root.style.setProperty("--header", theme.header);
|
||||
root.style.setProperty("--nav-link", theme.navLink);
|
||||
root.style.setProperty("--primary-link", theme.primaryLink);
|
||||
root.style.setProperty("--primary-link-hover", theme.primaryLinkHover);
|
||||
root.style.setProperty("--secondary-link", theme.secondaryLink);
|
||||
root.style.setProperty("--secondary-link-hover", theme.secondaryLinkHover);
|
||||
root.style.setProperty("--ternary-link", theme.ternaryLink);
|
||||
root.style.setProperty("--ternary-link-hover", theme.ternaryLinkHover);
|
||||
root.style.setProperty("--shadow", theme.shadow);
|
||||
root.style.setProperty("--link-shadow", theme.linkShadow);
|
||||
root.style.setProperty("--nav-spotlight", theme.navSpotlight);
|
||||
mainNavbar.style.background = theme.navSpotlight;
|
||||
mainNavbar.style.transition = 'background-position 0.25s';
|
||||
}
|
||||
|
||||
const enableDarkMode = () => {
|
||||
applyTheme(darkMode);
|
||||
localStorage.setItem('theme', 'dark');
|
||||
themeToggle.innerText = '☀️ Light Theme';
|
||||
themeToggle.value = 'Light Mode';
|
||||
}
|
||||
|
||||
const disableDarkMode = () => {
|
||||
applyTheme(lightMode);
|
||||
localStorage.setItem('theme', 'light');
|
||||
themeToggle.innerText = '🌙 Dark Theme';
|
||||
themeToggle.value = 'Dark Mode';
|
||||
}
|
||||
|
||||
const detectTheme = () => {
|
||||
let theme = 'light';
|
||||
let themeObj = lightMode;
|
||||
|
||||
if (localStorage.getItem('theme')) {
|
||||
theme = localStorage.getItem('theme');
|
||||
}
|
||||
else if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
|
||||
theme = 'dark';
|
||||
}
|
||||
|
||||
theme === 'dark' ? enableDarkMode() : disableDarkMode();
|
||||
}
|
||||
|
||||
mainNavbar.addEventListener("mousemove", (evt) => {
|
||||
mainNavbar.style.setProperty('background-position-x', `${mouseX - navX - (navW / 2)}px`);
|
||||
mainNavbar.style.setProperty('background-position-y', `${mouseY - navY - (navH / 2)}px`);
|
||||
});
|
||||
|
||||
document.addEventListener("mousemove", (evt) => {
|
||||
mouseX = evt.clientX;
|
||||
mouseY = evt.clientY;
|
||||
});
|
||||
|
||||
const calcNavOffset = () => {
|
||||
const rect = mainNavbar.getBoundingClientRect()
|
||||
navX = rect.x;
|
||||
navY = rect.y;
|
||||
navW = rect.width;
|
||||
navH = rect.height;
|
||||
}
|
||||
|
||||
calcNavOffset();
|
||||
|
||||
themeToggle.className = "";
|
||||
detectTheme();
|
||||
|
||||
themeToggle.addEventListener('click', () => {
|
||||
localStorage.getItem('theme') === 'light' ? enableDarkMode() : disableDarkMode();
|
||||
});
|