/* The home page: hero, steps, access request, FAQ.

   On the Astro site these four sections were React components whose every rule
   was an inline `style={{...}}` object -- `story.jsx`, about 190 lines of which
   maybe thirty were structure. Inline styles cannot carry a media query, so the
   layouts asked `useNarrow()`, a hook that reads `matchMedia` into state, which
   means the first server-rendered paint is always the wide layout and a phone
   gets a reflow on hydration.

   Here the sections are PHP and their rules are ordinary CSS, so the media
   query does the work and the page is right before any JavaScript runs. Every
   value is the one the inline object held; the token names are unchanged, so a
   rule here can be read against the component it came from.

   Only the figure is still React. It keeps its inline styles, because it is
   ported from a design bundle that wrote them that way and staying close to
   the source keeps the two comparable -- see src/RevisionAnimation.jsx.

   The breakpoint is 860px, which is what `useNarrow()` asked matchMedia for. */

/* --- section rhythm ----------------------------------------------------- */

.story-section {
	padding: var(--section-pad-y-lg) 0;
}

.story-hero {
	background: var(--blue-800);
	padding: var(--space-14) 0 var(--space-13);
}

.story-steps {
	background: var(--blue-900);
	border-top: var(--border-width) solid var(--line-on-dark);
}

.story-access {
	background: var(--blue-800);
	/* Clear of the sticky nav when the "Request access" link jumps here. */
	scroll-margin-top: 90px;
}

.story-faq {
	background: var(--paper-100);
	scroll-margin-top: 90px;
}

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

.hero-headline {
	font: var(--type-display);
	letter-spacing: var(--tracking-display);
	color: var(--paper);
	max-width: 26ch;
	margin-bottom: var(--gap-stack);
}

/* The one red thing in the headline. Keep it to the accent: the redline marks
   what changed, and if it decorates it stops marking. */
.hero-headline .accent {
	color: var(--redline-500);
}

.hero-lede {
	font: var(--type-lede);
	color: var(--paper-dim);
	max-width: var(--measure-prose);
	margin-bottom: var(--gap-stack);
}

.hero-body {
	font: var(--type-body);
	color: var(--paper-dim);
	max-width: var(--measure-prose);
	margin-bottom: var(--gap-block);
}

.hero-actions {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: var(--gap-inline);
	margin-bottom: var(--space-13);
}

.hero-figure {
	scroll-margin-top: var(--space-11);
}

/* Reserves the figure's height before the island mounts, so the sections below
   do not jump when it does. The figure is two sheets side by side, each half
   the width less a 16px gap, plus a fixed run of labels and controls: the
   sheets' 20px label row above, and the caption bar and the play/replay row
   below. So the placeholder is an aspect ratio for the sheets (1684 x 1191,
   twice over) and top padding for the rest, which includes the outline and
   inner padding around the whole figure (content-box, so the padding adds to
   the ratio rather than eating into it). The figure has no stacked layout;
   the sheets stay side by side at every width. Measured off the rendered
   figure at 320-976px wide: within 1px from 500px up. */
.figure-placeholder {
	display: block;
	box-sizing: content-box;
	width: 100%;
	aspect-ratio: 3368 / 1191;
	padding-top: 105px;
	border: var(--border-width) solid var(--line-on-dark);
	background: var(--fill-on-dark);
}

/* On a phone the caption bar under the sheets wraps to two lines. */
@media (max-width: 479px) {
	.figure-placeholder {
		padding-top: 117px;
	}
}

/* The figure's play/pause and replay buttons. The rest of the figure keeps its
   inline styles from the design bundle; these are here because an inline
   style cannot carry :hover or :focus-visible. */
.figure-control {
	height: 24px;
	min-width: 26px;
	padding: 0 var(--space-3);
	display: flex;
	align-items: center;
	justify-content: center;
	background: transparent;
	border: var(--border-width) solid var(--line-on-dark);
	border-radius: 0;
	font: var(--type-label);
	letter-spacing: var(--tracking-mono-wide);
	line-height: 1;
	color: var(--paper-dim);
	cursor: pointer;
	transition: var(--transition-action), var(--transition-border);
}

