/* Front page extras (extras.php): the hero canvas, the header search button, and the command palette. */

/* Hero canvas (assets/js/hero.js). The SVG keeps the box; the canvas lies over it once the script runs,
   and the SVG shows again under reduced motion, in print, and without JavaScript. */
.sf-hero-art { position: relative; }
/* The telemetry readout (lower left) is its own canvas on top, shown whenever the script runs; under
   reduced motion it stays, drawn once, over the SVG. */
.sf-hero-canvas, .sf-hero-tel {
	position: absolute;
	inset: 0;
	display: block;
	width: 100%;
	height: 100%;
}
.sf-hero-canvas[hidden], .sf-hero-tel[hidden] { display: none; }
.sf-hero-tel { pointer-events: none; }
.sf-hero-live > img { visibility: hidden; }
@media (prefers-reduced-motion: reduce) {
	.sf-hero-canvas { display: none !important; }
	.sf-hero-live > img { visibility: visible; }
}

/* Header button that opens the palette (printed hidden; palette.js shows it) */
.sf-pal-open {
	display: inline-flex;
	flex: none;
	align-items: center;
	gap: 10px;
	min-height: 44px; /* mobile pass: 44 px tap target */
	padding: 6px 8px 6px 12px;
	border: 1px solid var(--line-strong);
	border-radius: 8px;
	background: transparent;
	color: var(--muted);
	font: 500 14px/1.2 var(--font);
	cursor: pointer;
	transition: color 0.15s ease, border-color 0.15s ease;
}
.sf-pal-open:hover { color: var(--text); border-color: var(--accent); }
.sf-pal-open[hidden] { display: none; }
.sf-pal-icon {
	position: relative;
	flex: none;
	width: 15px;
	height: 15px;
}
.sf-pal-icon::before {
	content: "";
	position: absolute;
	left: 0;
	top: 0;
	width: 10px;
	height: 10px;
	border: 1.75px solid currentColor;
	border-radius: 50%;
}
.sf-pal-icon::after {
	content: "";
	position: absolute;
	left: 8.2px;
	top: 7.4px;
	width: 7px;
	height: 1.75px;
	border-radius: 1px;
	background: currentColor;
	transform: rotate(45deg);
	transform-origin: 0 50%;
}
.sf-pal-key {
	padding: 3px 7px;
	border: 1px solid var(--line-strong);
	border-radius: 4px;
	color: var(--muted);
	font: 600 12px/1 var(--font);
}
@media (hover: none) {
	.sf-pal-key { display: none; }
}
@media (min-width: 861px) {
	/* One row: the menu and the button sit together on the right. */
	.home .sf-nav { margin-left: auto; }
}
@media (min-width: 561px) and (max-width: 860px) {
	/* Too narrow for one row: the logo and the button share the first, the menu takes the second. */
	.home .sf-nav { order: 3; width: 100%; }
}
@media (max-width: 980px) {
	.sf-pal-open { padding: 0; width: 44px; justify-content: center; }
	.sf-pal-open-text, .sf-pal-open .sf-pal-key { display: none; }
}
@media (max-width: 560px) {
	/* The front page header is the menu only; the button keeps its place at the right of it. */
	.home .sf-nav { flex: 1 1 0; width: auto; min-width: 0; }
	.home .sf-pal-open { align-self: flex-start; }
}

