/* The Frequency — layout, arrival, HUD + reveal typography (v2).
 *
 * Rendering philosophy (v2): the JS paints a TINY sky buffer and this file
 * stretches it (free bilinear blur on the compositor). Grain and breathing
 * are pure CSS — a tiled noise image with stepped transforms and an opacity
 * keyframe. No blur filters, no per-frame JS for either.
 */

:root {
	--tfq-base: hsl(228, 40%, 7%);
	--tfq-text: hsla(228, 28%, 95%, 1);
	--tfq-muted: hsla(228, 24%, 92%, 0.55);
	--tfq-serif: "Fraunces", Georgia, "Times New Roman", serif;
	--tfq-micro: ui-monospace, "SF Mono", SFMono-Regular, Menlo, Consolas, monospace;
}

/* ---------- the room ---------- */

.tfq-mount {
	position: relative;
	width: 100%;
	height: 100svh;
	overflow: hidden;
	isolation: isolate;
	background-color: var(--tfq-base);
	color: var(--tfq-text);
	cursor: default;
	touch-action: manipulation;
	-webkit-user-select: none;
	user-select: none;
}

/* The sky: a ~176 px buffer stretched to the viewport. The upscale IS the
 * softness — no filters anywhere. */
.tfq-sky {
	position: absolute;
	inset: 0;
	z-index: 0;
	width: 100%;
	height: 100%;
	display: block;
	image-rendering: auto; /* bilinear upscale: free blur */
}

/* ---------- breathing (pure CSS; JS sets only the outer opacity) ---------- */

.tfq-breath {
	position: absolute;
	inset: 0;
	z-index: 1;
	pointer-events: none;
	opacity: 0.05; /* ← telemetry writes this single value */
	transition: opacity 5s ease;
}

.tfq-breath-inner {
	position: absolute;
	inset: 0;
	background: radial-gradient(ellipse 80% 60% at 50% 45%, rgba(255, 245, 230, 0.9), transparent 70%);
	animation: tfq-breathe 14s ease-in-out infinite alternate;
}

@keyframes tfq-breathe {
	from { opacity: 0.15; }
	to   { opacity: 1; }
}

/* ---------- grain (pure CSS; one pre-rendered tile, stepped jumps) ---------- */

/* NO mix-blend-mode here: the tile carries alpha speckles and composites
 * normally. (blend modes force an offscreen surface + full-stack re-blend on
 * every composite — that was real money on retina Intel iGPUs.)
 * The layer only overhangs bottom/right (96 px) because the jump offsets are
 * negative-only — minimal overdraw. */
.tfq-grain {
	position: absolute;
	inset: 0 -96px -96px 0;
	z-index: 2;
	pointer-events: none;
	background-repeat: repeat;
	opacity: 0.07; /* ← telemetry writes this single value */
	transition: opacity 5s ease;
	animation: tfq-grain-jump 0.9s infinite;
	will-change: transform;
}

@keyframes tfq-grain-jump {
	0%     { transform: translate3d(0, 0, 0);         animation-timing-function: step-end; }
	12.5%  { transform: translate3d(-32px, -64px, 0); animation-timing-function: step-end; }
	25%    { transform: translate3d(-96px, -32px, 0); animation-timing-function: step-end; }
	37.5%  { transform: translate3d(-64px, -96px, 0); animation-timing-function: step-end; }
	50%    { transform: translate3d(-16px, -48px, 0); animation-timing-function: step-end; }
	62.5%  { transform: translate3d(-80px, -80px, 0); animation-timing-function: step-end; }
	75%    { transform: translate3d(-48px, -16px, 0); animation-timing-function: step-end; }
	87.5%  { transform: translate3d(-96px, -64px, 0); animation-timing-function: step-end; }
	100%   { transform: translate3d(0, 0, 0); }
}

/* ---------- static mode (.is-still — the "living sky" switch is off) ----------
 * No animation classes anywhere near full-screen layers: paused/removed
 * animations + no will-change means the compositor retains nothing and the
 * page costs what a static image costs. */

.tfq-mount.is-still .tfq-grain {
	animation: none;
	will-change: auto;
}

.tfq-mount.is-still .tfq-breath-inner {
	animation: none;
	opacity: 0.55; /* the mid-point of the breath — a fixed, painted glow */
}

/* ---------- fx + stars canvases ---------- */

.tfq-fx {
	position: absolute;
	inset: 0;
	z-index: 3;
	width: 100%;
	height: 100%;
	display: block;
	pointer-events: none;
}

