@font-face { font-family: "Manrope"; src: url("/assets/Manrope.woff2") format("woff2"), url("/assets/Manrope.ttf") format("truetype"); font-weight: 200 800; font-display: swap; }

:root {
  --bg: #0b0b0f; --bg2: #16141e; --panel: #1b1924; --line: rgba(246, 244, 240, .12);
  --ink: #f6f4f0; --muted: #a8a4b3; --red: #e52634; --red-2: #ff4453; --good: #3ccf8e; --warn: #f5b841;
  /* Side gutters clear a landscape iPhone's notch (viewport-fit=cover). */
  --radius: 10px; --gutter: max(clamp(16px, 4vw, 56px), env(safe-area-inset-left), env(safe-area-inset-right)); --card: clamp(118px, 13vw, 200px);
  /* Focus is white everywhere (a dark gap, then a white ring): red only means live or an error. */
  --focus: 0 0 0 3px var(--bg), 0 0 0 6px var(--ink);
  /* Artwork takes focus as light (docs/design.md): a white edge, a soft glow, a shadow under the lift. */
  --focus-art: 0 0 0 3px var(--ink), 0 0 26px rgba(246, 244, 240, .32), 0 14px 32px rgba(0, 0, 0, .6);
  /* Secondary text on imagery or a translucent layer (docs/design-language.md, colour): muted fails there. */
  --on-art: #cfccd8;
  /* Type steps (docs/design-language.md, type): size, leading, tracking, weight. Longhands, never the
     font shorthand (it resets font-variant-numeric). Rules move onto them when touched, no sweep.
     Clamped text with overflow: hidden needs leading 1.4 or more: Ş and Ç descend .31em at 600. */
  --t-display-size: clamp(2rem, 5vw, 3.6rem); --t-display-lh: 1.15; --t-display-ls: -.02em; --t-display-w: 800;
  --t-title1-lh: 1.15; --t-title2-size: 1.4rem; --t-title2-lh: 1.2; --t-title2-ls: -.015em; --t-title2-w: 700;
  --t-title3-size: 1.25rem; --t-title3-lh: 1.25; --t-title3-ls: -.01em; --t-title3-w: 700;
  --t-headline-size: 1.05rem; --t-headline-lh: 1.3; --t-headline-w: 700;
  --t-body-size: 1.05rem; --t-body-lh: 1.55; --t-body-w: 400;
  --t-callout-size: .92rem; --t-callout-lh: 1.4; --t-callout-w: 600;
  --t-caption-size: .85rem; --t-caption-lh: 1.4; --t-caption-ls: .005em; --t-caption-w: 600;
  --t-caption2-size: .75rem; --t-caption2-lh: 1.3; --t-caption2-ls: .01em; --t-caption2-w: 600;
  /* Motion (docs/motion.md): strong curves; the built-in ones are too weak. */
  --ease-out: cubic-bezier(0.23, 1, 0.32, 1);
  color-scheme: dark;
}
* { box-sizing: border-box; }
[hidden] { display: none !important; }
html, body { margin: 0; background: var(--bg); color: var(--ink); font-family: "Manrope", system-ui, sans-serif; -webkit-font-smoothing: antialiased; }
body { min-height: 100vh; overflow-x: hidden; }
a { color: inherit; text-decoration: none; }
button { font: inherit; color: inherit; background: none; border: 0; cursor: pointer; }
/* 10-foot step (docs/design.md): TV browsers at 1600px+ scale every rem by 1.25 (16 -> 20px base).
   html.tv comes from the user agent (ui.js) for TV browsers that report a fine pointer. */
@media (min-width: 1600px) and (pointer: none), (min-width: 1600px) and (pointer: coarse) { html { font-size: 125%; } }
@media (min-width: 1600px) { html.tv { font-size: 125%; } }
/* A big screen with no hover (Android TV and Fire TV browsers, casting sticks) is a couch screen too;
   desktops always hover, so their type stays put. */
