/* =============================================================================
   Stockaroo — marketing surface
   -----------------------------------------------------------------------------
   The public, logged-out pages. Loaded AFTER site.css so it can consume both the
   brand tokens and the app's own components.

   WHY THIS FILE EXISTS
   The landing page kept its styles in a ~440-line inline <style> block inside
   index.pug, which no second page could reach. Adding /product/* pages without a
   shared sheet would mean copy/pasting that block per page. This is the smallest
   structure that avoids that: one plain stylesheet, no build step, no framework.
   Pair it with views/mixins/marketing.pug.

   WHAT IT DELIBERATELY DOES NOT CONTAIN
   Stat tiles, tables and status badges. The app already has .stat-card,
   .stat-value, .stat-label, .table, .table-container and .badge--* in site.css,
   and site.css is loaded on these pages. A readout renders THOSE, at their real
   size. Two payoffs: the marketing page shows the product's actual components
   rather than a lookalike, and a restyle of the app carries to the marketing
   site for free instead of drifting away from it.
   So: if the app has a component, use it. Only add here what is marketing-only.

   THE COLOUR RULE (inherited from site.css, restated because it is load-bearing)
     --color-primary  is a FILL.  #25863a is 4.48:1 on the paper background,
                      which misses WCAG AA for body text by a hair.
     --color-accent   is accent TEXT. #1b6a2c is 6.49:1 on the same background.
   Both flip correctly in the dark theme, so neither needs a dark-mode override.
   Never set accent-coloured text to --color-primary.

   THE HONESTY RULE
   Every .sk-readout is a DEPICTION of the product. The figures inside one are
   representative, not any customer's data. +readout() therefore renders the
   "Illustrative" marker unconditionally — not as an opt-in flag, because an
   opt-in flag is a thing someone forgets. See docs/slop.md §3 and §18.
   ========================================================================== */

:root {
	/* ---- type ---------------------------------------------------------------
	   Instrument Sans, for the whole public surface. This is the Precision
	   typeface and it is used there the way it is used here: one family doing
	   display, body and label work, with the label role separated by case,
	   tracking and size rather than by a second font. Precision's own
	   --pc-font-mono resolves to Instrument Sans (its IBM Plex Mono line is
	   commented out), which is why its "THE PRECISION DIFFERENCE" eyebrows read
	   as machine-set without actually being monospace.

	   SCOPE: public pages only. The app keeps Clash Display + Satoshi from
	   site.css — those are self-hosted and wired into every logged-in screen.
	   Marketing and product therefore differ by one typeface. That is a
	   deliberate split, not an oversight; unify in one direction or the other
	   when someone decides which face is the brand. */
	--font-marketing: "Instrument Sans", -apple-system, BlinkMacSystemFont,
		"Segoe UI", sans-serif;

	/* The eyebrow / table-head / chip role. Same family, set small, uppercase
	   and widely tracked. Not a monospace — figures get tabular-nums instead,
	   which aligns columns without changing the face. */
	--font-label: var(--font-marketing);

	/* Stated as a flat fallback first, so a browser without color-mix() drops
	   only the second declaration and still renders the rule. */
	--sk-rule: var(--border-secondary);
	--sk-rule: color-mix(in srgb, var(--border-secondary) 55%, transparent);

	/* Marketing-only rhythm.
	   Tightened 2026-09-10 from clamp(4rem, 9vw, 7.5rem). At 7.5rem a section
	   break cost 240px of empty page top and bottom, so on a laptop you scrolled
	   through a screen of nothing between every two ideas. This is a tool for
	   people who work in a warehouse, not a gallery wall — the density should
	   read as "there is a lot here", not "please admire the spacing".
	   Sections still separate clearly because .sk-band--sunken alternates the
	   surface and rules the edges; the gap is not carrying that job alone. */
	--sk-band: clamp(2.5rem, 5vw, 4.25rem);
	--sk-gutter: clamp(1.25rem, 4vw, 2.5rem);
	--sk-measure: 62ch;

	/* Gap between a band's heading block and whatever it introduces. */
	--sk-lead: clamp(1.5rem, 3vw, 2.25rem);
}

/* =============================================================================
   0. THE PUBLIC SURFACE
   -----------------------------------------------------------------------------
   Instrument Sans applies to the whole logged-out page, not only to the
   components below, so the public site reads as one typeface rather than two.
   index.pug's .sk-body rule sets Satoshi directly, and its inline <style> block
   loads after this file — hence the element+class selector here, which outruns
   a bare class without needing !important.
   ========================================================================== */

body.sk-body,
body.sk-body h1,
body.sk-body h2,
body.sk-body h3,
body.sk-body h4,
body.noauth-body,
body.noauth-body h1,
body.noauth-body h2,
body.noauth-body h3,
body.noauth-body h4 {
	font-family: var(--font-marketing);
}

/* noauth.css sets the brand display face on these by name. It loads before
   this file on the auth pages, so a matching-specificity rule here wins, but
   state it explicitly rather than relying on order. */
.noauth-body .auth-title,
.noauth-body .auth-logo__text,
.noauth-body .public-nav__brand,
.noauth-body .section-title,
.noauth-body .hero-title,
.noauth-body .cta-title {
	font-family: var(--font-marketing);
}

/* ---- theme toggle icons -----------------------------------------------------
   The nav button holds both a sun and a moon and shows one. These rules lived
   in index.pug's inline <style>, so when the shared layout copied the nav
   markup for /security and /product/* it got both icons at once. Shared now —
   one definition, every public page.

   Light mode REMOVES the data-theme attribute rather than setting it to
   "light" (see js/theme.js), which is why the sun is selected with :not()
   rather than [data-theme="light"]. */
.sk-sun,
.sk-moon {
	display: none;
}

:root:not([data-theme="dark"]) .sk-sun {
	display: block;
}

[data-theme="dark"] .sk-moon {
	display: block;
}

/* =============================================================================
   1. SECTION CHASSIS
   ========================================================================== */

.sk-band {
	padding-block: var(--sk-band);
}

.sk-band--sunken {
	background: var(--bg-secondary);
	border-block: 1px solid var(--border-primary);
}

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

.sk-shell--tight {
	width: min(56rem, 100% - (var(--sk-gutter) * 2));
}

/* ---- the measure rule ------------------------------------------------------
   Stockaroo counts things for a living, so the section index is drawn as a
   ruler: an index number, a mono label, then a tick rule with a taller tick
   every fifth position. Two repeating gradients — no image, no JS. This is the
   page's signature; it should not be reused as generic decoration. */

.sk-index {
	display: flex;
	align-items: center;
	gap: 0.875rem;
	margin-bottom: 1rem;
}

/* The body of a band — whatever the heading introduces. */
.sk-body-slot {
	margin-top: var(--sk-lead);
}

.sk-index__no {
	font-family: var(--font-label);
	font-size: 0.75rem;
	font-weight: 600;
	font-variant-numeric: tabular-nums;
	color: var(--color-accent);
	letter-spacing: 0.06em;
}

.sk-index__label {
	font-family: var(--font-label);
	font-size: 0.6875rem;
	font-weight: 500;
	text-transform: uppercase;
	letter-spacing: 0.16em;
	color: var(--text-tertiary);
	white-space: nowrap;
}