.tfq-stars {
	position: absolute;
	inset: 0;
	z-index: 4;
	width: 100%;
	height: 100%;
	display: block;
	opacity: 0;
	transition: opacity 2.5s ease;
	pointer-events: none;
}

.tfq-noscript {
	position: absolute;
	inset: 0;
	display: grid;
	place-items: center;
	padding: 2rem;
	text-align: center;
	color: var(--tfq-muted);
}

/* ---------- the arrival (tune-in sequence) ---------- */

.tfq-arrival {
	position: absolute;
	inset: 0;
	z-index: 9;
	display: grid;
	place-items: center;
	background: #05060a;
	opacity: 0;
	visibility: hidden;
	pointer-events: none;
	transition: opacity 1.6s ease, visibility 0s linear 1.6s;
}

.tfq-static {
	position: absolute;
	inset: 0 -96px -96px 0;
	background-repeat: repeat;
	opacity: 0.4; /* the tile is alpha-speckled now, so this reads like 0.16 did */
	animation: tfq-grain-jump 0.35s infinite, tfq-static-flicker 2s ease-in-out infinite;
	transition: opacity 1.4s ease;
}

@keyframes tfq-static-flicker {
	0%, 100% { opacity: 0.4; }
	42%      { opacity: 0.24; }
	43%      { opacity: 0.52; }
	70%      { opacity: 0.32; }
}

.tfq-tuning-label {
	position: relative;
	margin: 0;
	font-family: var(--tfq-micro);
	font-size: 0.72rem;
	letter-spacing: 0.32em;
	text-transform: lowercase;
	color: rgba(244, 241, 234, 0.65);
	opacity: 0;
	animation: tfq-label-in 1.4s ease 0.5s forwards;
}

@keyframes tfq-label-in {
	to { opacity: 1; }
}

/* Sequence states. While tuning: overlay on, sky and UI hidden. */
.tfq-mount.is-tuning .tfq-arrival,
.tfq-mount.is-resolving .tfq-arrival {
	opacity: 1;
	visibility: visible;
	transition: none;
}

.tfq-mount.is-tuning .tfq-sky,
.tfq-mount.is-tuning .tfq-fx,
.tfq-mount.is-tuning .tfq-breath {
	opacity: 0;
}

/* Resolving: the sky fades up through the thinning static. */
.tfq-mount.is-resolving .tfq-arrival {
	background: transparent;
}

.tfq-mount.is-resolving .tfq-sky {
	opacity: 1;
	transition: opacity 2.2s ease;
}

.tfq-mount.is-resolving .tfq-static {
	opacity: 0;
}

.tfq-mount.is-resolving .tfq-tuning-label {
	animation: none;
	opacity: 0;
	transition: opacity 1.2s ease 0.6s;
}

/* UI stays hidden until arrival completes, then fades up. */
.tfq-ui {
	opacity: 0;
	pointer-events: none;
	transition: opacity 1.4s ease 0.2s;
}

.tfq-mount.is-arrived .tfq-ui {
	opacity: 1;
	pointer-events: auto;
}

.tfq-mount.is-arrived .tfq-arrival {
	opacity: 0;
	visibility: hidden;
}

/* No-JS-sequence path (reduced motion): mount never gets is-tuning, and
 * is-arrived is applied immediately — everything above resolves to visible. */

/* ---------- the event line (word reveal, universe-fact DNA) ---------- */

.tfq-line-wrap {
	position: absolute;
	z-index: 5;
	left: 50%;
	top: 47%;
	transform: translate(-50%, -50%);
	width: min(44rem, calc(100% - 3rem));
	text-align: center;
}

.tfq-line {
	margin: 0;
	font-family: var(--tfq-serif);
	font-size: clamp(1.3rem, 1rem + 2.1vw, 2.2rem);
	line-height: 1.42;
	font-weight: 300;
	letter-spacing: 0.01em;
	color: var(--tfq-text);
	text-wrap: balance;
}

.tfq-line.is-settled {
	text-shadow: 0 1px 40px rgba(0, 0, 0, 0.45);
}

.tfq-word {
	display: inline-block;
	white-space: pre;
	opacity: 0;
	transform: translate3d(0, 0.45em, 0);
	filter: blur(9px);
	will-change: opacity, filter, transform;
}

