/* Theerv — marketing site
   Hand-written, no build step. Tokens are lifted verbatim from
   theerv-app/src/app.css so the site and the app share one palette. */

/* ── Type ───────────────────────────────────────────── */

@font-face {
	font-family: 'Plus Jakarta Sans';
	font-style: normal;
	font-weight: 400 800;
	font-display: swap;
	src: url('../fonts/PlusJakartaSans-latin.woff2') format('woff2');
	unicode-range:
		U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329,
		U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
	font-family: 'Plus Jakarta Sans';
	font-style: normal;
	font-weight: 400 800;
	font-display: swap;
	src: url('../fonts/PlusJakartaSans-latin-ext.woff2') format('woff2');
	unicode-range:
		U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329,
		U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F,
		U+A720-A7FF;
}

/* ── Tokens ─────────────────────────────────────────── */

:root {
	/* From theerv-app/src/app.css — do not drift these. */
	--color-background: #fafaf8;
	--color-foreground: #1a1a1a;
	--color-card: #ffffff;
	--color-card-foreground: #1a1a1a;
	--color-muted: #f0efed;
	--color-muted-foreground: #7a756e;
	--color-tertiary: #a8a29e;
	--color-primary: #5b4ae4;
	--color-primary-foreground: #ffffff;
	--color-secondary: #f5f3ff;
	--color-secondary-foreground: #5b4ae4;
	--color-accent: #5b4ae4;
	--color-accent-foreground: #ffffff;
	--color-accent-light: #ede9fe;
	--color-accent-lighter: #f5f3ff;
	--color-destructive: #dc2626;
	--color-border: rgba(0, 0, 0, 0.06);
	--color-primary-shadow: rgba(91, 74, 228, 0.3);
	--color-subtle-bg: rgba(0, 0, 0, 0.04);
	--color-subtle-border: rgba(0, 0, 0, 0.03);
	/* The app's checkbox edge (input[type='checkbox']), for the site's form controls. */
	--color-control-border: rgba(0, 0, 0, 0.12);

	/* App status tokens, used only inside the mock screen grabs. */
	--color-status-completed: #22a06b;
	--color-green-bg: #ecfdf5;
	--color-amber: #d97706;
	--color-amber-bg: #fffbeb;
	--color-red-bg: #fef2f2;
	--color-blue-gray: #64748b;

	--radius-sm: 8px;
	--radius-md: 12px;
	--radius-lg: 16px;
	--radius-xl: 20px;
	--radius-2xl: 24px;
	--radius-full: 999px;

	--shadow-card: 0 2px 8px rgba(0, 0, 0, 0.05), 0 1px 2px rgba(0, 0, 0, 0.04);
	--shadow-card-hover: 0 4px 16px rgba(0, 0, 0, 0.06), 0 2px 4px rgba(0, 0, 0, 0.04);
	--shadow-modal: 0 12px 40px rgba(0, 0, 0, 0.1), 0 4px 12px rgba(0, 0, 0, 0.05);

	--font-sans: 'Plus Jakarta Sans', ui-sans-serif, system-ui, -apple-system, sans-serif;

	/* Site-only */
	--ease-out: cubic-bezier(0.16, 1, 0.3, 1);
	--ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);
	--wrap: 1200px;
	--gutter: clamp(20px, 5vw, 56px);
	--inset: max(var(--gutter), (100% - var(--wrap)) / 2);
	--section-space: clamp(56px, 6vw, 88px);
	--fade: clamp(48px, 6vw, 88px); /* how far a grey band of grabs takes to rise out of the white */
	--rule: 1px solid rgba(0, 0, 0, 0.08);
	--grab-w: 620px; /* a full-size screen grab; the sheets are drawn to this width */
}

/* ── Base ───────────────────────────────────────────── */

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

html {
	-webkit-font-smoothing: antialiased;
	-moz-osx-font-smoothing: grayscale;
	text-rendering: optimizeLegibility;
	-webkit-text-size-adjust: 100%;
	text-size-adjust: 100%;
}

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

body {
	margin: 0;
	font-family: var(--font-sans);
	font-size: 1.0625rem;
	line-height: 1.55;
	background: var(--color-card);
	color: var(--color-foreground);
	overflow-x: clip;
	-webkit-tap-highlight-color: transparent;
}

h1,
h2,
h3,
p,
figure {
	margin: 0;
}

::selection {
	background: var(--color-accent-light);
	color: var(--color-foreground);
}

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

svg {
	display: block;
}

.sprite {
	position: absolute;
	width: 0;
	height: 0;
	overflow: hidden;
}

.wrap {
	width: min(100% - 2 * var(--gutter), var(--wrap));
	margin-inline: auto;
}

/* The mark. One symbol, used everywhere; recolour with `color`. */
.mark {
	width: var(--mark-size, 28px);
	height: var(--mark-size, 28px);
	flex: none;
}

/* ── Header ─────────────────────────────────────────── */

.site-header .wrap {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 24px;
	min-height: 88px;
}

.brand {
	display: inline-flex;
	align-items: center;
	gap: 0.5em;
	min-height: 44px;
	color: var(--color-foreground);
	font-size: clamp(1.3125rem, 1.15rem + 0.5vw, 1.5rem);
	font-weight: 700;
	letter-spacing: -0.025em;
	text-decoration: none;
	border-radius: var(--radius-sm);
}

.brand .mark {
	--mark-size: 1.6em;
	transition: transform 0.9s var(--ease-out);
}

@media (hover: hover) {
	.brand:hover .mark {
		transform: rotate(-6deg);
	}
}

/* ── Buttons ────────────────────────────────────────── */

/* Same recipes as the app's .pill-btn and .text-btn: the accent tint, and the
   quiet one that only shows itself on hover. */
.pill-btn,
.text-btn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 8px;
	min-height: 44px;
	padding: 0 18px;
	border: 0;
	border-radius: 10px;
	background: var(--color-accent-lighter);
	color: var(--color-primary);
	font: inherit;
	font-size: 0.875rem;
	font-weight: 600;
	text-decoration: none;
	white-space: nowrap;
	cursor: pointer;
	transition:
		background-color 0.4s var(--ease-out),
		color 0.4s var(--ease-out),
		transform 0.2s var(--ease-out);
}

.text-btn {
	background: transparent;
	color: var(--color-muted-foreground);
}

.pill-btn svg,
.text-btn svg {
	width: 16px;
	height: 16px;
}

@media (hover: hover) {
	.pill-btn:hover {
		background: var(--color-accent-light);
	}

	.text-btn:hover {
		background: var(--color-subtle-bg);
		color: var(--color-foreground);
	}
}

.pill-btn:active,
.text-btn:active {
	transform: scale(0.96);
}

.btn {
	display: inline-flex;
	align-items: center;
	gap: 10px;
	min-height: 52px;
	padding: 0 24px;
	border: 0;
	border-radius: var(--radius-md);
	background: var(--color-primary);
	color: var(--color-primary-foreground);
	font: inherit;
	font-size: 0.9375rem;
	font-weight: 600;
	letter-spacing: -0.005em;
	text-decoration: none;
	cursor: pointer;
	box-shadow: 0 1px 2px rgba(0, 0, 0, 0.08);
	transition:
		box-shadow 0.6s var(--ease-out),
		transform 0.6s var(--ease-out);
}

.btn svg {
	width: 18px;
	height: 18px;
	transition: transform 0.6s var(--ease-out);
}

@media (hover: hover) {
	.btn:hover {
		transform: translateY(-1px);
		box-shadow:
			0 10px 24px -10px var(--color-primary-shadow),
			0 1px 2px rgba(0, 0, 0, 0.08);
	}

	.btn:hover svg {
		transform: translateX(3px);
	}
}

.btn:active {
	transform: scale(0.98);
	transition-duration: 0.15s;
}

/* Present but asleep: the waitlist's sign-in, until all three are answered.
   aria-disabled wears the same look while a send is under way, when the
   button keeps focus but won't take another press. */
