/* Kinwhistle, the website.
 *
 * The colours are the app's and the mark's, not new ones: parchment, ink and
 * amber from docs/logo/README.md, the wax red of the app's record button and
 * the accent text from Elder.swift. Every pair a reader has to read is
 * measured by scripts/site-check.mjs, in both schemes, from the tokens below:
 * keep the two blocks' names in step, and name a colour here before using it.
 *
 * Built for whoever reads it, often somebody older: a large base size in rem,
 * so the browser's own text size and zoom move everything; on an iPhone the
 * reader's Dynamic Type size, as the app uses; no motion that is not asked
 * for; a focus ring that can be seen on every ground.
 */

:root {
	color-scheme: light dark;
	--bg: #F6ECDC;
	--surface: #FFFAF2;
	--honey: #F4E2C1;
	--ink: #241A14;
	--ink-soft: #5B4A3E;
	--accent: #B93D0B;
	--button: #B4392B;
	--button-ink: #FFF8EC;
	--rule: #E2D2B8;
	--underline: #E8A33C;
	--focus: #241A14;
	--mark-bg: #FBE3B6;
	--mark-ink: #241A14;
	--shadow: 24 40% 14%;
	--phone: #000000;
	--phone-edge: #A39B93;
	--phone-rim: #5C554F;
}

@media (prefers-color-scheme: dark) {
	:root {
		--bg: #2E1D16;
		--surface: #3A241A;
		--honey: #4A3022;
		--ink: #FBF1E2;
		--ink-soft: #C3B2A0;
		--accent: #F0A27A;
		--button: #F0A27A;
		--button-ink: #241A14;
		--rule: #4A362A;
		--underline: #E8A33C;
		--focus: #FBF1E2;
		--mark-bg: #5A3A1E;
		--mark-ink: #FBF1E2;
		--shadow: 20 50% 4%;
		--phone: #000000;
		--phone-edge: #A39B93;
		--phone-rim: #5C554F;
	}
}

/* The reader's own text size on an iPhone, where Dynamic Type reaches a page
 * only through this font. iOS only: a Mac's WebKit knows the font too, and
 * would set the page in its 13-pixel body size. */
@supports (font: -apple-system-body) and (-webkit-touch-callout: none) {
	html { font: -apple-system-body; }
}

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

html {
	-webkit-text-size-adjust: 100%;
	text-size-adjust: 100%;
}

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

body {
	margin: 0;
	background: var(--bg);
	color: var(--ink);
	font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
	font-size: 1.25rem;
	line-height: 1.6;
	overflow-wrap: break-word;
}

h1, h2, h3 {
	font-family: Charter, "Bitstream Charter", "Sitka Text", Georgia, "Times New Roman", serif;
	line-height: 1.15;
	overflow-wrap: anywhere;
	hyphens: manual;
	text-wrap: balance;
}
h1 { font-size: clamp(2.25rem, 1.5rem + 2.6vw, 3.6rem); margin: 0.5rem 0 1rem; letter-spacing: -0.01em; }
h2 { font-size: clamp(1.75rem, 1.35rem + 1.4vw, 2.5rem); margin: 0 0 1rem; }
h3 { font-size: 1.3rem; margin: 0 0 0.4rem; }
p { margin: 0 0 1rem; }

