/* --------------------------------------------------------------------
   landing.css — gallery home page. Loaded AFTER viewer/style.css, so it
   inherits every design token (:root vars), the Fraunces/Geist/JetBrains
   fonts, and the .light theme palette — and overrides only the few global
   rules the viewer set for its full-screen app shell. Selectors are scoped
   to .landing / landing-only classes so nothing here can bleed back into the
   viewer when both share style.css tokens.
   -------------------------------------------------------------------- */

/* the viewer makes <body> a non-scrolling flex column; the gallery scrolls */
body.landing {
  display: block;
  overflow-y: auto;
  height: auto;
  min-height: 100%;
  /* reserve the scrollbar gutter so a language switch that changes content
     height (and toggles the scrollbar) never shifts the layout sideways */
  scrollbar-gutter: stable;
}

/* ---------- main ---------- */
.landing-main {
  max-width: 1140px;
  margin: 0 auto;
  /* generous bottom padding so the last row of cards clears the fixed CTA strip */
  padding: 0 28px 100px;
}

/* ---------- hero + search ---------- */
.hero {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  padding: clamp(48px, 11vh, 116px) 0 40px;
}
.hero-title {
  font-family: var(--font-display);
  font-style: italic;
  font-weight: 500;
  font-size: clamp(38px, 6vw, 60px);
  letter-spacing: -0.02em;
  line-height: 1.05;
  margin: 0;
  color: var(--text-0);
}
.hero-tagline {
  font-family: var(--font-ui);
  font-size: 16px;
  font-weight: 300;
  line-height: 1.5;
  color: var(--text-2);
  margin: 16px 0 0;
  max-width: 540px;
  /* both EN and ZH taglines fit on a single line — reserve one line so the
     search box and the grid below don't jump when the language is switched */
  min-height: 24px;
}

.search {
  position: relative;
  width: min(560px, 100%);
  margin-top: 20px;
}
.search-icon {
  position: absolute;
  left: 17px; top: 50%;
  transform: translateY(-50%);
  width: 17px; height: 17px;
  color: var(--text-3);
  pointer-events: none;
  transition: color 0.15s;
}
.search input {
  width: 100%;
  box-sizing: border-box;
  padding: 14px 18px 14px 44px;
  font-family: var(--font-ui);
  font-size: 16px;
  color: var(--text-0);
  background: var(--bg-1);
  border: 1px solid var(--line);
  border-radius: 11px;
  outline: none;
  transition: border-color 0.15s, box-shadow 0.15s, background 0.15s;
}
.search input::placeholder { color: var(--text-3); }
.search input:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-dim);
  background: var(--bg-0);
}
.search:focus-within .search-icon { color: var(--accent); }
/* hide the native search "x" clear button for a cleaner look */
.search input::-webkit-search-cancel-button { -webkit-appearance: none; appearance: none; }

/* ---------- gallery grid ---------- */
.gallery {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
  gap: 18px;
  margin-top: 14px;
}

.card {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 20px 21px 18px;
  background: var(--bg-1);
  border: 1px solid var(--line);
  border-radius: 12px;
  text-decoration: none;
  color: inherit;
  transition: border-color 0.16s, transform 0.16s, box-shadow 0.16s;
}
.card:hover {
  border-color: var(--accent);
  transform: translateY(-3px);
  box-shadow: 0 10px 30px -14px var(--shadow-panel);
}

.card-head { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; }
.card-head-side { flex: 0 0 auto; display: inline-flex; align-items: center; gap: 6px; }
.card-name {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: 20px;
  letter-spacing: -0.01em;
  color: var(--text-0);
  word-break: break-word;
}
.card-tag {
  flex: 0 0 auto;
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-3);
  border: 1px solid var(--line);
  border-radius: 4px;
  padding: 2px 6px;
}

.card-langs { display: flex; flex-wrap: wrap; gap: 6px; }
.lang-chip {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.03em;
  color: var(--text-1);
  background: var(--bg-2);
  border: 1px solid var(--line-faint);
  border-radius: 5px;
  padding: 3px 8px;
}

.card-desc {
  font-family: var(--font-ui);
  font-size: 13px;
  line-height: 1.5;
  color: var(--text-2);
  margin: 0;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.card-stats {
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.01em;
  color: var(--text-2);
  margin-top: auto;
}
.card-stats .dot { color: var(--text-3); margin: 0 6px; }
.card-git {
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--text-3);
  border-top: 1px solid var(--line-faint);
  padding-top: 10px;
}
.card-git .accent { color: var(--accent); }

/* ---------- empty / note ---------- */
.gallery-note {
  text-align: center;
  font-family: var(--font-ui);
  font-size: 15px;
  color: var(--text-2);
  margin-top: 64px;
}
.gallery-note code {
  font-family: var(--font-mono);
  font-size: 13px;
  color: var(--text-1);
  background: var(--bg-2);
  border: 1px solid var(--line);
  border-radius: 5px;
  padding: 2px 7px;
}

/* ---------- CTA banner — fixed floating strip at the bottom ----------
   A full-width bar pinned to the viewport bottom, mirroring the sticky
   .topbar (same --header-bg + blur) so the page is bracketed top & bottom.
   Title/desc are kept to a single line each (ellipsis) so the bar's height
   is constant across EN↔ZH — it never scrolls, never jumps. */
.cta {
  position: fixed;
  left: 0; right: 0; bottom: 0;
  z-index: 40;
  background: var(--header-bg);
  backdrop-filter: blur(8px);
  border-top: 1px solid var(--line);
}
.cta-inner {
  max-width: 1140px;
  margin: 0 auto;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  padding: 11px 28px;   /* short strip — was a 26px-tall card */
}
.cta-text { flex: 1 1 auto; min-width: 0; }   /* min-width:0 lets the desc ellipsis instead of forcing the bar taller */
.cta-title {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: 20px;       /* one notch smaller (was 22) */
  line-height: 1.3;      /* fixed line box so the CJK title isn't taller than the Latin one */
  letter-spacing: -0.01em;
  color: var(--text-0);
  margin: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.cta-desc {
  font-family: var(--font-ui);
  font-size: 13px;
  font-weight: 300;
  line-height: 1.4;
  color: var(--text-2);
  margin: 3px 0 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.cta-btn {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  gap: 9px;
  padding: 9px 16px;
  font-family: var(--font-mono);
  font-size: 13px;
  letter-spacing: 0.01em;
  color: var(--bg-0);
  background: var(--accent);
  border: 1px solid var(--accent);
  border-radius: 9px;
  text-decoration: none;
  transition: transform 0.16s, box-shadow 0.16s, filter 0.16s;
}
.cta-btn:hover {
  transform: translateY(-2px);
  filter: brightness(1.06);
  box-shadow: 0 8px 24px -12px var(--accent);
}
.cta-gh { width: 16px; height: 16px; flex: 0 0 auto; }
