/*! modern-normalize v3.0.1 | MIT License | https://github.com/sindresorhus/modern-normalize */
/*
Document
========
*/
/**
Use a better box model (opinionated).
*/
*,
::before,
::after {
  box-sizing: border-box;
}

/**
1. Improve consistency of default fonts in all browsers. (https://github.com/sindresorhus/modern-normalize/issues/3)
2. Correct the line height in all browsers.
3. Prevent adjustments of font size after orientation changes in iOS.
4. Use a more readable tab size (opinionated).
*/
html {
  font-family: system-ui, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji"; /* 1 */
  line-height: 1.15; /* 2 */
  -webkit-text-size-adjust: 100%; /* 3 */
  -moz-tab-size: 4;
    -o-tab-size: 4;
       tab-size: 4; /* 4 */
}

/*
Sections
========
*/
/**
Remove the margin in all browsers.
*/
body {
  margin: 0;
}

/*
Text-level semantics
====================
*/
/**
Add the correct font weight in Chrome and Safari.
*/
b,
strong {
  font-weight: bolder;
}

/**
1. Improve consistency of default fonts in all browsers. (https://github.com/sindresorhus/modern-normalize/issues/3)
2. Correct the odd 'em' font sizing in all browsers.
*/
code,
kbd,
samp,
pre {
  font-family: ui-monospace, SFMono-Regular, Consolas, "Liberation Mono", Menlo, monospace; /* 1 */
  font-size: 1em; /* 2 */
}

/**
Add the correct font size in all browsers.
*/
small {
  font-size: 80%;
}

/**
Prevent 'sub' and 'sup' elements from affecting the line height in all browsers.
*/
sub,
sup {
  font-size: 75%;
  line-height: 0;
  position: relative;
  vertical-align: baseline;
}

sub {
  bottom: -0.25em;
}

sup {
  top: -0.5em;
}

/*
Tabular data
============
*/
/**
Correct table border color inheritance in Chrome and Safari. (https://issues.chromium.org/issues/40615503, https://bugs.webkit.org/show_bug.cgi?id=195016)
*/
table {
  border-color: currentcolor;
}

/*
Forms
=====
*/
/**
1. Change the font styles in all browsers.
2. Remove the margin in Firefox and Safari.
*/
button,
input,
optgroup,
select,
textarea {
  font-family: inherit; /* 1 */
  font-size: 100%; /* 1 */
  line-height: 1.15; /* 1 */
  margin: 0; /* 2 */
}

/**
Correct the inability to style clickable types in iOS and Safari.
*/
button,
[type=button],
[type=reset],
[type=submit] {
  -webkit-appearance: button;
}

/**
Remove the padding so developers are not caught out when they zero out 'fieldset' elements in all browsers.
*/
legend {
  padding: 0;
}

/**
Add the correct vertical alignment in Chrome and Firefox.
*/
progress {
  vertical-align: baseline;
}

/**
Correct the cursor style of increment and decrement buttons in Safari.
*/
::-webkit-inner-spin-button,
::-webkit-outer-spin-button {
  height: auto;
}

/**
1. Correct the odd appearance in Chrome and Safari.
2. Correct the outline style in Safari.
*/
[type=search] {
  -webkit-appearance: textfield; /* 1 */
  outline-offset: -2px; /* 2 */
}

/**
Remove the inner padding in Chrome and Safari on macOS.
*/
::-webkit-search-decoration {
  -webkit-appearance: none;
}

/**
1. Correct the inability to style clickable types in iOS and Safari.
2. Change font properties to 'inherit' in Safari.
*/
::-webkit-file-upload-button {
  -webkit-appearance: button; /* 1 */
  font: inherit; /* 2 */
}

/*
Interactive
===========
*/
/*
Add the correct display in Chrome and Safari.
*/
summary {
  display: list-item;
}

/**
 * Reset margins to selectively add them back later.
 */
h1, h2, h3, h4, h5, h6, figure, p, ol, ul {
  margin: 0;
}

/**
 * If an ol/ul has their list style removed, it tends to remove the implicit
 * role used by screen readers.
 * 1. Reset margins applied to regular list items.
 */
ol[role=list], ul[role=list] {
  list-style: none;
  padding-inline: 0;
}
ol[role=list] li, ul[role=list] li {
  margin: 0; /* 1 */
}

/**
 * Reset typography for a blank slate.
 */
h1, h2, h3, h4, h5, h6 {
  font-size: inherit;
  font-weight: inherit;
}

/**
 * Limit max width/height (depending on writing mode) to container size.
 * 1. Make images responsive and maintain aspect ratio
 */
img {
  display: block;
  max-inline-size: 100%;
  block-size: auto; /* 1 */
}

/**
 * Custom property to allow header gradients to be animated.
 * Default value is the banner color at 100% opacity.
 */
@property --gradient-100 {
  syntax: "<color>";
  initial-value: hsl(from hsl(240, 6.25%, 17.75%) h s l/1);
  inherits: true;
}
/**
 * Custom property to allow header gradients to be animated.
 * Default value is the banner color at 90% opacity.
 */
@property --gradient-90 {
  syntax: "<color>";
  initial-value: hsl(from hsl(240, 6.25%, 17.75%) h s l/0.9);
  inherits: true;
}
/**
 * Custom property to allow header gradients to be animated.
 * Default value is the banner color at 70% opacity.
 */
@property --gradient-70 {
  syntax: "<color>";
  initial-value: hsl(from hsl(240, 6.25%, 17.75%) h s l/0.7);
  inherits: true;
}
/**
 * Custom property to allow header gradients to be animated.
 * Default value is the banner color at 0% opacity.
 */
@property --gradient-00 {
  syntax: "<color>";
  initial-value: hsl(from hsl(240, 6.25%, 17.75%) h s l/0);
  inherits: true;
}
/**
 * Custom property to allow gradients to be animated.
 * Default value is the opposing theme's background color at 50% opacity.
 */
@property --gradient-shadow {
  syntax: "<color>";
  initial-value: hsl(from hsl(240, 6.25%, 100%) h s l/0.5);
  inherits: true;
}
/**
 * Custom property to allow gradients to be animated.
 * Default value is the background color at 100% opacity.
 */
@property --gradient-bg {
  syntax: "<color>";
  initial-value: hsl(from hsl(240, 6.25%, 12.5%) h s l/1);
  inherits: true;
}
/**
 * Baseline root styles.
 * 1. Breaks words that are too big for the container, helps make sure the grid
 *    doesn't break.
 */
:root {
  overflow-wrap: break-word; /* 1 */
}
@media (prefers-reduced-motion: no-preference) {
  :root {
    scroll-behavior: smooth;
  }
}
:root {
  --duration: 100ms;
  --max-weight: 800;
  --base-weight: 300;
  --content-margin: 1.5rem;
}
@media screen and (max-width: 43rem) {
  :root {
    --content-margin: 0rem;
  }
}

/**
 * Theme-related root styles.
 * 1. Dark scheme is preferred, reflected in meta tags.
 */
