:root {
  --bg: #f4f6fb;
  --card: #ffffff;
  --text: #0f172a;
  --muted: #5b6b82; /* 5:1 on --bg, the darker of the two it is drawn on; text needs 4.5:1 */
  --border: #e2e8f0;
  --primary: #2563eb;
  --primary-text: #ffffff;
  --accent: #16a34a;
  --danger: #c81e1e; /* 5.3:1 on --bg, where the network check draws its ✗ */
  /* The network check's ✓ and !, text on --bg as well: --accent and an amber are 3:1 there. */
  --ok: #15803d;
  --warn: #b45309;
  /* What white text sits on: a primary button, an error toast. The dark scheme's --primary and
     --danger are lighter, to stand out on a dark page, and white on them is 3.7:1 and 2.8:1, under
     the 4.5:1 text needs; so these are set apart, and the button's blue is the same in both. */
  --primary-fill: #2563eb;
  --danger-fill: #dc2626;
  --track: #e2e8f0;
  /* The rows of the list: hovered, open, selected. Plain colours, so the tests can read their contrast. */
  --row-hover: #f1f4f9;
  --row-open: #f1f5fe;
  --row-selected: #e5edfe;
  --shadow: 0 1px 2px rgba(15, 23, 42, 0.06), 0 4px 16px rgba(15, 23, 42, 0.04);
  --radius: 14px;
  color-scheme: light dark;
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg: #0b1220;
    --card: #131c2e;
    --text: #e5e9f2;
    --muted: #94a3b8;
    --border: #243049;
    --primary: #3b82f6;
    --accent: #22c55e;
    --danger: #f87171;
    --ok: #22c55e;
    --warn: #d97706;
    --danger-fill: #b91c1c;
    --track: #243049;
    --row-hover: #18233a;
    --row-open: #172544;
    --row-selected: #1d3157;
    --shadow: none;
  }
}

* { box-sizing: border-box; }

[hidden] { display: none !important; }

html, body { margin: 0; padding: 0; }

body {
  font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  background: var(--bg);
  color: var(--text);
  line-height: 1.45;
  -webkit-text-size-adjust: 100%;
  padding-bottom: env(safe-area-inset-bottom);
}

.topbar {
  position: sticky;
  top: 0;
  z-index: 5;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: calc(10px + env(safe-area-inset-top)) 16px 10px;
  background: color-mix(in srgb, var(--bg) 88%, transparent);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--border);
}

/* During a transfer the pill's speeds, and Install where the browser offers it, leave a phone's top bar
   short of room. The title gives way first, down to the icon, then the pill, to an ellipsis; Install
   and Settings never do, and nothing is drawn over anything else. */
