1
0
Fork 0

Initial commit

This commit is contained in:
Owen Ryan 2023-05-15 23:59:18 -04:00
commit 530fc76ede
84 changed files with 60305 additions and 0 deletions

9
.gitignore vendored Normal file
View file

@ -0,0 +1,9 @@
_site
.sass-cache
.jekyll-cache
.jekyll-metadata
vendor
Gemfile.lock
.idea
/package.json
node_modules

4
Gemfile Normal file
View file

@ -0,0 +1,4 @@
# frozen_string_literal
source "https://rubygems.org"
gemspec

12
LICENSE Normal file
View file

@ -0,0 +1,12 @@
Copyright © 2023 Owen Ryan
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
---
Bundled software:
- Bootstrap (assets/bootstrap/): MIT License

49
README.md Normal file
View file

@ -0,0 +1,49 @@
# Homepage
This repository contains all the code that I use to host my website. Pages are written in markdown and are rendered to
static HTML using Jekyll and a custom Bootstrap theme that I created.
## Installing dependencies
Based on the [Jekyll quick start guide](https://jekyllrb.com/docs/)
**Note:** Make sure Ruby and RubyGems are installed
1. Install the jekyll and bundler gem packages
```shell
gem install jekyll bundler
```
2. Install site dependencies
**Make sure you are in the root directory of the git repository**
```shell
bundle install
```
## Building the static site
Static HTML and CSS files can be built using the following command.
```shell
bundle exec jekyll build
```
All static files should now be in the ```site/``` directory.
## Important note:
The static site's root is ``_site/``. Everything outside of that is processed by Jekyll and placed in `_site/`.
**Note:** Some of the final code in ``_site`` may not have proper indentation, and some comments might have been
removed.
## Sources I used in a bunch of places
- [W3Schools](https://www.w3schools.com/)
- [MDN](https://developer.mozilla.org/en-US/)
- [Bootstrap Docs](https://getbootstrap.com/docs/5.3/getting-started/introduction/)
- [Bootstrap Examples](https://getbootstrap.com/docs/5.3/examples/)
- [Jekyll Documentation](https://jekyllrb.com/docs/)
- [Liquid Documentation](https://shopify.github.io/liquid/)
- [SASS Documentation](https://sass-lang.com/guide)

43
_config.yml Normal file
View file

@ -0,0 +1,43 @@
# Welcome to Jekyll!
#
# This config file is meant for settings that affect your whole blog, values
# which you are expected to set up once and rarely edit after that. If you find
# yourself editing this file very often, consider using Jekyll's data files
# feature for the data you need to update frequently.
#
# For technical reasons, this file is *NOT* reloaded automatically when you use
# 'bundle exec jekyll serve'. If you change this file, please restart the server process.
#
# If you need help with YAML syntax, here are some quick references for you:
# https://learn-the-web.algonquindesign.ca/topics/markdown-yaml-cheat-sheet/#yaml
# https://learnxinyminutes.com/docs/yaml/
#
# Site settings
# These are used to personalize your new site. If you look in the HTML files,
# you will see them accessed via {{ site.title }}, {{ site.email }}, and so on.
# You can create any custom variable you would like, and they will be accessible
# in the templates via {{ site.myvariable }}.
title: Owen Ryan
author: Owen Ryan
description: >- # this means to ignore newlines until "baseurl:"
The official homepage of Owen Ryan!
baseurl: "/" # the subpath of your site, e.g. /blog
# TODO: Baseurl currently does not do anything.
# Build settings
theme: homepage
# Site-wide SEO tags
SEO_tags: [ "Owen Ryan" ]
sass:
sass_dir: _sass
exclude:
- .idea
- README.md
- LICENSE
- homepage.gemspec
- package.json
- package-lock.json

11
_data/navigation.yml Normal file
View file

@ -0,0 +1,11 @@
# Links in the navigation bar
header:
- name: Home
link: /
- name: About
link: /about
- name: Projects
link: /projects
- name: Contact
link: /contact

26
_data/social-media.yml Normal file
View file

@ -0,0 +1,26 @@
# Links on the landing page
links:
- name: Git
url: https://code.owenryan.us/owenryan
style:
fa-classes: [ fa-brands fa-git-alt ]
color-primary: F44D27
- name: Mastodon
url: https://activitypub.owenryan.us/@owen
style:
# TODO: Replace with activitypub logo when available (https://github.com/FortAwesome/Font-Awesome/issues/19668)
fa-classes: [ fa-brands, fa-mastodon ]
color-primary: 6364FF
- name: LinkedIn
url: https://www.linkedin.com/in/owenryandev/
style:
fa-classes: [ fa-brands, fa-linkedin ]
color-primary: 0077B5
- name: LeetCode
url: https://leetcode.com/owenryan/
style:
# Leetcode's logo is not in fontawesome so just using this generic one
fa-classes: [ fa-solid, fa-laptop-code ]
# Leetcode does not have a press kit, and does not publish their brand colors. Hopefully this is close enough.
color-primary: FFA116

8
_includes/footer.html Normal file
View file

@ -0,0 +1,8 @@
{% comment %}
Based on bootstrap footer examples
https://getbootstrap.com/docs/5.3/examples/footers/
https://getbootstrap.com/docs/5.3/examples/sticky-footer-navbar/#
{% endcomment %}
<footer class="row justify-content-center mt-auto py-3 bg-body-tertiary">
<span class="col footer-text mx-5">© 2023 Owen Ryan | Icons by FontAwesome</span>
</footer>

30
_includes/head.html Normal file
View file

@ -0,0 +1,30 @@
<head>
<meta charset="UTF-8">
{% comment %}
Set meta description to the page description if it has one, otherwise fallback to the site description
{% endcomment %}
<meta name="description"
content="{% if page.description %}{{ page.description }}{% else %}{{ site.description }}{% endif %}">
{% comment %}
Add page keywords if there are any
{% endcomment %}
{% assign tags = site.SEO_tags %}
{% if page.SEO_tags %}
{% assign tags = tags | concat: page.SEO_tags %}
{% endif %}
<meta name="keywords" content="{{ tags | join: ", " }}">
<meta name="author" content="{{ site.author }}">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{%- if page.title -%}{{ page.title }} | {% endif %}{{ site.title }}</title>
<script src="/assets/utils.js"></script>
{% comment %}
Dependencies are self-hosted instead of using a public CDN.
See this article for more info https://httptoolkit.com/blog/public-cdn-risks/
{% endcomment %}
<link href="/assets/bootstrap/css/bootstrap.min.css" rel="stylesheet">
<link href="/css/style.css" rel="stylesheet">
<!-- Load fontawesome here for faster loadtimes: https://stackoverflow.com/a/35880730/9523246 -->
<script>
lazyLoadCSS('https://use.fontawesome.com/releases/v6.4.0/css/all.css');
</script>
</head>

18
_includes/header.html Normal file
View file

@ -0,0 +1,18 @@
<div class="container">
<header class="header d-flex flex-wrap justify-content-center py-3 mb-4 border-bottom">
<a class="d-flex align-items-center mb-3 mb-md-0 me-md-auto link-body-emphasis text-decoration-none"
href="/">
<img id="gravatar" class="bi me-2" alt="Owen's Gravatar"
src="https://www.gravatar.com/avatar/6ad4a9bcc388180c6d2ca34e0c185a8c?size=128">
<span class="fs-4">Owen Ryan</span>
</a>
<ul class="nav nav-pills">
{%- for link in site.data.navigation.header -%}
<li class="nav-item">
<a class="nav-link{% if page.url == link.link %} active{% endif %}" href="{{ link.link }}"
aria-current="page">{{ link.name }}</a>
</li>
{%- endfor -%}
</ul>
</header>
</div>

View file

@ -0,0 +1,12 @@
{% comment %}
Social media icons are dynamically rendered based on the contents of _data/social-media.yml
{% endcomment %}
<div class="row justify-content-center">
{%- for icon in site.data.social-media.links -%}
<a class="col social-button" href="{{ icon.url }}" target="_blank" rel="noopener noreferrer">
<i class="{{ icon.style.fa-classes | join: " " }} p-3" title="{{ icon.name }}"
style="color:#{{ icon.style.color-primary }};"></i>
</a>
{%- endfor -%}
</div>

12
_layouts/base.html Normal file
View file

@ -0,0 +1,12 @@
---
# Base HTML layout with the bare essentials
---
<!DOCTYPE html>
<html class="h-100" lang="en" data-bs-theme="dark">
{% include head.html %}
<body class="d-flex flex-column h-100">
{{ content }}
<script src="/assets/bootstrap/js/bootstrap.bundle.min.js"></script>
</body>
</html>

8
_layouts/basicmd.html Normal file
View file

@ -0,0 +1,8 @@
---
# Layout for basic markdown pages. Everything is nested in a container and row
layout: main
---
<div class="container">
{{ content }}
</div>

12
_layouts/main.html Normal file
View file

@ -0,0 +1,12 @@
---
# Base layout with header, footer, and content is in a main tag
layout: base
---
{% include header.html %}
<main class="flex-shrink-0">
{{ content }}
</main>
{% include footer.html %}

33
_layouts/project.html Normal file
View file

@ -0,0 +1,33 @@
---
layout: main
---
<div class="container">
<div class="row d-flex">
<div class="col-md-auto p-2">
<div class="card project-card">
{% if page.thumbnail_url %}
<img src="{{ page.thumbnail_url }}" class="card-img-top" alt="{{ page.title }} thumbnail">
{% endif %}
<div class="card-body">
<p>{{ page.description }}</p>
{% if page.project_url %}
<a href="{{ page.project_url }}" class="btn btn-primary">
<i class="fa-solid fa-arrow-up-right-from-square"></i>
Project
</a>
{% endif %}
{% if page.source_url %}
<a href="{{ page.source_url }}" class="btn btn-primary">
<i class="fa-solid fa-code"></i>
Source Code
</a>
{% endif %}
</div>
</div>
</div>
<div class="col">
{{ content }}
</div>
</div>
</div>

View file

@ -0,0 +1,89 @@
---
layout: project
title: Adventures with old calculators
description: Shenanigans with graphing calculators my school was throwing away
thumbnail_url: /assets/images/calculators.webp
SEO_tags: [Calculator, Texas Instruments, TI82, Z80, Assembly, MS-DOS, Overclocking]
---
**Note: This article is still expanding, check back later for more content!**
In January 2023, my high school was getting rid of over a hundred old calculators. Around half were mismatched
scientific and 4-function calculators, and the other half consisted of graphing calculators from the early and mid
1990s. Most of the graphing calculators are Texas Instruments TI-82, so this article will be focused on them, but I do
plan on making other posts.
After replacing the dead batteries every single TI-82 turned on and functioned, but some had malfunctioning screens.
# Overclocking
This section is based on
[this archived webpage](https://web.archive.org/web/20220303160216/http://richfiles.solarbotics.net/Turbo82.html).
There is a 26pf capacitor labeled **C7** on the top right of the TI-82's motherboard. When this is replaced with a 15pf
capacitor, the speed of the calculator increases by 2-2.5x.
Here is the resistor before and after replacement:
<img src="/assets/images/resistorcomparison.webp" class="auto-scale" alt="Split photo of motherboard with old and new resistor">
And here is a speed comparison between a stock TI-82 (left), and an overclocked TI-82 (right):
<video src="/assets/videos/calculatorperf.webm" class="auto-scale" loop autoplay></video>
# Connecting to computer
The TI-82 and TI-85 introduced the ability to connect to another calculator or to a computer to share programs.
## Hardware
The TI-82 (and TI-85) used the TI Graph-link adapter, which connected to the calculator's link port and to a computer's
9 or 25-pin serial port. Luckily, this serial adapter can be converted to USB (shown below).
<img src="/assets/images/graphlinkadapter.webp" class="auto-scale" alt="Photo of TI-Graph Link adapter attached to a serial to USB adapter">
## Software
The TI-Graph Link™ software only supports very old versions of Microsoft Windows based on DOS, and some ancient versions
of Mac OS. I chose to run the software in an MS-DOS virtual machine with Windows 3.1 since I already have experience
with the platform.
If you want to replicate my virtual machine, use the [MS-DOS 6.22](https://winworldpc.com/product/ms-dos/622) and
[Windows 3.1](https://winworldpc.com/product/windows-3/31) images from WinWorldPC, and use this archive of the
[TI Graph Link Software](https://archive.org/details/TiGraphLink). For transferring files I decided to use a physical
Floppy Drive since I had one lying around. Here is my Proxmox configuration file (I would recommend editing the config
file after creating a VM through Proxmox).
```yaml
# Replace with your floppy drive block device
args: -fda /dev/sdb
acpi: 0
# You may need to enable booting from floppy to install DOS
boot: order=ide0
cores: 1
cpu: kvm32
hotplug: disk
# Change this to the storage device you want to store your OS
ide0: local-lvm:vm-69420-disk-0,size=2G
localtime: 0
memory: 512
name: msdos
numa: 0
ostype: other
scsihw: virtio-scsi-pci
# Replace with your serial adapter
serial0: /dev/ttyUSB0
sockets: 1
tablet: 1
tags: ms-dos
vga: std
```
## What's next
Both CRASH and ASH allow you to create and load programs written in Z80 assembly. In the near future I plan on creating
some basic programs in assembly and stretching the limits on what can be run on a TI-82.

View file

@ -0,0 +1,36 @@
---
layout: project
title: "Informinator"
description: News aggregator built with Python, AioHTTP, and Jinja
thumbnail_url: /assets/images/informinator.webp
project_url: https://informinator.owenryan.us/
# TODO: Uncomment this when source code is published
# source_url: https://code.owenryan.us/owenryan/informinator
SEO_tags: [Python, aiohttp, News]
---
Informinator is the one-stop site for all of your news needs! It aims to be a central hub that delivers the stories you
need to know while also funneling you to the proper news sources to get more information. Informinator is currently in
a very early beta and only sources news from Al Jazeera, BBC News, The Associated Press, and editorials from The
Guardian.
**Note: Informinator will be open-sourced in the next few weeks when the server is stable**
## Origins
During the spring 2023 semester, two separate classes I was taking had weekly news quizzes that checked that you had
been following current events. I decided that the best way to study for these quizzes was to create a news aggregator
to simplify the process of looking at several news outlets per day.
## Current issues
The first version of Informinator was hacked together over a weekend, so some design choices are suboptimal. Some of these include:
- All articles are loaded on page-load, even though most are hidden behind the carousel.
- Informinator's RSS parsing code only supports feeds from [RSSHub](https://docs.rsshub.app/en/).
- RSSHub's New York Times English feed is currently unusable due to [a parsing error](https://github.com/DIYgod/RSSHub/issues/12371).
- All articles are cached in Python when an in-memory database such as Redis would greatly improve performance.
## Roadmap
Informinator's public roadmap can be found [here](https://informinator.owenryan.us/roadmap).

16
_posts/2023-5-6-jambox.md Normal file
View file

@ -0,0 +1,16 @@
---
layout: project
title: "Jambox"
description: "Discord music bot built with Hikari and Lavalink"
project_url: https://discord.com/api/oauth2/authorize?client_id=1102705272805404722&permissions=4298394880&scope=applications.commands%20bot
thumbnail_url: /assets/images/jambox.webp
SEO_tags: [Discord, Python, Hikari, Lavalink]
---
Jambox is a *soon-to-be* open source Discord music bot built for convince. It utilises the
[Lavalink](https://github.com/lavalink-devs/Lavalink) audio node for streaming music, and also adds support for
streaming local files¹. Jambox was built from the ground up using Discord's modern feature set, and
utilises [slash commands](https://support.discord.com/hc/en-us/articles/1500000368501-Slash-Commands-FAQ), embeds,
message components¹, and modals¹.
- ¹ - Features are not currently implemented, but are planned additions

View file

@ -0,0 +1,41 @@
---
layout: project
title: This website
description: The self-built site using Jekyll, Bootstrap, TypeScript, and more!
thumbnail_url: /assets/images/website.webp
project_url: https://owenryan.us/
source_url: https://code.owenryan.us/owenryan/owenryan.us
SEO_tags: [web, html, css, jekyll]
---
After squatting on this domain for 7 years, I finally stopped procrastinating and decided to create a website.
Here is everything I used to turn my visions into reality.
## Structure
This website was created using the [Jekyll](https://jekyllrb.com/) static site generator, which runs on the
[Liquid](https://shopify.github.io/liquid/) template engine. Jekyll supports writing posts in [Markdown](https://en.wikipedia.org/wiki/Markdown), which makes writing simple pages
like this one much easier. On the other hand, using plain markdown makes embedding videos and icons much more difficult.
## Theme
Every page is running a custom theme built with the [Bootstrap](https://getbootstrap.com/) CSS library, and styled wit
[SASS](https://sass-lang.com/). Jekyll automatically renders markdown files to fit the site theme.
## Typescript
When it comes to creating websites, I try to keep scripting down to a minimum to improve client performance. On this
site, there are currently only three times Javascript is used on this site.
- Lazy loading Stylesheets (Used for loading FontAwesome icons in the background)
- Gradient rotator (Only on index.html)
- "Get Email Address" button in contact.html (Decodes an obfuscated version of my email address to prevent scraping)
I chose to work with TypeScript over JavaScript since I prefer to use static-typing whenever possible to avoid confusion
and to allow better static analysis and linting. On the other hand, Jekyll only has built-in support for CoffeeScript,
so compiling to JavaScript has to be done manually.
## Hosting
Jekyll produces static HTML and CSS files, meaning that they can be hosted anywhere. I chose to host this website using
the [Apache webserver](https://httpd.apache.org/) because it's reliable and has better documentation than NGINX.

27
_sass/style.sass Normal file
View file

@ -0,0 +1,27 @@
// Set the margins and size of social media icons
.social-button
margin: .5em
font-size: 3vw
// Make the gravatar icon a circle
#gravatar
border-radius: 50%
height: 50px
// Set the width for project cards to 18rem and set the margin to auto (will center the card in the div)
.project-card
width: 18rem
margin: auto
// https://stackoverflow.com/a/26056554/14395984
.auto-scale
width: 100%
height: auto
max-height: 100%
// Remove bullet points from the about page
// https://stackoverflow.com/questions/1027354/i-need-an-unordered-list-without-any-bullets
main li
list-style-type: none
padding-left: 2em
text-indent: -2em

49
about.md Normal file
View file

@ -0,0 +1,49 @@
---
layout: basicmd
title: About
permalink: /about
---
Hey there!
I'm currently a high school specialising in Computer Science and related fields. I do some occasional side jobs,
so [contact me](/contact) if you are interested!
## Skills
### Proficient
- <i class="fa-brands fa-python"></i> Python
- <i class="fa-brands fa-discord"></i>
[hikari](https://pypi.org/project/hikari/)/[lightbulb](https://pypi.org/project/hikari-lightbulb/)/[miru](https://pypi.org/project/hikari-miru/)
Discord bot stack
- <i class="fa-solid fa-code-branch"></i> Check out the source code for the [Jambox](/2023/05/06/jambox.html) music bot for a representation of my
current abilities
- <i class="fa-solid fa-globe"></i> [aiohttp](https://pypi.org/project/aiohttp/) asynchronus web server
- <i class="fa-solid fa-layer-group"></i> Experience integrating Jinja templates
using [aiohttp-jinja2](https://pypi.org/project/aiohttp-jinja2/)
- <i class="fa-solid fa-server"></i> [Proxmox virtual environment](https://www.proxmox.com/en/proxmox-ve)
- <i class="fa-solid fa-boxes-stacked"></i> Experience with both Virtual Machines and Linux Containers
- <i class="fa-solid fa-desktop"></i> Experience configuring Linux, Windows, and DOS virtual machines
- <i class="fa-brands fa-linux"></i> Linux command line (sh/bash/zsh)
### Emerging
Skills that I am still working on improving
- <i class="fa-brands fa-docker"></i> Building Docker containers for Python projects
- <i class="fa-solid fa-microchip"></i> C
- <i class="fa-solid fa-memory"></i> C++
- <i class="fa-solid fa-chart-line"></i> Metrics aggregation using Prometheus and Grafana
- <i class="fa-brands fa-square-js"></i> JavaScript/TypeScript
- <i class="fa-solid fa-pen-ruler"></i> Frontend programming & Design
- <i class="fa-brands fa-html5"></i> HTML
- <i class="fa-brands fa-css3-alt"></i> CSS/SASS
- <i class="fa-brands fa-bootstrap"></i> Bootstrap
- <i class="fa-solid fa-circle-info"></i> I wrote this website and the Informinator news aggregator from scratch, check out their source code if you wnt to
see my current abilities
### Other
- <i class="fa-solid fa-mountain-sun"></i> Bryce 3.1 (The raytracing renderer from 1997)
- <i class="fa-solid fa-circle-info"></i> Used to create the logo for [Jambox](/2023/05/06/jambox.html)

4085
assets/bootstrap/css/bootstrap-grid.css vendored Normal file

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,591 @@
/*!
* Bootstrap Reboot v5.3.0-alpha3 (https://getbootstrap.com/)
* Copyright 2011-2023 The Bootstrap Authors
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
*/
:root,
[data-bs-theme=light] {
--bs-blue: #0d6efd;
--bs-indigo: #6610f2;
--bs-purple: #6f42c1;
--bs-pink: #d63384;
--bs-red: #dc3545;
--bs-orange: #fd7e14;
--bs-yellow: #ffc107;
--bs-green: #198754;
--bs-teal: #20c997;
--bs-cyan: #0dcaf0;
--bs-black: #000;
--bs-white: #fff;
--bs-gray: #6c757d;
--bs-gray-dark: #343a40;
--bs-gray-100: #f8f9fa;
--bs-gray-200: #e9ecef;
--bs-gray-300: #dee2e6;
--bs-gray-400: #ced4da;
--bs-gray-500: #adb5bd;
--bs-gray-600: #6c757d;
--bs-gray-700: #495057;
--bs-gray-800: #343a40;
--bs-gray-900: #212529;
--bs-primary: #0d6efd;
--bs-secondary: #6c757d;
--bs-success: #198754;
--bs-info: #0dcaf0;
--bs-warning: #ffc107;
--bs-danger: #dc3545;
--bs-light: #f8f9fa;
--bs-dark: #212529;
--bs-primary-rgb: 13, 110, 253;
--bs-secondary-rgb: 108, 117, 125;
--bs-success-rgb: 25, 135, 84;
--bs-info-rgb: 13, 202, 240;
--bs-warning-rgb: 255, 193, 7;
--bs-danger-rgb: 220, 53, 69;
--bs-light-rgb: 248, 249, 250;
--bs-dark-rgb: 33, 37, 41;
--bs-primary-text-emphasis: #052c65;
--bs-secondary-text-emphasis: #2b2f32;
--bs-success-text-emphasis: #0a3622;
--bs-info-text-emphasis: #055160;
--bs-warning-text-emphasis: #664d03;
--bs-danger-text-emphasis: #58151c;
--bs-light-text-emphasis: #495057;
--bs-dark-text-emphasis: #495057;
--bs-primary-bg-subtle: #cfe2ff;
--bs-secondary-bg-subtle: #e2e3e5;
--bs-success-bg-subtle: #d1e7dd;
--bs-info-bg-subtle: #cff4fc;
--bs-warning-bg-subtle: #fff3cd;
--bs-danger-bg-subtle: #f8d7da;
--bs-light-bg-subtle: #fcfcfd;
--bs-dark-bg-subtle: #ced4da;
--bs-primary-border-subtle: #9ec5fe;
--bs-secondary-border-subtle: #c4c8cb;
--bs-success-border-subtle: #a3cfbb;
--bs-info-border-subtle: #9eeaf9;
--bs-warning-border-subtle: #ffe69c;
--bs-danger-border-subtle: #f1aeb5;
--bs-light-border-subtle: #e9ecef;
--bs-dark-border-subtle: #adb5bd;
--bs-white-rgb: 255, 255, 255;
--bs-black-rgb: 0, 0, 0;
--bs-font-sans-serif: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", "Liberation Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
--bs-font-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
--bs-gradient: linear-gradient(180deg, rgba(255, 255, 255, 0.15), rgba(255, 255, 255, 0));
--bs-body-font-family: var(--bs-font-sans-serif);
--bs-body-font-size: 1rem;
--bs-body-font-weight: 400;
--bs-body-line-height: 1.5;
--bs-body-color: #212529;
--bs-body-color-rgb: 33, 37, 41;
--bs-body-bg: #fff;
--bs-body-bg-rgb: 255, 255, 255;
--bs-emphasis-color: #000;
--bs-emphasis-color-rgb: 0, 0, 0;
--bs-secondary-color: rgba(33, 37, 41, 0.75);
--bs-secondary-color-rgb: 33, 37, 41;
--bs-secondary-bg: #e9ecef;
--bs-secondary-bg-rgb: 233, 236, 239;
--bs-tertiary-color: rgba(33, 37, 41, 0.5);
--bs-tertiary-color-rgb: 33, 37, 41;
--bs-tertiary-bg: #f8f9fa;
--bs-tertiary-bg-rgb: 248, 249, 250;
--bs-link-color: #0d6efd;
--bs-link-color-rgb: 13, 110, 253;
--bs-link-decoration: underline;
--bs-link-hover-color: #0a58ca;
--bs-link-hover-color-rgb: 10, 88, 202;
--bs-code-color: #d63384;
--bs-highlight-bg: #fff3cd;
--bs-border-width: 1px;
--bs-border-style: solid;
--bs-border-color: #dee2e6;
--bs-border-color-translucent: rgba(0, 0, 0, 0.175);
--bs-border-radius: 0.375rem;
--bs-border-radius-sm: 0.25rem;
--bs-border-radius-lg: 0.5rem;
--bs-border-radius-xl: 1rem;
--bs-border-radius-xxl: 2rem;
--bs-border-radius-2xl: var(--bs-border-radius-xxl);
--bs-border-radius-pill: 50rem;
--bs-box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15);
--bs-box-shadow-sm: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075);
--bs-box-shadow-lg: 0 1rem 3rem rgba(0, 0, 0, 0.175);
--bs-box-shadow-inset: inset 0 1px 2px rgba(0, 0, 0, 0.075);
--bs-focus-ring-width: 0.25rem;
--bs-focus-ring-opacity: 0.25;
--bs-focus-ring-color: rgba(13, 110, 253, 0.25);
--bs-form-valid-color: #198754;
--bs-form-valid-border-color: #198754;
--bs-form-invalid-color: #dc3545;
--bs-form-invalid-border-color: #dc3545;
}
[data-bs-theme=dark] {
color-scheme: dark;
--bs-body-color: #adb5bd;
--bs-body-color-rgb: 173, 181, 189;
--bs-body-bg: #212529;
--bs-body-bg-rgb: 33, 37, 41;
--bs-emphasis-color: #fff;
--bs-emphasis-color-rgb: 255, 255, 255;
--bs-secondary-color: rgba(173, 181, 189, 0.75);
--bs-secondary-color-rgb: 173, 181, 189;
--bs-secondary-bg: #343a40;
--bs-secondary-bg-rgb: 52, 58, 64;
--bs-tertiary-color: rgba(173, 181, 189, 0.5);
--bs-tertiary-color-rgb: 173, 181, 189;
--bs-tertiary-bg: #2b3035;
--bs-tertiary-bg-rgb: 43, 48, 53;
--bs-primary-text-emphasis: #6ea8fe;
--bs-secondary-text-emphasis: #a7acb1;
--bs-success-text-emphasis: #75b798;
--bs-info-text-emphasis: #6edff6;
--bs-warning-text-emphasis: #ffda6a;
--bs-danger-text-emphasis: #ea868f;
--bs-light-text-emphasis: #f8f9fa;
--bs-dark-text-emphasis: #dee2e6;
--bs-primary-bg-subtle: #031633;
--bs-secondary-bg-subtle: #161719;
--bs-success-bg-subtle: #051b11;
--bs-info-bg-subtle: #032830;
--bs-warning-bg-subtle: #332701;
--bs-danger-bg-subtle: #2c0b0e;
--bs-light-bg-subtle: #343a40;
--bs-dark-bg-subtle: #1a1d20;
--bs-primary-border-subtle: #084298;
--bs-secondary-border-subtle: #41464b;
--bs-success-border-subtle: #0f5132;
--bs-info-border-subtle: #087990;
--bs-warning-border-subtle: #997404;
--bs-danger-border-subtle: #842029;
--bs-light-border-subtle: #495057;
--bs-dark-border-subtle: #343a40;
--bs-link-color: #6ea8fe;
--bs-link-hover-color: #8bb9fe;
--bs-link-color-rgb: 110, 168, 254;
--bs-link-hover-color-rgb: 139, 185, 254;
--bs-code-color: #e685b5;
--bs-border-color: #495057;
--bs-border-color-translucent: rgba(255, 255, 255, 0.15);
--bs-form-valid-color: #75b798;
--bs-form-valid-border-color: #75b798;
--bs-form-invalid-color: #ea868f;
--bs-form-invalid-border-color: #ea868f;
}
*,
*::before,
*::after {
box-sizing: border-box;
}
@media (prefers-reduced-motion: no-preference) {
:root {
scroll-behavior: smooth;
}
}
body {
margin: 0;
font-family: var(--bs-body-font-family);
font-size: var(--bs-body-font-size);
font-weight: var(--bs-body-font-weight);
line-height: var(--bs-body-line-height);
color: var(--bs-body-color);
text-align: var(--bs-body-text-align);
background-color: var(--bs-body-bg);
-webkit-text-size-adjust: 100%;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
}
hr {
margin: 1rem 0;
color: inherit;
border: 0;
border-top: var(--bs-border-width) solid;
opacity: 0.25;
}
h6, h5, h4, h3, h2, h1 {
margin-top: 0;
margin-bottom: 0.5rem;
font-weight: 500;
line-height: 1.2;
color: var(--bs-heading-color, inherit);
}
h1 {
font-size: calc(1.375rem + 1.5vw);
}
@media (min-width: 1200px) {
h1 {
font-size: 2.5rem;
}
}
h2 {
font-size: calc(1.325rem + 0.9vw);
}
@media (min-width: 1200px) {
h2 {
font-size: 2rem;
}
}
h3 {
font-size: calc(1.3rem + 0.6vw);
}
@media (min-width: 1200px) {
h3 {
font-size: 1.75rem;
}
}
h4 {
font-size: calc(1.275rem + 0.3vw);
}
@media (min-width: 1200px) {
h4 {
font-size: 1.5rem;
}
}
h5 {
font-size: 1.25rem;
}
h6 {
font-size: 1rem;
}
p {
margin-top: 0;
margin-bottom: 1rem;
}
abbr[title] {
-webkit-text-decoration: underline dotted;
text-decoration: underline dotted;
cursor: help;
-webkit-text-decoration-skip-ink: none;
text-decoration-skip-ink: none;
}
address {
margin-bottom: 1rem;
font-style: normal;
line-height: inherit;
}
ol,
ul {
padding-left: 2rem;
}
ol,
ul,
dl {
margin-top: 0;
margin-bottom: 1rem;
}
ol ol,
ul ul,
ol ul,
ul ol {
margin-bottom: 0;
}
dt {
font-weight: 700;
}
dd {
margin-bottom: 0.5rem;
margin-left: 0;
}
blockquote {
margin: 0 0 1rem;
}
b,
strong {
font-weight: bolder;
}
small {
font-size: 0.875em;
}
mark {
padding: 0.1875em;
background-color: var(--bs-highlight-bg);
}
sub,
sup {
position: relative;
font-size: 0.75em;
line-height: 0;
vertical-align: baseline;
}
sub {
bottom: -0.25em;
}
sup {
top: -0.5em;
}
a {
color: rgba(var(--bs-link-color-rgb), var(--bs-link-opacity, 1));
text-decoration: underline;
}
a:hover {
--bs-link-color-rgb: var(--bs-link-hover-color-rgb);
}
a:not([href]):not([class]), a:not([href]):not([class]):hover {
color: inherit;
text-decoration: none;
}
pre,
code,
kbd,
samp {
font-family: var(--bs-font-monospace);
font-size: 1em;
}
pre {
display: block;
margin-top: 0;
margin-bottom: 1rem;
overflow: auto;
font-size: 0.875em;
}
pre code {
font-size: inherit;
color: inherit;
word-break: normal;
}
code {
font-size: 0.875em;
color: var(--bs-code-color);
word-wrap: break-word;
}
a > code {
color: inherit;
}
kbd {
padding: 0.1875rem 0.375rem;
font-size: 0.875em;
color: var(--bs-body-bg);
background-color: var(--bs-body-color);
border-radius: 0.25rem;
}
kbd kbd {
padding: 0;
font-size: 1em;
}
figure {
margin: 0 0 1rem;
}
img,
svg {
vertical-align: middle;
}
table {
caption-side: bottom;
border-collapse: collapse;
}
caption {
padding-top: 0.5rem;
padding-bottom: 0.5rem;
color: var(--bs-secondary-color);
text-align: left;
}
th {
text-align: inherit;
text-align: -webkit-match-parent;
}
thead,
tbody,
tfoot,
tr,
td,
th {
border-color: inherit;
border-style: solid;
border-width: 0;
}
label {
display: inline-block;
}
button {
border-radius: 0;
}
button:focus:not(:focus-visible) {
outline: 0;
}
input,
button,
select,
optgroup,
textarea {
margin: 0;
font-family: inherit;
font-size: inherit;
line-height: inherit;
}
button,
select {
text-transform: none;
}
[role=button] {
cursor: pointer;
}
select {
word-wrap: normal;
}
select:disabled {
opacity: 1;
}
[list]:not([type=date]):not([type=datetime-local]):not([type=month]):not([type=week]):not([type=time])::-webkit-calendar-picker-indicator {
display: none !important;
}
button,
[type=button],
[type=reset],
[type=submit] {
-webkit-appearance: button;
}
button:not(:disabled),
[type=button]:not(:disabled),
[type=reset]:not(:disabled),
[type=submit]:not(:disabled) {
cursor: pointer;
}
::-moz-focus-inner {
padding: 0;
border-style: none;
}
textarea {
resize: vertical;
}
fieldset {
min-width: 0;
padding: 0;
margin: 0;
border: 0;
}
legend {
float: left;
width: 100%;
padding: 0;
margin-bottom: 0.5rem;
font-size: calc(1.275rem + 0.3vw);
line-height: inherit;
}
@media (min-width: 1200px) {
legend {
font-size: 1.5rem;
}
}
legend + * {
clear: left;
}
::-webkit-datetime-edit-fields-wrapper,
::-webkit-datetime-edit-text,
::-webkit-datetime-edit-minute,
::-webkit-datetime-edit-hour-field,
::-webkit-datetime-edit-day-field,
::-webkit-datetime-edit-month-field,
::-webkit-datetime-edit-year-field {
padding: 0;
}
::-webkit-inner-spin-button {
height: auto;
}
[type=search] {
outline-offset: -2px;
-webkit-appearance: textfield;
}
/* rtl:raw:
[type="tel"],
[type="url"],
[type="email"],
[type="number"] {
direction: ltr;
}
*/
::-webkit-search-decoration {
-webkit-appearance: none;
}
::-webkit-color-swatch-wrapper {
padding: 0;
}
::-webkit-file-upload-button {
font: inherit;
-webkit-appearance: button;
}
::file-selector-button {
font: inherit;
-webkit-appearance: button;
}
output {
display: inline-block;
}
iframe {
border: 0;
}
summary {
display: list-item;
cursor: pointer;
}
progress {
vertical-align: baseline;
}
[hidden] {
display: none !important;
}
/*# sourceMappingURL=bootstrap-reboot.css.map */

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,588 @@
/*!
* Bootstrap Reboot v5.3.0-alpha3 (https://getbootstrap.com/)
* Copyright 2011-2023 The Bootstrap Authors
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
*/
:root,
[data-bs-theme=light] {
--bs-blue: #0d6efd;
--bs-indigo: #6610f2;
--bs-purple: #6f42c1;
--bs-pink: #d63384;
--bs-red: #dc3545;
--bs-orange: #fd7e14;
--bs-yellow: #ffc107;
--bs-green: #198754;
--bs-teal: #20c997;
--bs-cyan: #0dcaf0;
--bs-black: #000;
--bs-white: #fff;
--bs-gray: #6c757d;
--bs-gray-dark: #343a40;
--bs-gray-100: #f8f9fa;
--bs-gray-200: #e9ecef;
--bs-gray-300: #dee2e6;
--bs-gray-400: #ced4da;
--bs-gray-500: #adb5bd;
--bs-gray-600: #6c757d;
--bs-gray-700: #495057;
--bs-gray-800: #343a40;
--bs-gray-900: #212529;
--bs-primary: #0d6efd;
--bs-secondary: #6c757d;
--bs-success: #198754;
--bs-info: #0dcaf0;
--bs-warning: #ffc107;
--bs-danger: #dc3545;
--bs-light: #f8f9fa;
--bs-dark: #212529;
--bs-primary-rgb: 13, 110, 253;
--bs-secondary-rgb: 108, 117, 125;
--bs-success-rgb: 25, 135, 84;
--bs-info-rgb: 13, 202, 240;
--bs-warning-rgb: 255, 193, 7;
--bs-danger-rgb: 220, 53, 69;
--bs-light-rgb: 248, 249, 250;
--bs-dark-rgb: 33, 37, 41;
--bs-primary-text-emphasis: #052c65;
--bs-secondary-text-emphasis: #2b2f32;
--bs-success-text-emphasis: #0a3622;
--bs-info-text-emphasis: #055160;
--bs-warning-text-emphasis: #664d03;
--bs-danger-text-emphasis: #58151c;
--bs-light-text-emphasis: #495057;
--bs-dark-text-emphasis: #495057;
--bs-primary-bg-subtle: #cfe2ff;
--bs-secondary-bg-subtle: #e2e3e5;
--bs-success-bg-subtle: #d1e7dd;
--bs-info-bg-subtle: #cff4fc;
--bs-warning-bg-subtle: #fff3cd;
--bs-danger-bg-subtle: #f8d7da;
--bs-light-bg-subtle: #fcfcfd;
--bs-dark-bg-subtle: #ced4da;
--bs-primary-border-subtle: #9ec5fe;
--bs-secondary-border-subtle: #c4c8cb;
--bs-success-border-subtle: #a3cfbb;
--bs-info-border-subtle: #9eeaf9;
--bs-warning-border-subtle: #ffe69c;
--bs-danger-border-subtle: #f1aeb5;
--bs-light-border-subtle: #e9ecef;
--bs-dark-border-subtle: #adb5bd;
--bs-white-rgb: 255, 255, 255;
--bs-black-rgb: 0, 0, 0;
--bs-font-sans-serif: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", "Liberation Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
--bs-font-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
--bs-gradient: linear-gradient(180deg, rgba(255, 255, 255, 0.15), rgba(255, 255, 255, 0));
--bs-body-font-family: var(--bs-font-sans-serif);
--bs-body-font-size: 1rem;
--bs-body-font-weight: 400;
--bs-body-line-height: 1.5;
--bs-body-color: #212529;
--bs-body-color-rgb: 33, 37, 41;
--bs-body-bg: #fff;
--bs-body-bg-rgb: 255, 255, 255;
--bs-emphasis-color: #000;
--bs-emphasis-color-rgb: 0, 0, 0;
--bs-secondary-color: rgba(33, 37, 41, 0.75);
--bs-secondary-color-rgb: 33, 37, 41;
--bs-secondary-bg: #e9ecef;
--bs-secondary-bg-rgb: 233, 236, 239;
--bs-tertiary-color: rgba(33, 37, 41, 0.5);
--bs-tertiary-color-rgb: 33, 37, 41;
--bs-tertiary-bg: #f8f9fa;
--bs-tertiary-bg-rgb: 248, 249, 250;
--bs-link-color: #0d6efd;
--bs-link-color-rgb: 13, 110, 253;
--bs-link-decoration: underline;
--bs-link-hover-color: #0a58ca;
--bs-link-hover-color-rgb: 10, 88, 202;
--bs-code-color: #d63384;
--bs-highlight-bg: #fff3cd;
--bs-border-width: 1px;
--bs-border-style: solid;
--bs-border-color: #dee2e6;
--bs-border-color-translucent: rgba(0, 0, 0, 0.175);
--bs-border-radius: 0.375rem;
--bs-border-radius-sm: 0.25rem;
--bs-border-radius-lg: 0.5rem;
--bs-border-radius-xl: 1rem;
--bs-border-radius-xxl: 2rem;
--bs-border-radius-2xl: var(--bs-border-radius-xxl);
--bs-border-radius-pill: 50rem;
--bs-box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15);
--bs-box-shadow-sm: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075);
--bs-box-shadow-lg: 0 1rem 3rem rgba(0, 0, 0, 0.175);
--bs-box-shadow-inset: inset 0 1px 2px rgba(0, 0, 0, 0.075);
--bs-focus-ring-width: 0.25rem;
--bs-focus-ring-opacity: 0.25;
--bs-focus-ring-color: rgba(13, 110, 253, 0.25);
--bs-form-valid-color: #198754;
--bs-form-valid-border-color: #198754;
--bs-form-invalid-color: #dc3545;
--bs-form-invalid-border-color: #dc3545;
}
[data-bs-theme=dark] {
color-scheme: dark;
--bs-body-color: #adb5bd;
--bs-body-color-rgb: 173, 181, 189;
--bs-body-bg: #212529;
--bs-body-bg-rgb: 33, 37, 41;
--bs-emphasis-color: #fff;
--bs-emphasis-color-rgb: 255, 255, 255;
--bs-secondary-color: rgba(173, 181, 189, 0.75);
--bs-secondary-color-rgb: 173, 181, 189;
--bs-secondary-bg: #343a40;
--bs-secondary-bg-rgb: 52, 58, 64;
--bs-tertiary-color: rgba(173, 181, 189, 0.5);
--bs-tertiary-color-rgb: 173, 181, 189;
--bs-tertiary-bg: #2b3035;
--bs-tertiary-bg-rgb: 43, 48, 53;
--bs-primary-text-emphasis: #6ea8fe;
--bs-secondary-text-emphasis: #a7acb1;
--bs-success-text-emphasis: #75b798;
--bs-info-text-emphasis: #6edff6;
--bs-warning-text-emphasis: #ffda6a;
--bs-danger-text-emphasis: #ea868f;
--bs-light-text-emphasis: #f8f9fa;
--bs-dark-text-emphasis: #dee2e6;
--bs-primary-bg-subtle: #031633;
--bs-secondary-bg-subtle: #161719;
--bs-success-bg-subtle: #051b11;
--bs-info-bg-subtle: #032830;
--bs-warning-bg-subtle: #332701;
--bs-danger-bg-subtle: #2c0b0e;
--bs-light-bg-subtle: #343a40;
--bs-dark-bg-subtle: #1a1d20;
--bs-primary-border-subtle: #084298;
--bs-secondary-border-subtle: #41464b;
--bs-success-border-subtle: #0f5132;
--bs-info-border-subtle: #087990;
--bs-warning-border-subtle: #997404;
--bs-danger-border-subtle: #842029;
--bs-light-border-subtle: #495057;
--bs-dark-border-subtle: #343a40;
--bs-link-color: #6ea8fe;
--bs-link-hover-color: #8bb9fe;
--bs-link-color-rgb: 110, 168, 254;
--bs-link-hover-color-rgb: 139, 185, 254;
--bs-code-color: #e685b5;
--bs-border-color: #495057;
--bs-border-color-translucent: rgba(255, 255, 255, 0.15);
--bs-form-valid-color: #75b798;
--bs-form-valid-border-color: #75b798;
--bs-form-invalid-color: #ea868f;
--bs-form-invalid-border-color: #ea868f;
}
*,
*::before,
*::after {
box-sizing: border-box;
}
@media (prefers-reduced-motion: no-preference) {
:root {
scroll-behavior: smooth;
}
}
body {
margin: 0;
font-family: var(--bs-body-font-family);
font-size: var(--bs-body-font-size);
font-weight: var(--bs-body-font-weight);
line-height: var(--bs-body-line-height);
color: var(--bs-body-color);
text-align: var(--bs-body-text-align);
background-color: var(--bs-body-bg);
-webkit-text-size-adjust: 100%;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
}
hr {
margin: 1rem 0;
color: inherit;
border: 0;
border-top: var(--bs-border-width) solid;
opacity: 0.25;
}
h6, h5, h4, h3, h2, h1 {
margin-top: 0;
margin-bottom: 0.5rem;
font-weight: 500;
line-height: 1.2;
color: var(--bs-heading-color, inherit);
}
h1 {
font-size: calc(1.375rem + 1.5vw);
}
@media (min-width: 1200px) {
h1 {
font-size: 2.5rem;
}
}
h2 {
font-size: calc(1.325rem + 0.9vw);
}
@media (min-width: 1200px) {
h2 {
font-size: 2rem;
}
}
h3 {
font-size: calc(1.3rem + 0.6vw);
}
@media (min-width: 1200px) {
h3 {
font-size: 1.75rem;
}
}
h4 {
font-size: calc(1.275rem + 0.3vw);
}
@media (min-width: 1200px) {
h4 {
font-size: 1.5rem;
}
}
h5 {
font-size: 1.25rem;
}
h6 {
font-size: 1rem;
}
p {
margin-top: 0;
margin-bottom: 1rem;
}
abbr[title] {
-webkit-text-decoration: underline dotted;
text-decoration: underline dotted;
cursor: help;
-webkit-text-decoration-skip-ink: none;
text-decoration-skip-ink: none;
}
address {
margin-bottom: 1rem;
font-style: normal;
line-height: inherit;
}
ol,
ul {
padding-right: 2rem;
}
ol,
ul,
dl {
margin-top: 0;
margin-bottom: 1rem;
}
ol ol,
ul ul,
ol ul,
ul ol {
margin-bottom: 0;
}
dt {
font-weight: 700;
}
dd {
margin-bottom: 0.5rem;
margin-right: 0;
}
blockquote {
margin: 0 0 1rem;
}
b,
strong {
font-weight: bolder;
}
small {
font-size: 0.875em;
}
mark {
padding: 0.1875em;
background-color: var(--bs-highlight-bg);
}
sub,
sup {
position: relative;
font-size: 0.75em;
line-height: 0;
vertical-align: baseline;
}
sub {
bottom: -0.25em;
}
sup {
top: -0.5em;
}
a {
color: rgba(var(--bs-link-color-rgb), var(--bs-link-opacity, 1));
text-decoration: underline;
}
a:hover {
--bs-link-color-rgb: var(--bs-link-hover-color-rgb);
}
a:not([href]):not([class]), a:not([href]):not([class]):hover {
color: inherit;
text-decoration: none;
}
pre,
code,
kbd,
samp {
font-family: var(--bs-font-monospace);
font-size: 1em;
}
pre {
display: block;
margin-top: 0;
margin-bottom: 1rem;
overflow: auto;
font-size: 0.875em;
}
pre code {
font-size: inherit;
color: inherit;
word-break: normal;
}
code {
font-size: 0.875em;
color: var(--bs-code-color);
word-wrap: break-word;
}
a > code {
color: inherit;
}
kbd {
padding: 0.1875rem 0.375rem;
font-size: 0.875em;
color: var(--bs-body-bg);
background-color: var(--bs-body-color);
border-radius: 0.25rem;
}
kbd kbd {
padding: 0;
font-size: 1em;
}
figure {
margin: 0 0 1rem;
}
img,
svg {
vertical-align: middle;
}
table {
caption-side: bottom;
border-collapse: collapse;
}
caption {
padding-top: 0.5rem;
padding-bottom: 0.5rem;
color: var(--bs-secondary-color);
text-align: right;
}
th {
text-align: inherit;
text-align: -webkit-match-parent;
}
thead,
tbody,
tfoot,
tr,
td,
th {
border-color: inherit;
border-style: solid;
border-width: 0;
}
label {
display: inline-block;
}
button {
border-radius: 0;
}
button:focus:not(:focus-visible) {
outline: 0;
}
input,
button,
select,
optgroup,
textarea {
margin: 0;
font-family: inherit;
font-size: inherit;
line-height: inherit;
}
button,
select {
text-transform: none;
}
[role=button] {
cursor: pointer;
}
select {
word-wrap: normal;
}
select:disabled {
opacity: 1;
}
[list]:not([type=date]):not([type=datetime-local]):not([type=month]):not([type=week]):not([type=time])::-webkit-calendar-picker-indicator {
display: none !important;
}
button,
[type=button],
[type=reset],
[type=submit] {
-webkit-appearance: button;
}
button:not(:disabled),
[type=button]:not(:disabled),
[type=reset]:not(:disabled),
[type=submit]:not(:disabled) {
cursor: pointer;
}
::-moz-focus-inner {
padding: 0;
border-style: none;
}
textarea {
resize: vertical;
}
fieldset {
min-width: 0;
padding: 0;
margin: 0;
border: 0;
}
legend {
float: right;
width: 100%;
padding: 0;
margin-bottom: 0.5rem;
font-size: calc(1.275rem + 0.3vw);
line-height: inherit;
}
@media (min-width: 1200px) {
legend {
font-size: 1.5rem;
}
}
legend + * {
clear: right;
}
::-webkit-datetime-edit-fields-wrapper,
::-webkit-datetime-edit-text,
::-webkit-datetime-edit-minute,
::-webkit-datetime-edit-hour-field,
::-webkit-datetime-edit-day-field,
::-webkit-datetime-edit-month-field,
::-webkit-datetime-edit-year-field {
padding: 0;
}
::-webkit-inner-spin-button {
height: auto;
}
[type=search] {
outline-offset: -2px;
-webkit-appearance: textfield;
}
[type="tel"],
[type="url"],
[type="email"],
[type="number"] {
direction: ltr;
}
::-webkit-search-decoration {
-webkit-appearance: none;
}
::-webkit-color-swatch-wrapper {
padding: 0;
}
::-webkit-file-upload-button {
font: inherit;
-webkit-appearance: button;
}
::file-selector-button {
font: inherit;
-webkit-appearance: button;
}
output {
display: inline-block;
}
iframe {
border: 0;
}
summary {
display: list-item;
cursor: pointer;
}
progress {
vertical-align: baseline;
}
[hidden] {
display: none !important;
}
/*# sourceMappingURL=bootstrap-reboot.rtl.css.map */

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

12113
assets/bootstrap/css/bootstrap.css vendored Normal file

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

12077
assets/bootstrap/css/bootstrap.rtl.css vendored Normal file

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

6295
assets/bootstrap/js/bootstrap.bundle.js vendored Normal file

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

4423
assets/bootstrap/js/bootstrap.esm.js vendored Normal file

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

4469
assets/bootstrap/js/bootstrap.js vendored Normal file

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

7
assets/bootstrap/js/bootstrap.min.js vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

15
assets/email.js Normal file
View file

@ -0,0 +1,15 @@
// This code de-obfuscates my email and displays it on screen when the button is clicked
// It's not a perfect solution, but it should stop be enough to stop email scraping
// Email encoded in base64. This might be changed in the future to prevent scraping targeting base64 strings
const email = "Y29udGFjdEBvd2Vucnlhbi51cwo=";
document.addEventListener("DOMContentLoaded", function () {
// Get document elements
const button = document.querySelector("#emailButton");
const emailDiv = document.querySelector("#email");
// Decode the email string and insert a mailto link into the DOM, then disable the button
button.addEventListener("click", function () {
const decodedEmail = atob(email);
emailDiv.insertAdjacentHTML("beforeend", "<div class=\"col\"><a href=\"mailto:".concat(decodedEmail, "\"><strong>").concat(decodedEmail, "</strong></a></div>"));
button.disabled = true;
});
});

17
assets/email.ts Normal file
View file

@ -0,0 +1,17 @@
// This code de-obfuscates my email and displays it on screen when the button is clicked
// It's not a perfect solution, but it should stop be enough to stop email scraping
// Email encoded in base64. This might be changed in the future to prevent scraping targeting base64 strings
const email: string = "Y29udGFjdEBvd2Vucnlhbi51cwo=";
document.addEventListener("DOMContentLoaded", () => {
// Get document elements
const button: HTMLButtonElement = document.querySelector("#emailButton");
const emailDiv: HTMLDivElement = document.querySelector("#email");
// Decode the email string and insert a mailto link into the DOM, then disable the button
button.addEventListener("click", () => {
const decodedEmail: string = atob(email);
emailDiv.insertAdjacentHTML("beforeend", `<div class="col"><a href="mailto:${decodedEmail}"><strong>${decodedEmail}</strong></a></div>`);
button.disabled = true;
})
});

Binary file not shown.

After

Width:  |  Height:  |  Size: 1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1,017 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

BIN
assets/images/jambox.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 169 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 106 KiB

BIN
assets/images/website.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

14
assets/landingpage.js Normal file
View file

@ -0,0 +1,14 @@
// JS Code that rotates the gradient on the content box on the front page
document.addEventListener("DOMContentLoaded", function () {
const mainBox = document.querySelector("#rotating-gradient");
let angle = 0;
// Rotate the gradient 1 degree every 100ms
setInterval(function () {
const gradient = "linear-gradient(".concat(angle, "deg, #1E1F46, #404040)");
mainBox.style["background"] = gradient;
angle += 1;
if (angle >= 360) {
angle = 0;
}
}, 100);
});

16
assets/landingpage.ts Normal file
View file

@ -0,0 +1,16 @@
// JS Code that rotates the gradient on the content box on the front page
document.addEventListener("DOMContentLoaded", (): void => {
const mainBox: HTMLDivElement = document.querySelector("#rotating-gradient");
let angle: number = 0;
// Rotate the gradient 1 degree every 100ms
setInterval((): void => {
const gradient: string = `linear-gradient(${angle}deg, #1E1F46, #404040)`;
mainBox.style["background"] = gradient;
angle += 1;
if (angle >= 360) {
angle = 0
}
}, 100);
});

9
assets/utils.js Normal file
View file

@ -0,0 +1,9 @@
// Some useful functions used throughout my code
// Based on this SO answer https://stackoverflow.com/a/35880730/9523246
function lazyLoadCSS(url) {
const css = document.createElement('link');
css.href = url;
css.rel = 'stylesheet';
css.type = 'text/css';
document.getElementsByTagName('head')[0].appendChild(css);
}

10
assets/utils.ts Normal file
View file

@ -0,0 +1,10 @@
// Some useful functions used throughout my code
// Based on this SO answer https://stackoverflow.com/a/35880730/9523246
function lazyLoadCSS(url: string): void {
const css: HTMLLinkElement = document.createElement('link');
css.href = url;
css.rel = 'stylesheet';
css.type = 'text/css';
document.getElementsByTagName('head')[0].appendChild(css);
}

Binary file not shown.

18
contact.html Normal file
View file

@ -0,0 +1,18 @@
---
layout: main
permalink: /contact
---
<div class="container">
<div class="row">
<p>Thank you for choosing to contact me!</p>
<p>To prevent email scraping, my contact email is hidden behind this button.</p>
</div>
<div id="email" class="row d-inline-flex">
<div class="col">
<button id="emailButton" type="button" class="btn btn-primary">Get contact email</button>
</div>
</div>
</div>
<script src="/assets/email.js"></script>

7
css/style.scss Normal file
View file

@ -0,0 +1,7 @@
---
# Convert SASS into CSS
# Source: https://avic.devpractical.com/jekyll-sass/
---
// Imports styles in the file located at _sass/style.sass
@import "style.sass";

BIN
favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

17
homepage.gemspec Normal file
View file

@ -0,0 +1,17 @@
# frozen_string_literal: true
Gem::Specification.new do |spec|
spec.name = "homepage"
spec.version = "0.1.0"
spec.authors = ["Owen Ryan"]
spec.email = ["owen@owenryan.us"]
spec.summary = "Jekyll theme used for owenryan.us"
spec.homepage = "https://code.owenryan.us/owenryan/owenryan.us"
spec.license = "MIT"
spec.files = `git ls-files -z`.split("\x0").select { |f| f.match(%r!^(assets|_data|_layouts|_includes|_sass|LICENSE|README|_config\.yml)!i) }
spec.add_runtime_dependency "jekyll", "~> 4.3"
spec.add_runtime_dependency "jekyll-sass-converter", "~> 3.0"
end

14
index.html Normal file
View file

@ -0,0 +1,14 @@
---
layout: main
---
<div class="container my-5">
<div id="rotating-gradient" class="col-7 p-5 text-center rounded-3 position-absolute top-50 start-50 translate-middle">
<h1 class="text-body-emphasis">Hello there!</h1>
<p class="col-lg-8 mx-auto fs-5 text-muted">Welcome to my website!</p>
{% include social-media-icons.html %}
</div>
</div>
<script src="/assets/landingpage.js"></script>

22
projects.html Normal file
View file

@ -0,0 +1,22 @@
---
layout: main
permalink: /projects
---
<div class="container">
<div class="row">
{%- for post in site.posts -%}
<div class="col p-2">
<div class="card project-card">
{%- if post.thumbnail_url -%}
<img src="{{ post.thumbnail_url }}" class="card-img-top" alt="{{ post.title }} thumbnail">
{%- endif -%}
<div class="card-body">
<a class="card-title text-body-emphasis" href="{{ post.url }}">{{ post.title }}</a>
<p class="card-text">{{ post.description }}</p>
</div>
</div>
</div>
{%- endfor -%}
</div>
</div>