/* ==================================================================
   FAYAWO — flourish layer

   The richer, more atmospheric pass. Everything here is grounded in two
   materials from the subject's world: the printed document (grain, rules
   that draw themselves, figures that resolve) and the engineering drawing
   (blueprint grid, the wheel from the wordmark as a technical motif).

   Nothing here is load-bearing. Under prefers-reduced-motion, or with JS
   off, the page falls back to the plain composition underneath.
   ================================================================== */

/* ---------- paper grain ----------
   A fine noise wash over the dark sections. It stops large flat fields of
   ink from looking like plastic, and reads as printed stock rather than
   screen. Very low opacity — you should feel it, not see it. */
.fy-hero, .fy-section--ink, .fy-footer, .fy-cta { position: relative; }
.fy-hero > *, .fy-section--ink > *, .fy-footer > *, .fy-cta > * { position: relative; z-index: 2; }

.fy-grain::before {
	content: ""; position: absolute; inset: 0; z-index: 1; pointer-events: none;
	opacity: .16; mix-blend-mode: overlay;
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)' opacity='.55'/%3E%3C/svg%3E");
}

/* ---------- blueprint grid ----------
   Dark sections carry a faint technical grid, lit by a soft spotlight that
   follows the pointer. It suggests a drawing board without ever competing
   with the type. Desktop pointers only. */
