/* ================================================================
   asAi app shell (2026-11)

   The layer shared by every customer page: motion tokens, press feedback,
   skeletons, cross-document view transitions, the labelled phone tab bar,
   paged and compact request logs, and the top-up tabs and checkout dock.

   Loaded after app.css, theme.css and theme-dark.css, so the rules here
   win at equal specificity. New shell styling goes in this file, not in
   the app.css monolith.
   ================================================================ */

:root {
  --ease-out: cubic-bezier(0.23, 1, 0.32, 1);
  --ease-in-out: cubic-bezier(0.77, 0, 0.175, 1);
  --dur-press: 140ms;
  --dur-ui: 200ms;
  --skeleton-fill: rgba(25, 28, 31, 0.07);
  --tabbar-h: 62px;
}
html[data-theme="dark"] { --skeleton-fill: rgba(233, 238, 246, 0.08); }

/* ---------- Press feedback: the interface heard the tap ---------- */
.nav-tab, .range-tab, .topup-tab, .balance-pill, .filter-chip, .log-toggle,
.nav-more-toggle, .nav-more-item, .getting-started-steps .button {
  transition-property: background-color, color, border-color, box-shadow, transform;
  transition-duration: var(--dur-press);
  transition-timing-function: var(--ease-out);
}
.nav-tab:active, .range-tab:active, .topup-tab:active, .balance-pill:active,
.filter-chip:active, .log-toggle:active, .nav-more-toggle:active { transform: scale(0.97); }

/* ---------- Skeletons: reserve the real size, never show a fake zero ---------- */
@keyframes shell-pulse { from { opacity: 1; } to { opacity: 0.45; } }
.shell-skeleton-fill,
#side-balance.is-pending::before,
[aria-busy="true"] .stat-value:empty::before,
[aria-busy="true"] .stat-sub:empty::before,
[aria-busy="true"] .metric-cell strong:empty::before,
.chart-skeleton,
.list-skeleton span {
  background: var(--skeleton-fill);
  animation: shell-pulse 900ms ease-in-out infinite alternate;
}
/* A non-breaking space keeps the text line box, so the value lands in place. */
#side-balance.is-pending::before,
[aria-busy="true"] .stat-value:empty::before,
[aria-busy="true"] .stat-sub:empty::before,
[aria-busy="true"] .metric-cell strong:empty::before {
  content: "\00a0";
  display: inline-block;
  border-radius: 6px;
}
#side-balance.is-pending::before { width: 9ch; border-radius: 4px; }
[aria-busy="true"] .stat-value:empty::before { width: 5.5ch; }
[aria-busy="true"] .stat-sub:empty::before { width: 11ch; }
[aria-busy="true"] .metric-cell strong:empty::before { width: 4.5ch; }
.verification-badge.is-pending { min-width: 88px; min-height: 31px; background: var(--skeleton-fill); border-color: transparent; }
.chart-skeleton { height: 230px; border-radius: var(--r-md); }
.list-skeleton { display: grid; gap: 8px; }
.list-skeleton span { display: block; height: 44px; border-radius: var(--r-md); }
.list-skeleton span:nth-child(2n) { opacity: 0.8; }
.tier-achievement.is-loading > * { opacity: 0.55; }
/* Loaded heights with real data (1440 / 390 px), so arrival never pushes. */
.tier-achievement.is-loading { min-height: 221px; }
.credit-expiry-banner.is-loading { min-height: 73px; }
@media (max-width: 640px) {
  .tier-achievement.is-loading { min-height: 249px; }
  .credit-expiry-banner.is-loading { min-height: 115px; }
}
.balance-pill .pill-value { display: inline-block; min-width: 9ch; text-align: right; }

/* Chart range switch: keep the old series, dimmed, then fade the new one in. */
.chart-panel .usage-chart { transition: opacity var(--dur-ui) var(--ease-out); }
.chart-panel[aria-busy="true"] .usage-chart { opacity: 0.5; }
.chart-panel .usage-chart > svg { animation: shell-fade-in 220ms var(--ease-out); }
@keyframes shell-fade-in { from { opacity: 0; } to { opacity: 1; } }

/* ---------- Cross-document view transitions ---------- */
@view-transition { navigation: auto; }
.topnav { view-transition-name: site-header; }
::view-transition-group(site-header) { animation-duration: 0s; }
::view-transition-old(site-header), ::view-transition-new(site-header) { animation-duration: 120ms; }
::view-transition-old(root) { animation: 140ms var(--ease-out) both shell-vt-out; }
::view-transition-new(root) { animation: 200ms var(--ease-out) both shell-vt-in; }
@keyframes shell-vt-out { to { opacity: 0; } }
@keyframes shell-vt-in { from { opacity: 0; transform: translateY(6px); } }