:root {
  color-scheme: dark; /* 1 */
  --background: hsl(240, 6.25%, 12.5%);
  --shade-1: hsl(240, 6.25%, 17.75%);
  --shade-2: hsl(240, 6.25%, 23%);
  --shade-3: hsl(240, 6.25%, 28.25%);
  --shade-4: hsl(240, 6.25%, 33.5%);
  --shade-5: hsl(240, 6.25%, 38.75%);
  --banner: hsl(240, 6.25%, 17.75%);
  --banner-alt: hsl(240, 6.25%, 33.5%);
  --highlight: hsl(184, 100%, 50%);
  --link: hsl(30, 100%, 60%);
  --active: hsl(184, 100%, 27%);
  --secondary: hsl(240, 6.25%, 88%);
  --secondary-alt: hsl(240, 6.25%, 94%);
  --text: hsl(240, 6.25%, 100%);
  --opposite: hsl(240, 6.25%, 100%);
  --absolute: hsl(240, 6.25%, 0%);
  --kbd-shade: hsla(240, 6.25%, 38.75%, 0.7);
  --gradient-bg: hsl(240, 6.25%, 12.5%);
  --gradient-shadow: hsla(240, 6.25%, 100%, 0.5);
  --project-links-bg: hsla(240, 6.25%, 17.75%, 0.9);
  --gradient-100: hsl(240, 6.25%, 17.75%);
  --gradient-90: hsla(240, 6.25%, 17.75%, 0.9);
  --gradient-70: hsla(240, 6.25%, 17.75%, 0.7);
  --gradient-00: hsla(240, 6.25%, 17.75%, 0);
}
:root[data-theme=light] {
  color-scheme: light;
  --background: hsl(240, 6.25%, 100%);
  --shade-1: hsl(240, 6.25%, 94%);
  --shade-2: hsl(240, 6.25%, 88%);
  --shade-3: hsl(240, 6.25%, 82%);
  --shade-4: hsl(240, 6.25%, 76%);
  --shade-5: hsl(240, 6.25%, 70%);
  --banner: hsl(240, 6.25%, 88%);
  --banner-alt: hsl(240, 6.25%, 82%);
  --highlight: hsl(184, 100%, 27%);
  --link: hsl(18, 100%, 42%);
  --active: hsl(184, 100%, 17.28%);
  --secondary: hsl(240, 6.25%, 23%);
  --secondary-alt: hsl(240, 6.25%, 17.75%);
  --text: hsl(240, 6.25%, 23%);
  --opposite: hsl(240, 6.25%, 0%);
  --absolute: hsl(240, 6.25%, 100%);
  --kbd-shade: hsla(240, 6.25%, 100%, 0.7);
  --gradient-bg: hsl(240, 6.25%, 100%);
  --gradient-shadow: hsla(240, 6.25%, 12.5%, 0.5);
  --project-links-bg: hsla(240, 6.25%, 94%, 0.9);
  --gradient-100: hsl(240, 6.25%, 23%);
  --gradient-90: hsla(240, 6.25%, 23%, 0.9);
  --gradient-70: hsla(240, 6.25%, 23%, 0.7);
  --gradient-00: hsla(240, 6.25%, 23%, 0);
}

body {
  background-color: var(--background);
  transition: background-color var(--duration);
}

/**
 * Generic link styles.
 */
a {
  color: var(--link);
  transition-property: color, -webkit-text-decoration;
  transition-property: color, text-decoration;
  transition-property: color, text-decoration, -webkit-text-decoration;
  transition-duration: var(--duration);
  font-weight: calc(var(--base-weight) + 200);
  -webkit-text-decoration: underline from-font;
          text-decoration: underline from-font;
  text-underline-position: from-font;
}

/**
 * When a includes a highlight that doesn't want the underline, we separate the
 * link text into two spans. We want to inherit the important styles from the
 * the parent.
 */
a span {
  transition: inherit;
  font-weight: inherit;
  text-decoration: inherit;
  text-decoration-color: inherit;
  text-underline-position: inherit;
}

/**
 * Extra specificity with fake classes to make sure the effects get added
 * properly.
 * 1. Apply color changes to any highlights that are part of the link.
 * 2. If the link has NO highlights, apply the decoration styles normally.
 * 3. Apply text decoration styles ONLY to the link text, and not any spans that
 *    are highlights.
 */
a:not(.specificity):focus:not(:has(> .highlight)) {
  text-decoration-color: currentColor; /* 2 */
}
a:not(.specificity):focus :not(.highlight) {
  text-decoration-color: currentColor; /* 3 */
}
a:not(.specificity):focus, a:not(.specificity):focus .highlight { /* 1 */
  color: var(--highlight);
}
@media (hover: hover) {
  a:not(.specificity):hover:not(:has(> .highlight)) {
    text-decoration-color: currentColor; /* 2 */
  }
  a:not(.specificity):hover :not(.highlight) {
    text-decoration-color: currentColor; /* 3 */
  }
  a:not(.specificity):hover, a:not(.specificity):hover .highlight { /* 1 */
    color: var(--highlight);
  }
}
a:not(.specificity):active, a:not(.specificity):active .highlight { /* 1 */
  color: var(--active);
}

a.skip {
  position: absolute;
  overflow: hidden;
  inset-block-start: 0;
  inset-inline: -9999rem auto;
  z-index: 10;
  padding: 1rlh;
  font-size: 1.25rem;
  font-weight: calc(var(--base-weight) + 300);
  background-color: var(--banner);
}
a.skip:focus {
  inset-inline-start: 0;
}

/**
 * Set accent color on supported inputs (checkbox, radio, and range). Browser
 * support is Limited Availability, so we'll wrap it in a media query for now.
 */
@supports (accent-color: var(--link)) {
  input {
    accent-color: var(--link);
  }
}
/**
 * Abbreviations
 */
abbr {
  font-variant-caps: normal;
}
abbr[title] {
  cursor: help;
  -webkit-text-decoration: underline dotted from-font;
          text-decoration: underline dotted from-font;
  text-underline-position: from-font;
}

/**
 * Set base font size and line height according to WCAG criteria.
 */
:root {
  font-size: 100%;
  line-height: 1.5;
}

/**
 * Default styling for all text. These values are inherited by children.
 */
body {
  font-family: "Inter", sans-serif;
  font-weight: var(--base-weight);
  font-optical-sizing: auto;
  font-style: normal;
  color: var(--text);
}

/**
 * Default styles for ALL headings.
 */
:is(h1, h2, h3, h4, h5, h6), :is(.h1, .h2, .h3, .h4, .h5, .h6) {
  font-family: "JetBrains Mono", monospace;
  font-weight: var(--max-weight);
  margin: 0;
  transition-property: color;
  transition-duration: var(--duration);
}

/**
 * H1 specific styles.
 * 1. If it has any sibling directly touching it, ensure a bottom margin.
 */
:is(h1, .h1):has(+ *) {
  margin-block-end: 0.5rlh; /* 1 */
}

/**
 * Styling for headings that have a solid background (banner).
 */
:is(h2, h3), :is(.h2, .h3) {
  background-color: var(--banner);
  transition-property: background-color, color;
  transition-duration: var(--duration);
  line-height: 1;
  padding: 0.5rlh 1.5rem;
  margin-block-end: 0.5rlh;
}
@media screen and (max-width: 43rem) {
  :is(h2, h3), :is(.h2, .h3) {
    padding-inline: 1rlh;
    margin-inline: -1rlh;
  }
}