.figure-control:hover,
.figure-control:focus-visible {
	color: var(--redline-500);
	border-color: var(--redline-500);
}

/* --- steps -------------------------------------------------------------- */

.steps-grid {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(min(100%, 340px), 1fr));
	gap: var(--space-13);
	align-items: start;
}

.steps-heading {
	font: var(--type-h2);
	color: var(--redline-500);
	letter-spacing: var(--tracking-display);
	max-width: 22ch;
}

.steps-list {
	display: flex;
	flex-direction: column;
	gap: var(--space-7);
}

.step {
	display: grid;
	grid-template-columns: 40px minmax(0, 1fr);
	gap: var(--space-5);
	padding-bottom: var(--space-7);
	border-bottom: var(--border-width) solid var(--line-on-dark);
}

.step-number {
	font: var(--type-label);
	letter-spacing: var(--tracking-mono-wide);
	color: var(--redline-500);
	padding-top: 3px;
}

.step-title {
	font: var(--type-h3);
	color: var(--paper);
	margin-bottom: 6px;
}

.step-body {
	font: var(--type-body);
	color: var(--paper-dim);
}

/* --- access request ----------------------------------------------------- */

.access-grid {
	display: grid;
	grid-template-columns: minmax(0, 1fr) 380px;
	gap: var(--space-13);
	align-items: start;
}

.access-heading {
	font: var(--type-h2);
	color: var(--redline-500);
	letter-spacing: var(--tracking-display);
	max-width: 22ch;
	margin-bottom: var(--gap-stack);
}

.access-intro {
	font: var(--type-body);
	color: var(--paper-dim);
	max-width: var(--measure-narrow);
}

.access-card {
	border: var(--border-width) solid var(--line-on-dark);
	background: var(--fill-on-dark);
	padding: var(--space-7);
}

.access-form {
	display: flex;
	flex-direction: column;
	gap: var(--space-5);
}

/* `display` beats the `hidden` attribute: the browser's own `[hidden] {
   display: none }` is a UA rule, and any author rule that sets `display`
   wins it outright. Without this the confirmation appears and the form stays
   sitting under it, filled in, looking like the submit did nothing. Found by
   submitting the form in a browser, which is the only way it could have
   been. */
.access-form[hidden],
.access-sent[hidden] {
	display: none;
}

/* The bot trap. Off screen rather than display:none, because a field that is
   not rendered is a field a bot's parser skips too. Never focusable, never
   announced; see access.php for what filling it means. */
.access-trap {
	position: absolute;
	width: 1px;
	height: 1px;
	overflow: hidden;
	clip-path: inset(50%);
	white-space: nowrap;
}

/* Label, field and note as one <label>, so the text and the field are
   associated without an id. The border is the only state indicator. Ported
   from Input in src/components/cd/ui.jsx. */
.field {
	display: flex;
	flex-direction: column;
	gap: var(--space-2);
}

.field-label {
	font: var(--type-label);
	letter-spacing: var(--tracking-mono-wide);
	color: var(--paper-dim);
}

.field input[type="email"],
.field input[type="text"] {
	font: var(--type-body);
	color: var(--paper);
	background: var(--fill-on-dark);
	border: var(--border-width) solid var(--line-on-dark-strong);
	border-radius: var(--radius-none);
	padding: 14px 16px;
	outline: none;
	width: 100%;
	transition: var(--transition-border);
}

.field input:focus {
	border-color: var(--redline-500);
}

.field input[aria-invalid="true"] {
	border-color: var(--redline-600);
}

/* The personal-address note, and the server's answer when a submit is
   rejected. Same treatment: this is the thing to look at. */
.field-note,
.access-error {
	font: var(--type-label);
	color: var(--redline-500);
	line-height: 1.5;
	margin-top: var(--space-2);
}

