:root {
  --bg: #141414;
  --bg-raised: #1f1f1f;
  --bg-card: #262626;
  --text: #f2f2f2;
  --text-dim: #b3b3b3;
  --accent: #e50914;
  --border: #3a3a3a;
  --focus: #ffffff;
}

* {
  box-sizing: border-box;
}

html, body {
  margin: 0;
  padding: 0;
  background: var(--bg);
  color: var(--text);
  font-family: "Segoe UI", Arial, sans-serif;
}

body {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}

/* #app spans the whole document again, not just one viewport. flex-basis
   auto plus flex-shrink 0 lets it size to its real content height, and
   flex-grow 1 still fills a short document up to the viewport. .topbar is
   sticky inside #app, so #app must never be shorter than the document or
   the topbar unsticks once the user scrolls past #app's own bottom edge. */
#app {
  display: flex;
  flex-direction: column;
  flex: 1 0 auto;
}

/* Boot and store status banner. Not sticky on purpose: the user has
   already read it by the time they scroll, and a failed action repeats
   the same warning. Keeping it in normal flow avoids fighting the sticky
   topbar for the top of the viewport. */

.banner {
  background: var(--bg-raised);
  color: var(--text);
  border-bottom: 1px solid var(--accent);
  padding: 10px 24px;
  font-size: 13px;
  line-height: 1.4;
  flex: 0 0 auto;
}

.banner.hidden {
  display: none;
}

/* Topbar */

.topbar {
  position: sticky;
  top: 0;
  z-index: 10;
  background: linear-gradient(to bottom, rgba(20, 20, 20, 0.98), rgba(20, 20, 20, 0.9));
  padding: 14px 24px 8px 24px;
  border-bottom: 1px solid var(--border);
}

.topbar-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 10px;
}

.brand {
  margin: 0;
  font-size: 22px;
  font-weight: 700;
  color: var(--accent);
  letter-spacing: 0.5px;
}

#search-input {
  flex: 0 1 320px;
  padding: 8px 12px;
  border-radius: 4px;
  border: 1px solid var(--border);
  background: var(--bg-raised);
  color: var(--text);
  font-size: 14px;
}

#search-input:focus {
  outline: 2px solid var(--focus);
  outline-offset: 1px;
}

/* Scrolls horizontally rather than wrapping, the same gesture the genre
   rows already use. A fifth tab, or a phone width narrower than today's,
   grows this row instead of reflowing the whole header.

   overflow-x: auto forces overflow-y to compute as auto too, that is the
   spec, not a bug (visible on one axis becomes auto when the other axis
   is not visible). So .tabs is a scroll container on BOTH axes, and it
   clips anything painted outside its padding box, including the 2px
   focus-visible outline at 2px offset that every other control in the
   shared rule below gets. 4px padding gives that ring room on all four
   sides. The matching negative margin pulls the row back to the same
   horizontal position and keeps the previous 10px gap below it
   (4px padding + 6px margin), so nothing else in the header shifts. */
.tabs {
  display: flex;
  gap: 6px;
  padding: 4px;
  margin: 0 -4px 6px -4px;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}

.tab-btn {
  flex: 0 0 auto;
  background: none;
  border: none;
  color: var(--text-dim);
  font-size: 15px;
  padding: 8px 14px;
  cursor: pointer;
  border-bottom: 2px solid transparent;
  white-space: nowrap;
}

.tab-btn:hover {
  color: var(--text);
}

.tab-btn.active {
  color: var(--text);
  border-bottom-color: var(--accent);
  font-weight: 600;
}