a { color: inherit; text-decoration: none; border-bottom: 2px solid var(--underline); }
a:hover { background: var(--underline); color: #241A14; }

/* One ring for everything that takes focus, on every ground: ink on the light
 * page and cream on the dark one, both far above 3:1 against what is behind. */
:focus-visible {
	outline: 3px solid var(--focus);
	outline-offset: 3px;
	border-radius: 2px;
}

.vh {
	position: absolute !important;
	width: 1px; height: 1px;
	overflow: hidden;
	clip-path: inset(50%);
	white-space: nowrap;
}

/* Side padding in px, not rem: at the largest text size rem insets eat the
 * line and the page scrolls sideways on a narrow phone. */
.wrap {
	width: 100%;
	max-width: 70rem;
	margin: 0 auto;
	padding-left: clamp(16px, 5vw, 40px);
	padding-right: clamp(16px, 5vw, 40px);
}

.measure { max-width: 36em; }

/* ---------------------------------------------------------------- header -- */

.site-header .wrap {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: space-between;
	gap: 0.75rem 1.5rem;
	padding-top: 1.25rem;
	padding-bottom: 1.25rem;
}

.brand {
	display: inline-flex;
	align-items: center;
	gap: 0.6rem;
	border: 0;
	font-family: Charter, "Bitstream Charter", "Sitka Text", Georgia, "Times New Roman", serif;
	font-weight: 700;
	font-size: 1.5rem;
	color: var(--ink);
}
.brand:hover { background: none; color: var(--ink); }
.brand img { width: 2.4rem; height: 2.4rem; }
@media (prefers-color-scheme: dark) {
	/* The mark is ink on parchment; on the dark ground it sits on a parchment
	 * disc, as the app icon does. */
	.brand img { background: #FBF1E2; border-radius: 50%; padding: 0.15rem; }
}

.lang-switch {
	display: inline-flex;
	align-items: center;
	min-height: 2.75rem;
	padding: 0 0.25rem;
	font-weight: 600;
}

/* ------------------------------------------------------------------ hero -- */

/* The first screen of a phone holds the headline, one line and when the app
 * is coming. The picture follows it there, and stands beside the words on a
 * wide screen. (Until 10 Oct 2026 the waitlist form stood where the line
 * about the App Store is; the measurements below were taken with it.) */
.hero { padding: 1rem 0 clamp(3rem, 2rem + 4vw, 5rem); }
/* Every grid here names its columns minmax(0, …): an auto column is as wide
 * as its widest unbreakable content, and at 200 % text the email field's own
 * width (twenty characters) made the page scroll sideways on a phone. */
.hero .wrap {
	display: grid;
	grid-template-columns: minmax(0, 1fr);
	gap: 3rem;
	align-items: center;
}
/* Side by side, both columns start at the top: centred against the taller
 * picture column, the form's button fell below a laptop's first screen. */
@media (min-width: 60em) {
	.hero .wrap { grid-template-columns: minmax(0, 1.1fr) minmax(0, 0.9fr); gap: 4rem; align-items: start; }
	.hero .wrap > div:first-child { padding-top: 0.5rem; }
}

/* The headline is sized to its column. At 4.4rem the longest of the six
 * (three headlines, two languages) took four lines, and the form's button fell
 * below the first screen of a phone and of a laptop. On a phone it shrinks
 * with the screen down to 2rem. Beside the picture the column stops growing
 * at 537px, and three lines of the longest need about 11 em of it in Georgia
 * (the stand-in for Windows and Android) and 9.7 in Charter: hence 3rem. */
.hero h1 {
	font-size: clamp(2rem, min(1.5rem + 3.6vw, 8vw), 4.4rem);
	line-height: 1.06;
	letter-spacing: -0.015em;
	margin: 0.5rem 0 1.25rem;
}
@media (min-width: 60em) {
	.hero h1 { font-size: clamp(2.5rem, 4.9vw - 0.45rem, 3rem); }
}

/* The three headlines of the ad test (?v=a|b|c, assets/variant.js). One is
 * shown and the others are removed from the page, screen readers included. */
.hv-b, .hv-c { display: none; }
html[data-v="b"] .hv-a, html[data-v="c"] .hv-a { display: none; }
html[data-v="b"] .hv-b, html[data-v="c"] .hv-c { display: inline; }

.lede { font-size: 1.3rem; max-width: 34em; }
.hero .lede { font-size: clamp(1.3rem, 1.15rem + 0.6vw, 1.6rem); max-width: 28em; margin-bottom: 0; }

/* The one line about the App Store, said calmly under the lede: no link and
 * no badge until there is an App Store address to give. */
.soon { margin: 1.5rem 0 0; max-width: 28em; font-weight: 700; }

/* The promise in one picture: an old print, and the card in the app that
 * keeps its story with a play button. The print is the drawn picture from
 * that same card, laid over the phone's corner. */
.hero-visual { justify-self: center; width: min(100%, 24rem); }
@media (min-width: 60em) { .hero-visual { width: 100%; max-width: 27rem; } }
.hero-photos { position: relative; padding: 1.25rem 0 0 30%; }
.print {
	position: absolute;
	left: 0;
	top: 0;
	width: 54%;
	height: auto;
	transform: rotate(-5deg);
	box-shadow: 0 0.15rem 0.35rem hsl(var(--shadow) / 0.2), 0 1rem 2rem -0.5rem hsl(var(--shadow) / 0.5);
}
.hero-visual figcaption { margin-top: 1.25rem; }

/* A screenshot in the phone it came from, drawn here rather than baked into
 * the pictures: a black bezel, a metal band and the side buttons. The bezel is
 * padding in per cent of the phone's own width, so it scales with the phone,
 * and the outer radius is the screen's plus the bezel. The JPEGs' corners are
 * black outside the screen's own curve and vanish into the bezel. */
.phone {
	position: relative;
	display: block;
	padding: 2.8%;
	background: var(--phone);
	border-radius: 16.8% / 8%;
	box-shadow:
		0 0 0 2px var(--phone-edge),
		0 0 0 3px var(--phone-rim),
		0 1.5rem 3rem -1.25rem hsl(var(--shadow) / 0.45);
}
/* The action button and the two volume buttons on the left, cut from one bar
 * by a gradient, and the side button on the right. */
.phone::before, .phone::after {
	content: "";
	position: absolute;
	width: 3px;
	background: var(--phone-rim);
}
.phone::before {
	left: -5px;
	top: 16%;
	height: 27%;
	border-radius: 2px 0 0 2px;
	background: linear-gradient(var(--phone-rim) 0 16.7%, transparent 0 29.6%, var(--phone-rim) 0 59.3%, transparent 0 70.4%, var(--phone-rim) 0);
}
.phone::after {
	right: -5px;
	top: 26%;
	height: 13%;
	border-radius: 0 2px 2px 0;
}
.shot {
	display: block;
	width: 100%;
	height: auto;
	border-radius: 15% / 6.9%;
	background: var(--phone);
}

figure { margin: 0; }
figcaption { margin-top: 1rem; color: var(--ink-soft); font-size: 1.05rem; }
figcaption strong { color: var(--ink); }

/* -------------------------------------------------------------- sections -- */

section { padding: clamp(3rem, 2rem + 4vw, 5.5rem) 0; }
section + section { border-top: 1px solid var(--rule); }

/* A container for the layouts below that follow the text size as well as
 * the screen: a container query in em grows with the reader's own text size,
 * which a media query never sees. */
.cq { container-type: inline-size; }

/* A long Finnish compound carries a soft hyphen at its joint
 * (äly&shy;puhelinta). At ordinary sizes it stays unused and lines break
 * between words as before. It is let in only when the reader's text is so
 * large that the word no longer fits a line, where overflow-wrap would cut it
 * at any letter instead. Measured with WebKit at 390 px, when this comment's
 * example was the waitlist form's sähköposti&shy;osoite (the form went on
 * 10 Oct 2026): such a word fits at 150 % and not at 200 %, hence 10em. */
.perks p { -webkit-hyphens: none; hyphens: none; }
@container (max-width: 10em) {
	.perks p { -webkit-hyphens: manual; hyphens: manual; }
}

/* The scene: a band of honey, read like a page of a book. */
.scene { background: var(--honey); }
section.scene, .scene + section { border-top: 0; }
.scene .wrap { max-width: 48rem; }
.scene h2 { font-size: clamp(1.5rem, 1.25rem + 1vw, 2rem); margin-bottom: 0.75rem; }
.scene p {
	margin: 0;
	font-family: Charter, "Bitstream Charter", "Sitka Text", Georgia, "Times New Roman", serif;
	font-size: clamp(1.45rem, 1.2rem + 1vw, 2rem);
	line-height: 1.45;
}

/* What the family gets: three beats, each beside the screen it is about.
 * Words beside a small screen on a phone at ordinary text sizes, one above
 * the other when the text is large, three across on a wide screen. */
.beats {
	list-style: none;
	margin: 0;
	padding: 0;
	display: grid;
	gap: 3rem;
}
.beats h2 { font-size: clamp(1.5rem, 1.2rem + 1.3vw, 2.1rem); margin-bottom: 0.6rem; }
.beats p { margin: 0; }
.beats figure { width: min(100%, 62vw, 15rem); margin: 1.5rem auto 0; }
@container (min-width: 15em) {
	.beats > li { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 36%); gap: 1.25rem; align-items: center; }
	.beats > li:nth-child(even) { grid-template-columns: minmax(0, 36%) minmax(0, 1fr); }
	.beats > li:nth-child(even) figure { order: -1; }
	.beats figure { width: 100%; margin: 0; }
}
@container (min-width: 48em) {
	.beats { grid-template-columns: repeat(3, minmax(0, 1fr)); }
	.beats > li, .beats > li:nth-child(even) { grid-template-columns: minmax(0, 1fr); align-items: start; align-content: start; }
	.beats > li figure, .beats > li:nth-child(even) figure { order: -1; width: min(100%, 16rem); margin: 0 auto 0.75rem; }
}

/* On Grandma's terms: five short promises, ticked off. The tick is drawn
 * with borders, so a screen reader reads only the words. Two across with the
 * fifth on a line of its own, never beside an empty cell, and three over two
 * where the column is wide: a grid of six, spans of two and then of three. */
.perks {
	list-style: none;
	margin: 1.75rem 0 0;
	padding: 0;
	display: grid;
	grid-template-columns: minmax(0, 1fr);
	gap: 1.4rem 2rem;
}
@container (min-width: 30em) {
	.perks { grid-template-columns: repeat(2, minmax(0, 1fr)); }
	.perks li:last-child { grid-column: 1 / -1; }
}
@container (min-width: 44em) {
	.perks { grid-template-columns: repeat(6, minmax(0, 1fr)); }
	.perks li { grid-column: span 2; }
	.perks li:nth-child(n + 4) { grid-column: span 3; }
}
.perks li { position: relative; padding-left: 2.1rem; }
.perks li::before {
	content: "";
	position: absolute;
	left: 0.3rem;
	top: 0.1em;
	width: 0.5em;
	height: 0.95em;
	border-right: 4px solid var(--accent);
	border-bottom: 4px solid var(--accent);
	transform: rotate(40deg);
}
.perks h3 { margin-bottom: 0.2rem; }
.perks p { margin: 0; }

/* The one line about privacy a reader looks for, halfway down. */
.offer { margin-top: 2.5rem; text-align: center; }
.offer p { margin: 0 auto; }
.offer .assure { max-width: 32em; color: var(--ink-soft); font-size: 1.05rem; }

/* The founder's words and the questions: one narrow column down the middle,
 * the two left edges in line, with the closing box between them. */
.founder, .narrow { max-width: 40em; }

/* The last word, for whoever read this far. */
.closing {
	max-width: 44em;
	margin: 0 auto;
	padding: clamp(2rem, 1.5rem + 2vw, 3rem) clamp(16px, 4vw, 40px);
	text-align: center;
	background: var(--honey);
	border-radius: 1rem;
}
.closing h2 { font-size: clamp(2rem, 1.4rem + 2.4vw, 3.25rem); }
.closing p { margin: 0 auto 1.5rem; max-width: 30em; }
.closing p:last-child { margin-bottom: 0; }

/* Questions, closed until asked. The chevron is drawn with borders, so a
 * screen reader reads only the question, and the answer opens below it.
 *
 * At 320 px and 200 % "äänitteemme?" and the chevron beside it were wider
 * than the list, and the page scrolled sideways. Where the text is that large
 * the gap first shrinks to half, about the 16 px it is at ordinary sizes,
 * which also keeps "recordings?" whole. Only where the word still does not
 * fit is its soft hyphen let in (äänit&shy;teemme, as with the promises above).
 * Both are measured in Charter, the face an iPhone draws the questions in:
 * beside the chevron the word needs 8.56em of the list's own text with the
 * whole gap and 8.16em with half, hence 8.6em and 8.2em. In a wider face
 * (Georgia needs 8.95em) the word is broken where it must be: anywhere, as in
 * the headings, because the body's break-word does not let a flex row shrink
 * below its longest word. */
.faq { container-type: inline-size; border-bottom: 1px solid var(--rule); }
.faq details { border-top: 1px solid var(--rule); }
.faq summary {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 1rem;
	min-height: 3.25rem;
	padding: 0.9rem 0;
	font-family: Charter, "Bitstream Charter", "Sitka Text", Georgia, "Times New Roman", serif;
	font-size: 1.3rem;
	font-weight: 700;
	line-height: 1.3;
	list-style: none;
	cursor: pointer;
	overflow-wrap: anywhere;
	-webkit-hyphens: none;
	hyphens: none;
}
@container (max-width: 8.6em) {
	.faq summary { gap: 0.5rem; }
}
@container (max-width: 8.2em) {
	.faq summary { -webkit-hyphens: manual; hyphens: manual; }
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after {
	content: "";
	flex: none;
	width: 0.6em;
	height: 0.6em;
	margin-right: 0.3em;
	border-right: 3px solid var(--accent);
	border-bottom: 3px solid var(--accent);
	transform: translateY(-25%) rotate(45deg);
}
.faq details[open] summary::after { transform: translateY(25%) rotate(225deg); }
.faq details p { margin: 0 0 1.25rem; max-width: 40em; }

/* A blank only the founder can fill, marked so nobody publishes past it.
 * scripts/site-check.mjs --publish fails while one is left. */
.todo {
	background: var(--mark-bg);
	color: var(--mark-ink);
	padding: 0.05em 0.35em;
	border: 1px dashed var(--ink-soft);
	border-radius: 4px;
}

/* ---------------------------------------------------------------- footer -- */

.site-footer { border-top: 1px solid var(--rule); padding: 2rem 0 3rem; color: var(--ink-soft); font-size: 1.05rem; }
.site-footer nav ul { list-style: none; margin: 0 0 1rem; padding: 0; display: flex; flex-wrap: wrap; gap: 0.5rem 1.5rem; }
.site-footer nav a { display: inline-flex; align-items: center; min-height: 2.75rem; color: var(--ink); }
.site-footer p { margin: 0; }

/* ------------------------------------------------------------ plain pages -- */

.page { padding: 1.5rem 0 3rem; }
.page h2 { margin-top: 2.5rem; }
.page h3 { margin-top: 1.75rem; }
.page ul { padding-left: 1.2em; }
.page li { margin-bottom: 0.6rem; }