.btn:disabled,
.btn[aria-disabled='true'] {
	background: var(--color-muted);
	color: var(--color-muted-foreground);
	box-shadow: none;
	cursor: default;
}

@media (hover: hover) {
	.btn:disabled:hover,
	.btn[aria-disabled='true']:hover {
		transform: none;
		box-shadow: none;
	}

	.btn:disabled:hover svg,
	.btn[aria-disabled='true']:hover svg {
		transform: none;
	}
}

.btn:disabled:active,
.btn[aria-disabled='true']:active {
	transform: none;
}

/* ── Problem sections ───────────────────────────────── */

/* The words sit on white and the grabs on the app's paper. The bands' fades are
   the space between chapters, so the white above each heading only needs a breath. */
.problem {
	padding-top: clamp(8px, 2vw, 24px);
}

.problem--hero {
	padding-top: clamp(32px, 5vw, 72px);
}

.problem__head {
	display: grid;
	grid-template-columns: repeat(12, minmax(0, 1fr));
	column-gap: 24px;
	align-items: start;
}

.problem__label {
	grid-column: 1 / span 3;
	display: flex;
	align-items: baseline;
	gap: 12px;
	padding-top: 0.55em;
	color: var(--color-muted-foreground);
	font-size: 0.875rem;
	font-weight: 500;
	letter-spacing: 0.005em;
}

.problem__num {
	color: var(--color-foreground);
	font-weight: 600;
	font-variant-numeric: tabular-nums;
}

.problem__title {
	grid-column: 4 / -1;
	max-width: 17em;
	font-size: clamp(2rem, 1.35rem + 2.6vw, 3.5rem);
	font-weight: 500;
	line-height: 1.1;
	letter-spacing: -0.028em;
	text-wrap: balance;
}

.problem--hero .problem__title {
	max-width: 15.5em;
	font-size: clamp(2.25rem, 1.25rem + 3.6vw, 4.125rem);
	line-height: 1.04;
	letter-spacing: -0.034em;
}

@media (max-width: 860px) {
	.problem__label,
	.problem__title {
		grid-column: 1 / -1;
	}

	.problem__label {
		padding-top: 0;
		margin-bottom: 18px;
	}
}

/* ── Rail (horizontal screen-grab carousel) ─────────── */

/* No hard edges: each band comes up out of the white and settles back into it. */
.rail {
	margin-top: clamp(8px, 1.5vw, 20px);
	padding-block: var(--fade);
	background: linear-gradient(
		var(--color-card),
		var(--color-background) var(--fade),
		var(--color-background) calc(100% - var(--fade)),
		var(--color-card)
	);
}

/* The last band runs on into the disclaimer, which is about the grabs; the fade out
   comes after it. border-image paints the fade to both edges past the .wrap. */
.problem:has(.disclaimer) .rail {
	padding-bottom: 0;
	background: linear-gradient(var(--color-card), var(--color-background) var(--fade));
}

.wrap:has(> .disclaimer) {
	padding-bottom: var(--fade);
	border-image: linear-gradient(var(--color-background), var(--color-card)) fill 0 / 0 / 0 100vmax;
}

.rail__track {
	position: relative;
	display: flex;
	align-items: flex-start;
	gap: clamp(16px, 2vw, 28px);
	overflow-x: auto;
	overscroll-behavior-x: contain;
	scroll-snap-type: x mandatory;
	padding: 12px var(--inset) 28px;
	scroll-padding-inline: var(--inset);
	scrollbar-width: none;
	outline-offset: -2px;
}

.rail__track::-webkit-scrollbar {
	display: none;
}

.shot {
	flex: none;
	width: var(--shot-w, min(var(--grab-w), 82vw));
	scroll-snap-align: start;
}

.shot--phone {
	--shot-w: min(330px, 76vw);
}

.shot--drive {
	--shot-w: min(540px, 82vw);
}

.shot__frame {
	container-type: inline-size;
	height: var(--shot-h, 460px);
	overflow: hidden;
	background: var(--color-card);
	border-radius: var(--radius-lg);
	box-shadow:
		var(--shadow-card),
		0 0 0 1px var(--color-border);
}

.shot--phone .shot__frame {
	border-radius: var(--radius-2xl);
}

.shot figcaption {
	display: flex;
	align-items: flex-start;
	justify-content: space-between;
	gap: 16px;
	margin-top: 18px;
	padding-right: 4px;
	color: var(--color-muted-foreground);
	font-size: 0.9375rem;
	line-height: 1.5;
	text-wrap: pretty;
}

.shot figcaption > span {
	max-width: 36ch;
}

@media (max-width: 640px) {
	:root {
		--shot-h: 420px;
	}
}

.rail__controls {
	display: none;
	align-items: center;
	gap: 10px;
	margin-top: 4px;
}

.js .rail__controls {
	display: flex;
}

.rail.is-static .rail__controls {
	visibility: hidden;
}

.rail__btn {
	display: grid;
	place-items: center;
	width: 44px;
	height: 44px;
	padding: 0;
	border: 1px solid rgba(0, 0, 0, 0.1);
	border-radius: var(--radius-full);
	background: transparent;
	color: var(--color-foreground);
	cursor: pointer;
	transition:
		background-color 0.5s var(--ease-out),
		border-color 0.5s var(--ease-out),
		box-shadow 0.5s var(--ease-out),
		opacity 0.4s var(--ease-out);
}

.rail__btn svg {
	width: 18px;
	height: 18px;
	transition: transform 0.6s var(--ease-out);
}

.rail__btn:disabled {
	opacity: 0.3;
	cursor: default;
}

@media (hover: hover) {
	.rail__btn:not(:disabled):hover {
		background: var(--color-card);
		border-color: transparent;
		box-shadow: var(--shadow-card-hover), 0 0 0 1px var(--color-border);
	}

	.rail__btn[data-dir='-1']:not(:disabled):hover svg {
		transform: translateX(-2px);
	}

	.rail__btn[data-dir='1']:not(:disabled):hover svg {
		transform: translateX(2px);
	}
}

.rail__btn:not(:disabled):active {
	transform: scale(0.94);
}

.rail__progress {
	position: relative;
	flex: 0 1 200px;
	height: 2px;
	margin-left: 14px;
	overflow: hidden;
	border-radius: 2px;
	background: rgba(0, 0, 0, 0.08);
}

.rail__progress span {
	position: absolute;
	inset: 0 auto 0 0;
	width: 40%;
	border-radius: inherit;
	background: var(--color-foreground);
	will-change: transform;
}

/* On phones the rail is a stack: each grab full width, its caption above it, nothing to
   page through. Phone-shaped grabs keep their own narrower width. */
@media (max-width: 640px) {
	.rail__track {
		flex-direction: column;
		gap: 56px;
		overflow: visible;
		scroll-snap-type: none;
		padding-inline: var(--gutter);
	}

	.shot,
	.shot--drive {
		display: flex;
		flex-direction: column;
		width: 100%;
	}

	/* A chat spans the column like the other grabs, and its height follows its width so it
	   keeps a phone's proportions on any screen; the thread sits at the bottom, as in a
	   real chat. The cap stops it outgrowing the screen on foldables. */
	.shot--phone {
		--shot-w: min(100%, 390px);
		width: var(--shot-w);
	}

	.shot--phone .shot__frame {
		height: auto;
		aspect-ratio: 323 / 480;
	}

	.shot figcaption {
		order: -1;
		margin: 0 0 14px;
		color: var(--color-foreground);
		font-size: 1rem;
	}

	.rail__controls,
	.js .rail__controls {
		display: none;
	}
}

/* The running chapter label (site.js §2): once a chapter's heading has gone off the top, its
   number and name stay put while its grabs pass. Phones only; the real heading is the one read out. */
.runner {
	display: none;
}

