/* kladdle.com
   One stylesheet for the whole site. The tokens at the top are copied from the
   app's src/app.css (github.com/msblei/kladdle) with the same names, so a value
   here can be checked against the app by name. Only the light palette is
   defined: the page is drawn on paper. A dark set would go in below the light
   one, exactly as the app does it. */

:root {
	/* ---- brand, fixed by the identity ---------------------------------- */
	--brand-rose: #f0b4b0;
	--brand-rose-mid: #b96b66;
	--brand-rose-deep: #7a3630;
	--brand-ink: #23201b;
	--brand-paper: #f6f0e4;

	/* ---- the light palette --------------------------------------------- */
	--ground: #f4f2ee;
	--card: #fdfcfa;
	--chip-bg: #fbf8f2;
	--ink: #23201b;
	--ink-soft: #5a5344;
	--ink-faint: #746c5d;
	--edge: #e3ded4;
	--edge-strong: #d8d1c3;
	--good: #4a6b3f;
	--accent-soft: rgba(240, 180, 176, 0.3);

	/* page-only values, not in the app: the hairline a resting orb is drawn
	   with, the paper's own edge, and the three calendars in the plan visual */
	--edge-deep: #c9c0ac;
	--paper-edge: #e0d8c6;
	--cal-1: #6f9fd8;
	--cal-2: #6faa5e;
	--cal-3: #8a6fc4;

	/* ---- type, shape, motion ------------------------------------------- */
	--font: 'Kladdle Roman', Georgia, serif;
	--font-mono: 'Kladdle Mono', ui-monospace, SFMono-Regular, Consolas, monospace;
	--radius-sm: 8px;
	--motion: 160ms;
	--settle: cubic-bezier(0.22, 1, 0.36, 1);

	/* the page's one measure and its side gutter */
	--measure: 1080px;
	--gutter: 24px;

	/* the paper's grain; a tiny svg so it costs no request */
	--grain: url('data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22120%22%20height%3D%22120%22%3E%3Cfilter%20id%3D%22n%22%3E%3CfeTurbulence%20type%3D%22fractalNoise%22%20baseFrequency%3D%220.75%22%20numOctaves%3D%222%22%20stitchTiles%3D%22stitch%22%2F%3E%3CfeColorMatrix%20values%3D%220%200%200%200%200.35%200%200%200%200%200.3%200%200%200%200%200.22%200%200%200%200.07%200%22%2F%3E%3C%2Ffilter%3E%3Crect%20width%3D%22120%22%20height%3D%22120%22%20filter%3D%22url(%23n)%22%2F%3E%3C%2Fsvg%3E');
}

/* ---- faces ------------------------------------------------------------
   The same three files the app serves, under the app's names. Bold is the
   one addition: the chapter headlines are set in it. */
@font-face {
	font-family: 'Kladdle Roman';
	font-weight: normal;
	font-style: normal;
	font-display: swap;
	src: url('fonts/lmroman-regular-latin-v1.woff2') format('woff2');
}
@font-face {
	font-family: 'Kladdle Roman';
	font-weight: normal;
	font-style: italic;
	font-display: swap;
	src: url('fonts/lmroman-italic.woff2') format('woff2');
}
@font-face {
	font-family: 'Kladdle Roman';
	font-weight: bold;
	font-style: normal;
	font-display: swap;
	src: url('fonts/lmroman-bold.woff2') format('woff2');
}
@font-face {
	font-family: 'Kladdle Mono';
	font-weight: normal;
	font-style: normal;
	font-display: swap;
	src: url('fonts/lmmono-regular-latin-v1.woff2') format('woff2');
}

/* ---- ground ------------------------------------------------------------- */
* {
	box-sizing: border-box;
}

/* a click on the bar glides to its chapter; the chain rides along with the scroll */
html {
	scroll-behavior: smooth;
}

body {
	margin: 0;
	min-height: 100vh;
	display: flex;
	flex-direction: column;
	background: var(--ground);
	color: var(--ink);
	font-family: var(--font);
	line-height: 1.5;
	-webkit-font-smoothing: antialiased;
}