:is(h4, h5, h6), :is(.h4, .h5, .h6) {
  background-color: unset;
  line-height: revert;
  padding: 0;
  margin: 0;
}

/**
 * Styling for all headers that may touch content (banner + non-banner - h1).
 */
/**
 * Styling for all text basic elements.
 * 1. Ensures they play nice in the flex layout.
 */
p, ul, ol {
  flex: 1 1 auto; /* 1 */
}

/**
 * Big title at top of pages.
 * Proportionally larger than lower headings.
 */
h1, .h1 {
  font-size: 2.44140625rem;
  line-height: 1;
}

/**
 * Top level section heading, has 1 arrow.
 * Proportionally larger than lower headings.
 * 1. Set line height so overall element height matches that of other banners
 */
h2, .h2 {
  font-size: 1.5625rem;
}

/**
 * Sub-section heading, has 2 arrows.
 * Proportionally larger than lower headings.
 */
h3, .h3 {
  font-size: 1.25rem;
}

/**
 * Further sub-sub-section headings, have 3, 4, 5 arrows respectively.
 * Equal to body text size.
 * 1. Indent headings to align with text
 */
:is(h4, h5, h6), :is(.h4, .h5, .h6) {
  font-size: 1rem;
  margin-inline: var(--content-margin); /* 1 */
}

/**
 * No margin on top, small margin on bottom.
 */
p {
  transition: color var(--duration);
}

/**
 * Default list styles.
 * 1. Use a variant of lobotomized owl notation to add margins between list
 *    items and sub-lists.
 * 2. Add margin to top of sublists, as owl notation on list items will not
 */
:is(ul, ol) {
  padding-inline-start: calc(1rem + 0.5rlh);
}
:is(ul, ol) :is(ul, ol), :is(ul, ol) li + li {
  margin-block-start: calc(0.5rlh / 3); /* 1, 2 */
}

:is(ul, ol):not([role]) li {
  transition: color var(--duration);
}

/**
 * Figure captions.
 */
figcaption {
  font-size: 0.8rem;
  font-family: "JetBrains Mono", monospace;
  font-style: italic;
  color: var(--secondary);
  transition: color var(--duration);
  line-height: 1rlh;
}

/**
 * Increase font weight for bolded items.
 */
b, strong {
  font-weight: calc(var(--base-weight) + 400);
  transition: color var(--duration);
}

/**
 * Increases the visual hierarchy of an opening paragraph.
 */
.introduction {
  font-weight: calc(var(--base-weight) + 200);
}

/**
 * Monospaced elements
 */
:is(code, kbd, samp, pre) {
  font-family: "JetBrains Mono", monospace;
  font-weight: 300;
  background-color: var(--shade-2);
  padding: 0 0.25em;
  border-radius: 0.25rem;
  line-height: 1.4;
  white-space: nowrap;
}

/**
 * Extra rendering to differentiate `kbd` elements from regular code blocks
 */
kbd {
  border: 1px solid var(--shade-5);
  box-shadow: 0 1px 1px rgba(0, 0, 0, 0.2), 0 2px 0 0 var(--kbd-shade) inset;
}

/**
 * Utility class to hide text visually, but leave it accessible to screen
 * readers.
 * FontAwesome also has this same class built in, but I need a backup for pages
 * without FA sheets.
 *
 * Referenced: https://guides.18f.gov/accessibility/hidden-content/
 */
.visually-hidden {
  position: absolute;
  inline-size: 1px;
  block-size: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border-width: 0;
}

/**
 * Styles for secondary content, such as subtitles or descriptions.
 */
.description, .secondary {
  font-family: "JetBrains Mono", monospace;
  font-weight: var(--max-weight);
  font-weight: var(--base-weight);
  font-style: italic;
  color: var(--secondary);
}

/**
 * Make sure highlights are, well, highlighted.
 */
.highlight {
  font-family: "JetBrains Mono", monospace;
  font-weight: var(--max-weight);
  color: var(--highlight);
  font-variant-ligatures: none;
  font-weight: inherit;
  transition: color var(--duration);
}

/**
 * Style a UL/OL as a comma separated list.
 */
.comma-list li {
  display: inline;
}

/**
 * Make an element sticky.
 */
.sticky {
  position: sticky;
}

/**
 * Ensure body always fills the entire screen.
 * 1. Use dynamic viewport height to account for browser UI on mobile devices.
 *    See: https://stackoverflow.com/a/72245072
 * 2. Units like dvh are baseline now, so the @supports check isn't strictly
 *    necessary, but it doesn't hurt to have a fallback!
 */
body {
  min-block-size: 100vh;
}
@supports (min-block-size: 100dvh) {
  body { /* 2 */
    min-block-size: 100dvh; /* 1 */
  }
}

/**
 * Main wrapper for body of site.
 * 1. Push footer to bottom of page regardless of content size.
 */
.wrapper {
  margin: auto;
  min-block-size: 100dvh; /* 1 */
}
@supports (padding: max(0px)) {
  .wrapper {
    padding-top: max(1rlh, env(safe-area-inset-top));
    padding-left: max(1rlh, env(safe-area-inset-left));
    padding-right: max(1rlh, env(safe-area-inset-right));
    padding-bottom: max(1rlh, env(safe-area-inset-bottom));
  }
}

/**
 * Higher specificity for grid styles, so `grid-template-columns` can override
 * the shorthand `grid-template` values.
 * 1. Sidebar column is auto, main content has a limited width to preserve
 *    reasonable line lengths.
 * 2. Implicit rows of size auto, this makes it simpler when moving to smaller
 *    breakpoints.
 */
.wrapper.grid {
  display: grid;
  justify-content: center;
  -moz-column-gap: 1rlh;
       column-gap: 1rlh;
  row-gap: 1rlh;
  grid-template-columns: minmax(auto, auto) minmax(27.125rem, 43rem); /* 1 */
  grid-auto-rows: auto; /* 2 */
}
@media screen and (max-width: 43rem) {
  .wrapper.grid {
    grid-template-columns: minmax(16rem, 40rem);
  }
}

/**
 * Default grid for pages. Has no sidebar.
 * 1. Because the content begins at the top and spans multiple rows, we can tell
 *    the nav row to be as small as possible, allowing the sidebar to be placed
 *    directly beneath it.
 */
.grid-default {
  grid-template: "nav  head" auto ".    content" 1fr "foot foot" auto;
}
@media screen and (max-width: 43rem) {
  .grid-default {
    grid-template: "nav" auto "head" auto "content" 1fr "foot" auto;
  }
}

/**
 * Grid for pages with a sidebar.
 */
.grid-sidebar {
  grid-template: "nav  head" auto "side content" 1fr "foot foot" auto;
}
@media screen and (max-width: 43rem) {
  .grid-sidebar {
    grid-template: "nav" auto "head" auto "side" auto "content" 1fr "foot" auto;
  }
}

/**
 * Grid for pages that want a sidebar, but with an additional row before it to
 * place content (such as headings).
 */
