/* ============================================================
   Likee Downloader — stylesheet
   Light theme, mobile-first. Single file, no framework.
   ============================================================ */

:root {
  --ink: #0f1117;
  --ink-2: #2b3240;
  --muted: #616b7d;
  --bg: #ffffff;
  --bg-alt: #f6f7f9;
  --bg-sunk: #eef0f4;
  --line: #e3e7ee;
  --line-strong: #cfd6e2;

  --accent: #ff3b5c;
  --accent-ink: #d81e42;
  --accent-soft: #fff1f4;
  --violet: #7c5cff;
  --amber: #b26a00;
  --amber-soft: #fff8ec;
  --amber-line: #f3dcb0;

  --radius: 14px;
  --radius-sm: 9px;
  --radius-lg: 22px;
  --shadow-sm: 0 1px 2px rgba(15, 17, 23, .06), 0 1px 3px rgba(15, 17, 23, .04);
  --shadow: 0 4px 14px rgba(15, 17, 23, .07), 0 1px 3px rgba(15, 17, 23, .05);
  --shadow-lg: 0 18px 48px rgba(15, 17, 23, .11);
  --wrap: 1120px;
  --wrap-narrow: 780px;
  --font-latin: -apple-system, BlinkMacSystemFont, "Segoe UI", Inter, Roboto, "Helvetica Neue", Arial;
  --font-cjk: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei";
  --font: var(--font-latin), var(--font-cjk), sans-serif;
  --mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
}

/*
 * Traditional Chinese needs its own Han faces.
 *
 * The stack above names PingFang SC and Microsoft YaHei — Simplified faces.
 * They do contain the Traditional characters (they are different codepoints),
 * so nothing is missing or broken; what differs is the GLYPH FORM of characters
 * shared between the two scripts (骨, 直, 令, 者 …). A Traditional reader sees
 * Simplified-style shapes, which reads as "this page was not written for me"
 * even though every character is correct.
 *
 * The override works because `lang` sits on <html> (see layout.mjs), which IS
 * the root element — so the redefined --font-cjk and the --font that consumes
 * it are resolved on the same element. If `lang` is ever moved off <html>, this
 * silently stops applying and falls back to the Simplified faces; the Latin
 * half of the stack is unaffected either way.
 *
 * Order within --font-cjk is most-specific-first: TC and HK faces, then the
 * Windows and Android/Linux ones, then the Simplified faces kept as a last
 * resort so the stack still terminates in something that has Han glyphs.
 */
html:lang(zh-Hant) {
  --font-cjk: "PingFang TC", "PingFang HK", "Hiragino Sans TC", "Microsoft JhengHei",
              "Microsoft JhengHei UI", "Noto Sans TC", "Noto Sans CJK TC", "LiHei Pro",
              "PingFang SC", "Microsoft YaHei";
}

*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }

body {
  margin: 0;
  font-family: var(--font);
  font-size: 16px;
  line-height: 1.62;
  color: var(--ink-2);
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3, h4 { color: var(--ink); line-height: 1.22; margin: 0 0 .5em; font-weight: 700; letter-spacing: -.018em; }
h1 { font-size: clamp(1.9rem, 5.2vw, 3rem); }
h2 { font-size: clamp(1.35rem, 3.4vw, 1.9rem); }
h3 { font-size: 1.075rem; }
p { margin: 0 0 1rem; }
a { color: var(--accent-ink); text-decoration: none; }
a:hover { text-decoration: underline; }
img { max-width: 100%; height: auto; display: block; }
code { font-family: var(--mono); font-size: .875em; background: var(--bg-sunk); padding: .12em .42em; border-radius: 5px; color: var(--ink); }
ul, ol { margin: 0 0 1rem; padding-left: 1.25rem; }
li { margin-bottom: .35rem; }

.wrap { width: 100%; max-width: var(--wrap); margin: 0 auto; padding: 0 20px; }
.wrap--narrow { max-width: var(--wrap-narrow); }
.center { text-align: center; }
.muted { color: var(--muted); }
.small { font-size: .875rem; }

/*
 * The skip link is parked off-screen until focused. It used to be parked at
 * `left: -9999px` — the classic trick, and wrong here in two ways:
 *
 *   1. The site ships an RTL build (Arabic), and `left` is a physical side. In
 *      RTL the element is pushed off the inline-START side, and Chrome counts
 *      that as scrollable overflow: `scrollWidth` reports 11279px on a 1280px
 *      viewport. Nothing is visible because of it — the page still refuses to
 *      scroll, `scrollTo` clamps at 0 — but Safari is known to show a
 *      horizontal scrollbar for exactly this shape, and the inflated
 *      scrollWidth breaks anything that sizes a capture area to the document.
 *      Our own RTL screenshot pass came back blank for this reason, which is
 *      how it was found.
 *   2. `left: 0` on focus also parks the focused link against the document's
 *      left edge, which is the far side of the screen once the text runs RTL.
 *
 * Parking it above the viewport is direction-agnostic — there is no horizontal
 * overflow to count in either writing direction, and no physical side to get
 * backwards. Focus behaviour and on-screen position are unchanged.
 */
.skip {
  position: absolute; left: 0; top: -100px; background: var(--ink); color: #fff;
  padding: 10px 16px; z-index: 200;
  /* Logical, so the rounded corner faces the content in both directions. */
  border-end-end-radius: 8px;
}
.skip:focus { top: 0; }

/* ---------------- header ---------------- */

.site-header {
  position: sticky; top: 0; z-index: 100;
  background: rgba(255, 255, 255, .88);
  backdrop-filter: saturate(180%) blur(14px);
  border-bottom: 1px solid var(--line);
}
.site-header__inner { display: flex; align-items: center; gap: 18px; height: 62px; }
.logo { display: inline-flex; align-items: center; gap: 9px; font-weight: 800; color: var(--ink); font-size: 1.08rem; letter-spacing: -.02em; flex-shrink: 0; }
.logo:hover { text-decoration: none; }
.logo svg { color: var(--accent); }

.site-nav { display: none; gap: 2px; margin-left: auto; flex-wrap: wrap; }
.site-nav a {
  color: var(--ink-2); font-size: .875rem; font-weight: 550; padding: 6px 10px;
  border-radius: 8px; white-space: nowrap;
}
.site-nav a:hover { background: var(--bg-alt); text-decoration: none; }
.site-nav a[aria-current="page"] { background: var(--accent-soft); color: var(--accent-ink); }

.site-header__actions { display: none; gap: 8px; margin-left: auto; }
.site-nav + .site-header__actions { margin-left: 12px; }

.nav-toggle {
  margin-left: auto; width: 40px; height: 40px; border: 1px solid var(--line);
  background: #fff; border-radius: 10px; display: grid; place-content: center; gap: 4px; cursor: pointer;
}
.nav-toggle span { display: block; width: 17px; height: 2px; background: var(--ink); border-radius: 2px; }

/* ---------------- buttons ---------------- */

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 7px;
  font: inherit; font-weight: 650; font-size: .92rem;
  padding: 10px 17px; border-radius: 10px; border: 1px solid transparent;
  cursor: pointer; transition: .16s ease; white-space: nowrap;
}
.btn:hover { text-decoration: none; transform: translateY(-1px); }
.btn--primary { background: var(--ink); color: #fff; box-shadow: var(--shadow-sm); }
.btn--primary:hover { background: #000; box-shadow: var(--shadow); }
.btn--ghost { background: #fff; border-color: var(--line-strong); color: var(--ink); }
.btn--ghost:hover { border-color: var(--ink); }
.btn--lg { padding: 14px 28px; font-size: 1rem; border-radius: 12px; }

/* ---------------- hero ---------------- */

.hero {
  padding: 52px 0 40px;
  background:
    radial-gradient(900px 380px at 12% -8%, #fff0f3 0%, rgba(255,255,255,0) 62%),
    radial-gradient(760px 340px at 88% 0%, #f0edff 0%, rgba(255,255,255,0) 60%),
    var(--bg);
  border-bottom: 1px solid var(--line);
}
.hero--compact { padding: 34px 0 30px; }
.hero__inner { max-width: 860px; margin: 0 auto; text-align: center; }
.hero h1 { margin-bottom: .35em; }
.grad {
  background: linear-gradient(96deg, var(--accent) 0%, var(--violet) 100%);
  -webkit-background-clip: text; background-clip: text; -webkit-text-fill-color: transparent; color: var(--accent);
}
.hero__sub { font-size: 1.06rem; color: var(--muted); max-width: 640px; margin: 0 auto 26px; }
.hero--compact .hero__sub { margin-bottom: 22px; }
.eyebrow {
  display: inline-block; font-size: .78rem; font-weight: 700; letter-spacing: .09em;
  text-transform: uppercase; color: var(--accent-ink);
  background: var(--accent-soft); border: 1px solid #ffd9e0;
  padding: 5px 12px; border-radius: 999px; margin: 0 0 18px;
}

/* ---------------- downloader widget ---------------- */

/* 728px, not 700: the leaderboard that sits inside this block is 728 wide, and
   .ad-slot has overflow:hidden — a 700px parent would shave 28px off the right
   edge of the creative. */
.dl { max-width: 728px; margin: 0 auto; text-align: left; }
.dl__row {
  display: flex; gap: 8px; background: #fff; padding: 8px;
  border: 1.5px solid var(--line-strong); border-radius: var(--radius-lg);
  box-shadow: var(--shadow); transition: border-color .16s, box-shadow .16s;
}
.dl__row:focus-within { border-color: var(--accent); box-shadow: 0 0 0 4px rgba(255, 59, 92, .12), var(--shadow); }
.dl__input {
  flex: 1; min-width: 0; border: 0; background: transparent; font: inherit;
  padding: 12px 14px; color: var(--ink); outline: none;
}
.dl__input::placeholder { color: #99a2b3; }
.dl__submit {
  border: 0; background: var(--ink); color: #fff; font: inherit; font-weight: 650;
  padding: 12px 24px; border-radius: 999px; cursor: pointer; transition: .16s; white-space: nowrap;
}
.dl__submit:hover { background: #000; }
.dl__submit:disabled { opacity: .55; cursor: progress; }
.dl__meta { display: flex; justify-content: space-between; gap: 12px; padding: 10px 6px 0; font-size: .82rem; color: var(--muted); }
.dl__spinner { color: var(--accent-ink); font-weight: 600; }
.dl__result { margin-top: 14px; display: grid; gap: 8px; }
.dl__error {
  margin-top: 14px; padding: 13px 15px; border-radius: var(--radius-sm);
  background: #fff5f5; border: 1px solid #ffd3d3; color: #9c1c1c; font-size: .9rem;
}

/* ---------------- result panel ----------------
   Three parts: proof we found the right video, one big row per format, and an
   ad slot underneath everything. Most of this traffic is mobile, so the format
   rows are full-width tap targets rather than a small button beside two lines
   of text. */

.rhead {
  /* flex-start, not center: the meta column can now run to title + byline +
     counts + facts + caption, and centring the thumbnail against a tall block
     leaves it floating in the middle of the card. */
  display: flex; align-items: flex-start; gap: 12px;
  background: #fff; border: 1px solid var(--line); border-radius: var(--radius);
  padding: 10px; box-shadow: var(--shadow-sm);
}
.rhead__thumb {
  width: 68px; height: 68px; flex: none; object-fit: cover;
  border-radius: var(--radius-sm); background: var(--bg-sunk);
}
.rhead__meta { min-width: 0; flex: 1; }
.rhead__title {
  margin: 0; font-size: .95rem; font-weight: 650; color: var(--ink); line-height: 1.35;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.rhead__by { margin: 4px 0 0; font-size: .82rem; color: var(--muted); }
.rhead__author { color: inherit; }
.rhead__author:hover { color: var(--accent-ink); }

/* Counts — views / likes / comments / shares.
   Rendered only for the counts the platform actually reported, so the row can
   be anything from one item to four. `flex-wrap` keeps a long localised label
   from pushing the row past the card. */
.rstats {
  list-style: none; margin: 6px 0 0; padding: 0;
  display: flex; flex-wrap: wrap; gap: 3px 12px;
  font-size: .78rem; color: var(--muted);
}
.rstats__i { white-space: nowrap; }
.rstats__i strong {
  color: var(--ink); font-weight: 650;
  /* Tabular figures stop the row from reflowing as numbers change width. */
  font-variant-numeric: tabular-nums;
}

/* Publish date and music credit. */
.rfacts { margin: 5px 0 0; font-size: .78rem; color: var(--muted); }

/* Caption.
   Clamped to three lines until asked for — a long TikTok caption would push the
   download buttons off the first screen, and the buttons are the whole point of
   the page. The "Show more" control is only revealed when the text actually
   overflows; see the post-render check in app.js. */
.rdesc { margin: 7px 0 0; }
.rdesc__text {
  margin: 0; font-size: .82rem; color: var(--muted); line-height: 1.45;
  display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical;
  overflow: hidden;
}
.rdesc.is-open .rdesc__text { display: block; -webkit-line-clamp: unset; overflow: visible; }
.rdesc__more {
  margin-top: 3px; padding: 0; border: 0; background: none; cursor: pointer;
  font: inherit; font-size: .78rem; font-weight: 600;
  color: var(--accent-ink); border-bottom: 1px dashed var(--line-strong);
}
.rdesc__more:hover { border-color: var(--accent); }
.rdesc__more[hidden] { display: none; }

.fmtlist__head {
  margin: 4px 0 -2px; padding: 0 2px;
  font-size: .82rem; font-weight: 650; color: var(--ink);
}

.fmtlist { list-style: none; margin: 0; padding: 0; display: grid; gap: 8px; }

/*
 * `position: relative` is load-bearing: the primary button stretches an
 * invisible ::after over this whole box, which is what turns the entire row
 * into one tap target. See .fmt__go.
 */
.fmt {
  position: relative;
  display: flex; align-items: center; gap: 12px;
  background: #fff; border: 1px solid var(--line); border-radius: var(--radius);
  padding: 12px; box-shadow: var(--shadow-sm);
  transition: border-color .15s, box-shadow .15s;
}
.fmt:hover { border-color: var(--line-strong); box-shadow: var(--shadow); }
/* The top video option. Two video rows used to differ only by a resolution
   number; this is the signal that breaks the tie. */
.fmt--best { border-color: var(--accent); }

.fmt__badge {
  flex: none; min-width: 46px; text-align: center;
  font-size: .7rem; font-weight: 700; letter-spacing: .05em;
  color: var(--accent-ink); background: var(--accent-soft);
  border-radius: 8px; padding: 7px 6px;
}
.fmt__text { min-width: 0; flex: 1; display: grid; gap: 2px; }
.fmt__title { display: flex; align-items: center; gap: 7px; flex-wrap: wrap; }
.fmt__label { font-size: .92rem; font-weight: 650; color: var(--ink); }
.fmt__flag {
  flex: none;
  font-size: .64rem; font-weight: 700; letter-spacing: .04em;
  color: #fff; background: var(--accent);
  border-radius: 999px; padding: 2px 7px;
}
.fmt__sub {
  font-size: .8rem; color: var(--muted);
  font-variant-numeric: tabular-nums;
  /*
   * Always a technical string — digits plus Latin units (1080p, 128 kbps,
   * 3.2 MB) — so it reads left-to-right no matter what the page is.
   *
   * Left to inherit, the bidi algorithm reorders it inside the RTL build: the
   * MP3 row rendered as "kbps · ~375 KB 128" instead of "128 kbps · ~375 KB".
   * The video rows escaped only by luck — their digits are glued to the unit
   * ("1080p"), which keeps the whole token one LTR run, while the space in
   * "128 kbps" gives the algorithm somewhere to break the line apart.
   */
  direction: ltr;
  unicode-bidi: isolate;
}

/*
 * The primary action — and the whole row is the target.
 *
 * This used to be a 42px circle. On a 390px phone that is ~1,760 px² of
 * tappable area per option, against ~18,700 px² for the full-width buttons on
 * the sites this competes with: an order of magnitude, on the screen where most
 * of the traffic lands. The comment above render() has described a "big
 * tappable row" since the panel was first written; the CSS never delivered it.
 *
 * `::after` stretches the anchor across the whole row, so the row becomes one
 * target without nesting the "with filename" link inside the button — invalid
 * HTML, and it would make the secondary link unclickable.
 */
.fmt__go {
  flex: none; margin-left: auto;
  display: inline-flex; align-items: center; gap: 7px;
  border-radius: 999px; padding: 9px 15px;
  background: var(--accent); color: #fff;
  font-size: .85rem; font-weight: 650;
  transition: background .15s, transform .1s;
}
.fmt__go::after {
  content: ''; position: absolute; inset: 0;
  border-radius: var(--radius);
}
.fmt__go:hover { background: var(--accent-ink); text-decoration: none; }
.fmt__go:active { transform: scale(.97); }
.fmt__goText { white-space: nowrap; }

.fmt__alt {
  /* Above the row-wide overlay, or the primary button's ::after would swallow
     every click meant for this link. */
  position: relative; z-index: 1;
  flex: none; font-size: .74rem; font-weight: 600; color: var(--muted);
  border-bottom: 1px dashed var(--line-strong); white-space: nowrap;
}
.fmt__alt:hover { color: var(--accent-ink); border-color: var(--accent); text-decoration: none; }

@media (max-width: 520px) {
  /*
   * The secondary link used to be hidden below this width, on the grounds that
   * it crowded the primary button. That was safe only while the primary button
   * was always the proxy path.
   *
   * It is not any more: the server now tells the client which mode to prefer,
   * and on platforms whose CDN accepts a browser-originated request that mode is
   * `direct`. If a direct fetch is refused, the visitor needs the other path —
   * and hiding it on mobile means the visitors most likely to be on a flaky
   * connection are the only ones without a fallback.
   *
   * So it wraps to its own line instead of disappearing. `flex-wrap` plus
   * `margin-left: auto` puts it at the end of a second row, still shrink-wrapped
   * so its dashed underline hugs the text rather than spanning the card.
   */
  .fmt { flex-wrap: wrap; }
  /*
   * Full-width button on its own line, under the label.
   *
   * Inline, the label and a labelled button fight over ~334px: the badge takes
   * 44, the button ~120, leaving the label ~140 — enough for "Best quality" and
   * nothing more, in any language. Dropping the button to its own line gives the
   * label the full width and the thumb a target the height of a thumb.
   */
  .fmt__go {
    order: 5; width: 100%; justify-content: center;
    margin: 2px 0 0; padding: 11px 15px;
  }
  .fmt__alt { order: 10; margin-left: auto; }
  .rhead__thumb { width: 56px; height: 56px; }
}

/* ---------------- post-download notice ----------------
   Shown once, after the visitor has already committed to a download. It never
   blocks the transfer: the anchor has started before this appears. */

.dlmodal {
  position: fixed; inset: 0; z-index: 200;
  display: grid; place-items: center; padding: 18px;
  background: rgba(15, 17, 23, .55);
}
.dlmodal[hidden] { display: none; }
.dlmodal__box {
  position: relative; width: 100%; max-width: 420px;
  background: #fff; border-radius: var(--radius-lg);
  padding: 22px 20px 18px; box-shadow: var(--shadow-lg); text-align: center;
}
.dlmodal__x {
  position: absolute; top: 8px; inset-inline-end: 10px;
  width: 32px; height: 32px; border: 0; border-radius: 999px;
  background: transparent; color: var(--muted); font-size: 1.4rem; line-height: 1;
  cursor: pointer;
}
.dlmodal__x:hover { background: var(--bg-alt); color: var(--ink); }
.dlmodal__ok {
  display: flex; align-items: center; justify-content: center; gap: 8px;
  margin: 0 0 4px; font-size: 1rem; font-weight: 650; color: var(--ink);
}
.dlmodal__ok svg { color: #1d9e75; flex: none; }
.dlmodal__sub { margin: 0 0 16px; font-size: .85rem; color: var(--muted); }
.dlmodal .ad-slot { margin: 0 0 14px; min-height: 200px; }
.dlmodal__close {
  width: 100%; border: 1px solid var(--line-strong); background: var(--bg);
  color: var(--ink-2); font: inherit; font-weight: 650; font-size: .9rem;
  padding: 11px; border-radius: var(--radius-sm); cursor: pointer;
}
.dlmodal__close:hover { background: var(--bg-alt); }

[dir="rtl"] .dlmodal__box { text-align: center; }

/* ---------------- chips / trust ---------------- */

.chips { display: flex; flex-wrap: wrap; gap: 8px; justify-content: center; margin: 22px 0 0; }
.chip {
  display: inline-flex; align-items: center; gap: 7px;
  font-size: .85rem; font-weight: 600; color: var(--ink-2);
  background: #fff; border: 1px solid var(--line); border-radius: 999px;
  padding: 7px 14px; box-shadow: var(--shadow-sm); transition: .16s;
}
.chip::before { content: ""; width: 8px; height: 8px; border-radius: 50%; background: var(--plat, var(--accent)); }
.chip:hover { border-color: var(--plat, var(--accent)); text-decoration: none; transform: translateY(-1px); }

.trust { display: flex; flex-wrap: wrap; gap: 8px 22px; justify-content: center; list-style: none; padding: 0; margin: 26px 0 0; font-size: .84rem; color: var(--muted); }
.trust li { display: flex; align-items: center; gap: 7px; margin: 0; }
.trust li::before { content: "✓"; color: #16a34a; font-weight: 800; }

/* ---------------- sections ---------------- */

.section { padding: 56px 0; }
.section--alt { background: var(--bg-alt); border-block: 1px solid var(--line); }
.section__head { display: flex; align-items: flex-end; justify-content: space-between; gap: 16px; flex-wrap: wrap; margin-bottom: 20px; }
.section__head h2 { margin-bottom: .15em; }
.section__head p { margin: 0; }

/* ---------------- filters + feed ---------------- */

.filters { display: flex; gap: 7px; flex-wrap: wrap; margin-bottom: 20px; }
.filter {
  font: inherit; font-size: .85rem; font-weight: 600; color: var(--ink-2);
  background: #fff; border: 1px solid var(--line); border-radius: 999px;
  padding: 7px 15px; cursor: pointer; transition: .14s;
}
.filter:hover { border-color: var(--line-strong); }
.filter.is-active { background: var(--ink); color: #fff; border-color: var(--ink); }

.grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(228px, 1fr)); gap: 18px; align-items: start; }

.card {
  background: #fff; border: 1px solid var(--line); border-radius: var(--radius);
  overflow: hidden; box-shadow: var(--shadow-sm); transition: .18s ease;
  display: flex; flex-direction: column;
}
.card:hover { transform: translateY(-3px); box-shadow: var(--shadow); border-color: var(--line-strong); }
.card[hidden] { display: none; }
.card__thumb { position: relative; background: var(--bg-sunk); aspect-ratio: 16 / 9; }
.card__thumb.is-vertical { aspect-ratio: 9 / 13; }
.card__thumb img { width: 100%; height: 100%; object-fit: cover; }
.card__plat {
  position: absolute; top: 9px; left: 9px; font-size: .68rem; font-weight: 700;
  text-transform: uppercase; letter-spacing: .05em; color: #fff;
  background: color-mix(in srgb, var(--plat) 82%, #000); padding: 3px 9px; border-radius: 999px;
  backdrop-filter: blur(4px);
}
.card__dur {
  position: absolute; bottom: 9px; right: 9px; font-size: .72rem; font-weight: 650;
  color: #fff; background: rgba(0, 0, 0, .62); padding: 2px 7px; border-radius: 5px;
  font-variant-numeric: tabular-nums;
}
.card__body { padding: 13px 14px 14px; display: flex; flex-direction: column; gap: 6px; flex: 1; }
.card__title { font-size: .95rem; margin: 0; line-height: 1.38; }
.card__meta { margin: 0; font-size: .78rem; color: var(--muted); }
.card__foot { display: flex; align-items: center; gap: 6px; margin-top: auto; padding-top: 8px; }
.tag {
  font-size: .72rem; font-weight: 650; color: var(--muted);
  background: var(--bg-alt); border: 1px solid var(--line); border-radius: 6px; padding: 2px 7px;
}
.card__grab {
  margin-left: auto; font: inherit; font-size: .8rem; font-weight: 650;
  color: var(--accent-ink); background: var(--accent-soft); border: 1px solid #ffd9e0;
  padding: 5px 12px; border-radius: 999px; cursor: pointer; transition: .14s;
}
.card__grab:hover { background: var(--accent); color: #fff; border-color: var(--accent); }

/* ---------------- steps / features ---------------- */

.steps { list-style: none; padding: 0; display: grid; gap: 18px; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); counter-reset: s; }
.steps li { background: #fff; border: 1px solid var(--line); border-radius: var(--radius); padding: 22px; margin: 0; box-shadow: var(--shadow-sm); }
.steps__n {
  display: grid; place-content: center; width: 30px; height: 30px; border-radius: 50%;
  background: var(--accent); color: #fff; font-weight: 800; font-size: .88rem; margin-bottom: 12px;
}
.steps h3 { margin-bottom: .3em; }
.steps p { margin: 0; color: var(--muted); font-size: .92rem; }
.steps--inline { grid-template-columns: 1fr; gap: 12px; }
.steps--inline li { display: flex; gap: 14px; align-items: flex-start; padding: 16px 18px; }
.steps--inline .steps__n { margin: 0; flex-shrink: 0; }
.steps--inline p { color: var(--ink-2); }

.features { display: grid; gap: 18px; grid-template-columns: repeat(auto-fit, minmax(272px, 1fr)); margin-top: 28px; }
.feature { background: #fff; border: 1px solid var(--line); border-radius: var(--radius); padding: 22px; box-shadow: var(--shadow-sm); }
.feature h3 { margin-bottom: .35em; }
.feature p { margin: 0; color: var(--muted); font-size: .92rem; }

/* ---------------- prose / tables / callouts ---------------- */

.prose > h2 { margin-top: 2em; padding-top: .2em; }
.prose > h2:first-child { margin-top: 0; }
.prose > p, .prose li { color: var(--ink-2); }

.table { width: 100%; border-collapse: collapse; margin: 0 0 1.4rem; font-size: .9rem; }
.table th, .table td { text-align: left; padding: 11px 13px; border-bottom: 1px solid var(--line); vertical-align: top; }
.table th { background: var(--bg-alt); font-weight: 650; color: var(--ink); font-size: .82rem; text-transform: uppercase; letter-spacing: .04em; }
.table tr:last-child td { border-bottom: 0; }
.table td:last-child { white-space: nowrap; }

.urls { list-style: none; padding: 0; }
.urls li { margin-bottom: .5rem; }
.urls code { display: inline-block; word-break: break-all; }

.callout { background: var(--bg-alt); border: 1px solid var(--line); border-left: 3px solid var(--violet); border-radius: var(--radius-sm); padding: 16px 18px; margin: 0 0 1.4rem; }
.callout p:last-child, .callout ul:last-child { margin-bottom: 0; }
.callout--warn { background: var(--amber-soft); border-color: var(--amber-line); border-left-color: var(--amber); }

/* ---------------- FAQ ---------------- */

.faq { margin-top: 24px; }
.faq__item { border: 1px solid var(--line); border-radius: var(--radius-sm); background: #fff; margin-bottom: 9px; overflow: hidden; }
.faq__item[open] { border-color: var(--line-strong); box-shadow: var(--shadow-sm); }
.faq__item summary { cursor: pointer; padding: 15px 18px; list-style: none; display: flex; align-items: center; gap: 12px; }
.faq__item summary::-webkit-details-marker { display: none; }
.faq__item summary::after { content: "+"; margin-left: auto; font-size: 1.3rem; color: var(--muted); line-height: 1; }
.faq__item[open] summary::after { content: "–"; }
.faq__item summary h3 { margin: 0; font-size: .97rem; font-weight: 650; }
.faq__body { padding: 0 18px 16px; color: var(--muted); font-size: .93rem; }
.faq__body p { margin: 0; }

/* ---------------- ads ---------------- */

/* Ad slots stay hidden until ads.js marks one live.
   An empty "Advertisement" box is worse than no box at all: it reads as broken,
   burns layout space, and gives a quality rater nothing to like. The reserved
   height still applies once a slot is live — that is what protects CLS. */
.ad-slot { display: none; }

/* An empty slot must look like nothing, not like a broken ad.
 *
 * `is-live` is added as soon as ads.js has written the network's snippet into
 * the slot — it means "a container was placed", not "a creative arrived". The
 * two are not the same thing, and the old dashed placeholder made the
 * difference visible: whenever the zone was configured but the network served
 * nothing, every page grew a grey hatched box labelled ADVERTISEMENT. That is
 * worse than a blank space — it advertises the failure.
 *
 * So the filled state is now a plain transparent container. The height is
 * still reserved (see .ad-slot--under) so a late-arriving banner does not
 * shove the result panel down, but until something actually renders there is
 * nothing to see. */
.ad-slot.is-live {
  display: grid; place-items: center;
  border-radius: var(--radius-sm);
  overflow: hidden;
}
.ad-slot__label { font-size: .68rem; letter-spacing: .14em; text-transform: uppercase; font-weight: 700; }


/* Sits inside the downloader, between the input row and the result panel.
   90px is the leaderboard's own height, reserved before it loads so the result
   panel does not jump. ads.js overwrites it once the banner is in, and shrinks
   both on narrow screens where 728px will not fit. */
.ad-slot--under {
  min-height: 90px;
  margin: 14px auto 10px;
  max-width: 728px;
}

/* Inside the post-download notice. 250px is the rectangle's own height; the
   modal is 420 wide, so a 300px banner sits comfortably. */
.ad-slot--inline { min-height: 250px; }

/* ---------------- footer ---------------- */

.site-footer { background: var(--bg-alt); border-top: 1px solid var(--line); padding: 52px 0 26px; margin-top: 0; font-size: .9rem; }
.site-footer__grid { display: grid; gap: 32px; grid-template-columns: 1fr; }
.site-footer h3 { font-size: .8rem; text-transform: uppercase; letter-spacing: .07em; color: var(--muted); margin-bottom: .9em; }
.site-footer ul { list-style: none; padding: 0; margin: 0; }
.site-footer li { margin-bottom: .45rem; }
.site-footer a { color: var(--ink-2); }
.site-footer a:hover { color: var(--accent-ink); }
.site-footer__bottom { display: flex; justify-content: space-between; gap: 14px; flex-wrap: wrap; margin-top: 40px; padding-top: 22px; border-top: 1px solid var(--line); font-size: .82rem; color: var(--muted); }
.site-footer__bottom p { margin: 0; }

/* ---------------- crumbs + cta ---------------- */

.crumbs { padding-top: 16px; font-size: .82rem; }
.crumbs ol { list-style: none; display: flex; flex-wrap: wrap; gap: 7px; padding: 0; margin: 0; }
.crumbs li { margin: 0; color: var(--muted); }
.crumbs li + li::before { content: "/"; margin-right: 7px; color: var(--line-strong); }

.cta { background: var(--ink); color: #fff; padding: 62px 0; text-align: center; }
.cta h2 { color: #fff; }
.cta .muted { color: #a8b0bf; margin-bottom: 24px; }
.cta .btn--primary { background: #fff; color: var(--ink); }
.cta .btn--primary:hover { background: #f0f2f5; }

/* ---------------- responsive ---------------- */

@media (min-width: 780px) {
  .site-footer__grid { grid-template-columns: 1.6fr 1fr 1.2fr 1fr; }
  .steps--inline { grid-template-columns: 1fr 1fr; }
}

@media (min-width: 1000px) {
  .site-nav { display: flex; }
  .site-header__actions { display: flex; }
  .nav-toggle { display: none; }
}

/* mobile nav drawer */
@media (max-width: 999px) {
  .site-header__inner { flex-wrap: wrap; height: auto; padding-block: 11px; }
  .nav-toggle { display: grid; }
  .site-header.is-open .site-nav,
  .site-header.is-open .site-header__actions { display: flex; width: 100%; margin: 8px 0 4px; }
  .site-header.is-open .site-nav { flex-direction: column; }
  .site-header.is-open .site-header__actions { margin-top: 0; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: .01ms !important; transition-duration: .01ms !important; scroll-behavior: auto !important; }
}

@media print {
  .site-header, .site-footer, .ad-slot, .dl, .cta { display: none; }
}

/* ---------- Language switcher ----------
   A <details> disclosure, so it works without JS and the links inside are
   real <a> elements a crawler can follow. Positioned inside the header
   actions; on mobile it collapses with the rest of the nav. */

.lang { position: relative; }
.lang > summary {
  display: inline-flex; align-items: center; gap: 7px;
  /* Sized to match .btn (10px 17px / .92rem / 10px radius) so the switcher and
     the Download button read as one row. It used to be 8px 10px / 13px, which
     made it ~6px shorter — visibly a different control sitting next to it.
     Horizontal padding stays tighter than .btn on purpose: language names vary
     in length, and 17px per side made the header overflow in German and
     Portuguese. */
  padding: 10px 12px; border-radius: 10px;
  border: 1px solid var(--line); background: var(--bg);
  color: var(--ink-2); font-size: .92rem; font-weight: 600;
  cursor: pointer; list-style: none; white-space: nowrap;
}
.lang > summary::-webkit-details-marker { display: none; }
.lang > summary:hover { border-color: var(--line-strong); background: var(--bg-alt); }
.lang[open] > summary { border-color: var(--accent); color: var(--accent-ink); }
.lang > summary svg { flex: none; opacity: .7; }

.lang__list {
  position: absolute; inset-inline-end: 0; top: calc(100% + 6px);
  z-index: 60; min-width: 190px; max-height: 60vh; overflow-y: auto;
  margin: 0; padding: 6px; list-style: none;
  background: var(--bg); border: 1px solid var(--line);
  border-radius: var(--radius); box-shadow: var(--shadow-lg);
}
.lang__list a {
  display: block; padding: 8px 10px; border-radius: var(--radius-sm);
  color: var(--ink-2); font-size: 14px; text-decoration: none;
}
.lang__list a:hover { background: var(--bg-alt); color: var(--ink); }
.lang__list a.is-current { background: var(--accent-soft); color: var(--accent-ink); font-weight: 600; }

/* The header actions row is hidden below 900px until the nav is opened, so the
   switcher rides along with it rather than needing its own breakpoint. */

/* ---------- Right-to-left ----------
   Only the handful of properties that are physically directional need
   overriding; everything else uses logical properties already. */

[dir="rtl"] .site-header__actions { margin-left: 0; margin-right: auto; }
[dir="rtl"] .lang__list { text-align: right; }
[dir="rtl"] .crumbs ol { direction: rtl; }
[dir="rtl"] .prose ul,
[dir="rtl"] .prose ol { padding-left: 0; padding-right: 1.3em; }
[dir="rtl"] .callout ul { padding-left: 0; padding-right: 1.1em; }
[dir="rtl"] .trust { padding-left: 0; padding-right: 0; }
[dir="rtl"] .steps__n { margin-right: 0; margin-left: 10px; }
[dir="rtl"] .table th,
[dir="rtl"] .table td { text-align: right; }
[dir="rtl"] .hero__inner { text-align: right; }
[dir="rtl"] .section__head { text-align: right; }
/* `.dl` pins the download panel to `text-align: left` so the URL field and the
   result copy line up on the same edge in LTR. In RTL that put a format row's
   detail line on the opposite edge from its own title — the title right, the
   "1080p · 3.2 MB" underneath it left. `direction: ltr` on `.fmt__sub` (see
   above) does not help here, because `text-align` is physical: with the
   element's own direction set to LTR, only an explicit `right` lands it back
   under the title. */
[dir="rtl"] .fmt__sub { text-align: right; }