a {
	color: var(--brand-rose-deep);
	text-decoration: none;
}
a:hover {
	color: var(--ink-soft);
}
a:focus-visible {
	outline: none;
	box-shadow: 0 0 0 3px rgba(122, 54, 48, 0.65);
	border-radius: var(--radius-sm);
}

h1,
h2,
p {
	margin: 0;
}

/* clip, not hidden: hidden would make this the sticky chain's scrollport, and
   it never scrolls, so the chain could never engage */
.page {
	width: 100%;
	flex: 1;
	display: flex;
	flex-direction: column;
	overflow-x: clip;
}
/* on a short page the paper grows to meet the footer */
.fill {
	flex: 1;
}

.measure {
	max-width: var(--measure);
	margin: 0 auto;
	padding: 0 var(--gutter);
}

.paper {
	background: var(--brand-paper) var(--grain);
}

.mono {
	font-family: var(--font-mono);
}

/* ---- wordmark -----------------------------------------------------------
   Outlines from the app's Wordmark.svelte, inline wherever the mark appears, so
   each copy takes the page's colour and runs its own motion. Sized by font-size,
   so one length gives the mark at that size, hat included. With .animate the letters arrive in reading order and the hat drops in and
   seats itself once; with .idle it lifts again every eight seconds. */
.wordmark {
	display: inline-flex;
	align-items: center;
	font-size: 32px;
	color: var(--ink);
	user-select: none;
}
.wordmark:hover {
	color: var(--ink);
}
.wordmark .mark {
	height: 1.62em;
	width: auto;
	display: block;
	fill: currentColor;
	overflow: visible;
}
.wordmark .k-only {
	display: none;
	overflow: hidden;
}
.wordmark .hat {
	fill: var(--brand-rose);
	stroke: var(--brand-rose);
	stroke-width: 5;
	/* mitred, not rounded: the circumflex comes to a point */
	stroke-linejoin: miter;
	stroke-miterlimit: 6;
	stroke-linecap: round;
}
.wordmark.animate .letters path {
	animation: ink-fade 0.4s ease-out both;
	animation-delay: calc(var(--i) * 0.07s);
}
.wordmark.animate .hat {
	animation: hat-settle 0.7s var(--settle) 0.62s both;
}
.wordmark.animate.idle .hat {
	animation:
		hat-settle 0.7s var(--settle) 0.62s both,
		hat-nod 8s ease-in-out 2s infinite;
}
.wordmark.small {
	font-size: 21px;
}

/* ---- hero --------------------------------------------------------------- */
.masthead {
	padding-top: 30px;
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 20px;
}
.sign-in {
	display: inline-flex;
	align-items: center;
	min-height: 44px;
	font-family: var(--font-mono);
	font-size: 16px;
}

.hero {
	padding-top: 66px;
	padding-bottom: 46px;
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 22px;
	text-align: center;
}
.hero h1 {
	max-width: 700px;
	font-size: clamp(34px, 6.4vw, 70px);
	font-weight: normal;
	line-height: 1.15;
	text-wrap: pretty;
	animation: rise 800ms var(--settle) 200ms both;
}
.hero .sub {
	font-size: clamp(19px, 2.4vw, 25px);
	line-height: 1.4;
	color: var(--ink-soft);
	animation: rise 800ms var(--settle) 340ms both;
}
.hero .cta {
	margin-top: 8px;
	animation: rise 800ms var(--settle) 480ms both;
}

.cta {
	display: inline-flex;
	align-items: center;
	gap: 10px;
	min-height: 52px;
	padding: 0 28px;
	border-radius: var(--radius-sm);
	background: var(--brand-rose);
	color: var(--ink);
	font-size: 19px;
	line-height: 52px;
	transition:
		box-shadow var(--motion) ease-out,
		background-color var(--motion) ease-out;
}
.cta:hover {
	color: var(--ink);
	box-shadow: inset 0 0 0 1px var(--brand-rose-deep);
}
.cta .arrow {
	font-family: var(--font-mono);
	transition: transform 240ms var(--settle);
}
.cta:focus-visible .arrow {
	transform: translateX(3px);
}
.cta:active {
	background-color: #eaa5a0;
}
@media (hover: hover) and (pointer: fine) {
	.cta:hover .arrow {
		transform: translateX(3px);
	}
}
.sign-in,
.footer nav a {
	text-decoration: underline;
	text-decoration-color: transparent;
	text-underline-offset: 4px;
	transition:
		color var(--motion),
		text-decoration-color var(--motion);
}
.sign-in:hover,
.footer nav a:hover {
	text-decoration-color: currentColor;
}