/* The palette */
html.sf-pal-is-open { overflow: hidden; }
.sf-pal {
	position: fixed;
	inset: 0;
	z-index: 1000;
	width: 100%;
	height: 100%;
	max-width: none;
	max-height: none;
	margin: 0;
	padding: 12vh 16px 16px;
	border: 0;
	background: rgba(3, 5, 10, 0.74);
	color: var(--text);
	overflow: hidden;
}
.sf-pal[hidden] { display: none; }
.sf-pal::backdrop { background: transparent; }
.sf-pal-box {
	display: flex;
	flex-direction: column;
	max-width: 600px;
	max-height: 100%;
	margin: 0 auto;
	overflow: hidden;
	border: 1px solid var(--line-strong);
	border-radius: 14px;
	background: var(--surface);
	box-shadow: 0 24px 80px rgba(0, 0, 0, 0.6), 0 0 48px rgba(231, 185, 95, 0.08);
}
.sf-pal-head {
	display: flex;
	flex: none;
	align-items: center;
	gap: 12px;
	padding: 0 8px 0 18px;
	border-bottom: 1px solid var(--line);
}
.sf-pal-head:focus-within { box-shadow: inset 0 -2px 0 var(--accent); }
.sf-pal-head .sf-pal-icon { color: var(--accent); }
.sf-pal-input {
	flex: 1;
	min-width: 0;
	padding: 18px 0;
	border: 0;
	border-radius: 0;
	background: transparent;
	color: var(--text);
	font: 400 18px/1.3 var(--font);
	-webkit-appearance: none;
	appearance: none;
}
.sf-pal-input:focus,
.sf-pal-input:focus-visible { outline: none; }
.sf-pal-input::placeholder { color: var(--muted); opacity: 1; }
.sf-pal-close {
	display: grid;
	flex: none;
	place-items: center;
	width: 44px; /* mobile pass: 44 px tap target */
	height: 44px;
	padding: 0;
	border: 0;
	border-radius: 8px;
	background: transparent;
	color: var(--muted);
	cursor: pointer;
}
.sf-pal-close:hover { color: var(--text); background: var(--line); }
.sf-pal-list {
	flex: 1 1 auto;
	max-height: min(440px, 60vh);
	margin: 0;
	padding: 8px;
	overflow-y: auto;
	overscroll-behavior: contain;
	list-style: none;
}
.sf-pal-list[hidden], .sf-pal-item[hidden] { display: none; }
.sf-pal-item {
	display: flex;
	align-items: baseline;
	gap: 12px;
	padding: 10px 12px;
	border-radius: 8px;
	color: var(--text);
	cursor: pointer;
}
.sf-pal-item[aria-selected="true"] {
	background: var(--teal-dim);
	box-shadow: inset 2px 0 0 var(--teal);
}
.sf-pal-label { flex: none; font-weight: 560; }
.sf-pal-query {
	flex: 1;
	min-width: 0;
	overflow: hidden;
	color: var(--muted);
	text-overflow: ellipsis;
	white-space: nowrap;
	quotes: "\201C" "\201D";
}
.sf-pal-query::before { content: open-quote; }
.sf-pal-query::after { content: close-quote; }
.sf-pal-query[hidden] { display: none; }
/* Narrow screens: the visitor's words take their own line under the label and wrap there, instead of ending in an ellipsis */
@media (max-width: 480px) {
	.sf-pal-item { flex-wrap: wrap; row-gap: 2px; }
	.sf-pal-query { order: 3; flex-basis: 100%; overflow: visible; white-space: normal; overflow-wrap: break-word; }
}
.sf-pal-group {
	flex: none;
	margin-left: auto;
	color: var(--muted);
	font-size: 13px;
}
.sf-pal-empty { margin: 0; padding: 18px 20px; color: var(--muted); }
.sf-pal-empty:empty { display: none; }
.sf-pal-hint {
	flex: none;
	margin: 0;
	padding: 10px 18px;
	border-top: 1px solid var(--line);
	color: var(--muted);
	font-size: 13px;
}
@media (hover: none) {
	.sf-pal-hint { display: none; }
}
@media (max-width: 560px) {
	.sf-pal { padding: 12px 16px 16px; }
	.sf-pal-list { max-height: 55vh; }
	.sf-pal-head { padding-left: 14px; }
	.sf-pal-input { font-size: 17px; padding: 15px 0; }
}
@media (max-width: 360px) {
	.sf-pal-input { font-size: 16px; }
}
@media (prefers-reduced-motion: no-preference) {
	.sf-pal:not([hidden]) .sf-pal-box { animation: sf-pal-in 0.16s ease-out; }
	.sf-pal-found { animation: sf-pal-found 1.8s ease-out; }
}
@keyframes sf-pal-in {
	/* Movement only, no fade, so the box is never see-through if an animation stalls. */
	from { transform: translateY(-8px) scale(0.98); }
}
@keyframes sf-pal-found {
	0%, 35% { box-shadow: 0 0 0 2px var(--accent); }
	100% { box-shadow: 0 0 0 2px rgba(231, 185, 95, 0); }
}
@media print {
	.sf-hero-canvas, .sf-hero-tel, .sf-pal-open, .sf-pal { display: none !important; }
}

/* Stage D polish (assets/js/polish.js), all only when the visitor has not asked for reduced motion.
   Reveal: the script marks the root element only then, and only with IntersectionObserver, so without
   JavaScript, under reduced motion and in print every section and card is simply visible. The hidden state
   is opacity and a 12 px transform only: the element keeps its box, so nothing below it moves (no layout shift). */
@media screen and (prefers-reduced-motion: no-preference) {
	/* The transition sits on the shown state only, so hiding at load is instant and only the rise animates. */
	.sf-reveal-on .sf-reveal.sf-in {
		transition: opacity 0.3s ease-out, transform 0.3s ease-out;
		transition-delay: var(--sf-reveal-delay, 0ms);
	}
	.sf-reveal-on .sf-reveal:not(.sf-in) {
		opacity: 0;
		transform: translateY(12px);
	}
	/* Scroll progress: a 2 px gold line fixed at the top of the window, scaled by the script (transform only). */
	.sf-progress {
		position: fixed;
		top: 0;
		left: 0;
		z-index: 59; /* under the launcher (60) and the assistant panel (61), so it never crosses the panel's head (mobile pass) */
		width: 100%;
		height: 2px;
		background: var(--accent);
		box-shadow: 0 0 8px var(--accent-glow);
		transform: scaleX(0);
		transform-origin: 0 50%;
		pointer-events: none;
	}
}
.sf-progress[hidden] { display: none; }
@media print, (prefers-reduced-motion: reduce) {
	.sf-progress { display: none; }
	.sf-reveal { opacity: 1 !important; transform: none !important; }
}

