/*
 * 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;
}

/* A hidden element is gone, whatever display its class gives it.
 *
 * An author's display beats the browser's own [hidden] rule, so a class here
 * that sets one keeps a hidden element on screen: .ott-btn's inline-block
 * showed the title page's Play from Beginning before there was anything to
 * resume, and the resume bar's block drew an empty track along every tile.
 * The website never showed either, because Bootstrap's reset carries
 * [hidden]{display:none!important}. A television package loads no Bootstrap:
 * the Samsung app met it as a "Try again" that stayed on screen and took the
 * highlight. Every class in this file that sets a display and is ever hidden
 * by the attribute is listed here; two classes outrank the one that sets it. */
.ott-btn[hidden],
.ott-card-resume[hidden] { display: none; }

/* -------------------------------------------------------------- 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;
}

/* Solid, for a page whose picture must start BELOW the header — the title
   page. The channel's own menu colour arrives from Theme::css; this is the
   template's, for a page drawn without it. */
.ott-nav-solid { background-image: none; background-color: #161B22; }

.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. */
/* Set apart from the section names, because it is not one of them: the tabs
   move you around the channel and this one asks you to identify yourself.
   
   It reads as a button — an outline the pill radius follows all the way round
   — and the divider is drawn as a separate mark beside it. A border-left on
   the button itself was the first attempt and came out as a crescent: this is
   a 22px pill, so a single-side border gets bent around the curve instead of
   standing up straight. */
/* The divider belongs to the SLOT, not to the button that happens to be in it.
   Signed out that is a Sign in button, signed in it is the account icon, and
   the rule that separates "where you are in the channel" from "who you are"
   does not change when the occupant does. */
.ott-tab-identity {
    position: relative;
    margin-left: 22px;
}

/* Half the margin, so the mark lands in the MIDDLE of the gap it divides.
   At the full -22px it sat flush against the search tab's box: 11px from that
   glyph and 33px from the next one, which reads as belonging to the search
   icon rather than separating the two. Both neighbours carry the same 11px of
   horizontal padding, so centring the gap centres the glyphs too. */
.ott-tab-identity::before {
    content: "";
    position: absolute;
    left: -11px;
    top: 50%;
    margin-top: -9px;
    width: 1px;
    height: 18px;
    background-color: rgba(255,255,255,.30);
}

/* Nothing on its left, nothing to divide.
 *
 * A channel with one menu and no search draws no tabs at all — one place to be
 * is not a choice — which leaves the identity slot first in the header, and a
 * rule with nothing before it reads as an item that failed to load rather than
 * as a separator. It can only ever hide the orphaned case: a header with tabs
 * has something ahead of the mark by definition. */
.ott-tab-identity:first-child::before { display: none; }

/* Only the signed-out one is a button; the signed-in one is an icon, and
   matches the search icon beside it.
   
   Which also moves the mark. The two occupants present different visual edges:
   an icon reads from its glyph, 11px inside its box, while a button reads from
   its outline, which IS the box. Centring on one leaves the other lopsided, so
   the button carries its own offset. 23px of margin rather than 22 only so the
   half falls on a whole pixel — a hairline on a half-pixel renders as two
   greys. */
.ott-tab-signin {
    margin-left: 23px;
    border: 1px solid rgba(255,255,255,.45);
    color: #FFFFFF;
}

.ott-tab-signin::before { left: -17px; }

/* Filled on hover by the theme, so the outline steps back rather than doubling
   up with the fill's own edge. */
.ott-tab-signin:hover,
.ott-tab-signin:focus { border-color: transparent; }

.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; }

/* Three classes, not two, and deliberately so. Theme::css() emits
   `.ott-row-landscape .ott-card{width:…}` from the channel's own geometry, it
   is inlined AFTER this stylesheet, and at equal specificity the later rule
   wins — so the Big Slider row quietly rendered at the ordinary card width on
   every channel that switched it on. The give-away was this file's own strip
   padding for that row, which is computed for the 360px art below. */
