Files
animexe/resources/views/frontend/anime.blade.php
T
2026-07-14 00:01:48 +03:00

1338 lines
66 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
@extends('frontend.layouts.app')
@php
$__izleLabel = $anime->type === 'movie' ? 'Filmi İzle' : 'İzle';
$__animeSeoTitle = $anime->title . ' ' . $__izleLabel . ' - Türkçe Altyazılı | Animexe';
$__animeSeoDesc = $anime->title . ' ' . $__izleLabel
. ' — Türkçe altyazılı ve dublajlı, ücretsiz HD kalitede Animexe\'de.'
. ($anime->description ? ' ' . Str::limit(strip_tags($anime->description), 80) : '');
$__animeOgImg = $anime->bannerUrl ?? $anime->coverUrl ?? url('/logo.jpg');
$__animeCanon = rtrim(\App\Models\Setting::get('seo_canonical_domain', config('app.url')), '/') . route('anime.show', $anime->slug, false);
$__animeType = $anime->type === 'movie' ? 'Movie' : 'TVSeries';
$__animeGenres = $anime->genres->pluck('name')->implode(', ');
$__domain = rtrim(\App\Models\Setting::get('seo_canonical_domain', config('app.url')), '/');
// Auto-FAQ: DB verilerinden kurallı sorular
$__faqItems = [];
$__faqItems[] = [
'q' => $anime->title . ' nerede izlenir?',
'a' => $anime->title . ', Animexe\'de Türkçe altyazılı ve Türkçe dublajlı olarak ücretsiz HD kalitede izlenebilir.',
];
$epCount = $anime->episode_count ?: $anime->episodes->count();
if ($epCount > 0) {
$__faqItems[] = [
'q' => $anime->title . ' kaç bölüm?',
'a' => $anime->type === 'movie'
? $anime->title . ' tek bölümlük bir anime filmidir.'
: $anime->title . ' şu an Animexe\'de ' . $epCount . ' bölümüyle yayında.',
];
}
if ($anime->release_year) {
$__faqItems[] = [
'q' => $anime->title . ' ne zaman çıktı?',
'a' => $anime->title . ', ' . $anime->release_year . ' yılında yayımlanmaya başladı.',
];
}
if ($anime->genres->count()) {
$__faqItems[] = [
'q' => $anime->title . ' hangi türde?',
'a' => $anime->title . ', ' . $__animeGenres . ' türlerinde bir anime' . ($anime->type === 'movie' ? ' filmidir.' : ' dizisidir.'),
];
}
if ($anime->rating) {
$__faqItems[] = [
'q' => $anime->title . ' puanı nedir?',
'a' => $anime->title . '\' un Animexe kullanıcı puanı 10 üzerinden ' . number_format($anime->rating,1) . '\'dir.',
];
}
$statusText = match($anime->status ?? '') {
'ongoing' => $anime->title . ' devam eden bir anime olup yeni bölümleri Animexe\'de yayımlanmaktadır.',
'completed' => $anime->title . ' tamamlanmış bir anime olup tüm bölümleri Animexe\'de mevcuttur.',
default => null,
};
if ($statusText) {
$__faqItems[] = ['q' => $anime->title . ' bitti mi, devam ediyor mu?', 'a' => $statusText];
}
if ($anime->studio) {
$__faqItems[] = [
'q' => $anime->title . '\'u hangi stüdyo yaptı?',
'a' => $anime->title . ', ' . $anime->studio . ' stüdyosu tarafından üretilmiştir.',
];
}
@endphp
@section('title', $__animeSeoTitle)
@section('meta_description', $__animeSeoDesc)
@section('meta_keywords', $anime->title . ' izle, ' . $anime->title . ' türkçe izle, ' . ($anime->title_en ? $anime->title_en . ' izle, ' : '') . 'anime izle, türkçe anime, ' . $__animeGenres . ' anime izle')
@section('og_type', $anime->type === 'movie' ? 'video.movie' : 'video.tv_show')
@section('og_title', $__animeSeoTitle)
@section('og_description', $__animeSeoDesc)
@section('og_image', $__animeOgImg)
@section('og_image_width', '1280')
@section('og_image_height', '720')
@section('canonical', $__animeCanon)
{{-- LCP: Cover görseli preload --}}
@section('preload')
@if($anime->bannerUrl ?? $anime->coverUrl)
<link rel="preload" as="image" href="{{ $anime->bannerUrl ?? $anime->coverUrl }}" fetchpriority="high">
@endif
@endsection
{{-- JSON-LD schemas --}}
@section('schema')
@if((\App\Models\Setting::get('seo_enable_schema','1')) === '1')
{{-- 1. TVSeries / Movie --}}
<script type="application/ld+json">
{
"@@context":"https://schema.org",
"@@type":"{{ $__animeType }}",
"name":"{{ addslashes($anime->title) }}",
@if($anime->title_en)"alternateName":"{{ addslashes($anime->title_en) }}",@endif
"url":"{{ $__animeCanon }}",
"description":"{{ addslashes(Str::limit(strip_tags($anime->description ?? ''), 300)) }}",
@if($anime->release_year)"startDate":"{{ $anime->release_year }}",@endif
@if($anime->rating)"aggregateRating":{"@@type":"AggregateRating","ratingValue":"{{ number_format($anime->rating,1) }}","bestRating":"10","worstRating":"1","ratingCount":"{{ max(1,$anime->episodes->count()) }}"},@endif
@if($anime->coverUrl)"image":{"@@type":"ImageObject","url":"{{ $anime->coverUrl }}","width":460,"height":650},@endif
@if($anime->studio)"productionCompany":{"@@type":"Organization","name":"{{ addslashes($anime->studio) }}"},@endif
@if($anime->genres->count())"genre":[{{ $anime->genres->map(fn($g)=>'"'.addslashes($g->name).'"')->implode(',') }}],@endif
"potentialAction":{"@@type":"WatchAction","target":{"@@type":"EntryPoint","urlTemplate":"{{ $__animeCanon }}","inLanguage":"tr","actionPlatform":["http://schema.org/DesktopWebPlatform","http://schema.org/MobileWebPlatform"]}},
"speakable":{"@@type":"SpeakableSpecification","xpath":["/html/head/title","/html/body//h1","/html/body//*[contains(@class,'ah-desc')]"]},
"inLanguage":"ja",
"countryOfOrigin":{"@@type":"Country","name":"Japan"},
"offers":{"@@type":"Offer","price":"0","priceCurrency":"TRY","availability":"https://schema.org/InStock","url":"{{ $__animeCanon }}"}
}
</script>
{{-- 2. VideoObject --}}
<script type="application/ld+json">
{
"@@context":"https://schema.org",
"@@type":"VideoObject",
"name":"{{ addslashes($anime->title) }} {{ $__izleLabel }} - Türkçe Altyazılı",
"description":"{{ addslashes(Str::limit(strip_tags($anime->description ?? $__animeSeoDesc), 300)) }}",
"thumbnailUrl":"{{ $anime->coverUrl ?? $anime->bannerUrl ?? url('/logo.jpg') }}",
"uploadDate":"{{ ($anime->created_at ?? now())->toIso8601String() }}",
"contentUrl":"{{ $__animeCanon }}",
"embedUrl":"{{ $__animeCanon }}",
"inLanguage":"tr",
@if($anime->rating)"aggregateRating":{"@@type":"AggregateRating","ratingValue":"{{ number_format($anime->rating,1) }}","bestRating":"10","worstRating":"1","ratingCount":"{{ max(1,$anime->episodes->count()) }}"},@endif
"publisher":{"@@type":"Organization","name":"Animexe","logo":{"@@type":"ImageObject","url":"{{ url('/logo.jpg') }}"}}
}
</script>
{{-- 3. FAQPage (auto-generated) --}}
@if(count($__faqItems) > 0)
<script type="application/ld+json">
{
"@@context":"https://schema.org",
"@@type":"FAQPage",
"mainEntity":[
@foreach($__faqItems as $i => $fq)
{"@@type":"Question","name":"{{ addslashes($fq['q']) }}","acceptedAnswer":{"@@type":"Answer","text":"{{ addslashes($fq['a']) }}"}}{{ $i < count($__faqItems)-1 ? ',' : '' }}
@endforeach
]
}
</script>
@endif
{{-- 4. Episode ItemList --}}
@php $__epList = $anime->episodes->take(20); @endphp
@if($__epList->count() > 0 && $anime->type !== 'movie')
<script type="application/ld+json">
{
"@@context":"https://schema.org",
"@@type":"ItemList",
"name":"{{ addslashes($anime->title) }} Bölüm Listesi",
"description":"{{ addslashes($anime->title) }} tüm bölümleri Animexe'de Türkçe altyazılı izle",
"numberOfItems":{{ $__epList->count() }},
"itemListElement":[
@foreach($__epList as $i => $__ep)
@php
$__epSeason = $__ep->season_id ? $anime->seasons->firstWhere('id',$__ep->season_id) : null;
$__epSNum = $__epSeason->season_number ?? 1;
@endphp
{"@@type":"ListItem","position":{{ $i+1 }},"name":"{{ addslashes($anime->title) }} {{ $__epSNum }}. Sezon {{ $__ep->episode_number }}. Bölüm İzle","url":"{{ $__domain }}{{ route('watch',[$anime->slug,$__epSNum,$__ep->episode_number],false) }}"}{{ $i < $__epList->count()-1 ? ',' : '' }}
@endforeach
]
}
</script>
@endif
{{-- 5. BreadcrumbList --}}
@if((\App\Models\Setting::get('seo_enable_breadcrumb','1')) === '1')
<script type="application/ld+json">
{
"@@context":"https://schema.org",
"@@type":"BreadcrumbList",
"itemListElement":[
{"@@type":"ListItem","position":1,"name":"Ana Sayfa","item":"{{ $__domain }}/"},
{"@@type":"ListItem","position":2,"name":"Anime","item":"{{ $__domain }}/search"},
{"@@type":"ListItem","position":3,"name":"{{ addslashes($anime->title) }} {{ $__izleLabel }}","item":"{{ $__animeCanon }}"}
]
}
</script>
@endif
@endif
@endsection
@push('styles')
<style>
/* ═══════════════════════════════════════════════════
ANIME DETAIL PAGE — REDESIGN
═══════════════════════════════════════════════════ */
/* ── Hero ──────────────────────────────────────────── */
.ah{position:relative;overflow:hidden;background:#05050e}
.ah-bg{
position:absolute;inset:0;
background-size:cover;background-position:center 25%;
transform:scale(1.05);
filter:blur(2px) saturate(1.2) brightness(.55);
transition:transform 12s ease;
}
.ah-bg.loaded{transform:scale(1)}
.ah-overlay{
position:absolute;inset:0;
background:
linear-gradient(105deg, rgba(5,5,14,.97) 0%, rgba(5,5,14,.82) 42%, rgba(5,5,14,.25) 100%),
linear-gradient(to top, #05050e 0%, rgba(5,5,14,.6) 35%, transparent 65%);
}
.ah-noise{
position:absolute;inset:0;
background-image:url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='.04'/%3E%3C/svg%3E");
opacity:.6;pointer-events:none;mix-blend-mode:overlay;
}
.ah-inner{
position:relative;z-index:2;
max-width:1300px;margin:0 auto;
padding:clamp(60px,10vw,100px) clamp(20px,5vw,64px) clamp(40px,6vw,72px);
display:grid;
grid-template-columns:1fr clamp(180px,20vw,260px);
gap:clamp(24px,4vw,56px);
align-items:end;
}
/* ── Poster ─────────────────────────────────────────── */
.ah-poster{
position:relative;
border-radius:14px;overflow:hidden;
box-shadow:0 40px 80px rgba(0,0,0,.8),0 0 0 1px rgba(255,255,255,.08),0 0 60px rgba(0,245,255,.08);
transform:translateY(30px);
transition:transform .4s ease,box-shadow .4s ease;
align-self:flex-end;
}
.ah-poster:hover{transform:translateY(24px);box-shadow:0 44px 88px rgba(0,0,0,.85),0 0 0 1px rgba(0,245,255,.2),0 0 80px rgba(255,45,125,.12)}
.ah-poster img{width:100%;display:block;aspect-ratio:2/3;object-fit:cover}
.ah-poster-ph{aspect-ratio:2/3;display:flex;align-items:center;justify-content:center;color:rgba(255,255,255,.2);font-size:3rem;background:rgba(255,255,255,.04)}
.ah-poster-score{
position:absolute;bottom:0;left:0;right:0;
padding:20px 12px 10px;
background:linear-gradient(to top,rgba(0,0,0,.9),transparent);
text-align:center;
font-size:.95rem;font-weight:800;color:#fbbf24;
letter-spacing:.03em;
}
.ah-poster-score i{font-size:.75rem;margin-right:3px}
/* ── Meta ──────────────────────────────────────────── */
.ah-meta{display:flex;flex-direction:column;gap:0;padding-bottom:4px}
.ah-badges{display:flex;flex-wrap:wrap;gap:6px;margin-bottom:14px}
.badge{padding:4px 12px;border-radius:20px;font-size:.7rem;font-weight:700;border:1px solid transparent;letter-spacing:.04em;text-transform:uppercase}
.b-type{background:rgba(147,51,234,.18);border-color:rgba(147,51,234,.45);color:#c084fc}
.b-on{background:rgba(34,197,94,.12);border-color:rgba(34,197,94,.35);color:#4ade80}
.b-done{background:rgba(59,130,246,.12);border-color:rgba(59,130,246,.35);color:#60a5fa}
.b-up{background:rgba(245,158,11,.12);border-color:rgba(245,158,11,.35);color:#fbbf24}
.b-yr{background:rgba(255,255,255,.06);border-color:rgba(255,255,255,.12);color:rgba(255,255,255,.5)}
.ah-title{
font-family:var(--font-display);
font-size:clamp(1.9rem,5vw,4rem);
font-weight:900;line-height:1.04;letter-spacing:-.02em;margin-bottom:10px;
background:linear-gradient(130deg,#fff 0%,rgba(255,255,255,.92) 55%,rgba(200,220,255,.75) 100%);
-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text;
filter:drop-shadow(0 4px 32px rgba(255,255,255,.1));
}
.ah-sub{
color:rgba(255,255,255,.42);font-size:.88rem;margin-bottom:16px;font-weight:400;
display:flex;align-items:center;gap:8px;flex-wrap:wrap;
}
.ah-sub-sep{width:3px;height:3px;border-radius:50%;background:rgba(255,255,255,.25);flex-shrink:0}
.ah-inline-score{
display:inline-flex;align-items:center;gap:5px;
background:rgba(251,191,36,.12);border:1px solid rgba(251,191,36,.28);
padding:3px 11px;border-radius:20px;
color:#fbbf24;font-weight:800;font-size:.82rem;
}
.ah-genres{display:flex;flex-wrap:wrap;gap:6px;margin-bottom:20px}
.ah-genre-chip{
padding:5px 13px;border-radius:20px;
background:rgba(255,255,255,.05);border:1px solid rgba(255,255,255,.1);
color:rgba(255,255,255,.55);font-size:.74rem;font-weight:500;
transition:all .15s;text-decoration:none;
}
.ah-genre-chip:hover{background:rgba(0,245,255,.1);border-color:rgba(0,245,255,.3);color:var(--accent2)}
/* ── Action buttons ────────────────────────────────── */
.ah-actions{display:flex;gap:10px;flex-wrap:wrap;margin-bottom:16px;align-items:center}
.ah-play{
display:inline-flex;align-items:center;gap:10px;
padding:16px 34px;border-radius:14px;
background:linear-gradient(135deg,var(--accent) 0%,var(--accent3) 100%);
color:#fff;font-size:.96rem;font-weight:900;border:none;cursor:pointer;text-decoration:none;
transition:transform .15s,box-shadow .2s,filter .15s;
box-shadow:0 0 44px rgba(255,45,125,.48),0 8px 24px rgba(0,0,0,.45);
letter-spacing:.03em;
position:relative;overflow:hidden;
}
.ah-play::before{
content:'';position:absolute;inset:0;
background:linear-gradient(135deg,transparent 40%,rgba(255,255,255,.12) 50%,transparent 60%);
transform:translateX(-100%) skewX(-15deg);transition:transform .5s ease;
}
.ah-play:hover::before{transform:translateX(200%) skewX(-15deg)}
.ah-play:hover{transform:translateY(-3px);filter:brightness(1.08);box-shadow:0 0 60px rgba(255,45,125,.62),0 10px 32px rgba(0,0,0,.5)}
.ah-play i{font-size:1.15rem}
.ah-btn{
display:inline-flex;align-items:center;gap:7px;
padding:13px 20px;border-radius:14px;
background:rgba(255,255,255,.07);backdrop-filter:blur(12px);
border:1px solid rgba(255,255,255,.13);
color:rgba(255,255,255,.8);font-size:.84rem;font-weight:600;
transition:all .18s;text-decoration:none;cursor:pointer;font-family:inherit;
white-space:nowrap;
}
.ah-btn:hover{background:rgba(0,245,255,.1);border-color:rgba(0,245,255,.3);color:var(--accent2)}
.ah-btn.active-wl{border-color:rgba(255,45,125,.4);color:var(--accent)}
.ah-btn.active-fl{border-color:rgba(0,245,255,.4);color:var(--accent2)}
/* ── User rating row ────────────────────────────────── */
.ah-rating{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.ah-rating-lbl{font-size:.76rem;color:rgba(255,255,255,.4);font-weight:500;white-space:nowrap}
.star-btn{
width:28px;height:28px;border-radius:8px;
border:1px solid rgba(255,255,255,.1);background:rgba(255,255,255,.05);
color:rgba(255,255,255,.35);font-size:.72rem;cursor:pointer;
transition:all .12s;padding:0;font-family:inherit;
}
.star-btn:hover,.star-btn.on{
background:linear-gradient(135deg,var(--accent),var(--accent3));
border-color:transparent;color:#fff;
box-shadow:0 0 12px rgba(255,45,125,.4);
}
/* ── Stats strip ────────────────────────────────────── */
.a-body{max-width:1300px;margin:0 auto;padding:0 clamp(14px,4vw,28px) 60px}
.a-stats-strip{
display:flex;gap:10px;
margin-top:clamp(40px,6vw,60px);
margin-bottom:32px;
overflow-x:auto;
scrollbar-width:none;
-webkit-overflow-scrolling:touch;
padding-bottom:4px;
}
.a-stats-strip::-webkit-scrollbar{display:none}
.a-stat-card{
display:flex;align-items:center;gap:12px;
background:rgba(255,255,255,.04);
border:1px solid rgba(255,255,255,.07);
border-radius:12px;padding:14px 20px;
flex-shrink:0;
transition:border-color .18s,background .18s;
}
.a-stat-card:hover{background:rgba(255,255,255,.06);border-color:rgba(255,255,255,.12)}
.a-stat-icon{
width:36px;height:36px;border-radius:10px;flex-shrink:0;
display:flex;align-items:center;justify-content:center;font-size:.9rem;
}
.a-stat-icon.gold{background:rgba(251,191,36,.12);color:#fbbf24}
.a-stat-icon.cyan{background:rgba(0,245,255,.1);color:var(--accent2)}
.a-stat-icon.pink{background:rgba(255,45,125,.1);color:var(--accent)}
.a-stat-icon.purple{background:rgba(147,51,234,.12);color:#c084fc}
.a-stat-icon.muted{background:rgba(255,255,255,.06);color:rgba(255,255,255,.4)}
.a-stat-info{min-width:0;flex:1}
.a-stat-val{font-size:.9rem;font-weight:800;color:var(--text);line-height:1.2}
.a-stat-lbl{font-size:.62rem;text-transform:uppercase;letter-spacing:.08em;color:var(--text3);font-weight:600;margin-top:2px}
/* ── Description ────────────────────────────────────── */
.a-desc-wrap{
margin-bottom:32px;
padding:24px;
background:rgba(255,255,255,.025);
border:1px solid rgba(255,255,255,.06);
border-radius:16px;
}
.a-desc{color:rgba(255,255,255,.65);font-size:.92rem;line-height:1.8}
.a-desc.clamped{display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden}
.a-desc-btn{
background:none;border:none;color:var(--accent2);font-size:.8rem;cursor:pointer;
margin-top:10px;padding:0;font-family:inherit;display:inline-flex;align-items:center;gap:5px;
opacity:.75;transition:opacity .15s;
}
.a-desc-btn:hover{opacity:1}
/* ── Tabs ───────────────────────────────────────────── */
.a-tabs{
display:flex;gap:4px;margin-bottom:24px;
background:rgba(255,255,255,.03);
border:1px solid rgba(255,255,255,.07);
border-radius:14px;padding:5px;
overflow-x:auto;scrollbar-width:none;
}
.a-tabs::-webkit-scrollbar{display:none}
.a-tab{
padding:11px 22px;background:none;border:none;border-radius:10px;
color:rgba(255,255,255,.42);font-size:.88rem;font-weight:700;
cursor:pointer;font-family:inherit;transition:all .15s;
white-space:nowrap;flex-shrink:0;display:flex;align-items:center;gap:7px;
}
.a-tab:hover{color:rgba(255,255,255,.72);background:rgba(255,255,255,.06)}
.a-tab.on{
background:rgba(0,245,255,.12);color:var(--accent2);
box-shadow:inset 0 0 0 1px rgba(0,245,255,.25),0 0 20px rgba(0,245,255,.06);
}
.a-tab.on i{filter:drop-shadow(0 0 8px rgba(0,245,255,.6))}
.tab-pane{display:none}
.tab-pane.on{display:block}
/* ── Season selector ────────────────────────────────── */
.season-tabs{display:flex;gap:7px;flex-wrap:wrap;margin-bottom:20px}
.s-btn{
padding:7px 18px;border-radius:10px;
background:rgba(255,255,255,.05);border:1px solid rgba(255,255,255,.08);
color:rgba(255,255,255,.5);font-size:.8rem;font-weight:600;
cursor:pointer;font-family:inherit;transition:all .15s;
}
.s-btn:hover{border-color:rgba(0,245,255,.25);color:var(--accent2)}
.s-btn.on{
background:rgba(0,245,255,.1);border-color:rgba(0,245,255,.3);color:var(--accent2);
}
/* ── Episode list ───────────────────────────────────── */
.ep-list{display:flex;flex-direction:column;gap:8px}
.ep-card{
display:flex;gap:14px;
background:rgba(255,255,255,.03);
border:1px solid rgba(255,255,255,.07);
border-radius:14px;padding:12px;
cursor:pointer;text-decoration:none;color:inherit;
transition:all .18s;
}
.ep-card:hover{
background:rgba(0,245,255,.05);
border-color:rgba(0,245,255,.2);
transform:translateX(3px);
}
@media(hover:none){
.ep-card:hover{transform:none}
.ep-card:active{background:rgba(0,245,255,.07);border-color:rgba(0,245,255,.2)}
}
.ep-card-thumb{
flex-shrink:0;width:130px;border-radius:9px;overflow:hidden;
background:rgba(255,255,255,.06);position:relative;aspect-ratio:16/9;
align-self:flex-start;
}
@media(max-width:500px){.ep-card-thumb{width:100px}}
.ep-card-thumb img{width:100%;height:100%;object-fit:cover;display:block;transition:transform .3s}
.ep-card:hover .ep-card-thumb img{transform:scale(1.06)}
.ep-card-thumb .no-thumb{width:100%;height:100%;display:flex;align-items:center;justify-content:center;color:rgba(255,255,255,.2);font-size:1.5rem}
.ep-play-overlay{
position:absolute;inset:0;background:rgba(0,0,0,.45);
display:flex;align-items:center;justify-content:center;
opacity:0;transition:opacity .18s;
}
.ep-card:hover .ep-play-overlay{opacity:1}
.ep-play-overlay i{font-size:1.4rem;color:#fff;filter:drop-shadow(0 0 10px rgba(0,245,255,.7))}
.ep-num-badge{
position:absolute;top:6px;left:6px;
background:rgba(0,0,0,.75);backdrop-filter:blur(4px);
color:rgba(255,255,255,.8);font-size:.6rem;font-weight:700;
padding:2px 7px;border-radius:5px;letter-spacing:.04em;
}
.ep-card-body{flex:1;min-width:0;display:flex;flex-direction:column;justify-content:center;gap:4px;padding:2px 0}
.ep-card-num{font-size:.67rem;color:var(--accent2);font-weight:700;letter-spacing:.08em;text-transform:uppercase}
.ep-card-title{font-size:.88rem;font-weight:700;color:var(--text);display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;line-height:1.45}
.ep-card-meta{font-size:.72rem;color:rgba(255,255,255,.3);display:flex;align-items:center;gap:10px;flex-wrap:wrap}
/* ── Info table ─────────────────────────────────────── */
.info-table{width:100%;border-collapse:collapse}
.info-table tr{border-bottom:1px solid rgba(255,255,255,.05)}
.info-table tr:last-child{border-bottom:none}
.info-table td{padding:13px 0;font-size:.88rem;vertical-align:top}
.info-table td:first-child{color:rgba(255,255,255,.35);width:140px;font-weight:600;font-size:.78rem;text-transform:uppercase;letter-spacing:.08em;padding-top:16px}
/* ── Related / AI grid ──────────────────────────────── */
.rel-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(130px,1fr));gap:12px}
.ah-genre-chip{padding:5px 13px;border-radius:20px;background:rgba(255,255,255,.05);border:1px solid rgba(255,255,255,.1);color:rgba(255,255,255,.55);font-size:.74rem;font-weight:500;transition:all .15s;text-decoration:none}
/* ── Watchlist dropdown ─────────────────────────────── */
.wl-opt{display:flex;align-items:center;gap:8px;width:100%;padding:8px 11px;border-radius:8px;border:none;background:transparent;color:rgba(255,255,255,.6);font-size:.82rem;cursor:pointer;transition:background .15s}
.wl-opt:hover,.wl-opt-on{background:rgba(255,255,255,.07);color:#fff}
.wl-opt-on{color:var(--accent)}
/* ── Login prompt modal ─────────────────────────────── */
.login-prompt-overlay{position:fixed;inset:0;background:rgba(0,0,0,.75);z-index:9999;display:flex;align-items:center;justify-content:center;backdrop-filter:blur(8px)}
.login-prompt-box{background:#0e0e1a;border:1px solid rgba(255,255,255,.1);border-radius:20px;padding:36px 30px;text-align:center;max-width:340px;width:90%;box-shadow:0 32px 80px rgba(0,0,0,.6)}
.login-prompt-box h3{color:#fff;font-size:1.1rem;margin-bottom:8px}
.login-prompt-box p{color:rgba(255,255,255,.45);font-size:.85rem;margin-bottom:20px}
.lp-btn{display:inline-block;padding:10px 26px;border-radius:12px;font-size:.88rem;font-weight:700;text-decoration:none}
.lp-btn-primary{background:linear-gradient(135deg,var(--accent),var(--accent3));color:#fff;margin-right:8px}
.lp-btn-secondary{background:rgba(255,255,255,.08);color:rgba(255,255,255,.6);border:1px solid rgba(255,255,255,.1)}
/* ── Achievement popup ──────────────────────────────── */
.ach-popup{position:fixed;bottom:24px;right:24px;background:#0e0e1a;border:1px solid rgba(255,255,255,.1);border-radius:14px;padding:14px 18px;display:flex;align-items:center;gap:12px;z-index:9998;animation:slideUp .3s ease;box-shadow:0 12px 40px rgba(0,0,0,.6)}
@keyframes slideUp{from{transform:translateY(20px);opacity:0}to{transform:translateY(0);opacity:1}}
.ach-popup .ach-icon{font-size:1.8rem}
.ach-popup .ach-title{font-size:.75rem;color:rgba(255,255,255,.4)}
.ach-popup .ach-name{font-size:.9rem;font-weight:700;color:#fff}
/* ══ RESPONSIVE ═══════════════════════════════════════ */
@media(max-width:900px){
.ah-inner{grid-template-columns:1fr clamp(140px,18vw,200px);gap:20px}
}
/* Tablet/large phone — remove poster, stack cleanly */
@media(max-width:700px){
.ah-inner{
grid-template-columns:1fr;
padding:clamp(24px,8vw,48px) 16px 28px;
}
.ah-poster{display:none}
.ah-title{font-size:clamp(1.3rem,5.5vw,1.9rem)}
.ah-play{padding:12px 22px;font-size:.86rem}
.ah-btn{padding:11px 16px;font-size:.8rem}
.a-stats-strip{gap:8px}
.a-stat-card{padding:11px 15px;gap:9px}
.a-stat-icon{width:30px;height:30px;font-size:.78rem}
.a-stat-val{font-size:.88rem}
}
/* Phone — stacked hero with top banner visual */
@media(max-width:480px){
.ah{padding-top:0}
.ah-bg{filter:blur(3px) saturate(1.1) brightness(.45)}
.ah-overlay{background:linear-gradient(to bottom,rgba(5,5,14,.4) 0%,rgba(5,5,14,.8) 50%,#05050e 85%)}
/* 180px was too high — banner is visible but content was pushed off-screen */
.ah-inner{padding:clamp(80px,20vw,130px) 14px 24px}
.ah-badges{margin-bottom:10px}
.ah-sub{margin-bottom:12px}
.ah-genres{margin-bottom:14px}
.ah-actions{gap:8px}
.ah-play{width:100%;justify-content:center}
.ah-btn{flex:1;justify-content:center}
.a-stats-strip{margin-top:24px}
.ep-card-thumb{width:90px}
.a-tabs{border-radius:12px}
.a-tab{padding:8px 13px;font-size:.78rem}
/* Larger star touch targets on mobile (was 28px, iOS HIG min 44pt) */
.star-btn{width:36px;height:36px;font-size:.8rem;border-radius:10px}
.ah-rating{gap:6px}
}
@media(max-width:400px){
/* Info table: narrow label column on very small phones */
.info-table td:first-child{width:100px;font-size:.74rem}
/* Achievement popup: stretch edge-to-edge instead of overflowing */
.ach-popup{left:10px;right:10px;bottom:14px;max-width:none}
}
/* ═══════════════════════════════════════════════════
ANIME PAGE PREMIUM ENHANCEMENTS
═══════════════════════════════════════════════════ */
/* Hero entrance animations */
@keyframes ah-fade-up{
from{opacity:0;transform:translateY(22px)}
to{opacity:1;transform:none}
}
.ah-badges{animation:ah-fade-up .5s cubic-bezier(.22,1,.36,1) .15s both}
.ah-title{animation:ah-fade-up .6s cubic-bezier(.22,1,.36,1) .25s both}
.ah-sub{animation:ah-fade-up .5s cubic-bezier(.22,1,.36,1) .35s both}
.ah-genres{animation:ah-fade-up .5s cubic-bezier(.22,1,.36,1) .4s both}
.ah-actions{animation:ah-fade-up .5s cubic-bezier(.22,1,.36,1) .5s both}
.ah-poster{animation:ah-fade-up .7s cubic-bezier(.22,1,.36,1) .3s both}
/* Title gradient glow */
.ah-title{
background:linear-gradient(135deg,#fff 0%,rgba(255,255,255,.88) 60%,rgba(240,244,255,.65) 100%);
-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text;
}
/* Poster reflection effect */
.ah-poster::after{
content:'';position:absolute;bottom:0;left:0;right:0;height:60%;
background:linear-gradient(to top,rgba(5,5,14,.85),transparent);
pointer-events:none;
}
.ah-poster::before{
content:'';position:absolute;inset:0;
background:linear-gradient(115deg,transparent 35%,rgba(255,255,255,.06) 50%,transparent 65%);
z-index:3;transform:translateX(-100%);
transition:transform .7s ease;
}
.ah-poster:hover::before{transform:translateX(200%)}
/* Stats strip counter anim */
@keyframes stat-pop{
from{opacity:0;transform:scale(.9) translateY(8px)}
to{opacity:1;transform:none}
}
.a-stat-card{animation:stat-pop .45s cubic-bezier(.22,1,.36,1) both}
.a-stat-card:nth-child(1){animation-delay:.1s}
.a-stat-card:nth-child(2){animation-delay:.16s}
.a-stat-card:nth-child(3){animation-delay:.22s}
.a-stat-card:nth-child(4){animation-delay:.28s}
.a-stat-card:nth-child(5){animation-delay:.34s}
.a-stat-card:nth-child(6){animation-delay:.4s}
/* Stats strip icon glow on hover */
.a-stat-card:hover .a-stat-icon.gold{box-shadow:0 0 20px rgba(251,191,36,.25)}
.a-stat-card:hover .a-stat-icon.cyan{box-shadow:0 0 20px rgba(0,245,255,.2)}
.a-stat-card:hover .a-stat-icon.pink{box-shadow:0 0 20px rgba(255,45,125,.2)}
.a-stat-card:hover .a-stat-icon.purple{box-shadow:0 0 20px rgba(184,77,255,.2)}
/* Episode card enhanced */
.ep-card{
border:1px solid rgba(255,255,255,.06);
position:relative;overflow:hidden;
}
.ep-card::before{
content:'';position:absolute;left:0;top:0;bottom:0;width:2px;
background:linear-gradient(180deg,var(--accent2),var(--accent));
transform:scaleY(0);transform-origin:bottom;
transition:transform .25s cubic-bezier(.22,1,.36,1);
}
.ep-card:hover::before{transform:scaleY(1)}
/* Tab active glow */
.a-tab.on{
box-shadow:inset 0 0 0 1px rgba(0,245,255,.25),0 0 24px rgba(0,245,255,.06);
}
/* Inline score glow */
.ah-inline-score:hover{
background:rgba(251,191,36,.2);
box-shadow:0 0 16px rgba(251,191,36,.2);
}
/* Play button pulse */
.ah-play::after{
content:'';position:absolute;inset:0;border-radius:14px;
box-shadow:0 0 0 0 rgba(255,45,125,.4);
animation:play-ripple 2s ease-out infinite;
}
@keyframes play-ripple{
0%{box-shadow:0 0 0 0 rgba(255,45,125,.35)}
70%{box-shadow:0 0 0 12px rgba(255,45,125,0)}
100%{box-shadow:0 0 0 0 rgba(255,45,125,0)}
}
.ah-play{position:relative;overflow:hidden}
/* Description box */
.a-desc-wrap{
background:linear-gradient(135deg,rgba(255,255,255,.03),rgba(0,245,255,.015));
border:1px solid rgba(0,245,255,.07);
}
/* Genre chips hover effect */
.ah-genre-chip{
position:relative;overflow:hidden;
}
.ah-genre-chip::after{
content:'';position:absolute;inset:0;background:rgba(0,245,255,.05);
transform:scaleX(0);transform-origin:left;
transition:transform .2s ease;
}
.ah-genre-chip:hover::after{transform:scaleX(1)}
/* Hero glow pulse under poster */
@keyframes poster-glow{
0%,100%{box-shadow:0 40px 80px rgba(0,0,0,.8),0 0 60px rgba(255,45,125,.06)}
50%{box-shadow:0 40px 80px rgba(0,0,0,.8),0 0 80px rgba(0,245,255,.1)}
}
.ah-poster{animation:poster-glow 4s ease-in-out infinite, ah-fade-up .7s cubic-bezier(.22,1,.36,1) .3s both}
/* Body section reveal */
.a-stats-strip,.a-desc-wrap,.a-tabs{
animation:ah-fade-up .5s cubic-bezier(.22,1,.36,1) .2s both;
}
</style>
@endpush
@section('content')
{{-- Hero --}}
<div class="ah">
@if($anime->bannerUrl ?: $anime->coverUrl)
<div class="ah-bg" id="ah-bg" style="background-image:url('{{ $anime->bannerUrl ?: $anime->coverUrl }}')"></div>
@else
<div style="position:absolute;inset:0;background:linear-gradient(135deg,rgba(20,20,40,1),rgba(5,5,14,1))"></div>
@endif
<div class="ah-overlay"></div>
<div class="ah-noise"></div>
<div class="ah-inner">
{{-- Left: info --}}
<div class="ah-meta">
<div class="ah-badges">
<span class="badge b-type">{{ $anime->type==='movie' ? 'Film' : 'Dizi' }}</span>
@if($anime->status==='ongoing')<span class="badge b-on">Devam Ediyor</span>
@elseif($anime->status==='completed')<span class="badge b-done">Tamamlandı</span>
@else<span class="badge b-up">Yakında</span>@endif
@if($anime->release_year)<span class="badge b-yr">{{ $anime->release_year }}</span>@endif
</div>
<h1 class="ah-title">{{ $anime->title }} <span style="font-size:.6em;font-weight:500;opacity:.55;letter-spacing:.02em">{{ $__izleLabel }}</span></h1>
@if($anime->title_en || $anime->rating)
<div class="ah-sub">
@if($anime->title_en)<span>{{ $anime->title_en }}</span>@endif
@if($anime->title_en && $anime->title_jp)<span class="ah-sub-sep"></span><span>{{ $anime->title_jp }}</span>@endif
@if($anime->rating)
@if($anime->title_en)<span class="ah-sub-sep"></span>@endif
<span class="ah-inline-score"><i class="bi bi-star-fill" style="font-size:.7rem"></i> {{ number_format($anime->rating,1) }}</span>
@endif
</div>
@endif
@if($anime->genres->count())
<div class="ah-genres">
@foreach($anime->genres->take(5) as $g)
<a href="{{ route('genre',$g->slug) }}" class="ah-genre-chip">{{ $g->name }}</a>
@endforeach
</div>
@endif
{{-- Action buttons --}}
<div class="ah-actions">
@if($anime->seasons->count() && $anime->seasons->first()->episodes->count())
@php $s1=$anime->seasons->first(); $e1=$s1->episodes->first(); @endphp
@auth
@if($continueEp && $continueEp->percent_complete > 3)
<a href="{{ route('watch',[$anime->slug,$continueEp->season_number,$continueEp->episode_number]) }}" class="ah-play" style="background:linear-gradient(135deg,#7c3aed,#a855f7)">
<i class="bi bi-play-circle-fill"></i>
Devam Et S{{ str_pad($continueEp->season_number,2,'0',STR_PAD_LEFT) }}E{{ str_pad($continueEp->episode_number,2,'0',STR_PAD_LEFT) }}
<span style="font-size:.68rem;opacity:.75;margin-left:2px">%{{ $continueEp->percent_complete }}</span>
</a>
@else
<a href="{{ route('watch',[$anime->slug,$s1->season_number,$e1->episode_number]) }}" class="ah-play">
<i class="bi bi-play-fill"></i> İzlemeye Başla
</a>
@endif
@else
<a href="{{ route('watch',[$anime->slug,$s1->season_number,$e1->episode_number]) }}" class="ah-play">
<i class="bi bi-play-fill"></i> İzlemeye Başla
</a>
@endauth
@endif
{{-- Watchlist --}}
@auth
<div id="wl-wrap" style="position:relative;display:inline-flex">
<button class="ah-btn {{ $userWatchlist ? 'active-wl' : '' }}" id="wl-btn" onclick="toggleWlMenu()">
<i class="bi bi-{{ $userWatchlist ? 'bookmark-fill' : 'bookmark-plus' }}"></i>
<span class="btn-lbl">{{ $userWatchlist ? \App\Models\Watchlist::STATUSES[$userWatchlist->status] : 'Listeye Ekle' }}</span>
</button>
<div id="wl-menu" style="display:none;position:fixed;background:#0e0e1a;border:1px solid rgba(255,255,255,.12);border-radius:12px;padding:6px;z-index:9000;min-width:170px;box-shadow:0 12px 40px rgba(0,0,0,.8)">
@foreach(\App\Models\Watchlist::STATUSES as $st=>$lbl)
<button onclick="setWatchlist('{{ $st }}')" class="wl-opt {{ ($userWatchlist && $userWatchlist->status===$st) ? 'wl-opt-on' : '' }}">
<i class="bi bi-{{ $st==='plan'?'clock':($st==='watching'?'play-circle':($st==='completed'?'check-circle':'x-circle')) }}"></i> {{ $lbl }}
</button>
@endforeach
@if($userWatchlist)
<hr style="border-color:rgba(255,255,255,.07);margin:5px 0">
<button onclick="setWatchlist('{{ $userWatchlist->status }}')" class="wl-opt" style="color:#f87171">
<i class="bi bi-trash"></i> Listeden Çıkar
</button>
@endif
</div>
</div>
@else
<a href="{{ route('frontend.login') }}" class="ah-btn">
<i class="bi bi-bookmark-plus"></i> <span class="btn-lbl">Listeye Ekle</span>
</a>
@endauth
{{-- Follow --}}
@auth
<button class="ah-btn {{ ($userFollowing ?? false) ? 'active-fl' : '' }}" id="follow-btn" onclick="toggleFollow()">
<i class="bi bi-{{ ($userFollowing ?? false) ? 'bell-fill' : 'bell' }}" id="follow-icon"></i>
<span id="follow-label" class="btn-lbl">{{ ($userFollowing ?? false) ? 'Takiptesin' : 'Takip Et' }}</span>
</button>
@else
<a href="{{ route('frontend.login') }}" class="ah-btn">
<i class="bi bi-bell"></i> <span class="btn-lbl">Takip Et</span>
</a>
@endauth
{{-- Anime Mahkemesi --}}
<a href="{{ route('tribunal.index') }}?anime={{ $anime->id }}" class="ah-btn" title="Bu anime için dava aç">
<i class="bi bi-balance"></i> <span class="btn-lbl">Mahkeme</span>
</a>
{{-- Zaman Kapsülü --}}
@auth
<button class="ah-btn" id="capsule-btn" onclick="openCapsuleModal()" title="Zaman kapsülü bırak">
<i class="bi bi-hourglass-split"></i> <span class="btn-lbl">Kapsül</span>
</button>
@endauth
{{-- Paylaş --}}
<button class="ah-btn" onclick="shareAnime()" title="Paylaş">
<i class="bi bi-share"></i> <span class="btn-lbl">Paylaş</span>
</button>
</div>
{{-- Sosyal: Kimler izliyor --}}
@if($watcherCount > 0)
<div style="display:flex;align-items:center;gap:10px;margin-top:6px;margin-bottom:4px">
<div style="display:flex">
@foreach($watchers->take(6) as $w)
<div data-uid="{{ $w->id }}" style="width:26px;height:26px;border-radius:50%;overflow:hidden;margin-right:-7px;border:2px solid #05050e;cursor:pointer;background:linear-gradient(135deg,var(--accent2),var(--accent));display:flex;align-items:center;justify-content:center;font-size:.62rem;font-weight:800;color:#fff;flex-shrink:0">
@if($w->avatar)<img src="{{ \App\Support\MediaUrl::fromStoragePath($w->avatar) }}" style="width:100%;height:100%;object-fit:cover" alt="">@else{{ mb_strtoupper(mb_substr($w->name,0,1)) }}@endif
</div>
@endforeach
</div>
<span style="font-size:.75rem;color:rgba(255,255,255,.4)">
@if($watcherCount === 1) 1 kişi listesine ekledi
@else <strong style="color:rgba(255,255,255,.65)">{{ number_format($watcherCount) }}</strong> kişi listesine ekledi
@endif
</span>
</div>
@endif
{{-- User rating --}}
@auth
<div class="ah-rating" id="rating-wrap">
<span class="ah-rating-lbl">Puanın:</span>
@for($i=1;$i<=10;$i++)
<button class="star-btn {{ $userRating >= $i ? 'on' : '' }}" data-r="{{ $i }}" onclick="rateAnime({{ $i }})">{{ $i }}</button>
@endfor
@if($userRating)<span id="my-rating-lbl" style="font-size:.76rem;color:var(--accent);margin-left:4px">{{ $userRating }}/10</span>@endif
</div>
@else
<div style="margin-top:2px">
<a href="{{ route('frontend.login') }}" style="font-size:.76rem;color:rgba(255,255,255,.28);text-decoration:none"><i class="bi bi-star me-1"></i>Giriş yap ve puan ver</a>
</div>
@endauth
</div>
{{-- Right: Poster --}}
<div class="ah-poster">
@if($anime->coverUrl)
<img src="{{ $anime->coverUrl }}" alt="{{ $anime->title }}">
@else
<div class="ah-poster-ph"><i class="bi bi-image"></i></div>
@endif
@if($anime->rating)
<div class="ah-poster-score"><i class="bi bi-star-fill"></i> {{ number_format($anime->rating,1) }}</div>
@endif
</div>
</div>
</div>
{{-- Body --}}
<div class="a-body">
{{-- Stats strip --}}
@php $totalEps = $anime->seasons->sum(fn($s) => $s->episodes->count()); @endphp
<div class="a-stats-strip">
@if($anime->rating)
<div class="a-stat-card">
<div class="a-stat-icon gold"><i class="bi bi-star-fill"></i></div>
<div class="a-stat-info">
<div class="a-stat-val">{{ number_format($anime->rating,1) }}</div>
<div class="a-stat-lbl">Puan</div>
</div>
</div>
@endif
<div class="a-stat-card">
<div class="a-stat-icon cyan"><i class="bi bi-collection-play"></i></div>
<div class="a-stat-info">
<div class="a-stat-val">{{ $totalEps }}</div>
<div class="a-stat-lbl">Bölüm</div>
</div>
</div>
<div class="a-stat-card">
<div class="a-stat-icon purple"><i class="bi bi-layers"></i></div>
<div class="a-stat-info">
<div class="a-stat-val">{{ $anime->seasons->count() }}</div>
<div class="a-stat-lbl">Sezon</div>
</div>
</div>
@if($anime->release_year)
<div class="a-stat-card">
<div class="a-stat-icon muted"><i class="bi bi-calendar3"></i></div>
<div class="a-stat-info">
<div class="a-stat-val">{{ $anime->release_year }}</div>
<div class="a-stat-lbl">Yıl</div>
</div>
</div>
@endif
@if($anime->studio)
<div class="a-stat-card">
<div class="a-stat-icon pink"><i class="bi bi-building"></i></div>
<div class="a-stat-info">
<div class="a-stat-val" style="font-size:.82rem;line-height:1.3">{{ $anime->studio }}</div>
<div class="a-stat-lbl">Stüdyo</div>
</div>
</div>
@endif
</div>
{{-- Description --}}
@if($anime->description)
<div class="a-desc-wrap">
<p class="a-desc clamped" id="adesc">{{ $anime->description }}</p>
<button class="a-desc-btn" id="adesc-btn" onclick="toggleDesc()">
<i class="bi bi-chevron-down" id="adesc-icon"></i> Devamını Oku
</button>
</div>
@endif
{{-- Tabs --}}
<div class="a-tabs" id="tabs">
<button class="a-tab on" data-tab="ep" onclick="showTab('ep',this)"><i class="bi bi-collection-play"></i>Bölümler</button>
<button class="a-tab" data-tab="info" id="tab-btn-info" onclick="showTab('info',this)"><i class="bi bi-info-circle"></i>Bilgiler</button>
@if($related->count())<button class="a-tab" data-tab="rel" onclick="showTab('rel',this)"><i class="bi bi-grid-3x3-gap"></i>Benzerler</button>@endif
@auth
<button class="a-tab" data-tab="ai-sim" onclick="showTab('ai-sim',this);loadAiSimilar()" style="color:var(--accent3)"><i class="bi bi-stars"></i>AI Önerileri</button>
@else
<button class="a-tab" onclick="showLoginPrompt()" style="color:var(--accent3);opacity:.55"><i class="bi bi-stars"></i>AI Önerileri <i class="bi bi-lock-fill" style="font-size:.65rem;margin-left:2px"></i></button>
@endauth
</div>
{{-- Episodes --}}
<div class="tab-pane on" id="tab-ep">
@if($anime->seasons->count() > 1)
<div class="season-tabs" id="stabs">
@foreach($anime->seasons as $s)
<button class="s-btn {{ $loop->first ? 'on' : '' }}" data-s="{{ $s->season_number }}" onclick="switchSeason({{ $s->season_number }},this)">
{{ $s->season_number }}. Sezon
<span style="opacity:.45;font-weight:400;margin-left:3px">({{ $s->episodes->count() }})</span>
</button>
@endforeach
</div>
@endif
@foreach($anime->seasons as $s)
<div class="ep-list" id="s{{ $s->season_number }}" style="{{ !$loop->first ? 'display:none' : '' }}">
@forelse($s->episodes as $ep)
<a href="{{ route('watch',[$anime->slug,$s->season_number,$ep->episode_number]) }}" class="ep-card">
<div class="ep-card-thumb">
@if($ep->thumbnailUrl)<img src="{{ $ep->thumbnailUrl }}" alt="" loading="lazy">
@elseif($anime->coverUrl)<img src="{{ $anime->coverUrl }}" alt="" loading="lazy">
@else<div class="no-thumb"><i class="bi bi-film"></i></div>@endif
<div class="ep-play-overlay"><i class="bi bi-play-circle-fill"></i></div>
<div class="ep-num-badge">{{ $ep->episode_number }}. Bölüm</div>
</div>
<div class="ep-card-body">
<div class="ep-card-num">S{{ str_pad($s->season_number,2,'0',STR_PAD_LEFT) }} · E{{ str_pad($ep->episode_number,2,'0',STR_PAD_LEFT) }}</div>
<div class="ep-card-title">{{ $ep->title ?: ($ep->episode_number.'. Bölüm') }}</div>
<div class="ep-card-meta">
@if($ep->duration)<span><i class="bi bi-clock me-1"></i>{{ $ep->duration_formatted }}</span>@endif
@if($ep->view_count)<span><i class="bi bi-eye me-1"></i>{{ number_format($ep->view_count) }}</span>@endif
</div>
</div>
</a>
@empty
<p style="color:rgba(255,255,255,.25);padding:24px 0;text-align:center">Bu sezonda henüz bölüm yok.</p>
@endforelse
</div>
@endforeach
</div>
{{-- Info --}}
<div class="tab-pane" id="tab-info">
<table class="info-table">
@if($anime->studio)<tr><td>Stüdyo</td><td>{{ $anime->studio }}</td></tr>@endif
@if($anime->release_year)<tr><td>Yıl</td><td>{{ $anime->release_year }}</td></tr>@endif
<tr><td>Tür</td><td>{{ $anime->type==='movie' ? 'Film' : 'Dizi' }}</td></tr>
<tr><td>Durum</td><td>{{ $anime->status==='ongoing' ? 'Devam Ediyor' : ($anime->status==='completed' ? 'Tamamlandı' : 'Yakında') }}</td></tr>
@if($anime->episode_count)<tr><td>Toplam Bölüm</td><td>{{ $anime->episode_count }}</td></tr>@endif
@if($anime->rating)<tr><td>Puan</td><td><span style="color:#fbbf24;font-weight:800"> {{ number_format($anime->rating,1) }}</span> <span style="color:rgba(255,255,255,.3)">/ 10</span></td></tr>@endif
@if($anime->genres->count())<tr><td>Türler</td><td><div style="display:flex;flex-wrap:wrap;gap:5px;padding:4px 0">@foreach($anime->genres as $g)<a href="{{ route('genre',$g->slug) }}" class="ah-genre-chip">{{ $g->name }}</a>@endforeach</div></td></tr>@endif
@if($anime->mal_id)<tr><td>MAL ID</td><td style="color:rgba(255,255,255,.5)">{{ $anime->mal_id }}</td></tr>@endif
</table>
</div>
{{-- Related --}}
@if($related->count())
<div class="tab-pane" id="tab-rel">
<div class="rel-grid">
@foreach($related as $r)
<a href="{{ $r->detailUrl }}" class="a-card">
<div class="a-poster">
@if($r->coverUrl)<img src="{{ $r->coverUrl }}" alt="{{ $r->title }}" loading="lazy">
@else<div class="a-no-img"><i class="bi bi-image"></i></div>@endif
@if($r->rating)<span class="a-rating"><i class="bi bi-star-fill" style="font-size:.65rem"></i>{{ number_format($r->rating,1) }}</span>@endif
<div class="a-hover-play"><div class="play-circle"><i class="bi bi-play-fill"></i></div></div>
</div>
<div class="a-info">
<div class="a-title">{{ $r->title }}</div>
<div class="a-meta">{{ $r->release_year }}</div>
</div>
</a>
@endforeach
</div>
</div>
@endif
{{-- AI Similar --}}
@auth
<div class="tab-pane" id="tab-ai-sim">
<div id="ai-sim-wrap" style="padding:8px 0">
<div style="display:flex;align-items:center;gap:12px;margin-bottom:20px;padding:18px 20px;background:linear-gradient(135deg,rgba(184,77,255,.08),rgba(0,245,255,.04));border:1px solid rgba(184,77,255,.18);border-radius:16px">
<div style="width:42px;height:42px;border-radius:12px;background:linear-gradient(135deg,var(--accent3),var(--accent));display:flex;align-items:center;justify-content:center;font-size:1.1rem;color:#fff;box-shadow:0 0 20px rgba(184,77,255,.35);flex-shrink:0"><i class="bi bi-stars"></i></div>
<div>
<div style="font-weight:700;color:#fff;font-size:.92rem">AI Benzer Öneri</div>
<div style="font-size:.76rem;color:rgba(255,255,255,.35);margin-top:2px">Bu animeye benzer alternatifleri yapay zeka analiz ediyor</div>
</div>
</div>
<div id="ai-sim-loader" style="display:flex;justify-content:center;align-items:center;gap:10px;padding:40px">
<div style="display:flex;gap:5px">
<div style="width:8px;height:8px;border-radius:50%;background:var(--accent3);animation:aip-b .9s ease-in-out infinite"></div>
<div style="width:8px;height:8px;border-radius:50%;background:var(--accent);animation:aip-b .9s .18s ease-in-out infinite"></div>
<div style="width:8px;height:8px;border-radius:50%;background:var(--accent2);animation:aip-b .9s .36s ease-in-out infinite"></div>
</div>
<span style="color:rgba(255,255,255,.3);font-size:.85rem">AI analiz yapıyor...</span>
</div>
<div class="rel-grid" id="ai-sim-grid" style="display:none"></div>
<div id="ai-sim-error" style="display:none;padding:20px;text-align:center;color:rgba(255,255,255,.3);font-size:.88rem"></div>
</div>
</div>
@endauth
</div>
{{-- FAQ Section (SEO + UX) --}}
@if(count($__faqItems) > 0)
<div class="section" style="padding-top:0;padding-bottom:48px">
<div style="max-width:860px;margin:0 auto">
<h2 class="ah-desc" style="font-family:var(--font-display);font-size:.82rem;text-transform:uppercase;letter-spacing:.1em;color:var(--accent2);font-weight:800;margin-bottom:18px">
<i class="bi bi-question-circle me-2"></i>{{ $anime->title }} Hakkında Sıkça Sorulan Sorular
</h2>
<div style="display:flex;flex-direction:column;gap:8px">
@foreach($__faqItems as $fq)
<details style="background:rgba(17,17,31,.7);border:1px solid rgba(0,245,255,.1);border-radius:10px;padding:0;overflow:hidden">
<summary style="padding:14px 18px;cursor:pointer;font-size:.88rem;font-weight:600;color:var(--text);list-style:none;display:flex;justify-content:space-between;align-items:center;gap:10px">
{{ $fq['q'] }}
<i class="bi bi-chevron-down" style="flex-shrink:0;font-size:.75rem;color:var(--accent2);transition:transform .2s"></i>
</summary>
<div style="padding:0 18px 14px;font-size:.86rem;color:var(--text2);line-height:1.65;border-top:1px solid rgba(0,245,255,.07)">
<p style="margin:12px 0 0">{{ $fq['a'] }}</p>
</div>
</details>
@endforeach
</div>
</div>
</div>
@endif
@endsection
{{-- Login prompt modal (misafirler için) --}}
<div id="login-prompt" class="login-prompt-overlay" style="display:none" onclick="if(event.target===this)this.style.display='none'">
<div class="login-prompt-box">
<div style="font-size:2.5rem;margin-bottom:12px">🔒</div>
<h3>Bu özellik üyelere özel</h3>
<p>AI önerileri, izleme listesi ve daha fazlası için giriş yapman yeterli.</p>
<a href="{{ route('frontend.login') }}" class="lp-btn lp-btn-primary">Giriş Yap</a>
<a href="{{ route('frontend.register') }}" class="lp-btn lp-btn-secondary">Kayıt Ol</a>
</div>
</div>
@push('scripts')
<script>
// Fade in backdrop
setTimeout(()=>document.getElementById('a-backdrop')?.classList.add('on'),100);
function showLoginPrompt() {
document.getElementById('login-prompt').style.display = 'flex';
}
// ── Follow ───────────────────────────────────────────────────────────────────
const CSRF = document.querySelector('meta[name=csrf-token]')?.content||'';
async function toggleFollow() {
const btn = document.getElementById('follow-btn');
const icon = document.getElementById('follow-icon');
const lbl = document.getElementById('follow-label');
btn.disabled = true;
try {
const res = await fetch('/anime/{{ $anime->slug }}/follow', {
method:'POST',
headers:{'Content-Type':'application/json','X-CSRF-TOKEN':CSRF},
body:'{}'
});
const d = await res.json();
if (d.following) {
icon.className = 'bi bi-bell-fill';
lbl.textContent = 'Takiptesin';
btn.classList.add('active-fl');
} else {
icon.className = 'bi bi-bell';
lbl.textContent = 'Takip Et';
btn.classList.remove('active-fl');
}
} catch(e) {}
btn.disabled = false;
}
// ── Watchlist ────────────────────────────────────────────────────────────────
function toggleWlMenu(){
const menu = document.getElementById('wl-menu');
const isOpen = menu.style.display === 'block';
if (isOpen) { menu.style.display = 'none'; return; }
const btn = document.getElementById('wl-btn');
const rect = btn.getBoundingClientRect();
// Önce göster (boyutu hesaplamak için)
menu.style.visibility = 'hidden';
menu.style.display = 'block';
const menuH = menu.offsetHeight;
const menuW = menu.offsetWidth;
menu.style.visibility = '';
// Alt boşluk yeterli mi?
const spaceBelow = window.innerHeight - rect.bottom;
if (spaceBelow >= menuH + 8) {
menu.style.top = (rect.bottom + 6) + 'px';
} else {
menu.style.top = (rect.top - menuH - 6) + 'px';
}
// Sağdan taşmasın
const left = Math.min(rect.left, window.innerWidth - menuW - 8);
menu.style.left = Math.max(8, left) + 'px';
}
document.addEventListener('click', e => {
if (!document.getElementById('wl-wrap')?.contains(e.target)) {
document.getElementById('wl-menu').style.display='none';
}
});
async function setWatchlist(status) {
document.getElementById('wl-menu').style.display='none';
const res = await fetch('{{ route("watchlist.toggle", $anime) }}', {
method:'POST',
headers:{'Content-Type':'application/json','X-CSRF-TOKEN':CSRF},
body: JSON.stringify({status})
});
const data = await res.json();
const btn = document.getElementById('wl-btn');
if (data.in_list) {
btn.innerHTML = `<i class="bi bi-bookmark-fill"></i> <span class="btn-lbl">${data.status_label}</span>`;
btn.classList.add('active-wl');
} else {
btn.innerHTML = `<i class="bi bi-bookmark-plus"></i> <span class="btn-lbl">Listeye Ekle</span>`;
btn.classList.remove('active-wl');
}
if (data.achievements?.length) {
data.achievements.forEach(a => showAchievement(a));
}
}
// ── Anime Puanlama ───────────────────────────────────────────────────────────
async function rateAnime(rating) {
const res = await fetch('{{ route("anime.rate", $anime) }}', {
method:'POST',
headers:{'Content-Type':'application/json','X-CSRF-TOKEN':CSRF},
body: JSON.stringify({rating})
});
const data = await res.json();
// Yıldızları güncelle
document.querySelectorAll('.star-btn').forEach(b => {
b.classList.toggle('on', parseInt(b.dataset.r) <= rating);
});
const lbl = document.getElementById('my-rating-lbl');
if (lbl) lbl.textContent = `${rating}/10 verdin`;
else {
const wrap = document.getElementById('rating-wrap');
if (wrap) {
const s = document.createElement('span');
s.id='my-rating-lbl';
s.style='font-size:.78rem;color:var(--accent);margin-left:8px';
s.textContent=`${rating}/10 verdin`;
wrap.appendChild(s);
}
}
}
// ── Paylaş ───────────────────────────────────────────────────────────────────
function shareAnime() {
const title = '{{ addslashes($anime->title) }}';
const url = window.location.href;
const text = `${title} — Animexe'de ücretsiz izle!`;
if (navigator.share) {
navigator.share({ title, text, url }).catch(() => {});
return;
}
// Fallback: share modal
const overlay = document.createElement('div');
overlay.style.cssText = 'position:fixed;inset:0;background:rgba(0,0,0,.78);z-index:9999;display:flex;align-items:center;justify-content:center;padding:16px;backdrop-filter:blur(8px)';
overlay.innerHTML = `
<div style="background:#0e0e1a;border:1px solid rgba(255,255,255,.12);border-radius:20px;width:100%;max-width:360px;overflow:hidden">
<div style="padding:16px 20px;border-bottom:1px solid rgba(255,255,255,.07);display:flex;justify-content:space-between;align-items:center">
<span style="font-size:.95rem;font-weight:700;color:#fff"><i class="bi bi-share" style="color:var(--accent2)"></i> Paylaş</span>
<button onclick="this.closest('[style*=fixed]').remove()" style="background:none;border:none;color:rgba(255,255,255,.4);font-size:1.1rem;cursor:pointer"><i class="bi bi-x-lg"></i></button>
</div>
<div style="padding:20px;display:flex;gap:12px;flex-wrap:wrap;justify-content:center">
<a href="https://twitter.com/intent/tweet?text=${encodeURIComponent(text)}&url=${encodeURIComponent(url)}" target="_blank" rel="noopener" style="display:flex;flex-direction:column;align-items:center;gap:6px;padding:14px 20px;border-radius:12px;background:rgba(29,161,242,.1);border:1px solid rgba(29,161,242,.25);color:#1da1f2;text-decoration:none;font-size:.75rem;font-weight:700;transition:background .15s" onmouseover="this.style.background='rgba(29,161,242,.2)'" onmouseout="this.style.background='rgba(29,161,242,.1)'">
<i class="bi bi-twitter-x" style="font-size:1.4rem"></i> X / Twitter
</a>
<a href="https://wa.me/?text=${encodeURIComponent(text + '\n' + url)}" target="_blank" rel="noopener" style="display:flex;flex-direction:column;align-items:center;gap:6px;padding:14px 20px;border-radius:12px;background:rgba(37,211,102,.1);border:1px solid rgba(37,211,102,.25);color:#25d366;text-decoration:none;font-size:.75rem;font-weight:700;transition:background .15s" onmouseover="this.style.background='rgba(37,211,102,.2)'" onmouseout="this.style.background='rgba(37,211,102,.1)'">
<i class="bi bi-whatsapp" style="font-size:1.4rem"></i> WhatsApp
</a>
<button onclick="navigator.clipboard?.writeText('${url.replace(/'/g,"\\'").replace(/\\/g,'\\\\').replace(/"/g,'&quot;')}').then(()=>{ if(window.showToast) showToast('Link kopyalandı!','success'); this.closest('[style*=fixed]').remove(); })" style="display:flex;flex-direction:column;align-items:center;gap:6px;padding:14px 20px;border-radius:12px;background:rgba(0,245,255,.08);border:1px solid rgba(0,245,255,.22);color:var(--accent2);cursor:pointer;font-size:.75rem;font-weight:700;transition:background .15s" onmouseover="this.style.background='rgba(0,245,255,.16)'" onmouseout="this.style.background='rgba(0,245,255,.08)'">
<i class="bi bi-link-45deg" style="font-size:1.4rem"></i> Link Kopyala
</button>
</div>
</div>
`;
document.body.appendChild(overlay);
overlay.addEventListener('click', e => { if (e.target === overlay) overlay.remove(); });
}
// ── Achievement popup ────────────────────────────────────────────────────────
function showAchievement(ach) {
const div = document.createElement('div');
div.className = 'ach-popup';
div.innerHTML = `<i class="bi ${ach.icon} ach-icon" style="color:${ach.color}"></i><div><div class="ach-title">🏆 Başarım Kazandın!</div><div class="ach-name">${ach.title}</div></div>`;
document.body.appendChild(div);
setTimeout(() => div.remove(), 4000);
}
function showTab(tab, btn) {
document.querySelectorAll('.a-tab').forEach(t=>t.classList.remove('on'));
document.querySelectorAll('.tab-pane').forEach(p=>p.classList.remove('on'));
if(btn) btn.classList.add('on');
else document.querySelector(`.a-tab[data-tab="${tab}"]`)?.classList.add('on');
document.getElementById('tab-'+tab)?.classList.add('on');
}
function switchSeason(n,btn){
document.querySelectorAll('[id^="s"]').forEach(el=>{ if(/^s\d+$/.test(el.id)) el.style.display='none'; });
document.querySelectorAll('.s-btn').forEach(b=>b.classList.remove('on'));
document.getElementById('s'+n).style.display='flex';
btn.classList.add('on');
}
function toggleDesc(){
const d=document.getElementById('adesc'), b=document.getElementById('adesc-btn'), ic=document.getElementById('adesc-icon');
d.classList.toggle('clamped');
const collapsed = d.classList.contains('clamped');
b.innerHTML = `<i class="bi bi-chevron-${collapsed?'down':'up'}" id="adesc-icon"></i> ${collapsed?'Devamını Oku':'Daha Az Göster'}`;
}
// Hash-based tab: #tab-info
if(location.hash==='#tab-info') setTimeout(()=>showTab('info', document.querySelector('.a-tab[data-tab="info"]')),50);
@auth
// ── AI Benzer Animeler ────────────────────────────────────────────────────────
let aiSimLoaded = false;
async function loadAiSimilar() {
if (aiSimLoaded) return;
const loader = document.getElementById('ai-sim-loader');
const grid = document.getElementById('ai-sim-grid');
const errEl = document.getElementById('ai-sim-error');
const csrf = document.querySelector('meta[name=csrf-token]')?.content || '';
try {
const res = await fetch('{{ route("ai.similar") }}', {
method: 'POST',
headers: {'Content-Type':'application/json','X-CSRF-TOKEN':csrf},
body: JSON.stringify({anime_id: {{ $anime->id }} })
});
const data = await res.json();
loader.style.display = 'none';
const items = data.similar || [];
if (!items.length) {
errEl.textContent = 'Şu an benzer öneri bulunamadı.';
errEl.style.display = 'block';
} else {
grid.style.display = '';
items.forEach(a => {
grid.innerHTML += `<a href="/anime/${a.slug}" class="a-card">
<div class="a-poster">
${a.cover ? `<img src="${a.cover}" alt="" loading="lazy">` : '<div class="a-no-img"><i class="bi bi-image"></i></div>'}
${a.rating ? `<span class="a-rating"><i class="bi bi-star-fill" style="font-size:.65rem"></i>${parseFloat(a.rating).toFixed(1)}</span>` : ''}
<div class="a-hover-play"><div class="play-circle"><i class="bi bi-play-fill"></i></div></div>
${a.reason ? `<div style="position:absolute;bottom:0;left:0;right:0;padding:6px 8px;background:linear-gradient(to top,rgba(0,0,0,.85),transparent);font-size:.65rem;color:rgba(255,255,255,.8);line-height:1.35">${esc(a.reason)}</div>` : ''}
</div>
<div class="a-info">
<div class="a-title">${esc(a.title)}</div>
<div class="a-meta">${a.type==='movie'?'Film':'Dizi'}</div>
</div>
</a>`;
});
}
aiSimLoaded = true;
} catch(e) {
loader.style.display = 'none';
errEl.textContent = 'AI servisi bağlantı hatası.';
errEl.style.display = 'block';
}
}
function esc(s){ return String(s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/"/g,'&quot;'); }
@endauth
// ── Zaman Kapsülü Modal ───────────────────────────────────────────────────────
function openCapsuleModal() {
document.getElementById('capsule-modal').classList.add('on');
}
function closeCapsuleModal() {
document.getElementById('capsule-modal').classList.remove('on');
}
async function submitCapsule() {
const msg = document.getElementById('cap-msg').value.trim();
const dt = document.getElementById('cap-date').value;
const err = document.getElementById('cap-err');
err.style.display = 'none';
if (msg.length < 5) { err.textContent = 'Mesaj en az 5 karakter olmalı.'; err.style.display = 'block'; return; }
if (!dt) { err.textContent = 'Açılış tarihi seçin.'; err.style.display = 'block'; return; }
const CSRF = document.querySelector('meta[name="csrf-token"]')?.content ?? '';
const r = await fetch('/kapsul', {
method: 'POST',
headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': CSRF, 'Accept': 'application/json' },
body: JSON.stringify({ anime_id: {{ $anime->id }}, message: msg, unlock_at: dt }),
});
const d = await r.json();
if (d.ok) {
closeCapsuleModal();
document.getElementById('cap-msg').value = '';
// toast mesajı
const t = document.createElement('div');
t.textContent = '⏳ Kapsül oluşturuldu!';
t.style.cssText = 'position:fixed;bottom:24px;left:50%;transform:translateX(-50%);background:#1a1a2e;border:1px solid rgba(167,139,250,.3);border-radius:12px;padding:12px 20px;color:#fff;font-size:.88rem;z-index:9999;pointer-events:none';
document.body.appendChild(t);
setTimeout(() => t.remove(), 3000);
} else {
err.textContent = d.error || 'Hata oluştu.';
err.style.display = 'block';
}
}
</script>
@endpush
{{-- Zaman Kapsülü Modal --}}
@auth
<div id="capsule-modal" style="display:none;position:fixed;inset:0;background:rgba(0,0,0,.75);z-index:9000;backdrop-filter:blur(8px);align-items:center;justify-content:center;padding:16px" onclick="if(event.target===this)closeCapsuleModal()">
<style>#capsule-modal.on{display:flex}</style>
<div style="background:#0e0e1a;border:1px solid rgba(167,139,250,.25);border-radius:20px;width:100%;max-width:440px;overflow:hidden">
<div style="padding:16px 20px;border-bottom:1px solid rgba(255,255,255,.07);display:flex;justify-content:space-between;align-items:center">
<h5 style="margin:0;font-size:.95rem;color:#fff"> Zaman Kapsülü Bırak</h5>
<button onclick="closeCapsuleModal()" style="background:none;border:none;color:rgba(255,255,255,.4);font-size:1.1rem;cursor:pointer"><i class="bi bi-x-lg"></i></button>
</div>
<div style="padding:20px">
<p style="font-size:.82rem;color:rgba(255,255,255,.45);margin-bottom:16px">
Gelecekteki kendine mesaj bırak. Seçtiğin tarihte <a href="{{ route('capsules.index') }}" style="color:#a78bfa">kapsüllerim</a> sayfasında açılır.
</p>
<div style="font-size:.72rem;font-weight:700;color:rgba(167,139,250,.7);text-transform:uppercase;letter-spacing:.07em;margin-bottom:6px">Mesajın</div>
<textarea id="cap-msg" rows="4" maxlength="1000" placeholder="Gelecekteki kendine ne söylemek istersin?"
style="width:100%;background:rgba(255,255,255,.07);border:1px solid rgba(255,255,255,.1);border-radius:10px;padding:10px 14px;color:#fff;font-size:.88rem;font-family:inherit;resize:none;outline:none;margin-bottom:14px;box-sizing:border-box"></textarea>
<div style="font-size:.72rem;font-weight:700;color:rgba(167,139,250,.7);text-transform:uppercase;letter-spacing:.07em;margin-bottom:6px">Açılış Tarihi (en az 30 gün sonra)</div>
<input type="date" id="cap-date" min="{{ now()->addDays(30)->format('Y-m-d') }}"
style="width:100%;background:rgba(255,255,255,.07);border:1px solid rgba(255,255,255,.1);border-radius:10px;padding:10px 14px;color:#fff;font-size:.88rem;font-family:inherit;outline:none;margin-bottom:14px;box-sizing:border-box">
<div id="cap-err" style="color:#ff4444;font-size:.78rem;margin-bottom:10px;display:none"></div>
<button onclick="submitCapsule()" style="width:100%;padding:12px;border-radius:12px;border:none;background:rgba(167,139,250,.2);color:#a78bfa;font-weight:700;font-size:.9rem;cursor:pointer;font-family:inherit;transition:background .15s" onmouseover="this.style.background='rgba(167,139,250,.35)'" onmouseout="this.style.background='rgba(167,139,250,.2)'">
Kapsülü Kilitle
</button>
</div>
</div>
</div>
@endauth