/* Service icon for the Development Pipeline card (2026-11-03). Services is on the front page only, where
   this file loads after site.css, so the rule works here; it was added while site.css was being edited by
   another stage and can join the other .sf-svc-* rules there later. Size and spacing: .sf-svc::before. */
.sf-svc-pipeline::before { background-image: url("../img/icon-pipeline.svg"); }

/* Case studies fold (assets/js/cases.js, jamie 2026-11-03, "Since the cards are so big maybe make them
   collapsible", and every width since the same day). The script adds these classes; without them every card shows in full. The chevron
   turn and the fade run only under no-preference. The button stays inside the h3; its ::after covers the top of the card, from the card's top edge (22 px
   padding, the 44 px icon and its 14 px margin above the label: .sf-case in site.css at 720 px) to the body, or to the
   card's bottom edge when closed, so the icon, the label and the title are one tap target. The chevron sits at the
   right of the label's row, which is short, so it takes no width from the title and no title wraps for it. */
.sf-case-head {
	position: relative;
	display: flex;
	flex-direction: column;
	align-items: flex-start;
}
.sf-case-head h3 { align-self: stretch; }
/* A grid, as the card is, so the paragraphs' margins add up as before instead of collapsing. */
.sf-case-body:not([hidden]) { display: grid; grid-template-columns: minmax(0, 1fr); }
@media screen {
	.sf-case-fold:not(.sf-case-open) .sf-case-head h3 { margin-bottom: 0; }
}
.sf-case-toggle {
	display: block;
	width: 100%;
	margin: -11px 0;
	padding: 11px 0; /* at least 44 px tall for a one-line title, with no change to the layout */
	border: 0;
	background: none;
	color: inherit;
	font: inherit;
	letter-spacing: inherit;
	text-align: left;
	cursor: pointer;
}
/* The chevron: down when closed, up when open, at the right of the label's row (.sf-case-head is its box). */
.sf-case-toggle::before {
	content: "";
	position: absolute;
	top: 6px;
	right: 4px;
	width: 9px;
	height: 9px;
	border-right: 2px solid var(--accent);
	border-bottom: 2px solid var(--accent);
	transform: rotate(45deg);
}
.sf-case-open .sf-case-toggle::before { transform: translateY(4px) rotate(-135deg); }
.sf-case-toggle::after {
	content: "";
	position: absolute;
	top: -80px;
	right: -20px;
	bottom: -20px;
	left: -20px;
	border-radius: 10px;
}
.sf-case-open .sf-case-toggle::after { bottom: 0; border-radius: 10px 10px 0 0; }
.sf-case-toggle:focus-visible { outline: none; }
.sf-case-toggle:focus-visible::after { outline: 2px solid var(--accent); outline-offset: -2px; }
@media (hover: hover) {
	.sf-case-toggle:hover::before { border-color: var(--accent-hover); }
}
@media (prefers-reduced-motion: no-preference) {
	.sf-case-toggle::before { transition: transform 200ms ease; }
	.sf-case-open .sf-case-body { animation: sf-case-in 200ms ease-out; }
}
@keyframes sf-case-in {
	from { opacity: 0; transform: translateY(-6px); }
}
@media print {
	.sf-case-body[hidden] { display: grid !important; grid-template-columns: minmax(0, 1fr); content-visibility: visible; }
	.sf-case-toggle::before, .sf-case-toggle::after { display: none; }
}

/* Section jump buttons (jump.js, jamie 2026-11-03): a stack of three 44 px round buttons above the Ask launcher,
   top, previous, next, at every width. Printed hidden; the script shows it once the hero has scrolled past, and
   steps it aside (sf-jump-tucked) while a control of the page lies under it. */
.sf-jump {
	position: fixed;
	right: max(20px, env(safe-area-inset-right));
	bottom: calc(max(20px, env(safe-area-inset-bottom)) + 64px + 14px);
	z-index: 59;
	display: flex;
	flex-direction: column;
	gap: 8px;
	margin: 0;
	padding: 0;
}
.sf-jump[hidden] { display: none !important; }
.sf-jump-btn {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 44px;
	height: 44px;
	padding: 0;
	border: 1px solid var(--accent);
	border-radius: 50%;
	background: var(--surface);
	color: var(--accent);
	box-shadow: 0 4px 16px rgba(0, 0, 0, 0.4);
	cursor: pointer;
}
.sf-jump-btn:hover { border-color: var(--accent-hover); color: var(--accent-hover); }
.sf-jump-btn:focus-visible { outline: 2px solid var(--text); outline-offset: 3px; }
.sf-jump.sf-jump-tucked {
	opacity: 0;
	visibility: hidden;
	transform: translateY(12px);
	pointer-events: none;
}
@media (max-width: 560px) {
	.sf-jump { bottom: calc(max(20px, env(safe-area-inset-bottom)) + 58px + 14px); }
}
@media (prefers-reduced-motion: no-preference) {
	.sf-jump { transition: transform 0.2s ease, opacity 0.2s ease, visibility 0.2s; }
}
@media print {
	.sf-jump { display: none !important; }
}