.ott-row.ott-row-slider .ott-card { width: 640px; }
.ott-row.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; }

/* A NARROW page centres itself; a wide one does not.
   
   At 1180px the container is close enough to the window to read as aligned
   with the rows, and centring it would pull it out of step with them. A 760px
   document on a 1440px screen is a different thing: left-aligned it leaves the
   whole right half empty and looks like a layout that failed rather than one
   that chose. Auto margins only bite when there is space to distribute, so
   this is inert until the window is wider than the measure.
   
   margin-left/right rather than margin-inline: the television runtimes this
   has to keep working on predate logical properties. */
.ott-page-prose,
.ott-page-narrow {
    margin-left: auto;
    margin-right: auto;
}

.ott-page-narrow { max-width: 620px; }

/* 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; }

/* Pressed. A button that looks the same while it is held as before reads as
   one that missed the press. Not on a disabled one, which takes no press. */
.ott-btn:active:not(:disabled) { transform: translateY(1px); }

/* 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 */

/*
 * The artwork and what to do with it: side by side on a wide screen, stacked
 * on a narrow one with the artwork first, as on a phone.
 *
 * The artwork is a FRAME rather than the page's background. It needs an edge
 * of its own — the resume bar sits flush along its bottom, the way the home
 * tiles carry theirs, and a picture that dissolves into the page has no
 * bottom edge to sit on — and it starts below the header, which is solid on
 * this page, instead of running up behind a see-through one.
 *
 * The artwork comes first in the markup; row-reverse puts it on the right on
 * a wide screen, the side the browse hero keeps its picture on.
 */
.ott-detail {
    display: flex;
    flex-direction: row-reverse;
    align-items: flex-start;
    gap: 40px;
    padding: 104px 56px 36px;
}

.ott-detail-art {
    flex: 0 0 46%;
    max-width: 760px;
}

/* 16:9 by padding, because aspect-ratio is newer than anything else this file
   leans on. The percentage resolves against .ott-detail-art's width, so the
   frame is always the artwork's own shape and never crops it to suit the
   window. Two background layers, like a card's: the artwork over the
   placeholder that ott_bg() supplies. */
.ott-detail-frame {
    position: relative;
    height: 0;
    padding-top: 56.25%;
    border-radius: 8px;
    overflow: hidden;
    background-color: #1A1A1A;
    background-position: center, center;
    background-size: cover, auto 38%;
    background-repeat: no-repeat, no-repeat;
}

.ott-detail-info { flex: 1 1 auto; min-width: 0; }

.ott-detail-info h1 { margin: 0 0 10px; font-size: 40px; font-weight: 700; line-height: 1.15; }

/* Over the buttons, as on the television and the phone. Muted by opacity
   rather than a fixed grey, so it follows whatever text colour the channel
   set. */
.ott-detail-left { margin: 0 0 8px; font-size: 13px; opacity: .66; }

/*
 * Side by side and the same size: Resume beside Play from Beginning, or one
 * button the width of either. No icons on any of them.
 *
 * The margin reset matters. `.ott-btn + .ott-btn` adds its own 10px on the
 * left, which on top of the gap would put the second button 20px from the
 * first. Same specificity, later in the file, so this wins.
 */
.ott-detail-actions {
    display: flex;
    gap: 10px;
    max-width: 460px;
    margin: 0 0 22px;
}

.ott-detail-actions .ott-btn {
    flex: 1 1 0;
    max-width: 225px;
    margin: 0;
}

.ott-detail-note { margin: -10px 0 22px; font-size: 13px; opacity: .66; }

.ott-detail .ott-badge-live {
    position: static;
    display: inline-block;
    margin-right: 10px;
    vertical-align: 1px;
}

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

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

.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; }

/* Every width this page changes at, here and in this order, so no rule later
   in the file can undo one. */
