/* ==========================================================================
   Kromesia — landing page
   Tokens transcribed from reference/Kromesia Design System/tokens/*.css
   ========================================================================== */

/* --- Fonts ---------------------------------------------------------------- */

@font-face {
	font-family: 'Poppins';
	src: url('../fonts/Poppins-Medium.woff2') format('woff2');
	font-weight: 500;
	font-style: normal;
	font-display: swap;
}

@font-face {
	font-family: 'Poppins';
	src: url('../fonts/Poppins-SemiBold.woff2') format('woff2');
	font-weight: 600;
	font-style: normal;
	font-display: swap;
}

@font-face {
	font-family: 'Noto Sans';
	src: url('../fonts/NotoSans-latin.woff2') format('woff2');
	font-weight: 400 500;
	font-style: normal;
	font-display: swap;
}

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

:root {
	/* colour */
	--kromesia-navy: #1D3557;
	--kromesia-steel: #457B9D;
	--kromesia-ice: #A8DADC;
	--kromesia-mint: #F1FAEE;
	--kromesia-coral: #E63946;

	--bg-canvas: #0A121E;
	--bg-surface: #0F1A2B;
	--bg-field: #0C1826;

	--text-primary: #F4FAF6;
	--text-secondary: #C3D6DE;
	--text-muted: #7E97A8;

	--accent-primary: var(--kromesia-steel);
	--accent-primary-hover: #5590B4;
	--accent-secondary: var(--kromesia-ice);
	--accent-alert: var(--kromesia-coral);

	--border-subtle: rgba(168, 218, 220, 0.12);
	--border-strong: rgba(168, 218, 220, 0.28);

	/* type */
	--font-display: 'Poppins', -apple-system, 'Segoe UI', sans-serif;
	--font-body: 'Noto Sans', -apple-system, 'Segoe UI', sans-serif;
	--ls-display: -0.02em;
	--ls-eyebrow: 0.22em;

	/* space */
	--space-2: 8px;
	--space-3: 12px;
	--space-4: 16px;
	--space-5: 24px;
	--space-6: 32px;
	--space-7: 48px;
	--space-8: 64px;

	/* effects */
	--radius-sm: 2px;
	--spectrum: linear-gradient(90deg, #E63946 0 20%, #1D3557 20% 40%, #457B9D 40% 60%, #A8DADC 60% 80%, #F1FAEE 80% 100%);
	--shadow-glow-ice: 0 0 0 1px rgba(168, 218, 220, 0.45), 0 12px 40px -8px rgba(168, 218, 220, 0.28);
	--ease-standard: cubic-bezier(.4, 0, .2, 1);
	--duration-fast: 120ms;
	--duration-base: 240ms;
}

/* --- Reset ---------------------------------------------------------------- */

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

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

body {
	margin: 0;
	min-height: 100svh;
	background: var(--bg-canvas);
	color: var(--text-secondary);
	font-family: var(--font-body);
	font-size: 16px;
	line-height: 1.5;
	-webkit-font-smoothing: antialiased;
	-moz-osx-font-smoothing: grayscale;
	overflow-x: hidden;
}

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

.visually-hidden {
	position: absolute;
	width: 1px;
	height: 1px;
	margin: -1px;
	padding: 0;
	overflow: hidden;
	clip: rect(0 0 0 0);
	clip-path: inset(50%);
	white-space: nowrap;
	border: 0;
}

:focus-visible {
	outline: 2px solid var(--accent-secondary);
	outline-offset: 3px;
}

/* --- Background ----------------------------------------------------------- */

/* Hexagonal parallax depth field. Decoration only — the page must read
   perfectly with this element removed. */
#field {
	position: fixed;
	inset: 0;
	z-index: 0;
	width: 100%;
	height: 100%;
	display: block;
	pointer-events: none;
}

/* Vignette, so the lattice never competes with the text column. */
body::after {
	content: '';
	position: fixed;
	inset: 0;
	z-index: 1;
	pointer-events: none;
	background:
		radial-gradient(120% 90% at 22% 45%, rgba(10, 18, 30, 0.92) 0%, rgba(10, 18, 30, 0.55) 38%, rgba(10, 18, 30, 0) 70%),
		linear-gradient(180deg, rgba(10, 18, 30, 0.6) 0%, rgba(10, 18, 30, 0) 25%, rgba(10, 18, 30, 0.75) 100%);
}

/* --- Fixed top band -------------------------------------------------------- */

