Initial commit

This commit is contained in:
Bad Manners 2024-03-20 00:56:57 -03:00
commit 09a1919d36
152 changed files with 22845 additions and 0 deletions

View file

@ -0,0 +1,29 @@
---
import '@fontsource-variable/noto-serif';
import "../styles/base.css"
const { pageTitle } = Astro.props
---
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png" />
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png" />
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png" />
<link rel="manifest" href="/site.webmanifest" />
<link rel="mask-icon" href="/safari-pinned-tab.svg" color="#37b340" />
<meta name="msapplication-TileColor" content="#37b340" />
<meta name="theme-color" content="#ffffff" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="generator" content={Astro.generator} />
<title>{pageTitle || 'Gallery'} | Bad Manners</title>
<link rel="alternate" type="application/rss+xml" title="Gallery | Bad Manners" href={`${Astro.site}feed.xml`} />
</head>
<body>
<slot />
<script>
import '../scripts/dark-mode.ts'
import '../scripts/verify-age.ts'
</script>
</body>
</html>

View file

@ -0,0 +1,53 @@
---
import { Image } from 'astro:assets'
import BaseLayout from './BaseLayout.astro'
import Navigation from '../components/Navigation.astro'
import logoBM from '../assets/images/logo_bm.png'
const { pageTitle } = Astro.props
---
<BaseLayout pageTitle={pageTitle}>
<div class="flex flex-col min-h-screen md:flex-row bg-stone-200 dark:bg-stone-800 text-stone-800 dark:text-stone-200">
<div class="text-stone-900 dark:text-stone-100 flex static md:fixed md:inset-y-0 md:left-0 md:w-60 bg-bm-300 dark:bg-green-900 flex-col items-center text-center pt-10 md:pt-20 shadow-xl mb-4 md:mb-0">
<Image loading="eager" src={logoBM} alt="Logo for Bad Manners" class="w-full max-w-48 shadow-md my-4 border-2 border-green-950 rounded-sm" />
<span class="text-2xl font-semibold my-2">Bad Manners</span>
<Navigation />
<div class="pt-4 text-center text-xs text-black dark:text-white">
<span>&copy; 2024</span>
</div>
<div class="flex items-center gap-x-1 mt-2 pb-10">
<a class="p-1 text-link" href="https://badmanners.xyz/" target="_blank" aria-label="Main website">
<svg viewBox="0 0 576 512" class="fill-current w-6 h-6" aria-hidden="true">
<path d="M575.8 255.5c0 18-15 32.1-32 32.1h-32l.7 160.2c0 2.7-.2 5.4-.5 8.1V472c0 22.1-17.9 40-40 40H456c-1.1 0-2.2 0-3.3-.1c-1.4 .1-2.8 .1-4.2 .1H416 392c-22.1 0-40-17.9-40-40V448 384c0-17.7-14.3-32-32-32H256c-17.7 0-32 14.3-32 32v64 24c0 22.1-17.9 40-40 40H160 128.1c-1.5 0-3-.1-4.5-.2c-1.2 .1-2.4 .2-3.6 .2H104c-22.1 0-40-17.9-40-40V360c0-.9 0-1.9 .1-2.8V287.6H32c-18 0-32-14-32-32.1c0-9 3-17 10-24L266.4 8c7-7 15-8 22-8s15 2 21 7L564.8 231.5c8 7 12 15 11 24z"/>
</svg>
</a>
<a class="p-1 text-link" href="/feed.xml" target="_blank" aria-label="RSS feed">
<svg viewBox="0 0 448 512" class="fill-current w-6 h-6" aria-hidden="true">
<path d="M64 32C28.7 32 0 60.7 0 96V416c0 35.3 28.7 64 64 64H384c35.3 0 64-28.7 64-64V96c0-35.3-28.7-64-64-64H64zM96 136c0-13.3 10.7-24 24-24c137 0 248 111 248 248c0 13.3-10.7 24-24 24s-24-10.7-24-24c0-110.5-89.5-200-200-200c-13.3 0-24-10.7-24-24zm0 96c0-13.3 10.7-24 24-24c83.9 0 152 68.1 152 152c0 13.3-10.7 24-24 24s-24-10.7-24-24c0-57.4-46.6-104-104-104c-13.3 0-24-10.7-24-24zm0 120a32 32 0 1 1 64 0 32 32 0 1 1 -64 0z"/>
</svg>
</a>
<a class="p-1 text-link" href="/licenses.txt" target="_blank" aria-label="Licenses">
<svg viewBox="0 0 640 512" class="fill-current w-6 h-6" aria-hidden="true">
<path d="M384 32H512c17.7 0 32 14.3 32 32s-14.3 32-32 32H398.4c-5.2 25.8-22.9 47.1-46.4 57.3V448H512c17.7 0 32 14.3 32 32s-14.3 32-32 32H320 128c-17.7 0-32-14.3-32-32s14.3-32 32-32H288V153.3c-23.5-10.3-41.2-31.6-46.4-57.3H128c-17.7 0-32-14.3-32-32s14.3-32 32-32H256c14.6-19.4 37.8-32 64-32s49.4 12.6 64 32zm55.6 288H584.4L512 195.8 439.6 320zM512 416c-62.9 0-115.2-34-126-78.9c-2.6-11 1-22.3 6.7-32.1l95.2-163.2c5-8.6 14.2-13.8 24.1-13.8s19.1 5.3 24.1 13.8l95.2 163.2c5.7 9.8 9.3 21.1 6.7 32.1C627.2 382 574.9 416 512 416zM126.8 195.8L54.4 320H199.3L126.8 195.8zM.9 337.1c-2.6-11 1-22.3 6.7-32.1l95.2-163.2c5-8.6 14.2-13.8 24.1-13.8s19.1 5.3 24.1 13.8l95.2 163.2c5.7 9.8 9.3 21.1 6.7 32.1C242 382 189.7 416 126.8 416S11.7 382 .9 337.1z"/>
</svg>
</a>
<button id="button-dark-mode" class="p-1 text-link" aria-label="Toggle dark mode">
<svg viewBox="0 0 512 512" class="fill-current w-6 h-6 hidden dark:block" aria-hidden="true">
<path
d="M361.5 1.2c5 2.1 8.6 6.6 9.6 11.9L391 121l107.9 19.8c5.3 1 9.8 4.6 11.9 9.6s1.5 10.7-1.6 15.2L446.9 256l62.3 90.3c3.1 4.5 3.7 10.2 1.6 15.2s-6.6 8.6-11.9 9.6L391 391 371.1 498.9c-1 5.3-4.6 9.8-9.6 11.9s-10.7 1.5-15.2-1.6L256 446.9l-90.3 62.3c-4.5 3.1-10.2 3.7-15.2 1.6s-8.6-6.6-9.6-11.9L121 391 13.1 371.1c-5.3-1-9.8-4.6-11.9-9.6s-1.5-10.7 1.6-15.2L65.1 256 2.8 165.7c-3.1-4.5-3.7-10.2-1.6-15.2s6.6-8.6 11.9-9.6L121 121 140.9 13.1c1-5.3 4.6-9.8 9.6-11.9s10.7-1.5 15.2 1.6L256 65.1 346.3 2.8c4.5-3.1 10.2-3.7 15.2-1.6zM160 256a96 96 0 1 1 192 0 96 96 0 1 1 -192 0zm224 0a128 128 0 1 0 -256 0 128 128 0 1 0 256 0z"
/>
</svg>
<svg viewBox="0 0 512 512" class="fill-current w-6 h-6 block dark:hidden" aria-hidden="true">
<path
d="M223.5 32C100 32 0 132.3 0 256S100 480 223.5 480c60.6 0 115.5-24.2 155.8-63.4c5-4.9 6.3-12.5 3.1-18.7s-10.1-9.7-17-8.5c-9.8 1.7-19.8 2.6-30.1 2.6c-96.9 0-175.5-78.8-175.5-176c0-65.8 36-123.1 89.3-153.3c6.1-3.5 9.2-10.5 7.7-17.3s-7.3-11.9-14.3-12.5c-6.3-.5-12.6-.8-19-.8z"
/>
</svg>
</button>
</div>
</div>
<main class="grow-0 ml-0 md:ml-60 px-2 pb-12 md:px-4 pt-4 max-w-6xl">
<slot />
</main>
</div>
</BaseLayout>

