/*
 * The channel UI.
 *
 * Written to survive on a television browser as well as a desktop one, which
 * rules out a few things a normal site would reach for: no CSS custom
 * properties (webOS 3 and Tizen 2017 cannot resolve a var(), and an
 * unresolvable one is an unstyled page rather than a slightly wrong one), no
 * grid, no :is()/:where(), no clamp(). Flexbox and transforms are the newest
 * things used here, and both go back to 2015.
 *
 * Per-channel colours are not here at all: they arrive as a small block of
 * literal declarations generated from the feed (see Theme::css) and loaded
 * after this file, so a channel's own palette always wins.
 */

* { box-sizing: border-box; }

html, body {
    margin: 0;
    padding: 0;
    /* NOT height: 100%. That makes BODY the scrolling element rather than the
       document, which is a quiet source of trouble: window.scrollTo stops
       working, scroll-position restoration gets confused, and anything that
       measures the document scrolls the wrong box. min-height gives the same
       full-bleed page with the normal scrolling model. */
    min-height: 100%;
}

/* On HTML, not on body. Setting one axis to hidden makes the other compute to
   auto, and on BODY that turns body itself into the scrolling box — whose
   height is its own content, so there is nothing left for it to scroll and
   everything past one screenful becomes unreachable. The footer was simply
   cut off. On html it does the job it was added for, keeping wide rows from
   producing a horizontal scrollbar, and the document scrolls normally. */
html { overflow-x: hidden; }

body {
    font-family: "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
    background-color: #0A0A0A;
    color: #FFFFFF;
    -webkit-font-smoothing: antialiased;
}

a { color: inherit; text-decoration: none; }
img { border: 0; }

.ott-app {
    position: relative;
    /* vh, not %: a percentage min-height resolves against a parent with a
       definite height, and body's is auto now. */
    min-height: 100vh;
    z-index: 0;
}

.ott-app > * { position: relative; z-index: 1; }