.sk-index__rule {
	flex: 1;
	height: 0.625rem;
	min-width: 2rem;
	background-image:
		repeating-linear-gradient(to right, var(--sk-rule) 0 1px, transparent 1px 8px),
		repeating-linear-gradient(to right, var(--sk-rule) 0 1px, transparent 1px 40px);
	background-size: 100% 0.25rem, 100% 0.5625rem;
	background-position: left bottom, left bottom;
	background-repeat: repeat-x;
	opacity: 0.7;
}

/* ---- headings -------------------------------------------------------------- */

.sk-title {
	font-family: var(--font-marketing);
	font-size: clamp(1.875rem, 4.2vw, 3rem);
	font-weight: 600;
	line-height: 1.1;
	letter-spacing: -0.02em;
	color: var(--text-primary);
	margin: 0 0 1rem;
	max-width: 20ch;
	text-wrap: balance;
}

/* The second clause of a two-clause headline: "Sell on six channels.
   /Hold one stock figure./" Carries the emphasis so clause one stays quiet.
   Accent TEXT, so --color-accent — never --color-primary. */
.sk-title__turn {
	color: var(--color-accent);
	display: block;
}

/* NOT .sk-lede — index.pug's inline <style> already owns that name for its
   centred section ledes (max-width 560px, margin auto) and, being an inline
   block in the head, wins the cascade over this file. This one is left-aligned
   and measure-limited, so it needs its own name. */
.sk-band__lede {
	max-width: var(--sk-measure);
	font-size: clamp(1rem, 1.6vw, 1.125rem);
	line-height: 1.65;
	color: var(--text-secondary);
	margin: 0;
}

/* A line of context inside a readout, above the thing it describes. */
.sk-readout__note {
	font-size: 0.8125rem;
	color: var(--text-secondary);
	margin: 0 0 0.125rem;
}

/* =============================================================================
   2. READOUT — the product depiction
   -----------------------------------------------------------------------------
   A small, honest drawing of a real Stockaroo screen, so a page can show a
   capability instead of asserting one. The frame is marketing-only; everything
   inside it should be the app's own components at their natural size.
   ========================================================================== */

.sk-readout {
	background: var(--bg-card);
	border: 1px solid var(--border-primary);
	border-radius: var(--radius-lg);
	overflow: hidden;
	/* One soft shadow, on this element only. Cards elsewhere on these pages are
	   flat — the shadow is what lifts the product above the prose. */
	box-shadow: 0 1.5rem 3rem -1.5rem rgb(19 77 32 / 0.18);
}

[data-theme="dark"] .sk-readout {
	box-shadow: 0 1.5rem 3rem -1.5rem rgb(0 0 0 / 0.55);
}

/* A readout given the whole shell instead of one column of a split. The point
   is NOT bigger chrome - it is ROOM, so the panel can hold what the real screen
   holds (four stat cards across, a full table) at the app's own sizes, instead
   of two cards and a stub. Same rule as ever: never scale a component down,
   change how many fit. */
.sk-readout--wide .sk-readout__body {
	padding: 1.25rem;
	gap: 1rem;
}

/* The scrollable table inside a wide readout is focusable (see index.pug), so
   it needs a visible focus ring like any other focusable thing. */
.sk-readout .table-container:focus-visible {
	outline: 2px solid var(--border-focus);
	outline-offset: 2px;
}

.sk-readout__bar {
	display: flex;
	align-items: center;
	gap: 0.75rem;
	padding: 0.6875rem 1rem;
	background: var(--bg-tertiary);
	border-bottom: 1px solid var(--border-primary);
}

/* The chrome carries the mascot, not just the word. Every readout is a small
   window onto the product, and the kangaroo is what makes one recognisably
   ours at a glance. favicon-512.png is the mark on its own - it was previously
   doing nothing but sitting in a browser tab. */
.sk-readout__mark {
	display: inline-flex;
	align-items: center;
	gap: 0.4375rem;
	font-family: var(--font-marketing);
	font-size: 0.8125rem;
	font-weight: 600;
	color: var(--text-primary);
	letter-spacing: -0.01em;
}

.sk-readout__mark img {
	width: 1.125rem;
	height: 1.125rem;
	object-fit: contain;
}

.sk-readout__crumb {
	font-size: 0.75rem;
	color: var(--text-tertiary);
}

.sk-readout__pick {
	margin-left: auto;
	display: inline-flex;
	align-items: center;
	gap: 0.375rem;
	padding: 0.25rem 0.625rem;
	font-size: 0.6875rem;
	color: var(--text-secondary);
	background: var(--bg-card);
	border: 1px solid var(--border-primary);
	border-radius: var(--radius-sm);
}

.sk-readout__body {
	padding: 0.875rem;
	display: grid;
	gap: 0.75rem;
}

/* NOTHING HERE RESIZES AN APP COMPONENT.
   An earlier version shrank .stat-card's padding, icon and 2rem figure so three
   would fit the hero column. The result no longer looked like the product,
   which defeats the entire purpose of rendering the real components. Fit is
   solved by showing FEWER cards in a wider column, never by scaling them down.
   If a readout looks cramped, cut what it shows.

   The single exception is below, and it removes behaviour rather than changing
   appearance. */

/* A readout is a picture, not a control. site.css gives .stat-card
   `transition: all`, which exists for hover states these cards do not have.
   Nothing here should animate under a cursor and imply it can be clicked. */
.sk-readout .stat-card {
	transition: none;
}

/* The app's own tabular-figure rule covers .table and .stat-value. This adds
   the right-alignment a numeric column needs, without touching the face. */
.sk-readout .table .sk-num {
	text-align: right;
	color: var(--text-primary);
}

/* ---- the illustrative marker ----------------------------------------------
   Non-negotiable. Inside the readout, in the reading order, legible, not a
   watermark. Amber because it is a caution and amber is already the app's
   warning hue. */

.sk-illustrative {
	display: flex;
	align-items: flex-start;
	gap: 0.4375rem;
	padding: 0.5rem 1rem;
	font-size: 0.6875rem;
	line-height: 1.45;
	color: var(--color-warning);
	background: var(--color-warning-bg);
	border-top: 1px solid var(--border-primary);
}

.sk-illustrative svg {
	flex: none;
	margin-top: 0.125rem;
}

/* =============================================================================
   3. THE ONE READOUT PART THAT IS OURS
   -----------------------------------------------------------------------------
   This section used to hold .sk-rail, .sk-fanout, .sk-channels and .sk-chip —
   marketing lookalikes of the onboarding wizard, the inventory listing rows,
   the dashboard's platform-status tiles and the app's badges. All four are
   deleted. The readouts now render the real components:

     wizard steps      -> .wizard-step*        (site.css, moved from onboarding.pug)
     connection cards  -> .connection-card*    (site.css, moved from connections.pug)
     platform tiles    -> .tk-panel + .tk-tint-* + .badge   (dashboard.pug markup)
     listing rows      -> edit-inventory.js buildListingRow()
     stat cards        -> .stat-card / .stat-value / .stat-label
     tables            -> .table / .table-container

   The rule this cost two rounds to learn: if the app has the component, use the
   app's component. Build nothing here that the product already draws.

   What remains is one modifier, because the product has no equivalent — the app
   never needs to point at the channel an order arrived on.
   ========================================================================== */

/* The listing row for the channel the sale landed on. A tint and a left edge
   over the real row; the row itself is unchanged, and the distinction is also
   written in the row's own text ("order landed here") so it survives greyscale. */