.brand { display: flex; align-items: center; gap: 10px; flex: 1 1 0; min-width: 28px; }
.brand img { flex: none; }
.brand h1 { font-size: 1.1rem; margin: 0; font-weight: 700; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.topbar-right { display: flex; align-items: center; gap: 8px; min-width: 0; }
.topbar-right > * { flex: none; }
.topbar-right > .pill { flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; }

.pill {
  font-size: 0.75rem;
  font-variant-numeric: tabular-nums;
  color: var(--muted);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 3px 10px;
  white-space: nowrap;
}

.container {
  max-width: 760px;
  margin: 0 auto;
  padding: 16px 16px 48px;
  display: grid;
  gap: 16px;
}

/* A grid item is as wide as its widest unbreakable content by default, and a text input's is its
   intrinsic width: on a 320px screen that alone made the page scroll sideways. */
.container > *, .list-pane > *, .detail-pane > * { min-width: 0; }

/* One column on a phone, as it always was: the two panes only group things on a computer. */
.list-pane, .detail-pane { display: contents; }

.card {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 16px;
}

.card h2 { margin: 0 0 12px; font-size: 1rem; }


.add-row { display: flex; gap: 8px; margin-bottom: 10px; }
.add-row input[type="text"], .add-row input[type="url"] {
  flex: 1;
  min-width: 0;
  font: inherit;
  padding: 12px 14px;
  border-radius: 10px;
  border: 1px solid var(--border);
  background: var(--bg);
  color: var(--text);
}
.add-row input[type="text"]:focus, .add-row input[type="url"]:focus { outline: 2px solid var(--primary); outline-offset: 1px; }

.btn {
  font: inherit;
  font-weight: 600;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 12px 16px;
  border-radius: 10px;
  border: 1px solid var(--border);
  background: var(--card);
  color: var(--text);
  cursor: pointer;
  touch-action: manipulation;
  min-height: 44px;
}
.btn:disabled { opacity: 0.45; cursor: not-allowed; }
.btn.primary { background: var(--primary-fill); border-color: var(--primary-fill); color: var(--primary-text); }
.btn.ghost { background: transparent; }
.btn.danger { border-color: var(--danger); color: var(--danger); background: transparent; }
.btn.small { padding: 6px 12px; min-height: 36px; font-size: 0.85rem; }
.file-btn { width: 100%; position: relative; overflow: hidden; }
.file-btn input { position: absolute; inset: 0; opacity: 0; cursor: pointer; }
/* The input is invisible, and so is the ring a keyboard's focus draws around it: its label shows it
   instead. Only for the keyboard (focus-visible), and on an engine without :has, for any focus. */
.file-btn:has(input:focus-visible) { outline: 2px solid var(--primary); outline-offset: 2px; }
@supports not selector(:has(*)) {
  .file-btn:focus-within { outline: 2px solid var(--primary); outline-offset: 2px; }
}
.file-btn:has(input:disabled) { opacity: 0.45; }
.file-btn input:disabled { cursor: not-allowed; }

.icon-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  border-radius: 10px;
  border: 1px solid transparent;
  background: transparent;
  color: var(--muted);
  cursor: pointer;
}
@media (hover: hover) {
  .icon-btn:hover { background: var(--bg); color: var(--text); }
  .btn:not(:disabled):hover { border-color: color-mix(in srgb, var(--text) 30%, var(--border)); }
  .btn.primary:not(:disabled):hover { filter: brightness(1.08); }
  .tab:not(.active):hover { color: var(--text); }
}
/* The ring the keyboard draws, on everything it reaches; a click draws none. */
:focus-visible { outline: 2px solid var(--primary); outline-offset: 2px; }

.hint { color: var(--muted); font-size: 0.85rem; margin: 6px 0 0; }
.hint code { font-family: ui-monospace, monospace; }

.empty { text-align: center; color: var(--muted); padding: 24px 8px; }

.torrents { display: grid; gap: 16px; }

.torrent-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 8px; }
.torrent-title { min-width: 0; }
.torrent .name { margin: 0; font-size: 1rem; overflow-wrap: anywhere; }
.torrent .meta { color: var(--muted); font-size: 0.8rem; margin-top: 2px; }

.progress {
  height: 8px;
  border-radius: 999px;
  background: var(--track);
  overflow: hidden;
  margin: 12px 0 6px;
}
.progress .bar { height: 100%; width: 0%; background: var(--primary); transition: width 0.3s ease; }
.torrent.done .progress .bar { background: var(--accent); }

.stats {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 14px;
  font-size: 0.8rem;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}
.stats .pct { color: var(--text); font-weight: 600; }

/* Five buttons do not fit on one line of a narrow card at any width, so the row always wraps. */
.actions { display: flex; flex-wrap: wrap; gap: 8px; margin: 12px 0 8px; }
.actions .zip-btn { flex: 1; }

.files { list-style: none; margin: 0; padding: 0; display: grid; gap: 4px; }
.file {
  display: grid;
  grid-template-columns: 1fr auto auto;
  grid-template-areas:
    "check size save"
    "prog  prog save";
  gap: 4px 10px;
  align-items: center;
  padding: 8px 4px;
  border-top: 1px solid var(--border);
}
.file-check { grid-area: check; display: flex; align-items: center; gap: 10px; min-width: 0; cursor: pointer; }
.file-check input { width: 20px; height: 20px; margin: 0; accent-color: var(--primary); flex: none; }
.file-name { font-size: 0.9rem; overflow-wrap: anywhere; }
.file-size { grid-area: size; font-size: 0.8rem; color: var(--muted); white-space: nowrap; font-variant-numeric: tabular-nums; }
.file-progress { grid-area: prog; height: 4px; border-radius: 999px; background: var(--track); overflow: hidden; }
.file-progress .bar { height: 100%; width: 0%; background: var(--primary); transition: width 0.3s ease; }
.file.done .file-progress .bar { background: var(--accent); }
.file.deselected { opacity: 0.55; }
.save-btn { grid-area: save; }