@media (prefers-reduced-motion: reduce) {
  @view-transition { navigation: none; }
  .shell-skeleton-fill,
  #side-balance.is-pending::before,
  [aria-busy="true"] .stat-value:empty::before,
  [aria-busy="true"] .stat-sub:empty::before,
  [aria-busy="true"] .metric-cell strong:empty::before,
  .chart-skeleton, .list-skeleton span { animation: none; }
  .chart-panel .usage-chart > svg { animation: none; }
  .nav-tab:active, .range-tab:active, .topup-tab:active, .balance-pill:active,
  .filter-chip:active, .log-toggle:active, .nav-more-toggle:active { transform: none; }
}

/* ---------- App header: "More" menu (phones only) ---------- */
.nav-more { display: none; position: relative; }
.nav-more-toggle {
  display: inline-flex; align-items: center; justify-content: center;
  width: 44px; height: 44px; border-radius: var(--r-md);
  color: var(--text); cursor: pointer; list-style: none;
}
.nav-more-toggle::-webkit-details-marker { display: none; }
.nav-more-toggle svg { width: 22px; height: 22px; }
.nav-more-toggle:hover, .nav-more[open] .nav-more-toggle { background: var(--surface-hover); }
.nav-more-toggle:focus-visible { outline: 2px solid var(--accent-strong); outline-offset: 2px; }
.nav-more-panel {
  position: absolute; right: 0; top: calc(100% + 6px); z-index: 230;
  display: grid; min-width: 220px; padding: 6px;
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-lg);
  box-shadow: 0 16px 40px rgba(25, 28, 31, 0.14);
  transform-origin: top right;
}
.nav-more[open] .nav-more-panel { animation: shell-pop 160ms var(--ease-out); }
@keyframes shell-pop { from { opacity: 0; transform: translateY(-4px) scale(0.97); } }
.nav-more-panel a, .nav-more-item {
  display: flex; align-items: center; gap: 6px; min-height: 44px; padding: 0 12px;
  border: 0; border-radius: var(--r-md); background: none; color: var(--text);
  font: 600 15px var(--font-sans); text-align: left; text-decoration: none; cursor: pointer;
}
.nav-more-panel a:hover, .nav-more-item:hover { background: var(--surface-hover); }
.nav-more-panel a:focus-visible, .nav-more-item:focus-visible { outline: 2px solid var(--accent-strong); outline-offset: -2px; }
.nav-more-item[data-sign-out] { border-top: 1px solid var(--line); border-radius: 0 0 var(--r-md) var(--r-md); margin-top: 4px; }
@media (prefers-reduced-motion: reduce) { .nav-more[open] .nav-more-panel { animation: none; } }

/* ---------- Phones: labelled bottom tab bar for the app ---------- */
@media (max-width: 720px) {
  .topnav.app-topnav {
    flex-wrap: nowrap; height: 56px; min-height: 0; padding: 0 12px 0 16px; row-gap: 0;
    /* backdrop-filter would make the header the containing block of the
       fixed tab bar and pin it to the top; an opaque header avoids that. */
    -webkit-backdrop-filter: none; backdrop-filter: none; background: var(--surface);
  }
  html[data-theme="dark"] .topnav.app-topnav { background: var(--bg-deep); }
  .app-topnav .nav-right { order: 0; margin-left: auto; gap: 6px; }
  .app-topnav .brand { order: -1; }
  .app-topnav .nav-right > .theme-toggle,
  .app-topnav .nav-right > #sign-out,
  .app-topnav .verification-badge { display: none; }
  .app-topnav .nav-more { display: block; }
  .app-topnav .balance-pill { padding: 6px 12px; }
  .app-topnav .balance-pill .pill-value { min-width: 0; }
  .app-topnav .main-nav {
    position: fixed; left: 0; right: 0; bottom: 0; z-index: 220; order: 0;
    display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); grid-auto-flow: row;
    width: auto; gap: 2px; overflow: visible;
    padding: 6px 6px calc(6px + env(safe-area-inset-bottom));
    background: var(--surface); border: 0; border-top: 1px solid var(--line); border-radius: 0;
    view-transition-name: app-tabbar;
  }
  html[data-theme="dark"] .app-topnav .main-nav { background: var(--bg-deep); }
  .app-topnav .main-nav .nav-tab-secondary { display: none; }
  .app-topnav .main-nav .nav-tab {
    flex-direction: column; justify-content: center; gap: 3px;
    min-height: 50px; padding: 4px 0; border-radius: var(--r-md);
    color: var(--text-muted); box-shadow: none;
  }
  .app-topnav .main-nav .nav-tab svg { width: 21px; height: 21px; opacity: 1; }
  .app-topnav .main-nav .nav-tab .nav-label { display: block; font-size: 11px; font-weight: 600; line-height: 1.2; }
  .app-topnav .main-nav .nav-tab.active { color: var(--accent-deep); background: var(--accent-tint); box-shadow: none; }
  html[data-theme="dark"] .app-topnav .main-nav .nav-tab.active { color: var(--accent); background: var(--accent-tint); }
  body:is([data-page="dashboard"], [data-page="models"], [data-page="keys"], [data-page="topup"], [data-page="logs"]) {
    padding-bottom: calc(var(--tabbar-h) + env(safe-area-inset-bottom));
  }
  ::view-transition-group(app-tabbar) { animation-duration: 0s; }
}

