/* ============================================================
   mobile-app.css — native-feel polish for ≤ 768px ONLY
   - Desktop (≥ 769px) is NEVER touched by anything in this file
   - Adaptive: body.platform-ios → iOS look, body.platform-android → Material
   - Add-only: no rules override existing desktop styles
   ============================================================ */

/* ── Mobile-only block: everything below is wrapped ────────────── */
@media (max-width: 768px) {

  /* Native font stacks — picked per platform via body class.
     Falls back to the existing site font (Inter) if class missing. */
  body.platform-ios {
    font-family: -apple-system, BlinkMacSystemFont, "SF Pro Text",
                 "Helvetica Neue", system-ui, sans-serif;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    /* iOS-style rubber-band only on body, not nested scrollers */
    -webkit-overflow-scrolling: touch;
  }
  body.platform-android {
    font-family: Roboto, "Google Sans Text", system-ui,
                 -apple-system, "Helvetica Neue", sans-serif;
  }

  /* Safe-area insets so content/tab-bar don't sit under the notch
     or Android gesture pill. Requires viewport-fit=cover in meta. */
  body {
    /* Reserve room for bottom tab bar (56dp android / 50pt ios + safe area) */
    padding-bottom: calc(64px + env(safe-area-inset-bottom, 0px));
  }

  /* Minimum tap targets — Apple HIG 44pt, Material 48dp.
     Only applied to in-content links/buttons; nav already sized. */
  main a:not(.logo):not(.skip-link),
  main button,
  main .home-button,
  main [role="button"] {
    min-height: 44px;
  }
  body.platform-android main a:not(.logo):not(.skip-link),
  body.platform-android main button,
  body.platform-android main .home-button,
  body.platform-android main [role="button"] {
    min-height: 48px;
  }

  /* Remove hover states on touch — replace with active feedback */
  @media (hover: none) {
    a:hover, button:hover, .home-button:hover { background: inherit; }
    a:active, button:active, .home-button:active {
      transform: scale(0.97);
      transition: transform 0.08s ease-out;
    }
  }

  /* ── Bottom tab bar ─────────────────────────────────────────── */

  .mobile-tabbar {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 990;
    display: flex;
    justify-content: space-around;
    align-items: stretch;
    padding: 6px 4px calc(6px + env(safe-area-inset-bottom, 0px));
    background: rgba(255, 255, 255, 0.92);
    backdrop-filter: saturate(180%) blur(20px);
    -webkit-backdrop-filter: saturate(180%) blur(20px);
    border-top: 0.5px solid rgba(60, 60, 67, 0.18);
    box-shadow: 0 -1px 12px rgba(17, 24, 39, 0.06);
  }

  /* Light frosted-glass tab bar is used on every page — works well over
     any background (iOS pattern). We deliberately don't switch to a dark
     variant because page theming is inconsistent (e.g. .modern-page sets
     dark accents but page-tracker/dashboard/company-match override with
     a light --bg). One bar style avoids per-page mismatches. */

  .mobile-tabbar__item {
    flex: 1 1 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 2px;
    padding: 4px 2px;
    color: #6b7280;
    text-decoration: none;
    font-size: 10px;
    font-weight: 500;
    line-height: 1.1;
    letter-spacing: 0.01em;
    min-height: 48px;
    border-radius: 10px;
    transition: color 0.15s ease, background 0.15s ease;
    -webkit-tap-highlight-color: transparent;
  }
  /* Single inactive tab colour for the single light bar style. */

  .mobile-tabbar__icon {
    font-size: 20px;
    line-height: 1;
  }

  /* Active tab — iOS uses solid colour only; Material uses pill bg */
  body.platform-ios .mobile-tabbar__item.is-active {
    color: #2563eb;
  }
  body.platform-android .mobile-tabbar__item.is-active {
    color: #1d4ed8;
    background: rgba(37, 99, 235, 0.10);
  }
  /* Default (no platform detected) — iOS-style */
  .mobile-tabbar__item.is-active {
    color: #2563eb;
  }

  .mobile-tabbar__item:active {
    transform: scale(0.94);
    transition: transform 0.06s ease-out;
  }

  /* Material ripple-ish feedback */
  body.platform-android .mobile-tabbar__item:active {
    background: rgba(37, 99, 235, 0.15);
  }

  /* iOS: slightly larger icon, SF-style label spacing */
  body.platform-ios .mobile-tabbar__icon { font-size: 22px; }
  body.platform-ios .mobile-tabbar__label { font-size: 10px; }

  /* Android: smaller icon, Material label */
  body.platform-android .mobile-tabbar__icon { font-size: 22px; }
  body.platform-android .mobile-tabbar__label {
    font-size: 11px;
    font-weight: 500;
  }

  /* ── Mobile cards: round corners + soft shadow on .home-card,
        sectioned blocks — only when not already styled darker  */
  body.platform-ios .home-card,
  body.platform-ios .card,
  body.platform-ios section.surface {
    border-radius: 14px;
  }
  body.platform-android .home-card,
  body.platform-android .card,
  body.platform-android section.surface {
    border-radius: 12px;
    box-shadow: 0 1px 3px rgba(0,0,0,0.06), 0 1px 2px rgba(0,0,0,0.04);
  }

  /* Sticky mobile app-bar — large title compresses on scroll (iOS feel).
     Opt-in via .mobile-large-title on a heading; no effect if absent. */
  body.platform-ios .mobile-large-title {
    font-size: 34px;
    line-height: 1.05;
    font-weight: 700;
    letter-spacing: -0.02em;
    padding: 8px 4px 12px;
  }

  /* Disable text selection in tab bar (feels like a button, not text) */
  .mobile-tabbar, .mobile-tabbar * {
    -webkit-user-select: none;
    user-select: none;
  }

  /* Push fixed-bottom UI above the tab bar so they aren't hidden by
     or overlapping with it. Covers all the known cases:
     - .home-toast-stack (homepage)
     - .util-toast-stack (global)
     - #frToast (fix-resume.html inline toast)
     - #sw-update-banner (service-worker update banner, all pages) */
  .home-toast-stack,
  .util-toast-stack,
  #frToast,
  #sw-update-banner {
    bottom: calc(72px + env(safe-area-inset-bottom, 0px)) !important;
  }

  /* ── Page transitions (View Transitions API) ────────────────────
     Mobile-only. The `@view-transition { navigation: auto }` rule that
     activates this is injected by mobile-app.js when on a mobile
     viewport, so desktop never opts in. Unsupported browsers no-op.

     Defaults: cross-fade with a soft scale-up (iOS-like).
     With JS-tagged transition types `forward` / `back`, swap to a
     directional slide that matches native push/pop. */

  ::view-transition-old(root),
  ::view-transition-new(root) {
    animation-duration: 0.28s;
    animation-timing-function: cubic-bezier(0.22, 0.61, 0.36, 1);
  }
  ::view-transition-old(root) {
    animation-name: mob-fade-out;
  }
  ::view-transition-new(root) {
    animation-name: mob-fade-in;
  }

  /* Forward (new page pushed in from right) */
  :root:active-view-transition-type(forward)::view-transition-old(root) {
    animation-name: mob-slide-out-left;
  }
  :root:active-view-transition-type(forward)::view-transition-new(root) {
    animation-name: mob-slide-in-right;
  }
  /* Back (popping — old slides off to right, new comes from left) */
  :root:active-view-transition-type(back)::view-transition-old(root) {
    animation-name: mob-slide-out-right;
  }
  :root:active-view-transition-type(back)::view-transition-new(root) {
    animation-name: mob-slide-in-left;
  }

  /* Keep the bottom tab bar visually persistent across transitions —
     name pairs it on both pages so it morphs instead of fading. */
  .mobile-tabbar {
    view-transition-name: mobile-tabbar;
  }

  /* ── Pull-to-refresh indicator ──────────────────────────────────
     A 40px disc with a spinner. Hidden by default; the JS adds
     `is-visible` while the user is dragging and `is-refreshing`
     after they release past the threshold. */

  /* Prevent native overscroll/PTR — we own this gesture now. */
  html, body {
    overscroll-behavior-y: contain;
  }

  .mobile-ptr {
    position: fixed;
    top: calc(env(safe-area-inset-top, 0px) + 8px);
    left: 50%;
    width: 40px;
    height: 40px;
    margin-left: -20px;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.96);
    box-shadow: 0 4px 14px rgba(17, 24, 39, 0.18);
    z-index: 985;
    display: flex;
    align-items: center;
    justify-content: center;
    transform: translateY(-200%);
    opacity: 0;
    pointer-events: none;
    will-change: transform, opacity;
  }
  .mobile-ptr.is-pulling {
    transition: opacity 0.12s ease;
  }
  .mobile-ptr.is-visible {
    opacity: 1;
  }
  .mobile-ptr.is-snapping {
    transition: transform 0.28s cubic-bezier(0.22, 0.61, 0.36, 1),
                opacity 0.2s ease;
  }
  .mobile-ptr__spinner {
    width: 18px;
    height: 18px;
    border: 2px solid #2563eb;
    border-top-color: transparent;
    border-radius: 50%;
  }
  .mobile-ptr.is-ready .mobile-ptr__spinner {
    border-color: #1d4ed8;
    border-top-color: transparent;
  }
  .mobile-ptr.is-refreshing .mobile-ptr__spinner {
    animation: mob-ptr-spin 0.8s linear infinite;
  }
  @keyframes mob-ptr-spin {
    to { transform: rotate(360deg); }
  }

  /* ── Bottom sheets ──────────────────────────────────────────────
     Reshape existing centered modals into iOS/Material bottom sheets
     on mobile. Three patterns exist in the codebase:
       1. .modal-overlay  + .modal-box      (Gemini buy modal etc.)
       2. .modal.active   + .modal-content  (resources/tracker modals)
       3. .util-dialog-overlay + .util-dialog (utility prompts)
     Each gets: backdrop pinned to flex-end, full-width sheet with
     top-only rounded corners, drag handle, slide-up animation, safe
     area padding at the bottom. */

  .modal-overlay,
  .modal.active,
  .util-dialog-overlay {
    align-items: flex-end !important;
    padding: 0 !important;
  }

  .modal-overlay .modal-box,
  .modal.active .modal-content,
  .util-dialog-overlay .util-dialog {
    max-width: 100% !important;
    width: 100% !important;
    border-radius: 18px 18px 0 0 !important;
    max-height: 88vh !important;
    padding-left: 1.25rem !important;
    padding-right: 1.25rem !important;
    padding-top: 1.5rem !important;
    padding-bottom: calc(1.25rem + env(safe-area-inset-bottom, 0px)) !important;
    box-shadow: 0 -8px 28px rgba(0, 0, 0, 0.35) !important;
    animation: mob-sheet-slide-up 0.32s cubic-bezier(0.22, 0.61, 0.36, 1) !important;
    position: relative;
    will-change: transform;
  }

  /* Drag handle — small grey pill at the top, native pattern. */
  .modal-overlay .modal-box::before,
  .modal.active .modal-content::before,
  .util-dialog-overlay .util-dialog::before {
    content: '';
    display: block;
    width: 36px;
    height: 4px;
    background: rgba(150, 150, 160, 0.5);
    border-radius: 2px;
    margin: -0.5rem auto 0.75rem;
    pointer-events: none;
  }

  /* The .util-dialog has an inline transform: translateY(20px) for its
     own slide animation — neutralise it so our keyframe owns the entry. */
  .util-dialog-overlay .util-dialog,
  .util-dialog-overlay.show .util-dialog {
    transform: translateY(0) !important;
  }

  /* While the user is drag-dismissing, JS sets a per-element transform
     directly — give it priority over the entrance animation. */
  .modal-overlay .modal-box.is-dragging,
  .modal.active .modal-content.is-dragging,
  .util-dialog-overlay .util-dialog.is-dragging {
    animation: none !important;
    transition: none !important;
  }
  .modal-overlay .modal-box.is-snapping,
  .modal.active .modal-content.is-snapping,
  .util-dialog-overlay .util-dialog.is-snapping {
    animation: none !important;
    transition: transform 0.22s cubic-bezier(0.22, 0.61, 0.36, 1) !important;
  }

  /* ── Skeleton loaders ───────────────────────────────────────────
     Generic shimmer block. Add `.mobile-skel` plus a size class
     (mobile-skel--card / mobile-skel--text / mobile-skel--avatar)
     to any element to render a shimmering placeholder.

     Existing per-section skeletons (news, tracker) stay untouched —
     they already use their own classes (.news-skeleton-card etc.). */
  .mobile-skel {
    position: relative;
    overflow: hidden;
    background: rgba(127, 130, 140, 0.10);
    border-radius: 10px;
  }
  .mobile-skel::after {
    content: '';
    position: absolute;
    inset: 0;
    transform: translateX(-100%);
    background: linear-gradient(
      90deg,
      transparent,
      rgba(127, 130, 140, 0.22),
      transparent
    );
    animation: mob-skel-shimmer 1.4s infinite;
  }
  .mobile-skel--card { height: 96px; border-radius: 12px; }
  .mobile-skel--text { height: 14px; border-radius: 4px; }
  .mobile-skel--text + .mobile-skel--text { margin-top: 8px; }
  .mobile-skel--avatar { width: 44px; height: 44px; border-radius: 50%; }

  .mobile-skel-list {
    display: grid;
    gap: 12px;
    padding: 4px 0;
  }

  /* Dark-page skeletons need a brighter shimmer to be visible. */
  body.modern-page .mobile-skel {
    background: rgba(255, 255, 255, 0.06);
  }
  body.modern-page .mobile-skel::after {
    background: linear-gradient(
      90deg,
      transparent,
      rgba(255, 255, 255, 0.16),
      transparent
    );
  }

  /* Mobile-only: hide the legacy Tavily spinner; the JS observer
     inserts skeleton cards alongside it. */
  .tavily-loading {
    display: none !important;
  }

  /* ── Swipe-back hint ───────────────────────────────────────────
     A circular arrow that follows the finger when the user drags
     from the left edge. JS only enables this on Android (iOS has its
     own native edge-swipe-back gesture). */
  .mobile-swipe-back-hint {
    position: fixed;
    left: 0;
    top: 50%;
    width: 44px;
    height: 44px;
    margin-top: -22px;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.96);
    box-shadow: 0 4px 14px rgba(17, 24, 39, 0.18);
    color: #2563eb;
    z-index: 988;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 18px;
    transform: translateX(-120%);
    opacity: 0;
    pointer-events: none;
    will-change: transform, opacity;
  }
  .mobile-swipe-back-hint.is-active { opacity: 1; }
  .mobile-swipe-back-hint.is-snapping {
    transition: transform 0.24s cubic-bezier(0.22, 0.61, 0.36, 1),
                opacity 0.18s ease;
  }

  /* Toast items get a horizontal drag-out cursor on touch — purely
     decorative; the JS handler applies the transform inline. */
  .home-toast,
  .util-toast {
    touch-action: pan-y;
  }

  /* ── Top app-bar (compact mobile header) ──────────────────────
     Tighten the existing .site-header on mobile and add a back
     arrow + truncated page title on inner pages. Hamburger and
     auth remain visible for nav and account access.

     We deliberately keep the existing .site-header DOM so per-page
     header colour overrides (page-tracker, page-dashboard, etc.)
     still apply. Only inject new children + override paddings. */

  .site-header .header-inner {
    padding-top: 0.45rem !important;
    padding-bottom: 0.45rem !important;
    gap: 0.4rem;
    min-height: 48px;
  }

  /* Back button — circular touch target, inherits header text color */
  .mobile-appbar-back {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 40px;
    height: 40px;
    margin-right: 0.15rem;
    border-radius: 10px;
    border: 0;
    background: transparent;
    color: inherit;
    font-size: 17px;
    cursor: pointer;
    flex-shrink: 0;
    order: -1;
    -webkit-tap-highlight-color: transparent;
  }
  .mobile-appbar-back:active {
    background: rgba(127, 127, 130, 0.14);
  }

  /* Page title — fills space between back button and right actions.
     Centered on iOS (Apple HIG), left-aligned on Material. */
  .mobile-appbar-title {
    flex: 1 1 auto;
    min-width: 0;
    font-size: 1rem;
    font-weight: 600;
    color: inherit;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    padding: 0 0.15rem;
    order: 0;
  }
  body.platform-ios .mobile-appbar-title {
    text-align: center;
  }
  body.platform-android .mobile-appbar-title {
    text-align: left;
    font-weight: 500;
  }

  /* When a back button is present, the logo is redundant — hide it.
     Page-specific selectors use !important on .logo, so we match. */
  body[data-mobile-appbar="inner"] .site-header .logo {
    display: none !important;
  }

  /* Home stays as-is: logo on left, no title, no back arrow. */

  /* Slightly tighten hamburger box on mobile so the bar feels compact. */
  .nav-hamburger {
    width: 40px !important;
    height: 40px !important;
    padding: 8px !important;
  }
}