@media (max-width: 640px) {
	.runner {
		position: sticky;
		top: 0;
		z-index: 5;
		display: block;
		height: 0;
	}

	.runner__bar {
		display: flex;
		align-items: baseline;
		gap: 10px;
		padding: 14px var(--gutter) 12px;
		border-bottom: var(--rule);
		background: var(--color-card);
		color: var(--color-muted-foreground);
		font-size: 0.875rem;
		font-weight: 500;
		opacity: 0;
		transform: translate3d(0, -6px, 0);
		transition:
			opacity 0.6s var(--ease-out),
			transform 0.8s var(--ease-out);
		pointer-events: none;
	}

	.runner__num {
		color: var(--color-foreground);
		font-weight: 600;
	}

	.runner.is-on .runner__bar {
		opacity: 1;
		transform: none;
	}
}

@media (max-width: 640px) and (prefers-reduced-motion: reduce) {
	.runner__bar {
		transform: none;
		transition: opacity 0.4s linear;
	}
}

.disclaimer {
	padding-top: 20px;
	color: var(--color-muted-foreground);
	font-size: 0.8125rem;
	letter-spacing: 0.005em;
}

/* ── Story ──────────────────────────────────────────── */

.story {
	padding-top: clamp(8px, 2vw, 24px);
}

.story__grid {
	display: grid;
	grid-template-columns: repeat(12, minmax(0, 1fr));
	column-gap: 24px;
}

.story__aside {
	grid-column: 1 / span 3;
}

/* Content-width, so it can be moved to the centre of the screen without overflowing it. */
.story__sign {
	position: sticky;
	top: 40px;
	display: flex;
	width: fit-content;
	align-items: center;
	gap: 12px;
	padding-top: 0.4em;
	color: var(--color-muted-foreground);
	font-size: 1rem;
	font-weight: 500;
}

.story__sign .mark {
	--mark-size: 46px;
	color: var(--color-primary);
}

.story__body {
	grid-column: 4 / -1;
	max-width: 42rem;
}

.story__title {
	max-width: 13em;
	font-size: clamp(2.25rem, 1.4rem + 3.4vw, 4rem);
	font-weight: 500;
	line-height: 1.06;
	letter-spacing: -0.034em;
	text-wrap: balance;
}

/* The story's own paragraphs, and the CTA's line, which reads as one of them.
   Only direct children: the waitlist panel's copy sits deeper and is set on
   its own smaller scale. */
.story__body > p,
.story__cta-note {
	font-size: clamp(1.1875rem, 1.05rem + 0.5vw, 1.4375rem);
	line-height: 1.6;
	letter-spacing: -0.012em;
	text-wrap: pretty;
}

.story__body > p {
	margin-top: 1.5em;
}

.story__body .story__beat {
	margin-top: 2em;
	font-size: clamp(1.5rem, 1.2rem + 1.1vw, 2rem);
	font-weight: 550;
	line-height: 1.3;
	letter-spacing: -0.028em;
}

.story__body .story__beat + p {
	margin-top: 1em;
}

.story__cta {
	margin-top: clamp(48px, 6vw, 72px);
}

@media (max-width: 860px) {
	.story__aside,
	.story__body {
		grid-column: 1 / -1;
	}

	.story__sign {
		position: static;
		margin-bottom: 28px;
		padding-top: 0;
	}

	.story__sign .mark {
		--mark-size: 36px;
	}
}

/* ── Waitlist ───────────────────────────────────────── */

/* The line above the page's one CTA. Story body copy, not a heading. */
.story__cta-note {
	max-width: 26em;
	margin-bottom: clamp(24px, 3vw, 32px);
}

/* The arrow turns to point at what it opened. `rotate` is an independent
   transform, so the hover nudge on .btn svg doesn't fight it. */
.story__cta-btn svg {
	transition:
		transform 0.6s var(--ease-out),
		rotate 0.7s var(--ease-out);
}

.story__cta-btn[aria-expanded='true'] svg {
	rotate: 90deg;
}

@media (hover: hover) {
	.story__cta-btn[aria-expanded='true']:hover svg {
		transform: none;
	}
}

/* The panel opens the way the chat's sent bubble grows: a 0fr → 1fr row, so the
   height is the content's own and nothing is measured in JS. The gap above it
   is padding inside that row, so it opens with the panel and the row is the
   one thing animated.
   --ring-room keeps focus rings whole inside the clip. The largest is the
   site's 2px outline at a 3px offset (:focus-visible), 5px in all, and the room
   is taken back at the sides so nothing moves. The bottom needs none: the note
   and the status line close the form, and nothing there takes focus. */
.waitlist {
	--ring-room: 6px;
	display: grid;
	grid-template-rows: 0fr;
	margin-inline: calc(var(--ring-room) * -1);
	opacity: 0;
	transition:
		grid-template-rows 0.75s var(--ease-out),
		opacity 0.35s var(--ease-out);
}

.waitlist__inner {
	min-height: 0;
	overflow: hidden;
}

.waitlist__form,
.waitlist__done {
	padding: clamp(28px, 3.5vw, 40px) var(--ring-room) 0;
}

/* One measure for the whole form: the lede, the questions, the controls and the
   sign-in share an edge on both sides, so nothing trails off to its own width. */
.waitlist__form {
	max-width: calc(36rem + 2 * var(--ring-room));
}

.waitlist.is-open {
	grid-template-rows: 1fr;
	opacity: 1;
	transition:
		grid-template-rows 0.85s var(--ease-out),
		opacity 0.7s var(--ease-out) 0.1s;
}

/* Arriving by a hand-off link (site.js §8), the panel is already open. */
.waitlist.is-back {
	transition: none;
}

/* Without JS the panel is simply open and all three questions are there to
   read, since nothing can step through them. The button that would open it has
   nothing to do, so it goes, and the panel follows the line above it directly;
   sign-in stays inert. */
html:not(.js) .story__cta-btn {
	display: none;
}

html:not(.js) .waitlist {
	grid-template-rows: 1fr;
	opacity: 1;
}

html:not(.js) .waitlist__form {
	padding-top: 0;
}

html:not(.js) .waitlist__step {
	display: block;
}

html:not(.js) .waitlist__step + .waitlist__step {
	margin-top: clamp(28px, 3.5vw, 40px);
}

html:not(.js) .waitlist__nav {
	display: none;
}

.waitlist__lede {
	color: var(--color-muted-foreground);
	font-size: 1.0625rem;
	line-height: 1.5;
	letter-spacing: -0.005em;
}

/* One question at a time. The leaving step is taken out of the flow so the two
   cross over in place, and the box's height is eased between the two (site.js
   §8 clears it after 620ms, just past this 0.55s). This clip sits inside the
   panel's, so it keeps its own ring room, given back as margin so nothing
   inside moves. */
.waitlist__steps {
	position: relative;
	margin: calc(clamp(24px, 3vw, 32px) - var(--ring-room)) calc(var(--ring-room) * -1) calc(var(--ring-room) * -1);
	padding: var(--ring-room);
	overflow: hidden;
	transition: height 0.55s var(--ease-out);
}

.waitlist__step {
	display: none;
}

.waitlist__step.is-current,
.waitlist__step.is-leaving {
	display: block;
}

/* --slide is set by site.js to ±16px, by the direction of the step. */
.waitlist__step.is-leaving {
	position: absolute;
	inset: var(--ring-room) var(--ring-room) auto;
	opacity: 0;
	transform: translate3d(calc(var(--slide, 16px) * -1), 0, 0);
	transition:
		opacity 0.3s var(--ease-out),
		transform 0.5s var(--ease-out);
	pointer-events: none;
}

.waitlist__step.is-current {
	opacity: 1;
	transform: none;
	transition:
		opacity 0.5s var(--ease-out) 0.08s,
		transform 0.6s var(--ease-out) 0.08s;
}

/* The frame before it becomes current: held off to the side, unanimated. */
.waitlist__step.is-fresh {
	opacity: 0;
	transform: translate3d(var(--slide, 16px), 0, 0);
	transition: none;
}