.sk-listing-source {
	background: var(--color-success-bg) !important;
	border-left: 2px solid var(--color-primary) !important;
}

/* =============================================================================
   3b. CONVERGENCE
   -----------------------------------------------------------------------------
   Six channel marks on one side, the Stockaroo mark on the other, a run
   between them. It replaces a section that asserted the problem in prose and
   showed nothing — measured as the thinnest real section on the page: 590px of
   height carrying 12 elements.

   Built from the app's own .tk-tint-<channel> wells, the same tiles the
   dashboard's Platform Status row and the logo strip use, so it speaks the
   product's vocabulary rather than being an infographic bolted on.
   ========================================================================== */

.sk-converge {
	display: grid;
	gap: clamp(1.25rem, 3vw, 2rem);
	align-items: center;
	justify-items: center;
	grid-template-columns: 1fr;
	/* Capped and centred. Left to fill the 78rem shell, the run stretched to
	   ~955px and the two sides stopped reading as related — the diagram is
	   about convergence, and convergence needs the ends close enough to see
	   at once. */
	max-width: 46rem;
	margin-inline: auto;
}

@media (min-width: 48rem) {
	.sk-converge {
		grid-template-columns: auto minmax(3rem, 1fr) auto;
	}
}

.sk-converge__channels {
	display: grid;
	grid-template-columns: repeat(3, auto);
	gap: 0.625rem;
	margin: 0;
	padding: 0;
	list-style: none;
}

@media (min-width: 48rem) {
	.sk-converge__channels {
		grid-template-columns: repeat(2, auto);
	}
}

.sk-converge__ch {
	width: 3.25rem;
	height: 3.25rem;
	border-radius: var(--radius-lg);
	display: flex;
	align-items: center;
	justify-content: center;
}

.sk-converge__ch img {
	width: 1.75rem;
	height: 1.75rem;
	object-fit: contain;
}

/* The run between the two sides. Same tick vocabulary as the measure rule, so
   it reads as this page's own language rather than a stock arrow. */
.sk-converge__run {
	position: relative;
	width: 100%;
	height: 0.625rem;
	background-image: repeating-linear-gradient(to right, var(--sk-rule) 0 1px, transparent 1px 8px);
	background-size: 100% 0.25rem;
	background-position: left center;
	background-repeat: repeat-x;
}

.sk-converge__run::after {
	content: "";
	position: absolute;
	right: 0;
	top: 50%;
	translate: 0 -50%;
	border-left: 0.5rem solid var(--color-primary);
	border-block: 0.3125rem solid transparent;
}

/* Stacked layout: the run turns to point downward. */
@media (max-width: 47.99rem) {
	.sk-converge__run {
		width: 0.625rem;
		height: 2.5rem;
		background-image: repeating-linear-gradient(to bottom, var(--sk-rule) 0 1px, transparent 1px 8px);
		background-size: 0.25rem 100%;
		background-position: center top;
		background-repeat: repeat-y;
	}

	.sk-converge__run::after {
		right: 50%;
		top: auto;
		bottom: 0;
		translate: 50% 0;
		border-left: 0.3125rem solid transparent;
		border-right: 0.3125rem solid transparent;
		border-top: 0.5rem solid var(--color-primary);
		border-bottom: 0;
	}
}

.sk-converge__hub {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 0.5rem;
	text-align: center;
}

.sk-converge__hub img {
	width: clamp(5.5rem, 12vw, 8rem);
	height: auto;
}

.sk-converge__hub b {
	font-size: 0.9375rem;
	color: var(--text-primary);
}

.sk-converge__hub span {
	font-family: var(--font-label);
	font-size: 0.625rem;
	text-transform: uppercase;
	letter-spacing: 0.12em;
	color: var(--text-tertiary);
}

/* =============================================================================
   3c. WORKFLOW RAIL
   -----------------------------------------------------------------------------
   The order's journey. Every step is a state the product actually has — there
   is no "pack" step in the schema, so there is none here. See the accuracy
   note on the section in index.pug.
   ========================================================================== */

.sk-flow {
	list-style: none;
	margin: 0;
	padding: 0;
	display: grid;
	gap: 0.625rem;
	grid-template-columns: 1fr;
	counter-reset: flow;
}

@media (min-width: 56rem) {
	.sk-flow {
		grid-template-columns: repeat(5, 1fr);
	}

	/* /platform's journey has SIX steps, not the five this rail was built for,
	   so the sixth wrapped alone onto a second row. Three across, twice, for a
	   six-step flow. Counted with :has() for the same reason as .sk-caps above. */
	.sk-flow:has(> :nth-child(6):last-child) {
		grid-template-columns: repeat(3, 1fr);
	}
}

.sk-flow__step {
	padding: 1rem;
	background: var(--bg-card);
	border: 1px solid var(--border-primary);
	border-radius: var(--radius-lg);
}

.sk-flow__step::before {
	counter-increment: flow;
	content: counter(flow, decimal-leading-zero);
	display: block;
	font-family: var(--font-label);
	font-size: 0.625rem;
	font-weight: 600;
	letter-spacing: 0.08em;
	color: var(--color-accent);
	margin-bottom: 0.5rem;
}

/* The steps Stockaroo owns end to end, marked in text as well as in colour. */
.sk-flow__step--ours {
	border-color: var(--color-primary);
	background: var(--color-success-bg);
}

.sk-flow__name {
	display: block;
	font-size: 0.9375rem;
	font-weight: 600;
	color: var(--text-primary);
	margin-bottom: 0.25rem;
}

.sk-flow__meta {
	display: block;
	font-size: 0.8125rem;
	line-height: 1.5;
	color: var(--text-secondary);
}

/* =============================================================================
   3d. CAPABILITY GRID
   -----------------------------------------------------------------------------
   Six cards, which docs/slop.md §4 warns about directly — so they earn it by
   carrying the APP'S OWN ICONS (views/mixins/icons.pug, the same marks in the
   product sidebar) and one concrete line each, rather than emoji and a slogan.
   If this ever drifts into six interchangeable platitudes, delete it.
   ========================================================================== */

.sk-caps {
	display: grid;
	gap: 1px;
	background: var(--border-primary);
	border: 1px solid var(--border-primary);
	border-radius: var(--radius-lg);
	overflow: hidden;
	grid-template-columns: 1fr;
}

@media (min-width: 40rem) {
	.sk-caps { grid-template-columns: repeat(2, 1fr); }
}

@media (min-width: 64rem) {
	.sk-caps { grid-template-columns: repeat(3, 1fr); }
}

/* A FOUR-item grid in a three-column track leaves the second row one card wide
   and two cells empty — and because the 1px "borders" here are the container's
   own background showing through the gap, those empty cells render as a solid
   grey block rather than as nothing. /platform, /about and the homepage
   security band all carry exactly four capabilities.

   Matched on the count with :has() rather than by a modifier class, so the
   layout stays right when someone adds or removes a capability without knowing
   this rule exists. Browsers without :has() simply keep the 3-column layout —
   the old imperfect result, never a broken one. */
@media (min-width: 64rem) {
	.sk-caps:has(> :nth-child(4):last-child) {
		grid-template-columns: repeat(4, 1fr);
	}
}

.sk-cap {
	background: var(--bg-card);
	padding: clamp(1.125rem, 2.5vw, 1.5rem);
}