.fy-blueprint::after {
	content: ""; position: absolute; inset: 0; z-index: 1; pointer-events: none;
	background-image:
		linear-gradient(rgba(110,155,239,.16) 1px, transparent 1px),
		linear-gradient(90deg, rgba(110,155,239,.16) 1px, transparent 1px);
	background-size: 68px 68px;
	opacity: 0;
	transition: opacity .5s ease;
	-webkit-mask-image: radial-gradient(320px circle at var(--fy-mx, 50%) var(--fy-my, 50%), #000 0%, transparent 72%);
	mask-image: radial-gradient(320px circle at var(--fy-mx, 50%) var(--fy-my, 50%), #000 0%, transparent 72%);
}
.fy-blueprint.is-lit::after { opacity: 1; }

/* ---------- hero aurora ----------
   Two slow blooms of brand blue behind the composition. Replaces the flat
   navy field with something that has depth and moves on its own clock. */
.fy-hero__aurora {
	position: absolute; inset: -30% -10%; z-index: 0; pointer-events: none;
	filter: blur(90px); opacity: .55;
}
.fy-hero__aurora i {
	position: absolute; display: block; border-radius: 50%;
	background: radial-gradient(circle, rgba(11,79,200,.85), transparent 68%);
}
.fy-hero__aurora i:nth-child(1) {
	width: 46vw; height: 46vw; top: 4%; left: -6%;
	animation: fy-bloom-a 22s ease-in-out infinite alternate;
}
.fy-hero__aurora i:nth-child(2) {
	width: 38vw; height: 38vw; bottom: -4%; right: 4%;
	background: radial-gradient(circle, rgba(46,120,255,.6), transparent 70%);
	animation: fy-bloom-b 27s ease-in-out infinite alternate;
}

@keyframes fy-bloom-a {
	from { transform: translate3d(0,0,0) scale(1); }
	to   { transform: translate3d(7vw, 5vh, 0) scale(1.16); }
}
@keyframes fy-bloom-b {
	from { transform: translate3d(0,0,0) scale(1.1); }
	to   { transform: translate3d(-6vw, -6vh, 0) scale(.92); }
}

/* ---------- the wheel motif ----------
   The wheel lifted straight out of the wordmark, drawn as a technical
   outline and rotated by scroll position. The brand's own mark, turning
   because you are moving — which is what the business does. */
.fy-wheel {
	position: absolute; pointer-events: none; z-index: 1;
	border-radius: 50%; border: 1px solid rgba(110,155,239,.22);
	display: grid; place-items: center;
	will-change: transform;
}
.fy-wheel::before {
	content: ""; width: 33%; height: 33%; border-radius: 50%;
	border: 1px solid rgba(110,155,239,.28);
}
/* Spokes, as hairlines. Four is enough to read as a wheel turning. */
.fy-wheel::after {
	content: ""; position: absolute; inset: 0; border-radius: 50%;
	background:
		linear-gradient(90deg, transparent calc(50% - .5px), rgba(110,155,239,.16) 50%, transparent calc(50% + .5px)),
		linear-gradient(0deg,  transparent calc(50% - .5px), rgba(110,155,239,.16) 50%, transparent calc(50% + .5px));
}
.fy-wheel--hero { width: 620px; height: 620px; top: -180px; right: -220px; }
.fy-wheel--track { width: 460px; height: 460px; bottom: -180px; left: -190px; }

/* ---------- headline: word-by-word mask reveal ----------
   Each word rises out of its own clipping box, so the sentence assembles
   rather than fading in. The display face earns this; nothing else gets it. */
.fy-reveal-words { display: block; }
.fy-reveal-words .w { display: inline-block; overflow: hidden; vertical-align: bottom; }
.fy-reveal-words .w > span {
	display: inline-block;
	/* fill-mode BOTH, not backwards. With `backwards` alone the word holds
	   its start position before the delay, animates up — and then reverts to
	   translateY(105%) inside an overflow:hidden box, leaving an invisible
	   headline that still occupies its space. */
	animation: fy-word .9s cubic-bezier(.16,.84,.28,1) both;
}
@keyframes fy-word {
	from { transform: translateY(105%); }
	to   { transform: none; }
}

/* ---------- rules that draw ---------- */
.fy-costs { display: grid; grid-template-columns: repeat(3, 1fr); gap: 0 42px; margin: 48px 0 0; }
.fy-costs > div { padding: 26px 0; border-top: 1px solid var(--fy-line); position: relative; }
.fy-costs > div::before {
	content: ""; position: absolute; top: -1px; left: 0; height: 1px; width: 100%;
	background: var(--fy-blue); transform-origin: 0 50%;
	transition: transform .7s cubic-bezier(.22,.68,.32,1);
}
.fy-js .fy-costs > div::before { transform: scaleX(0); }
.fy-js .fy-costs > div.is-in::before { transform: scaleX(1); }
.fy-costs dt {
	font-family: var(--fy-display); font-weight: 700; font-size: 1.08rem;
	letter-spacing: -0.015em; margin-bottom: 8px;
}
.fy-costs dd { margin: 0; font-size: .93rem; color: var(--fy-muted); }

/* ---------- ghost numerals behind the process ----------
   The step number, set enormous and nearly invisible. Reinforces the
   sequence at a glance without adding another element to read. */
.fy-steps li { position: relative; }
.fy-steps li::before {
	content: attr(data-step);
	position: absolute; right: -6px; top: 6px;
	font-family: var(--fy-display); font-weight: 800; font-size: 5.4rem; line-height: 1;
	color: var(--fy-blue); opacity: .05; letter-spacing: -0.06em;
	pointer-events: none; transition: opacity .4s ease, transform .5s cubic-bezier(.22,.68,.32,1);
	transform: translateX(10px);
}
.fy-steps li:not(.is-dim)::before { opacity: .1; transform: none; }

/* ---------- card tilt and sheen ---------- */
.fy-card-plain, .fy-show { transform-style: preserve-3d; }
.fy-card-plain { position: relative; overflow: hidden; }
.fy-card-plain::after {
	content: ""; position: absolute; inset: 0; pointer-events: none;
	background: linear-gradient(115deg, transparent 38%, rgba(11,79,200,.07) 50%, transparent 62%);
	transform: translateX(-120%);
	transition: transform .8s cubic-bezier(.22,.68,.32,1);
}
.fy-card-plain:hover::after { transform: translateX(120%); }

/* ---------- magnetic buttons ----------
   Primary calls to action lean very slightly toward the cursor. Two or
   three pixels — enough to feel responsive, not enough to notice. */
.fy-btn { will-change: transform; }

/* ---------- receipt: the total resolves ----------
   The figure counts up while the lines print, so the number settles at the
   moment the stamp lands. The whole page argues that a price resolves into
   something you can rely on; this is that argument in three seconds. */
.fy-receipt__total strong { font-variant-numeric: tabular-nums; }

/* ---------- marquee reacts to scroll direction ---------- */
.fy-marquee__track { animation-direction: normal; }
.fy-marquee.is-reversed .fy-marquee__track { animation-direction: reverse; }

/* ---------- section rule flourish ---------- */
.fy-eyebrow { position: relative; padding-left: 0; }
.fy-eyebrow::after {
	content: ""; display: inline-block; vertical-align: middle;
	width: 54px; height: 1px; margin-left: 14px; background: currentColor; opacity: .5;
	transition: width .8s cubic-bezier(.22,.68,.32,1) .15s;
}
.fy-js .fy-eyebrow::after { width: 0; }
.fy-js .fy-eyebrow.is-in::after { width: 54px; }

@media (max-width: 1000px) {
	.fy-costs { grid-template-columns: 1fr 1fr; gap: 0 30px; }
	.fy-wheel--hero { width: 420px; height: 420px; top: -140px; right: -180px; }
	.fy-wheel--track { display: none; }
	.fy-steps li::before { font-size: 4.4rem; opacity: .07; }
}
@media (max-width: 560px) {
	.fy-costs { grid-template-columns: 1fr; }
	.fy-hero__aurora { filter: blur(64px); opacity: .45; }
	.fy-wheel--hero { width: 300px; height: 300px; top: -100px; right: -130px; }
	.fy-steps li::before { display: none; }
}

@media (prefers-reduced-motion: reduce) {
	.fy-hero__aurora i,
	.fy-wheel,
	.fy-reveal-words .w > span { animation: none !important; transform: none !important; }
	.fy-costs > div::before { transform: scaleX(1) !important; }
	.fy-eyebrow::after { width: 54px !important; transition: none !important; }
	.fy-blueprint::after { display: none; }
	.fy-card-plain::after { display: none; }
}

/* Touch devices: no pointer, so no spotlight and no magnetism. */
@media (hover: none) {
	.fy-blueprint::after { display: none; }
	.fy-card-plain::after { display: none; }
}
