Site geneli üst/alt blur katmanları `position: fixed` + `backdrop-filter` taşıyordu. iOS/iPadOS WebKit (iPad'de Chrome da WebKit) bu birleşimde bulanıklığı ayrı kompozit katmana alıp scroll sırasında bayat kaydırma konumuyla çiziyor; katman ekranın ortasında şerit gibi görünüyordu. Katmanların stili skiper-ui bileşeninin inline stilinden globals.css'teki `.kt-sayfa-blur`a taşındı (inline stil `@supports` ile ezilemiyordu). `@supports (-webkit-touch-callout: none)` yalnızca iOS/iPadOS'ta eşleşir — masaüstü Safari dahil başka hiçbir tarayıcıda desteklenmez — ve orada bulanıklık + maske düşer, degrade fade korunur. Geometri (112px, z-40, print:hidden) ve diğer tarayıcılardaki görüntü değişmedi. Katalogdaki ProgressiveBlur kullanımları `absolute` olduğu için bu hatadan etkilenmiyor; bileşen onlar için olduğu gibi kaldı. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
126 lines
5.0 KiB
TypeScript
126 lines
5.0 KiB
TypeScript
import type { Metadata, Viewport } from "next";
|
||
import Script from "next/script";
|
||
import { Cal_Sans, Geist_Mono, Bricolage_Grotesque } from "next/font/google";
|
||
import localFont from "next/font/local";
|
||
import { Toaster } from "@/components/ui/sonner";
|
||
import { SiteHeader } from "@/components/site-header";
|
||
import { SiteTopBanner } from "@/components/site-top-banner";
|
||
import { ListeCekmecesiLazy } from "@/features/liste/components/liste-cekmecesi-lazy";
|
||
import { KaydetBannerLazy } from "@/features/liste/components/kaydet-banner-lazy";
|
||
import { TercihProfiliKapisiLazy } from "@/features/liste/components/tercih-profili-kapisi-lazy";
|
||
import { HeaderGate } from "@/components/header-gate";
|
||
import { DevPanelMount } from "@/components/dev/dev-panel-mount";
|
||
import { JsonLd, organizationJsonLd, webSiteJsonLd, SITE_URL } from "@/lib/seo";
|
||
import "./globals.css";
|
||
|
||
const calSans = Cal_Sans({
|
||
variable: "--font-cal-sans",
|
||
weight: "400",
|
||
subsets: ["latin", "latin-ext"],
|
||
});
|
||
|
||
const clarityCity = localFont({
|
||
variable: "--font-clarity-city",
|
||
src: [
|
||
{ path: "../fonts/ClarityCity-Regular.woff2", weight: "400" },
|
||
{ path: "../fonts/ClarityCity-Medium.woff2", weight: "500" },
|
||
{ path: "../fonts/ClarityCity-SemiBold.woff2", weight: "600" },
|
||
{ path: "../fonts/ClarityCity-Bold.woff2", weight: "700" },
|
||
{ path: "../fonts/ClarityCity-ExtraBold.woff2", weight: "800" },
|
||
],
|
||
});
|
||
|
||
const geistMono = Geist_Mono({
|
||
variable: "--font-geist-mono",
|
||
subsets: ["latin"],
|
||
// Yalnızca markdown/kod bloklarında kullanılıyor; landing'de preload israfı
|
||
preload: false,
|
||
});
|
||
|
||
const bricolage = Bricolage_Grotesque({
|
||
variable: "--font-bricolage-grotesque",
|
||
subsets: ["latin", "latin-ext"],
|
||
axes: ["opsz"],
|
||
});
|
||
|
||
export const metadata: Metadata = {
|
||
metadataBase: new URL(SITE_URL),
|
||
title: {
|
||
default: "KolayTercih — Yapay Zekâ Destekli YKS Tercih Danışmanı",
|
||
template: "%s — KolayTercih",
|
||
},
|
||
description:
|
||
"YKS sıralamana göre gerçek YÖK Atlas verisiyle dengeli 24 tercihlik liste. İnsan danışmandan çok daha düşük fiyata, yapay zekâ destekli tercih danışmanlığı.",
|
||
applicationName: "KolayTercih",
|
||
openGraph: {
|
||
type: "website",
|
||
locale: "tr_TR",
|
||
siteName: "KolayTercih",
|
||
url: "/",
|
||
title: "KolayTercih — Yapay Zekâ Destekli YKS Tercih Danışmanı",
|
||
description:
|
||
"YKS sıralamana göre gerçek YÖK Atlas verisiyle dengeli 24 tercihlik liste. Yapay zekâ destekli tercih danışmanlığı.",
|
||
},
|
||
twitter: { card: "summary_large_image" },
|
||
robots: { index: true, follow: true },
|
||
};
|
||
|
||
export const viewport: Viewport = {
|
||
themeColor: "#f8fafc",
|
||
};
|
||
|
||
export default function RootLayout({
|
||
children,
|
||
}: Readonly<{
|
||
children: React.ReactNode;
|
||
}>) {
|
||
return (
|
||
<html
|
||
lang="tr"
|
||
// `h-full` verme: html auto yükseklikte içerikle büyür, viewport tabanı
|
||
// body'deki min-h-dvh'den gelir.
|
||
className={`${calSans.variable} ${clarityCity.variable} ${geistMono.variable} ${bricolage.variable} antialiased`}
|
||
>
|
||
<body className="min-h-dvh flex flex-col bg-slate-50">
|
||
<HeaderGate>
|
||
{/* Site geneli progressive blur — üst ve alt. Stil globals.css'te
|
||
(.kt-sayfa-blur): iOS/iPadOS'ta fixed + backdrop-filter katmanı
|
||
kaydırmada ekranın ortasına kayıyor, orada bulanıklık @supports
|
||
ile düşürülüp degrade fade korunuyor. */}
|
||
<div className="kt-sayfa-blur kt-sayfa-blur-ust print:hidden" aria-hidden />
|
||
<div className="kt-sayfa-blur kt-sayfa-blur-alt print:hidden" aria-hidden />
|
||
<SiteTopBanner />
|
||
<SiteHeader />
|
||
</HeaderGate>
|
||
<div className="flex min-h-0 flex-1 flex-col pb-28 print:pb-0">
|
||
{children}
|
||
</div>
|
||
{/* Manuel 24'lük liste çekmecesi + "+" uçuş katmanı (navbar'dan açılır) */}
|
||
<ListeCekmecesiLazy />
|
||
{/* Girişsiz + 3 seçimli kullanıcıya "listen yalnızca bu tarayıcıda" banner'ı */}
|
||
<KaydetBannerLazy />
|
||
{/* İlk "+" için sıra + sihirbaz kapısı */}
|
||
<TercihProfiliKapisiLazy />
|
||
<Toaster position="top-center" />
|
||
{/* Dev süperadmin paneli — prod build'de modül grafiğine bile girmez */}
|
||
{process.env.NODE_ENV !== "production" ? <DevPanelMount /> : null}
|
||
<JsonLd data={organizationJsonLd()} />
|
||
<JsonLd data={webSiteJsonLd()} />
|
||
{/* Rybbit analitik — afterInteractive: hydration sonrası client'ta
|
||
enjekte edilir, LCP/kritik yolla yarışmaz. Yalnızca prod build'de:
|
||
Rybbit localhost'u da takip ettiği için dev trafiği prod verisini
|
||
kirletmesin (DevPanel ile aynı kapı). mask-patterns: /sonuc URL'i
|
||
ham başarı sıralamasını, /odeme/sonuc sipariş kimliğini taşıyor. */}
|
||
{process.env.NODE_ENV === "production" ? (
|
||
<Script
|
||
src="https://rybbit.kolaytercih.com/api/script.js"
|
||
data-site-id="f2cb042c657e"
|
||
data-mask-patterns='["/sonuc", "/odeme/sonuc"]'
|
||
strategy="afterInteractive"
|
||
/>
|
||
) : null}
|
||
</body>
|
||
</html>
|
||
);
|
||
}
|