/* =Tokens
-------------------------------------------------------------- */

:root {
	--ws-red: #ff3333;
	--ws-blue: #0066cc;
	--ws-ink: #000;
	--ws-text: #111;
	--ws-background: #fff;
	--ws-rule: #bbb;
	--ws-font-title: Oxanium, "Arial Narrow", sans-serif; /* Heaviest weight is 800. */
	--ws-font-display: Saira, Arial, sans-serif;
	--ws-font-body: Saira, Arial, sans-serif;
	--ws-font-brand: Impact, "Arial Narrow", "Roboto Condensed", sans-serif; /* Phones lack Impact, so they get Roboto Condensed Black. */
	--ws-wrap: 1050.8px; /* 37 cubes of 28.4px. */
	--ws-gutter: 16px;
	--ws-edge: #cfcfcf; /* Matches the darker teeth in edge-row.svg. */
	--ws-edge-tooth: 12.32px; /* How far each tooth reaches into the page. */
	--ws-edge-band: 20px; /* The lighter strip between the two rows of teeth. */
	--ws-page: 1420px; /* Width between the tips of the teeth. */
	--ws-header-height: 55px;
	/* The novels grid, shared with the header, the intro and the line above
	   the novels so they all line up. */
	--novels-columns: 4;
	--novels-column: 227px;
	--novels-gap: clamp(1.5rem, 6vw, 7.2rem);
	--novels-width: calc(var(--novels-columns) * var(--novels-column) + (var(--novels-columns) - 1) * var(--novels-gap));
	color-scheme: light dark;
}

/* Polar night, following the OS. The red stays; the blue is lifted to read on
   the dark. The SVGs carry their own dark styles with these same colours, so
   change them together. */
@media (prefers-color-scheme: dark) {
	:root {
		--ws-blue: #5aa9ff;
		--ws-ink: #f2f7fc;
		--ws-text: #dfe8f2;
		--ws-background: #0a0f17;
		--ws-rule: #2c3a4c;
		--ws-edge: #1f2b3a; /* Matches the darker teeth in edge-row.svg. */
	}
}

@media (max-width: 960px) {
	:root {
		--novels-columns: 2;
	}
}

/* =Base
-------------------------------------------------------------- */

*,
*::before,
*::after {
	box-sizing: border-box;
}

/* Anchors land below the sticky header rather than under it. */
html {
	scroll-padding-top: var(--ws-header-height);
}

@media (prefers-reduced-motion: no-preference) {
	html {
		scroll-behavior: smooth;
	}
}

body {
	position: relative;
	margin: 0;
	background: var(--ws-background);
	color: var(--ws-text);
	font: 1.125rem/1.55 var(--ws-font-body); /* Unitless, so each element scales it to its own size. */
	-webkit-font-smoothing: antialiased;
}

/* The grey edges either side of the page: a solid band ending in a row of
   teeth, then a lighter strip ending in a second row, repeated down the
   full height. edge-row.svg holds both rows, so it's the band and a tooth
   wide. The white page between them stays
   the same width, so the grey grows on wider screens and drops out of view
   on narrower ones. The right edge is the left one mirrored. */
body::before,
body::after {
	content: "";
	position: absolute;
	top: 0;
	bottom: 0;
	left: 0;
	z-index: -1;
	width: max(0px, (100% - var(--ws-page)) / 2);
	background:
		url("../../images/edge-row.svg") right top / calc(var(--ws-edge-band) + var(--ws-edge-tooth)) 21.12px repeat-y,
		linear-gradient(var(--ws-edge), var(--ws-edge)) left top / calc(100% - var(--ws-edge-band) - var(--ws-edge-tooth) + 1px) 100% no-repeat; /* 1px overlap hides the subpixel seam. */
	pointer-events: none;
}

body::after {
	right: 0;
	left: auto;
	transform: scaleX(-1);
}

img {
	max-width: 100%;
	height: auto;
}

a:focus-visible,
main:focus-visible {
	outline: 2px solid var(--ws-blue);
	outline-offset: 3px;
}

main:focus {
	outline: none;
}

.screen-reader-text:not(:focus) {
	position: absolute;
	width: 1px;
	height: 1px;
	overflow: hidden;
	clip-path: inset(50%);
	white-space: nowrap;
}

