:host {
    display: block;
    padding: 24px 28px 40px;
    box-sizing: border-box;
    min-height: 100%;
}

:host(.rails-page-host--empty) {
    padding: 0;
    height: 100%;
    min-height: 100%;
    display: flex;
    overflow: hidden;
}

.rails-page {
    max-width: 1440px;
    margin: 0 auto;
    display: flex;
    flex-direction: column;
    gap: 32px;
    min-width: 0;
}

.rails-page--empty {
    flex: 1;
    max-width: none;
    margin: 0;
    gap: 0;
    min-height: 0;
    height: 100%;
    overflow: hidden;
}

// ── Hero ────────────────────────────────────────────────────────────────────
// Netflix/Apple TV-style hero: blurred poster backdrop + vignette + sharp 2:3
// poster card + text block. Mirrors content-hero fallback (no dedicated
// backdrop asset available, so we reuse the poster blurred + scaled).
.hero {
    position: relative;
    display: grid;
    grid-template-columns: minmax(0, var(--hero-poster-width)) minmax(0, 1fr);
    gap: 20px;
    padding: 16px;
    text-decoration: none;
    color: inherit;
    border-radius: 18px;
    overflow: hidden;
    isolation: isolate;
    background: var(--app-widget-header-bg, #232840);
    border: 1px solid var(--app-widget-header-border, rgba(255, 255, 255, 0.08));
    box-shadow:
        0 1px 2px rgba(0, 0, 0, 0.2),
        0 12px 32px -18px var(--app-selection-glow, rgba(120, 173, 255, 0.4));
    transition:
        transform 0.2s ease,
        box-shadow 0.2s ease;

    // Tighter than v0.21 (was 160px). Matches the v0.22 mockup's 150px
    // poster intent, freeing space for the progress + remaining label
    // without growing total hero height.
    --hero-poster-width: 140px;

    &:hover {
        transform: translateY(-2px);
        box-shadow:
            0 1px 2px rgba(0, 0, 0, 0.2),
            0 20px 40px -20px
                var(--app-selection-glow, rgba(120, 173, 255, 0.55));
    }

    // No-image fallback keeps the accent gradient so the hero is never flat.
    &:not(.hero--with-image) {
        background:
            var(
                --app-accent-gradient,
                linear-gradient(
                    135deg,
                    rgba(99, 102, 241, 0.12) 0%,
                    rgba(168, 85, 247, 0.07) 100%
                )
            ),
            var(--app-widget-header-bg, #232840);
    }
}

// Layer 0: backdrop. Two modes:
//   (1) Real backdrop (`.hero--has-backdrop`): sharp wide image with no blur.
//   (2) Blurred-poster fallback: heavy blur + scale so the poster's colours
//       wash across the full panel without the portrait edges showing.
.hero__backdrop {
    position: absolute;
    inset: 0;
    background-size: cover;
    background-position: center 25%;
    background-repeat: no-repeat;
    z-index: 0;
    pointer-events: none;

    // Fallback: blurred poster.
    filter: blur(40px) saturate(1.5);
    transform: scale(1.5);
    opacity: 0.9;
}

.hero--has-backdrop .hero__backdrop {
    filter: none;
    transform: none;
    opacity: 1;
}

.hero--has-default-backdrop .hero__backdrop {
    filter: none;
    transform: none;
    opacity: 0.95;
}

.hero__image-probe {
    position: absolute;
    width: 1px;
    height: 1px;
    clip-path: inset(50%);
    opacity: 0;
    pointer-events: none;
}

// Layer 1: vignette. Scrim behind the poster card (contrast) and on the
// right edge (text legibility). Middle stays mostly transparent so the
// backdrop colours show through. Darkens further when a sharp backdrop is
// present, since real photography has more focal variation than a blur wash.
.hero__vignette {
    position: absolute;
    inset: 0;
    z-index: 1;
    pointer-events: none;
    background:
        linear-gradient(
            90deg,
            color-mix(
                    in srgb,
                    var(--app-widget-header-bg, #232840) 55%,
                    transparent
                )
                0%,
            color-mix(
                    in srgb,
                    var(--app-widget-header-bg, #232840) 10%,
                    transparent
                )
                45%,
            color-mix(
                    in srgb,
                    var(--app-widget-header-bg, #232840) 65%,
                    transparent
                )
                100%
        ),
        linear-gradient(
            to bottom,
            transparent 55%,
            color-mix(
                    in srgb,
                    var(--app-widget-header-bg, #232840) 35%,
                    transparent
                )
                100%
        );
}

.hero--has-backdrop .hero__vignette {
    background:
        linear-gradient(
            90deg,
            rgba(0, 0, 0, 0.55) 0%,
            rgba(0, 0, 0, 0.2) 35%,
            rgba(0, 0, 0, 0.78) 100%
        ),
        linear-gradient(
            to bottom,
            rgba(0, 0, 0, 0) 40%,
            rgba(0, 0, 0, 0.45) 100%
        );
}

// Layer 2: sharp poster in native 2:3 aspect (no more 16:9 crop).
.hero__poster {
    position: relative;
    z-index: 2;
    width: var(--hero-poster-width);
    aspect-ratio: 2 / 3;
    border-radius: 12px;
    overflow: hidden;
    background: var(--app-widget-bg, #1e2330);
    border: 1px solid var(--app-widget-header-border, rgba(255, 255, 255, 0.1));
    box-shadow: 0 8px 24px -10px rgba(0, 0, 0, 0.55);
    align-self: center;

    img {
        width: 100%;
        height: 100%;
        object-fit: cover;
        display: block;
    }
}

.hero__poster-fallback {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    background: radial-gradient(
        circle at 50% 40%,
        var(--app-selection-surface, rgba(120, 173, 255, 0.2)) 0%,
        transparent 60%
    );
    background-size: cover;
    background-position: center;

    mat-icon {
        font-size: 56px;
        width: 56px;
        height: 56px;
        color: var(--app-selection-color, #78adff);
        opacity: 0.75;
    }
}

// Live channel logos (small square images) get destroyed by the default
// `object-fit: cover` poster treatment. The `.hero--live` modifier centers
// the logo with breathing room over a tinted backdrop. The blurred
// `.hero__backdrop` already provides the ambient color wash for the wider hero.
.hero--live .hero__poster {
    background:
        radial-gradient(
            circle at 50% 35%,
            var(--app-selection-surface, rgba(120, 173, 255, 0.18)) 0%,
            transparent 65%
        ),
        var(--app-widget-bg, #1e2330);

    img {
        box-sizing: border-box;
        object-fit: contain;
        padding: 22% 18%;
        filter: drop-shadow(0 4px 12px rgba(0, 0, 0, 0.45));
    }
}

.hero__body {
    position: relative;
    z-index: 2;
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: 6px;
    min-width: 0;
}

.hero__title {
    margin: 6px 0 4px;
    font-size: 1.75rem;
    font-weight: 600;
    line-height: 1.15;
    // Display-weight tracking: looser than -0.02em which crushes glyphs at
    // this size (~28px). Matches Apple TV+ "Up Next" card scale.
    letter-spacing: -0.015em;
    color: var(--app-heading-color, #d8dce8);
    overflow: hidden;
    text-overflow: ellipsis;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;

    .hero--with-image & {
        color: #fff;
        text-shadow: 0 2px 12px rgba(0, 0, 0, 0.55);
    }
}

.hero__subtitle {
    margin: 0;
    font-size: 0.88rem;
    font-weight: 500;
    line-height: 1.45;
    letter-spacing: 0.002em;
    color: var(--app-body-color, #8b93a8);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;

    .hero--with-image & {
        color: rgba(255, 255, 255, 0.82);
        text-shadow: 0 1px 6px rgba(0, 0, 0, 0.45);
    }
}

// Watch-progress visualisation. Appears between the subtitle and the CTA
// only when a resume position is known — VOD/series only (M3U and live
// channels have no playback positions in the schema).
.hero__progress {
    display: block;
    position: relative;
    margin-top: 12px;
    height: 4px;
    width: min(320px, 70%);
    border-radius: 999px;
    background: color-mix(
        in srgb,
        var(--app-on-surface, #e6e1e5) 14%,
        transparent
    );
    overflow: hidden;

    .hero--with-image & {
        background: rgba(255, 255, 255, 0.18);
    }
}

.hero__progress-bar {
    display: block;
    height: 100%;
    background: var(--app-selection-color, #78adff);
    border-radius: 999px;
    transition: width 0.4s ease;
}

.hero__progress-meta {
    margin-top: 6px;
    display: inline-flex;
    align-items: center;
    gap: 8px;
    font-size: 0.74rem;
    font-weight: 500;
    color: var(--app-body-color, #8b93a8);
    letter-spacing: 0.005em;

    .hero--with-image & {
        color: rgba(255, 255, 255, 0.78);
        text-shadow: 0 1px 4px rgba(0, 0, 0, 0.45);
    }
}

.hero__progress-meta-sep {
    opacity: 0.5;
}

.hero__cta {
    margin-top: 14px;
    align-self: flex-start;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 10px 20px 10px 14px;
    border-radius: 999px;
    background: var(--app-selection-color, #78adff);
    color: var(--app-selection-on-color, #071225);
    font-size: 0.875rem;
    font-weight: 600;
    line-height: 1;
    letter-spacing: 0.005em;
    // Explicit min-height anchors the text baseline regardless of font-smoothing
    min-height: 36px;
    box-sizing: border-box;
    box-shadow: 0 4px 12px -4px
        var(--app-selection-glow, rgba(120, 173, 255, 0.5));

    mat-icon {
        font-size: 20px;
        width: 20px;
        height: 20px;
        line-height: 20px;
    }
}

// ── Loading skeleton ────────────────────────────────────────────────────────
// Geometry mirrors the real hero + rails so the layout doesn't shift when
// data arrives. All shimmer targets share the `%skeleton-shimmer` placeholder
// defined below.
%skeleton-shimmer {
    background: linear-gradient(
        90deg,
        var(--app-widget-bg, #1e2330) 0%,
        var(--app-widget-header-bg, #232840) 50%,
        var(--app-widget-bg, #1e2330) 100%
    );
    background-size: 200% 100%;
    animation: dashboard-skeleton-shimmer 1.6s linear infinite;
    border: 1px solid var(--app-widget-header-border, rgba(255, 255, 255, 0.05));
}

@keyframes dashboard-skeleton-shimmer {
    from {
        background-position: 200% 0;
    }
    to {
        background-position: -200% 0;
    }
}

// ── Hero ghost ──────────────────────────────────────────────────────────────
.rails-page__skeleton-hero {
    position: relative;
    display: grid;
    grid-template-columns: minmax(0, 160px) minmax(0, 1fr);
    gap: 24px;
    padding: 20px;
    border-radius: 18px;
    background: var(--app-widget-header-bg, #232840);
    border: 1px solid var(--app-widget-header-border, rgba(255, 255, 255, 0.08));
}

.rails-page__skeleton-hero-poster {
    @extend %skeleton-shimmer;
    width: 160px;
    aspect-ratio: 2 / 3;
    border-radius: 12px;
    align-self: center;
}

.rails-page__skeleton-hero-body {
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: 10px;
    min-width: 0;
}

.rails-page__skeleton-hero-title {
    @extend %skeleton-shimmer;
    width: 60%;
    height: 28px;
    border-radius: 6px;
}

.rails-page__skeleton-hero-title--short {
    width: 35%;
}

.rails-page__skeleton-hero-subtitle {
    @extend %skeleton-shimmer;
    width: 45%;
    height: 14px;
    border-radius: 4px;
    margin-top: 2px;
}

.rails-page__skeleton-hero-cta {
    @extend %skeleton-shimmer;
    width: 160px;
    height: 36px;
    border-radius: 999px;
    margin-top: 14px;
}

// ── Rail ghost ──────────────────────────────────────────────────────────────
.rails-page__skeleton-rail {
    display: flex;
    flex-direction: column;
    gap: 12px;
    padding: 12px 0 0;
}

.rails-page__skeleton-header {
    @extend %skeleton-shimmer;
    width: 180px;
    height: 22px;
    border-radius: 6px;
}

.rails-page__skeleton-track {
    display: flex;
    gap: var(--cover-gap, 14px);
    padding: 4px 0 16px;
    overflow: hidden;
}

.rails-page__skeleton-card {
    @extend %skeleton-shimmer;
    // Mirrors the real .rail__card width (--cover-rail-width) so geometry
    // matches when cards arrive — no layout shift.
    flex: 0 0 var(--cover-rail-width, 172px);
    width: var(--cover-rail-width, 172px);
    aspect-ratio: 2 / 3;
    border-radius: 12px;
}

@media (prefers-reduced-motion: reduce) {
    .rails-page__skeleton-hero-poster,
    .rails-page__skeleton-hero-title,
    .rails-page__skeleton-hero-subtitle,
    .rails-page__skeleton-hero-cta,
    .rails-page__skeleton-header,
    .rails-page__skeleton-card {
        animation: none;
        background-position: 0 0;
    }
}

// ── Responsive ──────────────────────────────────────────────────────────────
@media (max-width: 720px) {
    :host {
        padding: 16px 16px 32px;
    }

    .rails-page {
        gap: 24px;
    }

    .hero {
        --hero-poster-width: 120px;
        grid-template-columns: var(--hero-poster-width) minmax(0, 1fr);
        gap: 14px;
        padding: 14px;
    }

    // Skeleton hero mirrors real hero at this breakpoint.
    .rails-page__skeleton-hero {
        grid-template-columns: 120px minmax(0, 1fr);
        gap: 14px;
        padding: 14px;
    }

    .rails-page__skeleton-hero-poster {
        width: 120px;
    }

    .rails-page__skeleton-card {
        flex: 0 0 min(var(--cover-rail-width, 172px), 140px);
        width: min(var(--cover-rail-width, 172px), 140px);
    }

    .hero__title {
        font-size: 1.3rem;
    }
}
