feat(easter-egg): footer'da Tâhâ 25–26 âyeti, konsolda piksel kum saati + Asr Sûresi

- Footer: "Rabbi'şrah lî sadrî ve yessir lî emrî" (Tâhâ 25–26) Arapça +
  Diyanet İşleri meali; Arapça Amiri Quran ile (önceden yüklenmez, ~45 KB).
  Altında PixelMark'lı kaynak satırı.
- Konsol: ConsoleAsr artık kök layout'ta. Logodaki renklerle dot-matrix kum
  saati, Asr Sûresi (Diyanet mushafı + Diyanet meali, kaynakla bayt bayt
  aynı), İmam Şâfiî'nin sûfîlerden aktardığı vakit sözü, /meraklisina linki.
  Tarayıcı boşa çıkınca bir kez basar.
- DESIGN.md §3: Arapça yazı tipinin tek işi (yalnız Kur'an metni) yazıldı.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
bilalgursen
2026-10-03 19:27:08 +03:00
parent 70423853f3
commit 26626ae449
4 changed files with 165 additions and 19 deletions

View File

@@ -125,7 +125,7 @@ turuncu **tek tondur: `orange-500`** — CTA butonunun turuncusuyla birebir ayn
## 3. Tipografi ## 3. Tipografi
Dört yazı tipi, her birinin tek bir işi var: Dört arayüz yazı tipi (+ yalnız Kur'an metni için bir Arapça yazı tipi), her birinin tek bir işi var:
| Sınıf | Yazı tipi | İş | | Sınıf | Yazı tipi | İş |
|---|---|---| |---|---|---|
@@ -133,6 +133,7 @@ Dört yazı tipi, her birinin tek bir işi var:
| `font-sans` (varsayılan) | Clarity City 400–800 | Gövde, buton, form, tablo | | `font-sans` (varsayılan) | Clarity City 400–800 | Gövde, buton, form, tablo |
| `font-bricolage` | Bricolage Grotesque (opsz ekseni) | Vurgu: hero'da italik mavi span, logo yazısı, üst çubuktaki sayfa adı (§4.14), küçük etiketler/çipler | | `font-bricolage` | Bricolage Grotesque (opsz ekseni) | Vurgu: hero'da italik mavi span, logo yazısı, üst çubuktaki sayfa adı (§4.14), küçük etiketler/çipler |
| `font-mono` | Geist Mono | Yalnızca kod/markdown blokları. Arayüzde kullanılmaz | | `font-mono` | Geist Mono | Yalnızca kod/markdown blokları. Arayüzde kullanılmaz |
| `amiriQuran.className` (`site-footer.tsx`) | Amiri Quran | Yalnızca Kur'an metni: footer'daki âyet (`lang="ar" dir="rtl"`). Arayüz metninde kullanılmaz; önceden yüklenmez, Arapça alt kümesi âyet çizilirken iner. Aşağıdaki "serif yasak" kuralı Latin arayüz metni içindir |
Ölçek (kopyala, uydurma): Ölçek (kopyala, uydurma):

View File

@@ -10,6 +10,7 @@ import { KaydetBannerLazy } from "@/features/liste/components/kaydet-banner-lazy
import { TercihProfiliKapisiLazy } from "@/features/liste/components/tercih-profili-kapisi-lazy"; import { TercihProfiliKapisiLazy } from "@/features/liste/components/tercih-profili-kapisi-lazy";
import { HeaderGate } from "@/components/header-gate"; import { HeaderGate } from "@/components/header-gate";
import { DevPanelMount } from "@/components/dev/dev-panel-mount"; import { DevPanelMount } from "@/components/dev/dev-panel-mount";
import { ConsoleAsr } from "@/components/console-asr";
import { JsonLd, organizationJsonLd, webSiteJsonLd, SITE_URL } from "@/lib/seo"; import { JsonLd, organizationJsonLd, webSiteJsonLd, SITE_URL } from "@/lib/seo";
import "./globals.css"; import "./globals.css";
@@ -117,6 +118,8 @@ export default function RootLayout({
{/* İlk "+" için sıra + sihirbaz kapısı */} {/* İlk "+" için sıra + sihirbaz kapısı */}
<TercihProfiliKapisiLazy /> <TercihProfiliKapisiLazy />
<Toaster position="top-center" /> <Toaster position="top-center" />
{/* DevTools'u açan meraklıya piksel kum saati + Asr Sûresi */}
<ConsoleAsr />
{/* Dev süperadmin paneli — prod build'de modül grafiğine bile girmez */} {/* Dev süperadmin paneli — prod build'de modül grafiğine bile girmez */}
{process.env.NODE_ENV !== "production" ? <DevPanelMount /> : null} {process.env.NODE_ENV !== "production" ? <DevPanelMount /> : null}
<JsonLd data={organizationJsonLd()} /> <JsonLd data={organizationJsonLd()} />

View File

@@ -2,31 +2,136 @@
import { useEffect } from "react"; import { useEffect } from "react";
let hasPlayed = false; /**
* Konsol sürprizi: DevTools'u açan meraklıya sitenin piksel dilinde bir kum
* saati, Asr Sûresi (Arapça + meal) ve tasavvuftan bir vakit sözü. "Asr"
* zaman demek; kum saati de onu anlatır. Görünür arayüzde iz bırakmaz; kök
* layout'ta bir kez çalışır, sayfa geçişlerinde tekrar basmaz.
*
* DevTools açık ya da koyu temada olabilir: düz metne renk verilmez
* (konsolun kendi rengi kalır), yalnız iki zeminde de okunan marka renkleri
* kullanılır.
*
* Arapça metin Diyanet'in Kur'an-ı Kerim mushafından, meal Diyanet İşleri
* mealinden harfi harfine alındı (kuran.diyanet.gov.tr, âyet gruplaması
* aynen). Elle düzeltme yapılmaz; değişecekse kaynaktan yeniden kopyalanır.
*/
const consoleMessage = [ let basildi = false;
"%cبِسْمِ اللَّهِ الرَّحْمٰنِ الرَّحِيمِ",
"", // Logodaki üç kare (public/kolay-tercih-mark.svg)
"وَالْعَصْرِۙ اِنَّ الْاِنْسَانَ لَف۪ي خُسْرٍۙ", const MAVI = "#3b82f6";
"اِلَّا الَّذ۪ينَ اٰمَنُوا وَعَمِلُوا الصَّالِحَاتِ", const SEFTALI = "#fdc7a7";
"وَتَوَاصَوْا بِالْحَقِّ وَتَوَاصَوْا بِالصَّبْرِ", const TURUNCU = "#ff5a00";
"", // slate-400: açık ve koyu konsolda okunan silik metin
const SILIK = "#94a3b8";
// Hero'daki dot-matrix ızgarasıyla kum saati: # çerçeve, g boş cam,
// o yığılmış kum, p akan kum. Üst hazne boşalıyor, alt hazne doluyor.
const KUM_SAATI = [
"###########",
" #ggggggg# ",
" #ooooooo# ",
" #ooooo# ",
" #ooo# ",
" #p# ",
" #p# ",
" #gpg# ",
" #ggpgg# ",
" #ggooogg# ",
" #ooooooo# ",
"###########",
];
const PIKSEL_RENK: Record<string, string> = {
"#": MAVI,
g: "rgba(59,130,246,0.16)",
o: TURUNCU,
p: SEFTALI,
};
// Piksel = arka planı boyanmış iki boşluk; satır aralığı ve sağ boşluk
// hero'daki gibi kareler arasında eşit nefes bırakır.
const HUCRE = "font-size:8px;line-height:14px;margin-right:4px;border-radius:2px";
// Kum saatinin sağında, boğaz hizasında duran satırlar
const YAN_YAZI: Record<number, [string, string]> = {
5: ["KolayTercih", `font-size:13px;font-weight:700;color:${MAVI}`],
6: ["Asr Sûresi", `font-size:12px;color:${SILIK}`],
};
const BESMELE = "بِسْمِ اللّٰهِ الرَّحْمٰنِ الرَّح۪يمِ";
const ASR = [
"وَالْعَصْرِۙ",
"اِنَّ الْاِنْسَانَ لَفٖي خُسْرٍۙ",
"اِلَّا الَّذٖينَ اٰمَنُوا وَعَمِلُوا الصَّالِحَاتِ وَتَوَاصَوْا بِالْحَقِّ وَتَوَاصَوْا بِالصَّبْرِ",
];
const MEAL = [
"Rahmân ve Rahîm olan Allah’ın adıyla.", "Rahmân ve Rahîm olan Allah’ın adıyla.",
"", "",
"Asra yemîn olsun ki,", "1-2. Andolsun zamana ki, insan gerçekten ziyan içindedir.",
"İnsan gerçekten ziyândadır.", "3. Ancak, iman edip de sâlih ameller işleyenler, birbirlerine hakkı tavsiye edenler, birbirlerine sabrı tavsiye edenler başka (Onlar ziyanda değillerdir).",
"Ancak iman edip sâlih ameller yapanlar, birbirlerine hakkı tavsiye", ];
"edenler ve birbirlerine sabretmeyi öğütleyenler müstesnâ!",
].join("\n"); // Konsol sayfanın web fontlarını görmez; sistemde ne varsa o seçilir.
const ARAPCA_YAZI_TIPI =
"'Amiri Quran','Amiri','Scheherazade New','Noto Naskh Arabic','Geeza Pro','Traditional Arabic',serif";
function mesaj(): string[] {
let bicim = "";
const stiller: string[] = [];
const ekle = (metin: string, stil: string) => {
bicim += `%c${metin}`;
stiller.push(stil);
};
KUM_SAATI.forEach((satir, i) => {
for (const k of satir) {
const renk = PIKSEL_RENK[k];
ekle(" ", renk ? `${HUCRE};background:${renk}` : HUCRE);
}
const yan = YAN_YAZI[i];
if (yan) ekle(` ${yan[0]}`, `line-height:14px;${yan[1]}`);
bicim += "\n";
});
ekle(
`\n${BESMELE}\n${ASR.join("\n")}\n`,
`font-size:22px;line-height:2;font-family:${ARAPCA_YAZI_TIPI}`,
);
ekle(`\n${MEAL.join("\n")}\n`, "font-size:13px;line-height:1.7");
ekle("Asr Sûresi (103) · Diyanet İşleri meali\n\n", `font-size:11px;color:${SILIK}`);
ekle(
"«Vakit bir kılıçtır; sen onu kesmezsen o seni keser.»\n",
`font-size:13px;font-weight:600;line-height:1.8;color:${TURUNCU}`,
);
ekle(
"İmam Şâfiî’nin sûfîlerden öğrendiğini söylediği söz\n\n",
`font-size:11px;color:${SILIK}`,
);
ekle(
`Meraklısına: ${window.location.origin}/meraklisina`,
`font-size:11px;color:${SILIK}`,
);
return [bicim, ...stiller];
}
export function ConsoleAsr() { export function ConsoleAsr() {
useEffect(() => { useEffect(() => {
if (hasPlayed) return; if (basildi) return;
hasPlayed = true; basildi = true;
window.setTimeout(() => { // Hidrasyon ve ilk etkileşimle yarışmasın: tarayıcı boşa çıkınca bas.
console.log(consoleMessage, "font-size:16px"); // Safari'de requestIdleCallback yok, orada kısa bir gecikme yeter.
}, 250); const bas = () => console.log(...mesaj());
if (typeof window.requestIdleCallback === "function") {
window.requestIdleCallback(bas, { timeout: 3000 });
} else {
window.setTimeout(bas, 1000);
}
}, []); }, []);
return null; return null;

View File

@@ -1,6 +1,17 @@
import Image from "next/image"; import Image from "next/image";
import Link from "next/link"; import Link from "next/link";
import { Amiri_Quran } from "next/font/google";
import { PixelMark } from "@/components/pixel-decor";
import { getAllBolumler } from "@/lib/katalog"; import { getAllBolumler } from "@/lib/katalog";
import { cn } from "@/lib/utils";
// Yalnız footer'daki âyet için (DESIGN.md §3). Önceden yüklenmez: Arapça
// alt kümesi (~45 KB) âyet çizilirken bir kez iner, sonra önbellekten gelir.
const amiriQuran = Amiri_Quran({
weight: "400",
subsets: ["arabic"],
preload: false,
});
/** /**
* Site footer'ı: yasal metin + SEO iç link kolonları. Server component — * Site footer'ı: yasal metin + SEO iç link kolonları. Server component —
@@ -125,6 +136,32 @@ export function SiteFooter() {
</div> </div>
<div className="mt-10 border-t border-slate-200/70 pt-6 text-center text-sm leading-relaxed text-slate-500"> <div className="mt-10 border-t border-slate-200/70 pt-6 text-center text-sm leading-relaxed text-slate-500">
{/* Hz. Mûsâ'nın göreve çıkarken ettiği dua (Tâhâ 25–26); sınav
öncesi okunan dua da budur. "İşimi kolaylaştır" sitenin adıyla
aynı dilekten. Arapça Diyanet mushafından, meal Diyanet İşleri
mealinden harfi harfine; dua olarak okunduğu gibi baştaki
"kâle" (dedi ki) alınmadı. */}
<figure className="mx-auto mb-8 max-w-md">
<blockquote>
<p
lang="ar"
dir="rtl"
className={cn(
amiriQuran.className,
"text-2xl leading-loose text-slate-900",
)}
>
رَبِّ اشْرَحْ لٖي صَدْرٖيۙ وَيَسِّرْ لٖٓي اَمْرٖيۙ
</p>
<p className="mt-1 text-slate-600">
“Rabbim! Gönlüme ferahlık ver. İşimi bana kolaylaştır.”
</p>
</blockquote>
<figcaption className="mt-2 inline-flex items-center gap-1.5 text-xs text-slate-400">
<PixelMark className="text-primary" />
Tâhâ Sûresi 25–26 · Diyanet İşleri meali
</figcaption>
</figure>
<p> <p>
© 2026 KolayTercih. Veriler resmî YÖK Atlas kaynağından derlenir; © 2026 KolayTercih. Veriler resmî YÖK Atlas kaynağından derlenir;
KolayTercih, ÖSYM veya YÖK ile bağlantılı değildir. KolayTercih, ÖSYM veya YÖK ile bağlantılı değildir.