.grid-pre-sidebar {
  grid-template: "nav  head" auto "side pre-side" auto "side content" 1fr "foot foot" auto;
}
@media screen and (max-width: 43rem) {
  .grid-pre-sidebar {
    grid-template: "nav" auto "head" auto "pre-side" auto "side" auto "content" 1fr "foot" auto;
  }
}

/**
 * Grid for About page, where the profile photo needs to be aligned with
 * Content and not the Pre-Sidebar.
 */
.grid-pre-sidebar-low {
  grid-template: "nav  head" auto ".    pre-side" auto "side content" 1fr "foot foot" auto;
}
@media screen and (max-width: 43rem) {
  .grid-pre-sidebar-low {
    grid-template: "nav" auto "head" auto "pre-side" auto "side" auto "content" 1fr "foot" auto;
  }
}

/**
 * Due to semantic HTML, the content of the page is wrapped in some additional
 * tags. They are subgrids of the main wrapper, and inherit all grid template
 * areas. This allows me to position elements anywhere in any of these wrapping
 * elements, can think of them as layers.
 * 1. They're positioned to fill the entire outermost grid, otherwise they
 *    wouldn't be able to place in any grid areas outside of their box models.
 * 2. Ensure elements act block-like on smaller screens, otherwise
 *    clicking/tapping sends focus to unexpected places.
 */
.main, .article {
  display: grid;
  grid-template-columns: subgrid;
  grid-template-rows: subgrid;
  justify-items: stretch; /* 2 */
  grid-column: 1/-1; /* 1 */
  grid-row: 1/-1; /* 1 */
}

/**
 * The sidebar is in the outermost wrapper for semantic reasons (it relates to
 * the site as a whole, not the article on the page, such as a project). This
 * also acts as the header for the site.
 * 1. Needs to come to the foreground since the wrapper is behind the semantic
 *    elements.
 */
.nav-wrapper {
  grid-area: nav;
  z-index: 1; /* 1 */
}

/**
 * Mapping grid areas.
 */
.header {
  grid-area: head;
}

.content {
  grid-area: content;
}

.pre-sidebar {
  grid-area: pre-side;
}

.sidebar-wrapper {
  grid-area: side;
}

.footer {
  grid-area: foot;
}

/**
 * Navigation lists, general
 * 1. Add reduced margin above list items and sublists for clearer breaks when
 *    wrapping
 * 2. Line up left edge of bullets with left margin. We can safely use `2ch`
 *    because we're working in a monospace font.
 * 3. Use Sass function to grab the right combination of values from the map.
 */
.nav :is(ul, ol) {
  list-style-type: "> ";
  padding-inline-start: 2ch; /* 2 */
  display: flex;
  flex-direction: column;
  gap: 0.375rlh 1.5rlh; /* 3 */
  font-family: "JetBrains Mono", monospace;
  font-weight: var(--max-weight);
  font-size: 1.25rem;
  line-height: 1.2;
}

/**
 * Styles for all list items.
 * 1. If a navigation list item is marked as "current", highlight it blue
 * 2. Make list markers invisible by default
 * 3. Markers are shown when they have .current or are focused/hovered
 * 4. Change marker colour when link is active. We also don't need to worry
 *    about transparency here, since when it is active it is always focused.
 * 5. Remove default list margins in favour of flex/grid gap spacing.
 */
.nav :is(ul, ol) li {
  margin-block-start: 0;
}
.nav :is(ul, ol) li a {
  font-weight: var(--max-weight);
  text-decoration-color: transparent;
}
.nav :is(ul, ol) li::marker {
  font-family: "JetBrains Mono", monospace;
  font-weight: var(--max-weight);
  color: var(--highlight);
  font-variant-ligatures: none;
  font-weight: inherit;
  transition: color var(--duration);
  color: rgb(from var(--highlight) r g b/0); /* 2 */
}
.nav :is(ul, ol) li.current > a {
  color: var(--highlight); /* 1 */
}
.nav :is(ul, ol) li.current > a:active {
  color: var(--active);
}
.nav :is(ul, ol) li.current::marker {
  color: var(--highlight); /* 3 */
}
.nav :is(ul, ol) li:has(> a:focus)::marker {
  color: var(--highlight); /* 3 */
}
@media (hover: hover) {
  .nav :is(ul, ol) li:has(> a:hover)::marker {
    color: var(--highlight); /* 3 */
  }
}
.nav :is(ul, ol) li:has(> a:active)::marker {
  color: var(--active); /* 4 */
}

/**
 * Sub lists and items.
 * 1. Apply secondary styles to link only, we don't want to change the list
 *    marker here.
 * 2. Apply matching nav gap to sublists.
 */
.nav :is(ul, ol) :is(ul, ol) {
  font-size: 1rem;
  margin-block-start: 0.375rlh; /* 2 */
}
.nav :is(ul, ol) :is(ul, ol) li a {
  font-family: "JetBrains Mono", monospace;
  font-weight: var(--max-weight);
  font-weight: var(--base-weight);
  font-style: italic;
  color: var(--secondary);
  /* 1 */
}

/**
 * Wrapper for social icons and theme picker at the end of the nav.
 * 1. Set font styles for widgets to inherit.
 */
.nav-widgets {
  display: flex;
  flex-direction: row;
  gap: 0.5rlh 2rlh;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: center;
  justify-items: center;
  font-size: 1.5625rem; /* 1 */
  line-height: 1; /* 1 */
}

/**
 * Represents the body of an article. This comes after the header and TOC.
 * 1. Remove row-gap and recreate it with padding to avoid dead zones with the
 *    TOC scroll tracking.
 * 2. Remove extra padding from very top heading of very first section.
 *    This brings it properly inline with the top of the grid row.
 * 3. Add extra scroll margin to compensate for the lack of actual padding.
 */
.content {
  display: flex;
  flex-direction: column;
  gap: 0.5rlh;
  row-gap: 0; /* 1 */
}
.content section:first-child {
  padding-block-start: 0; /* 2 */
  scroll-margin-block-start: 1rlh; /* 3 */
}

/**
 * Remove top padding to the first section in the pre-sidebar area.
 */
.pre-sidebar section:first-child {
  padding-block-start: 0;
}

/**
 * Saves having to manage exact margins and gaps on each item I might add to a
 * page, project or otherwise.
 * 1. Remove row-gap and recreate it with padding to avoid dead zones with the
 *    TOC scroll tracking.
 * 2. With no row-gap, elements need their bottom margins back.
 * 3. Inset text a small amount from the edges of the container.
 * 4. Lower specificity with :where clause
 */
section {
  display: flex;
  flex-direction: column;
  gap: 0.5rlh;
  row-gap: 0; /* 1 */
  padding-block-start: 1rlh; /* 1 */
}
section > :where(:not(section)) {
  margin-block-end: 0.5rlh; /* 2 */
  margin-inline: var(--content-margin); /* 3 */
}
section > :where(:not(section)):last-child, section > :where(:not(section)):has(+ section) {
  margin-block-end: 0;
}

/**
 * Contains a number of project cards.
 * 1. Wrap cards to one-per-row if they're smaller than the minimum value.
 * 2. Undo margin applied to section children
 */