/* ---- the chain -----------------------------------------------------------
   One svg, no copies. The sticky box is height zero so it reserves nothing;
   the spacer below it reserves the room the hero curve needs. chain.js moves
   every orb, label and connector from the hero shape to the docked bar as the
   spacer scrolls past the top of the viewport. */
.journey {
	position: relative;
}

.chain {
	position: relative;
	z-index: 5;
	height: 0;
}
/* it sticks only once chain.js is there to drive it; without the script it
   stays in flow as the hero's illustration and scrolls away with the paper */
.js .chain {
	position: sticky;
	top: 0;
}
.chain-inner {
	position: relative;
	width: 100%;
	pointer-events: none;
}
.chain .band {
	position: absolute;
	left: 0;
	right: 0;
	top: 0;
	height: var(--band-h, 110px);
	background: var(--ground);
	border-bottom: 1px solid var(--edge);
	opacity: 0;
}
/* the wordmark and sign in, centred on the orbs' line; they arrive with the
   bar and take clicks only once it is docked */
.chain .chrome {
	position: absolute;
	left: 0;
	right: 0;
	top: 0;
	height: calc(var(--rail-y, 38px) * 2);
	display: flex;
	align-items: center;
	justify-content: space-between;
	opacity: 0;
}
.chain .docked .chrome a {
	pointer-events: auto;
}
/* the svg and the labels share this box, and it has no padding: the labels
   are placed in percent of it, so any padding would slide them off their orbs */
.chain .stage {
	position: relative;
}
.chain svg {
	width: 100%;
	height: auto;
	display: block;
	overflow: visible;
}

.chain .link {
	fill: none;
	stroke: var(--edge-strong);
	stroke-width: 1;
	stroke-dasharray: 2 6;
}
.chain .link:nth-of-type(1) {
	animation: fade 900ms ease-out 400ms both;
}
.chain .link:nth-of-type(2) {
	animation: fade 900ms ease-out 900ms both;
}
.chain .link:nth-of-type(3) {
	animation: fade 900ms ease-out 1400ms both;
}
.chain .link.lead {
	animation: fade 700ms ease-out 200ms backwards;
}

.chain .orb {
	stroke-width: 1.5;
	transform-box: fill-box;
	transform-origin: center;
	animation: swell 620ms var(--settle) both;
	transition:
		fill var(--motion),
		stroke var(--motion);
}
.chain .orb[data-i='0'] {
	animation-delay: 100ms;
}
.chain .orb[data-i='1'] {
	animation-delay: 600ms;
}
.chain .orb[data-i='2'] {
	animation-delay: 1100ms;
}
.chain .orb[data-i='3'] {
	animation-delay: 1600ms;
}
/* how an orb is painted: as hero art until halfway, then as a place you have
   reached, are at, or have not reached yet */
.chain .orb[data-state='hero'] {
	fill: var(--brand-paper);
	stroke: var(--edge-deep);
}
/* the last orb is the drawing's sun */
.chain .orb[data-state='hero'][data-i='3'] {
	fill: var(--brand-rose);
	stroke: var(--brand-rose-mid);
}
.chain .orb[data-state='current'] {
	fill: var(--brand-rose);
	stroke: var(--brand-rose-mid);
}
.chain .orb[data-state='reached'] {
	fill: var(--edge);
	stroke: var(--edge-strong);
}
.chain .orb[data-state='ahead'] {
	fill: transparent;
	stroke: var(--edge-strong);
}

