/* =============================================================================
   asher-appshell-2026-08-25  —  SHARED APP SHELL for the signed-in surfaces
   (members, account, login, autopilot, copilot, live, launch-configs,
    running-configs, affiliate, success, asher-connected, builder, strategy,
    strategy-lab, strategy-studio, sweep-results)

   PURPOSE: make asherlabs.ai FEEL like an installed app on phones and tablets —
   bottom tab bar, safe-area insets, dvh sizing, momentum scrolling, native tap
   feel — WITHOUT changing a single pixel of the desktop layout.

   DESKTOP CONTRACT — every rule in this file is one of:
     (a) inside a `@media (max-width:…)` query, or
     (b) applied to an `.ashell-*` class name. Those names appear NOWHERE in
         public/ (measured: 0 hits across every html/css/js/json/svg file) and
         are only ever put on elements asher-app.js creates; those elements are
         `display:none` until a max-width query turns them on.

   It does NOT restate or override anything from the earlier mobile passes
   (`asher-mobile-pass-2026-08-25`, `asher-mobile-qa2-2026-08-25`,
   `asher-mobile-qa3-2026-08-25`). It is purely additive on top of them.

   ⛔ ONE TRAP THIS FILE DELIBERATELY AVOIDS: these pages write their overlay
   padding as a `padding:Npx` SHORTHAND (.modal 22px/20px, #ov 14px …). This
   stylesheet loads LAST, so a bare `padding-left:env(safe-area-inset-left)`
   from here would WIN over the shorthand and zero their left/right padding on
   every phone — the exact class of bug the previous mobile pass had to repair.
   So safe-area gutters are set on <body> only, which was measured to declare
   no padding of its own in any of the 16 pages.
   ============================================================================= */


/* ---------------------------------------------------------------------------
   1. TOKENS + DEFAULT-OFF  (base rules — `.ashell-*` only, see contract)
   --------------------------------------------------------------------------- */
.ashell-tabbar,
.ashell-tabspacer,
.mnav-btn,
.mnav-panel { display: none; }

:root {
  /* Custom properties named --ashell-* appear nowhere else in public/ and a
     custom property renders nothing on its own, so declaring them at :root is a
     no-op. They live here (not on .ashell-tabbar) so the bar and its spacer read
     the SAME height — a token defined on the bar would not reach its sibling,
     and the two would drift apart silently. */
  --ashell-h: 54px;
}

.ashell-tabbar {
  /* Self-contained palette. The 16 pages carry four different variable sets
     (--txt / --text / --ink / --mut / --muted …), so the bar owns its own and
     never depends on the host page's names. Dark is the default because six of
     these pages have NO light theme at all — reacting to prefers-color-scheme
     would turn the bar white on a dark-only page. Only the site's own
     `data-theme="light"` (the sp_theme toggle) switches it. */
  --ashell-bg:       rgba(11, 14, 21, .90);
  --ashell-bg-solid: #0b0e15;
  --ashell-line:     #222c3a;
  --ashell-ink:      #7e8b9c;
  --ashell-active:   #ff8a1f;
}
html[data-theme="light"] .ashell-tabbar {
  --ashell-bg:       rgba(255, 255, 255, .92);
  --ashell-bg-solid: #ffffff;
  --ashell-line:     #dbe1ea;
  --ashell-ink:      #5d6b7c;
  --ashell-active:   #c96a09;
}


/* ---------------------------------------------------------------------------
   2. BOTTOM TAB BAR — phones only (≤767px)
   This never REPLACES a nav: every existing link, menu and button on every page
   stays exactly where it is. It is an added shortcut rail, so nothing that is
   reachable today becomes unreachable, and every tab points at a real page.
   --------------------------------------------------------------------------- */