.tab-btn:focus-visible,
.chip:focus-visible,
.card:focus-visible,
.row-track:focus-visible,
.plan-item:focus-visible,
.action-btn:focus-visible,
.detail-close:focus-visible,
.sort-controls select:focus-visible,
.tag-chip-remove:focus-visible,
#detail-rating-input:focus-visible,
#detail-review-input:focus-visible,
#detail-tag-input:focus-visible,
#diary-date-input:focus-visible,
#diary-note-input:focus-visible,
.diary-edit-date:focus-visible,
.diary-edit-note:focus-visible,
#episode-add-season:focus-visible,
#episode-add-number:focus-visible,
#episode-add-name:focus-visible,
#episode-add-airdate:focus-visible,
#episode-add-runtime:focus-visible,
.episode-edit-name:focus-visible,
.episode-edit-airdate:focus-visible,
.episode-edit-runtime:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 2px;
}

/* Controls row: genre chips, tag chips, sort controls, and the export and
   import button. Wraps freely so it never fights the topbar for width. */
.controls-row {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 10px 16px;
}

/* Phase 4 widened the genre chip row from 5 to 19. Wrapping that many into
   the controls row reads as a mess, so this reuses the same fix .tabs
   already uses above: scroll horizontally on its own full width row
   rather than wrap. flex-basis 100% is what claims that full row inside
   .controls-row, which is itself flex-wrap, so sort controls and the
   export button still fall to their own line beneath it. The padding and
   negative margin trick, and the min-width: 0, are the same reasons
   given on .tabs: an overflow-x scroll container needs room for the
   focus ring, and a flex item needs min-width: 0 to shrink to its
   container instead of growing to its content. */
.chips {
  display: flex;
  gap: 8px;
  padding: 4px;
  margin: -4px;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  flex: 1 1 100%;
  min-width: 0;
}

.chip {
  flex: 0 0 auto;
  background: var(--bg-raised);
  border: 1px solid var(--border);
  color: var(--text-dim);
  border-radius: 999px;
  padding: 5px 14px;
  font-size: 13px;
  white-space: nowrap;
  cursor: pointer;
}

.chip:hover {
  color: var(--text);
}

.chip.active {
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
}

/* Content */

#content {
  flex: 1;
  padding: 20px 24px 40px 24px;
}

.empty-state {
  color: var(--text-dim);
  font-size: 15px;
  padding: 40px 4px;
}

/* Rows */

.row {
  margin-bottom: 28px;
}

.row-label {
  font-size: 17px;
  margin: 0 0 10px 2px;
  color: var(--text);
}

.row-track {
  display: flex;
  gap: 12px;
  overflow-x: auto;
  padding: 4px 4px 10px 4px;
  scroll-behavior: smooth;
}

.row-track::-webkit-scrollbar {
  height: 8px;
}

.row-track::-webkit-scrollbar-thumb {
  background: var(--border);
  border-radius: 4px;
}

.card {
  flex: 0 0 auto;
  width: 160px;
  cursor: pointer;
  transition: transform 0.15s ease;
}

.card:hover,
.card:focus-visible {
  transform: scale(1.06);
}

.poster {
  position: relative;
  width: 160px;
  height: 220px;
  border-radius: 6px;
  display: flex;
  align-items: flex-end;
  padding: 10px;
  overflow: hidden;
}

.poster-title {
  color: #fff;
  font-size: 14px;
  font-weight: 600;
  line-height: 1.25;
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.6);
}