/* Spectrum strip and blog link stay put on scroll. The strip is the signature
   device — used exactly once, never behind text. */
.topband {
	position: fixed;
	top: 0;
	left: 0;
	right: 0;
	z-index: 5;
}

.spectrum {
	height: 2px;
	background: var(--spectrum);
}

/* Fade to canvas underneath, so content scrolling past never collides with
   the blog link. Solid at the top, transparent by the bottom edge. */
.topbar {
	display: flex;
	justify-content: flex-end;
	max-width: 1360px;
	margin: 0 auto;
	padding: var(--space-3) var(--space-6) var(--space-6);
	background: linear-gradient(180deg,
		var(--bg-canvas) 0%,
		var(--bg-canvas) 45%,
		rgba(10, 18, 30, 0) 100%);
}

/* --- Shell ---------------------------------------------------------------- */

.shell {
	position: relative;
	z-index: 2;
	display: flex;
	flex-direction: column;
	min-height: 100svh;
	max-width: 1360px;
	margin: 0 auto;
	padding: var(--space-8) var(--space-6) var(--space-5);
}

/* --- Blog link ------------------------------------------------------------ */

.loglink {
	display: inline-flex;
	align-items: center;
	gap: var(--space-2);
	padding: var(--space-2) var(--space-3);
	margin: calc(var(--space-2) * -1) calc(var(--space-3) * -1) 0 0;
	color: var(--text-muted);
	font-family: var(--font-display);
	font-size: 12px;
	font-weight: 500;
	letter-spacing: var(--ls-eyebrow);
	text-transform: uppercase;
	text-decoration: none;
	transition: color var(--duration-fast) var(--ease-standard);
}

.loglink svg {
	width: 12px;
	height: 12px;
	transition: transform var(--duration-base) var(--ease-standard);
}

.loglink:hover {
	color: var(--text-primary);
}

.loglink:hover svg {
	transform: translate(2px, -2px);
}

/* --- Stage ---------------------------------------------------------------- */

/* Deliberately off-centre: the column sits left, the depth field reads in the
   space to its right. Artwork can drop into that space later. */
.stage {
	flex: 1;
	display: flex;
	flex-direction: column;
	justify-content: center;
	max-width: 46ch;
	padding: var(--space-7) 0;
}

.lockup {
	display: flex;
	align-items: center;
	gap: var(--space-5);
	margin: 0;
}

.lockup .mark {
	width: clamp(84px, 11vw, 112px);
	height: auto;
	flex: none;
}

/* Sized to its own content so the eyebrow below can justify out to exactly
   the wordmark's width. Sizes and tracking live here as variables because the
   alignment maths below needs both. */
.lockup-text {
	--wm-size: clamp(30px, 3.6vw, 38px);
	--wm-track: 0.26;
	--eb-track: 0.22;

	/* The tagline is sized as a fraction of the wordmark rather than on its
	   own scale. text-align-last: justify can only stretch a line, so the
	   tagline must stay narrower than the wordmark or the lockup loses its
	   flush right edge — tying the two together keeps that headroom constant
	   at every breakpoint, instead of needing a fresh pair of numbers each
	   time one of them changes. Only --wm-size is set per tier below. */
	--eb-size: calc(var(--wm-size) * 0.32);

	display: flex;
	flex-direction: column;
	width: max-content;
	max-width: 100%;
}

.wordmark {
	margin: 0;
	font-family: var(--font-display);
	font-weight: 600;
	font-size: var(--wm-size);
	line-height: 1.06;
	/* Tracked out to read as a wordmark rather than a heading. */
	letter-spacing: calc(var(--wm-track) * 1em);
	color: var(--text-primary);
	text-transform: uppercase;
}

/* Justified to the wordmark: text-align-last spreads the four words to fill
   the line.

   Both lines stretch to the same box, but the wordmark's letter-spacing
   leaves a trailing gap after its final glyph, so its last letter stops short
   of the box edge. A justified line has no such gap — browsers trim trailing
   letter-spacing at the justified line end. Pulling the eyebrow in by exactly
   the wordmark's trailing gap lands the two last glyphs on the same pixel, at
   every clamped size. */
.eyebrow {
	margin: var(--space-3) 0 0;
	margin-right: calc(var(--wm-track) * var(--wm-size));
	font-family: var(--font-display);
	font-size: var(--eb-size);
	font-weight: 500;
	letter-spacing: calc(var(--eb-track) * 1em);
	text-transform: uppercase;
	color: var(--accent-secondary);
	text-align: justify;
	text-align-last: justify;
}