@media (max-width: 1024px) {
    .ott-detail { padding-left: 24px; padding-right: 24px; gap: 28px; }
}

/* Stacked: the artwork across the full width, flush under the header, as on
   a phone or a tablet held upright. */
@media (max-width: 900px) {
    .ott-detail { flex-direction: column; align-items: stretch; gap: 0; padding: 64px 0 8px; }
    .ott-detail-art { flex: none; max-width: none; }
    .ott-detail-frame { border-radius: 0; }
    .ott-detail-info { padding: 20px 24px 0; }
}

/* A phone: the buttons take the width, a lone one all of it, a pair half
   each — the full-width Play the phone apps keep. Smaller type and tighter
   padding so "Play from Beginning" fits beside Resume in half a phone. */
@media (max-width: 720px) {
    .ott-detail { padding-top: 56px; }
    .ott-detail-info h1 { font-size: 28px; }
    .ott-detail-actions { max-width: none; }
    .ott-detail-actions .ott-btn {
        max-width: none;
        padding-left: 10px;
        padding-right: 10px;
        font-size: 14px;
    }
}

/* ----------------------------------------------------------- activate */

/* The panel already carries the spacing a form needs; this only keeps it clear
   of whatever notice sits above it. */
.ott-activate-form { margin-top: 22px; }

/* The code is read off a television across a room and typed here, so it is set
   large, spaced, and in a face where 0 and O cannot be confused. */
/* .ott-field carries the box; this only makes it a CODE field. */
.ott-activate-code {
    /* Full width, like the button under it and like the email field on the
       sign-in page. It was capped at 320px on the reasoning that eight
       characters do not need a card's width — true of the TEXT, and beside the
       point: what a viewer sees is a box and a button that disagree about how
       wide the form is. The letter-spacing below does the work the narrow box
       was there for. */
    margin-bottom: 18px;
    font-family: "SF Mono", Menlo, Consolas, monospace;
    font-size: 26px;
    letter-spacing: .14em;
    text-align: center;
    text-transform: uppercase;
}

.ott-activate-problem { margin-bottom: 22px; }
.ott-activate-headline { margin: 0 0 6px; font-size: 16px; font-weight: 600; }

/* ------------------------------------------------------------- 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; }

/* White text, whatever the channel's: the player is black, and a title left to
   inherit a pale channel's dark text colour vanished into it. */
.ott-player {
    position: relative;
    width: 100%;
    height: 100vh;
    background-color: #000000;
    color: #FFFFFF;
    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.
 *
 * Above the loading scrim (25), not under it. It sat at 4, so while a stream
 * was loading — or stalled, which is exactly when somebody wants out — the one
 * way back was drawn dimmed under the spinner's scrim and could not be
 * pressed. The end and error cards carry their own way out and player.js
 * stands this down while either is up, so it never doubles one. Still under
 * the dialogs (90), which are questions that must be answered first. */
.ott-player-back {
    position: absolute;
    top: 18px;
    left: 18px;
    z-index: 26;
    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; }
/* Reached by Tab, it has to say so: a slightly darker pill is not focus. */
.ott-player-back:focus { outline: none; box-shadow: 0 0 0 2px rgba(255,255,255,.85); }
.ott-player-back:active { background-color: rgba(0,0,0,.92); transform: scale(.97); }
.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; }

/* Dark on every channel, so its words are white on every channel. Left to
   inherit, the heading took the page's text colour, and a channel with a pale
   page and dark text asked "Sign out?" in near-black on near-black. */
.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;
    color: #FFFFFF;
}

.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 { 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; }

    /* 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; }

/*
 * A plan that can be chosen has to LOOK chosen-able.
 *
 * It did not. At rest a plan and the "you are signed in" panel beside it were
 * the same near-black card with the same faint border, so the one thing on the
 * page a viewer must press looked exactly like the one thing that is only
 * telling them something. Nothing said where to click.
 *
 * Two changes, and the second is the one that actually answers it: a firmer
 * border, and a labelled control inside the card. Theme paints both in the
 * operator's own accent — a colour cannot be hardcoded here without giving
 * every channel the same one — and this is the neutral fallback underneath.
 *
 * .is-inert keeps every bit of its quietness. A plan that cannot be bought,
 * which is the only kind a television ever draws, must not grow a button.
 */