/* ---------- Public pages: one nav, mobile menu everywhere ---------- */
@media (max-width: 920px) {
  body:is([data-page="pricing"], [data-page="seo-landing"]) .nav-menu-toggle {
    display: inline-flex; align-items: center; justify-content: center;
    width: 44px; height: 44px; padding: 0; margin-right: -8px;
    border: 0; border-radius: var(--r-md); background: transparent; color: var(--text); cursor: pointer;
  }
  body:is([data-page="pricing"], [data-page="seo-landing"]) .nav-menu-toggle:focus-visible { outline: 2px solid var(--accent-strong); outline-offset: 2px; }
  body:is([data-page="pricing"], [data-page="seo-landing"]) .nav-menu-panel:not([hidden]) {
    display: grid; gap: 12px; position: absolute; top: 100%; left: 0; right: 0;
    padding: 12px 18px 20px; background: var(--surface); border-bottom: 1px solid var(--line);
    box-shadow: 0 16px 32px rgba(25, 28, 31, .08); animation: nav-menu-in 180ms var(--ease-out);
  }
}
@media (max-width: 640px) {
  body:is([data-page="pricing"], [data-page="seo-landing"]) .nav-right .nav-signin { display: inline-flex; }
  body:is([data-page="pricing"], [data-page="seo-landing"]) .nav-right .nav-register { display: none; }
  body:is([data-page="pricing"], [data-page="seo-landing"]) .nav-right .button { min-height: 44px; padding: 0 12px; font-size: 14px; }
}
.home-nav a[aria-current="page"] { color: var(--accent-deep); }
/* Footer links wrap on every public page (pricing overflowed to 407 px). */
.foot-links { flex-wrap: wrap; row-gap: 10px; }

/* Signed-in visitors on public pages: no "Sign in", one "Open dashboard". */
html[data-signed-in] .topnav:not(.app-topnav) a[href="/login"] { display: none !important; }
html[data-signed-in]:not([data-shell-ready]) .topnav:not(.app-topnav) :is(.nav-register, .nav-menu-cta) { visibility: hidden; }
@media (max-width: 640px) {
  html[data-signed-in] body .topnav:not(.app-topnav) .nav-right .nav-register { display: inline-flex; min-height: 40px; padding: 0 10px; font-size: 13px; }
  html[data-signed-in] body .topnav:not(.app-topnav) .brand-logo-full { width: 104px; }
  /* Keep the homepage controls inside the header even at 320px. The base
     public nav wraps, but its fixed 60px height leaves row two outside it. */
  body[data-page="home"] .topnav:not(.app-topnav) {
    flex-wrap: nowrap;
    height: 64px;
    min-height: 64px;
    padding-inline: 10px;
    gap: 4px;
  }
  html[data-signed-in] body[data-page="home"] .topnav:not(.app-topnav) .brand-logo-full,
  body[data-page="home"] .topnav:not(.app-topnav) .brand-logo-full { width: clamp(76px, 25vw, 104px); }
  body[data-page="home"] .topnav:not(.app-topnav) .nav-right { flex: 0 0 auto; gap: 4px; min-width: 0; }
  body[data-page="home"] .topnav:not(.app-topnav) .nav-right .button { padding-inline: 7px; font-size: 12px; }
  body[data-page="home"] .topnav:not(.app-topnav) .nav-menu-toggle { margin-right: 0; }
}
@media (max-width: 360px) {
  body[data-page="home"] .topnav:not(.app-topnav) { padding-inline: 6px; gap: 2px; }
  html[data-signed-in] body[data-page="home"] .topnav:not(.app-topnav) .brand-logo-full,
  body[data-page="home"] .topnav:not(.app-topnav) .brand-logo-full { width: 80px; }
  body[data-page="home"] .topnav:not(.app-topnav) .nav-right { gap: 2px; }
  body[data-page="home"] .topnav:not(.app-topnav) .lang-btn { padding-inline: 4px; font-size: 11px; }
  body[data-page="home"] .topnav:not(.app-topnav) .nav-right .button { padding-inline: 5px; font-size: 11px; }
}
/* ---------- Dashboard ---------- */
/* The announcement carousel sits at the top, under the nav. Until it loads,
   hold its space with a skeleton: the height measured on an earlier visit,
   else the usual two-slide carousel (slide min-height + controls + border). */