.card-meta {
  font-size: 12px;
  color: var(--text-dim);
  margin-top: 6px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Watching plan list */

.plan-list {
  display: flex;
  flex-direction: column;
  gap: 10px;
  max-width: 640px;
}

.plan-item {
  display: flex;
  align-items: center;
  gap: 14px;
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 10px 14px;
  cursor: pointer;
}

.plan-item:hover {
  border-color: var(--text-dim);
}

.plan-badge {
  flex: 0 0 auto;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  background: var(--accent);
  color: #fff;
  font-size: 13px;
  font-weight: 700;
  display: flex;
  align-items: center;
  justify-content: center;
}

.plan-poster {
  position: relative;
  flex: 0 0 auto;
  width: 48px;
  height: 66px;
  border-radius: 4px;
}

.plan-info {
  min-width: 0;
}

.plan-title {
  font-size: 14px;
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.plan-meta {
  font-size: 12px;
  color: var(--text-dim);
  margin-top: 3px;
}

/* Detail overlay */

.overlay {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.7);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 100;
}

.overlay.hidden {
  display: none;
}

.detail-panel {
  position: relative;
  background: var(--bg-raised);
  border: 1px solid var(--border);
  border-radius: 8px;
  width: 420px;
  max-width: 90vw;
  max-height: 85vh;
  overflow-y: auto;
  padding: 18px;
}

.detail-close {
  position: absolute;
  /* Above the poster. Phase 4 made .detail-poster position: relative so a
     real poster image can fill it, which also made it paint over this
     absolutely positioned button and swallow the click. smoke_web caught
     it. Without this the panel cannot be closed by clicking Close. */
  z-index: 2;
  top: 10px;
  right: 10px;
  background: var(--bg-card);
  border: 1px solid var(--border);
  color: var(--text);
  border-radius: 4px;
  padding: 5px 10px;
  font-size: 12px;
  cursor: pointer;
}

.detail-poster {
  position: relative;
  width: 100%;
  height: 160px;
  border-radius: 6px;
  display: flex;
  align-items: flex-end;
  padding: 12px;
  margin-bottom: 12px;
}

.detail-poster span {
  color: #fff;
  font-size: 18px;
  font-weight: 700;
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.6);
}

.detail-title {
  margin: 0 0 8px 0;
  font-size: 20px;
}

.detail-line {
  color: var(--text-dim);
  font-size: 13px;
  margin-bottom: 6px;
}

.detail-synopsis {
  font-size: 14px;
  line-height: 1.4;
  margin: 12px 0;
}

.detail-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
  margin-top: 12px;
}

.action-btn {
  background: var(--bg-card);
  border: 1px solid var(--border);
  color: var(--text);
  border-radius: 4px;
  padding: 8px 12px;
  font-size: 13px;
  cursor: pointer;
}

.action-btn:hover {
  border-color: var(--text-dim);
}

.status-label {
  font-size: 13px;
  color: var(--text-dim);
  display: flex;
  align-items: center;
  gap: 6px;
}

.status-label select {
  background: var(--bg-card);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 6px 8px;
  font-size: 13px;
}

.detail-error {
  color: var(--accent);
  font-size: 13px;
  margin-top: 10px;
  min-height: 1em;
}

/* Sort controls. Frontend only, see DATA_CONTRACT.md, "Sorting is frontend
   only". Disabled state is set from JS on the Watching Plan and Recommended
   tabs, using the native disabled attribute so it stays keyboard honest. */

.sort-controls {
  display: flex;
  align-items: center;
  gap: 8px;
}

.sort-label {
  font-size: 13px;
  color: var(--text-dim);
  display: flex;
  align-items: center;
  gap: 6px;
}

.sort-label select {
  background: var(--bg-card);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 6px 8px;
  font-size: 13px;
}

.sort-controls button:disabled,
.sort-controls select:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}

/* Detail panel: personal rating, review, and tags */

.detail-section {
  margin-top: 16px;
  padding-top: 12px;
  border-top: 1px solid var(--border);
}

.detail-section-title {
  font-size: 13px;
  font-weight: 600;
  color: var(--text-dim);
  margin-bottom: 8px;
}

.rating-row {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}

#detail-rating-input {
  width: 70px;
  padding: 6px 8px;
  border-radius: 4px;
  border: 1px solid var(--border);
  background: var(--bg-card);
  color: var(--text);
  font-size: 13px;
}

#detail-review-input {
  width: 100%;
  resize: vertical;
  padding: 8px;
  border-radius: 4px;
  border: 1px solid var(--border);
  background: var(--bg-card);
  color: var(--text);
  font-size: 13px;
  font-family: inherit;
}

.char-count {
  font-size: 12px;
  color: var(--text-dim);
  margin: 4px 0 8px 0;
}

.tag-list {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-bottom: 10px;
}