.skip-link:focus {
	position: absolute;
	top: 8px;
	left: 8px;
	z-index: 30;
	padding: 0.5em 1em;
	background: var(--ws-background);
	color: var(--ws-blue);
	font-family: var(--ws-font-display);
}

/* =Site header
-------------------------------------------------------------- */

/* A white bar across the full width, over the grey edges. On the front page
   it starts hidden above the novels, and site-header.js fades it in. */
.site-header {
	position: sticky;
	top: 0;
	z-index: 20;
	height: var(--ws-header-height);
	background: var(--ws-background);
	transition: opacity 0.3s, visibility 0.3s;
}

.js .has-intro .site-header:not(.is-shown) {
	opacity: 0;
	visibility: hidden;
}

.site-header__inner {
	display: flex;
	align-items: center;
	gap: 1.1rem;
	width: min(var(--novels-width), 100% - 2 * var(--ws-gutter));
	height: 100%;
	margin: 0 auto;
}

.site-header__home {
	flex: none;
}

.site-header__logo {
	display: block;
	width: 60px;
}

.site-header__tagline {
	margin: 0;
	color: var(--ws-red);
	font: 700 0.9375rem/1.55 var(--ws-font-display);
}

/* =Intro
-------------------------------------------------------------- */

/* With the header above it, the intro fills the first screen. */
.intro {
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	min-height: calc(100vh - var(--ws-header-height));
	min-height: calc(100svh - var(--ws-header-height));
	padding: 3rem var(--ws-gutter) 2.5rem;
}

.intro__inner {
	display: grid;
	grid-template-columns: auto minmax(0, 690px);
	justify-content: center;
	align-items: start;
	gap: 2rem clamp(2rem, 6vw, 5.3rem);
	width: min(100%, var(--novels-width));
}

.brand--stacked {
	flex-direction: column;
	align-items: flex-start;
	gap: 1.25rem;
}

.brand--stacked .brand__logo {
	width: 180px;
}

.intro__text {
	font: 400 1.25rem/1.55 var(--ws-font-display);
}

.intro__text > * {
	margin: 0 0 0.75em;
}

.intro__text > :last-child {
	margin-bottom: 0;
}

/* The About page's lede takes the shared .lede styles; it just needs more room beneath. */
.intro__text > .lede {
	margin-bottom: 1.25em;
}

@media (max-width: 760px) {
	.intro__inner {
		grid-template-columns: minmax(0, 1fr);
	}

	.brand--stacked {
		flex-direction: row;
		align-items: center;
	}

	.brand--stacked .brand__logo {
		width: clamp(110px, 25vw, 150px);
	}
}

/* =Splash
-------------------------------------------------------------- */

/* With the header above it, the novels fill the screen they scroll into. */
.splash {
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	min-height: calc(100vh - var(--ws-header-height));
	min-height: calc(100svh - var(--ws-header-height));
	padding: 3rem var(--ws-gutter) 2.5rem;
	text-align: center;
}

/* As wide as the novels grid at most, and narrower with it. */
.splash__intro {
	font-family: var(--ws-font-display);
	font-size: clamp(1.125rem, 1rem + 0.5vw, 1.25rem);
	line-height: 1.4;
	max-width: var(--novels-width);
	margin: 0 0 1.75rem;
	width: 100%;
}

.home-button {
	margin-top: clamp(3rem, 8vh, 6rem);
}

.brand {
	display: flex;
	align-items: center;
	gap: clamp(1rem, 2.5vw, 2.5rem);
	text-align: left;
}

.brand__logo {
	width: clamp(110px, 12vw, 150px);
	flex: none;
}

.brand__name {
	margin: 0 0 0.35em;
	color: var(--ws-blue);
	/* Impact only comes in one weight, so don't let the browser fake a bolder one;
	   900 picks Arial Narrow Bold or Roboto Condensed Black when Impact is missing. */
	font: 900 1.625rem/1 var(--ws-font-brand);
	font-synthesis: none;
	text-transform: uppercase;
}

.brand__tagline {
	max-width: 11.5em;
	margin: 0;
	color: var(--ws-red);
	font: 700 0.9375rem/1.55 var(--ws-font-display);
}