:is(ul, ol).project-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(16rem, 1fr)); /* 1 */
  gap: 1rlh;
  margin-inline: 0; /* 2 */
}

/**
 * Header at the top of project pages.
 * 1. Background image, to be covered by gradient from children.
 * 2. Position set to relative for absolute Automata canvas behind it.
 * 3. Variable --project-banner is set inline on the article element.
 * 4. Add fallback color if banner image is not found.
 */
.header {
  position: relative; /* 2 */
  display: flex;
  flex-direction: column;
  gap: 0;
  margin-block-start: -1rlh;
  min-block-size: 15rem;
  justify-content: center;
  background-color: var(--banner); /* 4 */
  background-image: var(--project-banner); /* 1, 3 */
  background-size: cover;
  background-position: top center;
  transition: background-color var(--duration);
}
.header .description {
  color: var(--secondary-alt);
  color: hsl(240, 6.25%, 94%);
}
@media screen and (max-width: 43rem) {
  .header {
    margin-block-start: 0;
    margin-inline: -1rlh;
  }
}

/**
 * When the header is inside an article (like on project pages)
 * 1. Use a bright placeholder background instead of a dark one
 */
.article .header {
  background-color: var(--link); /* 1 */
  transition: background-color var(--duration);
}

/**
 * Fallback heading for when the canvas fails to load or JS is disabled
 */
.canvas-fallback {
  flex: 0 1;
  font-family: "JetBrains Mono", monospace;
  font-weight: var(--max-weight);
  font-size: 3.8146972656rem;
  line-height: 1;
  text-align: center;
}

/**
 * Position noscript element within canvas (this is as a backup for when the
 * canvas fails to load)
 */
.header noscript {
  display: flex;
  flex-direction: column;
  gap: 0.5rlh;
  align-items: center;
  justify-content: center;
  font-style: italic;
  font-size: 0.8rem;
}

/**
 * When the page is supposed to have an Automata show, but JS is disabled
 * 1. Swap to grid layout to place JS hint at the bottom of the header
 */
@media (scripting: none) {
  .header:has(#automata-wrapper) {
    display: grid; /* 1 */
    grid-template-columns: 1fr;
    grid-template-rows: 1fr auto;
    align-items: center;
    padding: 1rlh;
    gap: 1rlh;
  }
}
.header:has(#automata-wrapper) {
  /**
   * When scripting is ENABLED, hide the canvas fallback briefly while the
   * canvas loads
   */
}
.header:has(#automata-wrapper) :is(.canvas-fallback, .header noscript) {
  z-index: 1;
}
@media (scripting: enabled) {
  .header:has(#automata-wrapper) :is(.canvas-fallback, .header noscript) {
    transition-property: opacity;
    transition-duration: calc(var(--duration) * 4);
    transition-delay: 1s;
    opacity: 1;
  }
  @starting-style {
    .header:has(#automata-wrapper) :is(.canvas-fallback, .header noscript) {
      opacity: 0;
    }
  }
}

/**
 * Apply margins to hgroups that are inside a pre-sidebar area. Normally they'd
 * get this styling from a parent section, but not in this case.
 */
.pre-sidebar {
  margin-block: 1rlh;
}
.pre-sidebar :is(hgroup, .hgroup) {
  margin-inline: 1rlh;
}
@media screen and (max-width: 43rem) {
  .pre-sidebar :is(hgroup, .hgroup) {
    margin-inline: 0;
  }
}

/**
 * Semi-transparent background color in front of `.header` background image,
 * but only where the text is.
 * 1. Set transparency using relative color syntax (Baseline 2024).
 * 2. Set z index so it's above the background image of `.header`. Mainly for
 *    with Automata wrapper.
 */
.header :is(hgroup, .hgroup) {
  padding-inline: 1rlh;
  padding-block: 1rlh 0;
  background: linear-gradient(var(--gradient-90) 0%, var(--gradient-70) 100%); /* 1 */
  z-index: 1; /* 2 */
  transition-property: --gradient-90, --gradient-70;
  transition-duration: var(--duration);
  color: hsl(240, 6.25%, 100%);
}

/**
 * Semi-transparent background gradient in front of `.header` background image,
 * filling rest of row space below the `hgroup`.
 * 1. Set transparency using relative color syntax (Baseline 2024).
 */
.header .gradient {
  z-index: 2;
  flex: auto;
  min-block-size: 4rlh;
  background: linear-gradient(var(--gradient-70) 0%, var(--gradient-00) 80%); /* 1 */
  transition-property: --gradient-70, --gradient-00;
  transition-duration: var(--duration);
}

/**
 * List of links at the bottom of header.
 * 1. Had to increase specificity a bit for padding/margins.
 * 2. Since we're bunching the links in the middle, this looks better than
 *    when they wrap aligned left.
 */
:is(ul, ol).links { /* 1 */
  flex: 0 auto;
  display: flex;
  flex-direction: row;
  gap: 0.5rlh 1rlh;
  flex-wrap: wrap;
  justify-content: center;
}
:is(ul, ol).links li {
  text-align: center; /* 2 */
}
:is(ul, ol).links {
  padding-block: 0.5rlh;
  padding-inline: 1rlh;
  background-color: var(--project-links-bg); /* 1 */
  transition: background-color var(--duration);
  font-family: "JetBrains Mono", monospace;
  font-weight: var(--max-weight);
  font-size: 0.8rem;
}

/**
 * List of tools in Overview section.
 */
.tools, .concepts {
  display: flex;
  flex-direction: row;
  gap: 0.5rlh;
  flex-wrap: wrap;
  align-items: start;
  justify-items: center;
}
.tools li, .concepts li {
  font-family: "JetBrains Mono", monospace;
  font-weight: var(--max-weight);
  font-size: 0.8rem;
  font-weight: calc(var(--base-weight) + 200);
  background-color: var(--shade-1);
  border: 0.1rem solid var(--active);
  transition-property: background-color, color, border;
  transition-duration: var(--duration);
  padding: 0.25rlh 0.5rlh;
}

/**
 * List of concepts in Overview section. Extends `.tools`.
 */
.concepts li {
  background-color: var(--banner-alt);
}

/**
 * Footer for entire site.
 * 1. Rearrange footer contents when screen becomes too small.
 */
.footer {
  display: grid;
  grid-template-columns: subgrid;
  grid-template-rows: subgrid;
  justify-items: stretch; /* 2 */
}
.footer .footer-contents {
  display: grid;
  grid-auto-rows: auto;
  grid-auto-columns: 1fr;
  grid-auto-flow: column; /* 1 */
  gap: 0.5rlh;
  justify-items: center;
  align-items: center;
  grid-column: 1/span 2; /* 1 */
  grid-row: -1/-1; /* 1 */
}
.footer .footer-contents :first-child {
  justify-self: start;
}
.footer .footer-contents :last-child {
  justify-self: end;
}
@media screen and (max-width: 43rem) {
  .footer .footer-contents {
    grid-auto-flow: row; /* 1 */
  }
  .footer .footer-contents :first-child, .footer .footer-contents :last-child {
    justify-self: center;
  }
}
.footer {
  background-color: var(--banner);
  transition: background-color var(--duration);
  font-size: 0.8rem;
  padding-left: max(1rlh, env(safe-area-inset-left));
  padding-right: max(1rlh, env(safe-area-inset-right));
  padding-block: 1rlh;
  padding-block-end: max(1rlh, env(safe-area-inset-bottom));
  margin-left: calc(-1 * max(1rlh, env(safe-area-inset-left)));
  margin-right: calc(-1 * max(1rlh, env(safe-area-inset-right)));
  margin-block-start: 1rlh;
  margin-bottom: calc(-1 * max(1rlh, env(safe-area-inset-bottom)));
}

