/**
 * ═══════════════════════════════════════════════════════════════════
 * Explore Page Component (SPA)
 * ═══════════════════════════════════════════════════════════════════
 * 
 * Extracted from pages/explore/index.html
 * 
 * Removed:
 * - TopBar (handled by app.html)
 * - Global bottom Tab Bar on Explore (handled by app shell — hidden while on Explore; **InternalShellTwinNav** twin strip + hotbar share bottom inset like NuAsk)
 * - Side Drawer (handled by app.html)
 * - TabButton component (shared in app.html)
 * - DrawerItem component (shared in app.html)
 * - Authentication checks (handled by router)
 * 
 * Uses:
 * - window.SylvanFlowState for destinations caching
 * - window.appState for state-driven navigation
 * - window.SylvanFlowAuth for authenticated API calls
 *
 * **Ask Sylvan in-TV:** canonical Ask UX is `exploreTvMode === 'askSylvan'` (`AskSylvanPage` with `embeddedExploreTv` + `embeddedPowerUpTv` so the composer stays in the TV column). Full-app `view: 'ask-sylvan'` is optional (deep link / “Full chat”); it does **not** use the global three-tab shell — same immersive contract as Explore/NuAsk (`InternalShellTwinNav` on standalone chat).
 * Issue #86: Explore hotbar — **premium glass** four tiles (visual parity with Power Up `PowerUpHubTileRow`): per-slot emerald / cyan / violet / amber `glow` + `ring`, stroke icons per slot, labels `text-white` / `#9CA3AF`. Bottom stack: **`SYLVAN_TECH_THEME.classes.shellTwinDockOuter`** + **`shellTwinDockHubInner`** (shared with Power Up). TV hero rim: **`flex-1`** + **`tvRimMaxHeight`** so the plate scales with viewport; scroll clears **`dockScrollPaddingBottom`**. Overlay modes use **minimal-height** flat chrome row (`window.TV_EMBED_CHROME_CLASSES`) + inner plate; **Ask Sylvan overlay** uses **`askRow` / `askTitle`** tokens for a tighter strip above chat (`pages/shared/tv-embed-chrome-classes.js`). Blue hotkey: pick itinerary → stay on **hero / destination** (not trip program); purple hotkey owns timeline + activities. Hero tap opens destination detail in-TV (`ExploreDestinationDetailEmbedded`); detail primary CTA matches purple (trip program timeline + scroll). Timeline activity tap opens **`ExploreActivityDetailEmbedded`** in-TV (no legacy `activity-detail` full page).
 * NuAsk-tech shell: dark corridor UI, fray loading hold, fixed four-tile hotbar (press **`motion-safe:active:scale-[0.97]`** / **`group-active:`** on icon well). **Phone/tablet first:** `brightness-110` on hover is non-blocking. New plan: tap the Create tile (no keyboard shortcut). **Hero TV gutters:** the flex column wrapping the teal rim uses **symmetric vertical padding** (`pt`/`pb` with `sm:` parity) so header→TV and TV→fixed hotbar gaps stay coherent; **no-plan empty state** uses **`flex-1` + `justify-center`** inside the scroll column so copy + CTA sit mid-plate instead of a tall dead void. **Hero with destination photo:** the hero tap control **`flex-1`** with **`justify-center`** on the image band fills the TV plate above the headline (**no** flipped reflection strip). Documented in **`docs/setup/EXPLORE_SCREEN_CONTRACT.md`**.
 */