.dialog {
  border: none;
  border-radius: var(--radius);
  padding: 0;
  background: var(--card);
  color: var(--text);
  width: min(92vw, 520px);
  max-height: calc(100dvh - 32px);
  overflow-y: auto;
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.35);
}
.dialog::backdrop { background: rgba(0, 0, 0, 0.5); }
.dialog-body { padding: 20px; display: grid; gap: 14px; }
.dialog-body h2 { margin: 0; font-size: 1.1rem; }
.field { display: grid; gap: 6px; }
.field > span:not(.hint) { font-weight: 600; font-size: 0.9rem; }
.field textarea {
  font: 0.85rem ui-monospace, monospace;
  padding: 10px;
  border-radius: 10px;
  border: 1px solid var(--border);
  background: var(--bg);
  color: var(--text);
  resize: vertical;
}
.dialog-actions { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 8px; }

.toasts {
  position: fixed;
  left: 50%;
  bottom: calc(16px + env(safe-area-inset-bottom));
  transform: translateX(-50%);
  display: grid;
  gap: 8px;
  width: min(92vw, 480px);
  z-index: 10;
  pointer-events: none;
}
.toast {
  background: var(--text);
  color: var(--bg);
  padding: 12px 16px;
  border-radius: 12px;
  font-size: 0.9rem;
  box-shadow: 0 8px 30px rgba(0, 0, 0, 0.25);
  animation: toast-in 0.2s ease;
}
.toast.error { background: var(--danger-fill); color: #fff; }
@keyframes toast-in { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }

.notice.error { color: var(--danger); }
.tab-panel > .notice { margin: 0 0 12px; font-size: 0.9rem; }

@media (max-width: 480px) {
  .actions .zip-btn { flex-basis: 100%; }
  .actions .ghost { flex: 1; }
}

/* ---- tabs ---- */
.tabs { display: flex; gap: 4px; background: var(--bg); border-radius: 10px; padding: 4px; margin-bottom: 14px; }
.tab {
  flex: 1; font: inherit; font-weight: 600; padding: 9px 12px; border-radius: 8px; border: none;
  background: transparent; color: var(--muted); cursor: pointer; min-height: 40px; min-width: 0;
}
/* Three tabs on a 320px screen (an iPhone SE, or any iPhone with Display Zoom) are wider than the
   card at the usual padding, and the whole page would scroll sideways. */
@media (max-width: 360px) {
  .tab { padding: 9px 4px; font-size: 0.9rem; }
}
/* Four of them on a phone: each as wide as its label, so "Download" is not cut at a quarter of the
   card while "Edit" has room to spare; "Seed & share" takes two lines when it must. */
@media (max-width: 480px) {
  .tabs .tab { flex: 1 1 auto; min-width: min-content; padding: 9px 6px; }
}
/* At 320px, a little smaller still: "Seed & share" on two lines, not one word a line. */
@media (max-width: 360px) {
  .tabs .tab { padding: 9px 3px; font-size: 0.85rem; }
}
.tab.active { background: var(--card); color: var(--text); box-shadow: var(--shadow); }

/* ---- torrent head actions ---- */
.head-actions { display: flex; gap: 2px; flex: none; }
.torrent .ic-play { display: none; }
.torrent.paused .ic-play { display: block; }
.torrent.paused .ic-pause { display: none; }
.torrent.paused .progress .bar { background: var(--muted); }
.torrent.seeding .progress .bar { background: var(--accent); }

/* ---- details ---- */
.details { border-top: 1px solid var(--border); margin-top: 10px; padding-top: 12px; display: grid; gap: 12px; }
.kv { display: grid; grid-template-columns: auto 1fr; gap: 6px 14px; margin: 0; font-size: 0.85rem; }
.kv dt { color: var(--muted); }
.kv dd { margin: 0; overflow-wrap: anywhere; }
.mono { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 0.8rem; }
.details-actions { display: flex; flex-wrap: wrap; gap: 8px; }
.log { list-style: none; margin: 0; padding: 8px 10px; background: var(--bg); border-radius: 8px; font-size: 0.75rem; color: var(--muted); display: grid; gap: 2px; max-height: 140px; overflow: auto; }
.log li { overflow-wrap: anywhere; }

.toggle { display: flex; align-items: center; gap: 10px; font-size: 0.9rem; cursor: pointer; }
.toggle input { width: 20px; height: 20px; margin: 0; accent-color: var(--primary); flex: none; }
.field .hint { margin: 0; }

@media (max-width: 480px) {
  .actions .ghost { flex: 1; }
}

/* seeding cards: the files are already on this device */
.torrent.seeding .zip-btn,
.torrent.seeding .folder-btn,
.torrent.seeding .select-all-btn,
.torrent.seeding .select-none-btn,
.torrent.seeding .file-progress,
.torrent.seeding .save-btn { display: none; }
.torrent.seeding .file { grid-template-areas: "check size"; grid-template-columns: 1fr auto; }
.torrent.seeding .file-check input { display: none; }
/* Sharing is not only for what you seed: a torrent you are downloading is one
   more peer for whoever you send it to. */
.share-link-btn { flex: 1; }

/* ---- settings extras ---- */
.field input[type="url"], .field input[type="text"], .field input[type="number"], .field select {
  font: inherit; padding: 10px 12px; border-radius: 10px; border: 1px solid var(--border);
  background: var(--bg); color: var(--text); min-width: 0; width: 100%;
}
.two-col { grid-template-columns: 1fr 1fr; }
@media (max-width: 420px) { .two-col { grid-template-columns: 1fr; } }
#install-btn { min-height: 34px; padding: 6px 12px; }

/* ---- no peers hint ---- */
.nopeers { margin-top: 10px; padding: 10px 12px; border-radius: 10px; background: var(--bg); border: 1px dashed var(--border); display: grid; gap: 8px; }
.nopeers .hint { margin: 0; }

/* ---- simple / expert ---- */
.mode-switch { display: flex; gap: 6px; padding: 4px; background: var(--bg); border-radius: 10px; }
.mode-switch .tab { flex: 1; }

/* ---- sharing: the link itself, not a message about it ---- */
.share-panel { margin-top: 10px; padding: 10px 12px; border-radius: 10px; background: var(--bg); border: 1px solid var(--border); display: grid; gap: 10px; }
.share-row { display: grid; gap: 4px; font-size: 0.85rem; color: var(--muted); }
.share-panel .hint { margin: 0; }
.share-field { display: flex; gap: 6px; align-items: center; }
/* width: 0, and flex: 1 fills the row: at its own width, twenty characters (more at the 16px an
   iPhone gets), the field set how narrow its card could be, and at 320px that was wider than the screen. */
.share-field input {
  flex: 1; min-width: 0; width: 0; padding: 8px 10px; border: 1px solid var(--border); border-radius: 8px;
  background: var(--card); color: var(--text); font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 0.8rem;
}

/* ---- cloud library ---- */
.cloud-library { display: grid; gap: 10px; }
.cloud-library h2 { margin: 0; font-size: 1rem; }
.cloud-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 10px; }
.cloud-item { display: grid; gap: 8px; padding: 10px 12px; border: 1px solid var(--border); border-radius: 10px; background: var(--bg); }
.cloud-item.ready { border-color: var(--accent); }
.cloud-item-head { display: flex; gap: 10px; align-items: flex-start; justify-content: space-between; }
.cloud-item-name { font-weight: 600; overflow-wrap: anywhere; }
.cloud-item-meta { color: var(--muted); font-size: 0.85rem; }
.cloud-item-files { display: grid; gap: 8px; }
.cloud-file { display: grid; gap: 6px; padding: 8px 0; border-top: 1px solid var(--border); }
.cloud-file-name { overflow-wrap: anywhere; }
.cloud-file-size { color: var(--muted); font-size: 0.85rem; }
.cloud-file-actions { display: flex; flex-wrap: wrap; gap: 6px; }
.cloud-file-actions a { text-decoration: none; }
.cloud-player video, .cloud-player audio { width: 100%; border-radius: 8px; background: #000; }

/* ---- cloud fetch ---- */
.cloud { margin-top: 10px; padding: 10px 12px; border-radius: 10px; background: var(--bg); border: 1px solid var(--border); display: grid; gap: 8px; }
.cloud .hint { margin: 0; }
.cloud-files { list-style: none; margin: 0; padding: 0; display: grid; gap: 6px; }
.cloud-files a { display: block; text-align: left; overflow-wrap: anywhere; text-decoration: none; }

/* ---- network check ---- */
.netcheck { list-style: none; margin: 0; padding: 8px 10px; background: var(--bg); border-radius: 8px; font-size: 0.8rem; display: grid; gap: 4px; }
.netcheck li { display: grid; grid-template-columns: 1.2em 1fr; gap: 6px; overflow-wrap: anywhere; }
.netcheck .ok { color: var(--ok); }
.netcheck .bad { color: var(--danger); }
.netcheck .warn { color: var(--warn); }

/* ---- iOS: second tap to share a prepared file ---- */
.save-ready {
  position: fixed; left: 50%; bottom: calc(16px + env(safe-area-inset-bottom)); transform: translateX(-50%);
  display: flex; gap: 8px; align-items: center; width: min(92vw, 480px); padding: 10px;
  background: var(--card); border: 1px solid var(--border); border-radius: 14px; box-shadow: 0 8px 30px rgba(0,0,0,0.25); z-index: 11;
}
/* The button names the file, and a release name (The.Show.S01E01.1080p.WEB.h264-GROUP.mkv) has
   nowhere to break: it wraps anywhere rather than push Cancel off the screen. */
.save-ready .primary { flex: 1; min-width: 0; overflow-wrap: anywhere; }
.save-ready .ghost { flex: none; }

/* ---- settings: a field that cannot be saved says so next to Save ---- */
#settings-error { margin: 0; color: var(--danger); }

/* ---- iOS zooms into a text field under 16px as it takes focus, and stays zoomed. Set here for
   iOS alone and always, not on :focus, so nothing jumps in size under the finger. ---- */
@supports (-webkit-touch-callout: none) {
  .field input, .field textarea, .field select, .share-field input { font-size: 16px; }
}

/* ---- The installed app on an iPhone gets its status bar drawn over the top of the page
   (black-translucent in index.html, which lets the top bar reach under it), and that status bar is
   always white. In light mode the strip under the clock and battery is dark, or they vanish into the
   top bar. Everywhere else the inset is 0, and so is the strip. ---- */
@supports (-webkit-touch-callout: none) {
  @media (prefers-color-scheme: light) {
    .topbar { padding-top: 10px; border-top: env(safe-area-inset-top) solid #0f172a; }
  }
}

/* ---- the .torrent editor ----
   Full screen on a phone, a column on a wider screen: a header that says which torrent (and whether it
   is still the same one), the form that scrolls, and the actions always in reach at the bottom. */
.dialog.editor {
  width: 100vw; max-width: 100vw; height: 100dvh; max-height: 100dvh; margin: 0;
  border-radius: 0; overflow: hidden; padding: 0;
}
.dialog.editor[open] { display: flex; flex-direction: column; }
@media (min-width: 760px) {
  .dialog.editor { width: min(720px, 92vw); height: calc(100dvh - 48px); margin: auto; border-radius: var(--radius); }
}
.editor-head {
  padding: calc(12px + env(safe-area-inset-top)) 16px 10px; border-bottom: 1px solid var(--border);
  display: grid; gap: 4px; min-width: 0;
}
.editor-title-row { display: flex; align-items: flex-start; justify-content: space-between; gap: 8px; }
.editor-title-row h2 { margin: 0; font-size: 1.05rem; overflow-wrap: anywhere; min-width: 0; }
.editor-hash { margin: 0; display: flex; flex-wrap: wrap; align-items: center; gap: 6px; color: var(--muted); min-width: 0; }
.editor-hash .mono { overflow-wrap: anywhere; min-width: 0; }
.new-pill { color: var(--warn); border-color: var(--warn); font-weight: 600; }
.editor-head .hint { margin: 0; }
.editor-body { flex: 1; overflow-y: auto; padding: 16px; display: grid; gap: 18px; align-content: start; overscroll-behavior: contain; }
.editor-body > * { min-width: 0; }
.editor-section { display: grid; gap: 8px; }
.editor-section h3 { margin: 0; font-size: 0.95rem; }
.editor-section .hint { margin: 0; }
.editor-body textarea { width: 100%; }
.field-label { font-weight: 600; font-size: 0.9rem; }
.notice.warn { color: var(--warn); margin: 0; font-size: 0.9rem; }
.editor-identity { border: 1px dashed var(--warn); border-radius: 10px; padding: 10px 12px; }
.editor-identity summary, .editor-inspector summary { font-weight: 600; cursor: pointer; }
.editor-identity summary .hint { font-weight: 400; margin-left: 4px; }
.editor-identity-body { display: grid; gap: 12px; margin-top: 12px; }
.editor-inspector { border: 1px solid var(--border); border-radius: 10px; padding: 10px 12px; }
.editor-inspector[open] { display: grid; gap: 10px; }
.editor-inspector .kv { margin-top: 10px; }
.editor-inspector .kv dt { cursor: help; text-decoration: underline dotted; text-underline-offset: 3px; }
.editor-files { list-style: none; margin: 0; padding: 0; display: grid; gap: 2px; font-size: 0.85rem; }
.editor-files li { display: flex; justify-content: space-between; gap: 10px; padding: 4px 0; border-top: 1px solid var(--border); overflow-wrap: anywhere; }
#ed-problems { margin: 0; display: grid; gap: 4px; font-size: 0.9rem; }
#ed-problems p { margin: 0; }
.editor-foot {
  display: flex; flex-wrap: wrap; gap: 8px; padding: 10px 16px calc(10px + env(safe-area-inset-bottom));
  border-top: 1px solid var(--border); background: var(--card);
}
.editor-foot > .primary { flex: 1 1 100%; }
.editor-foot > .btn:not(.primary) { flex: 1 1 auto; }
.menu { position: relative; }
.menu > summary { list-style: none; min-width: 48px; }
.menu > summary::-webkit-details-marker { display: none; }
.menu-list {
  position: absolute; right: 0; bottom: calc(100% + 6px); z-index: 2; display: grid; gap: 4px; min-width: 180px;
  padding: 6px; background: var(--card); border: 1px solid var(--border); border-radius: 10px; box-shadow: 0 8px 30px rgba(0, 0, 0, 0.25);
}
.menu-list .btn { justify-content: flex-start; }
@media (min-width: 520px) {
  .editor-foot > .primary { flex: 0 1 auto; margin-right: auto; }
}

/* ---- the editor's batch mode: what to do with each field, in every file ---- */
.field-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; min-width: 0; }
.field-head .toggle { flex: 1; min-width: 0; }
.ed-op, .field .ed-op { width: auto; font: inherit; font-size: 0.85rem; padding: 4px 8px; border-radius: 8px; border: 1px solid var(--border); background: var(--bg); color: var(--text); flex: none; }
.editor-chips { list-style: none; margin: 4px 0 0; padding: 0; display: flex; flex-wrap: wrap; gap: 6px; max-height: 96px; overflow-y: auto; }
.chip { display: inline-flex; align-items: baseline; gap: 6px; max-width: 100%; padding: 3px 10px; border: 1px solid var(--border); border-radius: 999px; font-size: 0.8rem; }
.chip-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
.chip-state { color: var(--muted); flex: none; }
.chip.new { border-color: var(--warn); }
.chip.new .chip-state { color: var(--warn); font-weight: 600; }
#ed-preset { min-height: 36px; padding: 6px 10px; }
.ed-rule { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 10px; }

/* ---- presets, in Settings ---- */
.preset-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 6px; }
.preset-item { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 8px 10px; border: 1px solid var(--border); border-radius: 10px; background: var(--bg); }
.preset-item > div:first-child { min-width: 0; }
.preset-name { font-weight: 600; overflow-wrap: anywhere; }
.preset-item .hint { margin: 0; }
.preset-form { border: 1px solid var(--border); border-radius: 10px; padding: 10px 12px; display: grid; gap: 10px; margin: 0; min-width: 0; }
.preset-form legend { font-weight: 600; font-size: 0.9rem; padding: 0 4px; }

