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ı 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 nabız atar (`kt-piksel-nabiz`). Hareketi azalt: dolu, durağan. Renk her zaman
`PikselListeAciklama` metniyle. `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. - 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. 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ı**: - Ç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 * 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). * 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({ export function PikselCtaYuzeyi({
children, children,
className, className,
@@ -39,7 +42,18 @@ export function PikselCtaYuzeyi({
className, 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="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"> <div className="flex min-w-0 flex-col items-center text-center lg:items-start lg:text-left">
{children} {children}

View File

@@ -15,11 +15,17 @@ import { cn } from "@/lib/utils";
export function PikselZemin({ export function PikselZemin({
seed = 7, seed = 7,
ton = "acik", ton = "acik",
bosBant,
yogunluk,
className, className,
}: { }: {
/** Aynı ekrandaki iki yüzey farklı desen alsın */ /** Aynı ekrandaki iki yüzey farklı desen alsın */
seed?: number; seed?: number;
ton?: "acik" | "koyu"; 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`) */ /** Dikey taşma payı vb. (varsayılan `-inset-y-6`) */
className?: string; className?: string;
}) { }) {
@@ -32,7 +38,7 @@ export function PikselZemin({
className, className,
)} )}
> >
<PixelMasonry seed={seed} /> <PixelMasonry seed={seed} bosBant={bosBant} yogunluk={yogunluk} />
</div> </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 * (§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"). * (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({ export function PixelMasonry({
seed = 7, seed = 7,
bosBant = BOS_BANT_VARSAYILAN,
yogunluk = 1,
className, className,
}: { }: {
seed?: number; 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; className?: string;
}) { }) {
const COLS = 42; const COLS = 42;
@@ -96,8 +106,8 @@ export function PixelMasonry({
const cx = (COLS - 1) / 2; const cx = (COLS - 1) / 2;
const cy = (ROWS - 1) / 2; const cy = (ROWS - 1) / 2;
const maxD = Math.sqrt(cx * cx + cy * cy); const maxD = Math.sqrt(cx * cx + cy * cy);
const BAND_MIN = COLS * 0.22; const BAND_MIN = COLS * bosBant[0];
const BAND_MAX = COLS * 0.78; const BAND_MAX = COLS * bosBant[1];
const sonuc: ReactNode[] = []; const sonuc: ReactNode[] = [];
let accentIdx = 0; let accentIdx = 0;
@@ -145,10 +155,10 @@ export function PixelMasonry({
if (mcx > BAND_MIN && mcx < BAND_MAX) continue; if (mcx > BAND_MIN && mcx < BAND_MAX) continue;
// Kenarlara doğru artan doluluk // Kenarlara doğru artan doluluk
const d = Math.sqrt((mcx - cx) ** 2 + (oy + MAKRO / 2 - cy) ** 2) / maxD; 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) { if (hash(mx, my, seed) > density) {
// Boş makro hücrede ara sıra tek küçük piksel: doku kopmasın // 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 px = ox + Math.floor(hash(mx, my, seed + 4) * MAKRO);
const py = oy + Math.floor(hash(mx, my, seed + 5) * MAKRO); const py = oy + Math.floor(hash(mx, my, seed + 5) * MAKRO);
sonuc.push(kare(px, py, 1, `k-${mx}-${my}`, false)); sonuc.push(kare(px, py, 1, `k-${mx}-${my}`, false));
@@ -171,7 +181,7 @@ export function PixelMasonry({
} }
} }
return sonuc; return sonuc;
}, [seed]); }, [seed, bosBant, yogunluk]);
return ( return (
<svg <svg