.chain .pip {
	fill: var(--edge-deep);
}
.chain .pip.hollow {
	fill: none;
	stroke: var(--edge-deep);
	stroke-width: 1;
}
/* the drawings from steps.svg: the walker arrives with the first orb, the
   rays light once the last one has swelled */
.chain .walker-in,
.chain .rays-in {
	fill: var(--ink-soft);
}
.chain .walker-in {
	animation: fade 700ms ease-out 200ms both;
}
.chain .rays-in {
	animation: fade 900ms ease-out 1900ms both;
}
.chain .hat-mark {
	font-family: var(--font);
	fill: var(--brand-rose-mid);
	animation: fade 700ms ease-out 1780ms both;
}

.chain .label {
	position: absolute;
	transform: translateX(-50%);
	margin-top: -15px;
	padding: 15px 12px;
	white-space: nowrap;
	font-family: var(--font-mono);
	font-size: 13px;
	color: var(--ink-faint);
	animation: fade 700ms ease-out both;
	transition: color var(--motion);
}
.chain .label.is-current {
	color: var(--ink);
}
/* only the docked bar is navigation: until then the orbs and labels are art
   and let the page beneath take the pointer */
.chain .docked .label,
.chain .docked .orb,
html:not(.js) .chain .label {
	pointer-events: auto;
	cursor: pointer;
}
.chain .label[data-i='0'] {
	animation-delay: 380ms;
}
.chain .label[data-i='1'] {
	animation-delay: 880ms;
}
.chain .label[data-i='2'] {
	animation-delay: 1380ms;
}
.chain .label[data-i='3'] {
	animation-delay: 1900ms;
}

/* A restored scroll position must show usable navigation immediately. Once
   docked, the hero's entrance has finished, including on a trip back up. */
.chain-settled .chain :is(.link, .orb, .label, .walker-in, .rays-in, .hat-mark) {
	animation: none;
}

/* the room the chain occupies before it docks, reserved so nothing shifts,
   and grained like the hero so at rest the two are one canvas */
.spacer-band {
	border-bottom: 1px solid var(--paper-edge);
}
.spacer {
	width: 100%;
	aspect-ratio: 1080 / 340;
}

/* ---- chapters -------------------------------------------------------------
   Four chapters, four arrangements, so the page does not settle into a rhythm:
   words beside a drawing, words above one, a chapter on its own sheet of
   paper, and the seal the page draws itself. */
.chapters {
	padding-top: 26px;
	display: flex;
	flex-direction: column;
	gap: 76px;
}

.chapter {
	scroll-margin-top: 136px;
}
.chapter .grid {
	display: grid;
	gap: 40px;
	align-items: center;
}
.chapter.split .grid {
	grid-template-columns: repeat(auto-fit, minmax(min(300px, 100%), 1fr));
}
.chapter.centered .grid {
	grid-template-columns: 1fr;
	justify-items: center;
	text-align: center;
	gap: 36px;
}
.chapter.centered .words {
	align-items: center;
}
.chapter.centered .visual {
	max-width: 820px;
}
.chapter.panel {
	padding-block: 72px;
	border-top: 1px solid var(--paper-edge);
	border-bottom: 1px solid var(--paper-edge);
}
.chapter .words {
	display: flex;
	flex-direction: column;
	gap: 14px;
}
.chapter h2 {
	font-size: clamp(32px, 4.6vw, 50px);
	font-weight: bold;
	line-height: 1.1;
	text-wrap: pretty;
}
.chapter .lead {
	max-width: 420px;
	font-size: 21px;
	line-height: 1.4;
	text-wrap: pretty;
}
.chapter .more {
	max-width: 420px;
	font-size: 17px;
	line-height: 1.55;
	color: var(--ink-soft);
	text-wrap: pretty;
}

.chapter .visual {
	position: relative;
	width: 100%;
}
.chapter .visual svg,
.chapter .visual .ill {
	width: 100%;
	height: auto;
	display: block;
}
/* the drawings keep their shape and never stand much taller than the words
   beside them; the one tall drawing may */