.sk-cap__icon {
	width: 2.25rem;
	height: 2.25rem;
	border-radius: var(--radius-md);
	display: flex;
	align-items: center;
	justify-content: center;
	margin-bottom: 0.75rem;
	color: var(--color-accent);
	background: var(--color-success-bg);
}

.sk-cap__name {
	font-size: 0.9375rem;
	font-weight: 600;
	color: var(--text-primary);
	margin: 0 0 0.25rem;
}

.sk-cap__note {
	font-size: 0.8125rem;
	line-height: 1.55;
	color: var(--text-secondary);
	margin: 0;
}

/* =============================================================================
   4. PROSE COMPONENTS
   ========================================================================== */

.sk-split {
	display: grid;
	gap: clamp(1.75rem, 4vw, 3rem);
	/* start, not center. The two columns are rarely the same height — a readout
	   is short, a facts list is long — and centring the short one left a block
	   of empty page above it as tall as the difference. Aligning to the top
	   removes that gap without changing either column. */
	align-items: start;
}

@media (min-width: 62rem) {
	.sk-split {
		grid-template-columns: minmax(0, 5fr) minmax(0, 6fr);
	}

	/* Presentational only — source order stays logical, so the prose is still
	   read before its illustration by a screen reader and on mobile. */
	.sk-split--flip > :first-child {
		order: 2;
	}
}

/* ---- fact list -------------------------------------------------------------
   Replaces the icon + heading + two-lines card repeated six times. A
   description list is the honest markup: the term, then what it means. */

.sk-facts {
	margin: 0;
	border-top: 1px solid var(--border-primary);
}

.sk-facts > div {
	display: grid;
	gap: 0.25rem 1.5rem;
	padding: 1rem 0;
	border-bottom: 1px solid var(--border-primary);
}

@media (min-width: 48rem) {
	.sk-facts > div {
		grid-template-columns: minmax(0, 14rem) minmax(0, 1fr);
	}
}

/* Inside a split column the list has roughly half the page to work with, and
   the two-column form above squeezed the detail to about four words a line.
   The media query cannot see this because it measures the viewport, not the
   container — so it is overridden by context instead. Term above detail. */
.sk-split .sk-facts > div {
	grid-template-columns: minmax(0, 1fr);
	gap: 0.375rem;
}

.sk-facts dt {
	font-weight: 600;
	color: var(--text-primary);
	font-size: 0.9375rem;
}

.sk-facts dd {
	margin: 0;
	color: var(--text-secondary);
	font-size: 0.9375rem;
	line-height: 1.6;
}

/* A limit, stated rather than omitted — docs/slop.md §5: do not hide missing
   functionality behind attractive UI. */
.sk-limit {
	font-family: var(--font-label);
	font-size: 0.625rem;
	text-transform: uppercase;
	letter-spacing: 0.08em;
	color: var(--text-tertiary);
	border: 1px solid var(--border-primary);
	border-radius: var(--radius-sm);
	padding: 0.0625rem 0.375rem;
	margin-right: 0.5rem;
	white-space: nowrap;
}

/* ---- before / after --------------------------------------------------------- */

.sk-versus {
	display: grid;
	gap: 1px;
	background: var(--border-primary);
	border: 1px solid var(--border-primary);
	border-radius: var(--radius-lg);
	overflow: hidden;
}

@media (min-width: 48rem) {
	.sk-versus {
		grid-template-columns: 1fr 1fr;
	}
}

.sk-versus__col {
	background: var(--bg-card);
	padding: clamp(1.25rem, 3vw, 1.75rem);
}

.sk-versus__col--good {
	background: var(--bg-secondary);
}

.sk-versus__head {
	font-family: var(--font-label);
	font-size: 0.6875rem;
	text-transform: uppercase;
	letter-spacing: 0.12em;
	color: var(--text-tertiary);
	margin: 0 0 1rem;
}

.sk-versus__col--good .sk-versus__head {
	color: var(--color-accent);
}

.sk-versus__list {
	list-style: none;
	margin: 0;
	padding: 0;
	display: grid;
	gap: 0.625rem;
	font-size: 0.875rem;
	color: var(--text-secondary);
	line-height: 1.5;
}

.sk-versus__list li {
	display: flex;
	gap: 0.5rem;
	align-items: flex-start;
}

.sk-versus__list svg {
	flex: none;
	margin-top: 0.1875rem;
}

/* =============================================================================
   4b. CTA BAND
   -----------------------------------------------------------------------------
   Was a solid green block. It read as an advert dropped into the page rather
   than part of it — the only saturated fill on a site whose every other surface
   is paper or a one-step-darker paper, so it broke the flow instead of ending
   it. Rebuilt on the same surface as the rest of the page: the emphasis now
   comes from the measure rule, the type and one filled button, which is how
   every other section earns attention.

   Because it sits on the normal surface, the tokens behave normally too — no
   inverted ink, no contrast special-casing, and the three `color: inherit`
   traps this band hit while it was green are gone with it.
   ========================================================================== */

.sk-cta {
	border: 1px solid var(--border-primary);
	border-radius: var(--radius-lg);
	background: var(--bg-card);
	padding: clamp(1.5rem, 3.5vw, 2.5rem);
	position: relative;
	overflow: hidden;
}

/* The ruler motif along the top edge, in accent rather than ink, so the ask is
   visibly the same family of thing as a numbered section. */
.sk-cta::before {
	content: "";
	position: absolute;
	inset: 0 0 auto 0;
	height: 0.375rem;
	background-image: repeating-linear-gradient(
		to right,
		var(--color-primary) 0 1px,
		transparent 1px 12px
	);
	opacity: 0.5;
}

.sk-cta__label {
	font-family: var(--font-label);
	font-size: 0.6875rem;
	font-weight: 500;
	text-transform: uppercase;
	letter-spacing: 0.16em;
	color: var(--text-tertiary);
	margin: 0 0 0.75rem;
}

.sk-cta__title {
	font-family: var(--font-marketing);
	font-size: clamp(1.5rem, 3.4vw, 2.375rem);
	font-weight: 600;
	line-height: 1.12;
	letter-spacing: -0.02em;
	color: var(--text-primary);
	margin: 0 0 0.75rem;
	max-width: 24ch;
	text-wrap: balance;
}

/* The second clause, same treatment as .sk-title__turn so the two heading
   styles on the page are one style. */
.sk-cta__turn {
	color: var(--color-accent);
}

.sk-cta__lede {
	font-size: clamp(0.9375rem, 1.5vw, 1.0625rem);
	line-height: 1.6;
	color: var(--text-secondary);
	margin: 0 0 1.5rem;
	max-width: 52ch;
}

.sk-cta__actions {
	display: flex;
	flex-wrap: wrap;
	gap: 0.75rem;
	align-items: center;
}

/* The one filled control on the page outside the nav. --color-on-primary is
   the ink site.css pairs with a primary fill, and it flips with the theme. */
.sk-cta__go {
	display: inline-flex;
	align-items: center;
	gap: 0.5rem;
	padding: 0.8125rem 1.5rem;
	background: var(--color-primary);
	color: var(--color-on-primary);
	border-radius: var(--radius-md);
	font-weight: 600;
	font-size: 0.9375rem;
	text-decoration: none;
}