@media (max-width: 767px) {

  html.ashell-tabs .ashell-tabbar {
    display: flex;
    position: fixed;
    left: 0; right: 0; bottom: 0;
    /* MEASURED z-index landscape across these 16 pages: ordinary content tops
       out at 12, sticky chrome (.nav, .thead, #ov) at 50, and every overlay
       starts at 60 and climbs (.modal 60/999, .chartfs.sp-maxed 900,
       .wire-reader 200, #symov/.tfmenu 2000, .ctxmenu 3000).
       45 puts the bar over all page content and UNDER every one of those
       overlays — which is also how a native tab bar behaves: a modal sheet
       covers it. A high value here would have parked the bar on top of modal
       action buttons on a phone, i.e. hidden a control. */
    z-index: 45;
    align-items: stretch;
    background: var(--ashell-bg-solid);
    border-top: 1px solid var(--ashell-line);
    /* the home-indicator gutter — the reason viewport-fit=cover is switched on */
    padding-bottom: env(safe-area-inset-bottom);
    padding-left:   env(safe-area-inset-left);
    padding-right:  env(safe-area-inset-right);
    -webkit-tap-highlight-color: transparent;
    -webkit-user-select: none;
    user-select: none;            /* chrome only — never prose/prices/keys */
    touch-action: manipulation;
    box-shadow: 0 -8px 22px -14px rgba(0, 0, 0, .9);
  }
  @supports ((-webkit-backdrop-filter: blur(1px)) or (backdrop-filter: blur(1px))) {
    html.ashell-tabs .ashell-tabbar {
      background: var(--ashell-bg);
      -webkit-backdrop-filter: saturate(160%) blur(16px);
      backdrop-filter: saturate(160%) blur(16px);
    }
  }

  .ashell-tab {
    flex: 1 1 0;
    min-width: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 3px;
    height: var(--ashell-h);       /* ≥44px touch target */
    min-height: 44px;
    padding: 4px 2px 5px;
    position: relative;
    color: var(--ashell-ink);
    text-decoration: none;
    font: 600 10px/1.1 system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
    letter-spacing: .2px;
    -webkit-tap-highlight-color: transparent;
    touch-action: manipulation;
    transition: color .12s ease, transform .09s ease;
  }
  .ashell-tab svg { width: 22px; height: 22px; display: block; flex: 0 0 auto; }
  .ashell-tab .ashell-tab-l {
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  .ashell-tab:active { transform: scale(.93); }

  .ashell-tab[aria-current="page"] { color: var(--ashell-active); }
  .ashell-tab[aria-current="page"]::before {
    content: "";
    position: absolute;
    top: 0;
    left: 50%;
    transform: translateX(-50%);
    width: 26px;
    height: 2.5px;
    border-radius: 0 0 3px 3px;
    background: var(--ashell-active);
  }

  /* Clearance so the bar never covers the last row of a page. Applied to the
     spacer element asher-app.js appends to <body> rather than to body padding:
     two of these pages set body{overflow:hidden} with a 100vh shell, where a
     body padding would have done nothing. Those pages get their own `calc()`
     rule in their inline `asher-appshell-2026-08-25` block. */
  html.ashell-tabs .ashell-tabspacer {
    display: block;
    width: 100%;
    height: calc(var(--ashell-h, 54px) + env(safe-area-inset-bottom));
    flex: 0 0 auto;
    pointer-events: none;
  }

  /* Never inside an embed — asher-connected.html is framed by the Launch
     Configs chart modal, and a tab bar inside a chart modal is wrong.
     (asher-app.js also refuses to build when window.self !== window.top;
     this is the belt to that braces.) */
  html[data-embed] .ashell-tabbar,
  html[data-embed] .ashell-tabspacer { display: none !important; }
}


/* ---------------------------------------------------------------------------
   3. SAFE-AREA GUTTERS  (≤1024px — phones + tablets, never desktop)
   Paired with `viewport-fit=cover` in the viewport meta. Every env() value here
   is 0 on desktop and 0 in portrait on a non-notched device, so it is inert
   everywhere it is not needed. <body> was measured to declare no padding of its
   own in any of the 16 pages, so this ADDS a gutter, it never replaces one.
   --------------------------------------------------------------------------- */
@media (max-width: 1024px) {
  body {
    padding-left:  env(safe-area-inset-left);
    padding-right: env(safe-area-inset-right);
  }
}


/* ---------------------------------------------------------------------------
   4. REAL APP SCROLLING  (phones + tablets)
   --------------------------------------------------------------------------- */
@media (max-width: 1024px) {
  /* Momentum + no scroll-chaining on the horizontal rails these pages use for
     wide tables and toolbars. Without `-webkit-overflow-scrolling:touch` these
     scroll with a dead, non-inertial feel on older iOS; without
     `overscroll-behavior-x` a flick that reaches the end drags the page. */
  .tblwrap, .ledger, .acct-strip, #topbar, .rangebar, .tfbar, .cc-top, .sd-toc {
    -webkit-overflow-scrolling: touch;
    overscroll-behavior-x: contain;
  }
  /* Vertical scrollers inside the page must not drag the page behind them. */
  .lessons, .tblwrap, #positions, .wl-body, .feed, .fswatch, #right {
    overscroll-behavior-y: contain;
  }
  /* Installed / standalone only: kill the browser rubber-band and pull-to-
     refresh so the window behaves like an app window. Scoped to the class
     asher-app.js adds ONLY when display-mode is standalone, so an ordinary
     browser tab keeps pull-to-refresh. */
  html.ashell-standalone,
  html.ashell-standalone body { overscroll-behavior-y: contain; }
}