.ott-plan:not(.is-inert) { border-color: rgba(255,255,255,.28); }

.ott-plan-go {
    display: inline-block;
    margin-top: 16px;
    padding: 9px 22px;
    border-radius: 4px;
    font-size: 14px;
    font-weight: 600;
    background-color: rgba(255,255,255,.16);
    color: #FFFFFF;
}

.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;
    /* Quieter than a plan on purpose: this panel reports, the plan acts, and
       until they differed a viewer had no way to tell which was which. */
    background-color: rgba(255,255,255,.03);
    border: 1px solid rgba(255,255,255,.07);
    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. */
/* A row of buttons never sits flush against whatever is above it.
 *
 * .ott-focus-aside carries 18px on top and nothing underneath, so a button row
 * with no margin of its own landed against the last line of text — twice,
 * reported twice. Stated here, once, so no page has to remember it and no page
 * can get it wrong: the gap above the aside and the gap below it are now the
 * same 18px. */
.ott-focus-actions {
    margin-top: 18px;
    display: flex;
    gap: 10px;
    justify-content: center;
    flex-wrap: wrap;
}

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

/* A link inside a sentence. The global `a` rule takes the underline away,
   which suits cards and buttons and leaves a link in running text looking
   exactly like the words around it — so this one keeps its underline, in the
   surrounding colour (and therefore readable wherever that text is), and every
   state is visible: hover and focus go full strength, focus adds a ring, a
   press dims it. */
.ott-text-link { color: inherit; text-decoration: underline; border-radius: 2px; }
.ott-text-link:hover,
.ott-text-link:focus { color: inherit; opacity: 1; text-decoration-thickness: 2px; outline: none; }
.ott-text-link:focus { box-shadow: 0 0 0 2px currentColor; }
.ott-text-link:active { opacity: .7; }

/* reCAPTCHA's floating badge sits over the bottom-right corner of the page —
   over the footer on a phone. Google allows hiding it when its attribution is
   shown in the flow instead, which partials/captcha-notice does. */
.grecaptcha-badge { visibility: hidden; }
.ott-captcha-notice { font-size: 12px; }

/*
 * On a phone the row becomes a column, and every button is the same width.
 *
 * Wrapped, they were not: three buttons of three natural widths, two on one
 * line and the third dropped underneath at a fourth width, centred so nothing
 * lined up with anything. It reads as a layout that broke rather than one that
 * adapted — and it is the narrow case, which is where most of these pages are
 * actually read.
 *
 * Still flex, so the 10px gap above keeps working; `stretch` is what makes the
 * widths equal, and it costs nothing on a television, where the viewport is
 * nowhere near this.
 */
@media (max-width: 560px) {
    .ott-focus-actions { flex-direction: column; align-items: stretch; }
    .ott-focus-actions form .ott-btn { width: 100%; }
}

/* 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; }
}

/* ================================================== account and About
 *
 * One column, as on the phone and television apps: the state, who is signed
 * in, then the buttons stacked and all one width, in the platform order.
 *
 * Every surface here is a wash of the channel's TEXT colour, stated in
 * Theme::css, so it shows on a light page as well as a dark one; the values
 * below are the dark-page fallback. Muted text is muted by opacity for the
 * same reason.
 */

.ott-account-status h2 { margin: 0 0 14px; font-size: 22px; font-weight: 700; }
.ott-account-status p { margin: 14px 0 0; }

/* The margin reset matters: .ott-btn + .ott-btn adds 10px on the left, which
   in a column pushed every button after the first out of line. */