.tfq-line.is-in .tfq-word {
	opacity: 1;
	transform: none;
	filter: blur(0);
	transition:
		opacity 0.9s cubic-bezier(0.22, 1, 0.36, 1),
		transform 1.05s cubic-bezier(0.22, 1, 0.36, 1),
		filter 0.9s cubic-bezier(0.22, 1, 0.36, 1);
	transition-delay: var(--tfq-delay, 0ms);
}

.tfq-line.is-settled .tfq-word {
	filter: none;
	transition: none;
	will-change: auto;
}

/* Poetry + proof: the factual sub-line. */
.tfq-line-data {
	margin: 0.9rem 0 0;
	font-family: var(--tfq-micro);
	font-size: 0.72rem;
	letter-spacing: 0.16em;
	color: var(--tfq-muted);
	opacity: 0;
	transition: opacity 1s ease 0.9s;
}

.tfq-line-data.is-in {
	opacity: 1;
}

/* ---------- explain ---------- */

.tfq-explain {
	margin-top: 1rem;
	appearance: none;
	background: none;
	border: 0;
	padding: 0.2rem 0.4rem;
	font-family: var(--tfq-micro);
	font-size: 0.72rem;
	letter-spacing: 0.14em;
	color: var(--tfq-muted);
	cursor: pointer;
	border-bottom: 1px solid transparent;
	transition: color 0.3s ease;
}

.tfq-explain:hover,
.tfq-explain:focus-visible {
	color: var(--tfq-text);
}

.tfq-explain[hidden] { display: none; }

.tfq-explanation {
	max-height: 0;
	opacity: 0;
	overflow: hidden;
	margin: 0 auto;
	max-width: 36rem;
	font-family: var(--tfq-serif);
	font-size: 0.98rem;
	line-height: 1.65;
	color: var(--tfq-muted);
	transform: translate3d(0, -8px, 0);
	transition:
		max-height 0.6s cubic-bezier(0.22, 1, 0.36, 1),
		opacity 0.45s ease,
		transform 0.6s cubic-bezier(0.22, 1, 0.36, 1);
}

.tfq-line-wrap.is-explained .tfq-explanation {
	max-height: 40vh;
	opacity: 1;
	transform: none;
	margin-top: 0.9rem;
	transition-delay: 0s, 0.12s, 0.12s;
}

/* ---------- quake ticker ---------- */

.tfq-ticker {
	position: absolute;
	z-index: 5;
	left: 50%;
	bottom: 5.4rem;
	transform: translateX(-50%);
	margin: 0;
	max-width: calc(100% - 2rem);
	font-family: var(--tfq-micro);
	font-size: 0.68rem;
	letter-spacing: 0.14em;
	color: var(--tfq-muted);
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
	opacity: 0;
	transition: opacity 0.6s ease;
	pointer-events: none;
}

.tfq-mount.is-arrived .tfq-ticker.is-in {
	opacity: 0.75;
}

/* ---------- live readout HUD ---------- */

.tfq-hud {
	position: absolute;
	z-index: 5;
	left: 50%;
	bottom: 1.4rem;
	transform: translateX(-50%);
	text-align: center;
	max-width: calc(100% - 1.6rem);
}

.tfq-readout {
	margin: 0;
	font-family: var(--tfq-micro);
	font-size: 0.72rem;
	letter-spacing: 0.12em;
	color: var(--tfq-muted);
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
}

.tfq-readout .tfq-sep {
	margin: 0 0.45em;
	opacity: 0.5;
}

.tfq-live {
	color: var(--tfq-text);
	letter-spacing: 0.2em;
}

.tfq-live-dot {
	display: inline-block;
	width: 6px;
	height: 6px;
	margin-right: 0.5em;
	border-radius: 50%;
	background: #ff6b57;
	vertical-align: 1px;
	animation: tfq-live-pulse 2.4s ease-in-out infinite;
}

.tfq-live-dot.is-fallback {
	background: #c9a15a;
	animation: none;
	opacity: 0.7;
}

@keyframes tfq-live-pulse {
	0%, 100% { opacity: 1; }
	50%      { opacity: 0.25; }
}

/* A number that just changed ticks visibly. */
.tfq-readout [data-hud].is-ticking {
	color: var(--tfq-text);
	transition: color 0.3s ease;
}

.tfq-hud-sub {
	display: flex;
	align-items: center;
	justify-content: center;
	flex-wrap: wrap;
	gap: 0.8rem;
	margin: 0.55rem 0 0;
}