/* ---------------------------------------------------------------------------
   5. NATIVE TOUCH POLISH  (phones + tablets)
   `user-select:none` is applied to NAV CHROME ONLY. Prose, prices, percentages,
   config values, wallet addresses, API keys and every <input> stay selectable —
   those are the things people have to be able to copy.
   --------------------------------------------------------------------------- */
@media (max-width: 1024px) {
  a, button, summary, label, select,
  input[type="checkbox"], input[type="radio"], input[type="range"],
  .btn, .tile, .abtn, .tfb, .tfb-g, .chip, .pill-trades, .modrow, .li {
    -webkit-tap-highlight-color: transparent;
    touch-action: manipulation;
  }
  .nav .nav-links, .nav .nav-cta, .menu, .ashell-tabbar, .ashell-tab,
  .mnav-btn, .mnav-links, .mnav-acts {
    -webkit-user-select: none;
    user-select: none;
  }
}
@media (max-width: 767px) {
  /* iOS zooms the whole page when a text field smaller than 16px is focused,
     and never zooms back — the single most "this is a website" moment on a
     phone. 16px is the documented threshold. Text entry only: <select> is left
     alone because on these pages selects sit in compact toolbars where growing
     them costs more than the zoom does. */
  input[type="text"], input[type="email"], input[type="password"],
  input[type="search"], input[type="number"], input[type="tel"],
  input[type="url"], input:not([type]), textarea {
    font-size: max(16px, 1em);
  }
}


/* ---------------------------------------------------------------------------
   6. STICKY PAGE HEADER on the plain internal shells (phones only)
   live.html / strategy-lab.html / strategy-studio.html each have exactly one
   `body > header` bar and already paint an opaque background on it, so nothing
   shows through when it pins. Opt-in per page via the `ashell-stickyhead` class
   that asher-app.js sets from a data attribute — it is never global.
   --------------------------------------------------------------------------- */
@media (max-width: 767px) {
  html.ashell-stickyhead body > header {
    position: sticky;
    top: 0;
    z-index: 40;
  }
}


/* ---------------------------------------------------------------------------
   7. MOBILE NAV MENU (hamburger) — repairs an orphan, measured not assumed.
   MEASURED on 2026-08-25: all nine pages here that carry the site nav
   (account, login, copilot, affiliate, success, asher-connected, builder,
   strategy + members) hide their link list below 900px —
       @media(max-width:900px){ … .nav-links{display:none;} … }
   and below 640px they also hide `.nav-cta .btn:not([data-authcta])` — with NO
   hamburger anywhere in the file (`grep mnav-btn` = 0 hits in all nine). The
   hamburger built by the earlier mobile pass lives only in index.html. So on a
   phone, Home / Platform / Markets / Terminal / Wire / Strategy / Builder /
   Docs / Pricing / Company and the theme toggle were UNREACHABLE on these
   pages. This puts them back; it removes nothing.

   Class names and the look are deliberately identical to index.html's
   `asher-mobile-pass-2026-08-25` menu so the two behave the same, and
   asher-app.js will not build a second one if that script got there first.
   Everything is gated on `html.ashell-mnav`, which asher-app.js sets ONLY after
   it has actually built the menu.
   --------------------------------------------------------------------------- */
