gomesite/index.html

304 lines
8.3 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang='en'>
<head>
<title>gomepage</title>
<meta charset='utf-8'/>
<meta name='theme-color' content='#efe5d7'>
<meta name='viewport' content='width=device-width, initial-scale=1.0, shrink-to-fit=no'/>
<link rel='icon' type='image/x-icon' href='./favicon.ico'>
<link rel='preconnect' href='https://fonts.googleapis.com'>
<link rel='preconnect' href='https://fonts.gstatic.com' crossorigin>
<link rel='preload' href='https://fonts.googleapis.com/css2?family=Lora:ital@0;1&display=swap' as='style' onload='this.onload=null;this.rel="stylesheet"'>
<noscript><link rel='stylesheet' href='https://fonts.googleapis.com/css2?family=Lora:ital@0;1&display=swap'></noscript>
<style>
html {
color: #323a42;
background-color: #efe5d7;
height: 100%;
font-family: 'Palatino Linotype', Lora, serif;
font-size: 1.25em;
}
body {
margin: 0;
min-height: 100%;
display: grid;
grid-template-columns: 1fr min-content;
grid-template-rows: 1fr auto min-content;
line-height: 1.2;
}
*::selection {
background: #ebdcc97f;
}
header {
grid-column: 2;
grid-row: 1 / span 2;
width: min-content;
overflow: hidden;
}
main {
grid-column: 1;
grid-row: 1;
padding: 1em;
}
footer {
display: flex;
grid-column: 1 / span 2;
grid-row: 2 / span 2;
}
.title-box, h1, h2, h3, h4, h5, h6 {
font-weight: normal;
}
.title-box {
position: relative;
border: 2px solid #323a42;
border-top: none;
border-right: none;
font-size: 48px;
height: 3em;
width: 10em;
background-color: #efe5d7;
}
.title-box .title {
background-color: inherit;
position: absolute;
bottom: -13px;
padding: 0 0.25em 0 0.25em;
user-select: none;
}
nav {
font-size: 18px;
position: relative;
display: flex;
flex-direction: column;
/* this counters the left offset, but adds no real padding */
padding-right: 1rem;
left: 1rem;
right: 0;
border-bottom: 2px solid #323a42;
transition: opacity 50ms;
opacity: 0;
pointer-events: none;
}
nav a {
margin: 0.25em 0.75em 0.25em 0;
padding: 0.25em;
position: relative;
left: -0.25em;
color: #323a42;
text-decoration: none;
line-height: 1.2;
border-radius: 2px;
}
nav a:first-child {
margin-top: 1em;
}
nav a:last-child {
margin-bottom: 1em;
}
a:hover, a:focus {
color: #6d747a;
outline: 0;
}
a:focus-visible {
outline: 1px dashed #beb0b1;
}
nav a .link-title {
font-weight: bold;
}
nav a .link-description::before {
font-weight: normal;
content: '— ';
}
nav a.new .link-title::after {
content: '*';
color: #984624;
}
nav a.new:hover .link-title::after, nav a.new:focus .link-title::after {
color: #BF8E7C;
}
nav.show, nav:focus-within {
opacity: 1;
pointer-events: all;
}
.gome-img {
user-select: none;
}
.gome-img[src^='./img/desktop'] {
width: auto;
max-width: min(1280px, 100%);
}
.gome-img[src^='./img/tablet'] {
display: none;
max-width: 100%;
}
.gome-img[src^='./img/mobile'] {
display: none;
max-width: 100%;
}
#wotd {
font-size: 18px;
}
#wotd h3 {
font-family: Optima, 'Palatino Linotype', Lora, serif;
font-size: 1.2em;
margin: 0 0 0.5em 0;
}
#wotd .definiendum {
font-size: 1.5em;
font-weight: bold;
margin-bottom: 0.5em;
}
#wotd time, #wotd .pronunciation {
display: block;
margin-bottom: 1em;
}
.pronunciation:not(:empty)::before, .pronunciation:not(:empty)::after {
content: '';
}
#wotd ul {
margin: 0 0 1em 0;
padding-left: 0.5em;
list-style: none;
}
#wotd li {
margin-bottom: 0.25em;
}
@media only screen and (max-width: 960px) {
body {
grid-template-rows: min-content auto min-content;
}
header {
grid-column: 1 / span 2;
grid-row: 1;
width: 100%;
}
main {
grid-row: 2;
}
footer {
grid-row: 3;
}
.title-box {
border-left: none;
height: 1em;
width: 100%;
}
nav {
opacity: 1;
pointer-events: all;
}
.gome-img[src^='./img/desktop'] {
display: none;
}
.gome-img[src^='./img/tablet'] {
display: initial;
}
}
@media only screen and (max-width: 640px) {
footer {
align-items: flex-end;
}
.gome-img[src^='./img/tablet'] {
display: none;
}
.gome-img[src^='./img/mobile'] {
display: initial;
}
}
</style>
</head>
<body>
<header id='header'>
<div class='title-box'>
<span class='title'>gomepage</span>
</div>
<nav>
<a href='journal'><span class='link-title'>Journal</span> <span class='link-description'>a collection of articles, essays, and posts authored by me.</span></a>
<a href='bookmarks'><span class='link-title'>Bookmarks</span> <span class='link-description'>some curated lists of web pages I want to keep track of and share with others.</span></a>
<a href='socials' class='new'><span class='link-title'>Socials</span> <span class='link-description'>other accounts of mine around the web.</span></a>
</nav>
</header>
<main>
<article id='wotd'>
<h3 class='title'>Word of the day</h3>
<time class='date'></time>
<div class='definiendum'></div>
<div class='pronunciation'></div>
</article>
</main>
<footer>
<img src='./img/desktop_gomes.webp' class='gome-img' alt='Kabouters at work' />
<img src='./img/tablet_gomes.webp' class='gome-img' alt='Kabouters at work' />
<img src='./img/mobile_gome.webp' class='gome-img' alt='Lone kabouter' />
</footer>
<script>
const header = document.querySelector('#header');
const nav = header.querySelector('nav');
const revealNav = () => {
nav.classList.add('show');
}
const hideNav = () => {
nav.classList.remove('show');
}
header.addEventListener('click', e => {
if (!nav.contains(e.target) && nav !== e.target) {
if (nav.classList.contains('show')) {
hideNav();
}
else if (!nav.classList.contains('show')) {
revealNav();
}
}
});
window.addEventListener('click', e => {
if (!header.contains(e.target) && header !== e.target) {
hideNav();
}
});
</script>
<script type='module'>
const months = ['January','February','March','April','June','July','August','September','October','November','December'];
const wotd = document.querySelector('#wotd');
const today = new Date();
let entry;
try {
let day = today.getDate().toString();
if (day.length === 1) {
day = '0' + day;
}
let month = (today.getMonth() + 1).toString();
if (month.length === 1) {
month = '0' + month;
}
const response = await fetch(`./wotd/${today.getFullYear()}.${month}.${day}.json`);
if (!response.ok) {
throw new Error(`HTTP response ${response.status} ${response.statusText}`);
}
entry = await response.json();
} catch (e) {
console.error('Word of the Day error:', e);
}
if (!entry) {
document.querySelector('#wotd').remove();
} else {
wotd.querySelector('.date').textContent = today.getDate() + ' ' + months[today.getMonth()] + ' ' + today.getFullYear();
wotd.querySelector('.definiendum').textContent = entry.word;
wotd.querySelector('.pronunciation').textContent = entry.pronunciation;
let definitionHTML = '';
for (const definitionEntry of entry.definitions) {
definitionHTML += `<h3 class='part-of-speech'>${definitionEntry.part}</h4>`;
definitionHTML += `<ul class='definitions'>`;
for (const definition of definitionEntry.definitions) {
definitionHTML += `<li class='definition'>${definition}</li>`
}
definitionHTML += `</ul>`;
}
wotd.innerHTML += definitionHTML;
}
</script>
</body>
</html>