.splash__intro {
	font-size: 1.25rem;
}

.novels {
	display: grid;
	grid-template-columns: repeat(var(--novels-columns), minmax(0, var(--novels-column)));
	justify-content: center;
	gap: 3rem var(--novels-gap);
	width: 100%;
	margin: 0;
	padding: 0;
	list-style: none;
	text-align: left;
}

/* The link fills the art above the blurb, so the title drops to the bottom. */
.novel__link {
	display: flex;
	flex: 1;
	flex-direction: column;
	color: var(--ws-ink);
	text-decoration: none;
}

/*
 * Each cover is cut into one of three cube masks, in front of one of three
 * sets of pillars, with the title and blurb on top of them. Variation A is
 * the default, and novel-mask.js picks the others at random.
 *
 * The art is at least 227 by 540 at full width, and the pillars sit at the
 * bottom of that box. Both scale with the column, so the pillars stay tucked
 * under the cover at any width, even when the text makes the art taller.
 */
.novel__art {
	position: relative;
	isolation: isolate;
	display: flex;
	flex-direction: column;
	width: 100%;
	min-width: 0; /* Without both, Safari widens the art from its height, by the aspect ratio. */
	aspect-ratio: 227 / 540;
	padding-bottom: 2.5rem;
}

.novel__art::before {
	content: "";
	position: absolute;
	top: 0;
	right: 0;
	left: 0;
	z-index: -1;
	aspect-ratio: 227 / 540;
	background: url("../../images/masks/novels/novel-background-variation-a.svg") center bottom / 100% auto no-repeat;
	pointer-events: none;
}

.novel__art[data-background="b"]::before {
	background-image: url("../../images/masks/novels/novel-background-variation-b.svg");
}

.novel__art[data-background="c"]::before {
	background-image: url("../../images/masks/novels/novel-background-variation-c.svg");
}

.novel__image {
	display: block;
	width: 100%;
	height: auto;
	aspect-ratio: 227 / 367;
	object-fit: cover;
	-webkit-mask: url("../../images/masks/novels/novel-variation-a.svg") 0 0 / 100% 100% no-repeat;
	mask: url("../../images/masks/novels/novel-variation-a.svg") 0 0 / 100% 100% no-repeat;
}

.novel__art[data-mask="b"] .novel__image {
	aspect-ratio: 227 / 365;
	-webkit-mask-image: url("../../images/masks/novels/novel-variation-b.svg");
	mask-image: url("../../images/masks/novels/novel-variation-b.svg");
}

.novel__art[data-mask="c"] .novel__image {
	aspect-ratio: 227 / 359;
	-webkit-mask-image: url("../../images/masks/novels/novel-variation-c.svg");
	mask-image: url("../../images/masks/novels/novel-variation-c.svg");
}

.novel__title {
	margin: auto 0 0.6rem;
	padding: 1.25rem 12px 0;
	font: 900 clamp(1.5rem, 1.1rem + 0.8vw, 2rem)/0.95 var(--ws-font-brand);
	font-synthesis: none;
	text-transform: uppercase;
	transition: color 0.2s;
}

.novel__link:hover .novel__title {
	color: var(--ws-red);
}

.novel__tagline {
	max-width: calc(11em + 24px); /* 11em of text inside the padding. */
	margin: 0;
	padding: 0 12px;
	font: 600 1.35rem/1.1 var(--ws-font-display);
}

.novel__blurb {
	max-width: calc(11em + 24px); /* 11em of text inside the padding. */
	margin: 0.6rem 0 0;
	padding: 0 12px;
	font: 400 1.1rem/1.25 var(--ws-font-display);
}

/*
 * Where subgrid is supported, the novels in a row share their tracks, so the
 * titles, taglines and blurbs line up however many lines each one takes. The cover's
 * track is the only flexible one, so it takes the art's extra height.
 */
@supports (grid-template-rows: subgrid) {
	.novels {
		grid-auto-rows: 1fr auto auto auto;
	}

	.novel,
	.novel__art,
	.novel__link {
		display: grid;
		grid-template-rows: subgrid;
		row-gap: 0;
	}

	.novel,
	.novel__art {
		grid-row: span 4;
	}

	.novel__link {
		grid-row: span 2;
	}

	.novel__title {
		margin-top: 0;
	}
}