.sk-cta__alt {
	display: inline-flex;
	align-items: center;
	gap: 0.5rem;
	padding: 0.8125rem 1.25rem;
	color: var(--text-primary);
	border: 1px solid var(--border-secondary);
	border-radius: var(--radius-md);
	font-weight: 500;
	font-size: 0.9375rem;
	text-decoration: none;
}

.sk-cta a:focus-visible {
	outline: 2px solid var(--border-focus);
	outline-offset: 3px;
}

/* The reassurance row. Facts about what signing up does and does not cost —
   not a trial we do not offer. */
.sk-cta__terms {
	list-style: none;
	margin: 1.5rem 0 0;
	padding: 1rem 0 0;
	border-top: 1px solid var(--border-primary);
	display: flex;
	flex-wrap: wrap;
	gap: 0.5rem 1.75rem;
	font-size: 0.8125rem;
	color: var(--text-secondary);
}

.sk-cta__terms li {
	display: flex;
	align-items: flex-start;
	gap: 0.4375rem;
}

.sk-cta__terms svg {
	flex: none;
	margin-top: 0.1875rem;
	color: var(--color-accent);
}

/* =============================================================================
   5. MOTION
   -----------------------------------------------------------------------------
   One reveal, once per section, and nothing else. No hover-lift on cards, no
   transition-all. The reveal sequences a long page as it is read; under
   prefers-reduced-motion it is removed entirely rather than merely shortened.
   ========================================================================== */

@media (prefers-reduced-motion: no-preference) {
	.sk-enter {
		opacity: 0;
		translate: 0 0.75rem;
		animation: sk-enter 0.5s cubic-bezier(0.22, 1, 0.36, 1) forwards;
		animation-timeline: view();
		animation-range: entry 0% cover 18%;
	}

	/* Without scroll-driven animation support, show immediately rather than
	   leaving the content permanently invisible. This is the NO-JAVASCRIPT
	   floor; js/marketing-motion.js upgrades these browsers to a real reveal
	   below, and it only ever does so after it has run. Order matters: content
	   must never depend on a script to become visible. */
	@supports not (animation-timeline: view()) {
		.sk-enter {
			opacity: 1;
			translate: 0 0;
			animation: none;
		}

		/* The observer path. `.sk-obs` is set on <html> by marketing-motion.js
		   only when scroll-timeline is missing AND the script is running, so
		   these selectors cannot hide anything in a browser that never gets
		   told to reveal it. Higher specificity than the rule above, so it
		   wins without !important. */
		.sk-obs .sk-enter {
			opacity: 0;
			translate: 0 0.75rem;
			transition:
				opacity 0.55s cubic-bezier(0.22, 1, 0.36, 1),
				translate 0.55s cubic-bezier(0.22, 1, 0.36, 1);
		}

		.sk-obs .sk-enter.sk-in {
			opacity: 1;
			translate: 0 0;
		}
	}
}

/* `translate: 0 0`, never `translate: none`, throughout this file.
   -----------------------------------------------------------------------------
   These are the independent transform properties (Transforms Level 2), and
   WebKit blends them through the same TransformOperation machinery as the
   `transform` shorthand. `none` there is a null operation, and blending a real
   translation against null segfaults Safari 26.5's UI process:

     WebCore::blend(RefPtr<TransformOperation> const&, ...)
     WebCore::AcceleratedEffect::apply(...)
     WebKit::RemoteLayerTreeHost::updateLayerTree(...)   -> EXC_BAD_ACCESS

   This was iOS-only for a structural reason, not a coincidence: the whole
   observer path lives inside `@supports not (animation-timeline: view())`.
   Chromium has scroll-timeline and takes the other branch, so it never
   executes any of this. Safari has neither, so it runs all of it - and
   js/marketing-motion.js arms it by setting .sk-obs on <html>.

   `0 0` and `none` render identically. The one real difference is that a
   non-`none` value keeps the stacking context the reveal already created, so
   nothing here should gain or lose one mid-animation. Do not "tidy" these back
   to `none`. */
@keyframes sk-enter {
	to {
		opacity: 1;
		translate: 0 0;
	}
}

/* ---- stagger ---------------------------------------------------------------
   The grids are the page's densest moments — six tiers, eight steps, ten FAQ
   rows land at once otherwise. A per-child delay walks them in instead. Capped
   at eight children: past that the last card is waiting nearly half a second
   after the first and the effect reads as sluggish rather than sequenced.

   Applied to the CONTAINER's children, not to .sk-enter itself, so a section
   still reveals as one thing and only its contents sequence within it. */

@media (prefers-reduced-motion: no-preference) {
	.sk-tiers > *,
	.sk-steps > *,
	.sk-caps > *,
	.sk-guides > *,
	.sk-qlinks > *,
	.sk-contacts > *,
	.sk-flow > * {
		animation: sk-enter 0.45s cubic-bezier(0.22, 1, 0.36, 1) both;
		animation-timeline: view();
		animation-range: entry 0% cover 14%;
	}

	@supports not (animation-timeline: view()) {
		.sk-tiers > *,
		.sk-steps > *,
		.sk-caps > *,
		.sk-guides > *,
		.sk-qlinks > *,
		.sk-contacts > *,
		.sk-flow > * {
			animation: none;
		}

		.sk-obs .sk-tiers > *,
		.sk-obs .sk-steps > *,
		.sk-obs .sk-caps > *,
		.sk-obs .sk-guides > *,
		.sk-obs .sk-qlinks > *,
		.sk-obs .sk-contacts > *,
		.sk-obs .sk-flow > * {
			opacity: 0;
			translate: 0 0.625rem;
			transition:
				opacity 0.45s cubic-bezier(0.22, 1, 0.36, 1),
				translate 0.45s cubic-bezier(0.22, 1, 0.36, 1);
		}

		.sk-obs .sk-in > * {
			opacity: 1;
			translate: 0 0;
		}

		.sk-obs .sk-in > :nth-child(1) { transition-delay: 0ms; }
		.sk-obs .sk-in > :nth-child(2) { transition-delay: 55ms; }
		.sk-obs .sk-in > :nth-child(3) { transition-delay: 110ms; }
		.sk-obs .sk-in > :nth-child(4) { transition-delay: 165ms; }
		.sk-obs .sk-in > :nth-child(5) { transition-delay: 220ms; }
		.sk-obs .sk-in > :nth-child(6) { transition-delay: 275ms; }
		.sk-obs .sk-in > :nth-child(7) { transition-delay: 330ms; }
		.sk-obs .sk-in > :nth-child(n + 8) { transition-delay: 385ms; }
	}
}

/* ---- micro-interactions ----------------------------------------------------
   §5 above used to end "no hover-lift on cards, no transition-all", and that
   rule still holds for anything that is NOT interactive: a .sk-readout is a
   picture of the product, and a .sk-guide card has no article behind it yet.
   Neither moves under a cursor, because moving implies clicking.

   What follows is the opposite case — elements that genuinely are links,
   buttons or disclosures, where a hover state is feedback rather than
   decoration. Every one names a single property, never `all`. */