.tag-empty {
  font-size: 13px;
  color: var(--text-dim);
}

.tag-chip {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 3px 6px 3px 12px;
  font-size: 12px;
}

.tag-chip-remove {
  background: none;
  border: none;
  color: var(--text-dim);
  cursor: pointer;
  font-size: 12px;
  padding: 2px 7px;
  border-radius: 999px;
}

.tag-chip-remove:hover {
  color: var(--text);
  background: var(--border);
}

.tag-add-row {
  display: flex;
  gap: 8px;
}

#detail-tag-input {
  flex: 1;
  padding: 6px 8px;
  border-radius: 4px;
  border: 1px solid var(--border);
  background: var(--bg-card);
  color: var(--text);
  font-size: 13px;
}

/* Export and import overlay. Reuses .overlay and .detail-panel, the shell
   already used by the title detail panel. */

.io-hint {
  font-size: 13px;
  color: var(--text-dim);
  line-height: 1.4;
  margin: 0 0 8px 0;
}

.io-result {
  font-size: 13px;
  color: var(--text-dim);
  margin-top: 8px;
  min-height: 1em;
}

.io-export-row {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
  padding: 8px 0;
  border-bottom: 1px solid var(--border);
}

.io-export-info {
  flex: 1 1 100%;
  font-size: 13px;
  color: var(--text);
}

/* Import from TMDb overlay. Reuses .overlay and .detail-panel, the same
   shell as export and import and the title detail panel. */

.action-btn.hidden {
  display: none;
}

.source-search-row {
  display: flex;
  gap: 8px;
  margin: 10px 0;
}

.source-search-row input {
  flex: 1;
  min-width: 0;
  padding: 8px 12px;
  border-radius: 4px;
  border: 1px solid var(--border);
  background: var(--bg-raised);
  color: var(--text);
  font-size: 14px;
}

.source-results {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-top: 10px;
}

.source-result-row {
  display: flex;
  align-items: center;
  gap: 12px;
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 8px 10px;
}

.source-result-row.in-library {
  opacity: 0.5;
}

.source-result-poster {
  flex: 0 0 auto;
  width: 40px;
  height: 58px;
  border-radius: 4px;
  object-fit: cover;
  background: var(--bg-raised);
}

.source-result-info {
  flex: 1;
  min-width: 0;
}

.source-result-title {
  font-size: 13px;
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.source-result-meta {
  font-size: 12px;
  color: var(--text-dim);
  margin-top: 2px;
}


/* Diary section. Lives inside the detail panel, under detail-section, same
   shell already used by rating, review, and tags above it. */

.diary-summary {
  font-size: 13px;
  color: var(--text-dim);
  margin-bottom: 10px;
}

.diary-add-row {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 10px;
}

#diary-date-input,
#diary-note-input,
.diary-edit-date,
.diary-edit-note {
  padding: 6px 8px;
  border-radius: 4px;
  border: 1px solid var(--border);
  background: var(--bg-card);
  color: var(--text);
  font-size: 13px;
  font-family: inherit;
}

/* Without color-scheme the native date picker glyph renders dark on this
   dark background and is effectively invisible. */
#diary-date-input,
.diary-edit-date {
  color-scheme: dark;
  flex: 0 0 auto;
}

#diary-note-input,
.diary-edit-note {
  flex: 1 1 160px;
  min-width: 0;
}

.diary-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-top: 4px;
}

.diary-empty {
  font-size: 13px;
  color: var(--text-dim);
}

.diary-row {
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 10px 12px;
}

/* The editing row swaps the two static lines for two inputs, laid out
   inline. Actions still get their own line, forced with a full width
   basis, so Save and Cancel never crowd the inputs on a narrow panel. */
.diary-row-editing {
  border-color: var(--text-dim);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
}

.diary-row-editing .diary-row-actions {
  flex: 1 0 100%;
  margin-top: 0;
}

.diary-row-main {
  display: flex;
  align-items: center;
  gap: 8px;
}