.home-button {
	display: inline-flex;
	flex-direction: column;
	align-items: center;
	gap: 0.5rem;
	color: var(--ws-ink);
	font: 900 0.9375rem/1 var(--ws-font-display);
	text-decoration: none;
	text-transform: uppercase;
}

.home-button img {
	width: 50px;
	transition: transform 0.2s;
}

.home-button:hover img {
	transform: translateY(4px);
}

/* =Stream
-------------------------------------------------------------- */

.stream {
	position: relative;
	width: min(var(--ws-wrap), 100% - 2 * var(--ws-gutter));
	margin-inline: auto;
	padding-block: 55px 60px;
}

.stream__bracket--top {
	position: absolute;
	top: 55px;
	left: 0;
	width: 96px;
}

.stream__bracket--bottom {
	display: block;
	width: 95px;
	margin: 2rem 0 0 auto;
}

.stream__empty {
	padding: 6rem 0;
	text-align: center;
}

.pagination {
	display: flex;
	justify-content: center;
	gap: 1.25rem;
	font: 900 1.125rem/1 var(--ws-font-display);
	text-transform: uppercase;
}

.pagination a {
	color: var(--ws-blue);
	text-decoration: none;
}

.pagination .current {
	color: var(--ws-red);
}

/* =Entry
-------------------------------------------------------------- */

.entry {
	margin-bottom: clamp(4rem, 10vw, 8rem);
}

.entry a:hover {
	text-decoration: underline;
}

.entry-header {
	margin-bottom: 1.5rem;
	padding: 0 50px 0 120px;
	text-align: right;
}

.entry-title {
	margin: 0 0 1rem;
	color: var(--ws-red);
	font: 800 clamp(2.25rem, 1.3rem + 2.6vw, 3.5rem)/1.05 var(--ws-font-title);
	text-wrap: balance;
}

.entry-title a {
	color: inherit;
	text-decoration: none;
}

.entry-meta {
	display: flex;
	flex-wrap: wrap;
	justify-content: flex-end;
	gap: 0.5rem 2rem;
	color: var(--ws-blue);
	font: 400 1rem/1.2 var(--ws-font-display);
}

.entry-meta a,
.entry-footer a {
	color: inherit;
	text-decoration: none;
}

.meta-item {
	display: inline-flex;
	align-items: center;
	gap: 0.4rem;
}

.meta-item svg {
	width: 16px;
	height: 16px;
	flex: none;
}

/* Without JavaScript or mask support, the hero is a plain rectangle. */
.hero {
	display: block;
	width: 100%;
	aspect-ratio: 1050 / 655;
	margin: 0 auto;
	overflow: hidden;
}

.hero.is-masked {
	aspect-ratio: auto;
	-webkit-mask-repeat: no-repeat;
	mask-repeat: no-repeat;
	-webkit-mask-size: 100% 100%;
	mask-size: 100% 100%;
}

.hero a,
.hero__image {
	display: block;
	width: 100%;
	height: 100%;
}

.hero__image {
	object-fit: cover;
	object-position: 50% 30%;
}

.entry-summary,
.entry-content,
.comments {
	margin-top: 0.75rem;
	padding: 0 50px 0 100px;
}

.entry-summary p {
	margin: 0 0 1em;
}

/* Blocks keep WordPress's own styles; this just sets the rhythm around them. */
.entry-content > * {
	margin-block: 0 1.25em;
}

.entry-content :is(h2, h3, h4, h5, h6) {
	margin-top: 1.75em;
	color: var(--ws-ink);
	font-family: var(--ws-font-title);
	font-weight: 800;
	line-height: 1.1;
}

/* The opening paragraph of a page: add "lede" under Advanced > Additional CSS class(es).
   Not scoped to .entry-content, so the About page's lede in the front page intro matches. */
.lede {
	font-family: var(--ws-font-title);
	font-size: 2rem;
	font-weight: 800;
	line-height: 1.2;
}

.entry-content a,
.comments a {
	color: var(--ws-blue);
}

