:root {
  color-scheme: dark;
  --canvas: #080a0c;
  --surface: #0e1114;
  --raised: #14181c;
  --hover: #191e23;
  --line: #252b31;
  --line-strong: #394149;
  --text: #eef2f4;
  --soft: #ccd5db;
  --muted: #9caab3;
  --faint: #85939d;
  --accent: #c8ff00;
  --accent-strong: #dcff5c;
  --accent-soft: rgba(200, 255, 0, .12);
  /* Reads on top of --accent, which is bright enough that only a near-black
     clears the contrast floor. A token because a missing one is invalid at
     computed-value time, which silently falls back to the inherited colour
     rather than to anything legible. */
  --ink: #0d0d0d;
  --green: #73d8a2;
  --yellow: #e7bf6a;
  --red: #f17b86;
  /* Code only: release documents, group names, API keys and the ASCII globe.
     Labels and numbers are sans; the digits align through tabular-nums. */
  --mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
  --sans: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  /* Every band of the page — top bar, category nav and content — is laid out on
     this single container so they share one left edge at any viewport width. */
  --shell: 104rem;
  --gutter: clamp(1rem, 3vw, 2.8rem);
  /* The inline padding every band shares, as a token so a band that needs to
     compensate for it can subtract from it rather than restate it. */
  --band-inline: max(var(--gutter), calc((100% - var(--shell)) / 2 + var(--gutter)));
  /* Vertical counterpart of --gutter. Full-bleed blocks cancel it to sit flush
     against the band above, so it has to be a token rather than a repeated
     literal. */
  --page-pad-block: clamp(1.25rem, 3vw, 2.8rem);
}

* { box-sizing: border-box; }
html { min-height: 100%; background: var(--canvas); scroll-behavior: smooth; scrollbar-gutter: stable; }
body { min-height: 100vh; margin: 0; color: var(--text); background: var(--canvas); font-family: var(--sans); font-variant-numeric: tabular-nums; }
a { color: inherit; text-decoration: none; }
button, input, select, textarea { color: inherit; font: inherit; }
button { cursor: pointer; }
form { margin: 0; }
img { display: block; max-width: 100%; }
/* The icon set is Hugeicons, drawn on a 24px grid at a 1.5 stroke. The weight
   and colour live here rather than on the paths, so every icon inherits the
   colour of whatever it sits in and keeps one weight across the app. */
.icon { width: 1.3rem; height: 1.3rem; display: block; color: inherit; fill: none; stroke: currentColor; stroke-width: 1.5; stroke-linecap: round; stroke-linejoin: round; vector-effect: non-scaling-stroke; }
.icon * { fill: none; stroke: currentColor; }
.icon-brand, .icon-brand * { fill: currentColor; stroke: none; }
::selection { color: var(--ink); background: var(--accent); }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.app-frame { min-height: 100vh; display: flex; flex-direction: column; }
.brand { display: flex; align-items: center; gap: .8rem; }
.brand > span:last-child { display: flex; align-items: baseline; font-size: 1.15rem; letter-spacing: .02em; text-transform: uppercase; }
.brand strong, .brand em { font-weight: 700; }
.brand em { color: var(--accent); font-style: normal; }
/* The plate, skew and [SN] ink all live inside logo.svg, which doubles as the favicon. */
.brand-mark { width: 2.45rem; height: 2.45rem; display: block; }
.top-primary-nav { display: flex; align-items: center; gap: .15rem; }
.top-primary-nav a { min-height: 2.65rem; padding: 0 .72rem; display: flex; align-items: center; gap: .45rem; color: var(--muted); border: 1px solid transparent; font-size: .9rem; font-weight: 580; }
.top-primary-nav a:hover, .top-primary-nav a.active { color: var(--text); background: var(--raised); border-color: var(--line); }
.top-primary-nav a.active .nav-icon { color: var(--accent); }
.top-primary-nav .nav-icon { width: 1.25rem; display: grid; place-items: center; }
.nav-icon .icon { width: 1.35rem; height: 1.35rem; }
.app-content { min-width: 0; flex: 1; display: flex; flex-direction: column; }
.topbar { position: sticky; z-index: 15; top: 0; background: rgba(8,10,12,.94); border-bottom: 1px solid var(--line); backdrop-filter: blur(18px); }
/* Each band spans the viewport so its background and rules stay full bleed,
   while the padding pins its contents to the shared container edge. */
.topbar-main, .category-nav, .page-content { padding-inline: var(--band-inline); }
.topbar-main { min-height: 4.8rem; padding-block: .7rem; display: flex; align-items: center; gap: .7rem; }
.topbar-main > .brand { margin-right: .35rem; flex: none; }
.global-search { width: 34rem; min-width: 12rem; height: 2.65rem; margin-left: auto; flex: 0 1 34rem; display: flex; align-items: stretch; background: var(--surface); border: 1px solid var(--line); }
/* Scoped to the query form: opening the filter menu focuses its summary, which
   should not light the whole bar up as if the user were typing. */
.global-search:has(.global-search-query :focus) { border-color: var(--line-strong); box-shadow: 0 0 0 3px var(--accent-soft); }
.global-search-query { min-width: 0; flex: 1; display: flex; align-items: center; gap: .7rem; }
.global-search-query > .search-icon { margin-left: .85rem; color: var(--accent); }
/* Scoped to the query form: the filter panel lives in this same shell and its
   fields keep the ordinary control styling. */