.diary-date {
  font-size: 13px;
  font-weight: 600;
  color: var(--text);
}

.diary-rewatch-badge {
  background: var(--accent);
  color: #fff;
  font-size: 11px;
  font-weight: 700;
  border-radius: 999px;
  padding: 2px 8px;
  text-transform: uppercase;
  letter-spacing: 0.3px;
}

.diary-note {
  font-size: 13px;
  color: var(--text-dim);
  margin-top: 6px;
}

.diary-row-actions {
  display: flex;
  gap: 8px;
  margin-top: 8px;
}

.diary-delete-btn:hover {
  border-color: var(--accent);
  color: var(--accent);
}

/* Episode section. Series only. Lives inside the detail panel, under
   detail-section, same shell already used by the diary section above it. */

.episodes-summary {
  font-size: 13px;
  color: var(--text-dim);
}

.episodes-next {
  font-size: 13px;
  color: var(--text);
  font-weight: 600;
  margin-top: 4px;
  margin-bottom: 10px;
}

.episodes-add-row {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 10px;
}

.episodes-add-row input,
.episode-edit-name,
.episode-edit-airdate,
.episode-edit-runtime {
  padding: 6px 8px;
  border-radius: 4px;
  border: 1px solid var(--border);
  background: var(--bg-card);
  color: var(--text);
  font-size: 13px;
  font-family: inherit;
  min-width: 0;
}

/* Without color-scheme the native date picker glyph renders dark on this
   dark background and is effectively invisible, matching the diary fix. */
#episode-add-airdate,
.episode-edit-airdate {
  color-scheme: dark;
}

#episode-add-season,
#episode-add-number {
  flex: 0 0 72px;
  width: 72px;
}

#episode-add-runtime,
.episode-edit-runtime {
  flex: 0 0 90px;
  width: 90px;
}

#episode-add-name,
.episode-edit-name {
  flex: 1 1 140px;
}

.episodes-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
  max-height: 320px;
  overflow-y: auto;
}

.episodes-empty {
  font-size: 13px;
  color: var(--text-dim);
}

.episode-row {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 10px;
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 8px 12px;
}

.episode-row-editing {
  border-color: var(--text-dim);
}

.episode-row-main {
  display: flex;
  align-items: center;
  gap: 8px;
  flex: 0 0 auto;
  cursor: pointer;
}

.episode-watched-checkbox {
  flex: 0 0 auto;
  width: 16px;
  height: 16px;
  accent-color: var(--accent);
}

.episode-label {
  flex: 0 0 auto;
  font-size: 13px;
  font-weight: 600;
  color: var(--text-dim);
}