/* The "living sky" switch — state always visible next to the readout. */
.tfq-motion {
	appearance: none;
	background: none;
	border: 1px solid color-mix(in srgb, var(--tfq-muted) 30%, transparent);
	border-radius: 2rem;
	padding: 0.32rem 0.95rem;
	font-family: var(--tfq-micro);
	font-size: 0.68rem;
	letter-spacing: 0.16em;
	color: var(--tfq-muted);
	cursor: pointer;
	transition: border-color 0.3s ease, background-color 0.3s ease, color 0.3s ease;
}

.tfq-motion:hover,
.tfq-motion:focus-visible {
	border-color: var(--tfq-muted);
	color: var(--tfq-text);
}

.tfq-motion.is-on {
	color: var(--tfq-text);
	border-color: color-mix(in srgb, var(--tfq-text) 55%, transparent);
	background: rgba(255, 255, 255, 0.08);
}

.tfq-motion[hidden] { display: none; }

.tfq-credit {
	font-family: var(--tfq-micro);
	font-size: 0.58rem;
	letter-spacing: 0.2em;
	text-transform: uppercase;
	color: var(--tfq-muted);
	opacity: 0.55;
}

/* ---------- sound as an invitation ---------- */

.tfq-sound {
	appearance: none;
	background: none;
	border: 1px solid color-mix(in srgb, var(--tfq-muted) 40%, transparent);
	border-radius: 2rem;
	padding: 0.32rem 0.95rem;
	font-family: var(--tfq-micro);
	font-size: 0.68rem;
	letter-spacing: 0.16em;
	color: var(--tfq-text);
	cursor: pointer;
	transition: border-color 0.3s ease, background-color 0.3s ease, color 0.3s ease;
}

.tfq-sound:hover,
.tfq-sound:focus-visible {
	border-color: var(--tfq-muted);
	background: rgba(255, 255, 255, 0.05);
}

.tfq-sound.is-on {
	border-color: color-mix(in srgb, var(--tfq-text) 55%, transparent);
	background: rgba(255, 255, 255, 0.08);
}

/* Volume: three bars, click cycles low → med → high. */
.tfq-vol {
	appearance: none;
	background: none;
	border: 0;
	padding: 0.3rem 0.2rem;
	display: inline-flex;
	align-items: flex-end;
	gap: 2px;
	cursor: pointer;
	vertical-align: middle;
}

.tfq-vol[hidden] { display: none; }

.tfq-vol span {
	width: 3px;
	border-radius: 1px;
	background: var(--tfq-muted);
	opacity: 0.35;
	transition: opacity 0.25s ease, background-color 0.25s ease;
}

.tfq-vol span:nth-child(1) { height: 5px; }
.tfq-vol span:nth-child(2) { height: 8px; }
.tfq-vol span:nth-child(3) { height: 11px; }

.tfq-vol[data-level="low"] span:nth-child(1),
.tfq-vol[data-level="med"] span:nth-child(-n+2),
.tfq-vol[data-level="high"] span {
	opacity: 1;
	background: var(--tfq-text);
}

.tfq-vol:hover span { opacity: 0.7; }

.tfq-vol[data-level="low"]:hover span:nth-child(1),
.tfq-vol[data-level="med"]:hover span:nth-child(-n+2),
.tfq-vol[data-level="high"]:hover span { opacity: 1; }

/* Turning sound on is a moment: the whole sky lifts for a breath. */
.tfq-mount.is-sound-on .tfq-breath {
	opacity: 0.12 !important;
	transition: opacity 2.2s ease;
}

/* ---------- first-visit micro-intro ---------- */

.tfq-intro {
	position: absolute;
	z-index: 8;
	left: 50%;
	bottom: 8.5rem;
	transform: translateX(-50%);
	max-width: min(30rem, calc(100% - 3rem));
	text-align: center;
	opacity: 0;
	transition: opacity 0.9s ease;
	pointer-events: none;
}

.tfq-intro.is-in { opacity: 1; }

.tfq-intro p {
	margin: 0;
	font-family: var(--tfq-serif);
	font-style: italic;
	font-size: 0.95rem;
	line-height: 1.6;
	color: var(--tfq-muted);
}

/* ---------- layers panel ---------- */

.tfq-panel {
	position: absolute;
	z-index: 6;
	right: 1.2rem;
	bottom: 1.2rem;
	display: flex;
	flex-direction: column;
	align-items: flex-end;
	gap: 0.6rem;
}