/**
 * Large name, acts as my logo
 */
.name {
  font-family: "JetBrains Mono", monospace;
  font-weight: var(--max-weight);
  color: var(--link);
  text-decoration-color: transparent !important;
  line-height: 1;
}

/**
 * A header element, contains the main navigation and social links
 */
.nav-wrapper, .nav-wrapper .nav {
  display: flex;
  flex-direction: column;
  gap: 0.5rlh;
}

.nav-wrapper {
  gap: 0.75rlh;
}

/**
 * On smaller screens, rearrange the nav section to conserve vertical space.
 * 1. Remove padding from taller layout
 * 2. Increase column gap to account for active indicators
 */
@media screen and (max-width: 43rem) {
  .nav-wrapper .nav :is(ul, ol) {
    padding-inline-start: 0; /* 1 */
    flex-direction: row;
    flex-wrap: wrap;
    justify-content: center;
    -moz-column-gap: 2.5rlh;
         column-gap: 2.5rlh; /* 2 */
  }
}

/**
 * Uses the same gap as the flex layout applied to top-level nav lists.
 * 1. Hide categories from main nav on smaller viewports. These are just
 *    convenience anchors for the same page, anyways.
 */
.nav-wrapper .nav :is(ul, ol) :is(ul, ol) {
  display: grid;
  gap: 0.375rlh 1.5rlh;
  grid-template-columns: repeat(auto-fit, minmax(10rem, max-content));
}
@media screen and (max-width: 43rem) {
  .nav-wrapper .nav :is(ul, ol) :is(ul, ol) {
    display: none; /* 1 */
  }
}

/**
 * Wrapper for name and tagline at the top of the sidebar
 * 1. Aligning to start stops the anchor from being wider than its text.
 * 2. Center text on smaller viewports.
 */
.nav-wrapper .name-wrapper {
  align-items: start; /* 1 */
}
.nav-wrapper .name-wrapper p {
  margin-top: 0.125rlh;
  color: var(--opposite);
  font-size: 1rem;
  font-weight: calc(var(--base-weight) + 200);
  font-style: normal;
}
@media screen and (max-width: 43rem) {
  .nav-wrapper .name-wrapper {
    text-align: center; /* 2 */
  }
}

/**
 * Large name linking to home page, acts as my logo
 */
.nav-wrapper .name {
  font-size: 1.953125rem;
}

/**
 * Table of Contents
 */
/**
 * Nav list within a Table of Contents
 * 1. Reduce font weight of root items to not compete with main nav as much.
 * 2. Fixes an issue where nav would show scrollbar despite enough room to grow.
 */
.toc .nav > :is(ul, ol) > li > a {
  font-weight: calc(var(--base-weight) + 500); /* 1 */
}
.toc .nav :is(ul, ol) {
  font-size: 1rem;
}

/**
 * Since sidebar headings are styled as H4, we need to adjust a few things.
 */
.sidebar-wrapper .sidebar-heading {
  margin: 0;
  margin-block-end: 0.25rlh;
  font-size: 1.25rem;
}

/**
 * Wrapper for sidebar contents.
 * 1. Removes top padding from first section in sidebar.
 * 2. Stops the grid from using the width of the sidebar to calculate column
 *    size, instead using the next largest element (the subtitle). This is
 *    especially useful with the skills lists.
 *    Referenced: https://stackoverflow.com/a/78771773/27162946
 */
.sidebar-wrapper {
  display: flex;
  flex-direction: column;
  gap: 1rlh;
  contain: inline-size; /* 2 */
  margin-block-start: 1rlh;
}
@media screen and (max-width: 43rem) {
  .sidebar-wrapper {
    margin-block-end: 1rlh;
  }
}
.sidebar-wrapper section:first-child {
  padding-block-start: 0; /* 1 */
}

/**
 * Generic sidebar, the section itself.
 * 1. This stops the back-to-top link from filling the full width.
 * 2. Allow words that are too long wrap, such as "Acknowledgements"
 */
.sidebar {
  display: flex;
  flex-direction: column;
  gap: 0;
  align-items: start; /* 1 */
  overflow-wrap: anywhere; /* 2*/
}

/**
 * Scrollable content within sidebar contents.
 * 1. Display a scroll bar if the sidebar is taller than the screen.
 * 2. Fix issue with sub-pixel rendering causing a scrollbar to appear
 *    erroneously
 */
.sidebar .scrollable {
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 0.5rlh;
}
.sidebar .scrollable .nav {
  padding-block-end: 1px; /* 2 */
}

/**
 * Back to Top link beneath sidebar contents.
 * 1. Same weight as TOC nav items, should really make this a variable
 */
.sidebar .to-top {
  display: block;
  margin: 0;
  margin-block-start: 1rlh;
  font-family: "JetBrains Mono", monospace;
  font-weight: var(--max-weight);
  font-size: 0.8rem;
  font-weight: calc(var(--base-weight) + 500); /* 1 */
  line-height: 1;
  text-decoration-color: transparent;
}
@media screen and (max-width: 43rem) {
  .sidebar .to-top {
    display: none;
  }
}

/**
 * Sticky sidebar styles.
 * 1. Limit height so it always fits on screen.
 */
.sidebar.sticky {
  inset-block-start: 1rlh;
  max-block-size: calc(100vh - 1rlh * 2); /* 1 */
}
@supports (max-block-size: 100dvh) {
  .sidebar.sticky {
    max-block-size: calc(100dvh - 1rlh * 2); /* 1 */
  }
}
@media screen and (max-width: 43rem) {
  .sidebar.sticky {
    max-block-size: none;
  }
}

/**
 * Styling for FontAwesome based social icons.
 * See PUG include of the same name.
 */
.socials {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rlh;
  font-size: 1.5625rem;
  line-height: 1;
}

/**
 * Links and icons inside the social list.
 */
.social-link {
  color: var(--text);
}

/**
 * Style YouTube embed in a responsive manner.
 * Referenced: https://embedresponsively.com/
 */
.youtube-container {
  position: relative;
  aspect-ratio: 16/9;
  overflow: hidden;
  max-inline-size: 100%;
  margin-inline: 0;
}

/**
 * Place the iframe and other components within container.
 */
.youtube-container iframe, .youtube-container object, .youtube-container embed {
  position: absolute;
  inset-block-start: 0;
  inset-inline-start: 0;
  block-size: 100%;
  inline-size: 100%;
  border: none;
}