@media (prefers-reduced-motion: no-preference) {
	.sk-qlink,
	.sk-contact {
		translate: 0 0;
		transition:
			border-color 180ms ease,
			background-color 180ms ease,
			translate 180ms cubic-bezier(0.22, 1, 0.36, 1);
	}

	.sk-qlink:hover,
	.sk-contact:hover {
		border-color: var(--color-primary);
		background: var(--color-success-bg);
		translate: 0 -2px;
	}

	.sk-qlink__go svg {
		translate: 0 0;
		transition: translate 180ms cubic-bezier(0.22, 1, 0.36, 1);
	}

	.sk-qlink:hover .sk-qlink__go svg {
		translate: 3px 0;
	}

	/* The CTA's arrow, same idea — it is the page's one filled action. */
	.sk-cta__go svg {
		translate: 0 0;
		transition: translate 180ms cubic-bezier(0.22, 1, 0.36, 1);
	}

	.sk-cta__go:hover svg {
		translate: 3px 0;
	}

	.sk-cta__go,
	.sk-cta__alt {
		translate: 0 0;
		transition:
			background-color 180ms ease,
			border-color 180ms ease,
			translate 180ms cubic-bezier(0.22, 1, 0.36, 1);
	}

	.sk-cta__go:hover,
	.sk-cta__alt:hover {
		translate: 0 -2px;
	}

	.sk-cta__alt:hover {
		border-color: var(--color-primary);
	}

	/* The FAQ chevron turns to point at the open answer. */
	.sk-faq__chev {
		rotate: 0deg;
		transition: rotate 220ms cubic-bezier(0.22, 1, 0.36, 1);
	}

	.sk-faq__item[open] .sk-faq__chev {
		rotate: 180deg;
	}

	.sk-faq__q {
		transition: background-color 160ms ease;
	}

	.sk-faq__q:hover {
		background: var(--bg-secondary);
	}

	/* The answer unrolling. <details> does not animate its own open state, so
	   the inner block is what moves; the height snap still happens, but the
	   text no longer appears fully-formed in one frame. */
	.sk-faq__item[open] .sk-faq__a {
		animation: sk-enter 0.32s cubic-bezier(0.22, 1, 0.36, 1) both;
	}
}

/* A touch device has no hover to give feedback with, so it gets the press
   instead. Kept outside the motion query deliberately — this is a 1-frame
   state change, not an animation, and it is the only affordance a thumb has. */
@media (hover: none) {
	.sk-qlink:active,
	.sk-contact:active,
	.sk-cta__go:active,
	.sk-cta__alt:active {
		background: var(--color-success-bg);
	}
}

/* =============================================================================
   6. FOCUS
   -----------------------------------------------------------------------------
   site.css styles focus for app controls; these are the marketing-only
   interactive elements, given the same ring so the two surfaces agree.
   ========================================================================== */

.sk-band a:focus-visible,
.sk-band button:focus-visible {
	outline: 2px solid var(--border-focus);
	outline-offset: 3px;
	border-radius: var(--radius-sm);
}

/* =============================================================================
   7. ROADMAP PAGE COMPONENTS
   -----------------------------------------------------------------------------
   Added for the site-roadmap pages: /pricing, /how-it-works, /faq, /resources
   and /about. Everything here follows §2's rule — if the app already draws it,
   the page renders the app's component instead. These five exist because the
   product has no equivalent: it never prices itself, never lists its own
   marketplace guides, and has no FAQ screen.
   ========================================================================== */

/* ---- pricing tiers ---------------------------------------------------------
   Six tiers, flat, no "most popular" ribbon and no visual favouritism. There is
   nothing to upsell: a tenant's tier is DERIVED from assessed revenue and
   checkout is locked to it server-side, so a highlighted card would be inviting
   a choice the product does not offer. */

.sk-tiers {
	display: grid;
	gap: 1px;
	background: var(--border-primary);
	border: 1px solid var(--border-primary);
	border-radius: var(--radius-lg);
	overflow: hidden;
	grid-template-columns: 1fr;
}

@media (min-width: 40rem) {
	.sk-tiers { grid-template-columns: repeat(2, 1fr); }
}

@media (min-width: 64rem) {
	.sk-tiers { grid-template-columns: repeat(3, 1fr); }
}

.sk-tier {
	background: var(--bg-card);
	padding: clamp(1.125rem, 2.5vw, 1.5rem);
}

.sk-tier__name {
	font-size: 1.0625rem;
	font-weight: 600;
	color: var(--text-primary);
	margin: 0 0 0.25rem;
}

.sk-tier__band {
	font-family: var(--font-label);
	font-size: 0.6875rem;
	text-transform: uppercase;
	letter-spacing: 0.12em;
	color: var(--text-tertiary);
	margin: 0 0 0.875rem;
}

.sk-tier__price {
	display: flex;
	align-items: baseline;
	gap: 0.375rem;
	margin: 0 0 0.75rem;
	flex-wrap: wrap;
}

.sk-tier__amount {
	font-size: 1.75rem;
	font-weight: 600;
	letter-spacing: -0.02em;
	color: var(--text-primary);
	font-variant-numeric: tabular-nums;
}

.sk-tier__per {
	font-size: 0.8125rem;
	color: var(--text-secondary);
}

.sk-tier__all {
	font-size: 0.8125rem;
	color: var(--color-accent);
	margin: 0;
	padding-top: 0.75rem;
	border-top: 1px solid var(--border-primary);
}

/* ---- numbered steps --------------------------------------------------------
   /how-it-works runs eight steps, which is three too many for .sk-flow's
   five-across rail. Two columns of numbered rows instead: the number stays a
   real element rather than a ::before counter, because the roadmap numbers them
   01–08 explicitly and a reader should be able to select the text. */

.sk-steps {
	display: grid;
	gap: 1px;
	background: var(--border-primary);
	border: 1px solid var(--border-primary);
	border-radius: var(--radius-lg);
	overflow: hidden;
	grid-template-columns: 1fr;
}

@media (min-width: 48rem) {
	.sk-steps { grid-template-columns: repeat(2, 1fr); }
}

.sk-step {
	background: var(--bg-card);
	padding: clamp(1rem, 2.2vw, 1.375rem);
	display: grid;
	grid-template-columns: auto minmax(0, 1fr);
	gap: 0.875rem;
	align-items: start;
}

.sk-step__no {
	font-family: var(--font-label);
	font-size: 0.75rem;
	font-weight: 600;
	font-variant-numeric: tabular-nums;
	letter-spacing: 0.06em;
	color: var(--color-accent);
	padding-top: 0.1875rem;
}

.sk-step__name {
	font-size: 0.9375rem;
	font-weight: 600;
	color: var(--text-primary);
	margin: 0 0 0.25rem;
}

.sk-step__note {
	font-size: 0.8125rem;
	line-height: 1.55;
	color: var(--text-secondary);
	margin: 0;
}

/* ---- FAQ disclosure --------------------------------------------------------
   Native <details>/<summary>. No JS, keyboard accessible for free, and the
   answer text stays in the DOM so in-page find and search engines both see it.
   The mockup drew ten permanently-open cards; ten open answers is a wall. */

.sk-faq {
	border: 1px solid var(--border-primary);
	border-radius: var(--radius-lg);
	overflow: hidden;
	background: var(--bg-card);
}

.sk-faq__item + .sk-faq__item {
	border-top: 1px solid var(--border-primary);
}

.sk-faq__q {
	display: grid;
	grid-template-columns: minmax(0, 1fr) auto;
	align-items: center;
	gap: 0.75rem 1rem;
	padding: 1rem clamp(1rem, 2.5vw, 1.375rem);
	cursor: pointer;
	list-style: none;
	font-weight: 600;
	color: var(--text-primary);
}