@keyframes mob-skel-shimmer {
  100% { transform: translateX(100%); }
}

@keyframes mob-sheet-slide-up {
  from { transform: translateY(100%); }
  to { transform: translateY(0); }
}

/* Keyframes live outside the @media wrap because @keyframes can't be
   nested in some older parsers; the animations above only reference
   them inside the mobile block, so desktop never runs them. */
@keyframes mob-fade-in {
  from { opacity: 0; transform: scale(0.985); }
  to   { opacity: 1; transform: scale(1); }
}
@keyframes mob-fade-out {
  from { opacity: 1; }
  to   { opacity: 0; }
}
@keyframes mob-slide-in-right {
  from { transform: translateX(100%); }
  to   { transform: translateX(0); }
}
@keyframes mob-slide-out-left {
  from { transform: translateX(0); }
  to   { transform: translateX(-22%); opacity: 0.4; }
}
@keyframes mob-slide-in-left {
  from { transform: translateX(-22%); opacity: 0.4; }
  to   { transform: translateX(0); opacity: 1; }
}
@keyframes mob-slide-out-right {
  from { transform: translateX(0); }
  to   { transform: translateX(100%); }
}

/* Respect reduced motion — skip the slide, keep a tiny fade so the
   change of context is still perceptible. */
@media (max-width: 768px) and (prefers-reduced-motion: reduce) {
  ::view-transition-old(root),
  ::view-transition-new(root) {
    animation-duration: 0.12s;
  }
  :root:active-view-transition-type(forward)::view-transition-old(root),
  :root:active-view-transition-type(back)::view-transition-old(root) {
    animation-name: mob-fade-out;
  }
  :root:active-view-transition-type(forward)::view-transition-new(root),
  :root:active-view-transition-type(back)::view-transition-new(root) {
    animation-name: mob-fade-in;
  }
}

/* ── Mobile-only block ends here ──────────────────────────────── */

/* Above 768px: explicitly hide the tab bar even if injected, so the
   desktop view is identical to before. */
@media (min-width: 769px) {
  .mobile-tabbar { display: none !important; }
}