/**
 * Responsive image styles for images with multiple sources. Since this wraps
 * the img element, we need to apply these structural styles here.
 * 1. Having the inner img inline means if it breaks, then the remaining alt
 *    alt text isn't forced to a size that cannot be overridden by things like
 *    a flex layout.
 * 2. This hides the extra height at the bottom of the containing element,
 *    which is due to `display: inline;`
 */
picture {
  display: block;
  max-inline-size: 100%;
  block-size: auto;
  background-color: var(--banner);
  transition: background-color var(--duration);
}
picture img {
  display: inline; /* 1 */
  vertical-align: middle; /* 2 */
  -o-object-fit: contain;
     object-fit: contain;
}

/**
 * Flex grid for a gallery of images. Used in "Examples" sections.
 * 1. Reduce row gap due to extra space from figcaptions
 * 2. Remove inline margin applied to children of section elements
 * 3. Reduce figcaption outer margin since this typically isn't placed inline
 *    with text
 * 4. Help stop broken images from escaping.
 */
:is(ul, ol).img-list {
  display: flex;
  flex-direction: row;
  gap: 0.5rlh 1rlh;
  /* 1 */
  flex-wrap: wrap;
  margin-inline: 0; /* 2 */
}
:is(ul, ol).img-list li {
  flex: 15rem;
  overflow: hidden; /* 4 */
}
:is(ul, ol).img-list li:first-child {
  flex: auto;
}
:is(ul, ol).img-list figcaption {
  margin-inline: 1rlh; /* 3 */
}

/**
 * Content contained within a figure and included caption.
 * 1. Extra inline margin to properly mimic general text margins.
 * 2. Undo section child margins.
 */
figure {
  display: flex;
  flex-direction: column;
  gap: 0.5rlh;
  align-items: center;
  margin-inline: 0;
}
figure picture {
  margin-inline: calc(var(--content-margin) * -1);
}
figure figcaption {
  margin-inline: calc(1.5rem + var(--content-margin)); /* 1 */
}

/**
 * Custom Gradio embed, preferred over iframe.
 * 1. Remove section child margins.
 */
gradio-app {
  margin-inline: 0; /* 1 */
}

/**
 * Inner container of Gradio app, had to be extra specific to override default
 * styles.
 */
gradio-app.gradio-app .embed-container.gradio-container {
  margin-block: 0;
}

/**
 * Card containing details about each project.
 * 1. One named grid area, easier to stack two elements together.
 * 2. Accessible card design, pseudo-content trick to expand anchor hitbox to
 *    cover entire card. See: https://inclusive-components.design/cards/
 * 3. Progressive enhancement to show/hide text underline depending on if
 *    :focus-within is supported.
 */
.project-card {
  display: grid;
  grid-template-areas: "banner"; /* 1 */
  grid-template-columns: 1fr;
  grid-template-rows: auto 1fr;
  position: relative; /* 2 */
  scroll-margin-block-start: 0.5rlh;
  box-shadow: 0.5rem 0.5rem 0.5rem rgba(0, 0, 0, 0.8);
  outline: 0 solid var(--highlight);
  transition-property: outline-width, outline-color;
  transition-duration: calc(var(--duration) / 2), var(--duration);
}
.project-card:hover, .project-card:focus-within {
  outline-width: 0.2rem;
}
.project-card:active {
  outline-color: var(--active);
}
.project-card a:focus {
  outline: none;
}

/**
 * Heading for project cards. Overlaps with `.project-image`.
 * 1. Push heading to bottom of banner row.
 * 2. Add extra padding to match border thickness of `.project-details`.
 */
.project-heading {
  grid-area: banner;
  align-self: end; /* 1 */
  margin: 0;
  padding-block: 0.5rlh;
  padding-inline: calc(1rlh + 0.2rem); /* 2 */
  background-color: rgb(from var(--banner) r g b/0.9);
}

/**
 * The card heading has an anchor nested within.
 * 1. Use a pseudo-element trick to expand the hitbox of the anchor, filling the
 *    entire card, making it all clickable.
 * 2. Since we're setting the text color, we have to re-set the highlight as
 *    well, due to specificity.
 */
.project-heading a {
  font-family: "JetBrains Mono", monospace;
  font-weight: var(--max-weight);
  text-decoration-color: transparent;
}
.project-heading a::after { /* 1 */
  content: "";
  position: absolute;
  inset-block: 0 0;
  inset-inline: 0 0;
}

/**
 * Banner image for card.
 * 1. Sits behind `.project-heading`.
 * 2. Responsive image styles
 * 3. Background color in case image not found
 * 4. Prevents broken image from spilling everywhere
 */
.project-img {
  grid-area: banner;
  z-index: -1; /* 1 */
  background-color: var(--link); /* 3 */
  transition: background-color var(--duration);
  overflow: hidden; /* 4 */
}
.project-img img { /* 2 */
  aspect-ratio: 2/1;
  -o-object-fit: cover;
     object-fit: cover;
  -o-object-position: top center;
     object-position: top center;
}

/**
 * Container for project description and tools.
 */
.project-details {
  border: 0.2rem solid var(--banner);
  border-block-start-style: none;
  transition: border var(--duration);
  display: flex;
  flex-direction: column;
  gap: 0.5rlh;
  align-items: start;
  justify-content: space-between;
  padding: 1rlh;
  padding-block-start: 0.5rlh;
}

/**
 * Button styling class.
 * 1. Since this is usually applied to anchors, they need to act like proper
 *    block elements.
 */
.button {
  font-family: "JetBrains Mono", monospace;
  font-weight: var(--max-weight);
  text-decoration: none;
  font-weight: calc(var(--base-weight) + 400);
  display: inline-block; /* 1 */
  padding-block: 0.25rlh;
  padding-inline: 0.5rlh;
  line-height: 1.5;
  background-color: var(--banner);
  border: 0.1rem solid var(--link);
  color: var(--link);
  transition-property: border-color, color, background-color;
  transition-duration: var(--duration);
  /**
   * 1. When button is hovered, also activate tooltip
   */
}
.button:is(:focus, :hover) {
  border-color: var(--highlight);
  color: var(--highlight);
}
.button:is(:focus, :hover) + [role=tooltip] { /* 1 */
  border-color: var(--highlight);
  opacity: 1;
  visibility: visible;
}
.button[aria-disabled=true] {
  border-color: var(--secondary);
  color: var(--secondary);
  cursor: not-allowed;
}
.button[aria-disabled=true] + [role=tooltip] {
  border-color: var(--secondary);
}
.button:is(:active):not([aria-disabled=true]) {
  border-color: var(--active);
  color: var(--active);
}
.button:is(:active):not([aria-disabled=true]) + [role=tooltip] {
  border-color: var(--active);
}

/**
 * Wraps around a paired button and tooltip.
 */
.button-tooltip-wrapper {
  position: relative;
}

/**
 * Tooltips for buttons with icons, to be wrapped in a .menu-button-wrapper
 * class.
 * 1. Center tooltip in relation to the button
 */
[role=tooltip] {
  position: absolute;
  inset-inline-start: 50%; /* 1 */
  transform: translate(-50%, 0); /* 1 */
  text-align: center;
  background-color: var(--banner);
  padding-block: 0.25rlh;
  padding-inline: 0.5rlh;
  margin-block-start: 0.25rlh;
  transition-property: border-color, opacity, visibility;
  transition-duration: var(--duration);
  border: 0.1rem solid var(--secondary);
  visibility: hidden;
  opacity: 0;
}