.rule {
	height: 1px;
	border: 0;
	background: var(--border-subtle);
	margin: var(--space-5) 0 var(--space-5);
}

.prompt {
	margin: 0 0 var(--space-4);
	font-size: 17px;
	color: var(--text-secondary);
}

/* --- Signup form ---------------------------------------------------------- */

#signup-form {
	margin: 0;
}

.field {
	display: flex;
	align-items: stretch;
	border: 1px solid var(--border-strong);
	border-radius: 7px;
	/* Clips the button's corners to the outer radius, so the two agree. */
	overflow: hidden;
	background: var(--bg-field);
	transition: border-color var(--duration-fast) var(--ease-standard),
	            box-shadow var(--duration-fast) var(--ease-standard);
}

.field:focus-within {
	border-color: var(--accent-secondary);
	box-shadow: var(--shadow-glow-ice);
}

.field input[type='email'] {
	flex: 1;
	min-width: 0;
	padding: var(--space-3) var(--space-4);
	border: 0;
	/* iOS gives inputs its own chrome — inset shadow, rounding, and extra
	   height that throws off a viewport-height layout. */
	-webkit-appearance: none;
	appearance: none;
	border-radius: 0;
	background: transparent;
	color: var(--text-primary);
	font-family: var(--font-body);
	font-size: 16px; /* 16px minimum: anything less makes iOS zoom on focus */
	line-height: 1.5;
}

.field input[type='email']::placeholder {
	color: #6A8395;
}

.field input[type='email']:focus {
	outline: none;
}

/* Ice on dark rather than light-on-steel: steel can't carry light text at AA
   (4.3:1, and 3.3:1 on hover). This also gives the page's one real action the
   weight it should have. */
.field button {
	flex: none;
	padding: var(--space-3) var(--space-5);
	border: 0;
	-webkit-appearance: none;
	appearance: none;
	border-radius: 0;
	background: var(--accent-secondary);
	color: var(--bg-canvas);
	font-family: var(--font-display);
	font-size: 13px;
	font-weight: 600;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	cursor: pointer;
	transition: background-color var(--duration-fast) var(--ease-standard);
}

.field button:hover {
	background: #C4E6E7;
}

#signup-form.loading .field button {
	opacity: 0.6;
	cursor: progress;
}

/* Ghost Portal toggles .success / .error on the form; site.js re-applies them
   after Portal's redirect, since classes don't survive a page load. */
.message {
	display: none;
	margin-top: var(--space-3);
	font-size: 14px;
	line-height: 1.5;
}

#signup-form.success .message.success {
	display: block;
	color: var(--accent-secondary);
}

#signup-form.error .message.failure:not(:empty) {
	display: block;
	color: var(--accent-alert);
}

/* Portal injects a floating trigger button we don't want. */
.gh-portal-triggerbtn-iframe {
	display: none !important;
}

/* --- Footer --------------------------------------------------------------- */

.foot {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: space-between;
	gap: var(--space-4);
	padding-top: var(--space-5);
	border-top: 1px solid var(--border-subtle);
}

.socials {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: var(--space-2);
	margin: 0;
	padding: 0;
	list-style: none;
}

.socials a {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 44px; /* 44px hit target, 20px glyph */
	height: 44px;
	color: var(--text-muted);
	transition: color var(--duration-fast) var(--ease-standard);
}

.socials svg {
	width: 20px;
	height: 20px;
}

/* Fab is a wordmark, not a square glyph — give it room instead of squashing it. */
.socials .wide a {
	width: 54px;
}

.socials .wide svg {
	width: 32px;
	height: 20px;
}

.socials a:hover {
	color: var(--accent-secondary);
}

.copyright {
	margin: 0;
	font-size: 12px;
	letter-spacing: 0.04em;
	color: #6F8698; /* 4.95:1 on canvas — #64798A was 4.15:1 and failed AA */
}

/* --- Narrow --------------------------------------------------------------- */