/* ---- Seed & share: how the torrent is made, folded into one line ---- */
.torrent-options { margin-bottom: 10px; border: 1px solid var(--border); border-radius: 10px; padding: 8px 12px; }
.torrent-options > summary { cursor: pointer; display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 8px; min-height: 28px; }
.torrent-options-title { font-weight: 600; font-size: 0.9rem; }
.torrent-options > summary .hint { margin: 0; }
.torrent-options-body { display: grid; gap: 12px; margin-top: 12px; }
.torrent-options-body .hint { margin: 0; }
.torrent-options-body > .btn { justify-self: start; }

/* ---- the editor checking files ---- */
#editor-dialog[data-mode="check"] .editor-body > :not(#ed-check),
#editor-dialog[data-mode="check"] .editor-foot { display: none; }
.details-actions .file-btn { width: auto; }
.check-result { display: grid; gap: 8px; padding: 10px 12px; border: 1px solid var(--warn); border-radius: 10px; }
.check-result.all-good { border-color: var(--ok); }
.check-summary { margin: 0; font-weight: 600; }
#ed-check .progress { margin: 0; }

/* ---- finding a torrent: search, filter, order, and on a computer, cards or a table ---- */
.list-tools { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.list-search {
  flex: 1 1 180px; min-width: 0; font: inherit; padding: 9px 12px; border-radius: 10px;
  border: 1px solid var(--border); background: var(--card); color: var(--text); min-height: 40px;
}
.list-tools select {
  font: inherit; font-size: 0.9rem; padding: 8px 10px; border-radius: 10px; min-height: 40px; min-width: 0;
  border: 1px solid var(--border); background: var(--card); color: var(--text);
}
.list-sort { display: inline-flex; align-items: center; gap: 2px; min-width: 0; }
.list-sort .icon-btn { font-size: 1.1rem; }
.list-density { display: none; gap: 4px; padding: 3px; background: var(--card); border: 1px solid var(--border); border-radius: 10px; }
.list-density .tab { min-height: 32px; padding: 4px 12px; font-size: 0.85rem; }
@media (max-width: 480px) {
  .list-search { flex-basis: 100%; }
  .list-tools select { flex: 1 1 0; }
}
/* What to do with the torrents selected in the list. */
.bulk-bar {
  display: flex; flex-wrap: wrap; align-items: center; gap: 8px; padding: 8px 10px 8px 14px;
  background: var(--row-selected); border: 1px solid var(--border); border-radius: 12px;
}
.bulk-count { font-weight: 600; font-size: 0.9rem; margin-right: auto; }
.bulk-bar .btn.danger { background: var(--card); }

/* What the search or the filter leaves out, on a phone; the order chosen comes from `order`. */
.torrents .torrent.filtered { display: none; }

/* ---- the list itself: only on a computer ---- */
.torrent-list { display: none; }
.detail-empty { margin: 0; }
.tl-head { display: none; }
.tl-row {
  display: grid; grid-template-columns: 28px minmax(0, 1fr); grid-template-areas: "check name" ". progress";
  align-items: center; gap: 4px 10px; padding: 10px 14px; border-top: 1px solid var(--border); cursor: pointer;
  outline-offset: -2px;
}
.tl-body > .tl-row:first-child { border-top: none; }
.tl-row > .tl-cell { display: none; min-width: 0; }
.tl-row > .tl-check { display: flex; grid-area: check; }
.tl-row > .tl-name { display: grid; gap: 1px; grid-area: name; }
.tl-row > .tl-progress { display: flex; grid-area: progress; }
.tl-row > .tl-progress .tl-pct { display: none; }
.tl-check { display: flex; align-items: center; }
.tl-check input { width: 18px; height: 18px; margin: 0; accent-color: var(--primary); cursor: pointer; }
.tl-title { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tl-sub { color: var(--muted); font-size: 0.8rem; font-variant-numeric: tabular-nums; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tl-progress { align-items: center; gap: 6px; }
.tl-track { flex: 1; height: 4px; border-radius: 999px; background: var(--track); overflow: hidden; }
.tl-bar { display: block; height: 100%; width: 0; background: var(--primary); transition: width 0.3s ease; }
.tl-row.done .tl-bar, .tl-row.seeding .tl-bar { background: var(--accent); }
.tl-row.paused .tl-bar { background: var(--muted); }
.tl-row.focused { background: var(--row-open); box-shadow: inset 3px 0 0 var(--primary); }
.tl-row.selected { background: var(--row-selected); }
.tl-row:focus-visible { outline: 2px solid var(--primary); }
@media (hover: hover) {
  .tl-row:hover:not(.focused, .selected) { background: var(--row-hover); }
}
.tl-empty { margin: 0; }
.tl-sort { font: inherit; font-weight: 600; color: inherit; background: none; border: 0; padding: 4px 0; cursor: pointer; }
[aria-sort="ascending"] > .tl-sort::after { content: " ↑"; }
[aria-sort="descending"] > .tl-sort::after { content: " ↓"; }

/* The table: one line a torrent, its numbers in columns, sorted by a click on a header. */
.torrent-list.table .tl-head,
.torrent-list.table .tl-row {
  display: grid; grid-template-areas: none; grid-template-columns: 28px minmax(0, 1.6fr) 68px 112px 68px 68px 48px 52px minmax(96px, 0.7fr);
  align-items: center; gap: 0 10px;
}
.torrent-list.table .tl-head {
  padding: 6px 14px; font-size: 0.75rem; color: var(--muted); background: var(--bg); border-bottom: 1px solid var(--border);
}
.torrent-list.table .tl-head > .tl-cell { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.torrent-list.table .tl-row { padding: 7px 14px; }
.torrent-list.table .tl-row > .tl-cell {
  display: block; grid-area: auto; font-size: 0.85rem; font-variant-numeric: tabular-nums;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.torrent-list.table .tl-row > .tl-check,
.torrent-list.table .tl-row > .tl-progress { display: flex; }
.torrent-list.table .tl-row > .tl-progress .tl-pct { display: inline; width: 3.2em; text-align: right; flex: none; }
.torrent-list.table .tl-sub { display: none; }
.torrent-list.table .tl-title { font-weight: 500; }
.torrent-list.table :is(.tl-size, .tl-down, .tl-up, .tl-peers, .tl-eta) { text-align: right; }
.torrent-list.table .tl-track { height: 6px; }
/* A narrow list (the window at 1024px, the open torrent taking its share) keeps the columns that matter. */
@container (max-width: 760px) {
  .torrent-list.table .tl-head,
  .torrent-list.table .tl-row { grid-template-columns: 28px minmax(0, 1.6fr) 64px 104px 64px minmax(88px, 0.7fr); }
  .torrent-list.table :is(.tl-head, .tl-row) > :is(.tl-up, .tl-peers, .tl-eta) { display: none; }
}

/* ---- a computer: the list, and the torrent open beside it ---- */
@media (min-width: 1024px) {
  .topbar { padding-inline: max(16px, calc((100% - 1440px) / 2 + 16px)); }
  .container { max-width: 1440px; grid-template-columns: minmax(0, 62fr) minmax(360px, 38fr); align-items: start; }
  .list-pane { display: grid; gap: 16px; min-width: 0; }
  /* Under the top bar as the list scrolls, and scrolling on its own when the torrent is longer than the window. */
  .detail-pane {
    display: grid; gap: 16px; min-width: 0; position: sticky; top: 77px;
    max-height: calc(100dvh - 93px); overflow-y: auto; overscroll-behavior: contain; border-radius: var(--radius);
  }
  .detail-empty { padding: 48px 24px; border: 1px dashed var(--border); border-radius: var(--radius); }
  .torrents .torrent { display: none; }
  .torrents .torrent.focused { display: block; }
  .torrent-list {
    display: block; background: var(--card); border: 1px solid var(--border); border-radius: var(--radius);
    box-shadow: var(--shadow); overflow: hidden; container-type: inline-size;
  }
  .list-density { display: inline-flex; }
  .list-tools .keys-btn { display: inline-flex; }
}

/* ---- the computer's ways in: a folder, a drop anywhere, the keyboard ---- */
.add-row .file-btn { flex: 1 1 0; min-width: 0; }
.add-row .folder-pick { flex: 0 1 auto; width: auto; }
.keys-btn { display: none; }
.drop-overlay {
  position: fixed; inset: 8px; z-index: 20; display: grid; place-items: center; pointer-events: none;
  border: 3px dashed var(--primary); border-radius: var(--radius);
  background: color-mix(in srgb, var(--bg) 86%, transparent);
}
.drop-overlay p {
  margin: 0; padding: 14px 22px; border-radius: 12px; font-weight: 600; font-size: 1.05rem;
  background: var(--card); color: var(--text); box-shadow: 0 8px 30px rgba(0, 0, 0, 0.2);
}
.keys { display: grid; grid-template-columns: auto 1fr; gap: 8px 16px; margin: 0; font-size: 0.9rem; align-items: baseline; }
.keys dt { white-space: nowrap; }
.keys dd { margin: 0; color: var(--muted); }
kbd {
  font: 0.8rem ui-monospace, SFMono-Regular, Menlo, monospace; padding: 1px 6px; border-radius: 6px;
  border: 1px solid var(--border); border-bottom-width: 2px; background: var(--bg); color: var(--text);
}