/* Safari draws its own disclosure triangle unless this is removed. */
.sk-faq__q::-webkit-details-marker { display: none; }

@media (min-width: 48rem) {
	.sk-faq__q {
		grid-template-columns: 8rem minmax(0, 1fr) auto;
	}
}

.sk-faq__tag {
	font-family: var(--font-label);
	font-size: 0.625rem;
	font-weight: 600;
	text-transform: uppercase;
	letter-spacing: 0.12em;
	color: var(--color-accent);
	grid-column: 1 / -1;
}

@media (min-width: 48rem) {
	.sk-faq__tag { grid-column: auto; }
}

.sk-faq__text {
	font-size: 0.9375rem;
	line-height: 1.45;
}

.sk-faq__chev {
	color: var(--text-tertiary);
	flex: none;
}

.sk-faq__a {
	padding: 0 clamp(1rem, 2.5vw, 1.375rem) 1.125rem;
}

@media (min-width: 48rem) {
	.sk-faq__a { padding-left: calc(8rem + clamp(1rem, 2.5vw, 1.375rem) + 1rem); }
}

.sk-faq__a p {
	margin: 0;
	font-size: 0.9375rem;
	line-height: 1.65;
	color: var(--text-secondary);
	max-width: var(--sk-measure);
}

.sk-faq__q:focus-visible {
	outline: 2px solid var(--border-focus);
	outline-offset: -2px;
}

/* ---- resource cards --------------------------------------------------------
   NOT links. The guides in the roadmap have titles but no articles behind them
   yet, so each carries a `.sk-limit` "Planned" tag and no href. Give a card an
   <a> only when the guide it names actually exists. */

.sk-guides {
	display: grid;
	gap: 1px;
	background: var(--border-primary);
	border: 1px solid var(--border-primary);
	border-radius: var(--radius-lg);
	overflow: hidden;
	grid-template-columns: 1fr;
}

@media (min-width: 48rem) {
	.sk-guides { grid-template-columns: repeat(2, 1fr); }
}

.sk-guide {
	background: var(--bg-card);
	padding: clamp(1.125rem, 2.5vw, 1.5rem);
}

.sk-guide__top {
	display: flex;
	align-items: center;
	gap: 0.625rem;
	margin-bottom: 0.75rem;
	flex-wrap: wrap;
}

.sk-guide__kind {
	font-family: var(--font-label);
	font-size: 0.625rem;
	font-weight: 600;
	text-transform: uppercase;
	letter-spacing: 0.12em;
	color: var(--color-accent);
}

.sk-guide__title {
	font-size: 1rem;
	font-weight: 600;
	line-height: 1.35;
	color: var(--text-primary);
	margin: 0 0 0.375rem;
	text-wrap: balance;
}

.sk-guide__note {
	font-size: 0.8125rem;
	line-height: 1.55;
	color: var(--text-secondary);
	margin: 0;
}

/* ---- question links --------------------------------------------------------
   These ARE links — each goes to the page that answers it — so unlike the guide
   cards above they get a hover state. */

.sk-qlinks {
	display: grid;
	gap: 0.625rem;
	grid-template-columns: 1fr;
}

@media (min-width: 48rem) {
	.sk-qlinks { grid-template-columns: repeat(2, 1fr); }
}

.sk-qlink {
	display: flex;
	flex-direction: column;
	gap: 0.375rem;
	padding: 1rem 1.125rem;
	background: var(--bg-card);
	border: 1px solid var(--border-primary);
	border-radius: var(--radius-lg);
	text-decoration: none;
}

.sk-qlink__t {
	font-size: 0.9375rem;
	font-weight: 600;
	color: var(--text-primary);
}

.sk-qlink__go {
	display: inline-flex;
	align-items: center;
	gap: 0.375rem;
	font-size: 0.8125rem;
	color: var(--color-accent);
}

/* ---- contact cards --------------------------------------------------------- */

.sk-contacts {
	display: grid;
	gap: 0.625rem;
	grid-template-columns: 1fr;
}

@media (min-width: 48rem) {
	.sk-contacts { grid-template-columns: repeat(2, 1fr); }
}

.sk-contact {
	display: block;
	padding: clamp(1.125rem, 2.5vw, 1.5rem);
	background: var(--bg-card);
	border: 1px solid var(--border-primary);
	border-radius: var(--radius-lg);
	text-decoration: none;
}

.sk-contact__name {
	font-size: 0.9375rem;
	font-weight: 600;
	color: var(--text-primary);
	margin: 0 0 0.25rem;
}

.sk-contact__addr {
	display: block;
	font-size: 0.875rem;
	color: var(--color-accent);
	margin-bottom: 0.5rem;
	word-break: break-word;
}

.sk-contact__note {
	font-size: 0.8125rem;
	line-height: 1.55;
	color: var(--text-secondary);
	margin: 0;
}

/* ---- footer + inline links -------------------------------------------------
   `.sk-link-muted` and `.sk-fine-muted` were already in use in the footer of
   layouts/template-marketing.pug and in index.pug, but were defined in NO
   stylesheet — every footer link was rendering with the default anchor style
   instead of the muted one the markup asked for. Defined here, where the rest
   of the public surface lives.

   `.sk-link-accent` is new: the inline "read more" link, accent-coloured, for
   running text. --color-accent, never --color-primary — see the colour rule at
   the top of this file. */

/* ---- three-up comparison ---------------------------------------------------
   The homepage's "Without Stockaroo / With Stockaroo / The result" trio from
   01_homepage.png. Not .sk-versus: that is a two-column before/after with tick
   and cross lists, and this is three plain statements where the third is a
   conclusion rather than a side. The accent edge marks the two Stockaroo
   columns, and each is labelled in words too, so the distinction is not
   carried by colour alone. */

.sk-compare {
	display: grid;
	gap: 0.75rem;
	grid-template-columns: 1fr;
}

@media (min-width: 52rem) {
	.sk-compare {
		grid-template-columns: repeat(3, minmax(0, 1fr));
	}
}

.sk-compare__col {
	background: var(--bg-card);
	border: 1px solid var(--border-primary);
	border-left: 3px solid var(--color-warning);
	border-radius: var(--radius-lg);
	padding: clamp(1.125rem, 2.5vw, 1.5rem);
}

.sk-compare__col--good {
	border-left-color: var(--color-primary);
}

.sk-compare__head {
	font-size: 1rem;
	font-weight: 600;
	color: var(--text-primary);
	margin: 0 0 0.5rem;
}

.sk-compare__body {
	font-size: 0.875rem;
	line-height: 1.6;
	color: var(--text-secondary);
	margin: 0;
}

/* ---- footer grid -----------------------------------------------------------
   NOT Tailwind. frontend/css/tailwind.css is a PREBUILT file (see
   tailwind.src.css — `npm run build:css`), and it only contains the utilities
   that existed when it was last built: grid-cols-1..5 and md:grid-cols-2..5.
   There is no grid-cols-6. Writing `md:grid-cols-6` therefore produced a class
   that matched no rule at all, the grid silently fell back to the mobile
   `grid-cols-2`, and the footer rendered as two squashed columns on desktop.

   A footer with five tracks (brand + four link columns) cannot be expressed in
   the shipped utility set, so it gets a real rule here instead. This also means
   adding a sixth column later does not depend on remembering to re-run the
   Tailwind build. */