.topup-bonus-announcement.is-reserving {
  min-height: 138px;
  background: var(--skeleton-fill);
  border-color: transparent;
  box-shadow: none;
  animation: shell-pulse 900ms ease-in-out infinite alternate;
}
@media (max-width: 640px) { .topup-bonus-announcement.is-reserving { min-height: 242px; } }
@media (prefers-reduced-motion: reduce) { .topup-bonus-announcement.is-reserving { animation: none; } }
/* Phones: the hero sub-line grows to two lines once the expiry date lands. */
@media (max-width: 640px) {
  .stats-grid .stat-card .stat-sub { align-items: flex-start; line-height: 1.35; min-height: calc(2em * 1.35); }
}
.getting-started { margin-bottom: 22px; }
.getting-started-steps { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px; margin: 0; padding: 0 20px 20px; list-style: none; }
.getting-started-steps li {
  display: grid; grid-template-columns: auto 1fr; align-content: start; gap: 6px 12px;
  padding: 16px; border: 1px solid var(--line); border-radius: var(--r-lg); background: var(--surface);
}
.getting-started-steps .step-mark {
  display: inline-flex; align-items: center; justify-content: center; width: 28px; height: 28px;
  border-radius: var(--r-full); background: var(--accent-tint); color: var(--accent-deep); font-weight: 700; font-size: 13px;
}
.getting-started-steps strong { font-size: 15px; }
.getting-started-steps p { margin: 4px 0 0; color: var(--text-secondary); font-size: 13px; line-height: 1.5; }
.getting-started-steps .button { grid-column: 2; justify-self: start; margin-top: 6px; }
.getting-started-steps li.is-done { background: var(--surface-hover); }
.getting-started-steps li.is-done .step-mark { background: var(--success-bg); color: var(--success); }
.getting-started-steps li.is-done strong { color: var(--text-secondary); }
.getting-started-steps li.is-done .button { display: none; }
.dashboard.is-new-account .metrics-strip { display: none; }
@media (max-width: 900px) { .getting-started-steps { grid-template-columns: 1fr; } }
@media (max-width: 640px) { .getting-started-steps { padding: 0 14px 14px; } }

/* ---------- Request log: 25-row pages, compact phone rows ---------- */
.log-pager { display: flex; align-items: center; justify-content: flex-end; gap: 10px; padding: 14px 18px 4px; }
.log-pager.hidden { display: none; }
.log-page-status { color: var(--text-muted); font-size: 13px; font-variant-numeric: tabular-nums; min-width: 9ch; text-align: center; }
#request-log .log-toggle-cell { display: none; }
.log-toggle {
  border: 1px solid var(--line); border-radius: var(--r-full); background: var(--surface);
  color: var(--text-secondary); font: 600 12px var(--font-sans); padding: 6px 12px; min-height: 32px; cursor: pointer;
}
.log-toggle:focus-visible { outline: 2px solid var(--accent-strong); outline-offset: 2px; }
@media (max-width: 720px) {
  #request-log .log-table tbody tr {
    grid-template-columns: minmax(0, 1fr) auto;
    grid-template-areas: "time status" "model credits" "toggle toggle";
    gap: 2px 12px; padding: 12px 14px;
  }
  #request-log .log-table td { padding: 0; }
  #request-log .log-table td::before { display: none; }
  #request-log .log-table td:nth-child(1) { grid-area: time; color: var(--text-muted); font-size: 12px; }
  #request-log .log-table td:nth-child(2) { grid-area: model; font-size: 13px; }
  #request-log .log-table td:nth-child(3) { grid-area: status; justify-self: end; }
  #request-log .log-table td:nth-child(8) { grid-area: credits; justify-self: end; max-width: 36vw; text-align: right; }
  #request-log .log-table td:is(:nth-child(4), :nth-child(5), :nth-child(6), :nth-child(7)) { display: none; }
  #request-log .log-table td.log-toggle-cell { display: block; grid-area: toggle; margin-top: 8px; }
  #request-log .log-table tr.is-open {
    grid-template-areas: "time status" "model credits" "in out" "cached latency" "toggle toggle";
  }
  #request-log .log-table tr.is-open td:is(:nth-child(4), :nth-child(5), :nth-child(6), :nth-child(7)) {
    display: block; margin-top: 8px; font-size: 13px;
  }
  #request-log .log-table tr.is-open td:is(:nth-child(4), :nth-child(5), :nth-child(6), :nth-child(7))::before {
    display: block; content: attr(data-label); margin-bottom: 2px; font: 500 11px/1.4 var(--font-sans); color: var(--text-muted);
  }
  #request-log .log-table tr.is-open td:nth-child(4) { grid-area: in; }
  #request-log .log-table tr.is-open td:nth-child(5) { grid-area: out; }
  #request-log .log-table tr.is-open td:nth-child(6) { grid-area: cached; }
  #request-log .log-table tr.is-open td:nth-child(7) { grid-area: latency; }
  .log-pager { justify-content: space-between; padding: 12px 14px 4px; }
}

