/* Reset + base typography (§2 DESIGN_SYSTEM.md) */
* { box-sizing: border-box; }

/* Bug fix (VPS render, 2026-09-26): the UA stylesheet's `[hidden]{display:none}`
   has the same specificity as a class selector, so an author rule like
   `.operator-bar{display:flex}` coming later in the sheet wins even while the
   [hidden] attribute is set — the operator bar showed for non-operators.
   Force it explicitly, everywhere, regardless of source order. */
[hidden] { display: none !important; }

html, body {
  margin: 0;
  padding: 0;
  background: var(--bg);
  color: var(--text);
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", sans-serif;
  font-size: 15px;
  line-height: 1.4;
  overflow-x: hidden;
  max-width: 100vw;
  -webkit-tap-highlight-color: transparent;
}

button, input, select { font-family: inherit; }

.tabular { font-variant-numeric: tabular-nums; font-feature-settings: "tnum" 1; }

.app {
  padding: var(--sp-2) var(--sp-3) calc(76px + env(safe-area-inset-bottom));
  min-height: 100vh;
  padding-top: calc(var(--sp-2) + env(safe-area-inset-top));
}

/* Plain-browser / demo-preview fallback for MainButton/SecondaryButton —
   Telegram itself renders these natively, so these stay empty inside a
   real Mini App. Fixed above the tab bar so they behave like the native
   buttons they stand in for. */
/* CRITIQUE_c4.md #9: outside real Telegram (this HTML fallback stands in
   for the native MainButton/SecondaryButton), the CTA used to float with no
   visual connection to the scrolling content above it — e.g. Actor Detail's
   "Open in Apify Store" reading as an isolated orphan below ~55% of empty
   viewport. A thin footer chrome (top border + matching bg) tethers it to
   the bottom of the screen the same way a native app's sticky action bar
   would, instead of looking like a button that landed there by accident. */
.fallback-btn-holder {
  position: fixed;
  left: 0; right: 0;
  bottom: calc(56px + env(safe-area-inset-bottom));
  padding: 6px var(--sp-3) 0;
  z-index: 9;
  background: var(--bg);
  border-top: 1px solid var(--section-separator);
}
.fallback-btn-holder:empty { display: none; border-top: none; background: none; padding: 0; }
.fallback-btn-holder + .fallback-btn-holder { bottom: calc(114px + env(safe-area-inset-bottom)); }

.large-font, .large-font .row-title, .large-font .card-big { font-size: 1.2em; }
.large-font .micro, .large-font .tab span:last-child { font-size: 11px; }

/* Skeleton (§7.15) — holds layout, never a spinner */
.skeleton-card {
  height: 64px;
  border-radius: var(--r-md);
  background: linear-gradient(90deg, var(--secondary-bg) 25%, rgba(127, 127, 127, 0.12) 37%, var(--secondary-bg) 63%);
  background-size: 400% 100%;
  animation: shimmer 1.4s ease infinite;
  margin-bottom: var(--sp-2);
}
@media (prefers-reduced-motion: reduce) {
  .skeleton-card { animation-duration: 2.4s; }
}
@keyframes shimmer {
  0% { background-position: 100% 50%; }
  100% { background-position: 0 50%; }
}

@keyframes fadeIn {
  from { opacity: 0; transform: translateY(4px); }
  to { opacity: 1; transform: translateY(0); }
}
.fade-in, .fadeIn { animation: fadeIn var(--m-swap) var(--ease-standard) both; }

@keyframes swapIn {
  from { opacity: 0; transform: translateY(6px); }
  to { opacity: 1; transform: translateY(0); }
}
.screen-root { animation: swapIn var(--m-swap) var(--ease-standard) both; }

/* CRITIQUE_c4.md #3/#6: --m-push existed as a token but nothing referenced
   `.push-in`, and `.screen-root`'s own swapIn never retriggers on a plain
   innerHTML swap (an `animation` bound to a class that's never removed/
   re-added doesn't restart) — main.js now forces a reflow and applies one
   of these two directional classes on every tab switch / push / pop. */
@keyframes pushIn {
  from { opacity: 0; transform: translateX(24px); }
  to { opacity: 1; transform: translateX(0); }
}
@keyframes popIn {
  from { opacity: 0; transform: translateX(-24px); }
  to { opacity: 1; transform: translateX(0); }
}
.screen-root.push-in { animation: pushIn var(--m-push) var(--ease-standard) both; }
.screen-root.pop-in { animation: popIn var(--m-push) var(--ease-standard) both; }

::selection { background: color-mix(in srgb, var(--brand-accent) 30%, transparent); }