/* The count and Back share a line above the question. Back is a step backwards,
   not the way forward, so it sits away from the control the eye is on; the row
   keeps its height on the first question, where there's nothing to go back to. */
.waitlist__head {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 16px;
	min-height: 44px;
}

.waitlist__head .text-btn {
	padding-inline: 12px;
}

html:not(.js) .waitlist__head [data-back] {
	display: none;
}

/* The chapters' hanging label, borrowed: muted words, the numeral in ink. */
.waitlist__count {
	color: var(--color-muted-foreground);
	font-size: 0.875rem;
	font-weight: 500;
	letter-spacing: 0.005em;
}

.waitlist__num {
	color: var(--color-foreground);
	font-weight: 600;
	font-variant-numeric: tabular-nums;
}

.waitlist__q {
	margin-top: 4px;
	font-size: clamp(1.25rem, 1.1rem + 0.6vw, 1.5rem);
	font-weight: 550;
	line-height: 1.3;
	letter-spacing: -0.022em;
	text-wrap: pretty;
}

.waitlist__field {
	--field-pad: 16px;
	position: relative;
	display: flex;
	align-items: center;
	width: min(100%, 220px);
	margin-top: 20px;
}

/* Focus is the site's own ring (:focus-visible), as on every other control
   in the panel, with no second edge of its own. */
.waitlist__input {
	width: 100%;
	min-height: 52px;
	padding: 0 var(--field-pad);
	border: 1px solid var(--color-control-border);
	border-radius: var(--radius-md);
	background: var(--color-card);
	color: var(--color-foreground);
	font: inherit;
	font-size: 1.0625rem;
	letter-spacing: -0.005em;
}

/* The ₹ sits in the field's own padding, and the text starts past it. */
.waitlist__input--prefixed {
	padding-inline-start: calc(var(--field-pad) + 18px);
}

.waitlist__input::placeholder {
	color: var(--color-tertiary);
}

.waitlist__prefix {
	position: absolute;
	inset-inline-start: var(--field-pad);
	color: var(--color-muted-foreground);
	font-size: 1.0625rem;
	pointer-events: none;
}

.waitlist__opts {
	display: flex;
	flex-wrap: wrap;
	gap: 10px;
	margin-top: 20px;
}

/* The radio itself stays in the page for the keyboard and for screen readers;
   only its box is drawn by the label. */
.waitlist__opt {
	position: relative;
	display: inline-flex;
	align-items: center;
	min-height: 44px;
	padding: 0 18px;
	border: 1px solid var(--color-control-border);
	border-radius: var(--radius-md);
	background: var(--color-card);
	font-size: 0.9375rem;
	font-weight: 500;
	letter-spacing: -0.005em;
	cursor: pointer;
	transition:
		border-color 0.4s var(--ease-out),
		background-color 0.4s var(--ease-out),
		color 0.4s var(--ease-out),
		transform 0.2s var(--ease-out);
}

/* A checked option is set in 600. An unseen 600 copy of the label holds its
   width at the heavier weight all along, so picking one never nudges the
   options after it. */
.waitlist__opt span {
	display: inline-grid;
}

.waitlist__opt span::after {
	content: attr(data-label);
	height: 0;
	overflow: hidden;
	font-weight: 600;
	visibility: hidden;
}

.waitlist__opt input {
	position: absolute;
	width: 1px;
	height: 1px;
	margin: 0;
	opacity: 0;
	pointer-events: none;
}

@media (hover: hover) {
	.waitlist__opt:hover {
		border-color: var(--color-tertiary);
	}
}

.waitlist__opt:has(input:checked) {
	border-color: var(--color-primary);
	background: var(--color-accent-lighter);
	color: var(--color-primary);
	font-weight: 600;
}

.waitlist__opt:has(input:focus-visible) {
	outline: 2px solid var(--color-primary);
	outline-offset: 3px;
}

.waitlist__opt:active {
	transform: scale(0.98);
}

.waitlist__error {
	margin-top: 12px;
	color: var(--color-destructive);
	font-size: 0.9375rem;
}

/* Only the way forward is left under the control: Next is the site's .pill-btn. */
.waitlist__nav {
	display: flex;
	flex-wrap: wrap;
	gap: 8px;
	margin-top: 20px;
}

/* Answering and signing in are two moves, so a hairline parts them. The note is
   about the button, so it stands beside it where there's room. */
.waitlist__signin {
	display: grid;
	grid-template-columns: auto minmax(0, 1fr);
	column-gap: 24px;
	align-items: center;
	margin-top: clamp(28px, 3.5vw, 36px);
	padding-top: clamp(28px, 3.5vw, 36px);
	border-top: var(--rule);
}

.waitlist__signin > * {
	grid-column: 1 / -1;
}

.waitlist__signin > [data-signin] {
	grid-column: 1;
}

.waitlist__signin > [data-signin-note] {
	grid-column: 2;
	max-width: 22em;
	margin-top: 0;
}

.waitlist__note {
	max-width: 32em;
	margin-top: 10px;
	color: var(--color-muted-foreground);
	font-size: 0.9375rem;
	line-height: 1.5;
}

.waitlist__status {
	max-width: 32em;
	margin-top: 14px;
	color: var(--color-destructive);
	font-size: 0.9375rem;
	line-height: 1.5;
}

.waitlist__status.is-busy,
.waitlist__status.is-ok {
	color: var(--color-muted-foreground);
}

/* Inside an app's own browser the sign-in gives way to a hand-off to the real
   one (site.js §8). The classes below set display, which would beat [hidden]. */
.waitlist__signin [hidden] {
	display: none;
}

.waitlist__handoff-line {
	max-width: 32em;
	font-size: 1.0625rem;
	line-height: 1.5;
	letter-spacing: -0.005em;
}

.waitlist__handoff .waitlist__nav {
	align-items: center;
	margin-top: 18px;
}

/* Copy link: the app's accent tint (.pill-btn's), never the filled violet. It is
   the fallback, beside a way out or on its own. */
.btn.btn--second {
	background: var(--color-accent-lighter);
	color: var(--color-primary);
	box-shadow: none;
}

@media (hover: hover) {
	.btn.btn--second:hover {
		background: var(--color-accent-light);
		box-shadow: none;
	}
}

/* The control a returning visitor lands on (site.js §8): focused, but the ring
   waits for a key. Instead it gives a soft press, as if tapped, and one more
   three seconds in if it's still untouched. */
.btn.is-cued:focus-visible {
	outline: none;
}

@media (prefers-reduced-motion: no-preference) {
	.btn.is-cued {
		animation: cue-press 1.4s var(--ease-out) 0.6s both;
	}

	.btn.is-cued.is-again {
		animation-delay: 0s;
	}
}

@keyframes cue-press {
	0%,
	100% {
		transform: none;
	}

	18% {
		transform: scale(0.97);
	}
}

/* The fallback copy selects this; it has to be on the page to be selected, so
   it is only taken out of sight. 16px keeps iOS from zooming in on it. */
.waitlist__copy {
	position: absolute;
	width: 1px;
	height: 1px;
	opacity: 0;
	font-size: 16px;
	pointer-events: none;
}

.waitlist__done-line {
	font-size: clamp(1.375rem, 1.2rem + 0.7vw, 1.75rem);
	font-weight: 550;
	line-height: 1.3;
	letter-spacing: -0.028em;
}

/* Focused only so it's read out when it appears (site.js §8). It isn't a
   control, so it takes no ring. */
.waitlist__done-line:focus {
	outline: none;
}

/* The note carries the visitor's email, which can be longer than a phone is
   wide; it breaks inside the address rather than running off the edge. */
.waitlist__done .waitlist__note {
	margin-top: 12px;
	overflow-wrap: anywhere;
}