.tfq-panel-toggle {
	appearance: none;
	width: 2.4rem;
	height: 2.4rem;
	border-radius: 50%;
	border: 1px solid color-mix(in srgb, var(--tfq-muted) 45%, transparent);
	background: rgba(0, 0, 0, 0.18);
	color: var(--tfq-muted);
	font-size: 0.9rem;
	line-height: 1;
	cursor: pointer;
	transition: color 0.3s ease, border-color 0.3s ease;
}

.tfq-panel-toggle:hover,
.tfq-panel-toggle[aria-expanded="true"] {
	color: var(--tfq-text);
	border-color: var(--tfq-muted);
}

.tfq-panel-body {
	display: flex;
	flex-direction: column;
	gap: 0.55rem;
	padding: 0.9rem 1rem;
	border-radius: 0.75rem;
	background: rgba(0, 0, 0, 0.35);
	border: 1px solid color-mix(in srgb, var(--tfq-muted) 30%, transparent);
}

.tfq-panel-body[hidden] { display: none; }

.tfq-layer {
	display: flex;
	align-items: center;
	gap: 0.55rem;
	font-family: var(--tfq-micro);
	font-size: 0.72rem;
	letter-spacing: 0.08em;
	color: var(--tfq-muted);
	cursor: pointer;
	transition: color 0.25s ease;
}

.tfq-layer:hover { color: var(--tfq-text); }

.tfq-layer input {
	appearance: none;
	width: 0.85rem;
	height: 0.85rem;
	margin: 0;
	border-radius: 50%;
	border: 1px solid var(--tfq-muted);
	cursor: pointer;
	transition: background-color 0.25s ease, box-shadow 0.25s ease;
}

.tfq-layer input:checked {
	background: var(--tfq-text);
	box-shadow: 0 0 8px color-mix(in srgb, var(--tfq-text) 60%, transparent);
}

.tfq-orbit-btn {
	appearance: none;
	background: none;
	border: 0;
	padding: 0.15rem 0;
	margin-top: 0.2rem;
	font-family: var(--tfq-micro);
	font-size: 0.68rem;
	letter-spacing: 0.1em;
	color: var(--tfq-muted);
	cursor: pointer;
	text-align: left;
	border-bottom: 1px dotted color-mix(in srgb, var(--tfq-muted) 60%, transparent);
	transition: color 0.25s ease;
}

.tfq-orbit-btn:hover { color: var(--tfq-text); }

/* ---------- your orbit ---------- */

.tfq-orbit {
	position: absolute;
	inset: 0;
	z-index: 7;
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	gap: 1rem;
	background: rgba(0, 0, 0, 0.6);
}

.tfq-orbit[hidden] { display: none; }

.tfq-orbit-canvas {
	width: min(40rem, calc(100% - 3rem));
	height: min(22rem, 50vh);
}

.tfq-orbit-caption {
	margin: 0;
	font-family: var(--tfq-micro);
	font-size: 0.75rem;
	letter-spacing: 0.08em;
	color: var(--tfq-muted);
	text-align: center;
	max-width: 30rem;
}

.tfq-orbit-close {
	appearance: none;
	background: none;
	border: 0;
	font-family: var(--tfq-micro);
	font-size: 0.68rem;
	letter-spacing: 0.16em;
	text-transform: lowercase;
	color: var(--tfq-muted);
	cursor: pointer;
	padding: 0.4rem 0.8rem;
	transition: color 0.25s ease;
}

.tfq-orbit-close:hover { color: var(--tfq-text); }

/* ---------- reduced motion ---------- */

@media (prefers-reduced-motion: reduce) {
	.tfq-word {
		opacity: 1;
		transform: none;
		filter: none;
		transition: none;
	}

	.tfq-line.is-in .tfq-word { transition: none; }

	.tfq-grain,
	.tfq-static {
		animation: none;
	}

	.tfq-breath-inner {
		animation: none;
		opacity: 0.5;
	}

	.tfq-live-dot { animation: none; }

	.tfq-explanation,
	.tfq-stars,
	.tfq-ui {
		transition: none;
	}

	.tfq-arrival { display: none; }
}

/* ---------- small screens ---------- */

@media (max-width: 640px) {
	.tfq-line-wrap { width: calc(100% - 2rem); }
	.tfq-panel { right: 0.9rem; bottom: 5.6rem; }
	.tfq-ticker { bottom: 6.6rem; }
	.tfq-hud { bottom: 1rem; width: calc(100% - 1.2rem); }
	.tfq-readout { font-size: 0.62rem; }
	.tfq-intro { bottom: 10rem; }
}