View file

@ -0,0 +1,103 @@
---
import { Image } from 'astro:assets'
import { type CollectionEntry } from 'astro:content'
import { Markdown } from '@astropub/md'
import { format as formatDate } from 'date-fns'
import { enUS as enUSLocale } from 'date-fns/locale/en-US'
import { slug } from 'github-slugger'
import BaseLayout from './BaseLayout.astro'
import Authors from '../components/Authors.astro'
import CopyrightedCharacters from '../components/CopyrightedCharacters.astro'
import Prose from '../components/Prose.astro'
type Props = CollectionEntry<'games'>['data']
const { props } = Astro
//const relatedStories = (await Promise.all((props.relatedStories || []).map(story => getEntry(story)))).filter(story => !story.data.isDraft)
// const relatedGames = (await Promise.all((props.relatedGames || []).map(game => getEntry(game)))).filter(game => !game.data.isDraft)
---
<BaseLayout pageTitle={props.title}>
<div id="top" class="relative min-w-screen min-h-screen px-1 pt-20 pb-16 bg-radial from-bm-300 to-bm-600 dark:from-green-700 dark:to-green-950 print:bg-none">
<div id="toolbox-buttons" aria-label="Toolbox" class="absolute top-0 h-[80vh] lg:inset-y-0 lg:h-full py-2 pl-2">
<div class="sticky top-6 rounded-full bg-white dark:bg-black shadow-md py-1 px-1 flex print:hidden">
<a href={props.series ? Object.values(props.series)[0] : "/games"} class="p-2 my-1 w-9 h-9 text-link" aria-label={`Return to ${props.series ? Object.keys(props.series)[0] : 'games'}`}>
<svg viewBox="0 0 512 512" class="fill-current" aria-hidden="true">
<path d="M48.5 224H40c-13.3 0-24-10.7-24-24V72c0-9.7 5.8-18.5 14.8-22.2s19.3-1.7 26.2 5.2L98.6 96.6c87.6-86.5 228.7-86.2 315.8 1c87.5 87.5 87.5 229.3 0 316.8s-229.3 87.5-316.8 0c-12.5-12.5-12.5-32.8 0-45.3s32.8-12.5 45.3 0c62.5 62.5 163.8 62.5 226.3 0s62.5-163.8 0-226.3c-62.2-62.2-162.7-62.5-225.3-1L185 183c6.9 6.9 8.9 17.2 5.2 26.2s-12.5 14.8-22.2 14.8H48.5z"/>
</svg>
</a>
<a href="#description" class="p-2 my-1 w-9 h-9 border-l border-stone-300 dark:border-stone-700 text-link" aria-label="Go to description">
<svg viewBox="0 0 512 512" class="fill-current" aria-hidden="true">
<path d="M256 512A256 256 0 1 0 256 0a256 256 0 1 0 0 512zM216 336h24V272H216c-13.3 0-24-10.7-24-24s10.7-24 24-24h48c13.3 0 24 10.7 24 24v88h8c13.3 0 24 10.7 24 24s-10.7 24-24 24H216c-13.3 0-24-10.7-24-24s10.7-24 24-24zm40-208a32 32 0 1 1 0 64 32 32 0 1 1 0-64z"/>
</svg>
</a>
<button id="button-dark-mode" class="p-2 my-1 w-9 h-9 border-l border-stone-300 dark:border-stone-700 text-link" aria-label="Toggle dark mode">
<svg viewBox="0 0 512 512" class="fill-current hidden dark:block" aria-hidden="true">
<path
d="M361.5 1.2c5 2.1 8.6 6.6 9.6 11.9L391 121l107.9 19.8c5.3 1 9.8 4.6 11.9 9.6s1.5 10.7-1.6 15.2L446.9 256l62.3 90.3c3.1 4.5 3.7 10.2 1.6 15.2s-6.6 8.6-11.9 9.6L391 391 371.1 498.9c-1 5.3-4.6 9.8-9.6 11.9s-10.7 1.5-15.2-1.6L256 446.9l-90.3 62.3c-4.5 3.1-10.2 3.7-15.2 1.6s-8.6-6.6-9.6-11.9L121 391 13.1 371.1c-5.3-1-9.8-4.6-11.9-9.6s-1.5-10.7 1.6-15.2L65.1 256 2.8 165.7c-3.1-4.5-3.7-10.2-1.6-15.2s6.6-8.6 11.9-9.6L121 121 140.9 13.1c1-5.3 4.6-9.8 9.6-11.9s10.7-1.5 15.2 1.6L256 65.1 346.3 2.8c4.5-3.1 10.2-3.7 15.2-1.6zM160 256a96 96 0 1 1 192 0 96 96 0 1 1 -192 0zm224 0a128 128 0 1 0 -256 0 128 128 0 1 0 256 0z"
/>
</svg>
<svg viewBox="0 0 512 512" class="fill-current block dark:hidden" aria-hidden="true">
<path
d="M223.5 32C100 32 0 132.3 0 256S100 480 223.5 480c60.6 0 115.5-24.2 155.8-63.4c5-4.9 6.3-12.5 3.1-18.7s-10.1-9.7-17-8.5c-9.8 1.7-19.8 2.6-30.1 2.6c-96.9 0-175.5-78.8-175.5-176c0-65.8 36-123.1 89.3-153.3c6.1-3.5 9.2-10.5 7.7-17.3s-7.3-11.9-14.3-12.5c-6.3-.5-12.6-.8-19-.8z"
/>
</svg>
</button>
</div>
</div>
<main class="mx-auto max-w-3xl px-2 pt-1 pb-4 rounded-lg shadow-sm bg-stone-50 dark:bg-stone-900 print:bg-none print:shadow-none print:max-w-full">
<h1 id="game-title" class="px-2 pt-2 font-serif text-3xl font-semibold text-stone-800 dark:text-stone-100">{props.title}</h1>
<section id="game-information" class="px-2 mt-1 space-y-2 font-serif italic text-stone-600 dark:text-stone-200 font-light">
<Authors authors={props.authors} lang={props.lang} />
{props.isDraft ?
<p id="draft-warning" class="text-center text-red-600 text-2xl not-italic font-semibold py-2">
DRAFT VERSION &ndash; DO NOT REDISTRIBUTE
</p> : null
}
<div id="content-warning">
<p>{props.contentWarning}</p>
</section>
</section>
<hr class="mx-auto my-10 border-stone-400 dark:border-stone-600 w-[80%] max-w-xl" />
{props.thumbnail && <Image loading="eager" src={props.thumbnail} alt={`Cover art for ${props.title}`} width={props.thumbnailWidth} height={props.thumbnailHeight} class="my-5 mx-auto shadow-lg" />}
<hr class="mx-auto my-10 border-stone-400 dark:border-stone-600 w-[80%] max-w-xl" />
<article id="story" class="font-serif pr-1">
<Prose>
<slot />
</Prose>
</article>
<hr class="mx-auto mt-10 mb-6 border-stone-400 dark:border-stone-600 w-[80%] max-w-xl" />
{props.isDraft ?
<p id="draft-warning-bottom" class="text-center font-serif text-red-600 text-2xl not-italic font-semibold py-2">
DRAFT VERSION &ndash; DO NOT REDISTRIBUTE
</p> :
<p id="publish-date" class="px-2 mt-2 text-center font-serif italic text-stone-600 dark:text-stone-200" aria-label="Publish date" aria-description={formatDate(props.pubDate, 'MMMM do, yyyy', { locale: enUSLocale })}>
{formatDate(props.pubDate, 'yyyy-MM-dd')}
</p>
}
<section id="description" class="px-2 font-serif" aria-describedby="title-description">
<h2 id="title-description" class="py-2 font-serif text-xl font-semibold text-stone-800 dark:text-stone-100">Description</h2>
<Prose>
<Markdown of={props.description} />
<CopyrightedCharacters copyrightedCharacters={props.copyrightedCharacters} lang={props.lang} />
</Prose>
</section>
<div class="text-right pr-3 print:hidden">
<a href="#top" class="text-link inline-flex items-center underline"><svg class="w-6 h-6 mr-1 fill-current" viewBox="0 0 384 512" aria-hidden="true"><path d="M214.6 41.4c-12.5-12.5-32.8-12.5-45.3 0l-160 160c-12.5 12.5-12.5 32.8 0 45.3s32.8 12.5 45.3 0L160 141.2V448c0 17.7 14.3 32 32 32s32-14.3 32-32V141.2L329.4 246.6c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3l-160-160z"/></svg><span>To top</span></a>
</div>
<section id="tags" aria-describedby="title-tags" class="my-5">
<h2 id="title-tags" class="p-2 font-serif text-xl font-semibold text-stone-800 dark:text-stone-100">Tags</h2>
<ul class="px-2 flex flex-wrap gap-x-2 gap-y-2">
{ props.tags.map(tag =>
<li class="text-sm rounded-full shadow-sm px-3 py-1 bg-bm-300 text-black dark:bg-bm-600 dark:text-white print:bg-none"><a class="focus:underline hover:underline" href={`/tags/${slug(tag)}`}>{tag}</a></li>
) }
</ul>
</section>
</main>
<div class="pt-6 text-center text-xs text-black dark:text-white">
<span>&copy; {formatDate(props.pubDate, 'yyyy')} | </span>
<a class="focus:underline hover:underline" href="/licenses.txt" target="_blank">Licenses</a>
</div>
</div>
</BaseLayout>