@media (min-width: 1800px) and (hover: none) { html { font-size: 125%; } }
.sr-only { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
.muted { color: var(--muted); }
:focus { outline: none; }
:focus-visible, .episode:focus { box-shadow: var(--focus); border-radius: var(--radius); }

/* ---------- icons (js/icons.js: 24px grid, 1.5px stroke, currentColor) ---------- */
.icon { width: 1.25em; height: 1.25em; flex: none; fill: none; stroke: currentColor; stroke-width: 1.5; stroke-linecap: round; stroke-linejoin: round; vertical-align: -.25em; }
.icon.solid { fill: currentColor; }

/* ---------- buttons & fields ---------- */
.btn { display: inline-flex; align-items: center; gap: .5em; min-height: 44px; padding: .7em 1.4em; border-radius: 8px; background: rgba(246, 244, 240, .16); font-weight: 700; font-size: 1rem; transition: background .15s, transform 200ms var(--ease-out); }
.btn:focus-visible { background: rgba(246, 244, 240, .28); }
.btn.primary { background: var(--ink); color: #111; }
.btn.primary:focus-visible { background: #fff; }
.btn .icon { margin-left: -.2em; }
.row-btns { display: flex; gap: 12px; flex-wrap: wrap; margin-top: 18px; }
/* A detail page's rating choices (app.js): wraps like .row-btns, every choice a full target. */
.rate-group { display: flex; flex-wrap: wrap; gap: 12px; }
.rate-group > * { min-height: 44px; min-width: 44px; }
.field { width: 100%; padding: 14px 16px; border-radius: 8px; border: 1px solid var(--line); background: var(--bg2); color: var(--ink); font: inherit; font-size: 1.05rem; }
.field:focus { border-color: var(--ink); }
.field:focus-visible { box-shadow: none; }   /* its white border already says so */
.field.pin { text-align: center; letter-spacing: .5em; font-size: 1.6rem; }
.field-label { font-weight: 700; font-size: .9rem; color: var(--ink); text-align: left; justify-self: start; }
.msg { min-height: 1.2em; color: var(--red-2); margin: 10px 0 0; }

/* ---------- gate / profiles ---------- */
.center-screen { min-height: 100vh; min-height: 100dvh; display: grid; place-content: center; justify-items: center; gap: 28px; padding: var(--gutter); text-align: center;
  background: radial-gradient(1200px 600px at 50% 110%, rgba(120, 18, 28, .45), transparent 60%), var(--bg); }
/* Text logo: randımanlı + red TV badge (brand kit colours, Manrope). */
.brand-mark { display: inline-flex; align-items: center; gap: .18em; font-weight: 800; font-size: clamp(1.9rem, 5vw, 2.6rem); letter-spacing: -.035em; color: var(--ink); line-height: 1; }
.brand-mark .tv { font-size: .42em; letter-spacing: .02em; background: var(--red); color: #fff; border-radius: .28em; padding: .22em .38em .2em; transform: translateY(-.55em); }
.brand-mark.big { font-size: clamp(2.6rem, 9vw, 4.2rem); }
.brand-mark.small { font-size: 1.45rem; }
@media (max-width: 720px) { .brand-mark.small { font-size: 1.15rem; } }
.gate { width: min(380px, 90vw); display: grid; gap: 10px; }
.gate p { color: var(--muted); margin: 0 0 8px; }
.gate .btn { justify-content: center; margin-top: 6px; }
.center-screen h1 { font-size: clamp(1.8rem, 4vw, 3rem); margin: 0; font-weight: 700; line-height: var(--t-title1-lh); }
/* TV pairing: the code is read from across the room. */
.gate.pair { width: min(560px, 90vw); }
.center-screen .pair-title { font-size: clamp(1.4rem, 3vw, 2rem); }
.pair-code { margin: 8px 0 16px; font-size: clamp(2.6rem, 8vw, 4.5rem); font-weight: 800; letter-spacing: .12em; line-height: 1.1; color: var(--ink);
  font-variant-numeric: tabular-nums; white-space: nowrap; }
.gate p.pair-code { color: var(--ink); }
.gate p.pair-code.waiting { color: var(--muted); opacity: .5; }
.gate.pair .msg { margin: 0; }
.profiles { display: flex; gap: clamp(16px, 3vw, 40px); flex-wrap: wrap; justify-content: center; }
.profile { display: grid; gap: 12px; justify-items: center; color: var(--muted); font-size: 1.1rem; padding: 8px; border-radius: 14px; transition: color .15s, transform 200ms var(--ease-out); }
.profile img { width: clamp(96px, 12vw, 160px); aspect-ratio: 1; border-radius: 50%; object-fit: cover; }
.profile:focus-visible { color: var(--ink); transform: scale(1.05); box-shadow: none; }
.profile:focus-visible img { box-shadow: var(--focus-art); }   /* the picture lights up, like a card */

/* Trailer: YouTube's player at 16:9, as large as the screen allows (a phone on its side too). */
.trailer-dialog { width: min(1100px, 94vw, calc(78vh * 16 / 9)); margin: auto; border: 0; padding: 12px; color: var(--ink); background: #000; border-radius: 16px; }
.trailer-dialog::backdrop { background: rgba(0, 0, 0, .85); }
.trailer-frame { display: block; width: 100%; aspect-ratio: 16 / 9; border: 0; border-radius: 10px; background: #000; }
.trailer-dialog .row-btns { justify-content: center; margin-top: 12px; }
/* PIN: native <dialog> (modal, inert background, Escape closes). */
.pin-dialog { width: min(360px, 92vw); margin: auto; border: 0; color: var(--ink); background: var(--panel); border-radius: 16px; padding: 28px; }
/* The scrim: black .85, never blurred, on every device (docs/design-language.md, materials). A blur
   behind it cost a TV 184 ms a key and showed nobody anything. */
.pin-dialog::backdrop { background: rgba(0, 0, 0, .85); }
.pin-dialog form { display: grid; gap: 12px; justify-items: center; }
.pin-dialog h2 { margin: 0; }
.pin-dialog .field-label { justify-self: center; color: var(--muted); font-weight: 600; }
.pin-dialog .row-btns { margin-top: 6px; }
.modal-avatar { width: 88px; height: 88px; border-radius: 50%; }

/* ---------- top bar ---------- */
/* Readable over bright art at the top of a page: a longer, stronger scrim. Scrolled, the bar is
   opaque and a 24 px edge fades the page into it (no line over moving content). A TV swaps at once. */
.topbar { position: fixed; top: 0; left: 0; right: 0; z-index: 20; display: flex; align-items: center; gap: clamp(12px, 2.5vw, 36px); padding: max(10px, env(safe-area-inset-top)) var(--gutter) 22px;
  background: linear-gradient(180deg, rgba(11, 11, 15, .94), rgba(11, 11, 15, .78) 55%, rgba(11, 11, 15, 0)); transition: background-color .2s; }
.topbar::after { content: ""; position: absolute; left: 0; right: 0; top: 100%; height: 24px; pointer-events: none; opacity: 0; transition: opacity .2s;
  background: linear-gradient(180deg, var(--bg), rgba(11, 11, 15, 0)); }
.topbar.scrolled { background-color: var(--bg); }
.topbar.scrolled::after { opacity: 1; }
html.tv .topbar, html.tv .topbar::after { transition: none; }
.brand { display: inline-flex; }
.topbar nav { display: flex; gap: clamp(10px, 2vw, 26px); overflow-x: auto; scrollbar-width: none; }
.topbar nav a { color: rgba(246, 244, 240, .78); font-weight: 600; white-space: nowrap; padding: 10px 2px; }
.topbar nav a.active { color: var(--ink); }
/* Where you are, by more than colour (inactive links are ink at .78): a 2 px bar under the label,
   out of the flow. Wider screens only; the phone's tab bar marks it with its icon and colour. */
@media (min-width: 721px) {
  .topbar nav a { position: relative; }
  .topbar nav a.active::after { content: ""; position: absolute; left: 2px; right: 2px; bottom: 4px; height: 2px; border-radius: 1px; background: currentColor; }
}
/* Tablets (iPad portrait, small laptops): all seven sections fit on one line, none cut off. */
@media (min-width: 721px) and (max-width: 1100px) {
  .topbar nav { gap: 10px; }
  .topbar nav a { font-size: .9rem; }
  .brand-mark.small { font-size: 1.25rem; }
}
@media (min-width: 721px) and (max-width: 820px) {
  .topbar { gap: 10px; }
  .topbar nav { gap: 5px; }
  .topbar nav a { font-size: .85rem; }
}
.nav-icon { display: none; }
.spacer { flex: 1; }
.icon-link { position: relative; display: grid; place-items: center; width: 44px; height: 44px; font-size: 1.2rem; color: var(--ink); }
.icon-link.active::after { content: ""; position: absolute; left: 12px; right: 12px; bottom: 2px; height: 2px; border-radius: 1px; background: currentColor; }
.back-link { margin-left: -10px; color: var(--ink); }
.me { display: grid; place-items: center; width: 44px; height: 44px; border-radius: 50%; }
.me img { width: 34px; height: 34px; border-radius: 50%; display: block; }

/* ---------- hero & detail ---------- */
.page { padding-bottom: 64px; }
.hero, .detail { position: relative; min-height: min(78vh, 760px); display: flex; align-items: flex-end; padding: calc(120px + env(safe-area-inset-top)) var(--gutter) 48px; }
.hero-none { height: 80px; }
.hero-bg { position: absolute; top: 0; right: 0; bottom: 0; left: 0; background-size: cover; background-position: center 20%; background-color: var(--bg2);
  mask-image: linear-gradient(180deg, #000 55%, transparent 100%); -webkit-mask-image: linear-gradient(180deg, #000 55%, transparent 100%); }
.hero-bg::after { content: ""; position: absolute; top: 0; right: 0; bottom: 0; left: 0;
  background: linear-gradient(90deg, rgba(11, 11, 15, .92) 0%, rgba(11, 11, 15, .8) 35%, rgba(11, 11, 15, .45) 60%, rgba(11, 11, 15, 0) 80%); }
/* No backdrop at TMDB: the poster itself, whole, on the right (app.js backdrop). */
.hero-bg.poster-bg { background-size: contain; background-repeat: no-repeat; background-position: right var(--gutter) top calc(80px + env(safe-area-inset-top)); }
.hero-body, .detail-body { position: relative; max-width: 640px; }
/* 1.15: at 1.05 a two-line Turkish title's ğ and y sit on the next line's İ dot. */
.hero h1, .detail h1 { font-size: var(--t-display-size); margin: 0 0 10px; line-height: var(--t-display-lh); font-weight: var(--t-display-w); letter-spacing: var(--t-display-ls); text-wrap: balance; }
.meta { color: var(--muted); font-weight: 600; margin: 6px 0; white-space: pre-wrap; }
.meta-strip { color: var(--on-art); }
/* Title art: a fixed box, so a logo that loads with the page moves nothing. Wide logos fill the
   width, tall ones the height; bottom-left keeps them on the text's edge. */
.title.has-logo { margin-bottom: 18px; line-height: 0; }
.title .logo { display: block; width: min(100%, 480px); height: clamp(72px, 15vh, 150px); object-fit: contain; object-position: left bottom;
  filter: drop-shadow(0 2px 14px rgba(0, 0, 0, .55)); }
.title.fade .logo { animation: logo-in 300ms var(--ease-out); }
@keyframes logo-in { from { opacity: 0; } }
.ep-line { font-weight: 700; margin: 0 0 4px; font-size: 1.05rem; }
.meta-strip, .ends { text-shadow: 0 1px 8px rgba(0, 0, 0, .7); }
.meta-strip { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 1em; font-size: 1.05rem; white-space: normal; }
.cert { padding: 1px 7px; border: 1.5px solid currentColor; border-radius: 5px; font-size: .8rem; font-weight: 800; letter-spacing: .02em; line-height: 1.4; }
.stars { position: relative; display: inline-flex; color: rgba(246, 244, 240, .22); }
.stars-row { display: inline-flex; }
.stars .icon { width: 1.15em; height: 1.15em; stroke: none; vertical-align: 0; }
.stars-fill { position: absolute; top: 0; right: auto; bottom: 0; left: 0; overflow: hidden; color: var(--ink); }
.ends { display: flex; align-items: center; gap: 8px; color: var(--on-art); font-weight: 600; margin: 12px 0 0; font-variant-numeric: tabular-nums; }
.ends .icon { width: 1.2em; height: 1.2em; }
.overview { font-size: 1.05rem; line-height: 1.55; color: #e4e1ea; }
/* The hero keeps a short synopsis (3 lines on phones); a detail page shows all of it. */
.hero .overview { display: -webkit-box; -webkit-line-clamp: 4; -webkit-box-orient: vertical; overflow: hidden; }
/* Cast, director and genres under the buttons: links, so a remote reaches them on its way down. */
.credits { display: grid; gap: 8px; margin-top: 18px; }
/* The labels sit in a gutter, so every line's chips start at one edge: Down from a chip, or from the
   buttons, reaches the chip right below it instead of skipping a line whose label pushed it aside. */
.credit-line { position: relative; display: flex; flex-wrap: wrap; align-items: center; gap: 6px 8px; padding-left: 7rem; }
.credit-label { position: absolute; left: 0; top: 0; height: 36px; display: flex; align-items: center; color: var(--muted); font-weight: 600; font-size: .92rem; }
.credits .chip { display: inline-flex; align-items: center; min-height: 36px; padding: 6px 14px; color: var(--ink); text-decoration: none; }
/* Height reserved: the language badges arrive after PlaybackInfo, without pushing the text down. */
.badges { display: flex; gap: 8px; flex-wrap: wrap; margin: 8px 0; min-height: 28px; }
.badge { display: inline-flex; align-items: center; gap: 6px; padding: 4px 10px; border-radius: 999px; background: rgba(246, 244, 240, .12); font-size: .85rem; font-weight: 700; }
.badge .icon { width: 16px; height: 16px; }
.badge.good { background: rgba(60, 207, 142, .18); color: #9ff0c9; }
.badge.warn { background: rgba(245, 184, 65, .18); color: #ffd98a; }

/* ---------- rows & cards ---------- */
.row { margin: 26px 0 0; }
.row h2 { font-size: 1.25rem; margin: 0 var(--gutter) 10px; font-weight: 700; }
.row-link { display: inline-flex; align-items: center; gap: 2px; }
.row-link .icon { width: 1em; height: 1em; }
/* A row's swipe ends at its end: it never chains into the page or the browser's back gesture. */
.track { display: flex; gap: 10px; overflow-x: auto; overscroll-behavior-x: contain; padding: 8px var(--gutter) 14px; scroll-padding: 0 var(--gutter); scrollbar-width: none; scroll-snap-type: x proximity; }
.track::-webkit-scrollbar { display: none; }
/* A mouse without a sideways wheel: a page back or on (ui.js scrollable). Hovering fine pointers
   only; remotes and touch screens never see them. */
.track-wrap { position: relative; }
.row-arrow { display: none; }
@media (hover: hover) and (pointer: fine) {
  .row-arrow:not([hidden]) { display: grid; place-items: center; position: absolute; top: 8px; bottom: 14px; z-index: 3; width: max(44px, var(--gutter));
    color: var(--ink); opacity: 0; transition: opacity .18s; cursor: pointer; }
  .row-arrow.prev { left: 0; background: linear-gradient(90deg, rgba(11, 11, 15, .85), transparent); }
  .row-arrow.next { right: 0; background: linear-gradient(270deg, rgba(11, 11, 15, .85), transparent); }
  .row-arrow.prev .icon { transform: rotate(180deg); }
  .row-arrow .icon { width: 32px; height: 32px; }
  .track-wrap:hover .row-arrow { opacity: 1; }
}
.card { position: relative; flex: 0 0 var(--card); display: flex; flex-direction: column; gap: 6px; border-radius: var(--radius); scroll-snap-align: start; transition: transform 200ms var(--ease-out); }
.card.wide { flex-basis: calc(var(--card) * 1.9); }
.poster { position: relative; display: block; aspect-ratio: 2/3; border-radius: var(--radius); overflow: hidden; background: var(--panel); }
.card.wide .poster { aspect-ratio: 16/9; }
.poster img { width: 100%; height: 100%; object-fit: cover; display: block; }
.card.broken .poster img { visibility: hidden; }
.card:focus-visible { box-shadow: none; transform: scale(1.06); z-index: 2; }
.card:focus-visible .poster { box-shadow: var(--focus-art); }
/* Titles: over the poster on hover/focus with a pointer; always shown under it on touch screens. */
.card-title { position: absolute; top: auto; right: 0; bottom: 0; left: 0; padding: 26px 10px 10px; border-radius: 0 0 var(--radius) var(--radius); font-size: .85rem; font-weight: 700;
  background: linear-gradient(0deg, rgba(0, 0, 0, .85), transparent); opacity: 0; transition: opacity .18s; pointer-events: none; }
.card.wide .card-title, .card:focus-visible .card-title { opacity: 1; }
.card.wide .card-title { padding-bottom: 16px; }
.card.broken .card-title { opacity: 1; top: 0; right: 0; bottom: 0; left: 0; display: grid; place-items: center; padding: 12px; text-align: center; background: none; border-radius: var(--radius); }
/* Turkish-dub mark: a small brand-red tag, top left, legible over any poster. */
.dub-mark { position: absolute; top: 8px; left: 8px; padding: 3px 6px 2px; border-radius: 5px; background: var(--red); color: #fff; font-size: .68rem; font-weight: 800; letter-spacing: .06em; line-height: 1; box-shadow: 0 1px 6px rgba(0, 0, 0, .35); }
.bar { position: absolute; left: 8px; right: 8px; bottom: 6px; height: 4px; border-radius: 2px; background: rgba(255, 255, 255, .25); overflow: hidden; }
.bar > span { display: block; height: 100%; background: var(--red); }
/* Placeholders while a row or search answer loads: the poster's shape, no motion. */
.card.skel { pointer-events: none; }
.card.skel .poster { background: var(--panel); }
.grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(var(--card), 1fr)); gap: 14px; padding: 8px var(--gutter); }
.grid .card { flex: none; }
.grid .empty { grid-column: 1 / -1; padding: 12px 0; }
/* Fixed offsets clear the top bar, which grows by the status bar in the home-screen app (black-translucent). */
.page-title { margin: calc(96px + env(safe-area-inset-top)) var(--gutter) 10px; }
.empty { color: var(--muted); padding: 20px var(--gutter); }
.empty p { margin: 0 0 6px; }
.empty > p:first-child { color: var(--ink); font-weight: 700; }
.page-error { padding-top: calc(120px + env(safe-area-inset-top)); }
.search-bar { padding: calc(84px + env(safe-area-inset-top)) var(--gutter) 10px; }
.field.search { font-size: 1.4rem; padding: 18px 20px; }
.sub-head { font-size: 1.05rem; font-weight: 700; color: var(--muted); margin: 18px var(--gutter) 2px; }

@media (hover: hover) {
  .btn:hover { background: rgba(246, 244, 240, .28); }
  .btn.primary:hover { background: #fff; }
  .profile:hover { color: var(--ink); transform: scale(1.05); }
  .topbar nav a:hover, .icon-link:hover { color: var(--ink); }
  .card:hover { transform: scale(1.06); z-index: 2; }
  .card:hover .card-title { opacity: 1; }
  .episode:hover { background: rgba(246, 244, 240, .1); }
  .episode:hover p { display: block; }
  .icon-btn:hover, .menu-item:hover { background: rgba(255, 255, 255, .12); }
}
@media (hover: none) {
  .card-title { position: static; padding: 0 2px; opacity: 1; background: none; font-weight: 600; font-size: .8rem; line-height: var(--t-caption-lh); color: #e4e1ea;
    display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
  .card.wide .card-title { padding: 0 2px; }
}

/* ---------- calm TV mode (html.tv, ui.js) ---------- */
/* A TV's chip repaints slowly, and a remote press must answer at once (docs/motion.md): nothing
   eases, blurs or masks there. The focused card still lifts, with a plain white edge instead of
   the glow; the hero fades into the page under a gradient instead of a mask; the logo has no shadow. */
html.tv { --focus-art: 0 0 0 4px var(--ink); }
html.tv .card, html.tv .poster, html.tv .card-title, html.tv .profile { transition: none; }
html.tv .hero-bg { mask-image: none; -webkit-mask-image: none; }
html.tv .hero-bg::before { content: ""; position: absolute; top: 0; right: 0; bottom: 0; left: 0; background: linear-gradient(180deg, rgba(11, 11, 15, 0) 55%, var(--bg) 100%); }
html.tv .title .logo { filter: none; }
/* One row of buttons on a TV, so Play to Benzerleri stays two or three presses: the buttons take the
   screen's width (a resumed, dubbed film with a trailer has seven, about 75rem in Manrope 700), and
   only the text keeps a reading width. In rem, so html.tv's 125% scales it with the labels. */
html.tv .detail-body { max-width: none; }
html.tv .detail-body > :not(.row-btns) { max-width: 52rem; }

/* ---------- the browser floor: Chromium 85 (Tizen 6.5) ---------- */
/* inset is Chromium 87: written out as top, right, bottom and left everywhere but the player's rules. */
@supports not (inset: 0) {
  .player, .player-overlay, .player-controls, .menu-scrim { top: 0; right: 0; bottom: 0; left: 0; }
}
/* aspect-ratio is Chromium 88. A box as wide as its parent takes its height from padding (a share of
   that width); a box of known width gets the height that width gives. */
@supports not (aspect-ratio: 1) {
  .poster { height: 0; padding-top: 150%; }
  .card.wide .poster { padding-top: 56.25%; }
  .poster img { position: absolute; top: 0; left: 0; }
  .card.service .poster { height: calc(var(--card) * 1.3 * .5625); padding-top: 0; }
  .card.service .poster img { position: static; }
  /* A grid that centres its label needs a real height: its row would start below the padding. */
  .card.more-tile .poster { height: calc(var(--card) * 1.5); padding-top: 0; }
  .dl-poster { height: 84px; }
  .profile img { height: clamp(96px, 12vw, 160px); }
  .trailer-frame { height: calc((min(1100px, 94vw, 78vh * 16 / 9) - 24px) * 9 / 16); }
  /* An img's padding hides the picture: a height, from the column's 240px (120px on a phone). */
  .episode img { height: 135px; }
  @media (max-width: 720px) { .episode img { height: 67.5px; } }
}

/* ---------- seasons ---------- */
.seasons { padding: 0 var(--gutter); }
.season-tabs { display: flex; gap: 8px; overflow-x: auto; padding: 8px 0 4px; scrollbar-width: none; }
.tab { padding: 10px 16px; border-radius: 999px; background: rgba(246, 244, 240, .1); font-weight: 700; white-space: nowrap; }
.tab.active { background: var(--ink); color: #111; }
.episodes { display: grid; gap: 10px; }
.episode { position: relative; display: grid; grid-template-columns: minmax(120px, 240px) 1fr; gap: 16px; text-align: left; padding: 10px; border-radius: var(--radius); background: rgba(246, 244, 240, .04); }
.episode:focus { background: rgba(246, 244, 240, .1); }
.episode img { width: 100%; aspect-ratio: 16/9; object-fit: cover; border-radius: 8px; background: var(--panel); }
.episode img.broken { visibility: hidden; }
.episode h3 { margin: 4px 0 6px; font-size: 1.05rem; }
.episode p { margin: 0; color: var(--muted); font-size: var(--t-callout-size); line-height: var(--t-callout-lh); display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; }
/* An episode shows its whole text where the remote or the keyboard rests (a tap plays it, so touch
   screens show it in full; a mouse gets it on hover, below). */
.episode:focus p { display: block; }
@media (hover: none) { .episode p { display: block; } }

/* ---------- İndirilenler (RealDebrid gathering) ---------- */
.btn.small { min-height: 36px; padding: .45em 1em; font-size: .9rem; }
.btn.danger { background: var(--red); color: #fff; }
.spinner.small { width: 16px; height: 16px; border-width: 2px; }
.gather { display: flex; align-items: center; flex-wrap: wrap; gap: 8px 14px; margin-top: 12px; }
.gather-meta { color: var(--muted); font-size: .88rem; font-weight: 600; font-variant-numeric: tabular-nums; }
.gather-status { display: inline-flex; align-items: center; gap: 10px; min-height: 44px; font-weight: 700; font-variant-numeric: tabular-nums; }
.gather-status.failed { color: #ffd98a; }
.ring { width: 24px; height: 24px; transform: rotate(-90deg); fill: none; stroke-width: 2.5; }
.ring-track { stroke: rgba(246, 244, 240, .18); }
.ring-fill { stroke: var(--red); stroke-linecap: round; transition: stroke-dasharray .4s; }
.season-tools .gather { margin: 0; }
/* The answer arrives 0.2–4 s after paint: on detail pages and seasons the slot keeps its height
   (invisible while empty) so the bottom-anchored title and Play button never jump. */
.detail-body > .gather, .season-tools .gather { min-height: 44px; }
.detail-body > .gather[hidden], .season-tools .gather[hidden] { display: flex !important; visibility: hidden; }
/* That slot already spaces a movie's detail from the row below: no bottom padding on top of it. */
.detail.movie { padding-bottom: 0; }
.player-error .gather { justify-content: center; margin: 4px 0 16px; }
/* Nothing plays in this browser: İndir leads, one plain line under it says why. */
.gather-why { flex-basis: 100%; margin: 0; color: var(--muted); font-size: .92rem; }
.no-copy { margin: 12px 0 4px; color: var(--muted); font-weight: 600; }
.dl-list { display: grid; gap: 8px; padding: 8px var(--gutter); max-width: 900px; }
.dl-row { display: flex; align-items: center; gap: 8px; border-radius: var(--radius); background: rgba(246, 244, 240, .04); padding-right: 8px; }
.dl-main { flex: 1; min-width: 0; display: flex; align-items: center; gap: 14px; padding: 8px; text-align: left; border-radius: var(--radius); }
.dl-main:focus-visible { background: rgba(246, 244, 240, .08); }
.dl-poster { flex: none; width: 56px; aspect-ratio: 2/3; border-radius: 6px; overflow: hidden; background: var(--panel); }
.dl-poster img { width: 100%; height: 100%; object-fit: cover; display: block; }
.dl-poster img.broken { visibility: hidden; }
.dl-text { flex: 1; min-width: 0; display: grid; gap: 3px; }
.dl-title { font-weight: 800; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.dl-sub { color: var(--muted); font-size: .85rem; }
.dl-bar { display: block; height: 3px; border-radius: 2px; background: rgba(246, 244, 240, .14); overflow: hidden; margin-top: 4px; }
.dl-bar > span { display: block; height: 100%; background: var(--red); transition: width .4s; }
.dl-row.ready .dl-bar > span { background: var(--good); }
.dl-status { display: flex; justify-content: space-between; gap: 12px; font-size: .82rem; font-weight: 700; color: var(--muted); }
.dl-row.ready .dl-state { color: #9ff0c9; }
.dl-row.failed .dl-state { color: #ffd98a; }
.dl-pct { font-variant-numeric: tabular-nums; }
.dl-actions { display: flex; align-items: center; gap: 8px; flex: none; }
.dl-ask { font-size: .88rem; color: var(--muted); }
.dl-empty { padding-left: 0; padding-right: 0; }
@media (hover: hover) { .dl-main:hover { background: rgba(246, 244, 240, .08); } }
@media (max-width: 720px) {
  .dl-row { flex-wrap: wrap; padding-right: 0; }
  .dl-actions { margin-left: auto; padding: 0 8px 8px; }
  .dl-row .dl-actions:has(.icon-btn:only-child) { margin: 0 4px 0 0; padding: 0; }
}

/* ---------- live tv ---------- */

/* ---------- player ---------- */
.player { position: fixed; inset: 0; z-index: 100; background: #000; cursor: none; }
/* The page under an open player keeps no scrollbar, and the wheel or PageDown can't scroll it
   (claim adds the class; the full-screen element is the page itself, so its own overflow counts).
   :has() is its own rule: Chromium 80 drops a selector list it can't read. */
html.player-open { overflow: hidden; }
html:has(> body > .player) { overflow: hidden; }
.player.show-ui { cursor: default; }
/* Subtitles are the browser's own, laid out in the <video> box, not the picture. The film player
   (fitPicture) makes that box the picture plus a band of the black bar under it when the bar holds
   two lines, so a letterboxed film's subtitles sit just under the picture (on it when the bar is
   thinner), and it lifts them over the control bar while it shows. Unset (live TV, before the size
   is known) the video fills the player. */
.player { --cue-font: clamp(18px, 2.6vw, 34px); }
.player.sub-s { --cue-font: clamp(15px, 2vw, 26px); }
.player.sub-l { --cue-font: clamp(24px, 3.5vw, 46px); }
.player-video { position: absolute; left: 0; top: var(--pic-top, 0px); width: 100%; height: var(--pic-h, 100%); object-fit: contain;
  object-position: 50% var(--pic-y, 50%); font-size: var(--cue-font); background: #000; }
.player-video::cue { font-family: "Manrope", sans-serif; font-size: var(--cue-font); background: rgba(0, 0, 0, .55); }
/* The last frame held over the video while it goes over to another path (player.js holdFrame): taps reach the video. */
.frame-hold { pointer-events: none; }
/* Two rules: one unknown pseudo-element in a selector list drops the whole rule. WebKit (as its own
   controls do) shortens the cue container; Chromium ignores that height but moves each cue. Native
   full screen and PiP size the container inline, so neither applies there. Chromium's cues move
   with the control bar, in and out at its pace. */
.player.show-ui .player-video::-webkit-media-text-track-container { height: calc(100% - var(--cue-lift, 0px)); }
.player .player-video::-webkit-media-text-track-display { transition: transform .25s ease; }
.player.show-ui .player-video::-webkit-media-text-track-display { transform: translateY(calc(-1 * var(--cue-lift, 0px)));
  transition-duration: .1s; transition-timing-function: var(--ease-out); }
/* Subtitle looks (prefs.subStyle; the box above is "box"). iPhone's own full-screen player and a
   system caption style the viewer set win over these. */
.player.cue-shadow .player-video::cue { background: transparent; text-shadow: 0 0 2px #000, 0 0 4px #000, 0 2px 6px rgba(0, 0, 0, .9); }
.player.cue-yellow .player-video::cue { color: #ffd60a; background: rgba(0, 0, 0, .85); }
/* The subtitles the page draws (player.js drawCues, cues.js): over the video's box (fitPicture), rising
   with the bar like the browser's own. The ::cue rules above are for where the browser draws them. */
.cue-layer { position: absolute; left: 0; top: var(--pic-top, 0px); width: 100%; height: var(--pic-h, 100%); pointer-events: none;
  font: 500 var(--cue-font)/1.3 "Manrope", sans-serif; color: #fff; transition: transform .25s ease; }
.player.show-ui .cue-layer { transform: translateY(calc(-1 * var(--cue-lift, 0px))); }
.cue-band { position: absolute; left: 4%; right: 4%; display: flex; flex-direction: column; gap: .08em; }
.cue-band.top { top: .4em; }
.cue-band.middle { top: 50%; transform: translateY(-50%); }
.cue-band.bottom { bottom: .4em; }
.cue-line { text-align: center; }
.cue-line.start { text-align: start; }
.cue-line.end { text-align: end; }
.cue-text { white-space: pre-line; background: rgba(0, 0, 0, .55); padding: 0 .25em; -webkit-box-decoration-break: clone; box-decoration-break: clone; }
.player.cue-shadow .cue-text { background: transparent; text-shadow: 0 0 2px #000, 0 0 4px #000, 0 2px 6px rgba(0, 0, 0, .9); }
.player.cue-yellow .cue-text { color: #ffd60a; background: rgba(0, 0, 0, .85); }
/* Above the controls layer (both inset: 0): tap-to-play and the error card stay tappable while the
   controls show; the overlay itself lets taps through to them. */
.player-overlay { position: absolute; inset: 0; display: grid; place-items: center; pointer-events: none; z-index: 1; }
.player-overlay > * { pointer-events: auto; grid-area: 1 / 1; }
.player-status { font-size: 1.2rem; color: var(--muted); padding: 12px 20px; border-radius: 10px; background: rgba(0, 0, 0, .5); pointer-events: none; }
.player-error { text-align: center; max-width: 520px; padding: 24px; }
.player-error p { color: var(--muted); }
.spinner { width: 48px; height: 48px; border-radius: 50%; border: 3px solid rgba(255, 255, 255, .2); border-top-color: var(--ink); animation: spin .9s linear infinite; pointer-events: none; }
@keyframes spin { to { transform: rotate(360deg); } }
/* The top scrim holds .55 where the title's second line sits (12%), so it reads on bright art. */
.player-controls { position: absolute; inset: 0; display: flex; flex-direction: column; justify-content: space-between; opacity: 0; transition: opacity .25s; pointer-events: none;
  background: linear-gradient(180deg, rgba(0, 0, 0, .78), rgba(0, 0, 0, .55) 12%, transparent 26%, transparent 70%, rgba(0, 0, 0, .8)); }
.player.show-ui .player-controls { opacity: 1; pointer-events: auto; }
.player-controls .top { display: flex; align-items: center; gap: 16px; padding: max(16px, env(safe-area-inset-top)) var(--gutter) 16px; }
.player-controls .bottom { padding: 0 var(--gutter) max(20px, env(safe-area-inset-bottom)); }
.player-title .pt-main, .live-label .pt-main { font-size: 1.3rem; font-weight: 800; }
/* Secondary text over the picture: --on-art (#CFCCD8), not muted, which is for solid surfaces. */
.player-title .pt-sub, .live-label .pt-sub { color: var(--on-art); }
.seekrow { position: relative; display: flex; align-items: center; gap: 12px; }
.seek-wrap { position: relative; flex: 1; min-width: 0; display: flex; align-items: center; }
/* Touch drags through a 44 px layer over the bar (player.js bindScrub); mouse, keys and TV use the range.
   It reaches up from the bar, never down: on a phone the times sit right under it (a tap on the length
   shows the time left), in landscape the buttons. */
.seek-hit { display: none; }
@media (pointer: coarse) { .seek-hit { display: block; position: absolute; left: 0; right: 0; top: -20px; bottom: 0; touch-action: none; } }
html.tv .seek-hit { display: none; }
/* Above the thumb while it is dragged, or where a press sends the film: the time there, how far
   ("+30 sn") and the segment it falls in. The rail spans the thumb's travel (the bar less 12 px);
   player.js (paintBubble) moves it by a share of its own width, so placing the bubble reads no layout. */
.seek-rail { position: absolute; left: 6px; right: 6px; bottom: calc(100% + 6px); pointer-events: none; }
.seek-bubble { position: absolute; bottom: 0; left: 0; display: grid; justify-items: center; gap: 2px; padding: 6px 10px; border-radius: 8px;
  background: var(--panel); box-shadow: 0 6px 20px rgba(0, 0, 0, .5); white-space: nowrap; pointer-events: none; transform: translateX(-50%);
  opacity: 0; transition: opacity 250ms ease; }
.seek-bubble.show { opacity: 1; transition-duration: 100ms; }
.sb-time { font-weight: 800; font-variant-numeric: tabular-nums; }
.sb-seg, .sb-note { color: var(--muted); font-size: .82rem; font-weight: 700; }
.sb-note { font-variant-numeric: tabular-nums; }
/* The seek bar, drawn by hand so it reads calm: a 4 px track (6 px focused or dragged), the played
   part ink up to --p (player.js paintSeek) over the track at .40, a small ink thumb. Not red: red is
   live and errors only, and red on light grey told the two parts apart by hue alone (1.10:1). Each engine's pseudo-elements get
   rules of their own: one unknown pseudo-element voids a whole selector list. */
.seek { --track: 4px; flex: 1; min-width: 0; height: 24px; margin: 0; background: transparent; -webkit-appearance: none; appearance: none; }
.seek:focus-visible { --track: 6px; }
.seek:active, .seek.dragging { --track: 6px; }
.seek::-webkit-slider-runnable-track { height: var(--track); border-radius: 3px;
  background: linear-gradient(90deg, var(--ink) var(--p, 0%), rgba(246, 244, 240, .4) var(--p, 0%)); }
.seek::-webkit-slider-thumb { -webkit-appearance: none; width: 12px; height: 12px; margin-top: calc((var(--track) - 12px) / 2); border: 0; border-radius: 50%; background: var(--ink); }
.seek::-moz-range-track { height: var(--track); border-radius: 3px; background: rgba(246, 244, 240, .4); }
.seek::-moz-range-progress { height: var(--track); border-radius: 3px; background: var(--ink); }
.seek::-moz-range-thumb { width: 12px; height: 12px; border: 0; border-radius: 50%; background: var(--ink); }
/* Phones: the bar spans the full width, the times under it at either end. */
@media (max-width: 720px) {
  .seekrow { flex-wrap: wrap; justify-content: space-between; row-gap: 0; }
  .seekrow .seek-wrap { order: -1; flex-basis: 100%; }
  .seekrow .time { min-width: 0; font-size: .85rem; }
}
.time { font-variant-numeric: tabular-nums; color: #ddd; min-width: 60px; text-align: center; }
.player .dur { cursor: pointer; }   /* a tap shows the time left (player.js toggleLeft) */
/* Paused a while with no input (player.js settle): the controls fade as when idle (250 ms) and one
   card says where the viewer is, bottom left, until the next key or tap. A tint at .86, no blur: its
   time line reads 8:1 over a bright frame. */
.pause-card { position: absolute; left: var(--gutter); bottom: calc(40px + env(safe-area-inset-bottom)); z-index: 1; max-width: min(560px, calc(100vw - 2 * var(--gutter)));
  padding: 16px 20px; border-radius: 14px; background: rgba(22, 20, 30, .86); pointer-events: none;
  opacity: 0; visibility: hidden; transition: opacity 250ms ease, visibility 0s 250ms; }
.player.settled .pause-card { opacity: 1; visibility: visible; transition: opacity 250ms ease, visibility 0s; }
.pause-card p { margin: 0; }
.pc-title { font-size: 1.5rem; font-weight: 800; }
.pc-sub { margin-top: 4px; font-weight: 700; }
.pc-time { margin-top: 8px; color: var(--on-art); font-variant-numeric: tabular-nums; }
.buttons { display: flex; align-items: center; gap: 8px; margin-top: 6px; }
.icon-btn { display: grid; place-items: center; width: 48px; height: 48px; border-radius: 10px; font-size: 1.4rem; }
.icon-btn:focus-visible { background: rgba(255, 255, 255, .15); }
.buttons > .icon-btn { flex: none; }
/* "Ses ve altyazı": the captions icon and its name; on a phone the icon alone (player.js menuBtn). */
.buttons > .menu-btn { display: flex; gap: 8px; width: auto; padding: 0 14px 0 12px; font-size: 1rem; font-weight: 700; white-space: nowrap; }
.menu-btn .icon { font-size: 1.4rem; }
@media (max-width: 720px) {
  .buttons > .menu-btn { width: 44px; padding: 0; justify-content: center; }
  .menu-btn .mb-label { display: none; }
}
.next-ep { background: var(--ink); color: #111; white-space: nowrap; }
/* Settings menu: opaque (no video bleeding through), the picture dimmed behind it. A panel above
   the control bar on wide screens, a bottom sheet on phones, a side sheet on phones held sideways. */
.player { touch-action: manipulation; }   /* no double-tap zoom: a double tap skips 10 s */
.menu-scrim { position: absolute; inset: 0; z-index: 2; background: rgba(0, 0, 0, .6); }
.player-menu { position: absolute; right: var(--gutter); bottom: calc(110px + env(safe-area-inset-bottom)); z-index: 3; width: min(380px, 90vw); max-height: min(70vh, 560px);
  display: flex; flex-direction: column; background: var(--panel); border-radius: 14px; box-shadow: 0 12px 40px rgba(0, 0, 0, .5); }
.menu-grab { display: none; }
.menu-head { display: flex; align-items: center; gap: 8px; min-height: 56px; padding: 4px 4px 4px 16px; border-bottom: 1px solid var(--line); }
.menu-head h2 { flex: 1; margin: 0; font-size: 1.05rem; }
.menu-back { flex: 1; display: flex; align-items: center; gap: 10px; min-height: 48px; margin-left: -8px; padding: 0 8px; border-radius: 8px; font-weight: 800; font-size: 1.05rem; text-align: left; }
.menu-close { flex: none; color: var(--muted); }
.menu-body { overflow-y: auto; overscroll-behavior: contain; padding: 8px; }
/* More below: the last rows fade out instead of ending at a hard edge. */
.menu-body.more { -webkit-mask-image: linear-gradient(180deg, #000 calc(100% - 40px), transparent); mask-image: linear-gradient(180deg, #000 calc(100% - 40px), transparent); }
/* Nothing masks on a TV (docs/motion.md): the mask made each remote scroll of a long list 2.4x the raster. */
html.tv .menu-body.more { -webkit-mask-image: none; mask-image: none; }
.menu-body h3 { font-size: .85rem; color: var(--muted); margin: 14px 12px 6px; }
.menu-body h3 .h3-value { float: right; color: var(--ink); font-weight: 700; }   /* Altyazı zamanlaması: "0,5 sn erken" */
.menu-sizes[data-group="timing"] .menu-item { justify-content: center; }
.menu-row, .menu-item { display: flex; align-items: center; gap: 12px; width: 100%; min-height: 48px; text-align: left; padding: 10px 12px; border-radius: 8px; }
.menu-row-label { font-weight: 700; flex: none; }
.menu-row-value { flex: 1; min-width: 0; text-align: right; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.menu-row .icon { color: var(--muted); }
.menu-item .icon { visibility: hidden; }
.menu-item[aria-checked="true"] { font-weight: 800; }
.menu-item[aria-checked="true"] .icon { visibility: visible; }
.menu-sizes { display: flex; gap: 4px; }
.menu-sizes .menu-item { flex: 1; gap: 6px; }
/* "Koyu kutu" in a third of a 390 px sheet wrapped onto two lines: each look as wide as its words, on one
   line (tighter under 340 px, where the three in Manrope need 330 px at 12 px padding). */
.menu-sizes[data-group="style"] .menu-item { flex: 1 1 auto; white-space: nowrap; }
@media (max-width: 340px) { .menu-sizes[data-group="style"] .menu-item { gap: 4px; padding-left: 6px; padding-right: 6px; } }
/* Solid, so the focused item reads from the couch and never looks like the selected (bold, checked) one. */
.menu-row:focus-visible, .menu-item:focus-visible, .menu-back:focus-visible { background: var(--ink); color: #111; box-shadow: none; }
.menu-row:focus-visible .icon, .menu-row:focus-visible .menu-row-value { color: #111; }
@media (max-width: 720px), (pointer: coarse) and (max-height: 500px) {
  .player-menu { left: 0; right: 0; bottom: 0; width: auto; max-height: 50vh; max-height: 50dvh; border-radius: 16px 16px 0 0; padding-bottom: env(safe-area-inset-bottom); }
  /* The phone's sheet going down on its spring (player.js sheetGo): closed (hidden) for everything else,
     drawn and untouchable until it is down. */
  .player-menu.closing[hidden] { display: flex !important; pointer-events: none; }
  .menu-scrim.closing[hidden] { display: block !important; pointer-events: none; }
  .menu-grab { display: block; width: 40px; height: 4px; margin: 8px auto 0; border-radius: 2px; background: rgba(246, 244, 240, .3); }
  .menu-head { min-height: 52px; }
}
/* Reduced motion: the spring jumps (spring.js), so the sheet fades in instead (150 ms). */
@media (max-width: 720px) and (prefers-reduced-motion: reduce) { .player-menu, .menu-scrim { animation: fade-in 150ms var(--ease-out); } }
@media (pointer: coarse) and (max-height: 500px) and (min-width: 721px) {
  .player-menu { left: auto; top: 0; width: min(380px, 50vw); max-height: none; border-radius: 16px 0 0 16px; padding-right: env(safe-area-inset-right); }
  .menu-grab { display: none; }
}
/* Error: a solid card on a dark scrim; the controls behind it go away. */
.player.failed .player-controls { display: none; }
.player.failed .player-overlay { background: rgba(0, 0, 0, .82); }
.player-error { background: var(--panel); border-radius: 16px; margin: 16px; }
.player-error h2 { margin: 0 0 8px; font-size: 1.3rem; }
.player-error .row-btns { justify-content: center; }
/* Up next: bottom right, above the controls, until picked, cancelled or counted down. */
.next-card { position: absolute; right: var(--gutter); bottom: calc(120px + env(safe-area-inset-bottom)); z-index: 2; width: min(360px, calc(100vw - 32px));
  padding: 16px 18px; border-radius: 14px; background: var(--panel); box-shadow: 0 12px 40px rgba(0, 0, 0, .5); }
.next-card p { margin: 0; }
.nc-kicker { color: var(--muted); font-size: .85rem; font-weight: 700; }
.nc-title { font-weight: 800; margin-top: 2px !important; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.nc-count { color: var(--muted); font-size: .9rem; margin-top: 6px !important; font-variant-numeric: tabular-nums; }
.next-card .row-btns { margin-top: 12px; }
@media (max-width: 720px) { .next-card { left: 16px; right: 16px; width: auto; bottom: calc(130px + env(safe-area-inset-bottom)); } }
/* "Nasıldı?" (player.js askRating): the up-next card's look at the bottom left, clear of the skip pill
   a film's mid-credits scene brings; as wide as its three verdicts. */
.rate-card { left: var(--gutter); right: auto; width: auto; max-width: calc(100vw - 2 * var(--gutter)); }
.rate-card .row-btns { flex-wrap: wrap; }
@media (max-width: 720px) { .rate-card { left: 16px; right: 16px; bottom: calc(190px + env(safe-area-inset-bottom)); } }   /* over the pill */
/* Skip intro, recap or credits: bottom right above the control bar, seen with or without it. In
   200 ms (fade and scale from .96), out 250 ms; hidden, it is out of the focus order and unread. */
.skip-wrap { position: absolute; right: var(--gutter); bottom: calc(120px + env(safe-area-inset-bottom)); z-index: 2; }
.skip-pill { background: rgba(22, 20, 30, .92); color: var(--ink); border: 1px solid rgba(246, 244, 240, .5); box-shadow: 0 8px 28px rgba(0, 0, 0, .5);
  opacity: 0; visibility: hidden; transform: scale(.96); transition: opacity 250ms ease, transform 250ms ease, visibility 0s 250ms; }
.skip-pill.show { opacity: 1; visibility: visible; transform: none; transition: opacity 200ms var(--ease-out), transform 200ms var(--ease-out), visibility 0s; }
.skip-pill:focus-visible { background: var(--ink); color: #111; }
.player.failed .skip-wrap { display: none; }
/* The soft dip around a skip (player.js dip): to black in 200 ms while the sound ramps down, back in
   300 ms once the new frame is in. Over the picture, under the controls and the pill. Ease-in going
   dark: the picture leaves gently and is black before the cut. Reduced motion keeps it: it is a fade. */
.skip-dip { position: absolute; top: 0; right: 0; bottom: 0; left: 0; background: #000; opacity: 0; pointer-events: none; transition: opacity 300ms var(--ease-out); }
.skip-dip.on { opacity: 1; transition: opacity 200ms ease-in; }
/* "Kaldığın yer 23:14": the place kept while the transcode runs from the beginning, under the title;
   with the controls, and alone for a moment when it first shows (.peek). */
.place-line { position: absolute; left: var(--gutter); top: calc(88px + env(safe-area-inset-top)); z-index: 2; display: flex; align-items: center; gap: 12px;
  max-width: calc(100vw - 2 * var(--gutter)); padding: 8px 14px; border-radius: 10px; background: rgba(22, 20, 30, .82); font-weight: 700; font-variant-numeric: tabular-nums;
  opacity: 0; visibility: hidden; transition: opacity 200ms var(--ease-out), visibility 0s 200ms; }
.player.show-ui .place-line, .place-line.peek { opacity: 1; visibility: visible; transition: opacity 200ms var(--ease-out), visibility 0s; }
.place-line { flex-wrap: wrap; row-gap: 8px; }
.place-line > * { white-space: nowrap; }
.place-line .btn { margin-right: -6px; }
.place-line[hidden], .player.failed .place-line { display: none; }
/* Remuxed in the page there is nothing AirPlay could send. */
.player.remuxing .airplay-btn { display: none; }
@media (hover: hover) { .skip-pill:hover { background: var(--ink); color: #111; } }
/* Double-tap skip: a mark on that side counting the run ("+30 sn", player.js ripple). Mounted once; in
   100 ms with a scale from .92 over 120 ms, out 250 ms. A further tap changes its number, never
   restarts it. Reduced motion: the scale goes (only opacity transitions there). */
.seek-ripple { position: absolute; top: 50%; z-index: 1; display: grid; place-items: center; width: 96px; height: 96px; margin-top: -48px; border-radius: 50%;
  background: rgba(255, 255, 255, .18); pointer-events: none; font-size: 1.1rem; font-weight: 800; font-variant-numeric: tabular-nums; white-space: nowrap;
  opacity: 0; transform: scale(.92); transition: opacity 250ms ease, transform 120ms var(--ease-out); }
.seek-ripple.on { opacity: 1; transform: none; transition-duration: 100ms, 120ms; }
@media (prefers-reduced-motion: reduce) { .seek-ripple { transform: none; } }
.seek-ripple.left { left: 12%; }
.seek-ripple.right { right: 12%; }

.toast { position: fixed; left: 50%; bottom: calc(32px + env(safe-area-inset-bottom)); z-index: 200; display: flex; align-items: center; gap: 12px; width: max-content; max-width: min(560px, calc(100vw - 32px));
  transform: translate(-50%, 20px); opacity: 0; background: var(--panel); padding: 12px 18px; border-radius: 10px; box-shadow: 0 8px 30px rgba(0, 0, 0, .45);
  transition: opacity 300ms var(--ease-out), transform 300ms var(--ease-out); }
.toast.show { opacity: 1; transform: translate(-50%, 0); }
.toast.error { border-left: 3px solid var(--red); padding-right: 8px; }
.toast.sticky { padding-right: 8px; }
.toast-close { display: grid; place-items: center; width: 36px; height: 36px; border-radius: 8px; flex: none; color: var(--muted); }
.toast-close:focus-visible { color: var(--ink); }

/* ---------- phones ---------- */
@media (max-width: 720px) {
  .topbar { gap: 10px; padding-top: max(8px, env(safe-area-inset-top)); padding-bottom: 8px; }
  /* Phones: the sections become a bottom tab bar (thumb reach, nothing cut off). */
  /* Opaque, with no blur and no line: a 20 px edge fades the page into it instead. Visible overflow,
     or the edge above it would be clipped (the labels fit: their size is capped below). */
  .topbar nav { position: fixed; left: 0; right: 0; bottom: 0; z-index: 30; justify-content: space-around; gap: 0; overflow: visible;
    padding: 6px 4px calc(6px + env(safe-area-inset-bottom)); background: var(--bg); }
  .topbar nav::before { content: ""; position: absolute; left: 0; right: 0; bottom: 100%; height: 20px; pointer-events: none;
    background: linear-gradient(0deg, var(--bg), rgba(11, 11, 15, 0)); }
  /* Five sections (Filmler and Diziler live in Keşfet on a phone): each as wide as its label needs
     (İndirilenler more than Listem), the rest shared. */
  /* Inactive labels on the opaque bar: muted (8:1). The size is capped: at 200% text every label
     overflowed ("İndirilenler" needs 122 px of 96), and tab bars don't scale their labels. */
  .topbar nav a { color: var(--muted); display: grid; justify-items: center; gap: 3px; font-size: min(.75rem, 14px); padding: 4px 1px; text-align: center; flex: 1 1 auto; min-width: 0; min-height: 48px; }
  .topbar nav a.nav-wide { display: none; }
  .nav-icon { display: block; width: 22px; height: 22px; }
  .page { padding-bottom: calc(84px + env(safe-area-inset-bottom)); }
  .hero, .detail { min-height: 62vh; padding-top: calc(96px + env(safe-area-inset-top)); padding-bottom: 32px; }
  .hero-none { height: calc(80px + env(safe-area-inset-top)); }
  .hero .overview { -webkit-line-clamp: 3; }
  /* No remote here: the label leads its line. */
  .credit-line { padding-left: 0; }
  .credit-label { position: static; height: auto; margin-right: 4px; }
  .title .logo { height: 80px; width: min(100%, 320px); }
  /* Text spans the full width here: shade from the bottom as well, so it reads on bright art. */
  .hero-bg::after { background: linear-gradient(0deg, rgba(11, 11, 15, .95) 0%, rgba(11, 11, 15, .75) 55%, rgba(11, 11, 15, 0) 90%),
    linear-gradient(90deg, rgba(11, 11, 15, .6), rgba(11, 11, 15, 0) 80%); }
  .episode { grid-template-columns: 120px 1fr; }
  /* "Sonraki bölüm" floats above the seek bar: in the button row it pushed fullscreen off-screen. */
  .player-controls .bottom { position: relative; }
  .next-ep { position: absolute; right: var(--gutter); bottom: calc(100% + 8px); }
  /* The pill clears the seek bar, and "Sonraki bölüm" floating above it when that shows. */
  .skip-wrap { bottom: calc(130px + env(safe-area-inset-bottom)); }
  .player.next-shown .skip-wrap { bottom: calc(186px + env(safe-area-inset-bottom)); }
  .toast { bottom: calc(84px + env(safe-area-inset-bottom)); }
  .icon-btn { width: 44px; height: 44px; }
  /* Thumb-sized targets (44px). */
  .toast-close { width: 44px; height: 44px; }
  .btn.small { min-height: 44px; }
  .dl-actions { gap: 12px; }
  .tab { min-height: 44px; }
}
@media (prefers-reduced-motion: reduce) {
  /* Fewer and gentler, not none: fades and colour changes stay (they explain what changed);
     movement goes (transforms apply at once). */
  /* visibility too: the pause card and the place line fade out instead of cutting. */
  * { transition-property: opacity, visibility, background-color, color, border-color !important; scroll-behavior: auto !important; }
  .card:hover, .card:focus-visible, .profile:hover, .profile:focus-visible { transform: none; }
  .spinner { animation-duration: 3s; }
  .seek-ripple { animation-name: fade-in-out; }
  .skip-pill, .skip-pill.show { transform: none; transition-property: opacity, visibility !important; }
}
/* Reduced transparency and increased contrast (docs/design-language.md, accessibility): the top
   bar and the marks over posters go opaque. More contrast also lifts muted text and lines and darkens
   the hero's scrim by .2 (a colour under its gradient, so the phone's own gradient gets it too).
   Chromium 85 on the TV knows none of these queries and keeps the base. */
@media (prefers-reduced-transparency: reduce) {
  .topbar, .topbar.scrolled { background: var(--bg); }
  .remove-mark { background: var(--bg); }
}
@media (prefers-contrast: more) {
  :root { --muted: #cfccd8; --line: rgba(246, 244, 240, .28); }
  .topbar, .topbar.scrolled { background: var(--bg); }
  .remove-mark { background: var(--bg); }
  .hero-bg::after { background-color: rgba(11, 11, 15, .2); }
}
/* Forced colours drop every box-shadow, and the focus ring is one: an outline takes its place. */
@media (forced-colors: active) {
  :focus-visible, .episode:focus, .card:focus-visible, .profile:focus-visible, .field:focus-visible { outline: 3px solid CanvasText; outline-offset: 2px; }
}
/* Its own rule (* matches no pseudo-element; an unknown one voids a list): the lift applies at once. */
@media (prefers-reduced-motion: reduce) { .player .player-video::-webkit-media-text-track-display, .cue-layer { transition: none; } }

/* Tap-to-play: shown only when a browser refuses to autoplay (iOS after async loading). */
.tap-play { display: grid; place-items: center; width: 132px; height: 132px; border-radius: 50%; background: rgba(229, 38, 52, .92); color: #fff; box-shadow: 0 10px 40px rgba(0, 0, 0, .5); }
.tap-play .icon { width: 56px; height: 56px; transform: translateX(3px); }
.tap-play small { position: absolute; margin-top: 190px; font-size: 1rem; color: var(--ink); white-space: nowrap; }
.tap-play:focus-visible { box-shadow: var(--focus); }

/* ---------- profile settings (js/settings.js) ---------- */
.settings { max-width: 760px; margin: 0 auto; padding: calc(96px + env(safe-area-inset-top)) var(--gutter) 48px; display: grid; gap: 28px; }
.set-head { display: grid; grid-template-columns: auto 1fr auto; align-items: center; gap: 20px; }
.set-head .page-title { margin: 0 0 4px; }
.set-head p { margin: 0; }
.set-avatar { width: 84px; height: 84px; border-radius: 16px; }
.set-saved { position: fixed; top: calc(76px + env(safe-area-inset-top)); left: 50%; z-index: 25; margin: 0; padding: 8px 16px; border-radius: 999px; background: var(--panel); color: var(--good);
  font-weight: 700; font-size: .9rem; opacity: 0; transform: translate(-50%, -6px); transition: opacity .2s, transform .2s; pointer-events: none; }
.set-saved.show { opacity: 1; transform: translate(-50%, 0); }
.set-group h2 { margin: 0 0 4px; font-size: 1.15rem; }
.set-hint { margin: 0 0 12px; color: var(--muted); }
.set-group h2 + .set-opts { margin-top: 12px; }
.set-opts { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: 10px; }
.set-opt, .set-switch { display: grid; gap: 4px; text-align: left; padding: 14px 16px; border-radius: 12px; background: var(--bg2); border: 1px solid var(--line);
  color: var(--ink); transition: border-color .15s, background .15s; }
/* Chosen: filled, with a check. The check's room is kept when unchosen, so nothing reflows. */
.set-opt[aria-checked="true"] { border-color: var(--ink); background: var(--ink); color: #111; }
.set-opt[aria-checked="true"] .set-opt-sub { color: #4a4652; }
.set-opt-label { display: flex; align-items: center; gap: 8px; font-weight: 700; }
.set-opt-label .icon { stroke-width: 2.5; visibility: hidden; }
.set-opt[aria-checked="true"] .set-opt-label .icon { visibility: visible; }
.set-group > .btn { margin-top: 12px; }
/* Televizyonu bağla: the code field and its button on one line, wrapping on narrow phones. */
.tv-link-form { display: flex; flex-wrap: wrap; gap: 10px; align-items: stretch; }
.tv-link-form .tv-code { width: min(240px, 100%); flex: 0 1 240px; letter-spacing: .25em; }
.tv-msg { margin: 10px 0 0; min-height: 1.35em; }
.tv-msg.bad { color: var(--red-2); }
/* Genres: wide enough for "Bilim kurgu" on one line with its check. */
.set-opts.chips, .set-opts.compact.chips { grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); }
.set-opt-sub { color: var(--muted); font-size: .88rem; line-height: 1.35; }
.set-switch { width: 100%; grid-template-columns: 1fr auto; align-items: center; gap: 16px; }
.set-switch-text { display: grid; gap: 4px; }
.set-knob { position: relative; width: 48px; height: 28px; border-radius: 999px; background: rgba(246, 244, 240, .2); transition: background .2s; }
.set-knob::after { content: ""; position: absolute; top: 3px; left: 3px; width: 22px; height: 22px; border-radius: 50%; background: var(--ink); transition: transform .2s; }
.set-switch[aria-checked="true"] .set-knob { background: var(--good); }
.set-switch[aria-checked="true"] .set-knob::after { transform: translateX(20px); }
/* Full width, fixed height (an aspect-ratio with a max-height would narrow it). */
.set-sample { margin-top: 12px; display: grid; place-items: end center; width: 100%; height: clamp(110px, 22vw, 160px); border-radius: 12px; padding: 16px;
  background: linear-gradient(180deg, #2a2733, #0e0d12); }
.set-sample span { background: rgba(0, 0, 0, .55); padding: 2px 8px; border-radius: 4px; }
.set-sample.sub-s span { font-size: 15px; }
.set-sample.sub-m span { font-size: 20px; }
.set-sample.sub-l span { font-size: 27px; }
.set-sample.cue-shadow span { background: transparent; text-shadow: 0 0 2px #000, 0 0 4px #000, 0 2px 6px rgba(0, 0, 0, .9); }
.set-sample.cue-yellow span { color: #ffd60a; background: rgba(0, 0, 0, .85); }
.set-note { margin: 0; font-size: .9rem; }
.me.active img { box-shadow: 0 0 0 2px var(--ink); }
@media (max-width: 720px) {
  .set-head { grid-template-columns: auto 1fr; }
  .set-head .btn { grid-column: 1 / -1; justify-self: start; }
  .set-avatar { width: 64px; height: 64px; }
  .set-opts { grid-template-columns: 1fr; gap: 8px; }
  .set-opts.compact { grid-template-columns: repeat(auto-fit, minmax(90px, 1fr)); }
}

/* ---------- Listem tools ---------- */
.list-head { display: flex; flex-wrap: wrap; align-items: end; justify-content: space-between; gap: 12px; margin: calc(96px + env(safe-area-inset-top)) var(--gutter) 10px; }
.list-head .page-title { margin: 0; }
.list-bar { display: flex; flex-wrap: wrap; gap: 8px; }
.chip { min-height: 40px; padding: 8px 16px; border-radius: 999px; background: rgba(246, 244, 240, .1); color: var(--muted); font: inherit; font-weight: 700; font-size: .92rem; border: 0; }
.chip[aria-pressed="true"] { background: var(--ink); color: #111; }
.chip.select { appearance: none; -webkit-appearance: none; padding-right: 32px; color: var(--ink);
  background: rgba(246, 244, 240, .1) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8'%3E%3Cpath d='M1 1l5 5 5-5' fill='none' stroke='%23a8a4b3' stroke-width='1.5'/%3E%3C/svg%3E") no-repeat right 12px center; }
.chip.select option { background: var(--panel); color: var(--ink); }
/* Phones: 44px chips, and 16px text so iOS does not zoom into the sort select. After the base rule, or it loses. */
@media (max-width: 720px) { .chip { min-height: 44px; font-size: 1rem; } }
.remove-mark { position: absolute; top: 8px; right: 8px; display: grid; place-items: center; width: 32px; height: 32px; border-radius: 50%; background: rgba(11, 11, 15, .82); color: var(--ink); }
.remove-mark .icon { width: 18px; height: 18px; }
.grid.editing .card .poster img { opacity: .7; }
.card.removable { text-align: left; color: var(--ink); }
.card.removable:focus-visible .remove-mark, .card.removable:hover .remove-mark { background: var(--red); }

/* İndirilenler summary line */
.dl-summary { margin: -4px var(--gutter) 14px; min-height: 1.2em; font-weight: 600; }

/* İndirilenler ready notice: toast action and the count on the nav link */
.toast { width: max-content; }   /* left: 50% alone shrinks it to half the screen on phones */
.toast-action { flex: none; min-height: 44px; padding: 8px 18px; border-radius: 8px; background: var(--ink); color: #111; font-weight: 800; }
.toast-action:focus-visible { background: #fff; }
.nav-dot { display: inline-grid; place-items: center; min-width: 18px; height: 18px; margin-left: 6px; padding: 0 5px; border-radius: 9px; background: var(--red); color: #fff;
  font-size: .7rem; font-weight: 800; line-height: 1; vertical-align: 1px; font-variant-numeric: tabular-nums; }
@media (max-width: 720px) {
  .topbar nav a { position: relative; }
  .nav-dot-box { position: absolute; top: 0; left: calc(50% + 6px); }
  .nav-dot { margin-left: 0; }
}

/* ---------- watching state: row edit (Continue Watching, Next Up), İzlendi, season tools ---------- */
.row-head { display: flex; align-items: center; gap: 12px; margin: 0 var(--gutter) 10px; }
.row-head h2 { margin: 0; }
.track.editing .card .poster img { opacity: .7; }
.track .remove-mark { width: 40px; height: 40px; }
.btn.seen .icon { opacity: .45; }
.btn.seen[aria-pressed="true"] .icon { opacity: 1; color: var(--good); stroke-width: 2.5; }
/* One button size and one baseline: "Sezonu izlendi olarak işaretle" next to "Sezonu indir". */
.season-tools { display: flex; flex-wrap: wrap; align-items: center; gap: 12px 14px; margin: 4px 0 12px; }

/* ---------- motion (docs/motion.md) ---------- */
/* Remote focus answers the key at once: the focused card and profile scale up without a
   transition (a D-pad hop is the most frequent action in the app), and the one left behind
   eases back. Pointer hover keeps the 200 ms ease-out from the base rules. */
.card:focus-visible, .card:focus-visible .card-title, .profile:focus-visible { transition: none; }
/* Press feedback for taps and clicks: the interface heard it. In fast (60 ms: an 80 ms tap releases
   before a 160 ms press-in ends), out slower (200 ms). */
.icon-btn, .chip, .tab, .toast-action { transition: transform 200ms var(--ease-out); }
.btn:active, .icon-btn:active, .chip:active, .tab:active, .toast-action:active { transform: scale(0.97); transition-duration: 60ms; }
.poster { transition: transform 200ms var(--ease-out); }
.card:active .poster { transform: scale(0.97); transition-duration: 60ms; }
/* Player controls appear with the key press that asks for them; the idle hide fades (.25s). */
.player.show-ui .player-controls { transition: opacity 100ms var(--ease-out); }
/* PIN and trailer dialogs: enter instead of teleporting over the page. Centred, so they scale from the centre. */
.pin-dialog[open], .trailer-dialog[open] { animation: pop-in 200ms var(--ease-out); }
@keyframes pop-in { from { opacity: 0; transform: scale(0.96); } }
@keyframes fade-in { from { opacity: 0; } }
@keyframes fade-in-out { 20% { opacity: 1; } from, to { opacity: 0; } }
@media (prefers-reduced-motion: reduce) { .pin-dialog[open], .trailer-dialog[open] { animation-name: fade-in; } }
/* A profile answers the press that picks it (app.js): the chosen one holds its lift and light, the
   others step back, and further picks are ignored until the app opens. Opacity only on a TV. */
.profile.chosen { color: var(--ink); transform: scale(1.05); }
.profile.chosen img { box-shadow: var(--focus-art); }
.picking .profile:not(.chosen) { opacity: .35; transition: opacity 150ms var(--ease-out); }
html.tv .picking .profile:not(.chosen) { transition: opacity 120ms var(--ease-out); }
/* A long press on an episode (app.js) shows it is being held from 150 ms: a slow press-in, transform only. */
.episode { transition: transform 200ms var(--ease-out); }   /* let go, it eases back from the hold */
.episode.holding { transform: scale(.97); transition: transform 450ms var(--ease-out); }
@media (prefers-reduced-motion: reduce) { .profile.chosen { transform: none; } .episode.holding { transform: none; opacity: .7; } }

/* ---------- pixel pets (js/pets.js): rare moments only ---------- */
.pets { position: fixed; left: 0; right: 0; bottom: var(--pet-ground, calc(14px + env(safe-area-inset-bottom))); height: 0; z-index: 40; pointer-events: none; }
.pet { position: absolute; left: 0; bottom: 0; transform-origin: 22% 100%; will-change: transform; }
.pet-nap { left: auto; right: max(24px, var(--gutter)); pointer-events: auto; cursor: pointer; }
.pet-sprite { background-repeat: no-repeat; image-rendering: pixelated; animation: pet-frames var(--fps, 360ms) steps(2) infinite; }
.pet-sprite.flip { transform: scaleX(-1); }
@keyframes pet-frames { to { background-position-x: var(--sheet); } }
.pet-bubble { position: absolute; bottom: calc(100% + 10px); left: 50%; transform: translateX(-50%); padding: 5px 10px; white-space: nowrap;
  font: 800 .8rem/1.2 Manrope, system-ui, sans-serif; color: #0b0b0f; background: #f6f4f0;
  box-shadow: 0 -3px 0 #2a1a12, 0 3px 0 #2a1a12, -3px 0 0 #2a1a12, 3px 0 0 #2a1a12; }
.pet-spark { position: absolute; bottom: 18px; width: 6px; height: 6px; }
.pet-heart { position: absolute; left: 62%; bottom: 70%; transform: translate(-50%, 0); }
.pet-z { position: absolute; right: 12px; bottom: 90%; font: 800 1rem Manrope, system-ui, sans-serif; color: #f6f4f0;
  animation: pet-z 2.4s ease-out infinite; }
@keyframes pet-z { from { transform: translate(0, 6px); opacity: 0; } 30% { opacity: .9; } to { transform: translate(10px, -26px); opacity: 0; } }
.pet-loading { display: inline-block; vertical-align: middle; margin-right: 12px; }
.player-status:has(.pet-loading) { display: flex; align-items: center; }
@media (max-width: 720px) { .pets { --pet-ground: calc(72px + env(safe-area-inset-bottom)); } }
@media (prefers-reduced-motion: reduce) { .pet-sprite, .pet-z { animation: none; } }

/* ---------- sign-in with Clerk: TV QR code, #/bagla, Profil ayarları > Hesap, #/admin (js/account.js) ---------- */
/* The QR code: white quiet zone drawn in, a fixed size that a phone reads from the sofa. */
.pair-qr { justify-self: center; width: clamp(160px, 22vh, 240px); height: auto; border-radius: 8px; image-rendering: pixelated; }   /* square: the canvas is */
.pair-qr.waiting { opacity: .2; }
.gate.pair .pair-code { margin: 4px 0 8px; }
.bagla { max-width: 760px; margin: 0 auto; padding: calc(96px + env(safe-area-inset-top)) var(--gutter) 48px; display: grid; gap: 16px; }
.bagla .page-title { margin: 0; }
.bagla p { margin: 0; }
.bagla-choices { display: flex; flex-wrap: wrap; align-items: center; gap: clamp(16px, 3vw, 32px); }
.ask-dialog { width: min(420px, 92vw); margin: auto; border: 0; color: var(--ink); background: var(--panel); border-radius: 16px; padding: 28px; }
.ask-dialog::backdrop { background: rgba(0, 0, 0, .7); }
.ask-dialog h2 { margin: 0 0 8px; font-size: 1.2rem; }
.ask-dialog p { margin: 0; }
.account-body { display: grid; gap: 16px; }
.account h3 { margin: 0 0 4px; font-size: 1rem; }
.link-card { display: grid; gap: 10px; padding: 18px; border-radius: 12px; background: var(--panel); }
.link-card .set-hint { margin: 0; }
.link-card .btn { justify-self: start; }
.devices { list-style: none; margin: 8px 0 0; padding: 0; display: grid; gap: 4px; }
.devices li { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 16px; padding: 10px 0; border-bottom: 1px solid var(--line); }
.devices li:last-child { border-bottom: 0; }
.devices .dev-name { font-weight: 700; }
.devices .btn { margin-left: auto; min-height: 40px; padding: .5em 1.1em; }
/* #/admin email sign-in steps (account.js readinessBlock): name over its one-line what, the link at the end */
.rd-step { flex-wrap: nowrap; }
.rd-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; flex: 1; }
.rd-step.done .dev-name { font-weight: 500; color: var(--muted); }
.rd-step.done > .muted { margin-left: auto; }
.admin-person { align-items: flex-start; }
.admin-add { display: flex; gap: 10px; flex: 1 1 100%; }
.admin-add .field { flex: 1; min-width: 0; padding: 10px 14px; }
.admin-person .msg { flex: 1 1 100%; margin: 0; }
.admin-person .msg:empty { display: none; }