/* Screen-reader-only, for the labels a mouse user does not need. */
.ott-sr {
    position: absolute;
    width: 1px; height: 1px;
    padding: 0; margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

/* -------------------------------------------------------------- header */

.ott-nav {
    position: fixed;
    top: 0; left: 0; right: 0;
    height: 64px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 0 56px;
    z-index: 40;
    /* Fades to NOTHING at its bottom edge. The header used to sit on a solid
       fill with a gradient over it, which ended in a hard horizontal line
       across the page — the gradient softened the top and the fill drew the
       edge anyway. The channel's menu colour is now applied as the gradient
       itself (see Theme::css), so the header dissolves into whatever is under
       it. */
    background-color: transparent;
}

.ott-nav-solid { background-image: none; }

.ott-brand {
    display: flex;
    align-items: center;
    height: 38px;
    font-size: 20px;
    font-weight: 700;
    letter-spacing: .02em;
}

.ott-brand img { max-height: 38px; width: auto; display: block; }

.ott-tabs {
    display: flex;
    align-items: center;
}

.ott-tab {
    display: inline-block;
    padding: 5px 18px;
    margin-left: 4px;
    font-size: 15px;
    line-height: 22px;
    color: #B3B3B3;
    background-color: transparent;
    border: 0;
    border-radius: 22px;
    cursor: pointer;
    white-space: nowrap;
    transition: background-color .12s ease, color .12s ease;
}

/* The current section reads as brighter text, never as a pill: at most one
   pill — the focused one — is ever on screen, which is what stops the header
   looking like two things are selected at once. */
.ott-tab.is-active { color: #FFFFFF; font-weight: 600; }
.ott-tab:focus, .ott-tab:hover { background-color: #FFFFFF; color: #111111; outline: none; }

/* Icon-only tabs — search, account. Squarer padding so the pill around a
   glyph is a circle rather than a lozenge. */
.ott-tab-search,
.ott-tab-icon { padding: 5px 11px; }

.ott-tab-search svg,
.ott-tab-icon svg { display: block; width: 20px; height: 20px; fill: currentColor; }

/* ---------------------------------------------------------------- hero */

/* The picture behind everything.
 *
 * FIXED to the viewport rather than sitting inside the hero: the rows scroll
 * over it and it stays put, so hovering a card near the bottom of a long page
 * still changes a picture the viewer can actually see. Behind all content —
 * .ott-app > * carries z-index 1, and this sits below that. */
.ott-backdrop {
    position: fixed;
    top: 0; left: 0; right: 0;
    height: 100vh;
    z-index: 0;
    pointer-events: none;
}

.ott-backdrop-art {
    position: absolute;
    top: 0; right: 0;
    width: 60%;
    height: 100%;
    background-position: center 22%;
    background-size: cover;
    background-repeat: no-repeat;
    /* The image's own left edge is faded out, rather than being hidden under
       an opaque scrim. At 60% of a typical window that edge lands on a
       FRACTIONAL pixel (546.40625 at 1366 wide), and an image edge and the
       scrim above it antialias independently there — which showed as a
       hairline seam down the hero. Masked, the edge carries no colour at all,
       so there is nothing left to seam. The scrim below stays as the fallback
       for anything that cannot mask. */
    -webkit-mask-image: linear-gradient(to right, rgba(0,0,0,0) 0%, rgba(0,0,0,1) 55%);
    mask-image: linear-gradient(to right, rgba(0,0,0,0) 0%, rgba(0,0,0,1) 55%);
    transition: background-image .25s ease;
}

.ott-backdrop-scrim-h,
.ott-backdrop-scrim-v,
.ott-backdrop-scrim-top {
    position: absolute;
    top: 0; right: 0;
    width: 60%;
    height: 100%;
}

/* The rows scroll over the lower half, so it has to be solid page colour by
   the time they get there or the cards sit on a photograph. */
.ott-backdrop-scrim-top {
    height: 150px;
    background-image: linear-gradient(to bottom, rgba(0,0,0,.92) 0%, rgba(0,0,0,0) 100%);
    /* Masked on the left exactly like the art, and for a reason the other two
       scrims do not have: those are drawn in the PAGE colour, so where they are
       opaque they are invisible against the page and their left edge cannot be
       seen. This one is BLACK — it darkens the photograph so the header stays
       legible — and black over a navy page is a visible step. Ending at 40% of
       the viewport, it drew a hard vertical line straight down the top of the
       hero. */
    -webkit-mask-image: linear-gradient(to right, rgba(0,0,0,0) 0%, rgba(0,0,0,1) 55%);
            mask-image: linear-gradient(to right, rgba(0,0,0,0) 0%, rgba(0,0,0,1) 55%);
}

.ott-hero {
    position: relative;
    height: 30vh;
    min-height: 260px;
}

.ott-hero-text {
    position: absolute;
    left: 56px;
    top: 40%;
    width: 52%;
    max-width: 760px;
}

.ott-hero-title {
    margin: 0;
    font-size: 34px;
    line-height: 1.15;
    font-weight: 700;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.ott-hero-desc {
    margin: 10px 0 0;
    font-size: 15px;
    line-height: 1.5;
    color: rgba(255,255,255,.80);
    /* Two lines, like the television hero. The max-height is the fallback for
       browsers without line-clamp; both agree at this line-height. */
    max-height: 45px;
    overflow: hidden;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
}

.ott-hero-meta {
    margin-top: 10px;
    font-size: 13px;
    color: rgba(255,255,255,.55);
}

.ott-hero-meta span + span:before { content: " · "; }

/* ---------------------------------------------------------------- rows */

.ott-rows { padding: 14px 0 64px 0; }

.ott-row { margin: 0 0 30px 0; }

.ott-row-title {
    margin: 0 0 12px 56px;
    font-size: 17px;
    font-weight: 600;
    letter-spacing: .04em;
    text-transform: uppercase;
    color: rgba(255,255,255,.82);
}

/* The strip scrolls sideways. Padding rather than margin on the ends so a
   focused card at either edge still has room to grow into. */
.ott-strip {
    display: flex;
    align-items: flex-start;
    padding: 10px 56px 18px 56px;
    overflow-x: auto;
    overflow-y: hidden;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
}

.ott-strip::-webkit-scrollbar { display: none; }

/* Wraps the strip so the arrows centre on the CARDS. Anchoring them to the row
   instead would drop them by half the heading's height. */
.ott-strip-wrap { position: relative; }

/* Over the strip, not beside it: a control that took layout space would narrow
   every row by 88px on a television that never shows one. */
.ott-strip-arrow {
    position: absolute;
    top: 10px;
    bottom: 18px;               /* the strip's own padding, so this spans the cards */
    width: 52px;
    z-index: 6;                 /* above a hovered card, which lifts to 5 */
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    border: 0;
    color: #FFFFFF;
    cursor: pointer;
    opacity: 0;
    transition: opacity .16s ease;
}

.ott-strip-arrow svg { width: 26px; height: 26px; display: block; }

.ott-strip-arrow-back { left: 0;  background-image: linear-gradient(to right, rgba(0,0,0,.55) 0%, rgba(0,0,0,0) 100%); }
.ott-strip-arrow-next { right: 0; background-image: linear-gradient(to left,  rgba(0,0,0,.55) 0%, rgba(0,0,0,0) 100%); }

/* Shown on approach rather than always, and only part-way: a control that
   arrives at full strength reads as a panel bolted over the artwork. It comes
   up to full when the pointer is actually on it, which is the moment it stops
   being decoration and becomes a target. */
.ott-row:hover .ott-strip-arrow { opacity: .58; }
.ott-strip-arrow:hover { opacity: 1; }
.ott-strip-arrow.is-hidden { display: none; }

/* A remote already walks the strip with left and right, so an on-screen
   control is a second way to do the same thing and one more place for focus
   to get lost. */
.ott-tv .ott-strip-arrow { display: none; }

/* No hover on a touch screen, and a finger can already swipe the strip. */
@media (hover: none) {
    .ott-strip-arrow { display: none; }
}

.ott-card {
    position: relative;
    display: block;
    flex: 0 0 auto;
    width: 320px;
    margin-right: 12px;
    background-color: #3D3D3D;
    border: 0;
    /* Square corners read as unfinished next to the panels elsewhere, which
       are 6-8px. Matched to those. */
    border-radius: 8px;
    /* Clip the children, in every state, so the artwork's corners and the info
       panel cannot paint outside the radius. */
    overflow: hidden;
    text-align: left;
    cursor: pointer;
    transform-origin: center center;
    transition: transform .14s ease, background-color .14s ease;
}

.ott-card:focus { outline: none; }

/* A focused card lifts above its neighbours instead of being clipped by
   them — z-index alone is not enough once the strip is scrollable. */
.ott-card:focus, .ott-card:hover, .ott-card.is-focused { z-index: 5; }

.ott-card-art {
    /* A span, so a card stays one <a> with no block elements inside it — but
       an inline box ignores height, which is the whole point of this one. */
    display: block;
    position: relative;
    height: 180px;
    width: 100%;
    /* Only the top pair — the bottom of the artwork meets the info panel. */
    border-radius: 8px 8px 0 0;
    background-color: #1A1A1A;
    /* Two layers: the artwork, then the placeholder behind it. The second
       pair of values is the placeholder's — centred and small, so a missing
       thumbnail reads as "no artwork" rather than as a stretched icon. */
    background-position: center, center;
    background-size: cover, auto 38%;
    background-repeat: no-repeat, no-repeat;
    overflow: hidden;
}

/* The artwork fades into the panel below it instead of stopping at a ruled
   line. The gradient's colours are per-channel (the card colour, and the
   highlight it fills with on focus), so they come from Theme::css. */
.ott-card-art:after {
    content: "";
    position: absolute;
    left: 0; right: 0; bottom: 0;
    /* Short on purpose. At 38px the wash began 46px above the title and read as
       a grey slab climbing into the artwork rather than as the picture meeting
       the caption. This is a seam-hider, so it only needs to cover the join. */
    height: 8px;
    pointer-events: none;
    z-index: 1;
}

/* Above the fade: a resume bar under it would be washed out, and a badge
   sits at the other end but is given a layer for the same reason. */
.ott-card-resume { z-index: 2; }
.ott-badge { z-index: 2; }

.ott-card-info { display: block; padding: 8px 10px 10px; }

.ott-card-title {
    display: block;
    font-size: 14px;
    line-height: 18px;
    font-weight: 600;
    color: #FFFFFF;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.ott-card-sub {
    display: block;
    margin-top: 2px;
    font-size: 12px;
    line-height: 16px;
    color: rgba(255,255,255,.62);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Badges sit on the artwork: what a card is, before you read its name. */
.ott-badge {
    display: block;
    position: absolute;
    /* Clear of the corner, not level with it. The card rounds by 8px and grows
       to 1.2x on hover, so an 8px inset put the badge's corner exactly on the
       arc and it read as touching the edge. 14px keeps daylight around it in
       both states. */
    top: 14px;
    padding: 2px 7px;
    font-size: 11px;
    font-weight: 700;
    letter-spacing: .06em;
    text-transform: uppercase;
    border-radius: 2px;
    line-height: 16px;
}

/* Icon-only: square rather than a text pill, and line-height zeroed so the
   box is the icon's size and nothing else. */
.ott-badge-icon { padding: 4px; line-height: 0; }
.ott-badge-icon svg { display: block; width: 14px; height: 14px; }

.ott-badge-live  { left: 14px; background-color: #FF3144; color: #FFFFFF; }
.ott-badge-lock  { right: 14px; background-color: rgba(0,0,0,.72); color: #FFFFFF; }
.ott-badge-soon  { left: 8px; background-color: rgba(0,0,0,.72); color: #FFFFFF; }
.ott-badge-eps   { right: 8px; background-color: rgba(0,0,0,.72); color: #FFFFFF; }

/* Resume bar, drawn from what this browser remembers watching. */
.ott-card-resume {
    display: block;
    position: absolute;
    left: 0; right: 0; bottom: 0;
    height: 3px;
    background-color: rgba(255,255,255,.25);
}

.ott-card-resume i {
    display: block;
    width: 0;
    height: 100%;
    background-color: #FFAA3F;
}

/* ------------------------------------------------------------ big slider */

.ott-row-slider .ott-strip { padding-bottom: 24px; }

.ott-row-slider .ott-card { width: 640px; }
.ott-row-slider .ott-card-art { height: 360px; }
.ott-row-slider .ott-card-title { font-size: 18px; }

/* -------------------------------------------------------------- pages */

.ott-page {
    padding: 104px 56px 64px;
    max-width: 1180px;
}

.ott-page-wide { max-width: none; }

/* Content that follows a hero: the hero already provides the top margin, so
   the page's own header clearance would double it.
   Two classes deep on purpose — the responsive block further down restates
   .ott-page's padding, and an equally specific rule there would win on order
   alone. */
.ott-page.ott-page-flush { padding-top: 28px; }

.ott-page h1 {
    margin: 0 0 6px;
    font-size: 30px;
    font-weight: 700;
}

.ott-page .lead {
    margin: 0 0 28px;
    font-size: 15px;
    color: rgba(255,255,255,.66);
}

.ott-panel {
    background-color: rgba(255,255,255,.05);
    border: 1px solid rgba(255,255,255,.10);
    border-radius: 6px;
    padding: 22px 24px;
    margin-bottom: 18px;
}

.ott-panel h2 {
    margin: 0 0 4px;
    font-size: 18px;
    font-weight: 600;
}

.ott-muted { color: rgba(255,255,255,.60); }
.ott-small { font-size: 13px; }

.ott-alert {
    padding: 12px 16px;
    border-radius: 4px;
    margin-bottom: 18px;
    background-color: rgba(255,49,68,.14);
    border: 1px solid rgba(255,49,68,.45);
    font-size: 14px;
}

.ott-alert-ok {
    background-color: rgba(60,200,120,.14);
    border-color: rgba(60,200,120,.45);
}

.ott-btn {
    display: inline-block;
    padding: 10px 22px;
    font-size: 15px;
    font-weight: 600;
    line-height: 20px;
    border: 1px solid rgba(255,255,255,.35);
    border-radius: 3px;
    background-color: transparent;
    color: #FFFFFF;
    cursor: pointer;
    text-align: center;
}

.ott-btn:focus, .ott-btn:hover { border-color: #FFFFFF; outline: none; }

/* A button that is off has to LOOK off.
   
   This is written against every .ott-btn rather than the one that needed it,
   because the failure is not specific: a control that ignores the pointer
   while looking exactly like one that does not reads as the page being broken,
   and the viewer's next move is to press it repeatedly. The disabled attribute
   was doing its job silently and saying nothing. */
.ott-btn[disabled],
.ott-btn:disabled {
    opacity: .42;
    cursor: not-allowed;
    border-color: rgba(255,255,255,.18);
}

/* And hover must not promise anything either. */
.ott-btn[disabled]:hover,
.ott-btn[disabled]:focus,
.ott-btn:disabled:hover,
.ott-btn:disabled:focus { border-color: rgba(255,255,255,.18); }
.ott-btn + .ott-btn { margin-left: 10px; }
.ott-btn-primary { background-color: #FFAA3F; border-color: #FFAA3F; color: #111111; }
.ott-btn-block { display: block; width: 100%; }

.ott-field {
    display: block;
    width: 100%;
    padding: 10px 14px;
    font-size: 15px;
    color: #FFFFFF;
    background-color: rgba(255,255,255,.08);
    border: 1px solid rgba(255,255,255,.22);
    border-radius: 3px;
}

.ott-field:focus { outline: none; border-color: #FFFFFF; }

/* ------------------------------------------------------------ title page */

.ott-title-hero {
    position: relative;
    min-height: 420px;
    padding: 132px 56px 40px;
    background-position: center 20%;
    background-size: cover;
}

.ott-title-hero:before {
    content: "";
    position: absolute;
    top: 0; left: 0; right: 0; bottom: 0;
    background-image: linear-gradient(to top, rgba(0,0,0,.96) 8%, rgba(0,0,0,.45) 60%, rgba(0,0,0,.75) 100%);
}

.ott-title-hero > * { position: relative; }

.ott-title-hero h1 { margin: 0 0 10px; font-size: 40px; font-weight: 700; }

.ott-title-meta {
    font-size: 13px;
    color: rgba(255,255,255,.62);
    margin-bottom: 14px;
}

.ott-title-meta span + span:before { content: " · "; }

.ott-title-desc {
    max-width: 720px;
    font-size: 16px;
    line-height: 1.6;
    color: rgba(255,255,255,.82);
    margin-bottom: 22px;
}

.ott-season { margin: 0 0 26px; }
.ott-season h3 { margin: 0 0 12px 56px; font-size: 16px; font-weight: 600; letter-spacing: .04em; text-transform: uppercase; }

/* ------------------------------------------------------------- footer */

.ott-footer {
    position: relative;
    z-index: 1;                 /* above the fixed backdrop */
    margin-top: 40px;
    padding: 28px 56px 34px;
    border-top: 1px solid rgba(255,255,255,.10);
    text-align: center;
}

.ott-footer-links {
    display: flex;
    flex-wrap: wrap;
    /* centred, and centred again on each wrapped line rather than only as a
       block — a two-line footer that left-aligns its second row reads as a
       mistake. */
    justify-content: center;
    gap: 10px 26px;
    margin: 0 0 14px;
    padding: 0;
    list-style: none;
}

.ott-footer-links a {
    font-size: 14px;
    font-weight: 600;
    color: rgba(255,255,255,.72);
    text-decoration: none;
}

.ott-footer-links a:hover,
.ott-footer-links a:focus { color: #FFFFFF; text-decoration: underline; }

.ott-footer-note { margin: 0; font-size: 13px; color: rgba(255,255,255,.45); }

/* A page of prose. .ott-page already carries the layout and the 104px that
   clears the fixed header — this only narrows the measure, because a legal
   document set to 1180px is unreadable. Redefining .ott-page here is what
   removed that clearance and pushed the heading under the logo. */
.ott-page-prose { max-width: 760px; }

.ott-page-body { font-size: 15px; line-height: 1.7; color: rgba(255,255,255,.82); }

/* A long legal document, given the spacing that makes one readable. Its own
   first heading stands in for the page title, so it is sized like one. */
.ott-page-legal h2 {
    margin: 34px 0 12px;
    font-size: 22px;
    font-weight: 700;
    color: #FFFFFF;
}

.ott-page-legal h2:first-child { margin-top: 0; font-size: 30px; }
.ott-page-legal { margin-top: 0; }

.ott-page-legal h3 { margin: 26px 0 10px; font-size: 17px; font-weight: 700; color: #FFFFFF; }
.ott-page-legal h4 { margin: 20px 0 8px; font-size: 15px; font-weight: 700; color: rgba(255,255,255,.92); }
.ott-page-legal p  { margin: 0 0 14px; }
.ott-page-legal ul { margin: 0 0 16px; padding-left: 22px; }
.ott-page-legal li { margin-bottom: 8px; }
.ott-page-legal strong { color: #FFFFFF; font-weight: 700; }

@media (max-width: 720px) {
    .ott-footer { padding: 22px 20px 28px; }
}

/* --------------------------------------------------------------- player */

/* Scrolls, so there is somewhere for the related row to be. It did not
   before: the player was fixed over the whole viewport and the body clipped,
   which is right for a player that is the only thing on the page and wrong the
   moment there is something under it. */
.ott-watching { background-color: #000000; }

.ott-player {
    position: relative;
    width: 100%;
    height: 100vh;
    background-color: #000000;
    overflow: hidden;
}

/* A television keeps the old arrangement. There is no scrolling past a player
   with a remote, and a row below the picture is somewhere focus can fall out
   of sight during playback. */
.ott-tv.ott-watching { overflow: hidden; }
.ott-tv .ott-player { position: fixed; top: 0; left: 0; height: 100%; }
.ott-tv .ott-related { display: none; }

.ott-related {
    margin: 0;
    padding: 26px 0 40px;
    background-color: #000000;
}

.ott-player video {
    position: absolute;
    top: 0; left: 0;
    width: 100%;
    height: 100%;
    background-color: #000000;
    object-fit: contain;
}

.ott-player-logo {
    position: absolute;
    max-height: 46px;
    max-width: 180px;
    z-index: 20;
    opacity: .9;
    pointer-events: none;
}

.ott-logo-top-right    { top: 24px; right: 32px; }
.ott-logo-top-left     { top: 24px; left: 32px; }
.ott-logo-bottom-right { bottom: 120px; right: 32px; }
.ott-logo-bottom-left  { bottom: 120px; left: 32px; }

/* Everything that fades with the controls. Kept as one layer so the title,
   the bar and the buttons can never be half-visible. */
.ott-controls {
    position: absolute;
    left: 0; right: 0; bottom: 0;
    padding: 90px 48px 28px;
    /* Strong early, then fading. Content is often bright — a white studio
       shot leaves white icons on pale grey if the scrim only gets dark at the
       very bottom edge. */
    background-image: linear-gradient(to top, rgba(0,0,0,.94) 0%, rgba(0,0,0,.78) 42%, rgba(0,0,0,0) 100%);
    text-shadow: 0 1px 3px rgba(0,0,0,.7);
    z-index: 30;
    opacity: 1;
    transition: opacity .25s ease;
}

.ott-controls.is-hidden { opacity: 0; pointer-events: none; }

/* Top left, over the picture, on the controls' own schedule. */
.ott-player-back {
    position: absolute;
    top: 18px;
    left: 18px;
    z-index: 4;
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 8px 14px 8px 10px;
    border-radius: 6px;
    background-color: rgba(0,0,0,.55);
    color: #FFFFFF;
    font-size: 14px;
    font-weight: 600;
    text-decoration: none;
    transition: opacity .18s ease, background-color .18s ease;
}

.ott-player-back svg { width: 18px; height: 18px; display: block; }
.ott-player-back:hover,
.ott-player-back:focus { background-color: rgba(0,0,0,.78); color: #FFFFFF; }
.ott-player-back.is-hidden { opacity: 0; pointer-events: none; }

.ott-player.is-idle { cursor: none; }

.ott-controls-title {
    font-size: 20px;
    font-weight: 600;
    margin-bottom: 4px;
}

.ott-controls-sub {
    font-size: 13px;
    color: rgba(255,255,255,.62);
    margin-bottom: 14px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.ott-progress {
    position: relative;
    height: 20px;
    display: flex;
    align-items: center;
    cursor: pointer;
}

.ott-progress-track {
    position: relative;
    width: 100%;
    height: 4px;
    background-color: rgba(255,255,255,.34);
    border-radius: 2px;
    box-shadow: 0 0 4px rgba(0,0,0,.5);
}

.ott-progress-buffer {
    position: absolute;
    top: 0; left: 0; bottom: 0;
    background-color: rgba(255,255,255,.35);
    border-radius: 2px;
    width: 0;
}

.ott-progress-played {
    position: absolute;
    top: 0; left: 0; bottom: 0;
    background-color: #FFAA3F;
    border-radius: 2px;
    width: 0;
}

.ott-progress-handle {
    position: absolute;
    top: 50%;
    width: 13px;
    height: 13px;
    margin: -6.5px 0 0 -6.5px;
    border-radius: 50%;
    background-color: #FFAA3F;
    left: 0;
}

/* Ad breaks marked on the bar, so a viewer can see one coming. */
.ott-progress-cue {
    position: absolute;
    top: 0; bottom: 0;
    width: 3px;
    margin-left: -1px;
    background-color: rgba(255,220,80,.9);
}

.ott-controls-bar {
    display: flex;
    align-items: center;
    margin-top: 10px;
}

.ott-ctl {
    background: transparent;
    border: 0;
    padding: 8px;
    margin-right: 10px;
    color: #FFFFFF;
    cursor: pointer;
    border-radius: 50%;
    line-height: 0;
}

.ott-ctl svg {
    width: 26px; height: 26px;
    fill: currentColor;
    display: block;
    /* The icons are shapes, not text, so the scrim's text-shadow does not
       reach them. */
    filter: drop-shadow(0 1px 2px rgba(0,0,0,.8));
}
.ott-ctl:focus, .ott-ctl:hover { background-color: rgba(255,255,255,.18); outline: none; }
.ott-ctl-big svg { width: 34px; height: 34px; }

.ott-time {
    font-size: 13px;
    font-variant-numeric: tabular-nums;
    color: rgba(255,255,255,.85);
    margin-left: 6px;
}

.ott-spacer { flex: 1 1 auto; }

/* Loading and errors sit above the video and below the controls. */
.ott-player-overlay {
    position: absolute;
    top: 0; left: 0; right: 0; bottom: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    text-align: center;
    background-color: rgba(0,0,0,.72);
    z-index: 25;
}

.ott-player-overlay img { max-width: 260px; max-height: 160px; margin-bottom: 20px; }
.ott-player-overlay p { margin: 0; font-size: 16px; color: rgba(255,255,255,.85); }
.ott-player-overlay.is-hidden { display: none; }

.ott-spinner {
    width: 42px;
    height: 42px;
    margin-bottom: 16px;
    border: 3px solid rgba(255,255,255,.25);
    border-top-color: #FFFFFF;
    border-radius: 50%;
    animation: ott-spin .9s linear infinite;
}

@keyframes ott-spin { to { transform: rotate(360deg); } }

/* The ad layer: same video element, different chrome. Controls are hidden
   while an ad runs, because seeking past one is not a thing a viewer may do. */
.ott-ad-bar {
    position: absolute;
    left: 0; right: 0; bottom: 0;
    padding: 16px 48px;
    background-image: linear-gradient(to top, rgba(0,0,0,.94) 0%, rgba(0,0,0,.72) 60%, rgba(0,0,0,0) 100%);
    text-shadow: 0 1px 3px rgba(0,0,0,.7);
    display: flex;
    align-items: center;
    z-index: 35;
    font-size: 14px;
}

.ott-ad-bar.is-hidden { display: none; }
.ott-ad-count { color: rgba(255,255,255,.85); }
.ott-ad-learn { margin-left: 16px; text-decoration: underline; }
.ott-ad-skip {
    margin-left: auto;
    padding: 8px 18px;
    border: 1px solid rgba(255,255,255,.6);
    background: rgba(0,0,0,.5);
    color: #FFFFFF;
    cursor: pointer;
}
.ott-ad-skip[disabled] { opacity: .55; cursor: default; }

/* --------------------------------------------------------------- dialog */

.ott-dialog-backdrop {
    position: fixed;
    top: 0; left: 0; right: 0; bottom: 0;
    background-color: rgba(0,0,0,.78);
    z-index: 90;
    display: flex;
    align-items: center;
    justify-content: center;
}

.ott-dialog-backdrop.is-hidden { display: none; }

.ott-dialog {
    width: 440px;
    max-width: 92%;
    background-color: #17181C;
    border: 1px solid rgba(255,255,255,.14);
    border-radius: 6px;
    padding: 26px 28px;
    text-align: left;
}

.ott-dialog h2 { margin: 0 0 8px; font-size: 20px; }
.ott-dialog p { margin: 0 0 20px; color: rgba(255,255,255,.72); font-size: 14px; line-height: 1.5; }
.ott-dialog-actions { text-align: right; }

/* ------------------------------------------------------------- pairing */

.ott-pair-code {
    font-size: 44px;
    font-weight: 700;
    letter-spacing: .18em;
    text-align: center;
    padding: 18px 0 8px;
    font-variant-numeric: tabular-nums;
}

.ott-pair-steps { padding-left: 20px; line-height: 1.9; color: rgba(255,255,255,.78); font-size: 14px; }

/* --------------------------------------------------------------- grids */

.ott-grid {
    display: flex;
    flex-wrap: wrap;
    margin: 0 -6px;
}

.ott-grid .ott-card { margin: 0 6px 22px; }

/* ------------------------------------------------------------ responsive
   The card sizes a channel states are ten-foot sizes. Below tablet width the
   generated rules are overridden so two cards still fit side by side rather
   than one and a sliver of the next. */

@media (max-width: 1024px) {
    .ott-nav { padding: 0 24px; }
    .ott-row-title, .ott-season h3 { margin-left: 24px; }
    .ott-strip { padding-left: 24px; padding-right: 24px; }
    .ott-hero-text { left: 24px; width: 70%; }
    .ott-page, .ott-title-hero { padding-left: 24px; padding-right: 24px; }
    .ott-controls, .ott-ad-bar { padding-left: 24px; padding-right: 24px; }
}

@media (max-width: 720px) {
    .ott-nav { height: 56px; }
    .ott-hero { height: 34vh; min-height: 220px; }
    .ott-hero-backdrop, .ott-hero-scrim-h, .ott-hero-scrim-v, .ott-hero-scrim-top { width: 100%; }
    .ott-hero-text { width: calc(100% - 48px); top: auto; bottom: 18px; }
    .ott-hero-title { font-size: 24px; }
    .ott-page { padding-top: 84px; }
    .ott-title-hero { padding-top: 96px; min-height: 320px; }
    .ott-title-hero h1 { font-size: 28px; }

    /* Halve the stated card geometry rather than letting a 320px landscape
       card push everything off a phone. */
    .ott-row-landscape .ott-card { width: 232px !important; }
    .ott-row-landscape .ott-card-art { height: 131px !important; }
    .ott-row-portrait .ott-card { width: 124px !important; }
    .ott-row-portrait .ott-card-art { height: 186px !important; }
    .ott-row-slider .ott-card { width: 288px !important; }
    .ott-row-slider .ott-card-art { height: 162px !important; }

    /* Touch has no hover, so the zoom would only ever fire mid-tap. */
    .ott-card:hover { transform: none !important; }
}

/* A television is a keyboard-only device with a cursor that never appears.
   Focus has to be unmistakable there, so it is drawn rather than implied. */
@media (pointer: coarse), (hover: none) {
    .ott-card:focus, .ott-card.is-focused { box-shadow: 0 0 0 3px #FFFFFF; }
}

.ott-tv .ott-card:focus,
.ott-tv .ott-card.is-focused { box-shadow: 0 0 0 3px #FFFFFF; }

/* ------------------------------------------------------------------ epg */

.ott-epg { margin-top: 8px; }
.ott-epg h2 { margin: 0 0 6px; font-size: 18px; font-weight: 600; }

.ott-epg-row {
    display: flex;
    align-items: center;
    padding: 9px 0;
    border-bottom: 1px solid rgba(255,255,255,.08);
    font-size: 14px;
}

.ott-epg-time {
    flex: 0 0 74px;
    color: rgba(255,255,255,.58);
    font-variant-numeric: tabular-nums;
}

.ott-epg-title {
    flex: 1 1 auto;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.ott-epg-row.is-live .ott-epg-title { font-weight: 600; }
.ott-epg-badge { position: static; margin-left: 12px; flex: 0 0 auto; }

/* A field for a short code: wide characters, spaced out, so a six-digit code
   is read back as six digits rather than as a number. */
.ott-code-field {
    text-align: center;
    font-size: 26px;
    letter-spacing: .38em;
    text-indent: .38em;
    font-variant-numeric: tabular-nums;
}

/* ========================================================== paywall
 *
 * The television app's subscribe screen, in a browser: a heading across the
 * top, two columns filling the width beneath it — what you can buy on the
 * left, where you stand on the right — and the way out along the bottom.
 *
 * The two columns are what stop this page being a narrow strip of text with
 * half the window empty beside it, which is what a max-width column looks like
 * on a television-shaped screen.
 */

.ott-paywall {
    display: flex;
    flex-direction: column;
    min-height: 100vh;
    padding: 104px 56px 40px;
}

.ott-paywall-head { margin-bottom: 26px; }

.ott-paywall-head h1 {
    margin: 0;
    font-size: 32px;
    font-weight: 700;
    line-height: 1.15;
}

.ott-paywall-sub {
    margin: 8px 0 0;
    font-size: 17px;
    color: rgba(255,255,255,.62);
    max-width: 720px;
}

.ott-paywall-cols {
    display: flex;
    flex: 1 1 auto;
    align-items: stretch;
    gap: 40px;
}

.ott-paywall-plans {
    flex: 1 1 0;
    min-width: 0;
}

.ott-eyebrow {
    margin: 0 0 14px;
    font-size: 13px;
    font-weight: 700;
    letter-spacing: .14em;
    text-transform: uppercase;
    color: rgba(255,255,255,.45);
}

/* A plan is one target: name, price, and what it is. Pressing anywhere on it
   buys it, so the whole card is the button rather than a button inside it. */
.ott-plan {
    display: block;
    width: 100%;
    text-align: left;
    padding: 20px 26px;
    margin: 0 0 14px;
    background-color: rgba(255,255,255,.05);
    border: 1px solid rgba(255,255,255,.10);
    border-radius: 6px;
    cursor: pointer;
    font: inherit;
    color: inherit;
    transition: background-color .12s ease, border-color .12s ease, transform .12s ease;
}

.ott-plan:focus, .ott-plan:hover {
    outline: none;
    transform: translateY(-1px);
}

.ott-plan.is-inert { cursor: default; opacity: .72; }

.ott-plan-name {
    display: block;
    font-size: 21px;
    font-weight: 600;
    line-height: 1.25;
}

.ott-plan-price {
    display: block;
    margin-top: 4px;
    font-size: 19px;
    font-weight: 700;
}

.ott-plan-per,
.ott-plan-trial {
    margin-left: 6px;
    font-size: 14px;
    font-weight: 400;
    opacity: .8;
}

.ott-plan-desc {
    display: block;
    margin-top: 6px;
    font-size: 14px;
    line-height: 1.5;
    color: rgba(255,255,255,.60);
}

.ott-paywall-note {
    margin: 4px 0 0;
    font-size: 13px;
    line-height: 1.6;
    color: rgba(255,255,255,.45);
}

/* The status panel. Three bands so it is USED rather than filled from the
   top: the state at the top, what it is about in the middle, and the detail
   at the bottom. The middle takes the slack, so the panel looks composed
   whether it is holding a wide backdrop or a small logo. */
.ott-status {
    flex: 1 1 0;
    min-width: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    padding: 26px 28px 28px;
    background-color: rgba(255,255,255,.045);
    border: 1px solid rgba(255,255,255,.09);
    border-radius: 8px;
}

.ott-status-badge {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 46px;
    height: 46px;
    border-radius: 50%;
    background-color: rgba(255,255,255,.10);
    flex: 0 0 auto;
}

.ott-status-badge svg { width: 24px; height: 24px; fill: currentColor; display: block; }

.ott-status-ok    .ott-status-badge { color: #33D17A; background-color: rgba(51,209,122,.14); }
.ott-status-info  .ott-status-badge { color: #4DA3FF; background-color: rgba(77,163,255,.14); }
.ott-status-warn  .ott-status-badge { color: #FFB414; background-color: rgba(255,180,20,.14); }
.ott-status-error .ott-status-badge { color: #FF6B6B; background-color: rgba(255,107,107,.14); }

.ott-status-title {
    margin: 12px 0 0;
    font-size: 22px;
    font-weight: 700;
}

/* The middle band: the title's own artwork on a per-title gate, the channel's
   logo otherwise — the same picture the television panel shows. */
.ott-status-art {
    flex: 1 1 auto;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    min-height: 96px;
    margin: 18px 0;
}

.ott-status-art img {
    max-width: 74%;
    max-height: 190px;
    border-radius: 4px;
    display: block;
}

.ott-status-body {
    margin: 0;
    font-size: 15px;
    line-height: 1.6;
    color: rgba(255,255,255,.82);
    max-width: 380px;
}

.ott-status-foot {
    margin: 10px 0 0;
    font-size: 13px;
    color: rgba(255,255,255,.48);
}

.ott-status-action { margin-top: 18px; }

.ott-paywall-foot {
    margin-top: 28px;
    padding-top: 20px;
    border-top: 1px solid rgba(255,255,255,.08);
}

@media (max-width: 1024px) {
    .ott-paywall { padding-left: 24px; padding-right: 24px; }
    .ott-paywall-cols { gap: 24px; }
}

/* Below tablet the two columns become one: the plans first, because that is
   what the viewer came for, and the status beneath them. */
@media (max-width: 860px) {
    .ott-paywall { padding-top: 84px; min-height: 0; }
    .ott-paywall-cols { display: block; }
    .ott-status { margin-top: 26px; }
    .ott-status-art { min-height: 0; margin: 14px 0; }
    .ott-status-art img { max-height: 130px; }
    .ott-paywall-head h1 { font-size: 26px; }
    .ott-paywall-sub { font-size: 15px; }
}

/* ================================================== focused screens
 *
 * Signing in, confirming a purchase, the parental gate. One short task each,
 * so they are CENTRED rather than pinned to the left margin — a 500px column
 * against the left edge of a 1600px window reads as a page that failed to
 * finish loading, which is exactly what a browse screen must not look like
 * two clicks away.
 *
 * The channel's backdrop shows through, so these still look like the channel
 * rather than like a form.
 */

.ott-focus {
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 100vh;
    padding: 104px 24px 56px;
}

.ott-focus-card {
    width: 100%;
    max-width: 440px;
}

/* Wider, for a screen carrying a table or a list of purchases. */
.ott-focus-wide .ott-focus-card { max-width: 760px; }

.ott-focus-card h1 {
    margin: 0 0 8px;
    font-size: 27px;
    font-weight: 700;
    text-align: center;
}

.ott-focus-card .lead {
    margin: 0 auto 24px;
    font-size: 15px;
    line-height: 1.6;
    color: rgba(255,255,255,.62);
    text-align: center;
    max-width: 400px;
}

.ott-focus-wide .ott-focus-card h1,
.ott-focus-wide .ott-focus-card .lead { text-align: left; }
.ott-focus-wide .ott-focus-card .lead { margin-left: 0; max-width: none; }

.ott-focus-card .ott-panel { margin-bottom: 14px; }

.ott-focus-aside {
    margin: 18px 0 0;
    font-size: 13px;
    line-height: 1.6;
    color: rgba(255,255,255,.48);
    text-align: center;
}

.ott-focus-wide .ott-focus-aside { text-align: left; }

/* Secondary actions under a form: side by side, evenly weighted. */
.ott-focus-actions {
    display: flex;
    gap: 10px;
    justify-content: center;
    flex-wrap: wrap;
}

.ott-focus-actions .ott-btn { margin: 0; }
.ott-focus-actions form { margin: 0; }

/* On the wide variant everything reads left-to-right from the panel's own
   text, so its buttons line up with that rather than floating in the middle. */
.ott-focus-wide .ott-focus-actions { justify-content: flex-start; }

@media (max-width: 720px) {
    .ott-focus { padding-top: 84px; display: block; }
}

.ott-thanks-badge {
    margin: 0 auto 18px;
    color: #33D17A;
    background-color: rgba(51,209,122,.14);
}

/* A plain table, styled here rather than borrowed from Bootstrap — the TV
   ports drop Bootstrap entirely and this still has to read. */
.ott-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 14px;
    margin-top: 6px;
}

.ott-table th,
.ott-table td {
    text-align: left;
    padding: 10px 14px 10px 0;
    border-bottom: 1px solid rgba(255,255,255,.08);
    white-space: nowrap;
}

.ott-table th {
    font-size: 12px;
    font-weight: 700;
    letter-spacing: .1em;
    text-transform: uppercase;
    color: rgba(255,255,255,.45);
}

.ott-table tr:last-child td { border-bottom: 0; }

/* ============================================================ parked
 *
 * A hostname that names no channel — the bare domain, or a name pointed here
 * before it was set up. Not an error page: it is the correct answer for those
 * names, and it is the first thing anyone sees at watch.ottflix.com, so it is
 * built to look deliberate rather than like something missing.
 */

.ott-parked {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 100vh;
    padding: 32px;
    overflow: hidden;
}

/* A wide, very low-contrast wash behind the card, so it sits in light rather
   than floating on flat black. */
.ott-parked::before {
    content: "";
    position: absolute;
    top: 50%;
    left: 50%;
    width: 900px;
    height: 900px;
    margin: -450px 0 0 -450px;
    background: radial-gradient(circle,
                rgba(192,0,160,.10) 0%,
                rgba(240,128,32,.04) 35%,
                rgba(0,0,0,0) 70%);
    pointer-events: none;
}

.ott-parked-card {
    position: relative;
    z-index: 1;
    text-align: center;
    padding: 46px 56px 40px;
    border-radius: 18px;
    background-color: rgba(255,255,255,.022);
    border: 1px solid rgba(255,255,255,.08);
    /* Depth first, glow second — the halo is what makes it feel lit, and it is
       kept well under half opacity so it reads as light rather than as neon.
       Sampled from the mark itself: #F08020 through #C000A0 are the two ends
       of the logo's own gradient, so the card reads as lit BY the logo. It was
       blue while the mark was a blue placeholder, and kept looking wrong
       against the real one. */
    box-shadow:
        0 30px 80px -28px rgba(0,0,0,.95),
        0 0 70px -18px rgba(192,0,160,.30);
    animation: ott-parked-breathe 7s ease-in-out infinite;
}

/* The lit edge. A gradient ring drawn as a masked border — a plain border
   cannot hold a gradient, and an outline would not follow the radius. */
.ott-parked-card::before {
    content: "";
    position: absolute;
    inset: -1px;
    border-radius: inherit;
    padding: 1px;
    background: linear-gradient(140deg,
                rgba(240,128,32,.65) 0%,
                rgba(255,255,255,.10) 42%,
                rgba(192,0,160,.55) 100%);
    -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
            mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
    -webkit-mask-composite: xor;
            mask-composite: exclude;
    pointer-events: none;
}

/* No background of its own any more: the icon IS the artwork, and a gradient
   behind it fought the one inside it. The glow is warmed to the mark's own
   magenta so it reads as the logo being lit rather than as a blue plate. */
.ott-parked-mark {
    display: block;
    width: 64px;
    height: 64px;
    margin: 0 auto 22px;
    filter: drop-shadow(0 10px 26px rgba(233,30,140,.42));
}

.ott-parked-mark img { display: block; width: 100%; height: 100%; }

.ott-parked-eyebrow {
    margin: 0 0 8px;
    font-size: 12px;
    font-weight: 600;
    letter-spacing: .16em;
    text-transform: uppercase;
    color: rgba(255,255,255,.42);
}

.ott-parked-brand {
    display: inline-block;
    font-size: 27px;
    font-weight: 700;
    letter-spacing: -.01em;
    color: #FFFFFF;
    text-decoration: none;
    border-bottom: 1px solid rgba(255,255,255,0);
    padding-bottom: 2px;
    transition: border-color .18s ease, color .18s ease;
}

.ott-parked-brand:hover,
.ott-parked-brand:focus {
    color: #FFFFFF;
    border-bottom-color: rgba(255,255,255,.55);
    outline: none;
}

.ott-parked-note {
    margin: 14px 0 0;
    font-size: 13px;
    line-height: 1.6;
    color: rgba(255,255,255,.36);
}

/* These re-declare box-shadow on every frame, so THIS is the glow that is
   actually on screen — the static rule above is only the un-animated
   fallback. Retinting the rule and not the keyframes changed nothing at all,
   which is exactly how it looked when checked. */
@keyframes ott-parked-breathe {
    0%, 100% { box-shadow: 0 30px 80px -28px rgba(0,0,0,.95), 0 0 70px -18px rgba(192,0,160,.30); }
    50%      { box-shadow: 0 30px 80px -28px rgba(0,0,0,.95), 0 0 96px -14px rgba(192,0,160,.46); }
}

/* A slow pulse is atmosphere, not information — anyone who has asked for less
   motion loses nothing by having it still. */
@media (prefers-reduced-motion: reduce) {
    .ott-parked-card { animation: none; }
}

@media (max-width: 480px) {
    .ott-parked-card { padding: 38px 30px 32px; }
    .ott-parked-brand { font-size: 23px; }
}