View file

@ -0,0 +1,171 @@
---
import { Image } from 'astro:assets'
import { getEntry, type CollectionEntry } from 'astro:content'
import { Markdown } from '@astropub/md'
import { format as formatDate } from 'date-fns'
import { enUS as enUSLocale } from 'date-fns/locale/en-US'
import { slug } from 'github-slugger'
import BaseLayout from './BaseLayout.astro'
import Authors from '../components/Authors.astro'
import UserComponent from '../components/UserComponent.astro'
import CopyrightedCharacters from '../components/CopyrightedCharacters.astro'
import Prose from '../components/Prose.astro'
type Props = CollectionEntry<'stories'>['data']
const { props } = Astro
let prev = props.prev && (await getEntry(props.prev))
if (prev && prev.data.isDraft) {
prev = undefined
}
let next = props.next && (await getEntry(props.next))
if (next && next.data.isDraft) {
next = undefined
}
const relatedStories = (await Promise.all((props.relatedStories || []).map(story => getEntry(story)))).filter(story => !story.data.isDraft)
// const relatedGames = (await Promise.all((props.relatedGames || []).map(game => getEntry(game)))).filter(game => !game.data.isDraft)
---
<BaseLayout pageTitle={props.title}>
<div id="top" class="relative min-w-screen min-h-screen px-1 pt-20 pb-16 bg-radial from-bm-300 to-bm-600 dark:from-green-700 dark:to-green-950 print:bg-none">
<div id="toolbox-buttons" aria-label="Toolbox" class="absolute top-0 h-[80vh] lg:inset-y-0 lg:h-full py-2 pl-2">
<div class="sticky top-6 rounded-full bg-white dark:bg-black shadow-md py-1 px-1 flex print:hidden">
<a href={props.series ? Object.values(props.series)[0] : "/stories/1"} class="p-2 my-1 w-9 h-9 text-link" aria-label={`Return to ${props.series ? Object.keys(props.series)[0] : 'stories'}`}>
<svg viewBox="0 0 512 512" class="fill-current" aria-hidden="true">
<path d="M48.5 224H40c-13.3 0-24-10.7-24-24V72c0-9.7 5.8-18.5 14.8-22.2s19.3-1.7 26.2 5.2L98.6 96.6c87.6-86.5 228.7-86.2 315.8 1c87.5 87.5 87.5 229.3 0 316.8s-229.3 87.5-316.8 0c-12.5-12.5-12.5-32.8 0-45.3s32.8-12.5 45.3 0c62.5 62.5 163.8 62.5 226.3 0s62.5-163.8 0-226.3c-62.2-62.2-162.7-62.5-225.3-1L185 183c6.9 6.9 8.9 17.2 5.2 26.2s-12.5 14.8-22.2 14.8H48.5z"/>
</svg>
</a>
<a href="#description" class="p-2 my-1 w-9 h-9 border-l border-stone-300 dark:border-stone-700 text-link" aria-label="Go to description">
<svg viewBox="0 0 512 512" class="fill-current" aria-hidden="true">
<path d="M256 512A256 256 0 1 0 256 0a256 256 0 1 0 0 512zM216 336h24V272H216c-13.3 0-24-10.7-24-24s10.7-24 24-24h48c13.3 0 24 10.7 24 24v88h8c13.3 0 24 10.7 24 24s-10.7 24-24 24H216c-13.3 0-24-10.7-24-24s10.7-24 24-24zm40-208a32 32 0 1 1 0 64 32 32 0 1 1 0-64z"/>
</svg>
</a>
<button id="button-dark-mode" class="p-2 my-1 w-9 h-9 border-l border-stone-300 dark:border-stone-700 text-link" aria-label="Toggle dark mode">
<svg viewBox="0 0 512 512" class="fill-current hidden dark:block" aria-hidden="true">
<path
d="M361.5 1.2c5 2.1 8.6 6.6 9.6 11.9L391 121l107.9 19.8c5.3 1 9.8 4.6 11.9 9.6s1.5 10.7-1.6 15.2L446.9 256l62.3 90.3c3.1 4.5 3.7 10.2 1.6 15.2s-6.6 8.6-11.9 9.6L391 391 371.1 498.9c-1 5.3-4.6 9.8-9.6 11.9s-10.7 1.5-15.2-1.6L256 446.9l-90.3 62.3c-4.5 3.1-10.2 3.7-15.2 1.6s-8.6-6.6-9.6-11.9L121 391 13.1 371.1c-5.3-1-9.8-4.6-11.9-9.6s-1.5-10.7 1.6-15.2L65.1 256 2.8 165.7c-3.1-4.5-3.7-10.2-1.6-15.2s6.6-8.6 11.9-9.6L121 121 140.9 13.1c1-5.3 4.6-9.8 9.6-11.9s10.7-1.5 15.2 1.6L256 65.1 346.3 2.8c4.5-3.1 10.2-3.7 15.2-1.6zM160 256a96 96 0 1 1 192 0 96 96 0 1 1 -192 0zm224 0a128 128 0 1 0 -256 0 128 128 0 1 0 256 0z"
/>
</svg>
<svg viewBox="0 0 512 512" class="fill-current block dark:hidden" aria-hidden="true">
<path
d="M223.5 32C100 32 0 132.3 0 256S100 480 223.5 480c60.6 0 115.5-24.2 155.8-63.4c5-4.9 6.3-12.5 3.1-18.7s-10.1-9.7-17-8.5c-9.8 1.7-19.8 2.6-30.1 2.6c-96.9 0-175.5-78.8-175.5-176c0-65.8 36-123.1 89.3-153.3c6.1-3.5 9.2-10.5 7.7-17.3s-7.3-11.9-14.3-12.5c-6.3-.5-12.6-.8-19-.8z"
/>
</svg>
</button>
</div>
</div>
<main class="mx-auto max-w-3xl px-2 pt-1 pb-4 rounded-lg shadow-sm bg-stone-50 dark:bg-stone-900 print:bg-none print:shadow-none print:max-w-full">
{(prev || next) ?
<div class="print:hidden">
<div id="story-nav-top" class="my-4 grid grid-cols-2 gap-2 justify-items-stretch">
{prev ?
<a href={`/stories/${prev.slug}`} class="py-3 px-1 flex justify-center items-center underline font-light text-link border-r border-stone-400 dark:border-stone-600">
<svg class="mr-1 w-5 h-5 fill-current" viewBox="0 0 320 512"><path d="M9.4 233.4c-12.5 12.5-12.5 32.8 0 45.3l192 192c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3L77.3 256 246.6 86.6c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0l-192 192z"/></svg>
<span>Previous: {prev.data.shortTitle || prev.data.title}</span>
</a> : <div class="h-full border-r border-stone-400 dark:border-stone-600"></div>
}
{next ?
<a href={`/stories/${next.slug}`} class="py-3 px-1 flex justify-center items-center underline font-light text-link">
<span>Next: {next.data.shortTitle || next.data.title}</span>
<svg class="ml-1 w-5 h-5 fill-current" viewBox="0 0 320 512"><path d="M310.6 233.4c12.5 12.5 12.5 32.8 0 45.3l-192 192c-12.5 12.5-32.8 12.5-45.3 0s-12.5-32.8 0-45.3L242.7 256 73.4 86.6c-12.5-12.5-12.5-32.8 0-45.3s32.8-12.5 45.3 0l192 192z"/></svg>
</a> : <div></div>
}
</div>
<hr class="mx-auto mb-5 border-stone-400 dark:border-stone-600 w-full max-w-2xl" />
</div> : null
}
<h1 id="story-title" class="px-2 pt-2 font-serif text-3xl font-semibold text-stone-800 dark:text-stone-100">{props.title}</h1>
<section id="story-information" class="px-2 mt-1 space-y-2 font-serif italic text-stone-600 dark:text-stone-200 font-light">
<Authors authors={props.authors} lang={props.lang} />
{props.isDraft ?
<p id="draft-warning" class="text-center text-red-600 text-2xl not-italic font-semibold py-2">
DRAFT VERSION &ndash; DO NOT REDISTRIBUTE
</p> : null
}
{props.commissioner &&
<p id="commissioner">
Commissioned by <UserComponent user={props.commissioner} />
</p>}
{props.requester &&
<p id="requester">
Requested by <UserComponent user={props.requester} />
</p>}
<div id="content-warning">
<p>{props.lang === 'eng' ? `Word count: ${props.wordCount}.` : props.lang === 'tok' ? `` : null} {props.contentWarning}</p>
</section>
</section>
<hr class="mx-auto my-10 border-stone-400 dark:border-stone-600 w-[80%] max-w-xl" />
{props.thumbnail && <Image loading="eager" src={props.thumbnail} alt={`Cover art for ${props.title}`} width={props.thumbnailWidth} height={props.thumbnailHeight} class="my-5 mx-auto shadow-lg" />}
<hr class="mx-auto my-10 border-stone-400 dark:border-stone-600 w-[80%] max-w-xl" />
<article id="story" class="font-serif pr-1">
<Prose>
<slot />
</Prose>
</article>
<hr class="mx-auto mt-10 mb-6 border-stone-400 dark:border-stone-600 w-[80%] max-w-xl" />
{props.isDraft ?
<p id="draft-warning-bottom" class="text-center font-serif text-red-600 text-2xl not-italic font-semibold py-2">
DRAFT VERSION &ndash; DO NOT REDISTRIBUTE
</p> :
<p id="publish-date" class="px-2 mt-2 text-center font-serif italic text-stone-600 dark:text-stone-200" aria-label="Publish date" aria-description={formatDate(props.pubDate, 'MMMM do, yyyy', { locale: enUSLocale })}>
{formatDate(props.pubDate, 'yyyy-MM-dd')}
</p>
}
<section id="description" class="px-2 font-serif" aria-describedby="title-description">
<h2 id="title-description" class="py-2 font-serif text-xl font-semibold text-stone-800 dark:text-stone-100">{props.lang === 'eng' ? 'Description' : props.lang === 'tok' ? 'lipu lili' : null}</h2>
<Prose>
<Markdown of={props.description} />
<CopyrightedCharacters copyrightedCharacters={props.copyrightedCharacters} lang={props.lang} />
</Prose>
</section>
<div class="text-right pr-3 print:hidden">
<a href="#top" class="text-link inline-flex items-center underline"><svg class="w-6 h-6 mr-1 fill-current" viewBox="0 0 384 512" aria-hidden="true"><path d="M214.6 41.4c-12.5-12.5-32.8-12.5-45.3 0l-160 160c-12.5 12.5-12.5 32.8 0 45.3s32.8 12.5 45.3 0L160 141.2V448c0 17.7 14.3 32 32 32s32-14.3 32-32V141.2L329.4 246.6c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3l-160-160z"/></svg><span>{props.lang === 'eng' ? 'To top' : props.lang === 'tok' ? 'tawa sewi' : null}</span></a>
</div>
{(prev || next) ?
<Fragment>
<hr class="mx-auto mt-5 border-stone-400 dark:border-stone-600 w-full max-w-2xl" />
<div id="story-nav-top" class="my-4 grid grid-cols-2 gap-2 justify-items-stretch">
{prev ?
<a href={`/stories/${prev.slug}`} class="py-3 px-1 flex justify-center items-center underline font-light text-link border-r border-stone-400 dark:border-stone-600">
<svg class="mr-1 w-5 h-5 fill-current" viewBox="0 0 320 512"><path d="M9.4 233.4c-12.5 12.5-12.5 32.8 0 45.3l192 192c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3L77.3 256 246.6 86.6c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0l-192 192z"/></svg>
<span>Previous: {prev.data.shortTitle || prev.data.title}</span>
</a> : <div class="h-full border-r border-stone-400 dark:border-stone-600"></div>
}
{next ?
<a href={`/stories/${next.slug}`} class="py-3 px-1 flex justify-center items-center underline font-light text-link">
<span>Next: {next.data.shortTitle || next.data.title}</span>
<svg class="ml-1 w-5 h-5 fill-current" viewBox="0 0 320 512"><path d="M310.6 233.4c12.5 12.5 12.5 32.8 0 45.3l-192 192c-12.5 12.5-32.8 12.5-45.3 0s-12.5-32.8 0-45.3L242.7 256 73.4 86.6c-12.5-12.5-12.5-32.8 0-45.3s32.8-12.5 45.3 0l192 192z"/></svg>
</a> : <div></div>
}
</div>
<hr class="mx-auto mb-5 border-stone-400 dark:border-stone-600 w-full max-w-2xl" />
</Fragment> : null
}
{
relatedStories.length > 0 ?
<section id="related" aria-describedby="title-related" class="my-5">
<h2 id="title-related" class="p-2 font-serif text-xl font-semibold text-stone-800 dark:text-stone-100">Related stories</h2>
<Prose>
<ul>
{ relatedStories.map(stories =>
<li><a href={`/stories/${stories.slug}`}>{stories.data.title}</a></li>
) }
</ul>
</Prose>
</section> : null
}
<section id="tags" aria-describedby="title-tags" class="my-5">
<h2 id="title-tags" class="p-2 font-serif text-xl font-semibold text-stone-800 dark:text-stone-100">{props.lang === 'eng' ? 'Tags' : props.lang === 'tok' ? 'nimi kulupu' : null}</h2>
<ul class="px-2 flex flex-wrap gap-x-2 gap-y-2">
{ props.tags.map(tag =>
<li class="text-sm rounded-full shadow-sm px-3 py-1 bg-bm-300 text-black dark:bg-bm-600 dark:text-white print:bg-none"><a class="focus:underline hover:underline" href={`/tags/${slug(tag)}`}>{tag}</a></li>
) }
</ul>
</section>
</main>
<div class="pt-6 text-center text-xs text-black dark:text-white">
<span>&copy; {formatDate(props.pubDate, 'yyyy')} | </span>
<a class="focus:underline hover:underline" href="/licenses.txt" target="_blank">Licenses</a>
</div>
</div>
</BaseLayout>