Compare commits
2 Commits
cf992deac8
...
c90c186b86
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c90c186b86 | ||
|
|
09c6868089 |
@@ -689,7 +689,20 @@ karar.
|
||||
`-inset-y-10`, h2 `font-heading text-2xl font-bold sm:text-3xl`, paragraf `text-white/90`.
|
||||
- Kullanıldığı yerler: `/sonuc`'taki iki sihirbaz paneli, katalog altındaki `CtaSiraForm`
|
||||
kart varyantı, "Kendi Listem" çekmecesinin altı (kompakt). Aynı sayfadaki iki band farklı
|
||||
`seed` alır. Band üstündeki ikincil metin `text-white/90`, ince yazı `text-white/70`;
|
||||
`seed` alır.
|
||||
|
||||
**Her CTA benzeri yüzeyin arkasında piksel zemin — `PikselZemin`, `src/components/piksel-zemin.tsx`**
|
||||
(Bilal, 24 Eyl 2026: "piksel arka planları her CTA benzeri kısmın arkasında olmalı, masonry gibi
|
||||
büyüklü küçüklü"). CTA benzeri yüzey = tek bir aksiyona çağıran kart, bant, boş durum ya da
|
||||
sayfa bölümü. Kap `relative isolate overflow-hidden`; zemin ilk çocuk. Açık kartta
|
||||
`ton="acik"` (silik mavi, `text-primary/70`), mavi bant ve koyu kartta `ton="koyu"` (beyaz).
|
||||
`CtaBandi` ve `PikselCtaYuzeyi` de bunu kullanır. Kapsananlar: `/sonuc` "24 tercihlik listen
|
||||
hazır" kartı, `/listem` dört üretim kartı + boş durum + kilit kartı, tadımlık kartı,
|
||||
sıralama-yok sayfası, meraklısına kapanış kartı, ana sayfa ve `/paket` ana paket kartı, kaydet
|
||||
bandı, katalog üstü kompakt satır, arama penceresi kartı. **Kapsam dışı:** form kartları (giriş,
|
||||
ödeme formu), durum kartları (ödeme sonucu), modal düğmeleri, hata/404 sayfası, yan kredi
|
||||
kartları — bunlar tek aksiyona çağıran yüzey değil. Yeni bir CTA yüzeyi açan ajan zemini
|
||||
ekler ve bu listeye yazar. Band üstündeki ikincil metin `text-white/90`, ince yazı `text-white/70`;
|
||||
`slate-300`/`slate-400` yazılmaz.
|
||||
|
||||
**Kapanış yüzeyi — `PikselCtaYuzeyi`, `src/components/piksel-cta-yuzeyi.tsx` (yalnız ana
|
||||
@@ -705,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ı**:
|
||||
|
||||
@@ -28,6 +28,7 @@ import {
|
||||
SectionEyebrow,
|
||||
} from "@/components/pixel-decor";
|
||||
import { PikselCtaYuzeyi } from "@/components/piksel-cta-yuzeyi";
|
||||
import { PikselZemin } from "@/components/piksel-zemin";
|
||||
import { MAX_REVIZYON, URUNLER } from "@/lib/credits";
|
||||
import { VERI_YIL_SAYISI } from "@/lib/veri-kapsami";
|
||||
import {
|
||||
@@ -554,8 +555,9 @@ export default function Home() {
|
||||
>
|
||||
<Reveal
|
||||
delay={0.08}
|
||||
className="rounded-2xl border-2 border-orange-500 bg-white p-8 shadow-sm"
|
||||
className="relative isolate overflow-hidden rounded-2xl border-2 border-orange-500 bg-white p-8 shadow-sm"
|
||||
>
|
||||
<PikselZemin seed={43} />
|
||||
<div className="flex flex-wrap items-baseline justify-between gap-2">
|
||||
<h3 className="font-heading text-xl font-bold">
|
||||
{URUNLER.paket.label}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import { PikselZemin } from "@/components/piksel-zemin";
|
||||
import { useState } from "react";
|
||||
import { usePathname, useRouter, useSearchParams } from "next/navigation";
|
||||
import {
|
||||
@@ -70,8 +71,9 @@ export function AramaFunnelKarti({ onSec }: { onSec: () => void }) {
|
||||
return (
|
||||
<section
|
||||
aria-label="Tercih listeni kur"
|
||||
className="mt-5 overflow-hidden rounded-2xl border border-blue-400/20 bg-slate-950 px-4 py-5 text-white sm:px-5"
|
||||
className="relative isolate mt-5 overflow-hidden rounded-2xl border border-blue-400/20 bg-slate-950 px-4 py-5 text-white sm:px-5"
|
||||
>
|
||||
<PikselZemin seed={61} ton="koyu" />
|
||||
<div className="grid items-center gap-4 sm:grid-cols-[minmax(0,1fr)_auto] sm:gap-5">
|
||||
<div className="min-w-0">
|
||||
<TypingAnimation
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
"use client";
|
||||
|
||||
import type { ComponentProps, Ref } from "react";
|
||||
import { PixelMasonry } from "@/components/pixel-decor";
|
||||
import { PikselZemin } from "@/components/piksel-zemin";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
/**
|
||||
@@ -44,15 +44,7 @@ export function CtaBandi({
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
<div
|
||||
aria-hidden
|
||||
className={cn(
|
||||
"pointer-events-none absolute inset-x-0 -z-10 text-white",
|
||||
buyuk ? "-inset-y-10" : "-inset-y-6",
|
||||
)}
|
||||
>
|
||||
<PixelMasonry seed={seed} />
|
||||
</div>
|
||||
<PikselZemin seed={seed} ton="koyu" className={buyuk ? "-inset-y-10" : undefined} />
|
||||
{children}
|
||||
</Etiket>
|
||||
);
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import { useState, type ReactNode } from "react";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { PixelMasonry } from "@/components/pixel-decor";
|
||||
import { PikselZemin } from "@/components/piksel-zemin";
|
||||
import { PikselListe, PikselListeAciklama } from "@/components/piksel-liste";
|
||||
|
||||
/**
|
||||
@@ -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,12 +42,18 @@ export function PikselCtaYuzeyi({
|
||||
className,
|
||||
)}
|
||||
>
|
||||
<div
|
||||
aria-hidden
|
||||
className="pointer-events-none absolute inset-x-0 -inset-y-10 -z-10 text-white"
|
||||
>
|
||||
<PixelMasonry seed={seed} />
|
||||
</div>
|
||||
{/* 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}
|
||||
|
||||
44
src/components/piksel-zemin.tsx
Normal file
44
src/components/piksel-zemin.tsx
Normal file
@@ -0,0 +1,44 @@
|
||||
"use client";
|
||||
|
||||
import { PixelMasonry } from "@/components/pixel-decor";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
/**
|
||||
* CTA yüzeylerinin piksel zemini (DESIGN.md §10.8) — tek kaynak. Bilal'in
|
||||
* kararı (24 Eyl 2026): "piksel arka planları her CTA benzeri kısmın
|
||||
* arkasında olmalı, masonry gibi büyüklü küçüklü." Kap `relative isolate
|
||||
* overflow-hidden` olmalı; zemin ilk çocuk olarak konur.
|
||||
*
|
||||
* - `acik`: beyaz/açık kart — silik mavi kareler.
|
||||
* - `koyu`: mavi bant ya da koyu kart — beyaz kareler.
|
||||
*/
|
||||
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;
|
||||
}) {
|
||||
return (
|
||||
<div
|
||||
aria-hidden
|
||||
className={cn(
|
||||
"pointer-events-none absolute inset-x-0 -inset-y-6 -z-10",
|
||||
ton === "acik" ? "text-primary/70" : "text-white",
|
||||
className,
|
||||
)}
|
||||
>
|
||||
<PixelMasonry seed={seed} bosBant={bosBant} yogunluk={yogunluk} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
// hariç her yerde görünür; kapatma oturum boyunca kalıcıdır (sessionStorage).
|
||||
// Exit-intent/agresif popup YOK (PRD kuralı).
|
||||
|
||||
import { PikselZemin } from "@/components/piksel-zemin";
|
||||
import { useEffect, useState } from "react";
|
||||
import Link from "next/link";
|
||||
import { usePathname } from "next/navigation";
|
||||
@@ -60,8 +61,9 @@ export function KaydetBanner() {
|
||||
ref={gorunumRef}
|
||||
// Telefonda metin kendi satırında, düğme altında tam genişlik:
|
||||
// yan yana dizince başlık kelime kelime kırılıyordu (375 px).
|
||||
className="pointer-events-auto relative mx-auto flex max-w-xl flex-wrap items-center gap-3 rounded-2xl border border-slate-200 bg-white p-4 pr-14 shadow-xl sm:flex-nowrap sm:gap-4"
|
||||
className="pointer-events-auto relative isolate mx-auto flex max-w-xl flex-wrap items-center gap-3 overflow-hidden rounded-2xl border border-slate-200 bg-white p-4 pr-14 shadow-xl sm:flex-nowrap sm:gap-4"
|
||||
>
|
||||
<PikselZemin seed={47} />
|
||||
{/* Kullanıcının o anki işletim sisteminin logosu: "bu tarayıcıda"
|
||||
mesajını somutlaştırır */}
|
||||
<div className="flex size-10 shrink-0 items-center justify-center rounded-xl border border-slate-200 bg-slate-50 text-slate-700">
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { PikselZemin } from "@/components/piksel-zemin";
|
||||
import { Suspense } from "react";
|
||||
import Image from "next/image";
|
||||
import Link from "next/link";
|
||||
@@ -58,7 +59,8 @@ export function PaketSatinAl() {
|
||||
className="mt-10 grid gap-6 sm:grid-cols-[1fr_auto]"
|
||||
>
|
||||
{/* Ana paket */}
|
||||
<section className="rounded-2xl border-2 border-orange-500 bg-white p-8 shadow-sm">
|
||||
<section className="relative isolate overflow-hidden rounded-2xl border-2 border-orange-500 bg-white p-8 shadow-sm">
|
||||
<PikselZemin seed={43} />
|
||||
<div className="flex items-baseline justify-between">
|
||||
<h2 className="font-heading text-xl font-bold">
|
||||
Tercih Dönemi Paketi
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
// context'ten okur. (Sihirbaz hunisi statik bir şemayla anlatılır — bkz.
|
||||
// huni-semasi.tsx.)
|
||||
|
||||
import { PikselZemin } from "@/components/piksel-zemin";
|
||||
import {
|
||||
createContext,
|
||||
useContext,
|
||||
@@ -234,7 +235,8 @@ export function DemoKapanisCta() {
|
||||
const profil = useTercihProfili();
|
||||
|
||||
return (
|
||||
<div className="rounded-2xl border border-slate-200 bg-white p-6 text-center">
|
||||
<div className="relative isolate overflow-hidden rounded-2xl border border-slate-200 bg-white p-6 text-center">
|
||||
<PikselZemin seed={41} />
|
||||
<p className="font-heading text-base font-bold text-slate-900">
|
||||
{profil
|
||||
? "Kuralları öğrendin — sayılar zaten senin sıralamanla hesaplandı."
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
// Kural: action cevabının hemen ardından yönlendiriciye TEK aksiyon gönder
|
||||
// (router.replace); ikinci aksiyon (refresh) ancak o gezinme bitince.
|
||||
|
||||
import { PikselZemin } from "@/components/piksel-zemin";
|
||||
import { useEffect, useRef, useState, type ReactNode } from "react";
|
||||
import Link from "next/link";
|
||||
import { useRouter } from "next/navigation";
|
||||
@@ -264,7 +265,8 @@ export function ListeUretici({
|
||||
// Paketli kullanıcıya paket satma: onun ürünü top-up. Liste ve sohbet
|
||||
// geçmişi kalıcı; kredi yükleyince kaldığı yerden devam eder.
|
||||
return (
|
||||
<section className="mx-auto w-full max-w-2xl rounded-2xl border border-slate-200 bg-white p-8 text-center sm:p-12">
|
||||
<section className="relative isolate mx-auto w-full max-w-2xl overflow-hidden rounded-2xl border border-slate-200 bg-white p-8 text-center sm:p-12">
|
||||
<PikselZemin seed={23} />
|
||||
<Lock className="mx-auto size-8 text-slate-400" aria-hidden />
|
||||
<h1 className="mt-4 font-heading text-xl font-bold">
|
||||
Kredin bu liste için yetmiyor
|
||||
@@ -294,7 +296,8 @@ export function ListeUretici({
|
||||
|
||||
if (durum.ad === "hata") {
|
||||
return (
|
||||
<section className="mx-auto w-full max-w-2xl rounded-2xl border border-slate-200 bg-white p-8 text-center sm:p-12">
|
||||
<section className="relative isolate mx-auto w-full max-w-2xl overflow-hidden rounded-2xl border border-slate-200 bg-white p-8 text-center sm:p-12">
|
||||
<PikselZemin seed={23} />
|
||||
<h1 className="font-heading text-xl font-bold">Liste kurulamadı</h1>
|
||||
<p className="mx-auto mt-2 max-w-md text-sm text-slate-600">
|
||||
{durum.mesaj}
|
||||
@@ -344,7 +347,8 @@ function SunucuYokEkrani() {
|
||||
}
|
||||
|
||||
return (
|
||||
<section className="mx-auto w-full max-w-2xl rounded-2xl border border-slate-200 bg-white p-8 text-center sm:p-12">
|
||||
<section className="relative isolate mx-auto w-full max-w-2xl overflow-hidden rounded-2xl border border-slate-200 bg-white p-8 text-center sm:p-12">
|
||||
<PikselZemin seed={23} />
|
||||
<h1 className="font-heading text-xl font-bold">
|
||||
Listen hazır, sunucuya şu an ulaşamıyoruz
|
||||
</h1>
|
||||
@@ -375,7 +379,8 @@ function SunucuYokEkrani() {
|
||||
* "Tekrar dene" yok: tekrar taze requestId üretip ikinci üretimi başlatırdı. */
|
||||
function SuruyorEkrani() {
|
||||
return (
|
||||
<section className="mx-auto w-full max-w-2xl rounded-2xl border border-slate-200 bg-white p-8 text-center sm:p-12">
|
||||
<section className="relative isolate mx-auto w-full max-w-2xl overflow-hidden rounded-2xl border border-slate-200 bg-white p-8 text-center sm:p-12">
|
||||
<PikselZemin seed={23} />
|
||||
<h1 className="font-heading text-xl font-bold">Listen zaten hazırlanıyor</h1>
|
||||
<p className="mx-auto mt-2 max-w-md text-sm text-slate-600">
|
||||
Bunu başka bir sekmede başlatmışsın. İki kez kurmayalım — kredin bu
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
// ekranda. Harita ⇄ liste köprüsü (pinden satıra, satırdan haritaya) ve
|
||||
// paketsiz paywall kartları burada; veri çekimi sunucuda (page.tsx) kalır.
|
||||
|
||||
import { PikselZemin } from "@/components/piksel-zemin";
|
||||
import { useMemo, useRef, useState } from "react";
|
||||
import Link from "next/link";
|
||||
import {
|
||||
@@ -337,8 +338,9 @@ export function ListemGovde({
|
||||
|
||||
<section
|
||||
ref={kilitKartRef}
|
||||
className="overflow-hidden rounded-2xl border border-slate-200 bg-white shadow-sm"
|
||||
className="relative isolate overflow-hidden rounded-2xl border border-slate-200 bg-white shadow-sm"
|
||||
>
|
||||
<PikselZemin seed={59} />
|
||||
<div className="border-b border-slate-100 p-6">
|
||||
<h3 className="font-heading text-xl font-bold tracking-tight">
|
||||
Tablo ücretsiz.
|
||||
|
||||
@@ -19,6 +19,7 @@ import { raporMaskele, ACIK_SATIR } from "@/lib/rapor-maske";
|
||||
import type { Mesaj } from "./sohbet-client";
|
||||
import { ListemGovde } from "./listem-govde";
|
||||
import { ListemBosCta } from "./listem-bos-cta";
|
||||
import { PikselZemin } from "@/components/piksel-zemin";
|
||||
import { ListeUretici } from "./liste-uretici";
|
||||
import { UretimBasladiOlayi } from "./uretim-basladi-olayi";
|
||||
|
||||
@@ -65,7 +66,8 @@ export async function ListemIcerik({
|
||||
|
||||
if (!raporVar) {
|
||||
const bosDurum = (
|
||||
<section className="mx-auto flex max-w-2xl flex-col items-center px-4 py-16 text-center">
|
||||
<section className="relative isolate mx-auto flex max-w-2xl flex-col items-center overflow-hidden px-4 py-16 text-center">
|
||||
<PikselZemin seed={29} />
|
||||
<Sparkles className="size-10 text-primary" aria-hidden />
|
||||
<h1 className="mt-4 font-heading text-2xl font-bold">
|
||||
Henüz Yapay Zeka listen yok
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
// varsa /api/tadimlik'ten kategoriye özel satır çekilip yerinde değiştirilir
|
||||
// (seçim sunucuda kalır). Havuzda içerik yoksa hiç render edilmez.
|
||||
|
||||
import { PikselZemin } from "@/components/piksel-zemin";
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import Link from "next/link";
|
||||
import { ArrowRight } from "lucide-react";
|
||||
@@ -150,7 +151,8 @@ export function TadimlikSatiri({
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="mt-6 rounded-2xl border border-slate-200 bg-white p-4 shadow-sm sm:p-6">
|
||||
<div className="relative isolate mt-6 overflow-hidden rounded-2xl border border-slate-200 bg-white p-4 shadow-sm sm:p-6">
|
||||
<PikselZemin seed={31} />
|
||||
{/* Rapor listesinin satırıyla aynı düzen (§4.15): ad sarar,
|
||||
üniversite adı altında, taban sıra sağda iri. */}
|
||||
<div className="flex items-start gap-3">
|
||||
|
||||
@@ -23,6 +23,7 @@ import { authClient } from "@/lib/auth-client";
|
||||
import { olay, siraKovasi } from "@/lib/analitik";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { CtaBandi } from "@/components/cta-bandi";
|
||||
import { PikselZemin } from "@/components/piksel-zemin";
|
||||
import { onbellekliJsonGetir } from "@/lib/istek-cache";
|
||||
import { useTercihProfili } from "@/features/liste/hooks/use-tercih-profili";
|
||||
import type { SihirbazFacetleri } from "@/types/yokatlas";
|
||||
@@ -373,10 +374,11 @@ export function CtaSiraForm({
|
||||
<section
|
||||
aria-labelledby={baslikId}
|
||||
className={cn(
|
||||
"rounded-2xl border p-4 transition-colors duration-200 sm:p-5",
|
||||
"relative isolate overflow-hidden rounded-2xl border p-4 transition-colors duration-200 sm:p-5",
|
||||
profil ? "border-primary/20 bg-primary/5" : "border-slate-200 bg-white",
|
||||
)}
|
||||
>
|
||||
<PikselZemin seed={53} />
|
||||
<div className="grid">
|
||||
<div
|
||||
ref={profil ? undefined : formRef}
|
||||
|
||||
@@ -8,6 +8,7 @@ import { animate } from "motion/mini";
|
||||
import { useReducedMotion } from "motion/react";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { CtaBandi } from "@/components/cta-bandi";
|
||||
import { PikselZemin } from "@/components/piksel-zemin";
|
||||
import { useGorunumOlayi } from "@/components/use-gorunum-olayi";
|
||||
import { olay, olayBirKez, siraKovasi } from "@/lib/analitik";
|
||||
import type { SihirbazFacetleri } from "@/types/yokatlas";
|
||||
@@ -262,7 +263,8 @@ export function SihirbazBolumu({
|
||||
edilmez; panel yalnızca funnel CTA'larını gösterir, üretim ve
|
||||
listenin kendisi /listem'de yaşar. */}
|
||||
{raporVar ? (
|
||||
<section className="mt-16 rounded-2xl border border-slate-200 bg-white p-8 text-center sm:p-12">
|
||||
<section className="relative isolate mt-16 overflow-hidden rounded-2xl border border-slate-200 bg-white p-8 text-center sm:p-12">
|
||||
<PikselZemin seed={21} />
|
||||
<h2 className="font-heading text-2xl font-bold sm:text-3xl">
|
||||
24 tercihlik listen hazır
|
||||
</h2>
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
// sayfayı tazele (URL değişmez); yoksa kapıyı aç. Sıra bilgisi localStorage'daki
|
||||
// TercihProfili ile tüm uygulamada ortak, sunucu tablosu çerezden okur.
|
||||
|
||||
import { PikselZemin } from "@/components/piksel-zemin";
|
||||
import { useEffect } from "react";
|
||||
import { useRouter } from "next/navigation";
|
||||
import Link from "next/link";
|
||||
@@ -42,7 +43,8 @@ export function SiraGerekli() {
|
||||
}
|
||||
|
||||
return (
|
||||
<main className="mx-auto flex max-w-2xl flex-col items-center px-4 py-24 text-center">
|
||||
<main className="relative isolate mx-auto flex max-w-2xl flex-col items-center overflow-hidden px-4 py-24 text-center">
|
||||
<PikselZemin seed={37} />
|
||||
<h1 className="font-heading text-3xl font-bold text-balance text-slate-900 sm:text-4xl">
|
||||
Önce sıralamanı gir
|
||||
</h1>
|
||||
|
||||
Reference in New Issue
Block a user