(function() {
  'use strict';

  const { useState, useEffect, useRef, useMemo } = React;

  /** Power Up personality carousel moment art — reused for Explore “no current trip” TV plate. */
  const EXPLORE_NO_CURRENT_HERO_IMAGE = '/assets/powerup-moment-quiet-lake.png';

  function exploreClientDayYmd() {
    const n = new Date();
    return (
      n.getFullYear() +
      '-' +
      String(n.getMonth() + 1).padStart(2, '0') +
      '-' +
      String(n.getDate()).padStart(2, '0')
    );
  }

  /** Active window or upcoming trip (pairs with `flow-plan-create-guard` + API list ranks). */
  function exploreIsCurrentOrUpcomingItinerary(it, todayYmd) {
    if (!it) return false;
    const today = todayYmd || exploreClientDayYmd();
    const Guard = typeof window !== 'undefined' ? window.flowPlanCreateGuard : null;
    if (Guard && typeof Guard.evaluateFlowPlanCreateBlockFromList === 'function') {
      return !!Guard.evaluateFlowPlanCreateBlockFromList([it], today);
    }
    return it.is_today_plan === true || it.is_today_plan === 'true';
  }

  function explorePickDefaultActiveTripKey(itins, todayYmd) {
    if (!Array.isArray(itins) || itins.length === 0) return null;
    const today = todayYmd || exploreClientDayYmd();
    const active = itins.filter((it) => exploreIsCurrentOrUpcomingItinerary(it, today));
    if (active.length === 0) return null;
    const flagged = active.find((it) => it.is_today_plan === true || it.is_today_plan === 'true');
    const row = flagged || active[0];
    return row.trip_key || row.Trip_Key || null;
  }

  /** Legacy SYS/KV `PowerUpAI` → current left-tab label (non-Latin strings unchanged). */
  function normalizeTabPowerUpLabel(raw) {
    const s = String(raw || '').trim();
    if (!s) return '';
    const compact = s.replace(/[\s_-]/g, '');
    if (/^powerupai$/i.test(compact)) return 'Flow Profile';
    return s;
  }

  /**
   * Explore dock — four-tile **premium glass** hotbar (visual parity with Power Up `PowerUpHubTileRow`):
   * per-slot emerald · cyan · violet · orange `glow` / `ring` (~1.33× baseline alpha for richer glass).
   */
  const EXPLORE_HOTBAR_SPECS = [
    {
      key: 'create',
      icon: 'calendarPlan',
      glow: 'rgba(34,197,94,0.35)',
      ring: 'rgba(52,211,153,0.4)'
    },
    {
      key: 'flowPick',
      icon: 'flowStack',
      glow: 'rgba(56,189,248,0.35)',
      ring: 'rgba(125,211,252,0.4)'
    },
    {
      key: 'tripTimeline',
      icon: 'timelineV',
      glow: 'rgba(167,139,250,0.35)',
      ring: 'rgba(196,181,253,0.4)'
    },
    {
      key: 'askChat',
      icon: 'askBubble',
      glow: 'rgba(248,130,18,0.35)',
      ring: 'rgba(251,162,52,0.4)'
    }
  ];

  /** Custom line-art glyphs — `h-[18px]` / `sw` aligned with Power Up hub icons; tint follows slot hue. */
  function ExploreHotbarIcon({ spec }) {
    const k = spec && spec.icon;
    const sw = 1.62;
    const cnBase = 'h-[18px] w-[18px] shrink-0 ';
    const cn =
      k === 'calendarPlan'
        ? cnBase + 'text-emerald-200'
        : k === 'flowStack'
          ? cnBase + 'text-sky-200'
          : k === 'timelineV'
            ? cnBase + 'text-violet-200'
            : k === 'askBubble'
              ? cnBase + 'text-amber-200'
              : cnBase + 'text-[#2DE2C5]/90';
    if (k === 'calendarPlan') {
      return (
        <svg className={cn} viewBox="0 0 24 24" fill="none" aria-hidden>
          <circle cx="8" cy="6" r="1" stroke="currentColor" strokeWidth={sw} />
          <circle cx="12" cy="6" r="1" stroke="currentColor" strokeWidth={sw} />
          <circle cx="16" cy="6" r="1" stroke="currentColor" strokeWidth={sw} />
          <rect x="5" y="7.5" width="14" height="12.5" rx="2" stroke="currentColor" strokeWidth={sw} />
          <path
            d="M8 13.5c1.2-1.8 2.8-1.2 4 0s2.8 1.4 4.5 0"
            stroke="currentColor"
            strokeWidth={sw}
            strokeLinecap="round"
            fill="none"
          />
          <circle cx="17.25" cy="17.25" r="2.15" stroke="currentColor" strokeWidth={sw} />
          <path d="M17.25 15.95v2.6M15.95 17.25h2.6" stroke="currentColor" strokeWidth={sw} strokeLinecap="round" />
        </svg>
      );
    }
    if (k === 'flowStack') {
      return (
        <svg className={cn} viewBox="0 0 24 24" fill="none" aria-hidden>
          <rect x="4" y="5.5" width="11" height="8.5" rx="1.35" stroke="currentColor" strokeWidth={sw} />
          <rect x="6" y="7.5" width="11" height="8.5" rx="1.35" stroke="currentColor" strokeWidth={sw} />
          <rect x="8" y="9.5" width="11" height="8.5" rx="1.35" stroke="currentColor" strokeWidth={sw} />
          <circle cx="17" cy="16.25" r="1.95" stroke="currentColor" strokeWidth={sw} />
          <path d="M15.85 16.25l.85.85 1.55-1.55" stroke="currentColor" strokeWidth={sw} strokeLinecap="round" strokeLinejoin="round" />
        </svg>
      );
    }
    if (k === 'timelineV') {
      return (
        <svg className={cn} viewBox="0 0 24 24" fill="none" aria-hidden>
          <line x1="12" y1="4.75" x2="12" y2="19.25" stroke="currentColor" strokeWidth={sw} strokeLinecap="round" />
          <circle cx="12" cy="4.85" r="1.2" fill="currentColor" stroke="none" />
          <circle cx="12" cy="12" r="2.85" stroke="currentColor" strokeWidth={sw} fill="none" />
          <circle cx="12" cy="12" r="1.1" fill="currentColor" stroke="none" />
          <circle cx="12" cy="19.15" r="1.2" fill="currentColor" stroke="none" />
        </svg>
      );
    }
    if (k === 'askBubble') {
      return (
        <svg className={cn} viewBox="0 0 24 24" fill="none" aria-hidden>
          <path
            d="M9 6.25h6.75a2.6 2.6 0 012.6 2.6v4.35a2.6 2.6 0 01-2.6 2.6h-4.35l-2.9 2.9v-2.9H9a2.6 2.6 0 01-2.6-2.6V8.85a2.6 2.6 0 012.6-2.6z"
            stroke="currentColor"
            strokeWidth={sw}
            strokeLinejoin="round"
            fill="none"
          />
          <path d="M9.55 10.85h4.9M9.55 12.45h3.65M9.55 14h5.35" stroke="currentColor" strokeWidth={sw} strokeLinecap="round" />
          <path d="M18.6 5.1l.4 1.15 1.15.4-1.15.4-.4 1.15-.4-1.15-1.15-.4 1.15-.4.4-1.15z" fill="currentColor" />
        </svg>
      );
    }
    return null;
  }

  // ✅ GATEWAY MIGRATION: Use SF_API_BASE (Gateway Worker) instead of SMART_BRAIN_URL
  // ✅ GATEWAY MIGRATION: Use SF_API_BASE from shared-api-config.js (no duplicate declaration)
  const SF_API_BASE = window.SF_API_BASE;

  /** NuAsk-style “fray” hold surface (same motion tokens as NuAskSylvanPage TOP gate). */
  function ExploreFrayHold({ linkLabel, titleText, captionText }) {
    const raw = (titleText || 'LOADING').trim();
    const latinTitle = /^[\sA-Za-z0-9·\-]+$/.test(raw);
    const phrase = latinTitle ? raw.toUpperCase() : raw;
    const linkTrim = (linkLabel || '').trim();
    const capTrim = (captionText || '').trim();
    const latinLinkEyebrow = /^[\sA-Za-z0-9·\-.]+$/.test(linkTrim);
    const latinCaptionLine = /^[\sA-Za-z0-9·\-.:,']+$/.test(capTrim);
    return (
      <div
        className="relative flex min-h-[min(42svh,280px)] w-full flex-col items-center justify-center overflow-hidden rounded-[14px] border border-[#2DE2C5]/30 bg-[#040809] px-5 py-10 text-center"
        style={{
          boxShadow:
            'inset 0 0 0 1px rgba(45,226,197,0.14), 0 0 48px -20px rgba(34,211,238,0.45)',
          animation: 'nuask-edge-refract-ring 6.4s ease-in-out infinite'
        }}
      >
        <div
          className="pointer-events-none absolute inset-0 opacity-[0.22]"
          style={{
            backgroundImage:
              'linear-gradient(rgba(45,226,197,0.07) 1px, transparent 1px), linear-gradient(90deg, rgba(45,226,197,0.07) 1px, transparent 1px)',
            backgroundSize: '22px 22px'
          }}
          aria-hidden
        />
        <div className="pointer-events-none absolute inset-0 overflow-hidden rounded-[14px]" aria-hidden>
          <div
            className="absolute left-0 right-0 h-[28%] bg-gradient-to-b from-[#2DE2C5]/25 via-[#2DE2C5]/10 to-transparent"
            style={{ animation: 'nuask-fray-scan 2.8s ease-in-out infinite' }}
          />
        </div>
        <div
          className="pointer-events-none absolute inset-3 rounded-[10px] border border-dashed border-[#2DE2C5]/25"
          style={{ animation: 'nuask-fray-edge 2.2s ease-in-out infinite' }}
          aria-hidden
        />
        <p
          className={`relative z-[1] text-[#2DE2C5]/85 ${
            latinLinkEyebrow
              ? 'font-mono text-[9px] uppercase tracking-[0.42em] text-[#2DE2C5]/75'
              : 'max-w-[20rem] px-1 text-center text-[10px] font-medium leading-snug tracking-wide text-[#2DE2C5]/90'
          }`}
        >
          {linkLabel}
        </p>
        <div className="relative z-[1] mt-5 flex flex-wrap justify-center gap-x-1 gap-y-1">
          {latinTitle ? (
            phrase.split('').map((ch, i) => (
              <span
                key={`ex-fray-${i}-${ch}`}
                className="inline-block text-[clamp(11px,3.6vw,18px)] font-black uppercase tracking-[0.08em] text-white"
                style={{
                  textShadow: '0 0 18px rgba(45,226,197,0.55), 0 0 42px rgba(34,211,238,0.35)',
                  animation: 'nuask-sync-letter 1.2s ease-in-out infinite',
                  animationDelay: `${i * 0.045}s`
                }}
              >
                {ch === ' ' ? '\u00a0' : ch}
              </span>
            ))
          ) : (
            <p
              className="relative z-[1] max-w-[20rem] text-center text-[clamp(13px,4vw,20px)] font-bold leading-snug tracking-wide text-white"
              style={{
                textShadow: '0 0 18px rgba(45,226,197,0.45), 0 0 36px rgba(34,211,238,0.28)'
              }}
            >
              {phrase}
            </p>
          )}
        </div>
        <p
          className={`relative z-[1] mt-4 max-w-[20rem] px-1 text-center ${
            latinCaptionLine
              ? 'font-mono text-[9px] uppercase leading-relaxed tracking-[0.22em] text-[#2DE2C5]/55'
              : 'text-[11px] font-normal leading-relaxed tracking-normal text-[#2DE2C5]/70'
          }`}
        >
          {captionText}
        </p>
        <div className="relative z-[1] mt-6 flex items-center justify-center gap-1.5">
          {[0, 1, 2, 3, 4].map((i) => (
            <span
              key={`ex-dot-${i}`}
              className="h-1 w-4 rounded-full bg-gradient-to-r from-[#2DE2C5]/20 to-[#2DE2C5]/90"
              style={{
                animation: 'nuask-fray-pulse 1.05s ease-in-out infinite',
                animationDelay: `${i * 0.1}s`
              }}
            />
          ))}
        </div>
      </div>
    );
  }
  
  // Legacy constant (removed)
  // const SMART_BRAIN_URL = 'https://smart-brain.foofiebean.workers.dev';

  function ExplorePage() {
    const TV_EMBED = window.TV_EMBED_CHROME_CLASSES;
    const [destinations, setDestinations] = useState([]);
    const [flowPlanCount, setFlowPlanCount] = useState(0);
    const [loading, setLoading] = useState(true);
    const [error, setError] = useState(null);
    const [profile, setProfile] = useState(null);
    /** Issue #86: itinerary list + detail (same sources as Flow Plan tab) */
    const [itineraries, setItineraries] = useState([]);
    const [selectedTripKey, setSelectedTripKey] = useState(null);
    const [selectedItinerary, setSelectedItinerary] = useState(null);
    const [itinerariesLoading, setItinerariesLoading] = useState(true);
    
    // ✅ PAGE LOADING GATE: Track when translations are ready
    const [translationsReady, setTranslationsReady] = useState(false);
    
    // ✅ PROFILE-PHOTO: State for authenticated photo blob URL
    const [profilePhotoUrl, setProfilePhotoUrl] = useState(null);
    const profilePhotoObjectUrlRef = useRef(null);
    const selectedTripKeyRef = useRef(null);
    const tripTimelineAnchorRef = useRef(null);
    const [itineraryPickerOpen, setItineraryPickerOpen] = useState(false);
    /** hero | createPlan (iframe) | tripProgram | destinationDetail | activityDetail | askSylvan */
    const [exploreTvMode, setExploreTvMode] = useState('hero');
    /** Tighter chrome row when Ask Sylvan fills the overlay TV (less vertical chrome above chat). */
    const tvEmbedChrome =
      TV_EMBED && exploreTvMode === 'askSylvan' && TV_EMBED.askRow
        ? {
            row: TV_EMBED.askRow,
            backBtn: TV_EMBED.askBackBtn,
            title: TV_EMBED.askTitle,
            spacer: TV_EMBED.askSpacer
          }
        : TV_EMBED;
    /** When exploreTvMode === 'destinationDetail', API id for window.ExploreDestinationDetailEmbedded */
    const [tvDestinationId, setTvDestinationId] = useState(null);
    /** In-TV activity detail (Explore only — avoids legacy full-page activity-detail view). */
    const [tvActivityEmbed, setTvActivityEmbed] = useState(null);
    /** Which hotkey opened trip program — affects TV chrome title only */
    const [tripProgramSource, setTripProgramSource] = useState('pick');
    const pendingTripTimelineScrollRef = useRef(false);
    /** SYS-backed copy when Create Flow Plan is blocked (active or upcoming itinerary). */
    const [createFlowPlanBlockedMessage, setCreateFlowPlanBlockedMessage] = useState(null);

    useEffect(() => {
      selectedTripKeyRef.current = selectedTripKey;
    }, [selectedTripKey]);

    /** BCP 47 tags for `toLocaleDateString` / weekday labels (matches app language codes). */
    const getExploreDateLocaleTag = () => {
      const lang = window.SylvanFlowState?.getLanguage?.() || 'en';
      const map = {
        en: 'en-US',
        'zh-CN': 'zh-CN',
        ja: 'ja-JP',
        ko: 'ko-KR',
        th: 'th-TH',
        vi: 'vi-VN',
        id: 'id-ID',
        ms: 'ms-MY',
        ar: 'ar',
        fil: 'fil-PH'
      };
      return map[lang] || 'en-US';
    };
    
    // ✅ UI LANGUAGE AWARENESS: State for language-aware UI strings
    const [uiStrings, setUiStrings] = useState({
      spontaneityAwaits: 'CORRIDOR · LIVE',
      yourFlowBegins: 'Your itinerary command center',
      flowPlansCreatedCount: 'Current Flow Plans: {number}',
      createNewFlowPlan: 'Create New Flow Plan',
      createFlowPlan: 'Create Flow Plan',
      createFirstFlowPlanMessage: 'Create your first flow plan to get started!',
      flowPlanUserTitle: '{displayName}\'s Flow Plan',
      flowPlanUserTitlePlural: '{displayName}\'s Flow Plans',
      flowPlanCurrentCount: 'Current Flow Plan: {number}',
      flowPlanCurrentCountPlural: 'Current Flow Plans: {number}',
      flowPlanCurrentLabel: 'CURRENT FLOW PLAN',
      flowPlanActivity: 'Activity',
      flowPlanActivities: 'Activities',
      clickDiscoverMore: 'Click to discover more',
      loadingHoldLink: 'Your trip link',
      loadingHoldTitle: 'Loading Explore',
      loadingHoldCaption: 'Syncing trips, stops, and this view…',
      itineraryLoadingCaption: 'Loading each day’s stops and activities…',
      itineraryLoadingTitle: 'Syncing day plan',
      hotbarCreateSub: '',
      hotbarFlowPickTitle: 'Flow Plan Selection',
      hotbarFlowPickSub: 'Choose which plan is on-screen',
      hotbarTripTimelineTitle: 'Trip timeline',
      hotbarTripTimelineSub: 'Jump to your day-by-day stops',
      tabAskSylvanShort: 'Ask Sylvan',
      hotbarAskSylvanSub: 'Chat with your travel copilot',
      tabExploreBadge: 'Explore',
      exploreFlowPickHotbarHint: 'Tap Flow Plan Selection in the bottom bar to open your trip list.',
      exploreNoActivePlanLabel: 'NO ACTIVE TRIP',
      exploreNoCurrentPlanTitle: 'No Flow Plan for today',
      exploreNoCurrentPlanMessage:
        "You don't have a trip in progress right now. Start a new Flow Plan when you're ready—or tap Flow Plan Selection below to open a past trip.",
      destinationsErrorHeading: 'Unable to load destinations',
      retryButton: 'Retry',
      recoverySyncMessage:
        'We found plans on your account, but this screen did not sync. Refresh to load itineraries and destinations again.',
      recoveryRefreshButton: 'Refresh',
      legalPoliciesLink: 'Legal & Policies',
      unknownDate: 'Unknown date',
      defaultGuestName: 'Traveler',
      heroFallbackTitle: 'Your trip',
      brandLogoAlt: 'SylvanFlow',
      exploreDestinationChromeTitle: 'Destination',
      exploreDestinationLoading: 'Loading destination...',
      exploreDestinationNoDescription: 'No description available.',
      exploreDestinationAiVoice: "In Sylvan AI's Words",
      exploreDestinationViewFlowPlan: 'View Detailed Flow Plan',
      exploreDestinationGoBack: 'Go Back',
      exploreActivityChromeTitle: 'Activity',
      exploreActivityLabelDestination: 'Destination',
      exploreActivityLabelDay: 'Day',
      exploreActivityLabelLocation: 'Location',
      exploreActivityLabelTime: 'Time',
      exploreActivityLabelType: 'Type',
      exploreActivityNoDescription: 'No description for this stop yet.',
      exploreActivityMissingParams: 'Could not open this activity.',
      navTwinPowerUp: 'Profile',
      navTwinNuAsk: 'NOW WHAT'
    });

    // ✅ FIX: Identity comes from Bearer token via authenticatedFetch, not from localStorage email
    // Removed userId dependency - authenticatedFetch works with session token only
    // Identity is derived server-side from Authorization Bearer token (opaque userKey)

    useEffect(() => {
      window.SYLVAN_TECH_THEME?.ensureKeyframes?.();
    }, []);

    useEffect(() => {
      // ✅ FIX: Identity guarantee log - once per page load (admin-only, sanitized)
      const sessionToken = localStorage.getItem('sylvanflow_session_token');
      if (window.uiLogger) {
        window.uiLogger.uiLog('[IDENTITY][EXPLORE] source=Bearer_only tokenLength=' + (sessionToken?.length || 0));
      }
      
      loadData();
      
      // Cleanup object URL on unmount
      return () => {
        if (profilePhotoObjectUrlRef.current) {
          URL.revokeObjectURL(profilePhotoObjectUrlRef.current);
          profilePhotoObjectUrlRef.current = null;
        }
      };
    }, []);
    
    // ✅ PROFILE-PHOTO: Fetch photo when profile changes
    useEffect(() => {
      // Reset photo URL when profile changes
      if (profilePhotoObjectUrlRef.current) {
        URL.revokeObjectURL(profilePhotoObjectUrlRef.current);
        profilePhotoObjectUrlRef.current = null;
      }
      setProfilePhotoUrl(null);
      
      if (!profile) {
        return;
      }
      
      // ✅ PROFILE-PHOTO: If profile_photo_url is already a public URL, use it directly
      if (profile.profile_photo_url && !profile.profile_photo_url.includes('/api/profile-photo/')) {
        setProfilePhotoUrl(profile.profile_photo_url);
        return;
      }
      
      // ✅ PROFILE-PHOTO: Use cached data URL (persists across refresh)
      if (profile.profile_photo_r2_key || profile.profile_photo_url?.includes('/api/profile-photo/')) {
        const loadPhoto = async () => {
          try {
            // Check cache first
            const CACHE_KEY = 'profile_photo_cache_v1';
            const CACHE_MAX_AGE_MS = 7 * 24 * 60 * 60 * 1000; // 7 days
            const r2Key = profile.profile_photo_r2_key;
            
            if (r2Key) {
              try {
                const cached = localStorage.getItem(CACHE_KEY);
                if (cached) {
                  const cacheData = JSON.parse(cached);
                  if (cacheData.profile_photo_r2_key === r2Key) {
                    const cacheAge = Date.now() - (cacheData.cachedAt || 0);
                    if (cacheAge < CACHE_MAX_AGE_MS) {
                      // Cache hit - use immediately
                      if (window.uiLogger) {
                        window.uiLogger.uiLog(`[EXPLORE] [PROFILE-PHOTO] Cache hit (age: ${Math.floor(cacheAge / 1000 / 60)} min)`);
                      }
                      setProfilePhotoUrl(cacheData.dataUrl);
                      // Refetch in background to refresh cache
                      fetchPhotoInBackground();
                      return;
                    } else {
                      // Cache expired
                      localStorage.removeItem(CACHE_KEY);
                    }
                  }
                }
              } catch (cacheError) {
                if (window.uiLogger) {
                  window.uiLogger.uiWarn('[EXPLORE] [PROFILE-PHOTO] Cache read error:', cacheError.message || cacheError);
                }
              }
            }
            
            // Cache miss - fetch and cache
            await fetchPhotoInBackground();
          } catch (error) {
            if (window.uiLogger) {
              window.uiLogger.uiWarn('[EXPLORE] [PROFILE-PHOTO] Error loading photo:', error.message || error);
            }
            setProfilePhotoUrl(null);
          }
        };
        
        const fetchPhotoInBackground = async () => {
          try {
            const res = await window.SylvanFlowAuth.authenticatedFetch(
              `${SF_API_BASE}/api/profile-photo/self`
            );
            
            // ✅ UI-BUG-02 FIX: Check status before reading blob (204 = no content)
            if (res.status === 204) {
              return;
            }
            
            if (res.ok) {
              const blob = await res.blob();
              if (blob.size === 0 || !blob.type.startsWith('image/')) {
                if (window.uiLogger) {
                  window.uiLogger.uiWarn('[EXPLORE] [PROFILE-PHOTO] Invalid blob', { size: blob.size, type: blob.type });
                }
                return;
              }
              
              // Convert to data URL
              const reader = new FileReader();
              reader.onloadend = () => {
                const dataUrl = reader.result;
                const r2Key = profile.profile_photo_r2_key;
                if (r2Key && dataUrl) {
                  // Cache it
                  try {
                    const cacheData = {
                      profile_photo_r2_key: r2Key,
                      dataUrl: dataUrl,
                      cachedAt: Date.now()
                    };
                    localStorage.setItem('profile_photo_cache_v1', JSON.stringify(cacheData));
                    if (window.uiLogger) {
                      window.uiLogger.uiLog('[EXPLORE] [PROFILE-PHOTO] Cached (size: ' + blob.size + ' bytes)');
                    }
                  } catch (cacheError) {
                    if (window.uiLogger) {
                      window.uiLogger.uiWarn('[EXPLORE] [PROFILE-PHOTO] Cache write error:', cacheError.message || cacheError);
                    }
                  }
                }
                setProfilePhotoUrl(dataUrl);
              };
              reader.onerror = () => {
                if (window.uiLogger) {
                  window.uiLogger.uiWarn('[EXPLORE] [PROFILE-PHOTO] FileReader error');
                }
                setProfilePhotoUrl(null);
              };
              reader.readAsDataURL(blob);
            } else {
              if (window.uiLogger) {
                window.uiLogger.uiWarn('[EXPLORE] [PROFILE-PHOTO] Failed to fetch photo:', res.status);
              }
              setProfilePhotoUrl(null);
            }
          } catch (error) {
            if (window.uiLogger) {
              window.uiLogger.uiWarn('[EXPLORE] [PROFILE-PHOTO] Error fetching photo:', error.message || error);
            }
            setProfilePhotoUrl(null);
          }
        };
        
        loadPhoto();
      }
    }, [profile?.profile_photo_r2_key, profile?.profile_photo_url]);

    // ✅ UI LANGUAGE AWARENESS: Load UI strings when language changes
    useEffect(() => {
      const loadUiStrings = async () => {
        const language = window.SylvanFlowState?.getLanguage() || 'en';
        
        // ✅ PAGE LOADING GATE: Reset translations ready state when loading new language
        setTranslationsReady(false);
        
        try {
          const [
            spontaneityAwaits,
            yourFlowBegins,
            flowPlansCreatedCount,
            createNewFlowPlan,
            createFlowPlan,
            createFirstFlowPlanMessage,
            flowPlanUserTitle,
            flowPlanUserTitlePlural,
            flowPlanCurrentCount,
            flowPlanCurrentCountPlural,
            flowPlanCurrentLabel,
            flowPlanActivity,
            flowPlanActivities,
            clickDiscoverMore,
            loadingHoldLink,
            loadingHoldTitle,
            loadingHoldCaption,
            itineraryLoadingCaption,
            itineraryLoadingTitle,
            hotbarCreateSub,
            hotbarFlowPickTitle,
            hotbarFlowPickSub,
            hotbarTripTimelineTitle,
            hotbarTripTimelineSub,
            tabAskSylvanShort,
            hotbarAskSylvanSub,
            tabExploreBadge,
            exploreFlowPickHotbarHint,
            exploreNoActivePlanLabel,
            exploreNoCurrentPlanTitle,
            exploreNoCurrentPlanMessage,
            destinationsErrorHeading,
            retryButton,
            recoverySyncMessage,
            recoveryRefreshButton,
            legalPoliciesLink,
            unknownDate,
            defaultGuestName,
            heroFallbackTitle,
            brandLogoAlt,
            navTwinPowerUp,
            navTwinNuAsk,
            exploreActivityChromeTitle,
            exploreActivityLabelDestination,
            exploreActivityLabelDay,
            exploreActivityLabelLocation,
            exploreActivityLabelTime,
            exploreActivityLabelType,
            exploreActivityNoDescription,
            exploreActivityMissingParams
          ] = await Promise.all([
            window.getSysMessage('ui:spontaneity_awaits', language),
            window.getSysMessage('ui:your_flow_begins', language),
            window.getSysMessage('ui:flow_plan_current_count_plural', language),
            window.getSysMessage('ui:create_new_flow_plan', language),
            window.getSysMessage('ui:create_flow_plan', language),
            window.getSysMessage('ui:create_first_flow_plan_message', language),
            window.getSysMessage('ui:flow_plan_user_title', language),
            window.getSysMessage('ui:flow_plan_user_title_plural', language),
            window.getSysMessage('ui:flow_plan_current_count', language),
            window.getSysMessage('ui:flow_plan_current_count_plural', language),
            window.getSysMessage('ui:flow_plan_current_label', language),
            window.getSysMessage('ui:flow_plan_activity', language),
            window.getSysMessage('ui:flow_plan_activities', language),
            window.getSysMessage('ui:explore_click_discover_more', language),
            window.getSysMessage('ui:explore_loading_hold_link', language),
            window.getSysMessage('ui:explore_loading_hold_title', language),
            window.getSysMessage('ui:explore_loading_hold_caption', language),
            window.getSysMessage('ui:explore_itinerary_loading_caption', language),
            window.getSysMessage('ui:explore_itinerary_loading_title', language),
            window.getSysMessage('ui:explore_hotbar_create_sub', language),
            window.getSysMessage('ui:explore_hotbar_flow_pick_title', language),
            window.getSysMessage('ui:explore_hotbar_flow_pick_sub', language),
            window.getSysMessage('ui:explore_hotbar_trip_timeline_title', language),
            window.getSysMessage('ui:explore_hotbar_trip_timeline_sub', language),
            window.getSysMessage('ui:tab_ask_sylvan', language),
            window.getSysMessage('ui:explore_hotbar_ask_sylvan_sub', language),
            window.getSysMessage('ui:tab_explore', language),
            window.getSysMessage('ui:explore_flow_pick_hotbar_hint', language),
            window.getSysMessage('ui:explore_no_active_plan_label', language),
            window.getSysMessage('ui:explore_no_current_plan_title', language),
            window.getSysMessage('ui:explore_no_current_plan_message', language),
            window.getSysMessage('ui:explore_destinations_error_heading', language),
            window.getSysMessage('ui:explore_retry_button', language),
            window.getSysMessage('ui:explore_recovery_sync_message', language),
            window.getSysMessage('ui:explore_recovery_refresh_button', language),
            window.getSysMessage('ui:explore_legal_policies_link', language),
            window.getSysMessage('ui:explore_unknown_date', language),
            window.getSysMessage('ui:explore_default_guest_name', language),
            window.getSysMessage('ui:explore_hero_fallback_title', language),
            window.getSysMessage('ui:explore_brand_logo_alt', language),
            window.getSysMessage('ui:tab_powerupai', language),
            window.getSysMessage('ui:tab_nu_ask_sylvan', language),
            window.getSysMessage('ui:explore_activity_chrome_title', language),
            window.getSysMessage('ui:explore_activity_label_destination', language),
            window.getSysMessage('ui:explore_activity_label_day', language),
            window.getSysMessage('ui:explore_activity_label_location', language),
            window.getSysMessage('ui:explore_activity_label_time', language),
            window.getSysMessage('ui:explore_activity_label_type', language),
            window.getSysMessage('ui:explore_activity_no_description', language),
            window.getSysMessage('ui:explore_activity_missing_params', language)
          ]);

          setUiStrings({
            spontaneityAwaits: spontaneityAwaits || 'CORRIDOR · LIVE',
            yourFlowBegins: yourFlowBegins || 'Your itinerary command center',
            flowPlansCreatedCount: flowPlansCreatedCount || 'Current Flow Plans: {number}',
            createNewFlowPlan: createNewFlowPlan || 'Create New Flow Plan',
            createFlowPlan: createFlowPlan || 'Create Flow Plan',
            createFirstFlowPlanMessage: createFirstFlowPlanMessage || 'Create your first flow plan to get started!',
            flowPlanUserTitle: flowPlanUserTitle || "{displayName}'s Flow Plan",
            flowPlanUserTitlePlural: flowPlanUserTitlePlural || "{displayName}'s Flow Plans",
            flowPlanCurrentCount: flowPlanCurrentCount || 'Current Flow Plan: {number}',
            flowPlanCurrentCountPlural: flowPlanCurrentCountPlural || 'Current Flow Plans: {number}',
            flowPlanCurrentLabel: flowPlanCurrentLabel || 'CURRENT FLOW PLAN',
            flowPlanActivity: flowPlanActivity || 'Activity',
            flowPlanActivities: flowPlanActivities || 'Activities',
            clickDiscoverMore: clickDiscoverMore || 'Click to discover more',
            loadingHoldLink: loadingHoldLink || 'Your trip link',
            loadingHoldTitle: loadingHoldTitle || 'Loading Explore',
            loadingHoldCaption: loadingHoldCaption || 'Syncing trips, stops, and this view…',
            itineraryLoadingCaption: itineraryLoadingCaption || 'Loading each day’s stops and activities…',
            itineraryLoadingTitle: itineraryLoadingTitle || 'Syncing day plan',
            hotbarCreateSub: hotbarCreateSub || '',
            hotbarFlowPickTitle: hotbarFlowPickTitle || 'Flow Plan Selection',
            hotbarFlowPickSub: hotbarFlowPickSub || 'Choose which plan is on-screen',
            hotbarTripTimelineTitle: hotbarTripTimelineTitle || 'Trip timeline',
            hotbarTripTimelineSub: hotbarTripTimelineSub || 'Jump to your day-by-day stops',
            tabAskSylvanShort: tabAskSylvanShort || 'Ask Sylvan',
            hotbarAskSylvanSub: hotbarAskSylvanSub || 'Chat with your travel copilot',
            tabExploreBadge: tabExploreBadge || 'Explore',
            exploreFlowPickHotbarHint:
              exploreFlowPickHotbarHint ||
              'Tap Flow Plan Selection in the bottom bar to open your trip list.',
            exploreNoActivePlanLabel: exploreNoActivePlanLabel || 'NO ACTIVE TRIP',
            exploreNoCurrentPlanTitle: exploreNoCurrentPlanTitle || 'No Flow Plan for today',
            exploreNoCurrentPlanMessage:
              exploreNoCurrentPlanMessage ||
              "You don't have a trip in progress right now. Start a new Flow Plan when you're ready—or tap Flow Plan Selection below to open a past trip.",
            destinationsErrorHeading: destinationsErrorHeading || 'Unable to load destinations',
            retryButton: retryButton || 'Retry',
            recoverySyncMessage:
              recoverySyncMessage ||
              'We found plans on your account, but this screen did not sync. Refresh to load itineraries and destinations again.',
            recoveryRefreshButton: recoveryRefreshButton || 'Refresh',
            legalPoliciesLink: legalPoliciesLink || 'Legal & Policies',
            unknownDate: unknownDate || 'Unknown date',
            defaultGuestName: defaultGuestName || 'Traveler',
            heroFallbackTitle: heroFallbackTitle || 'Your trip',
            brandLogoAlt: brandLogoAlt || 'SylvanFlow',
            navTwinPowerUp: 'Profile',
            navTwinNuAsk: navTwinNuAsk || 'NOW WHAT',
            exploreActivityChromeTitle: exploreActivityChromeTitle || 'Activity',
            exploreActivityLabelDestination: exploreActivityLabelDestination || 'Destination',
            exploreActivityLabelDay: exploreActivityLabelDay || 'Day',
            exploreActivityLabelLocation: exploreActivityLabelLocation || 'Location',
            exploreActivityLabelTime: exploreActivityLabelTime || 'Time',
            exploreActivityLabelType: exploreActivityLabelType || 'Type',
            exploreActivityNoDescription:
              exploreActivityNoDescription || 'No description for this stop yet.',
            exploreActivityMissingParams:
              exploreActivityMissingParams || 'Could not open this activity.'
          });
          
          // ✅ PAGE LOADING GATE: Mark translations as ready
          setTranslationsReady(true);
        } catch (error) {
          if (window.uiLogger) {
            window.uiLogger.uiWarn('[EXPLORE] Error loading UI strings:', error.message || error);
          }
          // Keep fallback values on error
          // ✅ PAGE LOADING GATE: Still mark as ready even on error (fallback values are acceptable)
          setTranslationsReady(true);
        }
      };
      
      loadUiStrings();
      
      // Re-fetch when language changes
      const handleLanguageChange = () => {
        loadUiStrings();
      };
      
      if (window.SylvanFlowState?.on) {
        window.SylvanFlowState.on('language', handleLanguageChange);
        return () => {
          window.SylvanFlowState.off('language', handleLanguageChange);
        };
      }
    }, []);

    function findDestinationForTripKey(destList, tripKey) {
      if (!tripKey || !destList?.length) return null;
      const norm = window.NormalizeTripKey?.normalizeTripKey(tripKey) || tripKey;
      return (
        destList.find((d) => {
          const tk = d.trip_key || d.Trip_Key || d.Flow_Plan_ID;
          if (!tk) return false;
          const nt = d._normalized_trip_key || window.NormalizeTripKey?.normalizeTripKey(tk);
          return nt === norm;
        }) || null
      );
    }

    const formatFlowPlanDate = (flowPlanCreatedOn, createdDate) => {
      const loc = getExploreDateLocaleTag();
      const unknown = uiStrings.unknownDate || 'Unknown date';
      try {
        if (createdDate) {
          const date = new Date(createdDate + 'T00:00:00');
          return date.toLocaleDateString(loc, {
            year: 'numeric',
            month: 'long',
            day: 'numeric'
          });
        }
        if (flowPlanCreatedOn) {
          const datePart = flowPlanCreatedOn.split(' at ')[0];
          return datePart;
        }
        return unknown;
      } catch {
        return flowPlanCreatedOn || createdDate || unknown;
      }
    };

    const formatFlowPlanDropdownLabel = (itinerary) => {
      const datePart = formatFlowPlanDate(itinerary.FlowPlanCreatedOn, itinerary.created_date || itinerary.created_at);
      const dest = (itinerary.destination_label || '').trim();
      if (dest) return `${dest} · ${datePart}`;
      return datePart;
    };

    const formatTime = (timeStr) => {
      try {
        if (!timeStr) return '';
        if (!timeStr.includes(':')) return timeStr;
        const [hours, minutes] = timeStr.split(':');
        const hour = parseInt(hours, 10);
        const min = parseInt(minutes || '0', 10);
        if (Number.isNaN(hour)) return timeStr;
        const d = new Date(2000, 0, 1, hour, Number.isNaN(min) ? 0 : min);
        return d.toLocaleTimeString(getExploreDateLocaleTag(), { hour: 'numeric', minute: '2-digit' });
      } catch {
        return timeStr || '';
      }
    };

    const formatDateDisplay = (dateStr) => {
      try {
        const date = new Date(dateStr);
        return date.toLocaleDateString(getExploreDateLocaleTag(), {
          year: 'numeric',
          month: 'long',
          day: 'numeric'
        });
      } catch {
        return dateStr;
      }
    };

    const getActivityImage = (activity) =>
      activity.image_url || activity.Image_URL || activity.photo_url || activity.Photo_URL || null;

    const getActivityLocation = (activity) => {
      if (typeof activity.location === 'object' && activity.location !== null) {
        return activity.location.address || activity.location.name || activity.location.Location || '';
      }
      return activity.location || activity.Location || '';
    };

    const navigateToActivityDetail = ({ tripKey, dayKey, activityIndex, lang, activity }) => {
      setTvDestinationId(null);
      setTvActivityEmbed({
        tripKey,
        dayKey,
        activityIndex,
        activity,
        lang: lang || window.SylvanFlowState?.getLanguage?.() || 'en'
      });
      setTripProgramSource('timeline');
      setExploreTvMode('activityDetail');
    };

    const navigateToFlowPlanForm = () => {
      setTvActivityEmbed(null);
      setTvDestinationId(null);
      setExploreTvMode('createPlan');
    };

    const tryOpenFlowPlanForm = async () => {
      const Guard = typeof window !== 'undefined' ? window.flowPlanCreateGuard : null;
      const lang =
        profile?.preferred_language ||
        (typeof window !== 'undefined' && window.SylvanFlowState?.getLanguage?.()) ||
        'en';
      if (!Guard || typeof Guard.fetchItinerariesForFlowPlanGuard !== 'function') {
        navigateToFlowPlanForm();
        return;
      }
      try {
        const list = await Guard.fetchItinerariesForFlowPlanGuard();
        const block = Guard.evaluateFlowPlanCreateBlockFromList(list, Guard.clientCalendarDayYMD());
        if (block && typeof Guard.getFlowPlanBlockedMessage === 'function') {
          const msg = await Guard.getFlowPlanBlockedMessage(block, lang);
          setCreateFlowPlanBlockedMessage(msg || null);
          return;
        }
      } catch (_) {
        /* fail open */
      }
      setCreateFlowPlanBlockedMessage(null);
      navigateToFlowPlanForm();
    };

    useEffect(() => {
      if (exploreTvMode !== 'tripProgram') return;
      if (!pendingTripTimelineScrollRef.current) return;
      pendingTripTimelineScrollRef.current = false;
      const id = requestAnimationFrame(() => {
        requestAnimationFrame(() => {
          const el =
            tripTimelineAnchorRef.current || document.getElementById('explore-trip-timeline-anchor');
          if (el && typeof el.scrollIntoView === 'function') {
            el.scrollIntoView({ behavior: 'smooth', block: 'start' });
          }
        });
      });
      return () => cancelAnimationFrame(id);
    }, [exploreTvMode, selectedItinerary, selectedTripKey]);

    const loadItineraryDetails = async (tripKey) => {
      if (window.uiLogger) {
        window.uiLogger.uiLog(`[EXPLORE] loadItineraryDetails tripKey length=${tripKey?.length || 0}`);
      }
      try {
        const encodedUrl = `${SF_API_BASE}/api/itineraries/${encodeURIComponent(tripKey)}`;
        const res = await window.SylvanFlowAuth.authenticatedFetch(encodedUrl);
        window.SylvanFlowAuth.handleAuthResponse(res);
        if (res.ok) {
          const data = await res.json();
          if (data.ok && data.itinerary) {
            setSelectedItinerary(data.itinerary);
          } else {
            setSelectedItinerary(null);
          }
        } else {
          setSelectedItinerary(null);
        }
      } catch (e) {
        if (window.uiLogger) {
          window.uiLogger.uiError('[EXPLORE] loadItineraryDetails:', e.message || e);
        }
        setSelectedItinerary(null);
      }
    };

    /**
     * @returns {{ itineraries: Array, flowPlanCount: number }}
     */
    const loadItineraries = async () => {
      let resultItins = [];
      let resultFpCount = 0;
      try {
        setItinerariesLoading(true);
        if (window.SylvanFlowState) {
          window.SylvanFlowState.invalidateItineraries();
        }

        if (window.SylvanFlowState && window.SylvanFlowState.isItinerariesLoaded()) {
          const cachedItineraries = window.SylvanFlowState.getItineraries();
          if (cachedItineraries && cachedItineraries.length > 0) {
            setItineraries(cachedItineraries);
          }
        }

        const clientDayKeyForList = (() => {
          const n = new Date();
          return `${n.getFullYear()}-${String(n.getMonth() + 1).padStart(2, '0')}-${String(n.getDate()).padStart(2, '0')}`;
        })();
        const url = `${SF_API_BASE}/api/itineraries?include_past=1&client_day_key=${encodeURIComponent(clientDayKeyForList)}`;

        const res = await window.SylvanFlowAuth.authenticatedFetch(url);
        window.SylvanFlowAuth.handleAuthResponse(res);

        if (!res.ok) {
          setItineraries([]);
          return { itineraries: [], flowPlanCount: 0 };
        }

        const data = await res.json();
        const itinerariesLength = data.itineraries?.length || 0;

        if (data.ok && data.itineraries) {
          const itins = data.itineraries || [];
          if (window.NormalizeTripKey) {
            itins.forEach((it) => {
              const tk = it.trip_key || it.Trip_Key;
              if (tk) {
                it._normalized_trip_key = window.NormalizeTripKey.normalizeTripKey(tk);
              }
            });
          }
          resultItins = itins;
          if (data.flow_plan_count !== undefined) {
            resultFpCount = data.flow_plan_count;
            setFlowPlanCount(data.flow_plan_count);
          }
          setItineraries(itins);
          if (window.SylvanFlowState) {
            window.SylvanFlowState.setItineraries(itins);
          }
          setSelectedTripKey((prev) => {
            if (prev) {
              const stillThere = itins.some((it) => (it.trip_key || it.Trip_Key) === prev);
              if (stillThere) return prev;
            }
            return explorePickDefaultActiveTripKey(itins, clientDayKeyForList);
          });
        } else {
          setItineraries([]);
        }

        if (window.uiLogger) {
          window.uiLogger.uiLog('[EXPLORE] itineraries loaded', { count: itinerariesLength });
        }
        return { itineraries: resultItins, flowPlanCount: resultFpCount };
      } catch (e) {
        if (window.uiLogger) {
          window.uiLogger.uiError('[EXPLORE] loadItineraries:', e.message || e);
        }
        setItineraries([]);
        return { itineraries: [], flowPlanCount: 0 };
      } finally {
        setItinerariesLoading(false);
      }
    };

    const exploreNavigateToView = (view) => {
      try {
        const legalAgreed = localStorage.getItem('sylvanflow_legal_agreed');
        const restrictedTabs = ['explore', 'ask-sylvan', 'nu-ask-sylvan'];
        if (restrictedTabs.includes(view) && !legalAgreed) {
          // SF_ALLOW_HARDEXIT_REDIRECT
          window.location.href = '/legal?return=/app';
          return;
        }
        if (window.appState && typeof window.appState.set === 'function') {
          window.appState.set({ view });
        }
      } catch (e) {
        if (window.uiLogger) {
          window.uiLogger.uiWarn('[EXPLORE] exploreNavigateToView', e?.message || e);
        }
      }
    };

    const TwinNav = typeof window !== 'undefined' ? window.InternalShellTwinNav : null;

    const scrollToTripTimeline = () => {
      setTvActivityEmbed(null);
      setTvDestinationId(null);
      setTripProgramSource('timeline');
      setExploreTvMode('tripProgram');
      pendingTripTimelineScrollRef.current = true;
    };

    /**
     * Refresh Explore destinations + profile + itineraries.
     * @returns {{ destinationCount: number, itineraryCount: number, flowPlanCount: number, tripKeys: Set<string> }}
     */
    const loadData = async () => {
      let lastDestinations = [];
      let lastDestFlowPlanCount = 0;
      try {
        setLoading(true);
        setError(null);
        
        // Check cache first
        if (window.SylvanFlowState && window.SylvanFlowState.isDestinationsLoaded()) {
          const cachedDestinations = window.SylvanFlowState.getDestinations();
          if (cachedDestinations && cachedDestinations.length > 0) {
            setDestinations(cachedDestinations);
            // Still fetch to get flowPlanCount and latest data
          }
        }

        // Load profile from cache or fetch
        if (window.SylvanFlowState && window.SylvanFlowState.isProfileLoaded()) {
          const cachedProfile = window.SylvanFlowState.getProfile();
          if (cachedProfile) {
            setProfile(cachedProfile);
          }
        }

        // ✅ FIX: Load profile using authenticatedFetch (identity from Bearer token, not email)
        // No userId check needed - authenticatedFetch works with session token only
        try {
          // ✅ SYSTEM_MAP COMPLIANT: No user_id query param (identity via Authorization header)
          const profileRes = await window.SylvanFlowAuth.authenticatedFetch(
            `${SF_API_BASE}/api/profile/me`
          );
          
          window.SylvanFlowAuth.handleAuthResponse(profileRes);
          
          if (profileRes.ok) {
            const profileData = await profileRes.json();
            if (profileData.ok && profileData.profile) {
              setProfile(profileData.profile);
              // Update state store
              if (window.SylvanFlowState) {
                window.SylvanFlowState.setProfile(profileData.profile);
              }
            }
          }
        } catch (e) {
          if (window.uiLogger) {
            window.uiLogger.uiWarn("Failed to load profile:", e.message || e);
          }
        }
        
        // ✅ SYSTEM_MAP COMPLIANT: No user_id query param (identity via Authorization header)
        // Load destinations
        const url = `${SF_API_BASE}/api/destinations`;
          
        // ✅ FIX: Log identity source (Bearer token, not email) (admin-only, sanitized)
        const sessionToken = localStorage.getItem('sylvanflow_session_token');
        if (window.uiLogger) {
          window.uiLogger.uiLog(`[IDENTITY] [EXPLORE]`, {
            identitySource: 'Bearer token (authenticatedFetch)',
            tokenLength: sessionToken?.length || 0,
            profileUserKeyLength: profile?.user_key?.length || 0,
            note: 'Identity derived server-side from Authorization header'
          });
          
          window.uiLogger.uiLog(`[EXPLORE] Fetch URL: ${url}`);
          window.uiLogger.uiLog(`[EXPLORE] SF_API_BASE: ${SF_API_BASE}`);
          window.uiLogger.uiLog(`[EXPLORE] Using authenticatedFetch: ${!!window.SylvanFlowAuth?.authenticatedFetch}`);
        }
          
        try {
          const res = await window.SylvanFlowAuth.authenticatedFetch(url);
          
          window.SylvanFlowAuth.handleAuthResponse(res);
          
          if (window.uiLogger) {
            window.uiLogger.uiLog(`[EXPLORE] Response status: ${res.status}`);
          }
          
          if (!res.ok) {
            if (window.uiLogger) {
              window.uiLogger.uiWarn(`API call failed: ${res.status}. This is normal for local preview.`);
            }
            setDestinations([]);
            setFlowPlanCount(0);
            lastDestinations = [];
            lastDestFlowPlanCount = 0;
            setError(null);
          } else {
          const data = await res.json();
          
          const destinationsLength = data.destinations?.length || 0;
          const flowPlanCountValue = data.flow_plan_count || 0;
          if (window.uiLogger) {
            window.uiLogger.uiLog(`[EXPLORE] Response metadata`, {
              responseKeys: Object.keys(data),
              ok: data.ok,
              destinationsLength: destinationsLength,
              flowPlanCount: flowPlanCountValue
            });
          }
          
          // Data mismatch warning log
          if (flowPlanCountValue > 0 && destinationsLength === 0) {
            const sessionToken = localStorage.getItem('sylvanflow_session_token');
            if (window.uiLogger) {
              window.uiLogger.uiWarn(`[EXPLORE] ⚠️ DATA MISMATCH:`, {
                identitySource: 'Bearer token (authenticatedFetch)',
                tokenLength: sessionToken?.length || 0,
                profileUserKeyLength: profile?.user_key?.length || 0,
                flowPlanCount: flowPlanCountValue,
                destinationsLength: destinationsLength,
                hasFirstTripKey: !!(data.destinations?.[0]?.trip_key || data.destinations?.[0]?.Trip_Key || data.destinations?.[0]?.Flow_Plan_ID),
                firstTripKeyLength: (data.destinations?.[0]?.trip_key || data.destinations?.[0]?.Trip_Key || data.destinations?.[0]?.Flow_Plan_ID || '').length,
                rawResponseKeys: Object.keys(data)
              });
            }
          }
          
          if (data.destinations && data.destinations.length > 0) {
            const firstDest = data.destinations[0];
            if (window.uiLogger) {
              window.uiLogger.uiLog(`[EXPLORE] First destination sample:`, {
                hasTripKey: !!(firstDest.trip_key || firstDest.Trip_Key || firstDest.Flow_Plan_ID),
                tripKeyLength: (firstDest.trip_key || firstDest.Trip_Key || firstDest.Flow_Plan_ID || '').length,
                hasDestination: !!firstDest.destination || !!firstDest.Destination,
                hasDestinationName: !!firstDest.destination_name || !!firstDest.Destination_Name
              });
            }
          }
          
          if (data.ok) {
            const dests = data.destinations || [];
            // Normalize trip_keys for all destinations
            if (window.NormalizeTripKey) {
              dests.forEach(dest => {
                const tripKey = dest.trip_key || dest.Trip_Key || dest.Flow_Plan_ID;
                if (tripKey) {
                  dest._normalized_trip_key = window.NormalizeTripKey.normalizeTripKey(tripKey);
                }
              });
            }
            lastDestinations = dests;
            lastDestFlowPlanCount = flowPlanCountValue;
            setDestinations(dests);
            setFlowPlanCount(flowPlanCountValue);
            // Update state store
            if (window.SylvanFlowState) {
              window.SylvanFlowState.setDestinations(dests);
            }
          } else {
            if (window.uiLogger) {
              window.uiLogger.uiWarn("API returned error:", data.error);
            }
            lastDestinations = [];
            lastDestFlowPlanCount = 0;
            setDestinations([]);
            setFlowPlanCount(0);
          }
          }
        } catch (fetchError) {
          // Network error (e.g., no backend running) - show empty state
          if (window.uiLogger) {
            window.uiLogger.uiWarn("Fetch error (normal for local preview):", fetchError.message);
          }
          lastDestinations = [];
          lastDestFlowPlanCount = 0;
          setDestinations([]);
          setFlowPlanCount(0);
          setError(null); // Don't show error for local preview
        }
      } catch (e) {
        if (window.uiLogger) {
          window.uiLogger.uiError("Data load error:", e.message || e);
        }
        // Only show error for unexpected errors, not API failures
        if (e.message && !e.message.includes("Failed to load destinations")) {
          setError(e.message);
        } else {
          setError(null);
        }
      } finally {
        const itSnap = await loadItineraries();
        setLoading(false);
        const tripKeys = new Set(
          (itSnap.itineraries || []).map((i) => i.trip_key || i.Trip_Key).filter(Boolean)
        );
        return {
          destinationCount: lastDestinations.length,
          itineraryCount: (itSnap.itineraries || []).length,
          flowPlanCount: Math.max(lastDestFlowPlanCount, itSnap.flowPlanCount || 0),
          tripKeys
        };
      }
    };

    const loadDataRef = useRef(loadData);
    useEffect(() => {
      loadDataRef.current = loadData;
    });

    const itinerariesPollRef = useRef([]);
    const destinationsPollRef = useRef([]);
    const flowPlanCountPollRef = useRef(0);
    useEffect(() => {
      itinerariesPollRef.current = itineraries;
    }, [itineraries]);
    useEffect(() => {
      destinationsPollRef.current = destinations;
    }, [destinations]);
    useEffect(() => {
      flowPlanCountPollRef.current = flowPlanCount;
    }, [flowPlanCount]);

    const flowPlanPollTimerRef = useRef(null);

    /** iframe flow-plan-form posts message after itinerary.generate accepts — refresh Explore + poll every 15s until new plan rows appear (sf-itinerary async). */
    useEffect(() => {
      const tripKeySetFromList = (list) => {
        const s = new Set();
        (list || []).forEach((i) => {
          const k = i.trip_key || i.Trip_Key;
          if (k) s.add(k);
        });
        return s;
      };

      const snapshotFresh = (snap, baseline) => {
        if (!snap || !baseline) return false;
        if (snap.itineraryCount > baseline.itineraryCount) return true;
        if (snap.destinationCount > baseline.destinationCount) return true;
        if (snap.flowPlanCount > baseline.flowPlanCount) return true;
        for (const k of snap.tripKeys) {
          if (!baseline.tripKeys.has(k)) return true;
        }
        return false;
      };

      const onMessage = (ev) => {
        if (!ev.data || ev.data.type !== 'sylvanflow-flow-plan-submitted') return;
        if (ev.data.source && ev.data.source !== 'flow-plan-form') return;

        if (flowPlanPollTimerRef.current) {
          clearInterval(flowPlanPollTimerRef.current);
          flowPlanPollTimerRef.current = null;
        }

        const baseline = {
          itineraryCount: itinerariesPollRef.current.length,
          destinationCount: destinationsPollRef.current.length,
          flowPlanCount: flowPlanCountPollRef.current,
          tripKeys: tripKeySetFromList(itinerariesPollRef.current)
        };

        let runs = 0;
        const MAX_RUNS = 120;

        const tick = async () => {
          runs += 1;
          const snap = await loadDataRef.current();
          if (snapshotFresh(snap, baseline)) {
            if (flowPlanPollTimerRef.current) {
              clearInterval(flowPlanPollTimerRef.current);
              flowPlanPollTimerRef.current = null;
            }
            if (window.uiLogger) {
              window.uiLogger.uiLog('[EXPLORE] Flow plan generation reflected in Explore data — poll stopped');
            }
            return;
          }
          if (runs >= MAX_RUNS && flowPlanPollTimerRef.current) {
            clearInterval(flowPlanPollTimerRef.current);
            flowPlanPollTimerRef.current = null;
            if (window.uiLogger) {
              window.uiLogger.uiWarn('[EXPLORE] Flow-plan poll stopped after max runs (itinerary may still be processing)');
            }
          }
        };

        if (window.uiLogger) {
          window.uiLogger.uiLog('[EXPLORE] flow-plan-form submitted — immediate refresh + 15s poll until materialized');
        }
        tick();
        flowPlanPollTimerRef.current = setInterval(tick, 15000);
      };

      window.addEventListener('message', onMessage);
      return () => {
        window.removeEventListener('message', onMessage);
        if (flowPlanPollTimerRef.current) {
          clearInterval(flowPlanPollTimerRef.current);
          flowPlanPollTimerRef.current = null;
        }
      };
    }, []);

    useEffect(() => {
      if (selectedTripKey) {
        loadItineraryDetails(selectedTripKey);
      } else {
        setSelectedItinerary(null);
      }
    }, [selectedTripKey]);

    useEffect(() => {
      if (itineraries.length === 0 || itinerariesLoading) return;
      const state = window.appState?.get() || {};
      const planId = state.flowPlan?.trip_key;
      if (!planId) return;
      const normalizedPlanId = window.NormalizeTripKey?.normalizeTripKey(planId) || planId;
      if (selectedTripKey) {
        const normalizedSelected =
          window.NormalizeTripKey?.normalizeTripKey(selectedTripKey) || selectedTripKey;
        if (normalizedPlanId === normalizedSelected) return;
      }
      const foundItinerary = itineraries.find((it) => {
        const itKey = it.trip_key || it.Trip_Key;
        if (!itKey) return false;
        const normalizedItKey = it._normalized_trip_key || window.NormalizeTripKey?.normalizeTripKey(itKey) || itKey;
        return normalizedItKey === normalizedPlanId;
      });
      if (foundItinerary) {
        const tk = foundItinerary.trip_key || foundItinerary.Trip_Key;
        setSelectedTripKey(tk);
      }
    }, [itineraries, itinerariesLoading, selectedTripKey]);

    // ✅ Search removed - show all destinations
    const filteredDestinations = destinations;

    filteredDestinations.forEach((dest) => {
      const tripKey = dest.trip_key || dest.Trip_Key || dest.Flow_Plan_ID;
      if (tripKey && window.NormalizeTripKey) {
        dest._normalized_trip_key = window.NormalizeTripKey.normalizeTripKey(tripKey);
      }
    });

    // Open destination detail inside Explore TV viewport (same content as explore-detail page)
    const navigateToDetail = (destinationId, e) => {
      if (e) {
        e.preventDefault();
        e.stopPropagation();
      }
      if (window.uiLogger) {
        window.uiLogger.uiLog(`[EXPLORE] Destination detail in TV (destinationId length):`, destinationId?.length || 0);
      }
      setTvActivityEmbed(null);
      setTvDestinationId(destinationId);
      setExploreTvMode('destinationDetail');
    };

    /** TV destination detail primary CTA — same navigation as purple Explore hotkey (trip program / timeline + scroll). */
    const handleTvDestinationTripTimeline = (destination) => {
      const tripKey = destination.Trip_Key || destination.Flow_Plan_ID || destination.trip_key || '';
      if (!tripKey) {
        scrollToTripTimeline();
        return;
      }
      const normalizedTripKey = window.NormalizeTripKey?.normalizeTripKey(tripKey) || tripKey;
      if (window.appState && typeof window.appState.set === 'function') {
        window.appState.set({
          view: 'explore',
          flowPlan: { trip_key: normalizedTripKey },
          destinationParams: null
        });
      }
      const foundItinerary = itineraries.find((it) => {
        const itKey = it.trip_key || it.Trip_Key;
        if (!itKey) return false;
        const n = window.NormalizeTripKey?.normalizeTripKey(itKey) || itKey;
        return n === normalizedTripKey;
      });
      if (foundItinerary) {
        setSelectedTripKey(foundItinerary.trip_key || foundItinerary.Trip_Key);
      } else {
        setSelectedTripKey(tripKey);
      }
      scrollToTripTimeline();
    };

    const ST = typeof window !== 'undefined' && window.SYLVAN_TECH_THEME ? window.SYLVAN_TECH_THEME : null;
    const topPlanRing =
      ST?.layout?.recoTopDefault || 'relative overflow-hidden rounded-2xl p-[2px]';
    const displayName = window.SYLVAN_TECH_THEME?.normalizeProfileDisplayName?.(
      profile?.name || profile?.user_name,
      uiStrings.defaultGuestName
    ) || uiStrings.defaultGuestName;
    const heroDest = findDestinationForTripKey(destinations, selectedTripKey);
    const heroImage =
      (heroDest && heroDest.PhotosOfDestinations) || selectedItinerary?.destination_photo || '';
    const heroTitle =
      (
        heroDest &&
        `${heroDest.Name || ''}${
          heroDest.Region && heroDest.Name !== heroDest.Region ? `, ${heroDest.Region}` : ''
        }`.trim()
      ) ||
      (selectedItinerary?.destination_label || '').trim() ||
      uiStrings.heroFallbackTitle;
    const heroDestinationId =
      heroDest && (heroDest.Destination_ID || heroDest.id || heroDest.Trip_Key || '');
    const clientTodayYmd = exploreClientDayYmd();
    const hasActiveFlowPlan = itineraries.some((it) =>
      exploreIsCurrentOrUpcomingItinerary(it, clientTodayYmd)
    );
    const hasPlanContent = destinations.length > 0 || itineraries.length > 0;
    const showRecovery = !hasPlanContent && flowPlanCount > 0;
    const showEmpty = !hasPlanContent && !showRecovery;
    const showNoCurrentHero =
      !itinerariesLoading &&
      hasPlanContent &&
      !hasActiveFlowPlan &&
      !selectedTripKey &&
      exploreTvMode === 'hero';

    /** Strip `hover:*` Tailwind utilities — product targets phones/tablets, not pointer-hover desktops. */
    const stripHoverClasses = (cls) => {
      if (typeof cls !== 'string' || !cls.trim()) return cls;
      return cls
        .split(/\s+/)
        .filter((t) => t && !t.startsWith('hover:'))
        .join(' ');
    };

    /** Bottom inset: fixed hotbar + InternalShellTwinNav — shared token with Power Up (`dockScrollPaddingBottom`). */
    const exploreDockBottomInset =
      ST?.classes?.dockScrollPaddingBottom ||
      'pb-[max(0.75rem,calc(9.25rem+env(safe-area-inset-bottom)))]';
    /** Fixed chrome + central TV viewport (hero | create form | trip program | destination detail); hotbar + twin nav docked at bottom (no inline legal/footer strip). */
    const exploreMainColumn =
      'relative z-[1] flex min-h-0 flex-1 flex-col ' + exploreDockBottomInset;
    const btnPrimaryFull =
      stripHoverClasses(ST?.classes?.btnPrimaryFull) ||
      'w-full min-h-[44px] rounded-xl font-semibold text-black bg-gradient-to-r from-teal-400 to-teal-300 shadow-[0_0_22px_-6px_rgba(45,226,197,0.65)] active:brightness-95 transition';
    const btnGhost =
      stripHoverClasses(ST?.classes?.btnGhost) ||
      'w-full min-h-[44px] rounded-xl font-semibold bg-white/5 text-slate-200 border border-white/10 active:bg-white/15 transition';
    const sectionDivider = ST?.classes?.sectionDivider || 'border-b border-white/10';

    const flowPlanFormIframeSrc = useMemo(() => {
      const lang = profile?.preferred_language || 'en';
      const params = new URLSearchParams();
      params.set('lang', lang);
      params.set('embed', 'tv');
      return `/flow-plan-form?${params.toString()}`;
    }, [profile?.preferred_language]);

    /** Sub-views that use flat TV chrome (no duplicate gradient rim). */
    const exploreTvOverlay =
      exploreTvMode === 'createPlan' ||
      exploreTvMode === 'tripProgram' ||
      exploreTvMode === 'destinationDetail' ||
      exploreTvMode === 'activityDetail' ||
      exploreTvMode === 'askSylvan';

    return (
      <div className="mx-auto flex h-full min-h-0 w-full max-h-[100dvh] max-w-[440px] flex-1 flex-col overflow-x-hidden bg-black [touch-action:manipulation]">
        <header className="sf-explore-header-edge-pulse relative z-[2] flex-shrink-0 border-b border-white/[0.06] px-4 pb-2 pt-[max(0.5rem,env(safe-area-inset-top))]">
          <div className="grid grid-cols-[2.5rem_minmax(0,1fr)_2.5rem] items-center gap-x-2">
            <button
              type="button"
              onClick={() => window.dispatchEvent(new CustomEvent('sylvanflow-open-drawer'))}
              className="flex h-10 w-10 shrink-0 items-center justify-center justify-self-start rounded-lg active:bg-white/10"
              aria-label="Menu"
            >
              <img
                src={
                  (typeof window !== 'undefined' &&
                    window.SF_TAB_GLYPH_SRC &&
                    window.SF_TAB_GLYPH_SRC['explore-radar']) ||
                  '/assets/nav-explore-premium.webp?v=9'
                }
                alt=""
                width={40}
                height={40}
                className="pointer-events-none h-10 w-10 object-contain"
                decoding="async"
                draggable={false}
              />
            </button>
            <div className="min-w-0 justify-self-center text-center">
              <h1 className="text-[22px] font-bold uppercase leading-tight tracking-[0.08em] text-[#2DE2C5]">
                {uiStrings.tabExploreBadge}
              </h1>
              <p className="mt-1 text-[13px] font-normal leading-snug text-[#9CA3AF]">{uiStrings.yourFlowBegins}</p>
            </div>
            <button
              type="button"
              onClick={() => exploreNavigateToView('power-up')}
              className="flex h-10 w-10 shrink-0 items-center justify-center justify-self-end overflow-hidden rounded-full ring-2 ring-[#2DE2C5] ring-offset-2 ring-offset-black"
              style={{
                backgroundColor: profilePhotoUrl ? '#0a0a0a' : '#2DE2C5',
                boxShadow: '0 0 22px rgba(45,226,197,0.35)'
              }}
              aria-label={displayName}
            >
              {profilePhotoUrl ? (
                <img
                  src={profilePhotoUrl}
                  alt={displayName}
                  className="h-full w-full object-cover"
                  onError={(e) => {
                    e.target.style.display = 'none';
                    const par = e.target.parentElement;
                    if (par) par.style.backgroundColor = '#2DE2C5';
                    const fb = e.target.nextElementSibling;
                    if (fb) fb.style.display = 'flex';
                  }}
                />
              ) : null}
              <span
                className="flex h-full w-full items-center justify-center text-[11px] font-bold tracking-tight text-black"
                style={{ display: profilePhotoUrl ? 'none' : 'flex' }}
              >
                {(displayName || 'U')[0].toUpperCase()}
              </span>
            </button>
          </div>
        </header>

        <div className={exploreMainColumn}>
          {(loading || !translationsReady) && (
            <div className="flex min-h-0 flex-1 flex-col justify-center px-4 py-6">
              <ExploreFrayHold
                linkLabel={uiStrings.loadingHoldLink}
                titleText={uiStrings.loadingHoldTitle}
                captionText={uiStrings.loadingHoldCaption}
              />
            </div>
          )}

          {!loading && translationsReady && error && (
            <div className="shrink-0 px-4 pb-4">
              <div
                className={
                  ST?.classes?.alertError ||
                  'rounded-xl border border-rose-500/35 bg-rose-950/50 p-4 text-sm text-rose-100'
                }
              >
                <p className="font-semibold">{uiStrings.destinationsErrorHeading}</p>
                <p className="mt-1 opacity-90">{error}</p>
                <button type="button" className={`${btnGhost} mt-4`} onClick={() => loadData()}>
                  {uiStrings.retryButton}
                </button>
              </div>
            </div>
          )}

          {!loading && translationsReady && !error && showRecovery && (
            <div className="shrink-0 px-4 pb-4">
              <div className="rounded-xl border border-white/10 bg-[#161b22] p-5 text-center">
                <p className="text-sm text-slate-300">{uiStrings.recoverySyncMessage}</p>
                <button
                  type="button"
                  className={btnPrimaryFull + ' mt-4'}
                  onClick={async () => {
                    if (window.SylvanFlowState) {
                      window.SylvanFlowState.invalidateItineraries();
                      window.SylvanFlowState.invalidateDestinations();
                    }
                    const sessionToken = localStorage.getItem('sylvanflow_session_token');
                    if (window.uiLogger) {
                      window.uiLogger.uiLog(`[EXPLORE] 🔄 Refresh triggered - Identity:`, {
                        identitySource: 'Bearer token (authenticatedFetch)',
                        tokenLength: sessionToken?.length || 0,
                        profileUserKeyLength: profile?.user_key?.length || 0,
                        flowPlanCount,
                        destinationsLength: destinations.length
                      });
                    }
                    await loadData();
                  }}
                >
                  {uiStrings.recoveryRefreshButton}
                </button>
              </div>
            </div>
          )}

          {!loading && translationsReady && !error && (hasPlanContent || showEmpty) && !showRecovery && (
            <>
              {hasPlanContent ? (
              <div className="relative z-[5] shrink-0 overflow-visible px-4 pb-1 pt-0">
                <div className="my-2 border-t border-white/10" />

                {itineraries.length > 0 && showNoCurrentHero ? (
                  <div className="mb-3">
                    <div className="mb-2 font-mono text-[9px] font-semibold uppercase tracking-[0.24em] text-[#2DE2C5]/75">
                      {uiStrings.exploreNoActivePlanLabel}
                    </div>
                    <p className="text-sm font-medium text-white/95">{uiStrings.exploreNoCurrentPlanTitle}</p>
                    <p className="mt-1 text-[10px] leading-snug text-slate-500">{uiStrings.exploreFlowPickHotbarHint}</p>
                  </div>
                ) : null}

                {itineraries.length > 0 && selectedTripKey && !showNoCurrentHero ? (
                  <div className="mb-3">
                    <div className="mb-2 font-mono text-[9px] font-semibold uppercase tracking-[0.24em] text-[#2DE2C5]/75">
                      {uiStrings.flowPlanCurrentLabel}
                    </div>
                    <p className="truncate text-sm font-medium text-white/95">
                      {(() => {
                        const row =
                          selectedItinerary ||
                          itineraries.find((i) => i.trip_key === selectedTripKey);
                        return row
                          ? formatFlowPlanDropdownLabel(row)
                          : uiStrings.heroFallbackTitle;
                      })()}
                    </p>
                    <p className="mt-1 text-[10px] leading-snug text-slate-500">{uiStrings.exploreFlowPickHotbarHint}</p>
                  </div>
                ) : null}
              </div>
              ) : null}

              {/* TV viewport — flex-fill hero rim + shared max-height token (`tvRimMaxHeight`); overlay modes stay flex-fill */}
              <div className="relative z-[1] flex min-h-0 flex-1 flex-col justify-start px-3 pt-3 pb-3 sm:px-4 sm:pt-4 sm:pb-4">
                {!exploreTvOverlay ? (
                  <div
                    className={`relative flex min-h-0 flex-1 w-full flex-col overflow-hidden ${ST?.classes?.tvRimMaxHeight || 'max-h-[min(82svh,calc(100dvh-9.25rem-env(safe-area-inset-bottom)))]'} ${topPlanRing}`}
                    style={{
                      background:
                        'linear-gradient(135deg, rgba(45,226,197,0.85), rgba(16,185,129,0.55))'
                    }}
                  >
                    <div className="relative flex max-h-full min-h-0 flex-1 flex-col overflow-hidden rounded-[13px] border border-white/[0.09] bg-[#070a0c] shadow-[0_10px_32px_-24px_rgba(0,0,0,0.92)]">
                      <div className="flex max-h-full min-h-0 flex-1 flex-col overflow-y-auto overscroll-y-contain">
                        {showNoCurrentHero ? (
                          <div className="relative flex min-h-0 flex-1 flex-col overflow-hidden rounded-[14px] border border-white/10 bg-[#070a0c]">
                            <div className="pointer-events-none absolute inset-0 z-[1] overflow-hidden" aria-hidden>
                              <img
                                src={EXPLORE_NO_CURRENT_HERO_IMAGE}
                                alt=""
                                decoding="async"
                                className="absolute inset-0 h-full w-full object-cover"
                                style={{ opacity: 0.32 }}
                                onError={(e) => {
                                  e.currentTarget.src = '/assets/powerup-nature-hero.png';
                                }}
                              />
                              <div className="absolute inset-0 bg-gradient-to-b from-[#030806]/55 via-[#070a0c]/88 to-[#070a0c]/95" />
                              <div className="absolute inset-0 bg-[radial-gradient(ellipse_80%_55%_at_50%_18%,rgba(45,226,197,0.14),transparent_62%)]" />
                            </div>
                            <div className="relative z-[2] flex min-h-0 flex-1 flex-col items-center justify-center gap-5 px-5 py-8 text-center sm:px-8 sm:py-10">
                              <p className="max-w-[19rem] font-mono text-[10px] font-semibold uppercase tracking-[0.28em] text-[#2DE2C5]/88">
                                {uiStrings.exploreNoActivePlanLabel}
                              </p>
                              <h3 className="max-w-[20rem] text-xl font-semibold leading-snug text-white text-balance sm:text-2xl">
                                {uiStrings.exploreNoCurrentPlanTitle}
                              </h3>
                              <p className="max-w-[21rem] text-sm leading-relaxed text-slate-300/95">
                                {uiStrings.exploreNoCurrentPlanMessage}
                              </p>
                              <button
                                type="button"
                                className={`${btnPrimaryFull} mx-auto w-full max-w-[min(100%,18rem)]`}
                                onClick={tryOpenFlowPlanForm}
                              >
                                {uiStrings.createFlowPlan}
                              </button>
                            </div>
                          </div>
                        ) : selectedTripKey ? (
                          <div className="flex min-h-full w-full flex-1 flex-col text-white">
                            <div
                              className="relative flex min-h-0 w-full min-w-0 flex-1 flex-col overflow-hidden rounded-[14px] border border-white/10 bg-[#070a0c] shadow-[0_12px_48px_-20px_rgba(0,0,0,0.85)]"
                            >
                              {!heroImage ? (
                                <div className="pointer-events-none absolute inset-0 z-[1] overflow-hidden" aria-hidden>
                                  <img
                                    src={EXPLORE_NO_CURRENT_HERO_IMAGE}
                                    alt=""
                                    decoding="async"
                                    className="absolute inset-0 h-full w-full object-cover"
                                    style={{ opacity: 0.28 }}
                                    onError={(e) => {
                                      e.currentTarget.src = '/assets/powerup-nature-hero.png';
                                    }}
                                  />
                                  <div className="absolute inset-0 bg-gradient-to-b from-[#030806]/50 via-[#070a0c]/82 to-[#070a0c]/94" />
                                </div>
                              ) : null}
                              {heroImage ? (
                                <button
                                  type="button"
                                  className="group relative flex w-full max-w-full min-h-0 flex-1 cursor-pointer flex-col overflow-hidden rounded-t-[14px] bg-[#070a0c] text-left outline-none focus-visible:ring-2 focus-visible:ring-[#2DE2C5]/60"
                                  onClick={(e) =>
                                    heroDestinationId ? navigateToDetail(heroDestinationId, e) : undefined
                                  }
                                  disabled={!heroDestinationId}
                                >
                                  <div className="flex min-h-0 flex-1 flex-col justify-center pt-1 pb-0 sm:pt-2 sm:pb-0">
                                    <div className="relative mx-auto aspect-[16/10] w-full max-h-[min(46svh,340px)] min-h-[128px] overflow-hidden bg-slate-800">
                                      <img
                                        src={heroImage}
                                        alt={heroTitle}
                                        className="absolute inset-0 h-full w-full object-cover object-center transition duration-300 group-active:brightness-110"
                                        onError={(e) => {
                                          e.target.style.display = 'none';
                                        }}
                                      />
                                      {heroDestinationId ? (
                                        <div className="pointer-events-none absolute inset-0 bg-gradient-to-t from-black/85 via-black/25 to-transparent" />
                                      ) : null}
                                      {heroDestinationId ? (
                                        <div className="pointer-events-none absolute inset-x-0 bottom-0 flex justify-center px-3 pb-3 pt-10 sm:px-4 sm:pb-4 sm:pt-12">
                                          <span className="max-w-full text-center font-mono text-[10px] font-semibold uppercase tracking-[0.22em] text-[#2DE2C5]/95 drop-shadow-[0_0_12px_rgba(45,226,197,0.45)]">
                                            {uiStrings.clickDiscoverMore}
                                          </span>
                                        </div>
                                      ) : null}
                                    </div>
                                  </div>
                                </button>
                              ) : null}
                              <div
                                className={
                                  'relative z-[2] flex w-full min-w-0 shrink-0 flex-col p-4 sm:p-5' +
                                  (!heroImage ? ' min-h-[min(42svh,280px)] justify-end' : '')
                                }
                              >
                                <div className="mb-1 font-mono text-[9px] font-semibold uppercase tracking-[0.22em] text-[#2DE2C5]/85">
                                  {uiStrings.flowPlanCurrentLabel}
                                </div>
                                <h3 className="mb-1 break-words text-xl font-semibold leading-snug text-white text-balance">
                                  {heroTitle}
                                </h3>
                                <p className="break-words text-xs leading-snug text-slate-500">
                                  {(itineraries.length !== 1
                                    ? uiStrings.flowPlanUserTitlePlural
                                    : uiStrings.flowPlanUserTitle
                                  ).replace('{displayName}', displayName)}
                                </p>
                                {!heroImage && heroDestinationId ? (
                                  <button
                                    type="button"
                                    className={btnPrimaryFull + ' mt-4'}
                                    onClick={(e) => navigateToDetail(heroDestinationId, e)}
                                  >
                                    {uiStrings.clickDiscoverMore}
                                  </button>
                                ) : null}
                              </div>
                            </div>
                          </div>
                        ) : showEmpty ? (
                          <div className="flex min-h-0 flex-1 flex-col items-center justify-center gap-5 px-5 py-8 text-center sm:py-10">
                            <p className="max-w-[18rem] text-sm leading-relaxed text-slate-300">
                              {uiStrings.createFirstFlowPlanMessage}
                            </p>
                            <button
                              type="button"
                              className={`${btnPrimaryFull} mx-auto w-full max-w-[min(100%,18rem)]`}
                              onClick={tryOpenFlowPlanForm}
                            >
                              {uiStrings.createFlowPlan}
                            </button>
                          </div>
                        ) : (
                          <div className="flex min-h-0 flex-1 flex-col items-center justify-center px-4 py-10 text-center text-xs leading-snug text-slate-500 sm:py-12">
                            {uiStrings.exploreFlowPickHotbarHint}
                          </div>
                        )}
                      </div>
                      <div
                        className="pointer-events-none absolute bottom-[calc(0.75rem+0.3cm)] right-[calc(0.75rem+0.2cm)] z-[5] flex items-center"
                      >
                        <span className="inline-flex max-w-[min(100%,calc(100%-1.5rem))] items-center whitespace-nowrap text-[9px] leading-none text-slate-400/95">
                          Powered by SylvanFlow<sup className="text-[6px] align-super">™</sup>
                        </span>
                      </div>
                    </div>
                  </div>
                ) : (
                  <div className="flex min-h-0 max-h-full flex-1 flex-col overflow-hidden rounded-2xl border border-white/[0.09] bg-[#070a0c] shadow-[0_24px_56px_-36px_rgba(0,0,0,0.92)]">
                    <div className={tvEmbedChrome.row}>
                      <button
                        type="button"
                        className={tvEmbedChrome.backBtn}
                        onClick={() => {
                          if (exploreTvMode === 'activityDetail') {
                            setTvActivityEmbed(null);
                            setExploreTvMode('tripProgram');
                            return;
                          }
                          setExploreTvMode('hero');
                          setTvDestinationId(null);
                          setTvActivityEmbed(null);
                        }}
                      >
                        ←{' '}
                        {exploreTvMode === 'askSylvan'
                          ? uiStrings.tabExploreBadge
                          : exploreTvMode === 'activityDetail'
                            ? uiStrings.hotbarTripTimelineTitle
                            : uiStrings.flowPlanCurrentLabel}
                      </button>
                      <span className={tvEmbedChrome.title}>
                        {exploreTvMode === 'askSylvan'
                          ? uiStrings.tabAskSylvanShort
                          : exploreTvMode === 'createPlan'
                            ? uiStrings.createNewFlowPlan
                            : exploreTvMode === 'destinationDetail'
                              ? uiStrings.exploreDestinationChromeTitle
                              : exploreTvMode === 'activityDetail'
                                ? uiStrings.exploreActivityChromeTitle
                                : tripProgramSource === 'timeline'
                                  ? uiStrings.hotbarTripTimelineTitle
                                  : uiStrings.hotbarFlowPickTitle}
                      </span>
                      <span className={tvEmbedChrome.spacer} aria-hidden />
                    </div>
                    <div className="flex min-h-0 flex-1 flex-col overflow-hidden bg-[#070a0c]">
                    {exploreTvMode === 'createPlan' && (
                      <iframe
                        title={uiStrings.createNewFlowPlan}
                        src={flowPlanFormIframeSrc}
                        className="min-h-0 w-full flex-1 border-0 bg-[#070a0c]"
                      />
                    )}
                    {exploreTvMode === 'tripProgram' && (
                      <div
                        className={`flex min-h-0 flex-1 flex-col ${topPlanRing}`}
                        style={{
                          background:
                            'linear-gradient(135deg, rgba(45,226,197,0.85), rgba(16,185,129,0.55))'
                        }}
                      >
                        <div className="flex min-h-0 flex-1 flex-col overflow-hidden rounded-[13px] border border-white/10 bg-[#070a0c] shadow-[0_12px_48px_-20px_rgba(0,0,0,0.85)]">
                          <div className="flex min-h-0 flex-1 flex-col overflow-y-auto overscroll-y-contain px-3 pb-8 pt-3">
                        {tripProgramSource === 'pick' && flowPlanCount > 0 ? (
                          <div
                            className="mb-3 shrink-0 rounded-lg border border-[#2DE2C5]/25 bg-[rgba(45,226,197,0.06)] px-3 py-2 text-center font-mono text-[10px] uppercase tracking-[0.18em] text-[#2DE2C5]/90"
                            role="status"
                          >
                            {(uiStrings.flowPlansCreatedCount || '').replace(
                              /\{number\}/g,
                              String(flowPlanCount)
                            )}
                          </div>
                        ) : null}
                        {itineraries.length > 0 && selectedTripKey ? (
                          <div
                            ref={tripTimelineAnchorRef}
                            id="explore-trip-timeline-anchor"
                            className="scroll-mt-4 space-y-4 sm:space-y-6"
                          >
                            {selectedItinerary && selectedItinerary.items_by_day ? (
                              <>
                                {Object.entries(selectedItinerary.items_by_day)
                                  .sort(([dateA], [dateB]) => dateA.localeCompare(dateB))
                                  .map(([date, activities]) => (
                                    <div key={date} className="mb-6 space-y-2">
                                      <div className="mb-3">
                                        <div className="mb-1 text-[9px] font-semibold tracking-[0.12em] text-[#2DE2C5]/75 sm:tracking-[0.24em]">
                                          {new Date(date).toLocaleDateString(getExploreDateLocaleTag(), {
                                            weekday: 'long'
                                          })}
                                        </div>
                                        <h2 className="mb-2 text-xl font-semibold text-white sm:text-2xl">
                                          {formatDateDisplay(date)}
                                        </h2>
                                        {activities.length > 0 && (
                                          <p className="text-xs text-slate-400 sm:text-sm">
                                            {activities.length}{' '}
                                            {activities.length !== 1
                                              ? uiStrings.flowPlanActivities
                                              : uiStrings.flowPlanActivity}
                                          </p>
                                        )}
                                      </div>
                                      <div className="space-y-3">
                                        {activities.map((activity, idx) => {
                                          const imageUrl = getActivityImage(activity);
                                          const location = getActivityLocation(activity);
                                          const startTime =
                                            activity.start_time_local ||
                                            activity.start_time ||
                                            activity.Start_Time ||
                                            '';
                                          const endTime =
                                            activity.end_time_local ||
                                            activity.end_time ||
                                            activity.End_Time ||
                                            '';
                                          const timeRange = endTime
                                            ? `${formatTime(startTime)} - ${formatTime(endTime)}`
                                            : `${formatTime(startTime)} -`;
                                          const title =
                                            activity.title || activity.Title || uiStrings.flowPlanActivity;
                                          const description = activity.description || activity.Description || '';
                                          return (
                                            <div
                                              key={idx}
                                              className="block w-full cursor-pointer overflow-hidden rounded-xl border border-white/[0.08] bg-[#11151d]/95 text-left shadow-[inset_0_0_0_1px_rgba(45,226,197,0.05)] transition active:border-[#2DE2C5]/30 active:shadow-[0_0_24px_-8px_rgba(45,226,197,0.25)]"
                                              onClick={(e) => {
                                                e.preventDefault();
                                                e.stopPropagation();
                                                if (!selectedTripKey || !date || idx === undefined) {
                                                  return;
                                                }
                                                navigateToActivityDetail({
                                                  tripKey: selectedTripKey,
                                                  dayKey: date,
                                                  activityIndex: idx,
                                                  lang: window.SylvanFlowState?.getLanguage?.() || 'en',
                                                  activity: activity
                                                });
                                              }}
                                            >
                                              <div className="flex items-start gap-3 p-3">
                                                {imageUrl ? (
                                                  <div className="h-20 w-20 flex-shrink-0 overflow-hidden rounded-lg border border-white/10 bg-black/40 sm:h-24 sm:w-24">
                                                    <img
                                                      src={imageUrl}
                                                      alt={title}
                                                      className="h-full w-full object-cover"
                                                      onError={(e) => {
                                                        e.target.style.display = 'none';
                                                      }}
                                                    />
                                                  </div>
                                                ) : (
                                                  <div className="flex h-20 w-20 flex-shrink-0 items-center justify-center rounded-lg border border-dashed border-[#2DE2C5]/20 bg-black/30 sm:h-24 sm:w-24">
                                                    <span className="text-xl opacity-60">◆</span>
                                                  </div>
                                                )}
                                                <div className="flex min-w-0 flex-1 items-start justify-between gap-3">
                                                  <div className="min-w-0 flex-1">
                                                    <div className="mb-1 font-mono text-[10px] font-semibold uppercase tracking-[0.12em] text-[#2DE2C5]/90">
                                                      {timeRange}
                                                    </div>
                                                    <h4 className="mb-2 text-base font-semibold text-white sm:text-lg">
                                                      {title}
                                                    </h4>
                                                    {description ? (
                                                      <p className="text-xs leading-relaxed text-slate-400 sm:text-sm">
                                                        {description}
                                                      </p>
                                                    ) : null}
                                                    {location ? (
                                                      <p className="mt-1 font-mono text-[10px] text-slate-500 sm:text-xs">
                                                        📍 {location}
                                                      </p>
                                                    ) : null}
                                                  </div>
                                                  <div className="flex flex-shrink-0 items-center text-[#2DE2C5]/50">
                                                    <svg
                                                      xmlns="http://www.w3.org/2000/svg"
                                                      width="20"
                                                      height="20"
                                                      viewBox="0 0 24 24"
                                                      fill="none"
                                                      stroke="currentColor"
                                                      strokeWidth="2"
                                                      strokeLinecap="round"
                                                      strokeLinejoin="round"
                                                    >
                                                      <polyline points="9 18 15 12 9 6" />
                                                    </svg>
                                                  </div>
                                                </div>
                                              </div>
                                            </div>
                                          );
                                        })}
                                      </div>
                                    </div>
                                  ))}
                              </>
                            ) : (
                              <ExploreFrayHold
                                linkLabel={uiStrings.loadingHoldLink}
                                titleText={uiStrings.itineraryLoadingTitle}
                                captionText={uiStrings.itineraryLoadingCaption}
                              />
                            )}
                          </div>
                        ) : (
                          <div className="flex flex-1 flex-col items-center justify-center px-4 py-10 text-center text-sm text-slate-400">
                            {uiStrings.exploreFlowPickHotbarHint}
                          </div>
                        )}
                          </div>
                        </div>
                      </div>
                    )}
                    {exploreTvMode === 'activityDetail' &&
                    tvActivityEmbed &&
                    window.ExploreActivityDetailEmbedded ? (
                      <div
                        className={`flex min-h-0 flex-1 flex-col ${topPlanRing}`}
                        style={{
                          background:
                            'linear-gradient(135deg, rgba(168,85,247,0.55), rgba(45,226,197,0.35))'
                        }}
                      >
                        <div className="flex min-h-0 flex-1 flex-col overflow-hidden rounded-[13px] border border-white/10 bg-[#070a0c] shadow-[0_12px_48px_-20px_rgba(0,0,0,0.85)]">
                          {React.createElement(window.ExploreActivityDetailEmbedded, {
                            tripKey: tvActivityEmbed.tripKey,
                            dayKey: tvActivityEmbed.dayKey,
                            activityIndex: tvActivityEmbed.activityIndex,
                            initialActivity: tvActivityEmbed.activity,
                            labels: {
                              loading: uiStrings.itineraryLoadingTitle,
                              noDescription: uiStrings.exploreActivityNoDescription,
                              missingParams: uiStrings.exploreActivityMissingParams,
                              fallbackTitle: uiStrings.flowPlanActivity,
                              labelDestination: uiStrings.exploreActivityLabelDestination,
                              labelDay: uiStrings.exploreActivityLabelDay,
                              labelLocation: uiStrings.exploreActivityLabelLocation,
                              labelTime: uiStrings.exploreActivityLabelTime,
                              labelType: uiStrings.exploreActivityLabelType
                            }
                          })}
                        </div>
                      </div>
                    ) : exploreTvMode === 'activityDetail' && tvActivityEmbed ? (
                      <div className="flex min-h-0 flex-1 flex-col items-center justify-center px-4 py-8 text-center text-sm text-rose-300">
                        {uiStrings.destinationsErrorHeading}
                      </div>
                    ) : null}
                    {exploreTvMode === 'destinationDetail' && tvDestinationId ? (
                      window.ExploreDestinationDetailEmbedded ? (
                        <div
                          className={`flex min-h-0 flex-1 flex-col ${topPlanRing}`}
                          style={{
                            background:
                              'linear-gradient(135deg, rgba(45,226,197,0.72), rgba(16,185,129,0.42))'
                          }}
                        >
                          <div className="flex min-h-0 flex-1 flex-col overflow-hidden rounded-[13px] border border-white/10 bg-[#070a0c] shadow-[0_12px_48px_-20px_rgba(0,0,0,0.85)]">
                            {React.createElement(window.ExploreDestinationDetailEmbedded, {
                              destinationId: tvDestinationId,
                              onBack: () => {
                                setExploreTvMode('hero');
                                setTvDestinationId(null);
                                setTvActivityEmbed(null);
                              },
                              onViewFlowPlan: handleTvDestinationTripTimeline,
                              labels: {
                                loading: uiStrings.exploreDestinationLoading,
                                noDescription: uiStrings.exploreDestinationNoDescription,
                                aiVoice: uiStrings.exploreDestinationAiVoice,
                                viewFlowPlan: uiStrings.hotbarTripTimelineTitle,
                                viewFlowPlanSub: uiStrings.hotbarTripTimelineSub,
                                goBack: uiStrings.exploreDestinationGoBack
                              }
                            })}
                          </div>
                        </div>
                      ) : (
                        <div className="flex min-h-0 flex-1 flex-col items-center justify-center px-4 py-8 text-center text-sm text-rose-300">
                          {uiStrings.destinationsErrorHeading}
                        </div>
                      )
                    ) : null}
                    {exploreTvMode === 'askSylvan' && window.AskSylvanPage ? (
                      <div className="flex min-h-0 min-w-0 max-h-full flex-1 flex-col overflow-hidden">
                        {React.createElement(window.AskSylvanPage, {
                          embeddedExploreTv: true,
                          embeddedPowerUpTv: false
                        })}
                      </div>
                    ) : null}
                    </div>
                  </div>
                )}
              </div>
            </>
          )}

        </div>

        {itineraryPickerOpen && itineraries.length > 0 ? (
          <>
            <button
              type="button"
              className="fixed inset-0 z-[66] cursor-default border-0 bg-black/55 p-0 backdrop-blur-[1px]"
              aria-label="Close"
              onClick={() => setItineraryPickerOpen(false)}
            />
            <div
              className="fixed left-3 right-3 z-[70] flex max-h-[min(44vh,360px)] flex-col overflow-hidden rounded-xl border border-[#2DE2C5]/35 bg-[#070c10] shadow-[0_18px_56px_-16px_rgba(0,0,0,0.95)]"
              role="dialog"
              aria-modal="true"
              aria-labelledby="explore-trip-sheet-title"
              style={{
                bottom: 'calc(9.5rem + env(safe-area-inset-bottom, 0px))'
              }}
            >
              <div
                id="explore-trip-sheet-title"
                className="border-b border-white/10 px-3 py-2 font-mono text-[9px] font-semibold uppercase tracking-[0.2em] text-[#2DE2C5]/85"
              >
                {uiStrings.flowPlanCurrentLabel}
              </div>
              <ul className="max-h-[min(38vh,300px)] overflow-y-auto py-1" role="listbox">
                {itineraries.map((itinerary) => {
                  const picked = itinerary.trip_key === selectedTripKey;
                  return (
                    <li key={itinerary.trip_key} role="none">
                      <button
                        type="button"
                        role="option"
                        aria-selected={picked}
                        className={`flex w-full items-start gap-2 px-3 py-3 text-left text-sm transition-colors active:bg-white/[0.06] ${
                          picked ? 'bg-[#2DE2C5]/15 text-white' : 'text-white/95 active:bg-white/[0.04]'
                        }`}
                        onClick={() => {
                          const v = itinerary.trip_key;
                          setSelectedTripKey(v || null);
                          if (v && window.appState) {
                            window.appState.set({ flowPlan: { trip_key: v } });
                          }
                          setTvDestinationId(null);
                          /* Destination hero — trip timeline/activities stay on purple hotkey */
                          setExploreTvMode('hero');
                          setTripProgramSource('pick');
                          setItineraryPickerOpen(false);
                        }}
                      >
                        <span className="mt-0.5 shrink-0 text-[13px] leading-none text-[#2DE2C5]/90">
                          {picked ? '●' : '○'}
                        </span>
                        <span className="min-w-0 flex-1 leading-snug">{formatFlowPlanDropdownLabel(itinerary)}</span>
                      </button>
                    </li>
                  );
                })}
              </ul>
            </div>
          </>
        ) : null}

        {!loading && translationsReady ? (
          <div className="pointer-events-auto fixed bottom-0 left-0 right-0 z-[55] flex flex-col">
            <div
              className={`relative z-[2] min-w-0 ${
                ST?.classes?.shellTwinDockOuter ||
                'border-t border-white/[0.06] bg-[#05070a]/97 backdrop-blur-md pt-0 shadow-[inset_0_1px_0_rgba(255,255,255,0.05)]'
              }`}
            >
              <div
                className={
                  ST?.classes?.shellTwinDockHubInner || 'px-3 sm:px-4 pb-0.5 pt-0.5'
                }
              >
                <div className="mx-auto grid w-full max-w-[440px] grid-cols-4 gap-1 min-w-0 [touch-action:manipulation]">
                {EXPLORE_HOTBAR_SPECS.map((spec, hubIdx) => {
                  const title =
                    spec.key === 'create'
                      ? uiStrings.createNewFlowPlan
                      : spec.key === 'flowPick'
                        ? uiStrings.hotbarFlowPickTitle
                        : spec.key === 'tripTimeline'
                          ? uiStrings.hotbarTripTimelineTitle
                          : uiStrings.tabAskSylvanShort;
                  const sub =
                    spec.key === 'create'
                      ? uiStrings.hotbarCreateSub
                      : spec.key === 'flowPick'
                        ? uiStrings.hotbarFlowPickSub
                        : spec.key === 'tripTimeline'
                          ? uiStrings.hotbarTripTimelineSub
                          : uiStrings.hotbarAskSylvanSub;
                  const onTileClick = () => {
                    if (spec.key === 'create') {
                      tryOpenFlowPlanForm();
                      return;
                    }
                    if (spec.key === 'flowPick') {
                      if (itineraries.length >= 1) {
                        setTvActivityEmbed(null);
                        setTvDestinationId(null);
                        setTripProgramSource('pick');
                        setExploreTvMode('hero');
                        setItineraryPickerOpen((o) => !o);
                        return;
                      }
                      tryOpenFlowPlanForm();
                      return;
                    }
                    if (spec.key === 'tripTimeline') {
                      scrollToTripTimeline();
                      return;
                    }
                    if (spec.key === 'askChat') {
                      setTvActivityEmbed(null);
                      setTvDestinationId(null);
                      setExploreTvMode('askSylvan');
                      return;
                    }
                  };
                  const flowPickPickerActive =
                    spec.key === 'flowPick' && itineraryPickerOpen && itineraries.length > 0;
                  const pickerBlue = flowPickPickerActive;
                  const glow = pickerBlue ? 'rgba(59,130,246,0.48)' : spec.glow;
                  const ring = pickerBlue ? 'rgba(147,197,253,0.59)' : spec.ring;
                  return (
                    <button
                      key={spec.key}
                      type="button"
                      onClick={onTileClick}
                      aria-expanded={
                        spec.key === 'flowPick' && itineraries.length > 0 ? itineraryPickerOpen : undefined
                      }
                      aria-haspopup={
                        spec.key === 'flowPick' && itineraries.length > 0 ? 'listbox' : undefined
                      }
                      className={`group relative flex min-h-0 min-w-0 flex-col items-center overflow-hidden rounded-2xl border px-0.5 pb-2 pt-2 text-center backdrop-blur-lg transition duration-150 motion-safe:active:scale-[0.97] motion-safe:hover:brightness-110 ${
                        pickerBlue ? 'border-blue-400/45' : 'border-white/10'
                      }`}
                      style={{
                        background: [
                          `radial-gradient(96% 52% at 50% 108%, ${glow}, transparent 56%)`,
                          'radial-gradient(95% 54% at 50% -4%, rgba(255,255,255,0.09) 0%, transparent 46%)',
                          pickerBlue
                            ? 'linear-gradient(168deg, rgba(59,130,246,0.15) 0%, rgba(255,255,255,0.04) 11%, rgba(10,16,32,0.58) 40%, rgba(3,8,18,0.94) 100%)'
                            : 'linear-gradient(168deg, rgba(255,255,255,0.078) 0%, rgba(255,255,255,0.03) 11%, rgba(18,24,34,0.58) 40%, rgba(4,6,10,0.94) 100%)'
                        ].join(', '),
                        boxShadow: [
                          'inset 0 1px 0 rgba(255,255,255,0.13)',
                          `inset 0 0 0 1px ${ring}`,
                          'inset 0 14px 32px -10px rgba(0,0,0,0.32)',
                          'inset 0 -36px 48px -12px rgba(0,0,0,0.48)',
                          `0 16px 44px -16px ${glow}`,
                          pickerBlue ? '0 0 30px -10px rgba(59,130,246,0.53)' : '',
                          '0 1px 0 rgba(0,0,0,0.42)'
                        ]
                          .filter(Boolean)
                          .join(', ')
                      }}
                      aria-label={title}
                    >
                      <div
                        className="pointer-events-none absolute inset-x-0 bottom-0 h-[42%] opacity-[0.28]"
                        style={{
                          background: `linear-gradient(to top, ${glow}, transparent)`
                        }}
                        aria-hidden
                      />
                      <div
                        className="pointer-events-none absolute inset-x-0 bottom-0 h-px opacity-[0.82]"
                        style={{
                          background: `linear-gradient(90deg, transparent, ${glow}, transparent)`
                        }}
                        aria-hidden
                      />
                      <div
                        className="pointer-events-none absolute inset-x-0 top-0 h-px bg-gradient-to-r from-transparent via-white/40 to-transparent opacity-[0.85]"
                        aria-hidden
                      />
                      <div
                        className="pointer-events-none absolute inset-x-0 top-[2.25rem] h-12 -translate-y-1/2 opacity-[0.16]"
                        style={{
                          background: `radial-gradient(ellipse 72% 85% at 50% 50%, ${glow}, transparent 72%)`
                        }}
                        aria-hidden
                      />
                      <div className="relative mb-1.5 flex h-10 w-full max-w-full shrink-0 items-center justify-center">
                        <div
                          className="absolute h-11 w-11 rounded-full opacity-[0.56] blur-lg motion-safe:animate-pulse motion-safe:transition-opacity motion-safe:group-hover:opacity-[0.68]"
                          style={{ background: glow, animationDelay: `${hubIdx * 0.12}s` }}
                          aria-hidden
                        />
                        <div
                          className="relative flex h-10 w-10 shrink-0 items-center justify-center overflow-hidden rounded-full border border-white/[0.12] bg-gradient-to-b from-slate-800/52 via-[#0a1018]/78 to-[#020408]/92 backdrop-blur-sm motion-safe:transition-transform motion-safe:group-active:scale-95"
                          style={{
                            boxShadow: `inset 0 1px 0 rgba(255,255,255,0.12), inset 0 -14px 26px -10px rgba(0,0,0,0.42), inset 0 0 0 1px ${ring}, 0 0 28px -8px ${glow}`
                          }}
                        >
                          <div
                            className="pointer-events-none absolute inset-0 rounded-full opacity-[0.82]"
                            style={{
                              background: `radial-gradient(circle at 50% 24%, ${glow}, transparent 54%)`
                            }}
                            aria-hidden
                          />
                          <span className="relative z-[1] flex items-center justify-center">
                            <ExploreHotbarIcon spec={spec} />
                          </span>
                        </div>
                      </div>
                      <p className="relative z-[1] w-full min-w-0 truncate px-0.5 text-center text-[9px] font-bold leading-tight text-white">
                        {title}
                      </p>
                      <p className="relative z-[1] mt-0.5 line-clamp-2 w-full min-w-0 px-0.5 text-center text-[7px] leading-snug text-[#9CA3AF]">
                        {sub}
                      </p>
                    </button>
                  );
                })}
              </div>
              </div>
            </div>
            {TwinNav ? (
              <div className="relative z-[1] min-w-0">
                <TwinNav
                  variant="explore"
                  leftLabel={uiStrings.navTwinPowerUp}
                  rightLabel={uiStrings.navTwinNuAsk}
                  ariaLabel="Power Up and NuAsk"
                  staticTwinEdge
                />
              </div>
            ) : null}
          </div>
        ) : null}
        {createFlowPlanBlockedMessage ? (
          <div
            className="fixed inset-0 z-[280] flex items-center justify-center bg-black/82 px-5 backdrop-blur-sm"
            role="dialog"
            aria-modal="true"
            aria-live="polite"
          >
            <div className="max-w-[min(92vw,22rem)] rounded-2xl border border-white/15 bg-[#0c1018] px-5 py-6 text-center shadow-[0_0_48px_-12px_rgba(45,226,197,0.35)]">
              <p className="text-sm leading-relaxed text-slate-100 sm:text-base">{createFlowPlanBlockedMessage}</p>
              <button
                type="button"
                className="mt-5 min-h-[44px] w-full rounded-xl bg-gradient-to-r from-teal-400 to-teal-300 px-4 py-2.5 text-sm font-semibold text-black shadow-[0_0_22px_-6px_rgba(45,226,197,0.55)] active:brightness-95"
                onClick={() => setCreateFlowPlanBlockedMessage(null)}
              >
                OK
              </button>
            </div>
          </div>
        ) : null}
      </div>
    );
  }

  // Export component
  if (typeof window !== 'undefined') {
    window.ExplorePage = ExplorePage;
  }
})();