.chapter .visual .ill {
	max-height: 440px;
	object-fit: contain;
}
.chapter .visual .ill.tall {
	max-height: 600px;
}

/* the drawings' own strokes */
.visual .link {
	fill: none;
	stroke: var(--edge-strong);
	stroke-width: 1;
	stroke-dasharray: 2 6;
}
.visual .rule {
	stroke: var(--edge-strong);
	stroke-width: 1;
}
.visual .loose {
	fill: none;
	stroke: var(--edge-deep);
	stroke-width: 1.5;
}
.visual .faint {
	fill: none;
	stroke: var(--edge-strong);
	stroke-width: 1;
}
.visual .box {
	fill: var(--card);
	stroke: var(--brand-rose-mid);
	stroke-width: 1.5;
}
.visual .dot {
	fill: var(--brand-rose-mid);
}
.visual .top {
	fill: var(--accent-soft);
	stroke: var(--brand-rose);
	stroke-width: 1.5;
}
.visual .next {
	fill: var(--card);
	stroke: var(--edge-strong);
	stroke-width: 1;
}
.visual .cal-1 {
	fill: none;
	stroke: var(--cal-1);
	stroke-width: 1.5;
}
.visual .cal-2 {
	fill: none;
	stroke: var(--cal-2);
	stroke-width: 1.5;
}
.visual .cal-3 {
	fill: none;
	stroke: var(--cal-3);
	stroke-width: 1.5;
}
.visual .hub {
	fill: var(--brand-paper);
	stroke: var(--brand-rose-mid);
	stroke-width: 1.5;
}
.visual .hub-ring {
	fill: none;
	stroke: var(--brand-rose-mid);
	stroke-width: 1;
}
.visual .orbit {
	fill: none;
	stroke: var(--edge);
	stroke-width: 1;
	stroke-dasharray: 2 6;
}
.visual .seal {
	fill: var(--brand-paper);
	stroke: var(--edge-strong);
	stroke-width: 1.5;
}

/* small mono captions placed on a drawing, in percent of its box */
.visual .note {
	position: absolute;
	white-space: nowrap;
	font-family: var(--font-mono);
	font-size: 11px;
	color: var(--ink-faint);
}
.visual .note.centred {
	left: 50%;
	transform: translate(-50%, -50%);
}

/* the objective seal's tally and its count */
.visual .tally {
	position: absolute;
	left: 50%;
	top: 50%;
	transform: translate(-50%, -50%);
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 9px;
}
.visual .marks {
	display: inline-flex;
	gap: 3px;
}
.visual .marks span {
	width: 3px;
	height: 12px;
	border-radius: 1px;
	background: var(--good);
}
.visual .marks .missed {
	background: var(--edge-strong);
}
.visual .marks .due {
	background: none;
	border: 1px solid var(--brand-rose);
}
.visual .count {
	font-family: var(--font-mono);
	font-size: 12px;
	color: var(--good);
	border: 1px solid var(--good);
	border-radius: var(--radius-sm);
	padding: 1px 10px;
	white-space: nowrap;
}

/* the calendars, stated as chips rather than a sentence */
.chips {
	display: flex;
	flex-wrap: wrap;
	gap: 8px;
	margin-top: 4px;
}
.chip {
	display: inline-flex;
	align-items: center;
	gap: 5px;
	border: 1px solid var(--edge);
	background: var(--chip-bg);
	border-radius: var(--radius-sm);
	padding: 4px 11px;
	font-family: var(--font-mono);
	font-size: 12px;
	color: var(--ink-soft);
}
.chip .provider-icon {
	width: 14px;
	height: 14px;
	flex: none;
}
.chip.soon {
	border-style: dashed;
	border-color: var(--edge-strong);
	background: none;
	color: var(--ink-faint);
}

/* ---- closing and footer ------------------------------------------------- */
.closing {
	padding-top: 84px;
	padding-bottom: 88px;
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 28px;
	text-align: center;
}
.closing .strip {
	display: block;
	width: 100%;
	max-width: 960px;
	height: auto;
	margin-bottom: 28px;
}
.closing p {
	max-width: 560px;
	font-size: clamp(24px, 3.2vw, 32px);
	line-height: 1.3;
	text-wrap: pretty;
}