@media (max-width: 900px) {
  /* The panel is position:absolute against the nav, so the nav must be a
     positioned element wherever the button can appear. Eight of the nine navs
     are already `position:sticky;top:0;z-index:50` — this restates exactly those
     values, so for them it is a no-op; members.html's static nav becomes sticky,
     which is also what an app header should do on a phone. Deliberately done in
     CSS: setting `position:relative` from JS would outrank the stylesheet and
     un-stick the header. */
  html.ashell-mnav .nav { position: sticky; top: 0; z-index: 50; }

  html.ashell-mnav .mnav-btn {
    display: inline-flex;
    flex-direction: column;
    justify-content: center;
    gap: 4px;
    width: 44px;               /* ≥44px touch target */
    height: 44px;
    padding: 0 11px;
    flex: 0 0 auto;
    border: 1px solid var(--line-2, var(--border, #2a3644));
    border-radius: 10px;
    background: transparent;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
    touch-action: manipulation;
  }
  html.ashell-mnav .mnav-btn span {
    display: block;
    width: 100%;
    height: 2px;
    border-radius: 2px;
    background: var(--text, var(--txt, #e6edf5));
  }
  html.ashell-mnav .mnav-btn[aria-expanded="true"] {
    border-color: var(--accent, var(--gold, #ff8a1f));
  }
  /* asher-app.js stamps data-empty whenever nothing is actually hidden at the
     current width, so the button can never open an empty sheet. */
  html.ashell-mnav .mnav-btn[data-empty] { display: none; }

  html.ashell-mnav .nav.mnav-open .mnav-panel {
    display: block;
    position: absolute;
    left: 0; right: 0; top: 100%;
    z-index: 60;
    background: var(--nav, var(--surface, var(--bg, #0b0e15)));
    border-bottom: 1px solid var(--line, var(--border, #222c3a));
    box-shadow: 0 22px 46px -20px rgba(0, 0, 0, .8);
    padding: 6px 18px calc(16px + env(safe-area-inset-bottom));
    max-height: 76vh;
    overflow-y: auto;
    overscroll-behavior: contain;
    -webkit-overflow-scrolling: touch;
  }
  html.ashell-mnav .mnav-links { display: flex; flex-direction: column; }
  html.ashell-mnav .mnav-links a {
    display: flex;
    align-items: center;
    min-height: 46px;
    padding: 6px 2px;
    font-size: 16px;
    text-decoration: none;
    color: var(--muted, #8494a6);
    border-bottom: 1px solid var(--line, var(--border, #222c3a));
  }
  html.ashell-mnav .mnav-links a.active,
  html.ashell-mnav .mnav-links a[aria-current] {
    color: var(--accent, var(--gold, #ff8a1f));
  }
  html.ashell-mnav .mnav-acts {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
    margin-top: 14px;
  }
  html.ashell-mnav .mnav-acts > * {
    flex: 1 1 auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-height: 44px;
  }
}

/* members.html only. Its nav is a single non-wrapping flex row holding a 175px
   wordmark (the logo SVG is 1268×188, so height:26px ⇒ width≈175px), a four-link
   menu, the plan pill and Log out — about 620px of content on a 375px screen,
   with no rule anywhere in the file letting it wrap. It ran off the side of
   every phone. The selectors below use `.nav > .brand` / `.nav > .menu`, which
   match members.html's flat nav and CANNOT match the other eight pages, where
   the same elements sit one level deeper inside `.nav-in`.
   Log out is deliberately left IN the bar rather than cloned into the panel:
   its click handler is bound with addEventListener, which cloneNode does not
   copy, so a cloned Log out would look like a control and do nothing. */
@media (max-width: 767px) {
  html.ashell-mnav .nav {
    flex-wrap: wrap;      /* inert on the other eight: their .nav is not a flex box */
    row-gap: 8px;
    column-gap: 10px;
  }
  html.ashell-mnav .nav > .menu { display: none; }
  html.ashell-mnav .nav > .brand .brand-logo { height: 22px; }
}