.ott-account-actions {
    display: flex;
    flex-direction: column;
    gap: 10px;
    margin-top: 18px;
}

.ott-account-actions .ott-btn { margin: 0; }
.ott-account-actions form { margin: 0; }
.ott-account-actions form .ott-btn { width: 100%; }

.ott-account-owned { margin: 16px 0 0; font-size: 13px; line-height: 1.5; text-align: center; opacity: .62; }

/* Terms of Use and Privacy Policy, centred under everything, on the account
   page and the paywall alike on every other platform. */
.ott-legal-links {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 6px 22px;
    margin: 26px 0 0;
    font-size: 13px;
}

.ott-legal-links a { color: inherit; opacity: .62; border-radius: 2px; }
.ott-legal-links a:hover,
.ott-legal-links a:focus { opacity: 1; text-decoration: underline; outline: none; }
.ott-legal-links a:focus { box-shadow: 0 0 0 2px currentColor; }
.ott-legal-links a:active { opacity: .8; }

/* "✓ Signed in" and the address: a card of its own rather than the middle of
   a grey sentence, so who is signed in is read at a glance. */
.ott-signed-in {
    display: flex;
    align-items: center;
    gap: 14px;
    padding: 14px 16px 14px 14px;
    border: 1px solid rgba(255,255,255,.12);
    border-radius: 12px;
    background-color: rgba(255,255,255,.07);
    text-align: left;
}

.ott-signed-in-mark {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 44px;
    height: 44px;
    border-radius: 50%;
    font-size: 20px;
    font-weight: 700;
    background-color: #FFAA3F;
    color: #111111;
}

.ott-signed-in-text { display: flex; flex-direction: column; gap: 3px; min-width: 0; }

.ott-signed-in-state {
    display: flex;
    align-items: center;
    gap: 5px;
    font-size: 13px;
    font-weight: 600;
    color: #33D17A;
}

.ott-signed-in-state svg { display: block; width: 14px; height: 14px; fill: currentColor; }

/* The address whole, wrapping if it must: a shortened address is not one a
   viewer can check. */
.ott-signed-in-email { font-size: 17px; font-weight: 600; overflow-wrap: break-word; word-wrap: break-word; }

/* About: the logo and name, then grouped rows — a settings page's list. */
.ott-about-head { margin-bottom: 22px; text-align: center; }
.ott-about-logo { display: block; max-width: 70%; max-height: 56px; margin: 0 auto 14px; }
.ott-focus-card .ott-about-head h1 { margin: 0; }

.ott-about-group {
    margin: 0 0 16px;
    border: 1px solid rgba(255,255,255,.12);
    border-radius: 12px;
    background-color: rgba(255,255,255,.06);
    overflow: hidden;
}

.ott-about-row {
    position: relative;
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 16px;
    padding: 14px 16px;
    font-size: 15px;
    color: inherit;
    text-align: left;
}

/* The line between rows starts at the text, not the card's edge, so a group
   reads as one list rather than a stack of boxes. */
.ott-about-row + .ott-about-row:before {
    content: "";
    position: absolute;
    top: 0;
    left: 16px;
    right: 0;
    height: 1px;
    background-color: rgba(255,255,255,.12);
}

.ott-about-label { flex: 0 0 auto; }

.ott-about-value {
    min-width: 0;
    text-align: right;
    opacity: .62;
    overflow-wrap: break-word;
    word-wrap: break-word;
    -webkit-user-select: all;
    user-select: all;
}

.ott-about-link { align-items: center; cursor: pointer; transition: background-color .12s ease; }
.ott-about-link:hover,
.ott-about-link:focus { background-color: rgba(255,255,255,.10); outline: none; }
.ott-about-link:focus { box-shadow: inset 0 0 0 2px currentColor; }
.ott-about-link:active { background-color: rgba(255,255,255,.16); }
.ott-about-chevron { flex: 0 0 auto; width: 14px; height: 14px; opacity: .4; }

.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; }
}