@media (max-width: 736px) {

	.shell {
		padding: var(--space-8) var(--space-5) var(--space-4);
	}

	.topbar {
		padding: var(--space-3) var(--space-5) var(--space-5);
	}

	body::after {
		background:
			radial-gradient(150% 80% at 50% 45%, rgba(10, 18, 30, 0.9) 0%, rgba(10, 18, 30, 0.5) 45%, rgba(10, 18, 30, 0) 75%),
			linear-gradient(180deg, rgba(10, 18, 30, 0.6) 0%, rgba(10, 18, 30, 0) 25%, rgba(10, 18, 30, 0.8) 100%);
	}

	.stage {
		padding: var(--space-6) 0;
	}

	.lockup {
		gap: var(--space-4);
	}

	.lockup .mark {
		width: clamp(52px, 15vw, 76px);
	}

	.lockup-text {
		--wm-size: clamp(30px, 8vw, 38px);
		--eb-track: 0.18;
	}

	.prompt {
		font-size: 16px;
	}

	.field {
		flex-direction: column;
		align-items: stretch;
	}

	.field button {
		padding: var(--space-4) var(--space-5);
	}

	.foot {
		flex-direction: column;
		align-items: flex-start;
		gap: var(--space-3);
	}

	/* All eight icons on one row. Width tightens and the row spreads to fill;
	   the 44px height keeps the tap target comfortable even as width shrinks
	   (WCAG 2.5.8 asks for 24x24 minimum). */
	.socials {
		width: 100%;
		flex-wrap: nowrap;
		justify-content: space-between;
		gap: 0;
	}

	.socials a {
		width: auto;
		flex: 1 1 0;
		min-width: 0;
	}

	.socials svg {
		width: clamp(17px, 4.8vw, 20px);
		height: clamp(17px, 4.8vw, 20px);
	}

	.socials .wide a {
		width: auto;
		flex: 1.5 1 0;
	}

	.socials .wide svg {
		width: clamp(27px, 7.7vw, 32px);
		height: clamp(17px, 4.8vw, 20px);
	}
}

/* --- Short viewports ------------------------------------------------------ */

/* Small phones (iPhone 12 mini and similar) give roughly 375x630 of usable
   height once Safari's chrome is showing, and less again if the visitor has
   bumped their system text size. Everything tightens so the form is still
   reachable without a scroll. */
@media (max-height: 700px) and (max-width: 736px) {

	.shell {
		padding-top: 56px;
		padding-bottom: var(--space-3);
	}

	.topbar {
		padding: var(--space-2) var(--space-5) var(--space-5);
	}

	.stage {
		padding: var(--space-4) 0;
	}

	.lockup {
		gap: var(--space-3);
	}

	/* The mark gives up room here so the tagline can stay legible: it is sized
	   as a fraction of the wordmark, and the wordmark is capped by the width
	   left over beside the mark. A smaller mark buys ~2px of tagline. */
	.lockup .mark {
		width: clamp(40px, 11vw, 56px);
	}

	.lockup-text {
		--wm-size: clamp(28px, 8.5vw, 32px);
	}

	.rule {
		margin: var(--space-4) 0;
	}

	.prompt {
		margin-bottom: var(--space-3);
		font-size: 15px;
	}

	.field input[type='email'],
	.field button {
		padding-top: var(--space-3);
		padding-bottom: var(--space-3);
	}

	.foot {
		padding-top: var(--space-3);
		gap: var(--space-2);
	}
}

/* Landscape phones — very little height, so the lockup shrinks hard and the
   footer tucks up beside it. */
@media (max-height: 500px) {

	.shell {
		padding-top: 44px;
		padding-bottom: var(--space-2);
	}

	.topbar {
		padding: var(--space-1) var(--space-5) var(--space-4);
	}

	.stage {
		padding: var(--space-2) 0;
	}

	.lockup .mark {
		width: clamp(38px, 9vh, 52px);
	}

	.lockup-text {
		--wm-size: clamp(26px, 7vh, 30px);
	}

	.rule {
		margin: var(--space-3) 0;
	}

	.prompt {
		margin-bottom: var(--space-2);
	}

	/* Side by side rather than stacked — height is the scarce axis here. */
	.field {
		flex-direction: row;
	}

	.foot {
		flex-direction: row;
		align-items: center;
		padding-top: var(--space-3);
	}

	.socials {
		width: auto;
		flex: 1;
	}
}

/* Desktop at short heights. */
@media (max-height: 620px) and (min-width: 737px) {

	.stage {
		padding: var(--space-5) 0;
	}

	.rule {
		margin: var(--space-4) 0;
	}
}

/* --- Reduced motion ------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {

	*,
	*::before,
	*::after {
		animation-duration: 0.01ms !important;
		animation-iteration-count: 1 !important;
		transition-duration: 0.01ms !important;
	}
}