.sk-foot {
	display: grid;
	gap: 2.5rem;
	grid-template-columns: 1fr;
}

@media (min-width: 40rem) {
	.sk-foot {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}
}

@media (min-width: 64rem) {
	.sk-foot {
		/* Brand takes a double-width track; the four link columns take one each. */
		grid-template-columns: 2fr repeat(4, minmax(0, 1fr));
	}
}

/* Full width on small screens, its own track once there is room for one. */
.sk-foot__brand {
	grid-column: 1 / -1;
}

@media (min-width: 64rem) {
	.sk-foot__brand {
		grid-column: auto;
	}
}

.sk-foot__head {
	font-size: 11px;
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: 1px;
	color: var(--text-tertiary);
	margin: 0 0 16px;
}

.sk-foot__list {
	list-style: none;
	padding: 0;
	margin: 0;
	display: flex;
	flex-direction: column;
	gap: 12px;
}

.sk-link-muted {
	font-size: 14px;
	color: var(--text-secondary);
	text-decoration: none;
	transition: color 150ms ease;
}

.sk-link-muted:hover {
	color: var(--text-primary);
}

.sk-fine-muted {
	font-size: 13px;
	color: var(--text-tertiary);
	margin: 0;
}

.sk-link-accent {
	color: var(--color-accent);
	text-decoration: none;
	font-weight: 500;
	border-bottom: 1px solid transparent;
	transition: border-color 150ms ease;
}

.sk-link-accent:hover {
	border-bottom-color: currentColor;
}

.sk-link-muted:focus-visible,
.sk-link-accent:focus-visible {
	outline: 2px solid var(--border-focus);
	outline-offset: 3px;
	border-radius: var(--radius-sm);
}

/* =============================================================================
   PRE-LAUNCH — banner and waitlist
   -----------------------------------------------------------------------------
   Rendered only on the hosts in COMING_SOON_HOSTS, via views/mixins/prelaunch.pug.

   Lives here rather than in a sheet of its own because all three public layouts
   already load marketing.css — including index.pug, which extends no layout and
   would otherwise need its own <link>.

   Deliberately no transform animation. The reveal path in this file is the one
   place iOS Safari has crashed on a transform blended against `none`, and a
   launch banner is not worth re-entering that.
   ========================================================================== */

/* Fixed, not in normal flow, because two of the three public layouts pin their
   nav to the viewport: .public-nav (noauth.css) is `position: fixed` and
   index.pug's #navbar carries Tailwind's .fixed. An in-flow bar would simply be
   covered by both. So the bar is fixed above them, body gains matching padding,
   and the fixed navs start below it.

   --sk-prelaunch-h carries that height. The values below are a deliberate upper
   bound for the current copy (measured: 44px on desktop, 69px wrapped at 320px)
   and cover the case where the inline sync script in prelaunch.pug has not run.
   That script overwrites the variable with the height actually rendered, so the
   two cannot drift apart when the wording changes. */
:root {
	--sk-prelaunch-h: 44px;
}

@media (max-width: 640px) {
	:root {
		--sk-prelaunch-h: 72px;
	}
}

.sk-prelaunch {
	position: fixed;
	top: 0;
	left: 0;
	right: 0;
	/* Above .public-nav's z-index: 100 and index.pug's .z-50. */
	z-index: 200;
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: center;
	gap: 10px;
	padding: 10px 16px;
	background: var(--color-primary);
	color: #fff;
	font-size: 14px;
	line-height: 1.4;
	text-align: center;
}

.has-prelaunch {
	padding-top: var(--sk-prelaunch-h);
}

.has-prelaunch .public-nav,
.has-prelaunch #navbar.fixed {
	top: var(--sk-prelaunch-h);
}

.sk-prelaunch__dot {
	flex-shrink: 0;
	width: 8px;
	height: 8px;
	border-radius: 50%;
	background: #fff;
	opacity: 0.85;
}

.sk-prelaunch__text {
	font-weight: 500;
}

.sk-prelaunch__text--short {
	display: none;
}

@media (max-width: 640px) {
	.sk-prelaunch__text--long {
		display: none;
	}

	.sk-prelaunch__text--short {
		display: inline;
	}
}

.sk-prelaunch__link {
	color: #fff;
	font-weight: 600;
	text-decoration: underline;
	text-underline-offset: 3px;
}

.sk-prelaunch__link:focus-visible {
	outline: 2px solid #fff;
	outline-offset: 3px;
	border-radius: var(--radius-sm);
}

/* ---- waitlist ------------------------------------------------------------ */

.sk-waitlist {
	padding-block: var(--sk-band);
	background: var(--bg-secondary);
	border-top: 1px solid var(--border-primary);
}

.sk-waitlist__inner {
	max-width: 620px;
	margin: 0 auto;
	padding-inline: 24px;
	text-align: center;
}

.sk-waitlist__label {
	/* Accent TEXT, so --color-accent. See the colour rule at the top of this
	   file: --color-primary is a fill and misses AA as body text. */
	margin: 0 0 12px;
	color: var(--color-accent);
	font-size: 13px;
	font-weight: 600;
	letter-spacing: 0.08em;
	text-transform: uppercase;
}

.sk-waitlist__title {
	margin: 0 0 16px;
	color: var(--text-primary);
	font-size: clamp(1.75rem, 4vw, 2.5rem);
	font-weight: 700;
	line-height: 1.15;
}

.sk-waitlist__lede {
	margin: 0 0 28px;
	color: var(--text-secondary);
	font-size: 17px;
	line-height: 1.6;
}

.sk-waitlist__form {
	display: flex;
	flex-wrap: wrap;
	gap: 12px;
	justify-content: center;
}

.sk-waitlist__input {
	flex: 1 1 260px;
	min-width: 0;
	padding: 13px 16px;
	color: var(--text-primary);
	font-size: 15px;
	background: var(--bg-card);
	border: 1px solid var(--border-primary);
	border-radius: 10px;
}

.sk-waitlist__input:focus-visible {
	outline: 2px solid var(--border-focus);
	outline-offset: 1px;
}

.sk-waitlist__submit {
	flex: 0 0 auto;
	padding: 13px 28px;
	color: #fff;
	font-size: 15px;
	font-weight: 600;
	background: var(--color-primary);
	border: none;
	border-radius: 10px;
	cursor: pointer;
}

.sk-waitlist__submit:disabled {
	opacity: 0.6;
	cursor: default;
}

/* Off-screen rather than display:none. A form-filler skips what is not
   rendered, which is the whole mechanism the honeypot relies on. */
.sk-waitlist__hp {
	position: absolute;
	left: -9999px;
	width: 1px;
	height: 1px;
	overflow: hidden;
}

/* Reserves its line before there is a message, so a success or error does not
   shove the note below it down the page. */
.sk-waitlist__status {
	min-height: 1.4em;
	margin: 16px 0 0;
	font-size: 15px;
	font-weight: 500;
}

.sk-waitlist__status--ok {
	color: var(--color-accent);
}

.sk-waitlist__status--error {
	color: var(--color-error);
}

.sk-waitlist__note {
	margin: 20px 0 0;
	color: var(--text-tertiary);
	font-size: 13px;
	line-height: 1.6;
}

.sk-waitlist__note a {
	color: var(--color-accent);
	text-decoration: underline;
	text-underline-offset: 2px;
}