.footer {
	margin-top: auto;
	border-top: 1px solid var(--edge);
	background: var(--card);
}
.footer .measure {
	padding-top: 28px;
	padding-bottom: 34px;
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 20px;
	flex-wrap: wrap;
}
.footer nav {
	display: flex;
	align-items: center;
	gap: 20px;
	flex-wrap: wrap;
	font-family: var(--font-mono);
	font-size: 12px;
}
.footer nav a {
	display: inline-flex;
	align-items: center;
	min-height: 44px;
}

/* ---- the small pages ---------------------------------------------------- */
.plain {
	padding-top: 56px;
	padding-bottom: 96px;
	display: flex;
	flex-direction: column;
	gap: 18px;
}
.plain h1 {
	font-size: clamp(32px, 4.6vw, 50px);
	font-weight: normal;
	line-height: 1.1;
}
.plain p {
	max-width: 560px;
	font-size: 19px;
	color: var(--ink-soft);
}
.plain .quiet {
	display: block;
	width: 100%;
	max-width: 300px;
	height: auto;
	margin-top: 48px;
}

/* ---- motion ------------------------------------------------------------- */
/* Only JS-prepared, upcoming content waits for an entrance. It stays readable
   without JS, in print, and as soon as reduced motion is requested. */
@media screen and (prefers-reduced-motion: no-preference) {
	.reveal-pending {
		opacity: 0;
	}
}

@keyframes ink-fade {
	from {
		opacity: 0;
	}
	to {
		opacity: 1;
	}
}
@keyframes hat-settle {
	0% {
		opacity: 0;
		transform: translateY(-26px);
	}
	55% {
		opacity: 1;
		transform: translateY(4px);
	}
	100% {
		opacity: 1;
		transform: translateY(0);
	}
}
@keyframes hat-nod {
	0%,
	92%,
	100% {
		transform: translateY(0);
	}
	96% {
		transform: translateY(-5px);
	}
}
@keyframes rise {
	from {
		opacity: 0;
		transform: translateY(9px);
	}
	to {
		opacity: 1;
		transform: none;
	}
}
@keyframes fade {
	from {
		opacity: 0;
	}
	to {
		opacity: 1;
	}
}
@keyframes swell {
	0% {
		opacity: 0;
		transform: scale(0.5);
	}
	62% {
		opacity: 1;
		transform: scale(1.05);
	}
	100% {
		opacity: 1;
		transform: scale(1);
	}
}

/* Nothing moves for anyone who asked it not to. chain.js also pins the chain
   in its docked shape and marks the root .still, so the page loads as a still
   document with the bar sitting where the hero curve would have been. */
@media (prefers-reduced-motion: reduce) {
	*,
	*::before,
	*::after {
		animation: none !important;
		transition: none !important;
	}
	html {
		scroll-behavior: auto;
	}
	.cta .arrow {
		transform: none !important;
	}
}
.still .spacer {
	aspect-ratio: auto;
	height: var(--band-h, 110px);
}

/* ---- narrow screens ------------------------------------------------------
   Below this width the chain uses its phone geometry (see chain.js); the
   spacer reserves the matching room. */
@media (max-width: 559px) {
	.spacer {
		aspect-ratio: 390 / 300;
	}
	/* the bar keeps only the k and a smaller sign in, so the four labels fit between */
	.chain .chrome .mark {
		display: none;
	}
	.chain .chrome .k-only {
		display: block;
	}
	.chain .chrome .sign-in {
		font-size: 13px;
	}
	.chain .label {
		min-width: 44px;
		padding-inline: 2px;
		text-align: center;
	}
	.chapter {
		grid-template-columns: 1fr;
		gap: 24px;
	}
	.chapters {
		gap: 64px;
	}
	.hero {
		padding-top: 48px;
		padding-bottom: 36px;
	}
	.closing {
		padding-top: 64px;
		padding-bottom: 64px;
	}
}
