fix(tasarim): kapanış kartında piksel tablosunun arkası boş — dokuya bosBant/yogunluk
All checks were successful
Deploy / deploy (push) Successful in 4m30s

Bilal (24 Eyl 2026): ana sayfadaki piksel tablosunun arkasına çok piksel
yığılmıştı. PixelMasonry/PikselZemin boş bant ve yoğunluk alıyor;
kapanış kartı lg'de doku yalnız sol %16'da ve seyrek, altında liste
üstte ortada boş bantta. DESIGN.md §10.8: kreatif ile doku üst üste binmez.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
bilalgursen
2026-09-24 12:18:39 +03:00
parent 09c6868089
commit c90c186b86
4 changed files with 42 additions and 7 deletions

View File

@@ -718,6 +718,11 @@ yok** (Bilal, 24 Eyl 2026: kaldırıldı); `FUNNEL_METINLERI` yalnız arama penc
içindeki düğmeye imleç/odak gelince 24 kare birden dolar; dokunmada basılan kare ve komşuları
nabız atar (`kt-piksel-nabiz`). Hareketi azalt: dolu, durağan. Renk her zaman
`PikselListeAciklama` metniyle.
- Piksel tablosunun arkası boş kalır (Bilal, 24 Eyl 2026: "arkasına çok piksel yığılmış"):
telefon/tablette liste üstte ortada, dokunun boş bandında; `lg`'de liste sağ sütunda olduğu
için doku yalnız sol %16'da ve seyrek (`PikselZemin bosBant={[0.16, 1]} yogunluk={0.7}`).
Kural genel: bir kreatif ya da iri sayı piksel zeminin üstüne geliyorsa `bosBant` ile o
bölge boşaltılır; doku ile kreatif üst üste binmez.
- Bu yüzey **sayfada bir kez** ve yalnız kapanışta durur; ara paneller ve çekmece mavi banttır.
Yeni bir kreatif fikri (veriyi piksele çeviren, imlece tepki veren) önce burada denenir.
- Çekmece başlığında denenen "gerçek liste" pikseli (12×2, her kare tercihin riski) **kaldırıldı**:

View File

@@ -13,6 +13,9 @@ import { PikselListe, PikselListeAciklama } from "@/components/piksel-liste";
* düğmeye ya da linke imleç/odak gelince 24 kare birden dolar — "listen
* böyle hazır olur". Yazılıp silinen satır yok (Bilal, 24 Eyl 2026).
*/
// Geniş ekranda doku yalnız genişliğin ilk %16'sında (metnin sol boşluğu)
const SOL_KENAR: [number, number] = [0.16, 1];
export function PikselCtaYuzeyi({
children,
className,
@@ -39,7 +42,18 @@ export function PikselCtaYuzeyi({
className,
)}
>
<PikselZemin seed={seed} ton="koyu" className="-inset-y-10" />
{/* Telefon/tablet: liste üstte ortada, dokunun boş bandında. Geniş
ekranda liste sağ sütunda — orası tamamen boş kalır, doku yalnız
sol kenarda ve seyrek (Bilal, 24 Eyl 2026: "tablonun arkasına çok
piksel yığılmış"). */}
<PikselZemin seed={seed} ton="koyu" className="-inset-y-10 lg:hidden" />
<PikselZemin
seed={seed}
ton="koyu"
bosBant={SOL_KENAR}
yogunluk={0.7}
className="-inset-y-10 hidden lg:block"
/>
<div className="grid items-center gap-8 px-5 py-10 sm:px-10 sm:py-12 lg:grid-cols-[minmax(0,1fr)_16rem] lg:gap-12">
<div className="flex min-w-0 flex-col items-center text-center lg:items-start lg:text-left">
{children}

View File

@@ -15,11 +15,17 @@ import { cn } from "@/lib/utils";
export function PikselZemin({
seed = 7,
ton = "acik",
bosBant,
yogunluk,
className,
}: {
/** Aynı ekrandaki iki yüzey farklı desen alsın */
seed?: number;
ton?: "acik" | "koyu";
/** Boş bırakılacak yatay bant (varsayılan orta %22–78); bkz. PixelMasonry */
bosBant?: [number, number];
/** Doluluk çarpanı */
yogunluk?: number;
/** Dikey taşma payı vb. (varsayılan `-inset-y-6`) */
className?: string;
}) {
@@ -32,7 +38,7 @@ export function PikselZemin({
className,
)}
>
<PixelMasonry seed={seed} />
<PixelMasonry seed={seed} bosBant={bosBant} yogunluk={yogunluk} />
</div>
);
}

View File

@@ -80,11 +80,21 @@ function pixelRect(
* (§1.1 "doğal duruş"). Durağan zemin: imleç ısı fırçasına katılmaz
* (Bilal, 24 Eyl 2026: "üzerine gelindiğinde bir şey olmasın").
*/
// Varsayılan boş bant modül sabiti: her render'da yeni dizi olup useMemo'yu
// boşa düşürmesin (rendering-hoist-jsx)
const BOS_BANT_VARSAYILAN: [number, number] = [0.22, 0.78];
export function PixelMasonry({
seed = 7,
bosBant = BOS_BANT_VARSAYILAN,
yogunluk = 1,
className,
}: {
seed?: number;
/** Genişliğin bu oranları arasındaki bant boş kalır (içerik orada) */
bosBant?: [number, number];
/** Doluluk çarpanı; 1 varsayılan, 0.6 seyrek */
yogunluk?: number;
className?: string;
}) {
const COLS = 42;
@@ -96,8 +106,8 @@ export function PixelMasonry({
const cx = (COLS - 1) / 2;
const cy = (ROWS - 1) / 2;
const maxD = Math.sqrt(cx * cx + cy * cy);
const BAND_MIN = COLS * 0.22;
const BAND_MAX = COLS * 0.78;
const BAND_MIN = COLS * bosBant[0];
const BAND_MAX = COLS * bosBant[1];
const sonuc: ReactNode[] = [];
let accentIdx = 0;
@@ -145,10 +155,10 @@ export function PixelMasonry({
if (mcx > BAND_MIN && mcx < BAND_MAX) continue;
// Kenarlara doğru artan doluluk
const d = Math.sqrt((mcx - cx) ** 2 + (oy + MAKRO / 2 - cy) ** 2) / maxD;
const density = 0.3 + 0.6 * d * d;
const density = (0.3 + 0.6 * d * d) * yogunluk;
if (hash(mx, my, seed) > density) {
// Boş makro hücrede ara sıra tek küçük piksel: doku kopmasın
if (hash(mx, my, seed + 3) < 0.25) {
if (hash(mx, my, seed + 3) < 0.25 * yogunluk) {
const px = ox + Math.floor(hash(mx, my, seed + 4) * MAKRO);
const py = oy + Math.floor(hash(mx, my, seed + 5) * MAKRO);
sonuc.push(kare(px, py, 1, `k-${mx}-${my}`, false));
@@ -171,7 +181,7 @@ export function PixelMasonry({
}
}
return sonuc;
}, [seed]);
}, [seed, bosBant, yogunluk]);
return (
<svg