/* ---------- Home catalog (phones): eight models, then "Show all" ---------- */
.catalog-more { display: none; }
@media (max-width: 640px) {
  .public-catalog.is-collapsed .catalog-row:nth-child(n+9) { display: none; }
  .public-catalog.is-collapsed .catalog-more { display: inline-flex; width: 100%; justify-content: center; margin-top: 12px; min-height: 48px; }
}

/* ---------- Models (phones): one model, two lines ---------- */
@media (max-width: 640px) {
  .model-row.compact-model-row {
    grid-template-columns: repeat(3, auto) minmax(0, 1fr);
    grid-template-areas: "id id id id" "in cache out status";
    gap: 4px 16px; min-height: 0; padding: 10px 16px 12px;
  }
  .model-row.compact-model-row > div:first-child { grid-area: id; grid-column: 1 / -1; }
  .model-row.compact-model-row > .model-cell:nth-of-type(5) { grid-area: in; }
  .model-row.compact-model-row > .model-cell:nth-of-type(6) { grid-area: cache; }
  .model-row.compact-model-row > .model-cell:nth-of-type(7) { grid-area: out; display: grid; }
  .model-row.compact-model-row > .status-cell { grid-area: status; grid-column: auto; display: flex; justify-self: end; align-self: end; gap: 6px; }
  .model-row.compact-model-row > .status-cell::before { display: none; }
}

/* ---------- Top-up: tabs and checkout dock ---------- */
.topup-tabs {
  display: inline-flex; gap: 2px; margin: 0 0 16px; padding: 4px;
  border: 1px solid var(--line); border-radius: var(--r-lg); background: var(--surface-hover);
}
.topup-tab {
  min-height: 40px; padding: 0 16px; border: 0; border-radius: var(--r-md);
  background: transparent; color: var(--text-secondary); font: 600 14px var(--font-sans); cursor: pointer;
}
.topup-tab:hover { color: var(--text); }
.topup-tab[aria-selected="true"] { background: var(--surface); color: var(--accent-deep); box-shadow: 0 1px 2px rgba(25, 28, 31, 0.08); }
html[data-theme="dark"] .topup-tab[aria-selected="true"] { color: var(--accent); }
.topup-tab:focus-visible { outline: 2px solid var(--accent-strong); outline-offset: 2px; }
.topup-panel { display: grid; gap: 16px; }
.topup-panel[hidden] { display: none; }
.topup-panel:not([hidden]) { animation: shell-fade-in 180ms var(--ease-out); }
.checkout-dock { display: grid; gap: 12px; }
@media (max-width: 720px) {
  .topup-tabs { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); width: 100%; }
  .topup-tab { padding: 0 8px; }
  /* Total and Continue stay in reach while packs and payment are chosen. */
  .checkout-dock {
    position: sticky; z-index: 5;
    bottom: calc(var(--tabbar-h) + env(safe-area-inset-bottom) + 8px);
    margin-inline: -4px; padding: 12px;
    background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-lg);
    box-shadow: 0 -8px 24px rgba(25, 28, 31, 0.08);
  }
  .checkout-dock .checkout-price-summary { margin: 0; }
  .checkout-dock #continue-purchase { width: 100%; }
}
@media (prefers-reduced-motion: reduce) { .topup-panel:not([hidden]) { animation: none; } }