.entry-content img,
.entry-content video,
.entry-content iframe {
	max-width: 100%;
}

.entry-content .alignwide,
.entry-content .alignfull {
	margin-inline: -100px -50px;
}

/* =Page
-------------------------------------------------------------- */

.page-main {
	width: min(var(--ws-wrap), 100% - 2 * var(--ws-gutter));
	margin-inline: auto;
	padding-block: 75px 60px;
}

/* Everything beneath the hero lines up just inside its edges. */
.entry--page {
	margin-bottom: clamp(3rem, 7vw, 5.5rem);
}

.entry--page .entry-header {
	margin: 1.5rem 0 1rem;
	padding: 0 32px;
}

.entry--page .entry-title {
	margin-bottom: 0.75rem;
}

.entry--page .entry-content {
	margin-top: 0;
	padding: 0 32px;
}

.entry--page .entry-content .alignwide,
.entry--page .entry-content .alignfull {
	margin-inline: -32px;
}

.page-footer {
	display: grid;
	grid-template-columns: 227px 1fr 195px;
	grid-template-rows: auto auto;
	align-items: start;
	column-gap: 24px;
	padding-left: 32px;
}

/*
 * One of the novels' sets of pillars, flipped to rise from the foot of the
 * page. The pillars' ends are staggered (on the novels they hide behind the
 * covers), so each set has its ends cropped off to square the base, and is as
 * tall as what's left: its artwork's height less the crop. The base runs down
 * through the main element's 60px bottom padding to meet the bottom edge.
 */
.page-footer__pillars {
	grid-row: 1 / span 2;
	align-self: end;
	aspect-ratio: 227 / 321; /* 451 - 130. */
	margin-bottom: -60px;
	background: url("../../images/masks/novels/novel-background-variation-a.svg") center top -130px / 100% auto no-repeat;
	transform: scaleY(-1);
}

.page-footer__pillars[data-variation="b"] {
	aspect-ratio: 227 / 296; /* 461 - 165. */
	background-image: url("../../images/masks/novels/novel-background-variation-b.svg");
	background-position: center top -165px;
}

.page-footer__pillars[data-variation="c"] {
	aspect-ratio: 227 / 276; /* 431 - 155. */
	background-image: url("../../images/masks/novels/novel-background-variation-c.svg");
	background-position: center top -155px;
}

.page-footer__brand {
	grid-row: 1 / span 2;
	margin-top: 1.5rem;
}

.page-footer__home {
	display: block;
	width: fit-content;
	text-decoration: none;
}

.page-footer__home .brand__logo {
	display: block;
	margin-bottom: 2rem;
}

/* One word per line, as in the design. */
.page-footer .brand__name {
	display: block;
	width: min-content;
}

.page-footer__home:hover .brand__name {
	color: var(--ws-red);
}

.page-footer__shapes {
	width: 57px;
	margin-top: 0.5rem;
}

.page-footer__bracket {
	justify-self: end;
	width: 95px;
	margin-top: 6rem;
}

/*
 * On posts, the links to the posts either side take a row of their own above
 * the pillars and the logo, edge to edge; the bracket stays beside the brand.
 */
.page-footer--nav .page-footer__pillars,
.page-footer--nav .page-footer__brand,
.page-footer--nav .page-footer__bracket {
	grid-row: 2;
}

.page-footer--nav .page-footer__bracket {
	grid-column: -2;
}

.post-nav {
	grid-row: 1;
	grid-column: 1 / -1;
	display: grid;
	grid-template-columns: 1fr 1fr;
	align-items: start; /* Each link keeps to its own height, so both sit at the top. */
	column-gap: 24px;
	margin-top: 1.5rem;
	margin-bottom: 8rem;
}

.post-nav__link {
	display: grid;
	grid-template-columns: auto 1fr;
	align-items: center;
	column-gap: 0.75rem;
	color: var(--ws-ink);
	text-decoration: none;
}

/* Next keeps to the right-hand column, even when there's no previous post. */
.post-nav__link--next {
	grid-column: 2;
	grid-template-columns: 1fr auto;
	text-align: right;
}