@media (max-width: 640px) {
	.story__cta-btn,
	.waitlist__signin .btn {
		width: 100%;
		justify-content: center;
	}

	.waitlist__signin {
		grid-template-columns: minmax(0, 1fr);
	}

	.waitlist__signin > [data-signin-note] {
		grid-column: 1;
		margin-top: 12px;
	}

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

/* Under reduced motion the panel is open or shut and the step there or not:
   no height, slide or turn. Only a short fade is kept, as the reveals do, and
   presses keep their small scale, as every button on the site does. */
@media (prefers-reduced-motion: reduce) {
	.waitlist,
	.waitlist.is-open,
	.waitlist__step.is-current {
		transition: opacity 0.4s linear;
	}

	.waitlist__steps,
	.waitlist__step.is-leaving,
	.story__cta-btn svg {
		transition: none;
	}

	.waitlist__step.is-current,
	.waitlist__step.is-fresh,
	.waitlist__step.is-leaving {
		transform: none;
	}

	.waitlist__step.is-leaving {
		display: none;
	}
}

/* ── Privacy policy ─────────────────────────────────── */

/* Its own page, set like the story: hanging label, text in columns 4–12. */
.policy {
	padding-top: clamp(48px, 9vw, 120px);
}

.policy__grid {
	display: grid;
	grid-template-columns: repeat(12, minmax(0, 1fr));
	column-gap: 24px;
}

.policy__label {
	grid-column: 1 / span 3;
	padding-top: 1.1em;
	color: var(--color-muted-foreground);
	font-size: 0.875rem;
	font-weight: 500;
	letter-spacing: 0.005em;
}

.policy__body {
	grid-column: 4 / -1;
	max-width: 40rem;
}

.policy__title {
	font-size: clamp(2.25rem, 1.4rem + 3.4vw, 4rem);
	font-weight: 500;
	line-height: 1.06;
	letter-spacing: -0.034em;
}

.policy__body h2 {
	margin-top: 2.4em;
	font-size: 1.1875rem;
	font-weight: 600;
	letter-spacing: -0.015em;
}

.policy__body p {
	margin-top: 0.75em;
	font-size: 1.0625rem;
	line-height: 1.65;
	letter-spacing: -0.006em;
	text-wrap: pretty;
}

.policy__title + p {
	margin-top: 1.5em;
}

.policy__body a {
	color: var(--color-primary);
	text-decoration-thickness: 1px;
	text-underline-offset: 0.2em;
}

@media (max-width: 860px) {
	.policy__label,
	.policy__body {
		grid-column: 1 / -1;
	}

	.policy__label {
		padding-top: 0;
		margin-bottom: 16px;
	}
}

/* ── Footer ─────────────────────────────────────────── */

/* The page signs off in the middle: the name and who makes it, with the two
   quiet ways out at the edges, level with the name. */
.site-footer {
	margin-top: var(--section-space);
	padding-bottom: clamp(48px, 6vw, 72px);
}

.site-footer .wrap {
	padding-top: clamp(40px, 5vw, 64px);
	border-top: var(--rule);
}

.site-footer__body {
	display: grid;
	grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
	grid-template-areas:
		'reach brand privacy'
		'. maker .';
	align-items: center;
	text-align: center;
}

.site-footer .brand {
	grid-area: brand;
	justify-self: center;
	font-size: 1.125rem;
}

.site-footer .brand .mark {
	--mark-size: 1.35em;
}

/* An unregistered mark: small, raised to the cap height, out of the way. */
.brand__tm {
	margin-left: 0.1em;
	font-size: 0.5em;
	font-weight: 500;
	letter-spacing: 0;
	vertical-align: 1em;
	line-height: 0;
}

.site-footer__maker {
	grid-area: maker;
	margin-top: 2px;
	color: var(--color-muted-foreground);
	font-size: 0.8125rem;
	letter-spacing: 0.005em;
}

/* The maker's name is a way to write to them, for anyone who looks; it
   doesn't look like a link until it's pointed at. */
.site-footer__maker a {
	color: inherit;
	text-decoration: none;
	text-underline-offset: 0.25em;
	text-decoration-thickness: 1px;
	transition: color 0.4s var(--ease-out);
}

/* Reaching out and the policy are the same quiet text: neither is the page's
   call to action, which stays the waitlist. */
.site-footer__link {
	display: inline-flex;
	align-items: center;
	min-height: 44px;
	color: var(--color-muted-foreground);
	font-size: 0.875rem;
	font-weight: 500;
	text-decoration: none;
	text-underline-offset: 0.3em;
	text-decoration-thickness: 1px;
	transition: color 0.4s var(--ease-out);
}

.site-footer__link--reach {
	grid-area: reach;
	justify-self: start;
}

.site-footer__link--privacy {
	grid-area: privacy;
	justify-self: end;
}

@media (hover: hover) {
	.site-footer__link:hover,
	.site-footer__maker a:hover {
		color: var(--color-foreground);
		text-decoration-line: underline;
	}
}

/* Phones: the name and maker get the width; the ways out drop to a row under them. */
@media (max-width: 640px) {
	.site-footer__body {
		grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
		grid-template-areas:
			'brand brand'
			'maker maker'
			'reach privacy';
	}

	.site-footer__link {
		margin-top: 20px;
	}
}


/* ── Reveal ─────────────────────────────────────────── */

.js [data-reveal] {
	opacity: 0;
	transform: translate3d(0, 20px, 0);
	transition:
		opacity 1.1s var(--ease-out),
		transform 1.3s var(--ease-out);
	transition-delay: var(--d, 0ms);
}

.js .rail[data-reveal] {
	opacity: 1;
	transform: none;
}

.js .rail[data-reveal] .shot {
	opacity: 0;
	transform: translate3d(28px, 0, 0);
	transition:
		opacity 1.1s var(--ease-out),
		transform 1.4s var(--ease-out);
	transition-delay: calc(var(--i, 0) * 80ms + 120ms);
}

.js [data-reveal].is-in,
.js .rail[data-reveal].is-in .shot {
	opacity: 1;
	transform: none;
}

/* Stacked on phones, each grab arrives on its own as it comes into view (site.js §1),
   rising like the other reveals, not sliding in from the side. */
@media (max-width: 640px) {
	.js .rail[data-reveal] .shot,
	.js .rail[data-reveal].is-in .shot {
		opacity: 0;
		transition-delay: 0ms;
	}

	.js .rail[data-reveal] .shot.is-in {
		opacity: 1;
		transform: none;
	}
}

@media (max-width: 640px) and (prefers-reduced-motion: no-preference) {
	.js .rail[data-reveal] .shot,
	.js .rail[data-reveal].is-in .shot {
		transform: translate3d(0, 20px, 0);
	}

	.js .rail[data-reveal] .shot.is-in {
		transform: none;
	}
}

/* The story's mark (site.js §4) is held at the centre of the screen, fades in there,
   then travels to its place. site.js holds the heading until the mark has cleared it. */
@media (prefers-reduced-motion: no-preference) {
	.js .story__sign.is-away {
		translate: var(--travel, 0px) 0;
	}

	.js .story__sign.is-in {
		transition:
			opacity 0.8s var(--ease-out),
			transform 1.3s var(--ease-out),
			translate 1.5s var(--ease-in-out) 0.4s;
	}
}

@media (prefers-reduced-motion: reduce) {
	.js [data-reveal],
	.js .rail[data-reveal] .shot {
		transform: none;
		transition: opacity 0.4s linear;
		transition-delay: 0ms;
	}
}

/* ════════════════════════════════════════════════════
   Mock screen grabs
   Illustrations of the problem (sheets, chats, docs) —
   not Theerv's UI. Messy content, tidy execution.
   ════════════════════════════════════════════════════ */

/* The grabs rewrite and move their own contents (the document's pages, the chats' bubbles),
   so the browser mustn't pin the page's scroll to anything inside them: it would follow
   that content and jump the page. */
.mock {
	overflow-anchor: none;
	display: flex;
	flex-direction: column;
	height: 100%;
	color: var(--color-foreground);
	font-size: 12px;
	line-height: 1.4;
	font-variant-numeric: tabular-nums;
	cursor: default;
	-webkit-user-select: none;
	user-select: none;
}

.i {
	width: 16px;
	height: 16px;
	flex: none;
}

.glyph-sheet {
	color: var(--color-status-completed);
}
.glyph-doc {
	color: var(--color-blue-gray);
}
.glyph-pdf {
	color: var(--color-destructive);
}
.glyph-folder {
	color: var(--color-tertiary);
}

/* Window chrome shared by the sheet / drive / doc grabs */
.win {
	display: flex;
	align-items: center;
	gap: 10px;
	padding: 12px 14px 10px;
	border-bottom: 1px solid var(--color-border);
}

.win .i {
	width: 20px;
	height: 20px;
}

.win__title {
	font-size: 12.5px;
	font-weight: 600;
	letter-spacing: -0.01em;
	white-space: nowrap;
}

.win__menu {
	display: flex;
	gap: 11px;
	margin-top: 1px;
	color: var(--color-tertiary);
	font-size: 11px;
	white-space: nowrap;
}

/* ── Spreadsheet ── */

.fx {
	display: flex;
	align-items: center;
	height: 30px;
	border-bottom: 1px solid var(--color-border);
	font-size: 11.5px;
	white-space: nowrap;
}

.fx__ref {
	width: 58px;
	padding-left: 12px;
	color: var(--color-muted-foreground);
	border-right: 1px solid var(--color-border);
}

.fx__sym {
	padding: 0 10px;
	color: var(--color-tertiary);
	font-style: italic;
	font-weight: 500;
}

.sheet__grid {
	flex: 1;
	overflow: hidden;
	background: var(--color-card);
}

/* Columns keep their set widths and run off the frame edge, like a real sheet. */
.sheet table {
	width: max-content;
	border-collapse: collapse;
	table-layout: fixed;
	white-space: nowrap;
}

.sheet th,
.sheet td {
	height: 29px;
	padding: 0 8px;
	border: 1px solid rgba(0, 0, 0, 0.07);
	overflow: hidden;
	text-align: left;
	font-weight: 400;
}

.sheet thead th,
.sheet tbody th {
	background: var(--color-background);
	color: var(--color-tertiary);
	font-size: 10.5px;
	font-weight: 500;
	text-align: center;
}

.sheet thead th {
	height: 22px;
}

.sheet .hd td {
	font-weight: 600;
	background: rgba(0, 0, 0, 0.018);
}

.sheet .r {
	text-align: right;
}

.sheet .dim {
	color: var(--color-tertiary);
}

.sheet .muted {
	color: var(--color-muted-foreground);
}

.sheet .cx {
	background: var(--color-red-bg);
	color: var(--color-destructive);
	font-weight: 500;
}

.sheet .ok {
	background: var(--color-green-bg);
	color: var(--color-status-completed);
	font-weight: 500;
}

.sheet .hm {
	background: var(--color-amber-bg);
	color: var(--color-amber);
}

.sheet .note-cell {
	color: var(--color-amber);
	font-style: normal;
}

.sheet .sel {
	position: relative;
	outline: 2px solid var(--color-primary);
	outline-offset: -1px;
	background: var(--color-card);
}

.sheet .sel::after {
	content: '';
	position: absolute;
	right: -1px;
	bottom: -1px;
	width: 6px;
	height: 6px;
	background: var(--color-primary);
	border: 1px solid #fff;
}

.sheet .row-on th {
	background: var(--color-accent-light);
	color: var(--color-primary);
}

.sheet .row-new td {
	background: var(--color-accent-lighter);
}

.sheet .row-new td.sel {
	background: var(--color-card);
}

/* Frozen column divider */
.sheet .frz {
	border-right: 3px solid rgba(0, 0, 0, 0.1);
}

/* Widths are set per column in the markup, as --w. */
.sheet col {
	width: var(--w);
}

.sheet .has-note {
	position: relative;
}

.sheet .has-note::before {
	content: '';
	position: absolute;
	top: 0;
	right: 0;
	border-style: solid;
	border-width: 0 7px 7px 0;
	border-color: transparent var(--color-amber) transparent transparent;
}

.caret {
	display: inline-block;
	width: 1.5px;
	height: 1.15em;
	margin-left: 1px;
	vertical-align: -0.2em;
	background: var(--color-primary);
}

.sheet__tabs {
	display: flex;
	align-items: stretch;
	gap: 2px;
	height: 34px;
	padding: 0 10px;
	border-top: 1px solid var(--color-border);
	background: var(--color-background);
	font-size: 11px;
	white-space: nowrap;
	overflow: hidden;
}

.sheet__tabs span {
	display: flex;
	align-items: center;
	padding: 0 12px;
	color: var(--color-muted-foreground);
}

.sheet__tabs .on {
	background: var(--color-card);
	color: var(--color-foreground);
	font-weight: 600;
	box-shadow: inset 0 2px 0 var(--color-status-completed);
}

.sheet__tabs .add {
	color: var(--color-tertiary);
	font-size: 14px;
	padding: 0 10px;
}

/* Zoomed crop of a sheet */
.sheet--zoom {
	--row: 38px;
	font-size: 14px;
}

.sheet--zoom th,
.sheet--zoom td {
	height: var(--row);
	padding: 0 12px;
}

.sheet--zoom thead th,
.sheet--zoom tbody th {
	font-size: 12px;
}

.sheet--zoom thead th {
	height: 26px;
}

.sheet__stage {
	position: relative;
	flex: 1;
	overflow: hidden;
}

.sheet-note {
	position: absolute;
	width: 208px;
	padding: 12px 14px;
	background: var(--color-card);
	border-radius: var(--radius-md);
	box-shadow: var(--shadow-modal), 0 0 0 1px var(--color-border);
	font-size: 12.5px;
	line-height: 1.45;
	white-space: normal;
}

.sheet-note b {
	display: block;
	margin-bottom: 4px;
	color: var(--color-muted-foreground);
	font-size: 11px;
	font-weight: 600;
}

/* The sheet as drawn for a full-size grab, cut off at its edge. */
.sheet__pan {
	position: relative;
	width: var(--grab-w);
	overflow: clip;
}

/* In a narrower frame the whole sheet is still there: the grid and the tabs pan sideways
   under the fixed toolbar, the way a sheet does on a phone. */
@container (max-width: 619px) {
	.sheet__grid,
	.sheet__stage,
	.sheet__tabs {
		overflow-x: auto;
		scrollbar-width: none;
	}

	.sheet__grid::-webkit-scrollbar,
	.sheet__stage::-webkit-scrollbar,
	.sheet__tabs::-webkit-scrollbar {
		display: none;
	}

	/* Browsers make a pannable box a keyboard stop; keep its ring inside the frame. */
	.sheet__grid:focus-visible,
	.sheet__stage:focus-visible,
	.sheet__tabs:focus-visible {
		outline-offset: -2px;
	}

	/* The close-up's frozen column A holds while the dates pan beneath it. Its cells draw
	   their own borders here, so the frozen ones carry theirs along. */
	.sheet--zoom table {
		border-collapse: separate;
		border-spacing: 0;
	}

	.sheet--zoom th,
	.sheet--zoom td {
		border-width: 0 1px 1px 0;
	}

	.sheet--zoom tr > :first-child,
	.sheet--zoom .frz {
		position: sticky;
		left: 0;
		z-index: 1;
	}

	.sheet--zoom .frz {
		left: 38px; /* the row-number column's width */
		background: var(--color-card);
	}

	.sheet--zoom .hd .frz {
		background: linear-gradient(rgba(0, 0, 0, 0.018) 0 0) var(--color-card);
	}

	/* The note floats over everything, frozen column included, and gets out of the way once
	   the sheet is panned, as a sheet's note does when you scroll. */
	.sheet--zoom .sheet-note {
		z-index: 2;
	}

	@supports (animation-timeline: scroll()) {
		.sheet--zoom .sheet-note {
			animation: note-away linear both;
			animation-timeline: scroll(nearest inline);
			animation-range: 0 56px;
		}
	}
}

@keyframes note-away {
	to {
		opacity: 0;
		visibility: hidden;
	}
}

/* Phone frames are 40px shorter (--shot-h); rows tighten so the same rows still fit. */
@media (max-width: 640px) {
	.sheet:not(.sheet--zoom) tbody th,
	.sheet:not(.sheet--zoom) tbody td {
		height: 25px;
	}

	.sheet--zoom {
		--row: 34px;
	}
}

/* ── Chat ── */

.chat {
	font-size: 13px;
	line-height: 1.38;
	background: var(--color-muted);
}

.chat__bar {
	display: flex;
	align-items: center;
	gap: 10px;
	padding: 14px 14px 12px 8px;
	background: var(--color-card);
	border-bottom: 1px solid var(--color-border);
}

.chat__bar .i {
	width: 20px;
	height: 20px;
	color: var(--color-muted-foreground);
}

.chat__bar .i:last-child {
	margin-left: auto;
}

.avatar {
	display: grid;
	place-items: center;
	width: 34px;
	height: 34px;
	border-radius: 50%;
	background: var(--color-muted);
	color: var(--color-muted-foreground);
	font-size: 11.5px;
	font-weight: 600;
	letter-spacing: 0.02em;
}

.chat__name {
	font-size: 14px;
	font-weight: 600;
	letter-spacing: -0.01em;
}

.chat__status {
	color: var(--color-muted-foreground);
	font-size: 11px;
}

.chat__thread {
	flex: 1;
	display: flex;
	flex-direction: column;
	justify-content: flex-end;
	min-height: 0;
	overflow: hidden;
	padding: 12px 12px 10px;
}

.chat__day {
	align-self: center;
	margin: 10px 0 4px;
	padding: 3px 10px;
	border-radius: var(--radius-sm);
	background: rgba(255, 255, 255, 0.75);
	color: var(--color-muted-foreground);
	font-size: 10.5px;
	font-weight: 500;
}

.msg {
	position: relative;
	max-width: 80%;
	margin-top: 6px;
	padding: 7px 10px 6px;
	border-radius: 12px;
	background: var(--color-card);
	box-shadow: 0 1px 0.5px rgba(0, 0, 0, 0.06);
	align-self: flex-start;
	border-top-left-radius: 4px;
}

.msg--out {
	align-self: flex-end;
	background: var(--color-green-bg);
	border-top-left-radius: 12px;
	border-top-right-radius: 4px;
}

.msg + .msg--in,
.msg--in + .msg--in,
.msg--out + .msg--out {
	border-top-left-radius: 12px;
	border-top-right-radius: 12px;
	margin-top: 3px;
}

.msg p {
	display: inline;
}

.msg__meta {
	float: right;
	display: inline-flex;
	align-items: center;
	gap: 3px;
	margin: 6px 0 -2px 10px;
	color: var(--color-tertiary);
	font-size: 10px;
	line-height: 1;
	white-space: nowrap;
}

.ticks {
	position: relative;
	width: 16px;
	height: 12px;
	color: var(--color-muted-foreground);
}

.ticks svg {
	position: absolute;
	inset: 0;
	width: 16px;
	height: 12px;
}

.ticks .one {
	opacity: 0;
}

.ticks.is-pending .one {
	opacity: 1;
}

.ticks.is-pending .two {
	opacity: 0;
}

.ticks svg {
	transition: opacity 0.35s var(--ease-out);
}

/* Shared file bubble */
.file {
	position: relative;
	display: flex;
	align-items: center;
	gap: 9px;
	margin: 1px 0 4px;
	padding: 8px 9px;
	border-radius: var(--radius-sm);
	background: rgba(0, 0, 0, 0.035);
}

.file .i {
	width: 26px;
	height: 26px;
}

.file__name {
	max-width: 176px;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
	font-size: 12px;
	font-weight: 500;
}

.file__meta {
	color: var(--color-muted-foreground);
	font-size: 10.5px;
}

.msg--file {
	width: 238px;
	max-width: 88%;
	padding: 4px 4px 5px;
}

.msg--file .msg__meta {
	margin-right: 6px;
	margin-top: 0;
}

/* Sending (site.js §6): the file uploads, a ring filling round its icon and a clock where
   its ticks will be, then it's delivered. The ring snaps back to empty only while hidden;
   it fills over each file's own --load. */
.file .i,
.file__ring {
	transition: opacity 0.35s var(--ease-out);
}

.file__ring {
	position: absolute;
	top: calc(50% - 17px);
	left: 5px;
	width: 34px;
	height: 34px;
	rotate: -90deg;
	fill: none;
	stroke-width: 1.75;
	opacity: 0;
}

.file__ring circle:first-child {
	stroke: var(--color-border);
}

.file__ring circle:last-child {
	stroke: var(--color-status-completed);
	stroke-linecap: round;
	stroke-dasharray: 100;
}

.ticks .wait {
	opacity: 0;
}

.is-sending .file .i {
	opacity: 0.45;
}

.is-sending .file__ring,
.is-sending .ticks .wait {
	opacity: 1;
}

.is-sending .ticks .two {
	opacity: 0;
}

.is-sending .file__ring circle:last-child {
	stroke-dashoffset: 94;
}

.is-sending.is-loading .file__ring circle:last-child {
	stroke-dashoffset: 0;
	transition: stroke-dashoffset var(--load, 2s) cubic-bezier(0.37, 0, 0.63, 1);
}

/* Compose bar */
.chat__compose {
	display: flex;
	align-items: center;
	gap: 8px;
	padding: 8px 10px 12px;
}

.chat__field {
	position: relative;
	flex: 1;
	display: flex;
	align-items: center;
	justify-content: flex-end; /* only bites on overflow: keeps the caret end in view */
	min-width: 0;
	height: 40px;
	padding: 0 16px;
	border-radius: var(--radius-full);
	background: var(--color-card);
	box-shadow: 0 1px 0.5px rgba(0, 0, 0, 0.06);
	white-space: pre;
	overflow: hidden;
}

.chat__line {
	flex: 1 0 auto;
	display: flex;
	align-items: center;
}

.chat__placeholder {
	position: absolute;
	left: 16px;
	color: var(--color-tertiary);
}

.chat__placeholder[hidden] {
	display: none;
}

.chat__caret {
	display: none;
	width: 1.5px;
	height: 18px;
	margin-left: 1px;
	background: var(--color-status-completed);
	animation: caret-blink 1.06s steps(1, end) infinite;
}

.chat__field.is-focused .chat__caret {
	display: inline-block;
}

.chat__field.is-typing .chat__caret {
	animation: none;
}

@keyframes caret-blink {
	0%,
	100% {
		opacity: 1;
	}
	50% {
		opacity: 0;
	}
}

.chat__send {
	position: relative;
	display: grid;
	place-items: center;
	width: 40px;
	height: 40px;
	flex: none;
	border-radius: 50%;
	background: var(--color-status-completed);
	color: #fff;
	transition: transform 0.18s var(--ease-out);
}

.chat__send.is-pressed {
	transform: scale(0.9);
}

.chat__send svg {
	position: absolute;
	width: 19px;
	height: 19px;
	transition:
		opacity 0.25s var(--ease-out),
		transform 0.35s var(--ease-out);
}

.chat__send .send {
	opacity: 0;
	transform: scale(0.6) rotate(-20deg);
}

.chat__send.has-text .mic {
	opacity: 0;
	transform: scale(0.6);
}

.chat__send.has-text .send {
	opacity: 1;
	transform: none;
}

/* The sent bubble grows into the thread rather than popping in. Between loops it leaves
   the other way: fades first, then the gap closes (base transitions time the leave,
   .is-sent ones time the arrival). */
.msg-enter {
	display: grid;
	grid-template-rows: 0fr;
	justify-items: end;
	transition: grid-template-rows 0.6s var(--ease-in-out) 0.2s;
}

.msg-enter > div {
	display: flex;
	flex-direction: column;
	align-items: flex-end;
	min-height: 0;
	overflow: hidden;
	padding-bottom: 1px;
}

.msg-enter .msg {
	opacity: 0;
	transform: translate3d(0, 10px, 0) scale(0.97);
	transform-origin: 100% 100%;
	transition:
		opacity 0.3s var(--ease-out),
		transform 0.5s var(--ease-out);
}

.msg-enter.is-sent {
	grid-template-rows: 1fr;
	transition: grid-template-rows 0.7s var(--ease-out);
}

.msg-enter.is-sent .msg {
	opacity: 1;
	transform: none;
	transition:
		opacity 0.5s var(--ease-out) 0.08s,
		transform 0.8s var(--ease-out) 0.04s;
}

@media (prefers-reduced-motion: reduce) {
	.chat__caret {
		animation: none;
	}

	.msg-enter,
	.msg-enter .msg,
	.msg-enter.is-sent,
	.msg-enter.is-sent .msg,
	.chat__send svg {
		transition: none;
	}
}

/* ── Drive ── */

.drive__crumbs {
	display: flex;
	align-items: center;
	gap: 6px;
	color: var(--color-muted-foreground);
	font-size: 12px;
	white-space: nowrap;
}

.drive__crumbs b {
	color: var(--color-foreground);
	font-weight: 600;
}

.drive__crumbs .sep {
	color: var(--color-tertiary);
}

.drive__count {
	margin-left: auto;
	padding: 3px 9px;
	border-radius: var(--radius-full);
	background: var(--color-muted);
	color: var(--color-muted-foreground);
	font-size: 11px;
	font-weight: 500;
	white-space: nowrap;
}

.drive__cols,
.drive__list li {
	display: grid;
	grid-template-columns: 22px minmax(0, 1fr) 96px;
	align-items: center;
	gap: 10px;
	padding: 0 16px;
}

.drive__cols {
	height: 32px;
	border-bottom: 1px solid var(--color-border);
	color: var(--color-muted-foreground);
	font-size: 11px;
	font-weight: 500;
}

.drive__cols span:first-child {
	grid-column: 1 / span 2;
}

.drive__list {
	flex: 1;
	margin: 0;
	padding: 0;
	list-style: none;
	overflow: hidden;
	-webkit-mask-image: linear-gradient(to bottom, #000 70%, transparent);
	mask-image: linear-gradient(to bottom, #000 70%, transparent);
}

.drive__list li {
	height: 37px;
	border-bottom: 1px solid var(--color-subtle-border);
}

.drive__list li > span:nth-child(2) {
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

.drive__list li > span:last-child {
	color: var(--color-muted-foreground);
	font-size: 11px;
}

.drive__list .i {
	width: 18px;
	height: 18px;
}

@container (max-width: 400px) {
	.drive__cols,
	.drive__list li {
		grid-template-columns: 22px minmax(0, 1fr) 72px;
	}

	.drive__crumbs .far {
		display: none;
	}
}

/* ── Doc ── */

.doc__tools {
	display: flex;
	align-items: center;
	gap: 14px;
	height: 34px;
	padding: 0 14px;
	border-bottom: 1px solid var(--color-border);
	color: var(--color-muted-foreground);
	font-size: 11.5px;
	white-space: nowrap;
	overflow: hidden;
}

.doc__tools b {
	color: var(--color-foreground);
	font-weight: 700;
}

.doc__tools i {
	color: var(--color-foreground);
	font-style: italic;
}

.doc__tools u {
	color: var(--color-foreground);
}

.doc__tools .div {
	width: 1px;
	height: 16px;
	background: var(--color-border);
}

.doc__body {
	flex: 1;
	display: flex;
	min-height: 0;
	background: var(--color-muted);
}

.doc__outline {
	flex: none;
	width: 150px;
	padding: 16px 0 0 16px;
	overflow: hidden;
	color: var(--color-muted-foreground);
	font-size: 10.5px;
	-webkit-mask-image: linear-gradient(to bottom, #000 80%, transparent);
	mask-image: linear-gradient(to bottom, #000 80%, transparent);
}

.doc__outline-title {
	margin: 0 0 8px;
	color: var(--color-foreground);
	font-size: 11px;
	font-weight: 600;
}

.doc__outline ol {
	margin: 0;
	padding: 0;
	list-style: none;
}

.doc__outline li {
	padding: 3px 0;
	white-space: nowrap;
}

.doc__outline .gap {
	letter-spacing: 0.2em;
	color: var(--color-tertiary);
}

.doc__outline .on {
	color: var(--color-primary);
	font-weight: 600;
}

.doc__canvas {
	position: relative;
	flex: 1;
	min-width: 0;
	padding: 18px 26px 0 8px;
	overflow: hidden;
}

.doc__page {
	height: 100%;
	padding: 30px 34px;
	background: var(--color-card);
	box-shadow: 0 1px 3px rgba(0, 0, 0, 0.06);
	font-size: 11px;
	line-height: 1.6;
	overflow: hidden;
}

.doc__h {
	margin: 0 0 6px;
	font-size: 12.5px;
	font-weight: 700;
	letter-spacing: -0.01em;
}

.doc__h:not(:first-child) {
	margin-top: 18px;
}

.doc__page p {
	margin: 0 0 8px;
	color: #3a3835;
}

.doc__page .pg {
	margin: 0 -34px 18px;
	padding: 0 34px 8px;
	border-bottom: 1px dashed rgba(0, 0, 0, 0.1);
	color: var(--color-tertiary);
	font-size: 10px;
	text-align: right;
}

.doc__scroll {
	position: absolute;
	top: 18px;
	right: 9px;
	bottom: 8px;
	width: 5px;
	border-radius: 3px;
	background: rgba(0, 0, 0, 0.04);
}

.doc__scroll span {
	position: absolute;
	right: 0;
	bottom: 0;
	width: 5px;
	height: 7px;
	border-radius: 3px;
	background: var(--color-tertiary);
}

.doc__status {
	display: flex;
	justify-content: space-between;
	gap: 12px;
	padding: 9px 14px 10px;
	border-top: 1px solid var(--color-border);
	color: var(--color-muted-foreground);
	font-size: 11px;
	white-space: nowrap;
}

.doc__status b {
	color: var(--color-foreground);
	font-weight: 600;
}

/* The document hauled up to page 1 (site.js §7). Its pages ride a reel of three, placed by
   transform; the thumb darkens while it's held. Without the reel (no JS, reduced motion)
   the drawn page stands alone, as above. Nothing here scrolls for the reader. */
.doc__reel {
	--page-gap: 22px; /* past the canvas's top margin and the page shadow, so at rest the page before stays out of sight */
	position: relative;
	height: 100%;
	transition: opacity 0.5s var(--ease-out);
}

.doc__reel .doc__page {
	position: absolute;
	inset: 0 0 auto;
	height: auto;
	aspect-ratio: 210 / 297; /* A4; no will-change, which would set the text differently from the drawn page */
}

.doc__reel .doc__page > * {
	opacity: var(--ink, 1);
}

.doc__scroll {
	transition: opacity 0.5s var(--ease-out);
}

.doc__scroll span {
	transition: background-color 0.4s var(--ease-out);
}

.doc__scroll.is-held span {
	background: var(--color-muted-foreground);
}

.doc.is-rewinding .doc__reel,
.doc.is-rewinding .doc__scroll {
	opacity: 0;
	transition-duration: 0.3s;
}

@container (max-width: 480px) {
	.doc__outline {
		display: none;
	}

	.doc__canvas {
		padding-left: 18px;
	}

	.doc__page {
		padding: 24px 22px;
	}

	.doc__page .pg {
		margin-inline: -22px;
		padding-inline: 22px;
	}
}