.global-search-query input { min-width: 0; flex: 1; padding: 0; background: transparent; border: 0; outline: 0; font-size: 1.02rem; }
.global-search-query input::placeholder { color: var(--faint); }
.global-search-submit { padding: 0 1rem; color: var(--accent); background: transparent; border: 0; border-left: 1px solid var(--line); font-size: .76rem; font-weight: 600; letter-spacing: .08em; }
.top-actions, .user-pill { display: flex; align-items: center; gap: .7rem; }
.top-actions { flex: none; }
.cart-shortcut { width: 2.6rem; height: 2.6rem; display: grid; place-items: center; position: relative; color: var(--soft); border: 1px solid var(--line); }
.cart-shortcut:hover, .cart-shortcut.active { color: var(--accent); border-color: var(--line-strong); background: var(--accent-soft); }
.cart-badge { position: absolute; top: -.52rem; right: -.52rem; min-width: 1.35rem; height: 1.35rem; padding: 0 .3rem; display: grid; place-items: center; color: #0b0d0f; background: var(--accent); border: 2px solid var(--canvas); border-radius: 999px; font-size: .72rem; font-weight: 900; line-height: 1; }
.cart-badge[hidden] { display: none; }
.user-menu { position: relative; }
.user-menu > summary { list-style: none; cursor: pointer; user-select: none; }
.user-menu > summary::-webkit-details-marker { display: none; }
/* The glyph hue is seeded per account from the username (--g, set inline), so
   every member gets its own colour at one shared brightness. The span holds a
   hashed pixel identicon; the default is the accent lime, which keeps unseeded
   glyphs looking as they always did. */
.user-pill > span { --g: 112; width: 2.6rem; height: 2.6rem; padding: .5rem; display: grid; place-items: center; color: oklch(.84 .17 calc(var(--g) * 1deg)); background: oklch(.84 .17 calc(var(--g) * 1deg) / .12); border: 1px solid oklch(.84 .17 calc(var(--g) * 1deg) / .3); }
.user-pill > span svg { width: 100%; height: 100%; display: block; }
.user-pill div { display: grid; }
.user-pill strong { font-size: .95rem; font-weight: 650; }
.user-pill small { color: var(--faint); font-size: .74rem; font-weight: 600; letter-spacing: .06em; text-transform: uppercase; }
.user-pill > .icon { width: .9rem; height: .9rem; color: var(--faint); transition: transform 150ms ease; }
.user-menu[open] .user-pill > .icon { transform: rotate(180deg); }
.user-dropdown { position: absolute; z-index: 45; top: calc(100% + .7rem); right: 0; min-width: 13rem; padding: .45rem; display: grid; background: #0b0e10; border: 1px solid var(--line-strong); box-shadow: 0 1rem 2.5rem rgba(0,0,0,.45); }
.user-dropdown > a, .user-dropdown button, .user-menu-primary a { width: 100%; min-height: 2.7rem; padding: .55rem .7rem; display: flex; align-items: center; gap: .65rem; color: var(--muted); background: transparent; border: 0; font-size: .9rem; text-align: left; }
.user-dropdown > a:hover, .user-dropdown button:hover, .user-menu-primary a:hover { color: var(--text); background: var(--raised); }
.user-dropdown .icon { width: 1.15rem; height: 1.15rem; }
.user-menu-primary { display: none; padding-bottom: .35rem; margin-bottom: .35rem; border-bottom: 1px solid var(--line); }
/* The panel hangs off the whole bar rather than off the toggle, so it lines up
   with the bar's edges instead of with the icon sitting inside it. */
.global-search, .category-menu { position: relative; }
.advanced-search > summary, .category-menu > summary { list-style: none; cursor: pointer; user-select: none; }
.advanced-search > summary::-webkit-details-marker, .category-menu > summary::-webkit-details-marker { display: none; }
/* The toggle rides inside the search bar, just left of the submit button, so it
   is a bare icon rather than a box of its own. */
.advanced-search { display: flex; flex: none; }
.advanced-search > summary { width: 2.4rem; display: grid; place-items: center; color: var(--soft); }
.advanced-search > summary .icon { width: 1.1rem; height: 1.1rem; }
.category-menu > summary .icon { width: .9rem; height: .9rem; transition: transform 150ms ease; }
.advanced-search[open] > summary, .advanced-search > summary:hover { color: var(--accent); background: var(--raised); }
.category-menu[open] > summary .icon { transform: rotate(180deg); }
.advanced-panel { position: absolute; z-index: 40; top: calc(100% + .75rem); right: 0; width: min(35rem,calc(100vw - 2rem)); max-height: calc(100vh - 6.5rem); padding: 1.1rem; display: grid; grid-template-columns: repeat(2,minmax(0,1fr)); gap: .8rem; overflow-y: auto; background: #0b0e10; border: 1px solid var(--line-strong); box-shadow: 0 1.5rem 4rem rgba(0,0,0,.5); }
.advanced-heading { grid-column: 1/-1; padding-bottom: .85rem; display: flex; align-items: flex-start; justify-content: space-between; border-bottom: 1px solid var(--line); }
.advanced-heading > div { display: grid; gap: .25rem; }
.advanced-heading strong { font-size: 1.1rem; }
.advanced-heading a { color: var(--accent); font-size: .72rem; font-weight: 600; letter-spacing: .06em; text-transform: uppercase; }
.advanced-wide { grid-column: 1/-1; }
.advanced-quality { grid-template-columns: repeat(4,1fr); }
/* The row is pulled back by one tab inset so the first label, rather than its
   button box, lands on the edge the logo and the content below share. Doing it
   here instead of stripping the first tab's padding is what keeps every tab the
   same shape, so the hover fill and the active rule stay centred on their
   labels at both ends. */
.category-nav { --tab-inset: .78rem; padding-inline-start: calc(var(--band-inline) - var(--tab-inset)); min-height: 3.15rem; display: flex; align-items: stretch; gap: .1rem; border-top: 1px solid rgba(37,43,49,.65); }
.category-nav > a, .category-menu > summary { min-height: 3.1rem; padding-inline: var(--tab-inset); display: flex; align-items: center; gap: .25rem; color: var(--muted); font-size: .88rem; font-weight: 560; white-space: nowrap; }
.category-nav > a:hover, .category-menu > summary:hover, .category-menu[open] > summary { color: var(--accent-strong); background: var(--raised); }
/* The unfiltered view lives at the top of the catch-all menu; the rule keeps it
   from reading as one more thing inside that category. */
.category-dropdown { position: absolute; z-index: 35; top: calc(100% + 1px); left: 0; min-width: 13.5rem; padding: .45rem; display: grid; background: #0b0e10; border: 1px solid var(--line-strong); box-shadow: 0 1rem 2.5rem rgba(0,0,0,.45); }
.category-dropdown a { min-height: 2.5rem; padding: .55rem .65rem; display: grid; align-content: center; gap: .15rem; color: var(--muted); font-size: .88rem; }
.category-dropdown a:hover { color: var(--text); background: var(--raised); }
.category-dropdown strong { color: var(--accent-strong); font-size: .9rem; }
.category-dropdown small { color: var(--faint); font-size: .72rem; }
/* The add control is swapped for this once the release is in the cart. */
.release-actions .cart-added, .cart-added { color: var(--accent); background: var(--accent-soft); border-color: rgba(200,255,0,.45); }
/* htmx marks the indicator target while a swap is in flight. */
#entity-main.htmx-request, #search-results.htmx-request { opacity: .55; transition: opacity 120ms ease; pointer-events: none; }
/* Inset instead of a real border so marking a tab active never shifts the row. */
.category-nav > a.active, .category-menu.active > summary { color: var(--accent); box-shadow: inset 0 -2px 0 var(--accent); }
.category-dropdown a.active { color: var(--accent-strong); background: var(--accent-soft); }
.page-content { flex: 1; padding-block: var(--page-pad-block); }

/* Another band, so it shares the inline padding; it grows from the bottom so a
   short page still pins it to the viewport edge rather than mid-screen. */
.site-footer { margin-top: auto; padding: 2.2rem var(--band-inline) 1.5rem; background: var(--surface); border-top: 1px solid var(--line); color: var(--muted); font-size: .85rem; }
.site-footer-main { display: flex; flex-wrap: wrap; gap: 2rem 3.5rem; justify-content: space-between; }
.site-footer-brand { max-width: 22rem; display: grid; gap: .9rem; align-content: start; }
/* Same brand as the top bar; only the narrow-viewport wordmark collapse is
   undone, because down here there is room for it. */
.site-footer-brand .brand { color: var(--text); }
.site-footer-brand .brand > span:last-child { display: flex; }
.site-footer-nav { display: flex; flex-wrap: wrap; gap: 1.6rem 3.5rem; }
.site-footer-nav > div { min-width: 8rem; display: grid; gap: .5rem; align-content: start; }
.site-footer-nav h3 { margin: 0 0 .2rem; color: var(--text); font-size: .74rem; font-weight: 640; letter-spacing: .08em; text-transform: uppercase; }
.site-footer-nav a { display: flex; align-items: center; gap: .45rem; width: fit-content; color: var(--muted); }
.site-footer-nav a:hover { color: var(--text); }
.site-footer-nav a .icon { width: 1.05rem; height: 1.05rem; color: var(--faint); }
.site-footer-nav a:hover .icon { color: var(--accent); }
.site-footer-brand small { color: var(--faint); font-size: .78rem; }

/* The trial countdown is a band in its own right, so it takes the shared inline
   padding rather than the page box: it has to line up with the top bar above it
   and the content below, and it must stay visible on every page rather than
   scroll away with the first section. */
.trial-banner { padding: .7rem var(--band-inline); display: flex; align-items: center; gap: 1rem; background: var(--raised); border-top: 1px solid var(--line); box-shadow: inset 3px 0 0 var(--accent); }
.trial-banner-mark { flex: none; display: grid; place-items: center; color: var(--accent); }
.trial-banner-mark .icon { width: 1.3rem; height: 1.3rem; }
.trial-banner-copy { flex: 1; min-width: 0; display: grid; gap: .15rem; }
.trial-banner-copy strong { font-size: .98rem; }
.trial-banner-copy small { color: var(--muted); font-size: .86rem; }
.trial-banner .button { flex: none; }
.trial-banner.is-expired { box-shadow: inset 3px 0 0 var(--red); }
.trial-banner.is-expired .trial-banner-mark { color: var(--red); }

/* Sits on the same left edge as every other band through the shared
   padding-inline rule above. */

.media-sections { display: grid; gap: 4rem; }
.section-header { margin-bottom: 1rem; display: flex; align-items: flex-end; justify-content: space-between; }
.section-header h2 { margin: 0; font-size: 1.35rem; font-weight: 620; letter-spacing: -.025em; }
.section-header > a { color: var(--muted); font-size: .78rem; font-weight: 600; letter-spacing: .06em; }
.section-header > a b { color: var(--accent); }
.poster-grid { display: grid; grid-template-columns: repeat(6,minmax(0,1fr)); gap: clamp(.7rem,1.3vw,1.25rem); }
.poster-card { min-width: 0; display: grid; }
.poster-art { aspect-ratio: 2/3; display: grid; place-items: center; position: relative; overflow: hidden; background: linear-gradient(145deg,#202b31,#111519); border: 1px solid var(--line); }
.poster-art img { width: 100%; height: 100%; object-fit: cover; }
/* Only the bottom strip is shaded, just enough to seat the rating chip. */
.poster-art::after { content: ""; position: absolute; inset: 82% 0 0; background: linear-gradient(transparent,rgba(5,7,9,.45)); pointer-events: none; }
/* One hover for every card that shows artwork — home grid, saga row, cast row,
   release poster. The art zooms inside its own frame and the label takes the
   accent; the frame itself is left alone, because a border lighting up on four
   different card shapes reads as four different components rather than one.
   Defining it here once is what keeps them from drifting apart.

   The scale is on the image inside an overflow-hidden frame, so the card never
   changes size and the grid never reflows. */
.poster-art img, .collection-art img, .cast-face img, a.release-detail-poster img { transition: transform 280ms ease; }
.poster-card:hover .poster-art img,
.collection-card:hover .collection-art img,
.cast-card:hover .cast-face img,
a.release-detail-poster:hover img { transform: scale(1.06); }
.poster-card b, .cast-card b { transition: color 160ms ease; }
.poster-card:hover b, .cast-card:hover b { color: var(--accent-strong); }
.poster-fallback { color: var(--faint); font-size: 1.8rem; font-weight: 600; }
.rating { position: absolute; z-index: 2; right: .55rem; bottom: .55rem; padding: .24rem .45rem; font-size: .82rem; }
.rating { color: var(--yellow); background: rgba(8,10,12,.86); }
.row-empty, .table-empty { padding: 2.5rem 1rem; color: var(--faint); background: var(--surface); border: 1px dashed var(--line); font-size: .92rem; text-align: center; }
.row-empty { grid-column: 1/-1; }

.page-heading { margin-bottom: 2.3rem; }
.page-heading h1 { margin: 0 0 .6rem; font-size: clamp(1.85rem,3.4vw,3rem); font-weight: 570; letter-spacing: -.05em; }
.page-heading p { max-width: 48rem; margin: 0; color: var(--muted); line-height: 1.7; }
.search-summary { margin-bottom: 1.15rem; display: flex; align-items: flex-end; justify-content: space-between; gap: 1rem; }
.search-summary h1 { margin: 0 0 .35rem; font-size: clamp(1.15rem,2vw,1.55rem); font-weight: 520; letter-spacing: -.025em; }
.search-summary h1 span { color: var(--accent); }
.search-summary p { margin: 0; color: var(--muted); font-size: .86rem; }
.search-summary p strong { color: var(--text); font-weight: 500; }
label { display: grid; gap: .4rem; color: var(--muted); font-size: .84rem; letter-spacing: .035em; }
input, select, textarea { width: 100%; min-height: 2.55rem; padding: .55rem .7rem; color: var(--text); background: #0a0d0f; border: 1px solid var(--line); border-radius: 0; outline: 0; }
input:focus, select:focus, textarea:focus,
input:focus-visible, select:focus-visible, textarea:focus-visible {
  border-color: var(--accent);
  outline: none;
  box-shadow: none;
}
fieldset { min-width: 0; margin: 0; padding: 0; border: 0; }
fieldset legend { margin-bottom: .45rem; }
.quality-selector { display: grid; grid-template-columns: repeat(2,1fr); gap: .35rem; }
.quality-selector .check { min-height: 2.2rem; padding: .45rem; display: flex; align-items: center; gap: .45rem; background: #0a0d0f; border: 1px solid var(--line); }
.quality-selector input { width: .95rem; min-height: 0; height: .95rem; accent-color: var(--accent); }
.button { min-height: 2.8rem; padding: .7rem 1rem; display: inline-flex; align-items: center; justify-content: center; gap: .5rem; border: 1px solid var(--line); font-size: .92rem; font-weight: 650; }
.button .icon { width: 1.15rem; height: 1.15rem; }
.button.primary { color: var(--ink); background: var(--accent); border-color: var(--accent); }
.button.primary:hover { background: var(--accent-strong); }
.button.subtle { color: var(--soft); background: var(--surface); }
.button.subtle:hover { background: var(--hover); border-color: var(--line-strong); }
.button.full { width: 100%; }
.result-panel { min-width: 0; }
.release-list { overflow: visible; border: 1px solid var(--line); }
.release-head, .release-row { display: grid; grid-template-columns: minmax(15rem,1fr) 4rem 5.5rem 3.5rem 4.5rem; align-items: center; gap: .55rem; }
.release-head { min-height: 2.6rem; padding: 0 .8rem; color: var(--faint); background: #0a0d0f; border-bottom: 1px solid var(--line); font-size: .74rem; font-weight: 600; letter-spacing: .06em; text-transform: uppercase; }
/* Age, size and grabs are magnitudes: right-aligning them lines every value up
   on its last digit, and each header follows its own column. */
/* Centred rather than flush right: a heading is always wider than the figure
   under it, so aligning their right edges left every value looking nudged off
   its column. The name column stays left, where a ragged right edge is what
   makes a list of titles scannable. */
.release-head > :nth-child(n+2), .release-row > :nth-child(n+2) { text-align: center; }
.release-row > :nth-child(n+2) { justify-items: center; }
.release-actions { justify-content: center; }
.release-row { min-height: 5.5rem; padding: .55rem .8rem; background: var(--surface); border-bottom: 1px solid var(--line); }
.release-list-compact .release-row { min-height: 4rem; }
.release-row:last-child { border-bottom: 0; }
.release-row:hover { background: var(--hover); }
.release-primary { min-width: 0; display: flex; align-items: center; gap: .75rem; }
.release-thumbnail { width: 2.9rem; height: 4.35rem; flex: none; overflow: hidden; background: var(--raised); border: 1px solid var(--line); }
.release-thumbnail img { width: 100%; height: 100%; display: block; object-fit: cover; }
.release-preview { padding: .12rem .32rem; position: relative; display: inline-flex; align-items: center; gap: .2rem; color: var(--muted); background: var(--raised); border: 1px solid var(--line); font-size: .82rem; line-height: 1.2; }
.release-preview:hover, .release-preview:focus-visible { color: var(--accent-strong); }
.release-preview .icon { width: .95rem; height: .95rem; }
.release-preview-pop { width: min(20rem,calc(100vw - 2rem)); padding: .25rem; position: absolute; bottom: calc(100% + .4rem); left: 0; z-index: 40; display: none; background: var(--raised); border: 1px solid var(--line-strong); box-shadow: 0 12px 28px rgb(0 0 0 / .45); }
.release-preview-pop img { width: 100%; height: auto; display: block; }
.release-preview:hover .release-preview-pop, .release-preview:focus-visible .release-preview-pop, .release-preview.is-open .release-preview-pop { display: block; }
.release-preview-pop:empty, .release-preview-pop img:not([src]) { display: none; }
.release-sample a { display: block; max-width: 32rem; }
.release-sample img { width: 100%; height: auto; display: block; border: 1px solid var(--line); }
.release-name { min-width: 0; display: grid; gap: .28rem; }
.release-name a { overflow: hidden; font-size: .96rem; font-weight: 600; text-overflow: ellipsis; white-space: nowrap; }
.release-name a:hover { color: var(--accent-strong); }
.release-name small { color: var(--faint); font-size: .82rem; }
.release-meta, .release-languages { display: flex; align-items: center; flex-wrap: wrap; gap: .38rem; }
.meta-separator { color: var(--line-strong); font-style: normal; }
.release-meta .quality { padding: .12rem .32rem; }
/* One badge per track: a fixed label segment, then every flag that track ships. */
.language-track { min-width: 0; max-width: 100%; min-height: 1.3rem; padding-right: .3rem; display: inline-flex; align-items: center; flex-wrap: wrap; gap: .22rem; background: var(--raised); border: 1px solid var(--line); font-size: .92rem; line-height: 1; }
.track-label { align-self: stretch; padding: 0 .3rem; display: inline-flex; align-items: center; color: var(--faint); background: var(--surface); border-right: 1px solid var(--line); font-size: .58rem; }
.track-label .icon { width: .8rem; height: .8rem; }
.track-flag { display: inline-flex; }
.track-more { color: var(--faint); font-size: .58rem; }
.sr-only { width: 1px; height: 1px; padding: 0; position: absolute; overflow: hidden; clip: rect(0,0,0,0); white-space: nowrap; border: 0; }
.release-row > span { color: var(--muted); font-size: .87rem; }
.mono { font-family: var(--mono); }
.quality { padding: .24rem .4rem; color: var(--soft); background: var(--raised); border: 1px solid var(--line); font-size: .82rem; font-weight: 500; }
.q-2160p { color: #c89df2; border-color: rgba(200,157,242,.3); }
.q-1080p { color: var(--accent-strong); border-color: rgba(200,255,0,.3); }
.q-720p { color: var(--green); border-color: rgba(115,216,162,.3); }
.release-actions, .release-actions form { display: flex; justify-content: flex-end; gap: .3rem; }
/* Both action targets are locked to the same square on every axis so the
   button (form-wrapped) and the anchor can never drift apart in width. */
.release-actions button, .release-actions a { box-sizing: border-box; flex: none; width: 2.3rem; min-width: 2.3rem; max-width: 2.3rem; height: 2.3rem; padding: 0; display: grid; place-items: center; color: var(--soft); background: transparent; border: 1px solid var(--line); }
.release-actions .icon { width: 1.2rem; height: 1.2rem; }
.release-actions button:hover, .release-actions a:hover { color: var(--accent); background: var(--accent-soft); }
.release-actions button.is-added, button.is-added { color: var(--accent); background: var(--accent-soft); border-color: rgba(200,255,0,.45); }
.pagination { margin: 1rem 0; display: flex; align-items: center; justify-content: center; gap: .18rem; color: var(--muted); font-size: .85rem; }
.result-panel > .pagination:first-child { margin-top: 0; }
.pagination-page, .pagination-edge { min-width: 2.35rem; height: 2.35rem; padding: 0 .5rem; display: inline-grid; place-items: center; color: var(--soft); background: transparent; border: 1px solid var(--line); font-weight: 650; }
.pagination-edge { font-size: 1.2rem; }
/* Chips and pills answer a hover with a tinted ground and brighter text, never
   a lit border — the same restraint the cards keep. A border that changes only
   on hover also shifts what the eye reads as the element's edge. */
.pagination-page:hover, .pagination-edge:not(.is-disabled):hover { color: var(--text); background: var(--accent-soft); }
.pagination-page.is-current { color: var(--ink); background: var(--accent); border-color: var(--accent); }
/* A disabled edge is the same control with its ink taken away, so it inherits
   the whole box from the rule above and overrides colour alone. Setting the
   font shorthand here would reset the size and weight back to the row's, which
   is what made the arrows render a size smaller than the ones beside them. */
.pagination-edge.is-disabled { color: var(--line-strong); cursor: default; }
.notice { margin-bottom: 1rem; padding: .8rem 1rem; font-size: .96rem; }
/* A banner at the top of the page pulls itself up through the page padding so
   the gap above it matches the one below, rather than the content's own inset. */
.page-content > .notice:first-child { margin-top: calc(1rem - var(--page-pad-block)); }
.notice.error, .form-error { color: var(--red); background: rgba(241,123,134,.08); border: 1px solid rgba(241,123,134,.22); }
/* Toasts sit over the page corner and leave on their own; app.js times them
   out and wires the close button. */
.toast-stack { position: fixed; z-index: 60; right: 1rem; bottom: 1rem; width: min(24rem, calc(100vw - 2rem)); display: grid; gap: .5rem; }
.toast { padding: .75rem .5rem .75rem .9rem; display: flex; align-items: center; gap: .6rem; color: var(--text); background: var(--raised); border: 1px solid var(--line-strong); border-left: 3px solid var(--green); box-shadow: 0 1rem 2.5rem rgba(0,0,0,.45); font-size: .92rem; line-height: 1.45; animation: toast-in 180ms ease-out; }
.toast > .icon { flex: none; color: var(--green); }
.toast > span { flex: 1; min-width: 0; }
.toast-close { width: 2rem; height: 2rem; flex: none; color: var(--muted); background: transparent; border: 0; font-size: 1.4rem; line-height: 1; cursor: pointer; }
.toast-close:hover { color: var(--text); }
.toast.is-leaving { animation: toast-out 160ms ease-in forwards; }
@keyframes toast-in { from { opacity: 0; transform: translateY(.5rem); } }
@keyframes toast-out { to { opacity: 0; transform: translateY(.5rem); } }
@media (prefers-reduced-motion: reduce) { .toast, .toast.is-leaving { animation: none; } }

/* The hero bleeds past the page box by one gutter, so it has to give that same
   gutter back as padding: any other value drifts the poster off the left edge
   every panel below it sits on. */
/* Synopses have no length TMDB enforces, so the copy gets a line budget rather
   than being allowed to set the height of the band. Both columns read it. */
.media-hero { --hero-copy-lines: 5; min-height: 30rem; margin-block-start: calc(var(--page-pad-block)*-1); margin-inline: calc(var(--gutter)*-1); margin-bottom: 2.5rem; padding: clamp(4rem,9vw,8rem) var(--gutter) 3rem; display: flex; align-items: flex-end; gap: 2rem; position: relative; overflow: hidden; background: linear-gradient(145deg,#162027,#0c1013); border-bottom: 1px solid var(--line); }
/* Two soft ramps instead of one flat wash: the backdrop stays visible across the
   top and right, and the ink pools in the bottom-left corner where the poster
   and the copy actually need contrast. */
.media-hero::after { content: ""; position: absolute; inset: 0; pointer-events: none; background:
    linear-gradient(to top, rgba(8,10,12,.94) 0%, rgba(8,10,12,.62) 26%, rgba(8,10,12,0) 64%),
    linear-gradient(to right, rgba(8,10,12,.86) 0%, rgba(8,10,12,.3) 34%, rgba(8,10,12,0) 66%); }
.media-backdrop { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.media-poster, .media-copy { position: relative; z-index: 1; }
/* The poster is as tall as the copy beside it is allowed to get, so the text
   never climbs past the artwork. The sum is the copy's own worst case: 9.5rem
   of fixed rows, a title at its two-line limit — 2 x 3rem x 1.18 — and one
   line-height per line of synopsis. A shorter title or synopsis simply leaves the poster taller, which
   is what the bottom alignment is for. */
.media-poster { width: auto; height: calc(9.5rem + 7.1rem + var(--hero-copy-lines) * 1.7rem); aspect-ratio: 2/3; flex: none; display: grid; place-items: center; overflow: hidden; color: var(--faint); background: var(--raised); border: 1px solid var(--line-strong); font-size: 1.4rem; font-weight: 600; box-shadow: 0 1.5rem 4rem rgba(0,0,0,.35); }
.media-poster img { width: 100%; height: 100%; object-fit: cover; }
/* Rating badges: the source sits in its own segment, the score is toned by band
   so critics and audience read at a glance without decoding the provider. */
.rating-list { margin-top: .7rem; display: flex; flex-wrap: wrap; gap: .4rem; }
.score { display: inline-flex; align-items: center; gap: .4rem; padding: .28rem .5rem; color: var(--soft); background: rgba(8,10,12,.72); border: 1px solid var(--line); font-size: .84rem; font-weight: 650; }
/* The provider marks replace the lettered chip that used to label each score.
   They carry their own brand colour, so unlike the icon set they are raster-
   agnostic images rather than currentColor SVGs, and the tone class tints only
   the number. Height is fixed and width left free because the marks do not
   share an aspect ratio: the tomato and popcorn are square, TMDB is a block. */
.score-mark { width: auto; height: 1rem; display: block; flex: none; }
.score-mark-wide { height: .8rem; }
/* Only the figure takes the tone. The badge keeps a neutral frame so a row of
   scores reads as one set of chips rather than three differently framed ones,
   and so the provider's own colour in the mark is the only brand colour there. */
.score b { font-weight: 650; }
.score .tone-high { color: var(--green); }
.score .tone-mid { color: var(--yellow); }
.score .tone-low { color: var(--red); }
.media-copy { max-width: 52rem; }
/* Negative tracking shrinks the word space along with the letter gaps, and past
   about -.03em the words in a long title start touching. */
/* Negative tracking shrinks the word space along with the letter gaps, and past
   about -.03em the words in a long title start touching. */
/* The line box has to clear the descenders, because -webkit-line-clamp needs
   overflow: hidden and that clips anything hanging below it — at 1.05 the tail
   of a g or a y was sliced off mid-stroke. */
.media-copy h1 { margin: 0 0 .75rem; font-size: clamp(1.9rem,3.2vw,3rem); font-weight: 570; letter-spacing: -.02em; line-height: 1.18; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden; }
.media-copy > p { max-width: 46rem; color: var(--soft); font-size: 1rem; line-height: 1.7; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: var(--hero-copy-lines); overflow: hidden; }
.media-meta, .tag-list, .inline-actions { display: flex; flex-wrap: wrap; gap: .4rem; align-items: center; }
.media-meta span { color: var(--muted); font-size: .85rem; }
.media-meta span:not(:last-child)::after { content: "·"; margin-left: .4rem; color: var(--faint); }
.tag-list span, .tag-list a { padding: .32rem .55rem; color: var(--soft); background: rgba(8,10,12,.65); border: 1px solid var(--line); font-size: .82rem; }
.tag-list a:hover { color: var(--accent-strong); background: var(--accent-soft); }
/* The facts that used to sit in a right-hand aside now ride in the hero, so the
   release list gets the full page width. */
/* The row gap carries the wrapped case, where a long country or title list puts
   these on two lines and .3rem read as one crowded block. */
.media-facts { margin: .85rem 0 0; display: flex; flex-wrap: wrap; gap: .5rem .95rem; }
/* The genre chips are their own row, not a continuation of the facts above. */
.media-copy .media-facts + .tag-list { margin-top: .7rem; }
.media-facts > div { display: flex; align-items: baseline; gap: .38rem; }
.media-facts dt { color: var(--faint); font-size: .67rem; font-weight: 600; letter-spacing: .1em; text-transform: uppercase; }
.media-facts dd { margin: 0; color: var(--soft); font-size: .88rem; }
.media-facts dd a { color: var(--accent); border-bottom: 1px solid rgba(200,255,0,.3); }
.media-facts dd a:hover { border-bottom-color: var(--accent); }
/* The total a held count is measured against — "1 of 2" — reads as the quieter
   half of the pair, so the figure we actually have keeps the emphasis. */
.fact-aside { color: var(--faint); }
/* Framed, not toned: an age rating is a classification and must not be mistaken
   for one of the scores a few pixels below it. */
.cert { padding: .1rem .34rem; color: var(--soft); border: 1px solid var(--line-strong); font-size: .74rem; font-weight: 650; }
.media-meta .cert::after { content: none; }
/* Title-level actions. Sized and framed like the per-release controls, because
   they are the same kind of thing at a different scale and a second button
   vocabulary would only invite them to drift. The row wraps rather than
   scrolls: more of these are coming, and on a narrow screen a second line of
   icons reads better than a hidden one. */
.title-actions { margin-top: .95rem; display: flex; flex-wrap: wrap; gap: .4rem; }
.title-actions > a, .title-actions > button {
  width: 2.4rem; height: 2.4rem; display: grid; place-items: center; padding: 0;
  color: var(--soft); background: rgba(8,10,12,.65); border: 1px solid var(--line);
  cursor: pointer; transition: color 160ms ease, background-color 160ms ease;
}
.title-actions > a:hover, .title-actions > button:hover,
.title-actions > a:focus-visible, .title-actions > button:focus-visible { color: var(--accent); background: var(--accent-soft); }
.title-actions .icon { width: 1.05rem; height: 1.05rem; }
.trailer-link { display: inline-flex; align-items: center; gap: .45rem; padding: .48rem .8rem; color: var(--accent); background: var(--accent-soft); border: 1px solid rgba(200,255,0,.4); font-size: .82rem; font-weight: 650; }
.trailer-link:hover { color: var(--ink); background: var(--accent); border-color: var(--accent); }
.trailer-link .icon { width: .95rem; height: .95rem; }

/* The episode the selector is pointing at, named. The accent edge ties it to
   the selected chip above rather than to the release rows below. */
.episode-head { margin-bottom: 1rem; padding: .85rem; display: flex; gap: .95rem; align-items: center; background: var(--surface); border: 1px solid var(--line); border-left: 2px solid var(--accent); }
.episode-still { width: 8.5rem; aspect-ratio: 16/9; flex: none; object-fit: cover; background: var(--raised); border: 1px solid var(--line-strong); }
.episode-copy { min-width: 0; }
.episode-number { margin: 0; color: var(--accent); font-size: .68rem; font-weight: 600; letter-spacing: .08em; }
.episode-copy h2 { margin: .2rem 0 .3rem; font-size: 1.05rem; font-weight: 600; }
.episode-aired { margin: 0; color: var(--muted); font-size: .78rem; }

/* Credits sit below the release list, so this block starts a new band rather
   than continuing the one above it. */
.credits { margin-top: 2rem; padding-top: 1.5rem; border-top: 1px solid var(--line); }
.credits h2 { margin: 0 0 .9rem; font-size: 1.05rem; font-weight: 600; }
/* Both rows scroll sideways rather than wrapping: each is ranked — the cast by
   billing, the saga by release date — and a wrapping grid would break that
   order into arbitrary lines. grid-auto-flow: column is what guarantees it,
   since a column track list never wraps however narrow the page gets.
   min-width: 0 keeps the row from pushing the page wide instead of scrolling
   when it sits inside a grid or flex parent. */
.cast-row, .collection-row { min-width: 0; overflow-x: auto; overscroll-behavior-x: contain; padding-bottom: .6rem; scrollbar-width: thin; scrollbar-color: var(--line-strong) transparent; }
/* A thin permanent bar rather than the overlay one: against this ground an
   overlay scrollbar is invisible until touched, so nothing says the row
   continues past the edge. */
.cast-row::-webkit-scrollbar, .collection-row::-webkit-scrollbar { height: .4rem; }
.cast-row::-webkit-scrollbar-thumb, .collection-row::-webkit-scrollbar-thumb { background: var(--line-strong); }
.cast-row::-webkit-scrollbar-thumb:hover, .collection-row::-webkit-scrollbar-thumb:hover { background: var(--faint); }
/* A card sliced flat against the container edge reads as a layout fault rather
   than as a row that continues, so the edges the row can still scroll towards
   are faded out instead of cut. The two lengths are driven by the row's own
   scroll position, which is what keeps the fade honest: none on the left until
   something has been scrolled past, none on the right once the end is reached.
   A row too short to scroll has an inactive timeline and so keeps the base
   values, which draw no fade at all — the same as a browser without support,
   where the row simply behaves as it does today. */
@property --rail-fade-start { syntax: "<length>"; inherits: false; initial-value: 0px; }
@property --rail-fade-end { syntax: "<length>"; inherits: false; initial-value: 0px; }
@supports (animation-timeline: scroll(self inline)) {
  .cast-row, .collection-row {
    --rail-fade-start: 0px; --rail-fade-end: 0px;
    mask-image: linear-gradient(to right, transparent 0, #000 var(--rail-fade-start),
      #000 calc(100% - var(--rail-fade-end)), transparent 100%);
    animation: rail-fade linear both; animation-timeline: scroll(self inline);
  }
  @keyframes rail-fade {
    0% { --rail-fade-start: 0px; --rail-fade-end: 40px; }
    6%, 94% { --rail-fade-start: 40px; --rail-fade-end: 40px; }
    100% { --rail-fade-start: 40px; --rail-fade-end: 0px; }
  }
}
.cast-row { display: grid; grid-auto-flow: column; grid-auto-columns: 6.2rem; gap: .7rem; }
.cast-card { min-width: 0; }
.cast-face { aspect-ratio: 2/3; margin-bottom: .45rem; display: grid; place-items: center; overflow: hidden; background: var(--raised); border: 1px solid var(--line-strong); color: var(--faint); font-size: .95rem; font-weight: 600; }
.cast-face img { width: 100%; height: 100%; object-fit: cover; }
.cast-card b { display: block; color: var(--soft); font-size: .8rem; font-weight: 600; line-height: 1.3; }
.cast-card span { display: block; color: var(--faint); font-size: .75rem; line-height: 1.35; }
/* A credit is a way through the catalogue, so it reads as a link. The hover
   colour is the only thing separating it from the fact beside it, which is
   deliberate: a row of chips here would compete with the genre tags. */
.cast-card { display: block; text-decoration: none; }

/* A person has no backdrop and no synopsis, so their header is a portrait and a
   name rather than the full media hero. */
.person-hero { margin-bottom: 2rem; padding-bottom: 1.5rem; display: flex; align-items: flex-start; gap: 1.4rem; border-bottom: 1px solid var(--line); }
.person-portrait { width: 7rem; aspect-ratio: 2/3; flex: none; display: grid; place-items: center; overflow: hidden; background: var(--raised); border: 1px solid var(--line-strong); color: var(--faint); font-size: 1.3rem; font-weight: 600; }
.person-portrait img { width: 100%; height: 100%; object-fit: cover; }
/* No clamp: shown whole or not at all. Held near 70 characters a line, which is
   where running prose stays readable, and the portrait beside it is free to be
   shorter than the text — the header grows to fit rather than hiding any. */
.person-bio { max-width: 44rem; margin: .8rem 0 0; color: var(--soft); font-size: .92rem; line-height: 1.65; }
.person-copy h1 { margin: 0 0 .5rem; font-size: clamp(1.6rem, 3vw, 2.4rem); font-weight: 570; letter-spacing: -.02em; line-height: 1.18; }

/* Wider cards than the cast row: these are posters, and a poster carries a
   title people read rather than a face they recognise. */
.collection-row { display: grid; grid-auto-flow: column; grid-auto-columns: 8.5rem; gap: .8rem; }
.collection-card { min-width: 0; display: block; }
.collection-art { aspect-ratio: 2/3; margin-bottom: .5rem; display: grid; place-items: center; overflow: hidden; background: var(--raised); border: 1px solid var(--line-strong); color: var(--faint); font-size: 1.1rem; font-weight: 600; }
.collection-art img { width: 100%; height: 100%; object-fit: cover; }
.entity-body { min-width: 0; }
.entity-main { min-width: 0; }
.episode-switcher { margin-bottom: 1rem; background: var(--surface); border: 1px solid var(--line); }
.episode-switcher-row { display: grid; grid-template-columns: 7rem minmax(0,1fr); gap: .75rem; padding: .7rem; border-bottom: 1px solid var(--line); }
.episode-switcher-row:last-child { border-bottom: 0; }
.episode-switcher-row h2 { margin: 0; padding: .58rem .3rem; color: var(--soft); font-size: .9rem; font-weight: 650; }
.episode-switcher-options { display: grid; grid-template-columns: repeat(auto-fill,minmax(4.5rem,7rem)); gap: .38rem; }
.episode-switcher-options a { min-height: 2.4rem; padding: .5rem .7rem; display: grid; place-items: center; color: var(--muted); background: #0a0d0f; border: 1px solid var(--line-strong); font-size: .84rem; font-weight: 650; text-align: center; }
.episode-switcher-options a:hover { color: var(--text); border-color: var(--soft); }
.episode-switcher-options a.selected { color: #091000; background: var(--accent); border-color: var(--accent); }
.quality-switcher-row .episode-switcher-options { grid-template-columns: repeat(auto-fill,minmax(5.5rem,8rem)); }

.release-detail { min-width: 0; }
.release-detail-hero { margin-bottom: 1rem; padding: 1rem; display: grid; grid-template-columns: 7.25rem minmax(0,1fr) minmax(11.5rem,14rem); grid-template-areas: "poster head metrics" "poster actions metrics"; align-items: start; gap: 1rem 1.2rem; background: linear-gradient(115deg,var(--surface),rgba(200,255,0,.035)); border: 1px solid var(--line); }
/* Releases with no linked media render no poster, so the column is dropped
   instead of leaving a gap where the artwork would have been. */
.release-detail-hero-bare { grid-template-columns: minmax(0,1fr) minmax(11.5rem,14rem); grid-template-areas: "head metrics" "actions metrics"; }
.release-detail-poster { width: 7.25rem; aspect-ratio: 2/3; grid-area: poster; display: grid; place-items: center; position: relative; overflow: hidden; color: var(--accent); background: var(--raised); border: 1px solid var(--line-strong); font-size: 1.35rem; font-weight: 600; box-shadow: 0 1rem 2.5rem rgba(0,0,0,.3); }
.release-detail-poster img { width: 100%; height: 100%; position: absolute; z-index: 1; inset: 0; object-fit: cover; background: var(--raised); }
.release-detail-poster img[hidden] { display: none; }
.release-poster-fallback { padding: .5rem; overflow-wrap: anywhere; text-align: center; }
/* One gap for the whole stack instead of a margin per block, so the title, the
   tags and the meta rows keep an even rhythm however many of them render. */
.release-detail-head { min-width: 0; max-width: 64rem; grid-area: head; align-self: center; display: flex; flex-direction: column; gap: .55rem; }
.release-detail-head h1 { margin: 0; overflow-wrap: anywhere; font-size: clamp(1.35rem,2vw,1.9rem); font-weight: 590; letter-spacing: -.035em; line-height: 1.12; }
.release-detail-head .tag-list span { padding: .29rem .5rem; font-size: .78rem; }
/* Same treatment nzb.su gives a locked release: a red chip that reads at a
   glance, with the recovered value (when the release's own NZB carried one)
   inline as code so a user without an auto-applying downloader can type it. */
.release-detail-head .tag-list .tag-passworded { color: #ffd7d1; background: rgba(154,29,21,.55); border-color: rgba(255,112,97,.45); }
.release-detail-head .tag-list .tag-passworded code { color: inherit; font-family: var(--mono); }
.release-groups { margin: 0; display: flex; align-items: baseline; flex-wrap: wrap; gap: .4rem; }
.release-groups > span { color: var(--faint); font-size: .74rem; font-weight: 600; letter-spacing: .06em; text-transform: uppercase; }
/* Plain text rather than a chip: the label already says what it is, and a box
   would sit heavier than the one line it carries. */
.release-groups code { color: var(--soft); font-family: var(--mono); font-size: .82rem; overflow-wrap: anywhere; }
.release-groups code + code::before { content: "· "; color: var(--faint); }
.metric-grid { height: 100%; margin: 0; grid-area: metrics; display: grid; grid-template-columns: 1fr; border: 1px solid var(--line); }
.metric-grid > div { min-width: 0; padding: .35rem .7rem; display: grid; grid-template-columns: 1fr auto; align-items: center; gap: .18rem; background: rgba(8,10,12,.55); border-bottom: 1px solid var(--line); }
.metric-grid > div:last-child { border-bottom: 0; }
.metric-grid span { color: var(--faint); font-size: .66rem; font-weight: 600; letter-spacing: .06em; text-transform: uppercase; }
.metric-grid strong { overflow: hidden; font-size: .94rem; font-weight: 550; text-overflow: ellipsis; }
.release-detail-actions { margin: 0; grid-area: actions; display: flex; align-self: end; justify-content: flex-start; gap: .4rem; }
.release-detail-actions .button { width: auto; min-height: 2.55rem; padding: .58rem .8rem; font-size: .84rem; white-space: nowrap; }
.page-actions { margin-bottom: 2rem; display: flex; justify-content: flex-end; align-items: center; gap: .6rem; }
.detail-panel { margin-top: 1rem; padding: 1.4rem; background: var(--surface); border: 1px solid var(--line); }
.detail-panel h2 { margin: 0 0 .5rem; font-size: 1.12rem; }
.detail-panel > p, .detail-panel div > p { color: var(--muted); font-size: .94rem; line-height: 1.65; }
/* The rest of the contents hang under the first few, so the second list carries
   no top rule of its own. */
/* Ordered so the control follows the rows it reveals instead of splitting the
   list in two once it is open. */
.file-more { display: flex; flex-direction: column; }
.file-more > summary { order: 2; min-height: 2.9rem; display: flex; align-items: center; gap: .35rem; color: var(--soft); font-size: .86rem; cursor: pointer; user-select: none; list-style: none; }
.file-more > summary::-webkit-details-marker { display: none; }
.file-more > summary:hover { color: var(--accent-strong); }
.file-more > summary .icon { width: .9rem; height: .9rem; transition: transform 150ms ease; }
.file-more[open] > summary .icon { transform: rotate(180deg); }
.file-more[open] .file-more-open, .file-more:not([open]) .file-more-close { display: none; }
.file-more .file-list { margin-top: 0; border-top: 0; }
.detail-panel.split { display: grid; grid-template-columns: 1fr 1fr; gap: 2rem; }
.file-list { margin-top: 1rem; border-top: 1px solid var(--line); }
.file-list > div { min-height: 3.2rem; padding: .7rem 0; display: flex; align-items: center; justify-content: space-between; gap: 1rem; border-bottom: 1px solid var(--line); }
.file-list span { min-width: 0; overflow-wrap: anywhere; font-size: .93rem; }
.file-list small { flex: none; color: var(--faint); font-size: .86rem; }
.vote-score { padding: .6rem; color: var(--accent); }
.report-form { margin-top: .7rem; display: grid; gap: .5rem; }
.report-form textarea { min-height: 5rem; resize: vertical; }


/* The account page reads as a record rather than a dashboard: a label column
   narrow enough to scan, the value beside it, and the action that changes that
   value pinned to the right edge so every row's button lines up. */
.account-section { margin-bottom: 2.5rem; }
.account-section-heading { margin: 0 0 1.4rem; padding-bottom: .5rem; color: var(--accent); border-bottom: 1px solid rgba(200,255,0,.28); font-size: 1.15rem; letter-spacing: -.02em; }
.account-section-note { margin: -.35rem 0 1.1rem; color: var(--muted); font-size: .92rem; }
.account-section-note a { color: var(--accent-strong); }
.account-rows { margin: 0; display: grid; }
.account-rows > div { padding: .85rem 0; display: grid; grid-template-columns: minmax(8rem,12rem) 1fr auto; align-items: center; gap: 1rem; border-bottom: 1px solid var(--line); }
.account-rows dt { margin: 0; color: var(--faint); font-size: .86rem; }
.account-rows dd { margin: 0; min-width: 0; color: var(--soft); overflow-wrap: anywhere; }
.account-rows dd small { color: var(--faint); font-size: .82rem; }
.account-rows > div > span { justify-self: end; }
/* An allowance is a row like any other fact, so its bar lives in the value
   column instead of in a grid of its own. */
/* The edit form is a sibling of the row it belongs to, revealed by a checkbox
   the row's label drives, so a field opens without script and closes by itself
   when another one opens is not needed — each keeps its own state. */
.edit-switch { position: absolute; width: 1px; height: 1px; opacity: 0; pointer-events: none; }
/* Row actions share one compact size, so a control never outweighs the fact it
   sits beside. The toggle is a label rather than a button and has to be dressed
   as one by hand. */
.account-rows > div > span .button, .edit-toggle { min-height: 2.1rem; padding: .4rem .75rem; font-size: .82rem; }
.edit-toggle { display: inline-flex; align-items: center; color: var(--soft); background: var(--surface); border: 1px solid var(--line); font-weight: 650; cursor: pointer; }
.edit-toggle:hover { background: var(--hover); border-color: var(--line-strong); }
.edit-form { display: none; padding: 1.2rem 0 1.4rem; grid-template-columns: repeat(auto-fit,minmax(15rem,1fr)); align-items: end; gap: .9rem; border-bottom: 1px solid var(--line); }
.edit-switch:checked + .edit-form { display: grid; }
.edit-switch:checked ~ * .edit-toggle[for] { color: var(--accent); }
.edit-form label { display: grid; gap: .35rem; color: var(--faint); font-size: .78rem; }
.edit-form input { min-height: 2.8rem; padding: .6rem .7rem; color: var(--text); background: #07090a; border: 1px solid var(--line); font-family: var(--sans); font-size: .95rem; }
.edit-form input:focus { border-color: var(--line-strong); outline: none; }
.edit-note { grid-column: 1 / -1; color: var(--faint); font-size: .82rem; }
.edit-form .button { justify-self: start; }
.account-rows .row-meter { display: grid; grid-template-columns: minmax(0,1fr) auto; align-items: center; gap: .9rem; }
.account-rows .row-meter progress { width: 100%; height: .35rem; }
.account-rows .row-meter b { color: var(--soft); font-size: .82rem; font-weight: 500; }
.account-rows .row-note { color: var(--faint); font-size: .78rem; }
.account-rows > div.is-spent { opacity: .55; }
.account-rows > div.is-spent dt { text-decoration: line-through; }
.countdown { color: var(--accent-strong); font-size: .88rem; }
.countdown.is-expired { color: var(--red); }
@media (max-width: 46rem) {
  .account-rows > div { grid-template-columns: 1fr; gap: .35rem; }
  .account-rows > div > span { justify-self: start; }
}
.settings-grid { display: grid; grid-template-columns: minmax(15rem,.7fr) 1.3fr; gap: 1rem; }
.settings-card { min-height: 20rem; padding: 1.5rem; background: var(--surface); border: 1px solid var(--line); }
.settings-card h2 { margin: .5rem 0 .25rem; font-size: 1.5rem; }
.settings-card > p { color: var(--muted); font-size: .96rem; line-height: 1.65; }
.admin-panel-grid { display: grid; gap: 1rem; }
.admin-heading { margin-bottom: 2rem; }
.admin-heading .page-actions { margin-top: 1.4rem; justify-content: flex-start; }
.admin-heading .page-actions .button { padding: .7rem 1.2rem; }
.admin-overview { min-height: 0; }
.admin-section-heading { display: flex; align-items: center; justify-content: space-between; gap: 1rem; }
.admin-section-heading h2 { margin: 0; line-height: 1; }
.status-pill { padding: .35rem .55rem; color: var(--accent); border: 1px solid rgba(160,251,0,.3); background: var(--accent-soft); font-size: .66rem; font-weight: 600; letter-spacing: .05em; text-transform: uppercase; }
.admin-summary-grid { margin-top: 1.1rem; display: grid; grid-template-columns: repeat(4,minmax(0,1fr)); border-top: 1px solid var(--line); border-left: 1px solid var(--line); }
.admin-summary-grid > div { min-height: 6rem; padding: .9rem 1rem; display: grid; align-content: center; gap: .18rem; border-right: 1px solid var(--line); border-bottom: 1px solid var(--line); }
.admin-summary-grid span { color: var(--muted); font-size: .66rem; font-weight: 600; letter-spacing: .07em; text-transform: uppercase; }
.admin-summary-grid strong { font-size: 1.55rem; line-height: 1.1; }
.admin-summary-grid small { color: var(--faint); font-size: .76rem; }
.admin-availability-chart { margin-top: 1rem; padding: 1rem; display: grid; grid-template-columns: minmax(12rem,.45fr) 1fr; gap: 1.5rem; align-items: center; background: #0a0d0f; border: 1px solid var(--line); }
.admin-chart-copy { display: grid; gap: .25rem; }
.admin-chart-copy span { color: var(--faint); font-size: .66rem; font-weight: 600; letter-spacing: .07em; text-transform: uppercase; }
.admin-chart-copy strong { font-size: .94rem; }
.admin-chart-bars { display: grid; gap: .55rem; }
.admin-chart-bars label { display: grid; grid-template-columns: 6rem minmax(0,1fr) 6rem; gap: .7rem; align-items: center; color: var(--muted); font-size: .72rem; }
.admin-chart-bars label strong { color: var(--soft); text-align: right; }
progress { width: 100%; height: .48rem; overflow: hidden; appearance: none; border: 0; background: var(--raised); }
progress::-webkit-progress-bar { background: var(--raised); }
progress::-webkit-progress-value { background: var(--accent); }
progress::-moz-progress-bar { background: var(--accent); }
progress.is-muted::-webkit-progress-value { background: #778087; }
progress.is-muted::-moz-progress-bar { background: #778087; }
progress.is-history::-webkit-progress-value { background: #7fb7ff; }
progress.is-history::-moz-progress-bar { background: #7fb7ff; }
.admin-navigation-row { min-height: 4.2rem; margin-top: .7rem; padding: .75rem 1rem; display: grid; grid-template-columns: minmax(0,1fr) auto 1.5rem; align-items: center; gap: 1rem; color: var(--text); border: 1px solid var(--line); text-decoration: none; }
.admin-navigation-row:hover { border-color: var(--line-strong); background: #0a0d0f; }
.admin-navigation-row.is-static { grid-template-columns: minmax(0,1fr) auto; }
.admin-navigation-row.is-static:hover { background: transparent; border-color: var(--line); }
.admin-navigation-row > span { display: grid; gap: .15rem; }
.admin-navigation-row > span:nth-child(2) { text-align: right; }
.admin-navigation-row small { color: var(--faint); font-size: .78rem; }
.admin-row-arrow { color: var(--accent); font-size: 1.25rem; }
.admin-group-table { margin-top: 1rem; border: 1px solid var(--line); }
.admin-group-head, .admin-group-row { min-height: 3.7rem; display: grid; grid-template-columns: minmax(14rem,1.35fr) minmax(10rem,1fr) minmax(10rem,1fr) minmax(10rem,.8fr) 4rem; align-items: center; gap: 1rem; padding: .7rem .9rem; border-bottom: 1px solid var(--line); }
.admin-group-head { min-height: 2.5rem; color: var(--faint); background: #0a0d0f; font-size: .66rem; font-weight: 600; letter-spacing: .08em; text-transform: uppercase; }
.admin-group-row:last-child { border-bottom: 0; }
.admin-group-row > span { min-width: 0; display: grid; gap: .22rem; font-size: .84rem; }
.admin-group-row strong, .admin-group-row small { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.admin-group-row small { color: var(--faint); font-size: .7rem; }
.admin-index-status { min-height: 0; }
.admin-user-search { margin-top: 1rem; display: flex; gap: .65rem; }
.admin-user-search input { max-width: 26rem; }
.admin-user-table { margin-top: 1rem; border: 1px solid var(--line); }
.admin-user-head, .admin-user-row { min-height: 3.7rem; display: grid; grid-template-columns: minmax(14rem,1.3fr) minmax(8rem,.9fr) minmax(7rem,.8fr) minmax(7rem,.8fr) minmax(8rem,.9fr) minmax(6rem,.7fr) 1.5rem; align-items: center; gap: 1rem; padding: .7rem .9rem; border-bottom: 1px solid var(--line); }
.admin-user-head { min-height: 2.5rem; color: var(--faint); background: #0a0d0f; font-size: .66rem; font-weight: 600; letter-spacing: .08em; text-transform: uppercase; }
.admin-user-row { color: var(--text); text-decoration: none; }
.admin-user-row:hover { background: #0a0d0f; }
.admin-user-row:last-child { border-bottom: 0; }
.admin-user-row > span { min-width: 0; display: grid; gap: .22rem; font-size: .84rem; }
.admin-user-row strong, .admin-user-row small { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.admin-user-row small { color: var(--faint); font-size: .7rem; }
.admin-user-row .is-banned { color: #ff9b9b; }
.membership-pill { justify-self: start; padding: .3rem .5rem; border: 1px solid var(--line-strong); color: var(--muted); font-size: .66rem; font-weight: 600; letter-spacing: .05em; text-transform: uppercase; }
.membership-pill.is-vip, .membership-pill.is-lifetime, .membership-pill.is-admin { color: var(--accent); border-color: rgba(160,251,0,.3); background: var(--accent-soft); }
.membership-pill.is-subscribed { color: #7fb7ff; border-color: rgba(127,183,255,.35); }
.membership-pill.is-none { color: var(--faint); }
.admin-action-form { display: flex; align-items: center; gap: .5rem; }
.admin-action-form .button { min-height: 2.1rem; padding: .4rem .75rem; font-size: .82rem; }
.admin-action-form input[type="number"] { width: 5.5rem; height: 2.1rem; min-height: 2.1rem; padding: .35rem .55rem; }
.admin-action-form select { width: auto; height: 2.1rem; min-height: 2.1rem; padding: .3rem 2.1rem .3rem .7rem; appearance: none; background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' fill='none' stroke='%23949ba1' stroke-width='1.5'/%3E%3C/svg%3E"); background-repeat: no-repeat; background-position: right .7rem center; }
.admin-download-table, .admin-usage-table { margin-top: 1rem; border: 1px solid var(--line); }
.admin-download-head, .admin-download-row { min-height: 3.25rem; display: grid; grid-template-columns: minmax(0,1fr) 6rem 4.5rem 8rem; align-items: center; gap: 1rem; padding: .65rem .9rem; border-bottom: 1px solid var(--line); }
.admin-usage-head, .admin-usage-row { min-height: 2.75rem; display: grid; grid-template-columns: 12rem minmax(8rem,1fr) 8rem; align-items: center; gap: 1rem; padding: .55rem .9rem; border-bottom: 1px solid var(--line); }
.admin-download-head, .admin-usage-head { min-height: 2.5rem; color: var(--faint); background: #0a0d0f; font-size: .66rem; font-weight: 600; letter-spacing: .08em; text-transform: uppercase; }
.admin-download-row:last-child, .admin-usage-row:last-child { border-bottom: 0; }
.admin-download-row > span, .admin-usage-row > span { min-width: 0; display: grid; gap: .2rem; font-size: .84rem; }
.admin-download-row strong, .admin-download-row small { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.admin-download-row small { color: var(--faint); font-size: .7rem; }
.admin-download-row a { color: var(--text); text-decoration: none; }
.admin-download-row a:hover { color: var(--accent); }
/* The explanatory column is much shorter than the form beside it, so centring
   left it floating in the middle of the card instead of heading it. */
.backfill-code-reveal, .backfill-enroll-card { min-height: 0; display: grid; grid-template-columns: minmax(0,1fr) minmax(22rem,.9fr); gap: 2rem; align-items: start; }
.backfill-code-reveal p, .backfill-enroll-card p { margin: 0; color: var(--muted); line-height: 1.6; }
/* The install code reuses the shared .secret-output component and only adds an
   accent border, because this value is shown exactly once. It is not truncated
   for the same reason: a code you must copy has to be readable in full. */
.backfill-secret { min-width: 0; margin-top: 0; border-color: rgba(160,251,0,.35); }
.backfill-secret code { min-width: 0; color: var(--accent); }
.backfill-code-form { display: grid; grid-template-columns: 1fr 1fr; gap: .75rem; }
.backfill-code-form > label, .backfill-code-form fieldset { display: grid; gap: .35rem; }
.backfill-code-form fieldset { grid-column: 1/-1; margin: 0; padding: .75rem; border: 1px solid var(--line); }
.backfill-code-form legend { padding: 0 .3rem; color: var(--muted); font-size: .66rem; font-weight: 600; letter-spacing: .06em; text-transform: uppercase; }
.backfill-field-help { margin: 0 0 .45rem; color: var(--faint); font-family: var(--sans); font-size: .78rem; line-height: 1.45; }
.backfill-pool-option { padding: .45rem 0; display: flex; align-items: center; gap: .65rem; }
.backfill-pool-option input[type="checkbox"] { width: 1rem; height: 1rem; min-height: 0; margin: 0; padding: 0; flex: none; accent-color: var(--accent); }
.backfill-pool-option span { display: grid; gap: .1rem; }
.backfill-pool-option small { color: var(--faint); }
.backfill-code-form .button { grid-column: 1/-1; justify-self: end; }
.backfill-fleet-card, .backfill-codes-card { min-height: 0; }
.backfill-table, .backfill-code-list { margin-top: 1rem; border: 1px solid var(--line); }
.backfill-table-head, .backfill-table-row { min-height: 3.7rem; display: grid; grid-template-columns: 1fr 1.25fr 1fr 1.15fr auto; align-items: center; gap: .8rem; padding: .7rem .9rem; border-bottom: 1px solid var(--line); }
.backfill-table-head { min-height: 2.5rem; color: var(--faint); background: #0a0d0f; font-size: .66rem; font-weight: 600; letter-spacing: .08em; text-transform: uppercase; }
.backfill-table-row:last-child, .backfill-code-row:last-child, .backfill-generation-row:last-child { border-bottom: 0; }
.backfill-table-row > span, .backfill-code-row > span, .backfill-generation-row > span { min-width: 0; display: grid; gap: .15rem; }
.backfill-table-row strong, .backfill-table-row small, .backfill-code-row strong, .backfill-code-row small { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.backfill-table-row small, .backfill-code-row small, .backfill-generation-row small { color: var(--faint); font-size: .72rem; }
.backfill-worker-controls { display: flex !important; align-items: center; justify-content: flex-end; gap: .4rem !important; }
.backfill-worker-controls form { display: flex; align-items: center; gap: .35rem; }
.backfill-worker-controls input { width: 3.5rem; min-height: 2rem; padding: .35rem .45rem; }
.backfill-worker-controls .button { min-height: 2rem; padding: .35rem .55rem; font-size: .72rem; }
.backfill-code-row, .backfill-generation-row { min-height: 3.5rem; display: grid; align-items: center; gap: .8rem; padding: .7rem .9rem; border-bottom: 1px solid var(--line); }
.backfill-generation-row { grid-template-columns: minmax(0,1fr) 12rem auto; }
/* Install codes carry no status column: their lifecycle is in the detail line. */
.backfill-code-row { grid-template-columns: minmax(0,1fr) auto; }
.backfill-generation-controls { display: flex !important; align-items: center; justify-content: flex-end; gap: .4rem !important; }
.button.danger { color: #ff9b9b; border-color: rgba(255,100,100,.3); }
.admin-index-status > div:first-child p { margin: 0; color: var(--muted); font-size: .96rem; line-height: 1.65; }
.admin-stat-grid { grid-template-columns: repeat(6,minmax(0,1fr)); }
.admin-checkpoints { margin-top: 1rem; border: 1px solid var(--line); }
.admin-checkpoint-head, .admin-checkpoint-row { min-height: 3.25rem; display: grid; grid-template-columns: 1.1fr 1.35fr 1fr .6fr .7fr; align-items: center; gap: .75rem; padding: .65rem .85rem; border-bottom: 1px solid var(--line); }
.admin-checkpoint-head { min-height: 2.5rem; color: var(--faint); background: #0a0d0f; font-size: .68rem; font-weight: 600; letter-spacing: .08em; text-transform: uppercase; }
.admin-checkpoint-row:last-child { border-bottom: 0; }
.admin-checkpoint-row > span { min-width: 0; display: grid; gap: .15rem; font-size: .88rem; }
.admin-checkpoint-row strong, .admin-checkpoint-row small { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.admin-checkpoint-row small { color: var(--faint); font-size: .75rem; }
.admin-settings { min-height: 0; grid-column: 1/-1; }
/* Registration and invitation credits share one card: copy on the left, the
   control on the right, split by a rule. */
.admin-settings-row { display: grid; grid-template-columns: minmax(0,1fr) minmax(20rem,.75fr); align-items: center; gap: 2rem; }
.admin-settings-row + .admin-settings-row { margin-top: 1.4rem; padding-top: 1.4rem; grid-template-columns: minmax(0,1fr) minmax(24rem,.9fr); align-items: end; border-top: 1px solid var(--line); }
.admin-settings h2 { margin: 0 0 .25rem; }
.admin-settings p { max-width: 48rem; margin: 0; color: var(--muted); font-size: .96rem; line-height: 1.65; }
.registration-control { display: flex; align-items: center; justify-content: flex-end; gap: .65rem; }
.registration-toggle { min-width: 20rem; padding: .85rem 1rem; display: flex; grid-template-columns: none; align-items: center; justify-content: space-between; gap: 1rem; color: var(--text); background: #0a0d0f; border: 1px solid var(--line); font-family: var(--sans); letter-spacing: 0; cursor: pointer; }
.registration-copy { display: grid; gap: .2rem; }
.registration-copy strong { font-size: .96rem; }
.registration-copy small { color: var(--faint); font-size: .82rem; line-height: 1.35; }
.switch { width: 3.25rem; height: 1.75rem; flex: none; position: relative; }
.switch input { width: 100%; height: 100%; min-height: 0; margin: 0; position: absolute; z-index: 2; inset: 0; opacity: 0; cursor: pointer; }
.switch-track { position: absolute; inset: 0; background: var(--raised); border: 1px solid var(--line-strong); transition: background 150ms ease,border-color 150ms ease; }
.switch-track::after { content: ""; width: 1.15rem; height: 1.15rem; position: absolute; top: .24rem; left: .25rem; background: var(--muted); transition: transform 150ms ease,background 150ms ease; }
.switch input:checked + .switch-track { background: var(--accent-soft); border-color: rgba(200,255,0,.5); }
.switch input:checked + .switch-track::after { background: var(--accent); transform: translateX(1.45rem); }
.switch input:focus-visible + .switch-track { outline: 2px solid var(--accent); outline-offset: 2px; }
.js .registration-control > button { display: none; }
.admin-credit-form { display: grid; grid-template-columns: minmax(0,1fr) 7rem auto; align-items: end; gap: .65rem; }
/* The results hang over the form and only while the field holds focus, which
   is also what closes them once a member is picked. They open upwards because
   this card is the last thing on the admin page, so a list below the field
   would drop past the fold. */
.member-picker { min-width: 0; position: relative; }
.member-options { max-height: 15rem; position: absolute; z-index: 30; right: 0; bottom: calc(100% + .3rem); left: 0; display: none; overflow-y: auto; background: var(--raised); border: 1px solid var(--line-strong); box-shadow: 0 -12px 28px rgb(0 0 0 / .45); }
.member-picker:focus-within .member-options:not(:empty) { display: block; }
.member-picker.is-dismissed .member-options { display: none; }
.member-option { width: 100%; min-height: 0; padding: .5rem .7rem; display: flex; align-items: baseline; gap: .5rem; color: var(--text); background: none; border: 0; border-bottom: 1px solid var(--line); font-family: var(--sans); text-align: left; cursor: pointer; }
.member-option:last-child { border-bottom: 0; }
.member-option:hover, .member-option:focus-visible { background: var(--accent-soft); }
.member-option strong { flex: none; font-size: .92rem; font-weight: 600; }
.member-option small { min-width: 0; overflow: hidden; color: var(--faint); font-size: .78rem; text-overflow: ellipsis; white-space: nowrap; }
.member-option-empty { margin: 0; padding: .6rem .7rem; color: var(--faint); font-size: .78rem; }
.membership-badge { width: fit-content; margin: 1.5rem 0 3rem; padding: .4rem .6rem; color: var(--green); background: rgba(115,216,162,.08); border: 1px solid rgba(115,216,162,.2); font-size: .74rem; font-weight: 600; letter-spacing: .06em; text-transform: uppercase; }
.membership-badge i { width: .35rem; height: .35rem; display: inline-block; margin-right: .35rem; background: var(--green); border-radius: 50%; }
.facts-list { display: grid; gap: .8rem; }
.facts-list div { display: flex; justify-content: space-between; gap: 1rem; }
.facts-list dt, .facts-list dd { margin: 0; color: var(--faint); font-size: .84rem; }
.facts-list dd { color: var(--soft); }
.inline-form { margin-top: 1.5rem; display: grid; grid-template-columns: 1fr auto; gap: .5rem; }
/* A secret sits in a control, not a panel: it hugs its content and keeps the
   copy button inside, so whatever acts on it can sit on the same line. */
.secret-row { margin-bottom: 1rem; display: flex; align-items: stretch; gap: .6rem; }
.secret-row .secret-output { flex: 1; min-width: 0; margin-top: 0; }
.secret-row .button { flex: none; }
.account-rows .secret-output { width: fit-content; max-width: 100%; margin-top: 0; padding: .35rem .35rem .35rem .75rem; }
.account-rows .secret-output code { font-size: .86rem; }
.account-rows .secret-output button { width: 2.1rem; height: 2.1rem; }
.secret-output { margin-top: 1rem; padding: 1rem; display: flex; align-items: center; gap: .75rem; color: var(--accent-strong); background: #07090a; border: 1px solid var(--line); }
.secret-output code { flex: 1; overflow-wrap: anywhere; font-size: .92rem; }
.secret-output button { flex: none; width: 2.3rem; height: 2.3rem; display: grid; place-items: center; color: var(--soft); background: transparent; border: 1px solid var(--line); }
.secret-output button .icon { width: 1.15rem; height: 1.15rem; }
.secret-output button:hover { color: var(--accent); background: var(--accent-soft); }
.secret-output button .icon:last-child, .secret-output button.is-copied .icon:first-child { display: none; }
.secret-output button.is-copied { color: var(--accent); background: var(--accent-soft); border-color: rgba(200,255,0,.45); }
.secret-output button.is-copied .icon:last-child { display: block; }
.key-list { margin-top: 1rem; display: grid; border-top: 1px solid var(--line); }
.key-list > div { padding: .8rem 0; display: flex; align-items: center; justify-content: space-between; gap: 1rem; border-bottom: 1px solid var(--line); }
.key-list span { display: grid; gap: .25rem; }
.key-list strong { font-size: .96rem; }
.key-list small, .muted { color: var(--faint); font-size: .82rem; }
.key-list .key-actions { display: flex; align-items: center; gap: .6rem; }
.key-actions button { padding: .4rem .55rem; color: var(--red); background: transparent; border: 1px solid rgba(241,123,134,.25); font-size: .82rem; }

/* A credential is only useful once it is on the clipboard, so the field is
   built around the copy button rather than around the text: label above, value
   and button on one line, and the caveat that stops a wrong paste below. */
.connect-grid { display: grid; grid-template-columns: repeat(auto-fit,minmax(17rem,1fr)); gap: 1.25rem; }
.copy-field { display: grid; gap: .35rem; align-content: start; }
.copy-field-label { color: var(--faint); font-size: .74rem; font-weight: 600; letter-spacing: .08em; text-transform: uppercase; }
.copy-field .secret-output { margin-top: 0; }
.copy-field > small { color: var(--faint); font-size: .84rem; line-height: 1.5; }
/* An invitation is a credential its owner has to read, copy and hand over, so
   the row leads with the code and its link rather than with a recipient. Spent
   ones keep their place as a record but drop the copy affordance. */
.invite-list { margin-top: 1.25rem; display: grid; gap: .75rem; }
.invite-row { padding: 1rem; display: grid; grid-template-columns: 1fr auto auto; align-items: center; gap: 1rem; background: #07090a; border: 1px solid var(--line); }
.invite-credentials { display: grid; grid-template-columns: repeat(auto-fit,minmax(13rem,1fr)); gap: .75rem; }
.invite-code-spent { color: var(--faint); font-size: .9rem; text-decoration: line-through; }
.invite-meta { display: grid; gap: .2rem; text-align: right; }
.invite-meta strong { font-size: .9rem; }
.invite-meta small { color: var(--faint); font-size: .78rem; }
.invite-row.is-spent { opacity: .62; }
@media (max-width: 46rem) {
  .invite-row { grid-template-columns: 1fr; }
  .invite-meta { text-align: left; }
}
/* A code-tutorial language picker: the radio that is checked reveals its own
   panel and lights its own tab, so switching applications costs no script. The
   panels are hidden rather than unmounted, which keeps every copy button in the
   document for the delegated handler. */
.app-tabs { display: grid; }
.app-tab-input { position: absolute; width: 1px; height: 1px; opacity: 0; pointer-events: none; }
.app-tabs-nav { display: flex; flex-wrap: wrap; gap: .1rem; border-bottom: 1px solid var(--line); }
.app-tabs-nav label { padding: .7rem 1rem; display: flex; align-items: center; gap: .5rem; color: var(--muted); font-size: .84rem; border-bottom: 2px solid transparent; cursor: pointer; }
.app-tabs-nav label:hover { color: var(--text); background: var(--raised); }
.app-tabs-nav img { width: 1.25rem; height: 1.25rem; object-fit: contain; }
/* The inputs are visually gone, so the ring has to land on the label the user
   is actually tabbing through. */
.app-tab-input:focus-visible ~ .app-tabs-nav label[for] { outline: none; }
#app-prowlarr:focus-visible ~ .app-tabs-nav label[for="app-prowlarr"],
#app-sonarr:focus-visible ~ .app-tabs-nav label[for="app-sonarr"],
#app-radarr:focus-visible ~ .app-tabs-nav label[for="app-radarr"],
#app-nzbhydra:focus-visible ~ .app-tabs-nav label[for="app-nzbhydra"] { outline: 2px solid var(--accent); outline-offset: -2px; }
.app-tab-panel { display: none; padding: 1.5rem; background: var(--surface); border: 1px solid var(--line); border-top: 0; }
#app-prowlarr:checked ~ .app-tabs-nav label[for="app-prowlarr"],
#app-sonarr:checked ~ .app-tabs-nav label[for="app-sonarr"],
#app-radarr:checked ~ .app-tabs-nav label[for="app-radarr"],
#app-nzbhydra:checked ~ .app-tabs-nav label[for="app-nzbhydra"] { color: var(--accent); background: var(--accent-soft); border-bottom-color: var(--accent); }
#app-prowlarr:checked ~ .app-tab-prowlarr,
#app-sonarr:checked ~ .app-tab-sonarr,
#app-radarr:checked ~ .app-tab-radarr,
#app-nzbhydra:checked ~ .app-tab-nzbhydra { display: block; }
.app-tab-heading { display: flex; align-items: flex-start; gap: 1rem; }
.app-tab-heading img { flex: none; width: 2.25rem; height: 2.25rem; object-fit: contain; }
.app-tab-heading h3 { margin: .15rem 0 .25rem; font-size: 1.15rem; }
.app-tab-heading p { margin: 0; color: var(--muted); font-size: .94rem; }
/* The breadcrumb is the menu walk, so the separator between steps is drawn
   rather than typed and cannot end up copied along with the value. */
.app-tab-path { margin: 1.25rem 0; display: flex; flex-wrap: wrap; align-items: center; gap: .4rem; font-size: .9rem; }
.app-tab-path span { color: var(--faint); }
.app-tab-path b { color: var(--soft); font-weight: 620; }
.app-tab-path span:not(:first-child)::before { content: "→"; margin-right: .4rem; color: var(--line-strong); }
.app-tab-fields { margin: 0; display: grid; border-top: 1px solid var(--line); }
.app-tab-fields > div { padding: .7rem 0; display: grid; grid-template-columns: minmax(6rem,10rem) 1fr; align-items: center; gap: 1rem; border-bottom: 1px solid var(--line); }
.app-tab-fields dt { color: var(--faint); font-size: .84rem; }
.app-tab-fields dd { margin: 0; min-width: 0; display: flex; align-items: center; gap: .6rem; }
.app-tab-fields code { flex: 1; min-width: 0; color: var(--accent-strong); font-size: .88rem; overflow-wrap: anywhere; }
.app-tab-fields button { flex: none; width: 2.1rem; height: 2.1rem; display: grid; place-items: center; color: var(--soft); background: transparent; border: 1px solid var(--line); }
.app-tab-fields button:hover { color: var(--accent); background: var(--accent-soft); }
.app-tab-fields button .icon { width: 1.05rem; height: 1.05rem; }
.app-tab-fields button .icon:last-child, .app-tab-fields button.is-copied .icon:first-child { display: none; }
.app-tab-fields button.is-copied { color: var(--accent); background: var(--accent-soft); border-color: rgba(200,255,0,.45); }
.app-tab-fields button.is-copied .icon:last-child { display: block; }
.docs-panel code { color: var(--accent-strong); font-size: .84rem; overflow-wrap: anywhere; }
.technical-grid { display: grid; grid-template-columns: repeat(4,minmax(0,1fr)); margin-top: 1rem; border-top: 1px solid var(--line); border-left: 1px solid var(--line); }
.technical-grid > div { min-height: 4.5rem; padding: .85rem 1rem; display: flex; flex-direction: column; gap: .35rem; border-right: 1px solid var(--line); border-bottom: 1px solid var(--line); }
.technical-grid span { color: var(--muted); font-size: .66rem; font-weight: 600; letter-spacing: .08em; text-transform: uppercase; }
.technical-grid strong { overflow-wrap: anywhere; }
.technical-panel { padding: .7rem .8rem; display: grid; grid-template-columns: auto minmax(0,1fr); align-items: center; gap: 1rem; }
.technical-heading { min-width: 9.5rem; }
.technical-panel .technical-heading h2 { margin: 0; }
.technical-panel .technical-grid { margin: 0; display: flex; align-items: center; flex-wrap: wrap; border: 0; }
.technical-panel .technical-grid > div { min-height: 0; padding: .24rem .65rem; display: inline-flex; flex-direction: row; align-items: baseline; gap: .35rem; border: 0; border-left: 1px solid var(--line); }
/* A forty language subtitle list is far wider than the panel, so this one cell
   is allowed to shrink past its text and wrap instead of pushing the row out. */
.technical-panel .technical-grid > div.technical-subtitles { min-width: 0; }
.technical-panel .technical-grid > div.technical-subtitles strong { overflow-wrap: anywhere; }
.technical-panel .technical-grid span { font-size: .61rem; letter-spacing: .06em; }
.technical-panel .technical-grid strong { color: var(--soft); font-size: .78rem; font-weight: 520; }
.release-document { width: min(92vw, 72rem); max-height: 88vh; padding: 0; color: var(--text); background: var(--surface); border: 1px solid var(--line-strong); }
/* Opaque rather than a tinted blur: the rest of the site draws flat surfaces on
   flat surfaces, and a frosted panel is the one place that would read as glass. */
.release-document::backdrop { background: var(--canvas); }
.release-document-card { display: grid; grid-template-rows: auto minmax(0,1fr); max-height: 88vh; }
.release-document-card > header { padding: 1rem 1.15rem; display: flex; align-items: center; justify-content: space-between; border-bottom: 1px solid var(--line); }
.release-document-card h2 { margin: .12rem 0 0; font-size: 1.15rem; }
.release-document-close, .dialog-close { width: 2.35rem; height: 2.35rem; color: var(--text); background: transparent; border: 1px solid var(--line); font-size: 1.65rem; line-height: 1; cursor: pointer; }
.release-document-close:hover, .dialog-close:hover { background: var(--hover); border-color: var(--line-strong); }
/* The moderation tools live behind a button so the release page stays a
   release page for the admin too; the dialog lays out the same panel that used
   to sit inline. */
.moderation-dialog { width: min(92vw, 52rem); max-height: 88vh; padding: 0; color: var(--text); background: var(--surface); border: 1px solid var(--line-strong); }
.moderation-dialog::backdrop { background: rgba(8,10,12,.82); }
.moderation-dialog .admin-moderation { padding: 0 1.4rem 1.4rem; }
.moderation-dialog-head { margin: 0 -1.4rem 1rem; padding: 1rem 1.4rem; display: flex; align-items: center; justify-content: space-between; gap: 1rem; border-bottom: 1px solid var(--line); }
.moderation-dialog-head h2 { margin: 0; font-size: 1.15rem; }
.release-document pre { min-height: 14rem; margin: 0; padding: 1rem 1.15rem 1.35rem; overflow: auto; color: var(--soft); background: var(--canvas); font: .78rem/1.45 var(--mono); white-space: pre; tab-size: 4; }
.technical-note { margin: .85rem 0 0; color: var(--muted); font-size: .86rem; }
.docs-panel { margin-top: 1rem; }
.endpoint-list { margin-top: 1rem; display: grid; grid-template-columns: 10rem 1fr; border-top: 1px solid var(--line); }
.endpoint-list code, .endpoint-list span { padding: .75rem; border-bottom: 1px solid var(--line); font-size: .88rem; }
.endpoint-list code { color: var(--accent); background: #0a0d0f; }
.endpoint-list span { color: var(--muted); }
/* Copy-pasteable command samples. A submission command carries the account's
   API key, so it must wrap rather than scroll a long line out of sight. */
.code-block { margin: .85rem 0 0; padding: .85rem 1rem; overflow-x: auto; color: var(--soft); background: var(--canvas); border: 1px solid var(--line); border-radius: 4px; font: .78rem/1.5 var(--mono); white-space: pre-wrap; overflow-wrap: anywhere; tab-size: 2; }
.code-block code { color: inherit; background: none; }
h3.account-section-heading { margin-top: 1.35rem; font-size: .95rem; }

/* Sign-in is split: the form on the left, the globe and the pitch on the right. */
/* These pages are exactly one viewport tall and never scroll, so the gutter the
   rest of the site reserves would only leave a strip of canvas showing beside
   the right-hand panel, which runs to the very edge. */
html:has(.auth-page) { scrollbar-gutter: auto; }
.auth-page { min-height: 100vh; display: grid; grid-template-columns: minmax(0,.92fr) minmax(0,1.08fr); background: var(--canvas); }
.auth-visual { min-height: 100vh; padding: clamp(2rem,4vw,3.5rem) clamp(2rem,4.5vw,4.5rem) clamp(2.5rem,6vh,4.5rem); display: flex; flex-direction: column; justify-content: flex-end; position: relative; overflow: hidden; background: radial-gradient(circle at 72% 22%,rgba(200,255,0,.14),transparent 30rem),#0d1114; border-left: 1px solid var(--line); }
/* Braille cells carry a 2x4 dot grid. line-height 1.2 makes those dots square,
   because a monospace cell is about 0.6em wide: 0.6/2 across, 1.2/4 down.
   The globe is oversized and cropped by the panel's top-right corner. */
/* No text-shadow here on purpose: a blurred shadow over a block this size has to
   be re-rasterised on every frame of the spin and locks up the renderer. The
   glow lives in the panel background instead, where it is painted once. */
.ascii-globe { position: absolute; top: -21%; right: -17%; z-index: 1; margin: 0; contain: paint; color: var(--accent); font-family: var(--mono); font-size: clamp(.38rem,.75vw,.64rem); line-height: 1.2; white-space: pre; cursor: grab; touch-action: none; user-select: none; }
.ascii-globe.is-dragging { cursor: grabbing; }
/* Scrim under the copy: the globe may run behind it, but the bottom of the panel
   darkens so the list never competes with the dots for contrast. */
.auth-visual::after { content: ""; position: absolute; inset: 0; z-index: 2; pointer-events: none; background: linear-gradient(to top,rgba(13,17,20,.97) 0%,rgba(13,17,20,.8) 22%,rgba(13,17,20,0) 52%); }
.auth-pitch { width: 100%; max-width: 30rem; position: relative; z-index: 3; }
/* A capability list, not a headline: nothing here is sized to sell. */
.auth-points { max-width: 34rem; margin: 1rem 0 0; padding: 0; display: grid; gap: .7rem; list-style: none; }
.auth-points li { padding-left: 1.4rem; position: relative; color: var(--soft); font-size: .95rem; line-height: 1.5; }
.auth-points li::before { content: "+"; position: absolute; left: 0; color: var(--accent); font-weight: 700; }
/* The mark and its name are one unit, so a wrap never leaves an icon stranded
   at the end of a line from the product it belongs to. */
.auth-app { display: inline-flex; align-items: center; gap: .32rem; white-space: nowrap; vertical-align: bottom; }
.auth-app img { width: 1.05em; height: 1.05em; display: block; }
.auth-brand { position: relative; z-index: 1; }
.auth-form-wrap { display: grid; place-items: center; padding: 2rem; }
/* Split sign-in: the form sits straight on the panel, no card around it. */
.auth-page > .auth-form-wrap { min-height: 100vh; padding: clamp(1.75rem,3.5vw,3rem) clamp(1.5rem,5vw,5.5rem); grid-template-rows: auto 1fr auto; place-items: stretch; }
.auth-brand { width: fit-content; }
/* The column is centred in the panel and only the brand stays pinned top-left;
   field labels keep their left edge so the inputs still read as a form. */
.auth-page > .auth-form-wrap .auth-form { width: min(100%,25rem); align-self: center; justify-self: center; text-align: center; }
.auth-page .auth-form h2 { font-size: 2.4rem; }
.auth-page .auth-form label { text-align: left; }
.auth-legal { max-width: 27rem; margin: 0 auto; color: var(--faint); font-size: .78rem; line-height: 1.6; text-align: center; }
.auth-form { width: min(100%,24rem); display: grid; gap: 1rem; }
.auth-form h2 { margin: .25rem 0 -.6rem; font-size: 2rem; letter-spacing: -.04em; }
.auth-form > p { margin: 0 0 1rem; color: var(--muted); font-size: 1rem; }
.auth-form > small { color: var(--faint); font-size: .89rem; text-align: center; }
.auth-form > small a { color: var(--accent); }
.auth-form label small { color: var(--faint); }
.auth-page-single { display: grid; grid-template-columns: 1fr; position: relative; overflow: hidden; background: radial-gradient(circle at 50% 42%,rgba(200,255,0,.09),transparent 27rem),var(--canvas); }
.auth-page-single::before { content: ""; position: absolute; inset: 0; opacity: .08; background-image: linear-gradient(rgba(255,255,255,.08) 1px,transparent 1px),linear-gradient(90deg,rgba(255,255,255,.08) 1px,transparent 1px); background-size: 3rem 3rem; mask-image: radial-gradient(circle at center,#000,transparent 68%); pointer-events: none; }
.auth-page-single .auth-form-wrap { min-height: 100vh; position: relative; z-index: 1; }
.auth-card { width: min(100%,29rem); padding: clamp(1.5rem,4vw,2.4rem); background: rgba(14,17,20,.96); border: 1px solid var(--line); box-shadow: 0 1.5rem 5rem rgba(0,0,0,.38); }
.auth-card-brand { width: fit-content; margin: 0 auto 2.15rem; }
.auth-card .auth-form { width: 100%; }
.auth-resend { display: grid; gap: 1rem; }
.form-notice { padding: .8rem; color: var(--accent-strong); background: var(--accent-soft); border: 1px solid rgba(200,255,0,.3); font-size: .9rem; line-height: 1.5; }
.form-error { padding: .75rem; font-size: .9rem; }
.error-state { min-height: 60vh; display: grid; place-content: center; justify-items: start; }
.error-state h1 { max-width: 42rem; margin: 0 0 .6rem; font-size: clamp(2.5rem,6vw,5rem); letter-spacing: -.06em; line-height: .95; }
.error-state p { color: var(--muted); }
.error-state div { display: flex; gap: .5rem; }

/* The labels hold on until the search bar next to them would be squeezed past
   its comfortable width; the bar shrinks first, these collapse second. */
@media (max-width: 1150px) {
  .top-primary-nav .top-nav-label { display: none; }
  .top-primary-nav a { width: 2.65rem; padding: 0; justify-content: center; }
}
@media (max-width: 1200px) {
  .poster-grid { grid-template-columns: repeat(4,minmax(0,1fr)); }
  .release-head, .release-row { grid-template-columns: minmax(12rem,1fr) 4rem 5rem 4.5rem; }
  .release-head > :nth-child(4), .release-row > :nth-child(4) { display: none; }
  .technical-grid { grid-template-columns: repeat(2,minmax(0,1fr)); }
  .admin-stat-grid { grid-template-columns: repeat(3,minmax(0,1fr)); }
  .admin-summary-grid { grid-template-columns: repeat(2,minmax(0,1fr)); }
  .admin-group-head, .admin-group-row { grid-template-columns: minmax(12rem,1.25fr) minmax(9rem,1fr) minmax(9rem,1fr) minmax(9rem,.8fr); }
  .admin-group-head > :last-child, .admin-group-row > :last-child { display: none; }
}
@media (max-width: 900px) {
  :root { --gutter: 1rem; }
  .brand > span:last-child { display: none; }
  .user-pill div { display: none; }
  .advanced-panel { width: min(35rem,calc(100vw - 2rem)); }
  .metric-grid { grid-template-columns: repeat(3,1fr); }
  .metric-grid > div:nth-child(3n) { border-right: 0; }
  .metric-grid > div:nth-child(-n+3) { border-bottom: 1px solid var(--line); }
  .auth-page { grid-template-columns: 1fr; }
  .auth-visual { display: none; }
  .admin-settings-row { grid-template-columns: 1fr; gap: 1.25rem; }
  .registration-control { justify-content: flex-start; }
  .admin-availability-chart { grid-template-columns: 1fr; gap: .8rem; }
  .admin-group-head { display: none; }
  .admin-group-row { grid-template-columns: 1fr 1fr; }
}
@media (max-width: 680px) {
  :root { --gutter: .85rem; --page-pad-block: 1rem; }
  .topbar-main { min-height: 4rem; padding-block: .65rem; gap: .5rem; }
  .top-primary-nav { display: none; }
  .topbar-main > .brand { margin-right: 0; }
  .brand-mark { width: 2.35rem; height: 2.35rem; }
  .global-search { width: auto; min-width: 0; flex: 1; }
  .global-search-submit { display: none; }
  .top-actions { margin-left: 0; }
  .cart-shortcut { width: 2.65rem; height: 2.65rem; }
  .user-pill { gap: 0; }
  .user-pill > span { width: 2.65rem; height: 2.65rem; }
  .user-pill > .icon { display: none; }
  .user-menu-primary { display: grid; }
  .advanced-panel { position: fixed; top: 4rem; right: .65rem; width: calc(100vw - 1.3rem); max-height: calc(100vh - 5rem); }
  /* Keep every top-level category reachable without replacing the tail with a
     synthetic More menu. The row is a compact horizontal scroller, and it stays
     one while a category is open: the dropdown leaves the scrollport by being
     fixed instead, because lifting the overflow to let it out would let the
     whole row out too and widen the page. With top left auto it keeps its
     in-flow spot right under the row; the top bar's backdrop filter makes it
     the containing block, so the panel rides with the sticky header. */
  .category-nav { overflow-x: auto; overscroll-behavior-inline: contain; scrollbar-width: none; -webkit-overflow-scrolling: touch; }
  .category-nav::-webkit-scrollbar { display: none; }
  .category-nav > * { flex: 0 0 auto; }
  .category-dropdown { position: fixed; top: auto; left: .65rem; right: .65rem; max-height: calc(100vh - 9rem); overflow-y: auto; }
  .poster-grid { grid-template-columns: repeat(2,minmax(0,1fr)); }
  .media-sections { gap: 2.5rem; }
  .search-summary { align-items: flex-start; flex-direction: column; }
  /* Mobile only needs the two directional actions. Desktop keeps the numbered
     navigator plus first/last shortcuts. */
  .pagination { width: 100%; display: grid; grid-template-columns: repeat(2,2.75rem); justify-content: center; gap: .5rem; overflow: visible; }
  .pagination > :first-child, .pagination > :last-child, .pagination-page { display: none; }
  .pagination-edge { min-width: 0; width: 2.75rem; height: 2.75rem; padding: 0; }
  .release-head { display: none; }
  .release-list, .release-row, .release-primary, .release-name, .release-meta, .release-languages { min-width: 0; max-width: 100%; }
  .release-row { grid-template-columns: minmax(0,1fr) auto; gap: .5rem; }
  .release-languages { align-items: flex-start; }
  .language-track { width: fit-content; padding-block: .2rem; }
  .track-label { min-height: 1.3rem; }
  .release-row > :nth-child(2), .release-row > :nth-child(3), .release-row > :nth-child(4) { display: none; }
  .release-actions { grid-column: 2; grid-row: 1; }
  .release-preview:hover .release-preview-pop, .release-preview:focus-visible .release-preview-pop { display: none; }
  .release-preview.is-open::before { content: ""; position: fixed; inset: 0; z-index: 39; background: rgb(0 0 0 / .68); }
  .release-preview.is-open .release-preview-pop { width: calc(100vw - 2rem); max-height: calc(100vh - 6rem); position: fixed; top: 50%; right: auto; bottom: auto; left: 50%; z-index: 40; display: block; overflow: auto; transform: translate(-50%,-50%); }
  .media-hero { min-height: 34rem; padding: 6rem var(--gutter) 2rem; align-items: flex-start; flex-direction: column; justify-content: flex-end; }
  /* The base rule pins a height computed from the copy beside it. Stacked, the
     copy is no longer beside it, and leaving that height set would defeat
     aspect-ratio — a declared width and height together win over it, and the
     artwork was being cropped to a 7rem-wide strip of a 25rem-tall box. */
  .media-poster { width: 9rem; height: auto; }
  .media-copy h1 { font-size: 2.3rem; }
  .release-detail-hero { padding: 1rem; align-items: flex-start; flex-direction: column; gap: 1rem; }
  .release-detail-poster { width: 6rem; }
  .release-detail-head h1 { font-size: 1.65rem; line-height: 1.16; }
    .episode-switcher-row { grid-template-columns: 1fr; gap: .2rem; }
  .episode-switcher-row h2 { padding: .25rem 0; }
  .episode-switcher-options { grid-template-columns: repeat(auto-fill,minmax(4rem,1fr)); }
  .metric-grid { grid-template-columns: repeat(2,1fr); }
  .metric-grid > div, .metric-grid > div:nth-child(3n) { border-right: 1px solid var(--line); border-bottom: 1px solid var(--line); }
  .metric-grid > div:nth-child(2n) { border-right: 0; }
  .detail-panel.split, .settings-grid { grid-template-columns: 1fr; }
  .registration-control, .registration-toggle { width: 100%; min-width: 0; }
  .admin-credit-form { grid-template-columns: 1fr; }
  .admin-stat-grid { grid-template-columns: repeat(2,minmax(0,1fr)); }
  .admin-summary-grid { grid-template-columns: 1fr 1fr; }
  .admin-summary-grid strong { font-size: 1.25rem; }
  .admin-chart-bars label { grid-template-columns: 4.5rem minmax(0,1fr); }
  .admin-chart-bars label strong { display: none; }
  .admin-navigation-row, .admin-navigation-row.is-static { grid-template-columns: 1fr auto; }
  .admin-navigation-row > span:nth-child(2) small { display: none; }
  .admin-row-arrow { display: none !important; }
  .admin-group-row { grid-template-columns: 1fr; gap: .65rem; }
  .admin-checkpoint-head { display: none; }
  .admin-checkpoint-row { grid-template-columns: 1fr 1fr; }
  .admin-checkpoint-row > span:nth-child(n+3) { color: var(--faint); }
  .file-list > div { align-items: flex-start; flex-direction: column; }
  .inline-form { grid-template-columns: 1fr; }
  .auth-form-wrap { padding: 1.25rem; }
  .endpoint-list { grid-template-columns: 1fr; }
  .endpoint-list code { border-bottom: 0; }
  .page-actions { align-items: flex-start; flex-direction: column; }
  .backfill-code-reveal, .backfill-enroll-card { grid-template-columns: 1fr; }
  .backfill-code-form { grid-template-columns: 1fr; }
  .backfill-code-form > *, .backfill-code-form fieldset, .backfill-code-form .button { grid-column: 1; }
  .backfill-table-head { display: none; }
  .backfill-table-row { grid-template-columns: 1fr; }
  .backfill-code-row { grid-template-columns: 1fr auto; }
  .backfill-code-row > span:first-child { grid-column: 1/-1; }
}
@media (max-width: 360px) {
  .category-nav { --tab-inset: .3rem; }
  .category-nav > a, .category-menu > summary { font-size: .76rem; }
}
@media (max-width: 900px) {
  .release-detail .release-detail-hero { grid-template-columns: 6rem minmax(0,1fr); grid-template-areas: "poster head" "poster metrics" "actions actions"; }
  .release-detail .release-detail-hero-bare { grid-template-columns: minmax(0,1fr); grid-template-areas: "head" "metrics" "actions"; }
  .release-detail .release-detail-poster { width: 6rem; }
  .release-detail .metric-grid { height: auto; grid-template-columns: repeat(4,1fr); }
  .release-detail .metric-grid > div { grid-template-columns: 1fr; border-right: 1px solid var(--line); border-bottom: 0; }
  .release-detail .metric-grid > div:last-child { border-right: 0; }
}
@media (max-width: 680px) {
  .release-detail .release-detail-hero { padding: .75rem; grid-template-columns: 4.4rem minmax(0,1fr); grid-template-areas: "poster head" "actions actions" "metrics metrics"; gap: .7rem; }
  .release-detail .release-detail-hero-bare { grid-template-columns: minmax(0,1fr); grid-template-areas: "head" "actions" "metrics"; }
  .release-detail .release-detail-poster { width: 4.4rem; }
  .release-detail .release-detail-head h1 { font-size: 1.12rem; }
  .release-detail .release-detail-actions { display: grid; grid-template-columns: 1fr 1fr; }
  .release-detail .release-detail-actions .button { width: 100%; }
  .release-detail .metric-grid { grid-template-columns: repeat(2,1fr); }
  .release-detail .metric-grid > div { padding: .45rem .55rem; border-right: 1px solid var(--line); border-bottom: 1px solid var(--line); }
  .release-detail .metric-grid > div:nth-child(2n) { border-right: 0; }
  .release-detail .metric-grid > div:last-child { border-bottom: 0; }
  .technical-panel { grid-template-columns: 1fr; gap: .5rem; }
  .technical-panel .technical-grid > div { padding-left: 0; padding-right: .65rem; border-left: 0; }
}
@media (max-width: 360px) {
  .release-detail .release-detail-actions { grid-template-columns: 1fr; }
}
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { transition-duration: .01ms !important; }
}

.admin-release-table { margin-top: 1rem; border: 1px solid var(--line); }
.admin-release-head, .admin-release-row { min-height: 3.7rem; display: grid; grid-template-columns: minmax(14rem,1.4fr) minmax(9rem,1fr) minmax(8rem,.9fr) minmax(4.5rem,.5fr) minmax(6rem,.7fr) 1.5rem; align-items: center; gap: 1rem; padding: .7rem .9rem; border-bottom: 1px solid var(--line); }
.admin-release-head { min-height: 2.5rem; color: var(--faint); background: #0a0d0f; font-size: .66rem; font-weight: 600; letter-spacing: .08em; text-transform: uppercase; }
.admin-release-row { color: var(--text); text-decoration: none; }
.admin-release-row:hover { background: #0a0d0f; }
.admin-release-row:last-child { border-bottom: 0; }
.admin-release-row > span { min-width: 0; display: grid; gap: .22rem; font-size: .84rem; }
.admin-release-row strong, .admin-release-row small { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.admin-release-row small { color: var(--faint); font-size: .7rem; }
.admin-release-row .is-banned { color: #ff9b9b; }
.admin-release-search select { width: auto; height: 2.6rem; }
.moderation-hint { margin: .9rem 0 0; color: var(--faint); font-size: .74rem; }
.moderation-pill { justify-self: start; padding: .3rem .5rem; border: 1px solid var(--line-strong); color: var(--muted); font-size: .66rem; font-weight: 600; letter-spacing: .05em; text-transform: uppercase; }
.moderation-pill.is-ready { color: var(--accent); border-color: rgba(160,251,0,.3); background: var(--accent-soft); }
.moderation-pill.is-quarantined { color: #7fb7ff; border-color: rgba(127,183,255,.35); }
.moderation-pill.is-hidden { color: #e8c46b; border-color: rgba(232,196,107,.35); }
.moderation-pill.is-removed { color: #ff9b9b; border-color: rgba(255,155,155,.35); }
.admin-moderation .moderation-state { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem; margin: .4rem 0 1rem; color: var(--muted); font-size: .88rem; }
.admin-moderation h3 { margin: 1.2rem 0 .6rem; font-size: 1rem; }
.moderation-form { display: flex; align-items: end; gap: .65rem; margin-top: .8rem; }
.moderation-form label { display: grid; gap: .3rem; flex: 1; color: var(--faint); font-size: .72rem; }
.moderation-form .member-picker { flex: 1; }
.member-options { display: grid; gap: .35rem; margin-top: .4rem; }
.member-option { display: flex; align-items: center; gap: .65rem; width: 100%; padding: .5rem .65rem; text-align: left; }
.member-option-poster { width: 2.2rem; height: 3.2rem; object-fit: cover; flex: none; }
.member-option span { display: grid; gap: .15rem; }
.member-option small { color: var(--faint); font-size: .68rem; }
.moderation-reports { display: grid; gap: .65rem; }
.moderation-report { padding: .7rem .9rem; display: grid; gap: .4rem; border: 1px solid var(--line); font-size: .84rem; }
.moderation-report p { margin: 0; }
.moderation-report small { color: var(--faint); font-size: .72rem; }