.post-nav__arrow {
	grid-row: 1 / span 2;
	width: 22px;
	height: auto;
	transition: transform 0.2s;
}

.post-nav__link--next .post-nav__arrow {
	grid-column: 2;
}

.post-nav__link--previous:hover .post-nav__arrow {
	transform: translateX(-4px);
}

.post-nav__link--next:hover .post-nav__arrow {
	transform: translateX(4px);
}

.post-nav__label {
	font: 900 0.9375rem/1 var(--ws-font-display);
	text-transform: uppercase;
}

.post-nav__title {
	margin-top: 0.25rem;
	font: 800 1.25rem/1.15 var(--ws-font-title);
}

.post-nav__link:hover .post-nav__title {
	color: var(--ws-red);
}

@media (max-width: 700px) {
	.entry--page .entry-header,
	.entry--page .entry-content,
	.page-footer {
		padding-inline: 0;
	}

	.entry--page .entry-content .alignwide,
	.entry--page .entry-content .alignfull {
		margin-inline: 0;
	}

	.page-footer {
		grid-template-columns: 1fr 95px;
	}

	.page-footer__pillars {
		display: none;
	}

	.page-footer__brand {
		margin-top: 0;
	}

	.page-footer__bracket {
		margin-top: 3rem;
	}

	.post-nav {
		grid-template-columns: 1fr;
		row-gap: 1.5rem;
		margin: 0 0 2.5rem;
	}

	.post-nav__link--next {
		grid-column: 1;
	}
}

/* =Comments
-------------------------------------------------------------- */

/* Follows the article, whose bottom margin supplies the space above. */
.comments {
	margin: 0 0 4rem;
}

.comments__title,
.comment-reply-title {
	margin: 0 0 1.5rem;
	color: var(--ws-red);
	font: 800 2rem/1.1 var(--ws-font-title);
}

.comments__list,
.comments__list .children {
	margin: 0 0 3rem;
	padding: 0;
	list-style: none;
}

.comments__list .children {
	margin: 1.5rem 0 0 2rem;
}

.comments__list > li + li {
	margin-top: 2rem;
}

.comment-meta,
.comment-reply-link,
.comment-form label,
.comment-notes,
.logged-in-as {
	color: var(--ws-blue);
	font-family: var(--ws-font-display);
	font-size: 0.9375rem;
}

.comment-meta a {
	color: inherit;
	text-decoration: none;
}

.comment-author .avatar {
	float: left;
	margin-right: 0.75rem;
}

.comment-content {
	clear: both;
	padding-top: 0.5rem;
}

.comment-form label {
	display: block;
	margin-bottom: 0.25rem;
}

.comment-form :is(input[type="text"], input[type="email"], input[type="url"], textarea) {
	width: 100%;
	padding: 0.5rem 0.75rem;
	border: 1px solid var(--ws-rule);
	font: inherit;
}

.comment-form .submit {
	padding: 0.6rem 1.5rem;
	border: 0;
	background: var(--ws-blue);
	color: var(--ws-background);
	font: 900 1rem/1 var(--ws-font-display);
	text-transform: uppercase;
	cursor: pointer;
}

.comment-form .submit:hover {
	background: var(--ws-red);
}

.entry-footer {
	display: flex;
	flex-wrap: wrap;
	align-items: flex-start;
	justify-content: flex-end;
	gap: 1.5rem 2.75rem;
	margin-top: 2.5rem;
	color: var(--ws-blue);
	font: 400 0.875rem/1.15 var(--ws-font-display);
}

.footer-meta {
	display: flex;
	align-items: flex-start;
	gap: 0.9rem;
}

.footer-meta__icon {
	flex: none;
}

.footer-meta ul {
	margin: 0;
	padding: 0;
	list-style: none;
}

.entry-footer__shapes {
	width: 57px;
}

@media (max-width: 700px) {
	.stream__bracket--top {
		position: static;
		display: block;
		width: 64px;
		margin-bottom: 1rem;
	}

	.entry-header,
	.entry-summary,
	.entry-content,
	.comments {
		padding: 0;
	}

	.entry-content .alignwide,
	.entry-content .alignfull {
		margin-inline: 0;
	}

	.entry-footer {
		justify-content: flex-start;
	}
}