/**
 * Groups containing a heading and a list of skills.
 * 1. Highlight category titles
 * 2. Undo section child margins
 */
.skills-group {
  display: flex;
  flex-direction: column;
  gap: 0;
}
.skills-group .h4 {
  font-weight: calc(var(--base-weight) + 400);
  margin-inline: 0; /* 2 */
  color: var(--highlight); /* 1 */
}

/**
 * Container for P5 automata canvas.
 * 1. Do not change the size of the header, just fit inside it.
 * 2. Behind hgroup text, but above the header background image.
 * 3. If Javascript is enabled, change background color to match simulation.
 *    Baseline 2023.
 * 4. When the canvas has loaded, make sure it's in front of the fallback text
 */
#automata-wrapper {
  position: absolute; /* 1 */
  inline-size: 100%; /* 1 */
  block-size: 100%; /* 1 */
  z-index: 0; /* 2 */
}
#automata-wrapper:has(#automata-canvas) {
  z-index: 2; /* 4 */
}

/**
 * Canvas used by P5js.
 * 1. Add transition when canvas is added to DOM. Using @starting-style is
 *    Baseline 2024.
 * 2. Reduces anti-aliasing fuzziness and keeps things looking crisp
 */
#automata-canvas {
  inline-size: 100%;
  block-size: 100%;
  image-rendering: pixelated; /* 2 */
  opacity: 1;
  transition: opacity calc(var(--duration) * 4);
}
@starting-style {
  #automata-canvas {
    opacity: 0; /* 1 */
  }
}

/**
 * Menu container for buttons that control the Automata sim.
 * 1. Horizontally center menu on smaller screens.
 */
.canvas-menu {
  position: absolute;
  inset-block-end: 0;
  inset-inline: 0 0; /* 1 */
  inline-size: -moz-fit-content;
  inline-size: fit-content; /* 1 */
  margin: 0;
  padding-inline: 0;
  list-style: none;
  display: flex;
  flex-direction: row;
  gap: 0.5rlh;
  font-size: 1rem;
}
@media screen and (max-width: 43rem) {
  .canvas-menu {
    margin-inline: auto; /* 1 */
  }
}

/**
 * Theme picker form.
 * 1. Remove default styles from fieldset.
 * 2. Add browser-default focus outline to form fieldset when focus is on any
 *    of the inputs.
 */
.theme-picker fieldset {
  display: flex;
  flex-direction: row;
  gap: 0.5rlh;
  flex-wrap: wrap;
  align-self: center;
  justify-self: center;
  margin: 0; /* 1 */
  padding: 0; /* 1 */
  border: none; /* 1 */
  font-size: 1.5625rem;
  line-height: 1;
}
.theme-picker fieldset:has(:focus-visible) {
  outline-style: auto; /* 2 */
}

/**
 * Label styles. These colours will be inherited by the text/icons inside the
 * actual labels.
 * 1. Needs to be listed first, so it can be overridden.
 */
.theme-picker label {
  transition: color var(--duration);
}
.theme-picker label:has(input:checked) {
  color: var(--link); /* 1 */
}
.theme-picker label:has(input):hover, .theme-picker label:has(input):focus {
  color: var(--highlight);
}
.theme-picker label:has(input):active {
  color: var(--active);
}

/**
 * Styles for References/Works Cited lists
 * 1. Indent every line except the first. Indent amount was suggested by the
 *    exported HTML from Zotero.
 * 2. Add extra space between items for better readability.
 */
.ref-list {
  text-indent: 2em hanging; /* 1 */
}
.ref-list .ref-entry + .ref-entry {
  margin-block-start: 0.5rlh; /* 2 */
}

/**
 * Adds scroll shadows to the top and bottom of a scroll container, if there is
 * more content to be seen. Uses `background-attachment` to overlay the
 * background images.
 * Referenced: https://lea.verou.me/blog/2012/04/background-attachment-local/
 */
.scrollable {
  overflow-y: auto;
  overflow-block: auto;
  background: linear-gradient(var(--gradient-bg) 30%, var(--gradient-00)) 0 0 no-repeat local, linear-gradient(var(--gradient-00), var(--gradient-bg) 70%) 0 100% no-repeat local, radial-gradient(farthest-side at 50% 0, var(--gradient-shadow), var(--gradient-00)) 0 0 no-repeat scroll, radial-gradient(farthest-side at 50% 100%, var(--gradient-shadow), var(--gradient-00)) 0 100% no-repeat scroll;
  background-size: 100% 2rem, 100% 2rem, 100% 0.5rem, 100% 0.5rem;
  transition-property: --gradient-bg, --gradient-shadow, --gradient-00;
  transition-duration: var(--duration);
}

/**
 * Center "Hi, I'm Robin;" text on smaller viewports.
 */
.grid-pre-sidebar-low .pre-sidebar {
  display: flex;
  flex-direction: column;
  gap: 0.5rlh;
  align-items: start;
}
@media screen and (max-width: 43rem) {
  .grid-pre-sidebar-low .pre-sidebar {
    align-items: center;
  }
}

/**
 * Profile picture is wrapped in a div with the same clip-path to create a
 * border that follows the path.
 */
.profile-border {
  position: relative;
  align-self: center;
  inline-size: 100%;
  max-inline-size: 256px;
  clip-path: circle();
  background-color: var(--banner);
  transition: background-color var(--duration);
  aspect-ratio: 1/1;
}

/**
 * Picture element containing the actual image.
 * 1. Equivalent to a 3px border, when 1rem=16px.
 */
.profile-picture {
  position: absolute;
  inset: 0.1875rem; /* 1 */
}

/**
 * Profile image itself.
 * 1. Calling the circle path without arguments places it in the center.
 */
.profile-picture img {
  clip-path: circle(); /* 1 */
}

.error-heading {
  font-size: 1.953125rem;
}

/**
 * Library comma-separated lists, see AutolumeGallery
 * 1. Place list inline with Library header/title text.
 */
.libraries {
  font-size: 0.8rem;
}
.libraries :is(p, .comma-list) {
  display: inline-block; /* 1 */
}

#intro .hgroup {
  padding-block-end: 1rlh;
}

/**
 * Adds border beneath the end of the overview section in the TOC
 */
.toc .nav > ol > li:first-child {
  padding-block-start: 0.5rlh;
}
.toc .nav > ol > li:first-child::after {
  content: "";
  padding-block-end: 0.75rlh;
  border-block-end: thin solid var(--shade-2);
  transition-property: border-bottom-color;
  transition-duration: var(--duration);
  margin-block-end: 0.5rlh;
  display: block;
}

/**
 * Adds border between sections, where the report/breakdown separation is
 */
section#overview:not(:has(section)), section#overview:has(section) > section:last-child {
  padding-block-end: 2rlh;
  border-block-end: thin solid var(--shade-2);
  transition-property: border-bottom-color;
  transition-duration: var(--duration);
}
section#overview + section {
  padding-block-start: 2rlh;
}
/*# sourceMappingURL=main.css.map */