.episode-row-body {
  flex: 1 1 140px;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.episode-name {
  font-size: 13px;
  color: var(--text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.episode-meta {
  font-size: 12px;
  color: var(--text-dim);
}

.episode-row-actions {
  display: flex;
  gap: 8px;
  flex: 0 0 auto;
  margin-left: auto;
}

.episode-row-editing .episode-row-actions {
  flex: 1 0 100%;
  margin-left: 0;
}

.episode-delete-btn:hover {
  border-color: var(--accent);
  color: var(--accent);
}

/* Statistics overlay. Reuses .overlay and .detail-panel, the same shell
   as the detail and export and import panels. Wider than .detail-panel's
   420px default, since a chart needs more horizontal room than a form. */

.stats-panel {
  width: 520px;
}

.stat-tiles {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 10px;
  margin-bottom: 4px;
}

.stat-tile {
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 12px 14px;
}

/* Semibold, proportional figures, no tabular-nums on a large number, per
   the chart style table in DATA_CONTRACT.md. Axis ticks inside the charts
   use tabular-nums instead, see .chart-axis-label and .chart-value-label. */
.stat-tile-value {
  font-size: 22px;
  font-weight: 600;
  color: var(--text);
}

.stat-tile-label {
  font-size: 12px;
  color: var(--text-dim);
  margin-top: 4px;
}

.stats-chart-section {
  margin-top: 18px;
  padding-top: 14px;
  border-top: 1px solid var(--border);
}

.stats-chart-title {
  font-size: 14px;
  font-weight: 600;
  color: var(--text);
  margin: 0 0 8px 0;
}

.stats-chart-note {
  font-size: 12px;
  color: var(--text-dim);
  margin-top: 4px;
}

.stats-loading {
  color: var(--text-dim);
  font-size: 13px;
  padding: 20px 0;
}

.chart-empty {
  color: var(--text-dim);
  font-size: 13px;
  padding: 16px 0;
}

/* The viewBox is 440 units wide and the panel gives 482px of content, so
   width 100% scaled every unit by 1.095. A 24 unit bar painted at 26.3px,
   the 1px axis at 1.1px, and the 4px corner at 4.4px. The contract calls
   those numbers settled, so cap the chart at its own width and let one
   unit be one pixel. Centred, so the leftover is even air on both sides. */
.chart {
  width: 100%;
  max-width: 440px;
  height: auto;
  display: block;
}

/* ONE hue for every data mark, and it is --accent, per DATA_CONTRACT.md,
   "Chart style, from /dataviz and validated". All three charts are single
   series, so no categorical palette and no legend. */
.chart-bar {
  fill: var(--accent);
}

/* Transparent, not none: a fill of none does not receive pointer events,
   so a zero value bar (no visible path) would have nothing to hover.
   This hit rect is what gives every bar a tooltip, non-zero or not. */
.chart-hit {
  fill: transparent;
}

.chart-axis {
  stroke: var(--border);
  stroke-width: 1;
  shape-rendering: crispEdges;
}

/* Text never wears the data colour. Axis ticks get tabular-nums, since
   these are the digits meant to align vertically down a column. */
.chart-axis-label {
  fill: var(--text-dim);
  font-size: 11px;
  font-variant-numeric: tabular-nums;
}

.chart-value-label {
  fill: var(--text);
  font-size: 11px;
  font-variant-numeric: tabular-nums;
}

/* Web build version line, foot of the Statistics overlay. Filled by
   app.js in wave P3, empty here. The :empty rule matters: between waves,
   and on desktop where nothing ever fills it, it must take no space and
   show no gap. */
.stats-version {
  margin: 14px 0 0 0;
  font-size: 11px;
  color: var(--text-dim);
}

.stats-version:empty {
  display: none;
}

/* TMDb attribution, required whenever the app can show TMDb sourced
   titles. Shown in both builds, so no :empty rule here, unlike
   .stats-version above. Sits under the version line, same small dim
   treatment. */
.tmdb-attribution {
  margin: 10px 0 0 0;
}

.tmdb-attribution-logo {
  display: block;
  width: 91px;
  height: auto;
  margin: 0 0 6px 0;
}

.tmdb-attribution-text {
  margin: 0;
  font-size: 11px;
  color: var(--text-dim);
}

/* One breakpoint, phone width. Below it, overlay panels become full
   screen sheets: no centered card, no rounded corners, no 90vw gap.
   Genre rows and the tab row keep their horizontal scroll unchanged,
   that gesture already works on touch and needs nothing here. */
@media (max-width: 640px) {
  .overlay {
    align-items: stretch;
    justify-content: stretch;
  }

  .detail-panel {
    width: min(420px, 100%);
    max-width: 100%;
    max-height: 100%;
    height: 100%;
    border-radius: 0;
    border-left: none;
    border-right: none;
  }

  /* Comes after .detail-panel on purpose. Both classes sit on the same
     element for the Statistics panel, and source order decides which
     same specificity width wins. */
  .stats-panel {
    width: min(520px, 100%);
  }
}

/* A real poster, laid over the gradient placeholder rather than replacing
   it. The gradient stays visible while this loads and if it never arrives,
   so a blocked or offline image degrades to the card that shipped before
   Phase 4 instead of a blank rectangle. */
.poster-img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: inherit;
}