/* Shown by the script the moment a free-mail domain is typed, and left in the
   markup so a server-side rejection can use the same slot. */
.field-note[hidden] {
	display: none;
}

/* What happens to the answers, under the form. It borrows .field-note's size
   and spacing and not its colour: the redline marks the thing that changed,
   and a standing note about data handling is not a change and not a fault.
   Red here would make the form look like it had rejected something. */
.access-privacy {
	color: var(--paper-dim);
}

.access-privacy a {
	color: inherit;
	text-decoration: underline;
	text-underline-offset: 2px;
}

.access-privacy a:hover,
.access-privacy a:focus-visible {
	color: var(--paper);
}

.access-check {
	display: flex;
	gap: var(--space-3);
	align-items: flex-start;
	cursor: pointer;
}

.access-check input {
	width: 16px;
	height: 16px;
	margin-top: 2px;
	accent-color: var(--redline-500);
	flex: 0 0 auto;
}

.access-check span {
	font: var(--type-label);
	color: var(--paper-dim);
	line-height: 1.5;
}

.btn-block {
	width: 100%;
	justify-content: center;
}

/* A disabled submit keeps its shape and loses its confidence, rather than
   disappearing and leaving the card looking unfinished. */
.btn:disabled {
	opacity: 0.42;
	cursor: not-allowed;
	background: var(--redline-500);
	color: var(--paper);
	border-color: var(--redline-500);
}

.access-sent-heading {
	font: var(--type-h3);
	color: var(--paper);
	margin-bottom: var(--space-3);
}

.access-sent-body {
	font: var(--type-body);
	color: var(--paper-dim);
	margin-bottom: var(--space-5);
}

.access-sent-link {
	font: var(--type-label);
	color: var(--redline-500);
}

/* --- FAQ ---------------------------------------------------------------- */

.faq-grid {
	display: grid;
	grid-template-columns: 280px minmax(0, 1fr);
	gap: var(--space-13);
}

.faq-heading {
	font: var(--type-h2);
	color: var(--redline-500);
	letter-spacing: var(--tracking-display);
}

/* <details>/<summary> rather than the React Accordion from ui.jsx.

   That component grew aria-expanded, aria-controls and a labelled region to
   tell a screen reader what the button did and what it opened. A disclosure
   element carries all three by itself, opens with JavaScript off, and is what
   LanguageSwitcher.astro already used for the same job. The visuals are
   unchanged, including the +/- glyph, which is decorative here because the
   element announces its own state. */
.accordion {
	border-top: var(--border-width) solid var(--line-on-light);
}

.accordion-item {
	border-bottom: var(--border-width) solid var(--line-on-light);
}

.accordion-question {
	display: flex;
	width: 100%;
	align-items: center;
	justify-content: space-between;
	gap: var(--space-5);
	list-style: none;
	cursor: pointer;
	text-align: left;
	padding: 18px 0;
	font: var(--type-body);
	font-weight: var(--weight-medium);
	color: var(--blue-800);
}

.accordion-question::-webkit-details-marker {
	display: none;
}

.accordion-question:focus-visible {
	outline: var(--border-width) solid var(--focus-ring);
	outline-offset: 2px;
}

.accordion-question::after {
	content: "+";
	font: var(--type-caption);
	color: var(--text-meta-light);
	flex: none;
}

.accordion-item[open] .accordion-question::after {
	content: "\2212";
	color: var(--redline-500);
}

.accordion-answer {
	font: var(--type-body);
	color: var(--text-body-light);
	max-width: var(--measure-prose);
	padding: 0 0 22px;
}

/* --- narrow ------------------------------------------------------------- */

/* 860px, the width useNarrow() asked matchMedia for. */
@media (max-width: 860px) {
	.story-section {
		padding: var(--section-pad-y) 0;
	}

	.story-hero {
		padding: var(--space-12) 0 var(--space-11);
	}

	.hero-actions {
		margin-bottom: var(--space-11);
	}

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

}
