import React, { FC, useState, useEffect, useRef } from "react";
import {
  View,
  Text,
  TouchableOpacity,
  StyleSheet,
  Platform,
  Linking,
  Image,
  Animated,
  useWindowDimensions,
} from "react-native";
import ActionSheet, { SheetManager, ScrollView } from "react-native-actions-sheet";
import { MaterialCommunityIcons } from "@expo/vector-icons";
import { getTrainType } from "@/lib/getTrainType";
import { useSheetMaxHeight } from "./useSheetMaxHeight";
import { TRAIN_TYPE_CONFIG } from "@/lib/webview/trainTypeConfig";
import type { NavigateFunction } from "@/types";
import type { OperationLogs, CustomTrainData } from "@/lib/CommonTypes";
import type { UnyohubData, ElesiteData } from "@/types/unyohub";
import { useUnyohub } from "@/stateBox/useUnyohub";
import { useElesite } from "@/stateBox/useElesite";
import { useThemeColors } from "@/lib/theme";
import ViewShot from "react-native-view-shot";
import * as Sharing from "expo-sharing";

export type TrainDataSourcesPayload = {
  trainNum: string;
  /** UnyoHub検索用列番（上書き列番があればそちら） */
  unyohubTrainNum?: string;
  unyohubEntries: UnyohubData[];
  elesiteEntries: ElesiteData[];
  todayOperation: OperationLogs[];
  navigate: NavigateFunction;
  expoPushToken: string;
  /** customTrainDataDetector から取得した priority 値 */
  priority: number;
  /** 進行方向: true = 上り (vehicle_img) / false = 下り (vehicle_img_right)
   * 未指定の場合は列番の奇数偶数でフォールバック */
  direction?: boolean;
  /** customTrainDataDetector の全データ */
  customTrainData?: CustomTrainData;
  /** 種別名 (e.g. "特急") */
  typeName?: string;
  /** 列車名・行先 (e.g. "モーニングEXP高松 高松行") */
  trainName?: string;
  /** 始発駅名 */
  departureStation?: string;
  /** 終着駅名（ダイヤから） */
  destinationStation?: string;
};

const HUB_LOGO_PNG = require("@/assets/relationLogo/unyohub_logo.webp");
const ELESITE_LOGO_PNG = require("@/assets/relationLogo/elesite_logo.jpg");

/** ISO 8601 日時文字列を "HH:MM" 形式にフォーマット */
const formatHHMM = (iso: string): string => {
  try {
    const d = new Date(iso);
    const h = d.getHours().toString().padStart(2, "0");
    const m = d.getMinutes().toString().padStart(2, "0");
    return `${h}:${m}`;
  } catch {
    return "";
  }
};

/**
 * "YYYY-MM-DD HH:MM:SS" 形式の文字列を "M/D HH:MM" 形式にフォーマット
 * ISO 8601 文字列にも対応
 */
const formatDateHHMM = (datetime: string): string => {
  try {
    // "YYYY-MM-DD HH:MM:SS" → space を T に置換して安全にパース
    const d = new Date(datetime.replace(" ", "T"));
    const mo = d.getMonth() + 1;
    const day = d.getDate();
    const h = d.getHours().toString().padStart(2, "0");
    const m = d.getMinutes().toString().padStart(2, "0");
    return `${mo}/${day} ${h}:${m}`;
  } catch {
    return "";
  }
};

/* ------------------------------------------------------------------ */
/* FormationChips: "+"区切りの編成名をチップ形式で表示                 */
/* ------------------------------------------------------------------ */
const FormationChips: FC<{ text: string; color: string }> = ({ text, color }) => {
  const parts = text.split("+").map((s) => s.trim()).filter(Boolean);
  if (parts.length === 0) return null;
  return (
    <View style={{ flexDirection: "row", alignItems: "center", flexWrap: "wrap", gap: 2 }}>
      {parts.map((part, i) => (
        <React.Fragment key={i}>
          {i > 0 && (
            <Text style={{ fontSize: 11, color, fontWeight: "bold" }}>+</Text>
          )}
          <View
            style={{
              borderWidth: 1,
              borderColor: color + "66",
              borderRadius: 4,
              paddingHorizontal: 5,
              paddingVertical: 1,
              backgroundColor: color + "12",
            }}
          >
            <Text style={{ fontSize: 12, fontWeight: "700", color }} numberOfLines={1}>
              {part}
            </Text>
          </View>
        </React.Fragment>
      ))}
    </View>
  );
};

/* ------------------------------------------------------------------ */
/* FadingSubCycler                                                       */
/* ------------------------------------------------------------------ */
type FadingSubItem = { label: string; datetime: string | null };

const FadingSubCycler: FC<{ items: FadingSubItem[]; color: string }> = ({ items, color }) => {
  const { colors } = useThemeColors();
  const [index, setIndex] = useState(0);
  const opacity = useRef(new Animated.Value(1)).current;

  useEffect(() => {
    if (items.length <= 1) return;
    const cycle = () => {
      Animated.timing(opacity, { toValue: 0, duration: 300, useNativeDriver: true }).start(() => {
        setIndex((i) => (i + 1) % items.length);
        Animated.timing(opacity, { toValue: 1, duration: 300, useNativeDriver: true }).start();
      });
    };
    const id = setInterval(cycle, 3000);
    return () => clearInterval(id);
  }, [items.length]);

  const item = items[index];
  return (
    <Animated.View style={{ opacity, flexDirection: "row", alignItems: "center", gap: 4 }}>
      {item.datetime ? (
        <Text style={{ fontSize: 11, color: colors.textSecondary }} numberOfLines={1}>
          {`最終投稿: ${formatDateHHMM(item.datetime)}`}
        </Text>
      ) : (
        <Text style={{ fontSize: 11, color: colors.textSecondary }} numberOfLines={1}>
          {`運用情報 ${index + 1}/${items.length}`}
        </Text>
      )}
    </Animated.View>
  );
};

/* ------------------------------------------------------------------ */
/* ActiveFormationChipsCycler: 全チップ常時表示、アクティブのみ枠アニメ */
/* ------------------------------------------------------------------ */
const ActiveFormationChipsCycler: FC<{ items: string[]; color: string }> = ({ items, color }) => {
  const [activeIndex, setActiveIndex] = useState(0);
  const borderAnim = useRef(new Animated.Value(items.length <= 1 ? 1.5 : 0)).current;

  useEffect(() => {
    if (items.length <= 1) return;
    Animated.timing(borderAnim, { toValue: 1.5, duration: 200, useNativeDriver: false }).start();
    const id = setInterval(() => {
      Animated.timing(borderAnim, { toValue: 0, duration: 200, useNativeDriver: false }).start(() => {
        setActiveIndex((i) => (i + 1) % items.length);
        Animated.timing(borderAnim, { toValue: 1.5, duration: 200, useNativeDriver: false }).start();
      });
    }, 3000);
    return () => clearInterval(id);
  }, [items.length]);

  return (
    <View style={{ flexDirection: "row", alignItems: "center", flexWrap: "wrap", gap: 4 }}>
      {items.map((text, i) => {
        const isActive = i === activeIndex;
        const parts = text.split("+").map((s) => s.trim()).filter(Boolean);
        const inner = (
          <View style={{ flexDirection: "row", alignItems: "center", flexWrap: "wrap", gap: 2 }}>
            {parts.map((part, j) => (
              <React.Fragment key={j}>
                {j > 0 && (
                  <Text style={{ fontSize: 11, fontWeight: "bold", color: isActive ? color : color + "55" }}>+</Text>
                )}
                <Text
                  style={{
                    fontSize: 12,
                    fontWeight: isActive ? "700" : "500",
                    color: isActive ? color : color + "55",
                    paddingHorizontal: 4,
                    paddingVertical: 1,
                  }}
                  numberOfLines={1}
                >
                  {part}
                </Text>
              </React.Fragment>
            ))}
          </View>
        );
        return (
          <React.Fragment key={i}>
            {i > 0 && (
              <Text style={{ fontSize: 11, color: color + "55" }}>・</Text>
            )}
            {isActive ? (
              <Animated.View
                style={{
                  borderWidth: borderAnim,
                  borderColor: color,
                  borderRadius: 6,
                  paddingHorizontal: 4,
                  paddingVertical: 1,
                  backgroundColor: color + "12",
                }}
              >
                {inner}
              </Animated.View>
            ) : (
              inner
            )}
          </React.Fragment>
        );
      })}
    </View>
  );
};

export const TrainDataSources: FC<{ payload?: TrainDataSourcesPayload }> = ({
  payload,
}) => {
  // ── フックはすべて条件分岐より前に呼ぶ（Rules of Hooks）──
  const { useUnyohub: unyohubEnabled } = useUnyohub();
  const { useElesite: elesiteEnabled } = useElesite();
  const { colors, fixed } = useThemeColors();
  const { height: windowHeight } = useWindowDimensions();
  const viewShot = useRef(null);
  const [isCapturing, setIsCapturing] = useState(false);
  const maxHeight = useSheetMaxHeight();

  if (!payload) return null;

  const onCapture = async () => {
    setIsCapturing(true);
    await new Promise(resolve => setTimeout(resolve, 150));
    try {
      const url = await (viewShot.current as any).capture();
      const ok = await Sharing.isAvailableAsync();
      if (ok) {
        await Sharing.shareAsync("file://" + url, { mimeType: "image/jpeg", dialogTitle: "Share this image" });
      }
    } finally {
      setIsCapturing(false);
    }
  };

  const {
    trainNum,
    unyohubTrainNum: unyohubTrainNumProp,
    unyohubEntries,
    elesiteEntries = [],
    todayOperation,
    navigate,
    expoPushToken,
    priority,
    direction: directionProp,
    customTrainData,
    typeName,
    trainName,
    departureStation,
    destinationStation,
  } = payload;

  // __メモ書き サフィックスを除去して列番部分だけを返す
  const stripMemoSuffix = (value: string | null | undefined): string => {
    if (!value) return "";
    return value.split("__")[0].trim();
  };

  const isFreightRetsuban = trainNum.includes("レ");
  const hubTrainNum = (unyohubTrainNumProp || trainNum).replace(/レ/g, "");
  const freightUnyohubCandidates = (() => {
    const digits = hubTrainNum.replace(/[^\d]/g, "");
    const candidates = new Set<string>();
    if (!digits) return candidates;
    candidates.add(digits);
    if (/^\d{2}$/.test(digits)) {
      candidates.add(`30${digits}`);
      candidates.add(`90${digits}`);
    } else if (/^(30|90)\d{2}$/.test(digits)) {
      candidates.add(digits.slice(-2));
    }
    return candidates;
  })();
  const matchesHubTrainNum = (candidate?: string | null): boolean => {
    if (!candidate) return false;
    const normalized = stripMemoSuffix(candidate).replace(/レ/g, "");
    if (normalized === hubTrainNum) return true;
    if (!isFreightRetsuban) return false;
    return freightUnyohubCandidates.has(normalized);
  };

  // APIデータ内の元の列番（__メモ付き）を取得して運用Hub連携 URL に使う
  const originalHubTrainNum = (() => {
    for (const entry of unyohubEntries) {
      const match = entry.trains?.find(
        (t) => stripMemoSuffix(t.train_number).replace(/レ/g, "") === hubTrainNum,
      );
      if (match?.train_number) return match.train_number;
    }
    return hubTrainNum;
  })();

  // 進行方向の確定:
  // 1. payload.direction が明示されていればそれを使う
  // 2. customTrainData.directions が設定されていればそれを使う
  // 3. どちらもなければ列番の偶数 = 上り / 奇数 = 下り でフォールバック
  const resolvedDirection: boolean = (() => {
    if (directionProp !== undefined) return directionProp;
    if (customTrainData?.directions !== undefined)
      return !!customTrainData.directions;
    return parseInt(trainNum.replace(/[^\d]/g, ""), 10) % 2 === 0;
  })();

  const close = () => SheetManager.hide("TrainDataSources");

  const openWebView = (uri: string, useExitButton: boolean) => {
    SheetManager.hide("TrainDataSources");
    SheetManager.hide("EachTrainInfo");
    navigate("generalWebView", { uri, useExitButton });
  };

  /* ── 各ソースの状態 ─────────────────────────────── */
  const opCount = todayOperation.length;
  const unyoCount = unyohubEntries.length;
  const elesiteCount = elesiteEntries.length;
  const hasTrainInfo = priority > 200;

  // 運用情報: train_ids / related_train_ids の位置番号でソートして unit_ids を収集
  // "4565M,2" のようなカンマ区切り位置番号を解析
  // 上り(resolvedDirection=true)=ASC, 下り(false)=DESC
  const positionOf = (op: (typeof todayOperation)[number]): number => {
    const all = [...(op.train_ids ?? []), ...(op.related_train_ids ?? [])];
    const match = all.find((id) => id.split(",")[0] === trainNum);
    const pos = match ? parseInt(match.split(",")[1] ?? "0", 10) : 0;
    return isNaN(pos) ? 0 : pos;
  };
  const sortedOperation = [...todayOperation].sort((a, b) => {
    const diff = positionOf(a) - positionOf(b);
    return resolvedDirection ? diff : -diff;
  });
  const allUnitIds = [
    ...new Set(sortedOperation.flatMap((op) => op.unit_ids ?? [])),
  ];
  const fallbackIds = sortedOperation
    .flatMap((op) => op.train_ids ?? [])
    .slice(0, 4);
  const unitIdsSub =
    allUnitIds.length > 0
      ? null
      : opCount > 0
        ? fallbackIds.join("・") || "運用記録あり"
        : "本日の運用記録なし";

  // 最新運用ログの更新時刻（IDが最大のエントリのdate）
  const latestOperationDate =
    opCount > 0
      ? [...todayOperation].sort((a, b) => b.id - a.id)[0]?.date ?? null
      : null;

  const operationDetail = (
    <View style={styles.operationDetailBlock}>
      {opCount > 0 &&
        (allUnitIds.length > 0 ? (
          <Text style={styles.unitIdText}>
            {allUnitIds.slice(0, 8).join("・")}
            {allUnitIds.length > 8 ? `他${allUnitIds.length - 8}件` : ""}
          </Text>
        ) : (
          <Text style={styles.subText}>
            {fallbackIds.join("・") || "運用記録あり"}
          </Text>
        ))}
      {opCount > 0 && <DirectionBanner direction={resolvedDirection} />}
      <CyclingRefDirectionBanner
        rows={[
          {
            leftLabel: "高松/岡山",
            lineLabel: "予讃線",
            rightLabel: "松山/宇和島",
          },
          { leftLabel: "高松", lineLabel: "高徳線", rightLabel: "徳島" },
          {
            leftLabel: "高松/岡山",
            lineLabel: "土讃線",
            rightLabel: "高知/窪川",
          },
          { leftLabel: "高松", lineLabel: "瀬戸大橋線", rightLabel: "岡山" },
          {
            leftLabel: "阿波池田/鳴門",
            lineLabel: "徳島/鳴門/牟岐線",
            rightLabel: "牟岐/阿波海南",
          },
        ]}
        color="#0099CC"
      />
    </View>
  );

  // 鉄道運用Hub: 車番(formations) が空でないエントリのみ表示対象にする
  const hasNonEmptyFormations = unyohubEntries.some(
    (e) => !!e.formations && e.formations.trim() !== "",
  );
  const nonEmptyFormationEntries = unyohubEntries.filter(
    (e) => !!e.formations && e.formations.trim() !== "",
  );

  // 最終投稿日時（エントリ中の最新値）
  const unyohubLastPostedDatetime =
    unyohubEntries
      .map((e) => e.last_posted_datetime)
      .filter((d): d is string => !!d)
      .sort()
      .at(-1) ?? null;

  // フェードサイクル用アイテム（編成あるエントリのみ）
  const unyohubSubItems: FadingSubItem[] = nonEmptyFormationEntries.map((e) => ({
    label: e.formations?.trim() || e.operation_id || "",
    datetime: e.last_posted_datetime ?? null,
  }));

  // 投稿日時が今日でない場合はカードを薄く表示（"YYYY-MM-DD HH:MM:SS" 形式）
  const todayDateStr = new Date().toLocaleDateString("sv"); // "YYYY-MM-DD"
  const isUnyohubStale =
    unyohubLastPostedDatetime == null ||
    !unyohubLastPostedDatetime.startsWith(todayDateStr);

  // 運用グループ名（重複除去して最大3件）
  const unyohubGroupNames = [
    ...new Set(
      nonEmptyFormationEntries
        .map((e) => e.operation_group_name)
        .filter((n) => !!n && n.trim() !== ""),
    ),
  ]
    .slice(0, 3)
    .join(" / ");

  // 新フィールドのチップ表示フラグ
  const hubHasIsQuotation = unyohubEntries.some((e) => e.is_quotation === true);
  const hubHasFromBeginner = unyohubEntries.some((e) => e.from_beginner === true);
  const hubHasCommentExists = unyohubEntries.some((e) => e.comment_exists === true);
  const hubHasHiddenByDefault = unyohubEntries.some((e) => e.hidden_by_default === true);

  // 先頭エントリで direction を取得し、表示順を決定:
  //   outbound → position_forward 昇順 (pos=1 が宇和島/南端側)
  //   inbound  → position_forward 降順 (pos=MAX が宇和島/南端側)
  const matchedDirection = nonEmptyFormationEntries[0]?.trains?.find(
    (t) => matchesHubTrainNum(t.train_number),
  )?.direction;
  const hubSortDescending = matchedDirection === "inbound";

  const sortedFormationDisplay = [...nonEmptyFormationEntries]
    .sort((a, b) => {
      const posA =
        a.trains?.find((t) => matchesHubTrainNum(t.train_number))
          ?.position_forward ?? 0;
      const posB =
        b.trains?.find((t) => matchesHubTrainNum(t.train_number))
          ?.position_forward ?? 0;
      return hubSortDescending ? posB - posA : posA - posB;
    })
    .slice(0, 4);

  const formationDetail = (
    <View style={styles.operationDetailBlock}>
      {hasNonEmptyFormations && (
        <View style={{ opacity: isUnyohubStale ? 0.4 : 1 }}>
          <ActiveFormationChipsCycler
            items={sortedFormationDisplay.map((e) => e.formations || "")}
            color={colors.textAccent}
          />
          {nonEmptyFormationEntries.length > 4 && (
            <Text style={{ fontSize: 11, color: colors.textTertiary, marginTop: 2 }}>
              他{nonEmptyFormationEntries.length - 4}件
            </Text>
          )}
        </View>
      )}
      {unyohubGroupNames !== "" && (
        <Text style={[styles.subText, { color: colors.textSecondary }]}>{unyohubGroupNames}</Text>
      )}
      {(hubHasIsQuotation || hubHasFromBeginner || hubHasCommentExists || hubHasHiddenByDefault) && (
        <View style={styles.metaChipRow}>
          {hubHasIsQuotation && (
            <View style={styles.metaChip}>
              <MaterialCommunityIcons name="content-copy" size={11} color="#888" />
              <Text style={styles.metaChipText}>引用データ</Text>
            </View>
          )}
          {hubHasFromBeginner && (
            <View style={[styles.metaChip, styles.metaChipOrange]}>
              <MaterialCommunityIcons name="account-school" size={11} color="#f57c00" />
              <Text style={[styles.metaChipText, { color: "#f57c00" }]}>初心者投稿</Text>
            </View>
          )}
          {hubHasCommentExists && (
            <View style={styles.metaChip}>
              <MaterialCommunityIcons name="comment-text-outline" size={11} color="#0077aa" />
              <Text style={[styles.metaChipText, { color: "#0077aa" }]}>コメントあり</Text>
            </View>
          )}
          {hubHasHiddenByDefault && (
            <View style={[styles.metaChip, styles.metaChipOrange]}>
              <MaterialCommunityIcons name="eye-off-outline" size={11} color="#f57c00" />
              <Text style={[styles.metaChipText, { color: "#f57c00" }]}>非表示設定</Text>
            </View>
          )}
        </View>
      )}
      <RefDirectionBanner
        rows={[{ leftLabel: "宇和島/宿毛/阿波海南" }]}
        color="#888"
      />
    </View>
  );

  // えれサイト最終投稿時刻（last_reported_at が最新のエントリ）
  const elesiteLastReportedAt =
    elesiteEntries
      .map((e) => e.report_info?.last_reported_at)
      .filter((d): d is string => !!d)
      .sort()
      .at(-1) ?? null;

  // えれサイト: units が1件以上あるエントリのみ「データあり」と判定
  const elesiteHasNonEmptyFormations = elesiteEntries.some(
    (e) => (e.formation_config?.units?.length ?? 0) > 0,
  );
  const elesiteNonEmptyFormationEntries = elesiteEntries
    .filter((e) => (e.formation_config?.units?.length ?? 0) > 0)
    .sort((a, b) => {
      // high松(left_station)側のユニットを先に表示
      // (heading_to === "left") === is_leading が true → high松(left)端のユニット
      const aNav = a.trains?.find((t) => t.train_number.trim() === trainNum)?.nav;
      const bNav = b.trains?.find((t) => t.train_number.trim() === trainNum)?.nav;
      const aIsLeft =
        (aNav?.heading_to === "left") === (aNav?.is_leading === true);
      const bIsLeft =
        (bNav?.heading_to === "left") === (bNav?.is_leading === true);
      if (aIsLeft === bIsLeft) return 0;
      return aIsLeft ? -1 : 1;
    });
  // えれサイト: 編成名テキスト（formation_config.units 優先）
  const elesiteFormationNames =
    elesiteNonEmptyFormationEntries
      .slice(0, 4)
      .map((e) => {
        const units = e.formation_config?.units;
        return units?.length
          ? units.map((u) => u.formation).join("+")
          : e.formations;
      })
      .join("・") +
    (elesiteNonEmptyFormationEntries.length > 4
      ? ` 他${elesiteNonEmptyFormationEntries.length - 4}件`
      : "");

  // 列車情報 subテキスト
  const trainInfoSub = customTrainData?.vehicle_formation
    ? customTrainData.vehicle_formation
    : hasTrainInfo
      ? "臨時情報あり / コミュニティ樓所データを確認・編集"
      : "編成データ・コミュニティ独自データを確認・編集";

  const trainDetail = customTrainData ? (
    <TrainInfoDetail
      data={customTrainData}
      typeName={typeName}
      trainName={trainName}
      departureStation={departureStation}
      destinationStation={destinationStation}
    />
  ) : null;

  const elesiteFormationDetail = (
    <View style={styles.operationDetailBlock}>
      {elesiteHasNonEmptyFormations && (
        <Text style={styles.unitIdText}>{elesiteFormationNames}</Text>
      )}
      {elesiteCount > 0
        ? (() => {
            const fc = (elesiteNonEmptyFormationEntries[0] ?? elesiteEntries[0])
              ?.formation_config;
            return fc?.left_station && fc?.right_station ? (
              <RefDirectionBanner
                rows={[
                  { leftLabel: fc.left_station, rightLabel: fc.right_station },
                ]}
                color="#44bb44"
              />
            ) : null;
          })()
        : undefined}
    </View>
  );
  return (
    <ActionSheet
      gestureEnabled
      CustomHeaderComponent={<></>}
      isModal={Platform.OS === "ios" && !Platform.isPad}
      containerStyle={{ backgroundColor: colors.sheetBackground, ...(maxHeight != null ? { maxHeight } : {}) }}
    >
      <View pointerEvents={isCapturing ? "none" : "auto"}>
      <ViewShot ref={viewShot} options={{ format: "jpg" }}>
        {/* ヘッダー */}
        <View style={[styles.header, { backgroundColor: colors.sheetBackground }]}>
          <View style={[styles.handleBar, { backgroundColor: colors.border }]} />
          <View style={styles.headerRow}>
            <Text style={[styles.headerTitle, { color: colors.textPrimary }]}>運用情報ソース</Text>
            {customTrainData?.train_number_override ? (
              <CyclingHeaderTrainNum
                original={trainNum}
                override={customTrainData.train_number_override}
                color={colors.textTertiary}
              />
            ) : (
              <Text style={[styles.headerSub, { color: colors.textTertiary }]}>{trainNum}</Text>
            )}
          </View>
        </View>

        <ScrollView
          nestedScrollEnabled
          style={[styles.scroll, { backgroundColor: colors.sheetBackground, maxHeight: isCapturing ? undefined : windowHeight * 0.65 }]}
          contentContainerStyle={styles.scrollContent}
        >
        {/* ─── jr-shikoku-data-system (列車情報 + 運用情報) ─── */}
        <CombinedCard
          rows={[
            {
              icon: "database-search",
              title: "列車情報",
              sub: null,
              badge: hasTrainInfo ? "!" : null,
              detail: trainDetail,
            },
            {
              icon: "calendar-clock",
              title: "運用情報",
              sub: latestOperationDate
                ? `更新: ${formatHHMM(latestOperationDate)}`
                : unitIdsSub,
              badge: opCount > 0 ? opCount : null,
              detail: operationDetail,
            },
          ]}
          color="#0099CC"
          label="jr-shikoku-data-system"
          onPress={() =>
            openWebView(
              `https://jr-shikoku-data-system.pages.dev/trainData/${trainNum}?userID=${expoPushToken}&from=eachTrainInfo`,
              false,
            )
          }
        />

        {/* ─── 鉄道運用Hub ─────────────────────────── */}
        {unyohubEnabled && (
          <SourceCard
            imagePng={HUB_LOGO_PNG}
            color={colors.textSecondary}
            title="鉄道運用Hub"
            label="外部コミュニティデータ"
    sub={
              hasNonEmptyFormations
                ? unyohubSubItems.length > 1
                  ? <FadingSubCycler items={unyohubSubItems} color={colors.textSecondary} />
                  : unyohubLastPostedDatetime
                    ? `最終投稿: ${formatDateHHMM(unyohubLastPostedDatetime)}`
                    : ""
                : unyoCount > 0
                  ? "数日の運用報告なし"
                  : "この列車の運用データはありません"
            }
            badge={hasNonEmptyFormations ? unyoCount : null}
            badgeColor={colors.textSecondary}
            detail={formationDetail}
            disabled={unyoCount === 0}
            onPress={() =>
              openWebView(
                `https://jr-shikoku-data-system.pages.dev/unyohub-connection-train-data/${originalHubTrainNum}`,

                true,
              )
            }
          />
        )}

        {/* ─── えれサイト ─────────────────────────── */}
        {elesiteEnabled && (
          <SourceCard
            imagePng={ELESITE_LOGO_PNG}
            color="#44bb44"
            title="えれサイト"
            label="外部コミュニティデータ"
            sub={
              elesiteCount === 0
                ? "この列車の運用データはありません"
                : !elesiteHasNonEmptyFormations
                  ? "本日の運用報告なし"
                  : elesiteLastReportedAt
                    ? `最終投稿: ${formatHHMM(elesiteLastReportedAt)}`
                    : ""
            }
            badge={elesiteHasNonEmptyFormations ? elesiteCount : null}
            badgeColor="#44bb44"
            detail={elesiteFormationDetail}
            disabled={elesiteCount === 0}
            onPress={() => {
              const matchedEntry =
                elesiteNonEmptyFormationEntries[0] ?? elesiteEntries[0];
              const matchedTrain = matchedEntry?.trains?.find(
                (t) => t.train_number.trim() === trainNum,
              );
              const url =
                matchedTrain?.timetable_url || "https://www.elesite-next.com/";
              SheetManager.hide("TrainDataSources");
              Linking.openURL(url);
            }}
          />
        )}
      </ScrollView>
      </ViewShot>
      </View>

      <TouchableOpacity
        style={[styles.shareButton, { backgroundColor: colors.sheetBackground, borderColor: colors.border }]}
        onPress={onCapture}
      >
        <MaterialCommunityIcons name="share-variant" size={22} color={colors.textSecondary} />
        <Text style={[styles.shareButtonText, { color: colors.textSecondary }]}>スクリーンショットを共有</Text>
      </TouchableOpacity>
      <View style={styles.footer} />
    </ActionSheet>
  );
};

/* ------------------------------------------------------------------ */
/* DirectionBanner: 進行方向表示                                        */
/* ------------------------------------------------------------------ */
const DirectionBanner: FC<{ direction: boolean }> = ({ direction }) => {
  const { colors, fixed } = useThemeColors();
  return (
    <View style={[styles.directionBanner, { backgroundColor: colors.backgroundSecondary }]}>
      {direction ? (
        <>
          <MaterialCommunityIcons name="arrow-left" size={13} color={fixed.primary} />
          <Text style={[styles.directionText, { color: fixed.primary }]}>進行方向</Text>
        </>
      ) : (
        <>
          <Text style={[styles.directionText, { color: fixed.primary }]}>進行方向</Text>
          <MaterialCommunityIcons name="arrow-right" size={13} color={fixed.primary} />
        </>
      )}
    </View>
  );
};

/* ------------------------------------------------------------------ */
/* CyclingHeaderTrainNum: 上書き列番と通常列番をフェードで切り替え       */
/* ------------------------------------------------------------------ */
const CyclingHeaderTrainNum: FC<{
  original: string;
  override: string;
  color: string;
}> = ({ original, override, color }) => {
  const [showOverride, setShowOverride] = useState(true);
  const opacity = useRef(new Animated.Value(1)).current;

  useEffect(() => {
    const timer = setInterval(() => {
      Animated.timing(opacity, {
        toValue: 0,
        duration: 250,
        useNativeDriver: true,
      }).start(() => {
        setShowOverride((prev) => !prev);
        Animated.timing(opacity, {
          toValue: 1,
          duration: 250,
          useNativeDriver: true,
        }).start();
      });
    }, 3000);
    return () => clearInterval(timer);
  }, []);

  return (
    <Animated.View style={[styles.headerTrainNumWrap, { opacity }]}>
      <Text style={[styles.headerSub, { color }]}>
        {showOverride ? override : original}
      </Text>
      <Text style={[styles.headerTrainNumLabel, { color }]}>
        {showOverride ? "上書" : "通常"}
      </Text>
    </Animated.View>
  );
};

/* ------------------------------------------------------------------ */
/* RefDirectionBanner: 基準方向ラベル                                   */
/* ------------------------------------------------------------------ */
type RefDirRow = {
  leftLabel?: string;
  lineLabel?: string;
  rightLabel?: string;
};

const RefDirectionBanner: FC<{ rows: RefDirRow[]; color?: string }> = ({
  rows,
  color = "#888",
}) => (
  <View style={styles.refDirContainer}>
    {rows.map((row, i) => (
      <View key={i} style={styles.refDirRow}>
        {!!row.leftLabel && (
          <MaterialCommunityIcons name="arrow-left" size={10} color={color} />
        )}
        {!!row.leftLabel && (
          <Text style={[styles.refDirText, { color }]}>{row.leftLabel}</Text>
        )}
        {!!row.lineLabel && (
          <View style={[styles.refDirLineTag, { borderColor: color + "55" }]}>
            <Text style={[styles.refDirLineText, { color }]}>
              {row.lineLabel}
            </Text>
          </View>
        )}
        {!!row.rightLabel && (
          <>
            <Text style={[styles.refDirText, { color }]}>{row.rightLabel}</Text>
            <MaterialCommunityIcons
              name="arrow-right"
              size={10}
              color={color}
            />
          </>
        )}
      </View>
    ))}
  </View>
);

/* ------------------------------------------------------------------ */
/* CyclingRefDirectionBanner: 1秒ごとにフェードして路線を切り替え       */
/* ------------------------------------------------------------------ */
const CyclingRefDirectionBanner: FC<{ rows: RefDirRow[]; color?: string }> = ({
  rows,
  color = "#888",
}) => {
  const [index, setIndex] = useState(0);
  const opacity = useRef(new Animated.Value(1)).current;

  useEffect(() => {
    if (rows.length <= 1) return;
    const timer = setInterval(() => {
      Animated.timing(opacity, {
        toValue: 0,
        duration: 250,
        useNativeDriver: true,
      }).start(() => {
        setIndex((prev) => (prev + 1) % rows.length);
        Animated.timing(opacity, {
          toValue: 1,
          duration: 250,
          useNativeDriver: true,
        }).start();
      });
    }, 3000);
    return () => clearInterval(timer);
  }, [rows.length]);

  const row = rows[index];
  return (
    <Animated.View style={[styles.refDirRow, { opacity }]}>
      {!!row.leftLabel && (
        <MaterialCommunityIcons name="arrow-left" size={10} color={color} />
      )}
      {!!row.leftLabel && (
        <Text style={[styles.refDirText, { color }]}>{row.leftLabel}</Text>
      )}
      {!!row.lineLabel && (
        <View style={[styles.refDirLineTag, { borderColor: color + "55" }]}>
          <Text style={[styles.refDirLineText, { color }]}>
            {row.lineLabel}
          </Text>
        </View>
      )}
      {!!row.rightLabel && (
        <>
          <Text style={[styles.refDirText, { color }]}>{row.rightLabel}</Text>
          <MaterialCommunityIcons name="arrow-right" size={10} color={color} />
        </>
      )}
    </Animated.View>
  );
};

/* ------------------------------------------------------------------ */
/* CombinedCard: 複数行を 1 枠にまとめるカード                         */
/* ------------------------------------------------------------------ */
type CombinedRow = {
  icon: string;
  title: string;
  sub: string | null;
  badge: number | string | null;
  detail?: React.ReactNode;
};

const CombinedCard: FC<{
  rows: CombinedRow[];
  color: string;
  label: string;
  onPress: () => void;
}> = ({ rows, color, label, onPress }) => {
  const { colors } = useThemeColors();
  return (
  <TouchableOpacity
    style={[styles.card, styles.combinedCard, { backgroundColor: colors.surface, borderColor: colors.borderCard }]}
    activeOpacity={0.7}
    onPress={onPress}
  >
    {/* 共通ヘッダー */}
    <View style={styles.combinedHeader}>
      <View style={[styles.colorBar, { backgroundColor: color }]} />
      <Text style={[styles.labelText, styles.combinedLabel, { color: colors.textTertiary }]}>{label}</Text>
    </View>
    {/* 各行 */}
    {rows.map((row, i) => (
      <React.Fragment key={row.title}>
        {i > 0 && <View style={[styles.divider, { marginLeft: 14, backgroundColor: colors.borderCard }]} />}
        <View style={styles.combinedRow}>
          {/* 左カラーバー分のスペーサー */}
          <View style={{ width: 4 }} />
          <View
            style={[
              styles.iconWrap,
              { backgroundColor: color + "18", marginTop: 6 },
            ]}
          >
            <MaterialCommunityIcons
              name={row.icon as any}
              size={22}
              color={color}
            />
          </View>
          <View style={styles.textWrap}>
            <View style={styles.titleRow}>
              <Text style={[styles.cardTitle, { color: colors.textPrimary }]}>{row.title}</Text>
              {row.badge !== null && (
                <View style={[styles.badge, { backgroundColor: color }]}>
                  <Text style={styles.badgeText}>{row.badge}</Text>
                </View>
              )}
            </View>
            {row.sub !== null && (
              <Text style={[styles.subText, { color: colors.textSecondary }]} numberOfLines={1}>
                {row.sub}
              </Text>
            )}
            {row.detail && <View style={styles.detailWrap}>{row.detail}</View>}
          </View>
          {i === rows.length - 1 && (
            <MaterialCommunityIcons
              name="chevron-right"
              size={20}
              color={colors.textDisabled}
              style={{ marginRight: 10, marginTop: 16 }}
            />
          )}
        </View>
      </React.Fragment>
    ))}
  </TouchableOpacity>
)};

/* ------------------------------------------------------------------ */
/* TrainInfoDetail: 列車情報の構造化表示                              */
/* ------------------------------------------------------------------ */
const TrainInfoDetail: FC<{
  data: CustomTrainData;
  typeName?: string;
  trainName?: string;
  departureStation?: string;
  destinationStation?: string;
}> = ({ data, typeName, trainName, departureStation, destinationStation }) => {
  const { colors } = useThemeColors();
  const {
    infogram,
    train_info,
    vehicle_formation,
    via_data,
    start_date,
    end_date,
    uwasa,
    optional_text,
  } = data;
  const { fontAvailable } = getTrainType({
    type: data.type,
    whiteMode: false,
  });
  // 位置情報表示と同じ種別色を使用（視認性向上）
  const trainTypeCfg = TRAIN_TYPE_CONFIG[data.type];
  const resolvedTypeColor = trainTypeCfg ? trainTypeCfg.typeColor : "#333333ff";
  // to_data がなければダイヤの終着駅をフォールバック
  const destDisplay = data.to_data || destinationStation || "";
  const hasAny =
    typeName ||
    trainName ||
    departureStation ||
    destDisplay ||
    infogram ||
    train_info ||
    vehicle_formation ||
    via_data ||
    start_date ||
    end_date ||
    uwasa ||
    optional_text;
  if (!hasAny) return null;

  return (
    <View style={styles.trainDetail}>
      {/* 種別・列車名・始発→行先 */}
      {(typeName || trainName || departureStation || destDisplay) && (
        <View style={[styles.trainTitleBlock, { borderBottomColor: colors.borderSecondary }]}>
          <View style={styles.trainHeaderRow}>
            {!!typeName && (
              <View
                style={[styles.typeTag, { backgroundColor: resolvedTypeColor }]}
              >
                <Text
                  style={[
                    styles.typeTagText,
                    {
                      fontFamily: fontAvailable ? "JR-Nishi" : undefined,
                      fontWeight: !fontAvailable ? "bold" : undefined,
                      paddingTop: fontAvailable ? 2 : 0,
                    },
                  ]}
                >
                  {typeName}
                </Text>
              </View>
            )}
            {!!trainName && (
              <Text style={[styles.trainNameText, { color: colors.textPrimary }]} numberOfLines={1}>
                {trainName}
              </Text>
            )}
          </View>
          {!!(departureStation || destDisplay) && (
            <View style={styles.routeRow}>
              {!!departureStation && (
                <Text style={[styles.routeStation, { color: colors.textSecondary }]}>{departureStation}</Text>
              )}
              {!!(departureStation && destDisplay) && (
                <MaterialCommunityIcons
                  name="arrow-right"
                  size={13}
                  color={colors.textQuaternary}
                />
              )}
              {!!destDisplay && (
                <Text style={[styles.routeStation, styles.routeDest, { color: colors.textPrimary }]}>
                  {destDisplay}
                </Text>
              )}
            </View>
          )}
        </View>
      )}
      {/* LED インフォグラム */}
      {!!infogram && (
        <View style={styles.ledSection}>
          <Text style={[styles.detailSectionLabel, { color: colors.textTertiary }]}>インフォグラム</Text>
          <View style={styles.ledDisplay}>
            <Text style={styles.ledText}>{infogram}</Text>
          </View>
        </View>
      )}

      {/* 列車情報テキスト */}
      {!!train_info && (
        <View style={styles.trainInfoSection}>
          <Text style={[styles.detailSectionLabel, { color: colors.textTertiary }]}>列車情報</Text>
          <Text style={[styles.trainInfoText, { color: colors.textSecondary }]}>{train_info}</Text>
        </View>
      )}

      {/* メタ情報チップ行 */}
      {!!(vehicle_formation || via_data || start_date || end_date) && (
        <View style={styles.metaChipRow}>
          {!!vehicle_formation && (
            <View style={[styles.metaChip, { backgroundColor: colors.backgroundTertiary }]}>
              <MaterialCommunityIcons name="train-car" size={11} color={colors.textTertiary} />
              <Text style={[styles.metaChipText, { color: colors.textSecondary }]}>{vehicle_formation}</Text>
            </View>
          )}
          {!!via_data && (
            <View style={[styles.metaChip, { backgroundColor: colors.backgroundTertiary }]}>
              <MaterialCommunityIcons
                name="map-marker-path"
                size={11}
                color={colors.textTertiary}
              />
              <Text style={[styles.metaChipText, { color: colors.textSecondary }]}>経由: {via_data}</Text>
            </View>
          )}
          {!!(start_date || end_date) && (
            <View style={[styles.metaChip, styles.metaChipOrange, { backgroundColor: colors.backgroundTertiary }]}>
              <MaterialCommunityIcons
                name="calendar-range"
                size={11}
                color={colors.textWarning}
              />
              <Text style={[styles.metaChipText, { color: colors.textWarning }]}>
                {start_date ?? ""}〜{end_date ?? ""}
              </Text>
            </View>
          )}
        </View>
      )}

      {/* うわさ / optional_text */}
      {(!!uwasa || !!optional_text) && (
        <View style={styles.noteSection}>
          {!!uwasa && (
            <View
              style={[
                styles.noteRow,
                styles.rumorRow,
                {
                  backgroundColor: "rgba(245, 158, 11, 0.1)",
                  borderColor: colors.textWarning,
                },
              ]}
            >
              <MaterialCommunityIcons
                name="alert-circle-outline"
                size={14}
                color={colors.textWarning}
                style={styles.rumorIcon}
              />
              <View style={styles.noteTextWrap}>
                <Text style={[styles.rumorLabel, { color: colors.textWarning }]}>噂情報</Text>
                <Text style={[styles.noteText, { color: colors.textSecondary }]}>{uwasa}</Text>
              </View>
            </View>
          )}
          {!!optional_text && (
            <View style={styles.noteRow}>
              <MaterialCommunityIcons
                name="information-outline"
                size={12}
                color={colors.iconSecondary}
              />
              <Text style={[styles.noteText, { color: colors.textSecondary }]}>{optional_text}</Text>
            </View>
          )}
        </View>
      )}
    </View>
  );
};

/* ------------------------------------------------------------------ */
/* SourceCard                                                           */
/* ------------------------------------------------------------------ */
type SourceCardProps = {
  icon?: string;
  imagePng?: any;
  color: string;
  title: string;
  label: string;
  sub?: string | React.ReactNode;
  badge: number | string | null;
  badgeColor: string;
  disabled?: boolean;
  onPress?: () => void;
  detail?: React.ReactNode;
};

const SourceCard: FC<SourceCardProps> = ({
  icon,
  imagePng,
  color,
  title,
  label,
  sub,
  badge,
  badgeColor,
  disabled,
  onPress,
  detail,
}) => {
  const { colors } = useThemeColors();
  return (
  <TouchableOpacity
    style={[styles.card, { backgroundColor: colors.surface, borderColor: colors.borderCard }, disabled && { opacity: 0.45 }]}
    activeOpacity={disabled ? 1 : 0.7}
    disabled={disabled}
    onPress={onPress}
  >
    {/* 左カラーバー */}
    <View style={[styles.colorBar, { backgroundColor: color }]} />

    {/* アイコン */}
    <View style={[styles.iconWrap, { backgroundColor: color + "18" }]}>
      {imagePng ? (
        <Image source={imagePng} style={{ width: 28, height: 28 }} />
      ) : (
        <MaterialCommunityIcons
          name={(icon ?? "information") as any}
          size={24}
          color={color}
        />
      )}
    </View>

    {/* テキスト */}
    <View style={styles.textWrap}>
      <View style={styles.titleRow}>
        <Text style={[styles.cardTitle, { color: colors.textPrimary }]}>{title}</Text>
        <Text style={[styles.labelText, { color: colors.textQuaternary }]}>{label}</Text>
      </View>
      {sub && (
        typeof sub === "string" ? (
          <Text style={[styles.subText, { color: colors.textSecondary }]} numberOfLines={1}>
            {sub}
          </Text>
        ) : (
          <View style={styles.subNodeWrap}>{sub}</View>
        )
      )}
      {detail && <View style={styles.detailWrap}>{detail}</View>}
    </View>

    {/* バッジ + 矢印 */}
    <View style={styles.rightArea}>
      {badge !== null ? (
        <View style={[styles.badge, { backgroundColor: badgeColor }]}>
          <Text style={styles.badgeText}>{badge}</Text>
        </View>
      ) : null}
      <MaterialCommunityIcons name="chevron-right" size={20} color={colors.textDisabled} />
    </View>
  </TouchableOpacity>
)};

/* ------------------------------------------------------------------ */
/* スタイル                                                              */
/* ------------------------------------------------------------------ */
const styles = StyleSheet.create({
  header: {
    paddingTop: 8,
    paddingBottom: 12,
    paddingHorizontal: 16,
  },
  handleBar: {
    width: 40,
    height: 5,
    borderRadius: 3,
    alignSelf: "center",
    marginBottom: 12,
  },
  headerRow: {
    flexDirection: "row",
    alignItems: "baseline",
    gap: 8,
  },
  headerTitle: {
    fontSize: 17,
    fontWeight: "bold",
  },
  headerSub: {
    fontSize: 14,
  },
  headerTrainNumWrap: {
    flexDirection: "row",
    alignItems: "baseline",
    gap: 4,
  },
  headerTrainNumLabel: {
    fontSize: 10,
    fontWeight: "600",
  },
  trainHeaderRow: {
    flexDirection: "row",
    alignItems: "center",
    flexWrap: "wrap",
    gap: 6,
  },
  trainTitleBlock: {
    gap: 4,
    paddingBottom: 4,
    borderBottomWidth: StyleSheet.hairlineWidth,
    marginBottom: 4,
  },
  typeTag: {
    borderRadius: 4,
    paddingHorizontal: 8,
    paddingVertical: 2,
  },
  typeTagText: {
    color: "#fff",
    fontSize: 13,
  },
  trainNameText: {
    fontSize: 16,
    flexShrink: 1,
  },
  routeRow: {
    flexDirection: "row",
    alignItems: "center",
    gap: 4,
  },
  routeStation: {
    fontSize: 13,
  },
  routeDest: {
    fontWeight: "bold",
  },
  scroll: {},
  scrollContent: {
    paddingHorizontal: 14,
    gap: 10,
    paddingBottom: 4,
  },
  card: {
    flexDirection: "row",
    alignItems: "center",
    borderRadius: 12,
    borderWidth: 1,
    overflow: "hidden",
    minHeight: 70,
  },
  combinedCard: {
    flexDirection: "column",
    alignItems: "stretch",
  },
  combinedHeader: {
    flexDirection: "row",
    alignItems: "center",
    paddingTop: 8,
    paddingBottom: 2,
    gap: 8,
  },
  combinedLabel: {
    marginLeft: 4,
  },
  combinedRow: {
    flexDirection: "row",
    alignItems: "flex-start",
    minHeight: 58,
    paddingVertical: 6,
  },
  divider: {
    height: StyleSheet.hairlineWidth,
  },
  colorBar: {
    width: 4,
    alignSelf: "stretch",
  },
  iconWrap: {
    width: 48,
    height: 48,
    borderRadius: 10,
    alignItems: "center",
    justifyContent: "center",
    marginHorizontal: 10,
    flexShrink: 0,
  },
  textWrap: {
    flex: 1,
    paddingVertical: 6,
    gap: 3,
  },
  titleRow: {
    flexDirection: "row",
    alignItems: "center",
    gap: 6,
  },
  cardTitle: {
    fontSize: 15,
    fontWeight: "bold",
  },
  cardTitleDisabled: {
  },
  labelText: {
    fontSize: 10,
    fontWeight: "500",
  },
  subText: {
    fontSize: 12,
  },
  subNodeWrap: {
    marginTop: 2,
  },
  subTextDisabled: {
    color: "#bbb",
  },
  rightArea: {
    flexDirection: "row",
    alignItems: "center",
    paddingRight: 10,
    gap: 4,
  },
  badge: {
    minWidth: 20,
    height: 20,
    borderRadius: 10,
    alignItems: "center",
    justifyContent: "center",
    paddingHorizontal: 5,
  },
  badgeText: {
    color: "#fff",
    fontSize: 11,
    fontWeight: "bold",
  },
  operationDetailBlock: {
    //marginTop: 4,
    gap: 6,
  },
  unitIdText: {
    fontSize: 13,
    fontWeight: "bold",
    color: "#0077aa",
    letterSpacing: 0.5,
  },
  footer: {
    height: 20,
  },
  shareButton: {
    flexDirection: "row",
    alignItems: "center",
    justifyContent: "center",
    gap: 8,
    marginHorizontal: 14,
    marginTop: 8,
    paddingVertical: 10,
    borderRadius: 10,
    borderWidth: 1,
  },
  shareButtonText: {
    fontSize: 14,
    fontWeight: "600",
  },
  /* ── TrainInfoDetail ──────────────── */
  detailWrap: {
    marginTop: 4,
    marginBottom: 4,
  },
  trainDetail: {
    gap: 8,
  },
  ledSection: {
    gap: 4,
  },
  detailSectionLabel: {
    fontSize: 10,
    fontWeight: "600",
    letterSpacing: 0.5,
  },
  ledDisplay: {
    backgroundColor: "#0077aa",
    borderRadius: 5,
    paddingHorizontal: 10,
    paddingVertical: 5,
    alignSelf: "flex-start",
  },
  ledText: {
    fontFamily: "JNR-font",
    fontSize: 20,
    color: "#ffffff",
    letterSpacing: 2,
  },
  trainInfoSection: {
    gap: 3,
  },
  trainInfoText: {
    fontSize: 12,
    lineHeight: 18,
  },
  metaChipRow: {
    flexDirection: "row",
    flexWrap: "wrap",
    gap: 5,
  },
  metaChip: {
    flexDirection: "row",
    alignItems: "center",
    backgroundColor: "#f0f0f0",
    borderRadius: 5,
    paddingHorizontal: 7,
    paddingVertical: 3,
    gap: 4,
  },
  metaChipOrange: {
    backgroundColor: "#fff3e0",
  },
  metaChipText: {
    fontSize: 11,
  },
  noteSection: {
    gap: 6,
    marginTop: 4,
    paddingRight: 10,
  },
  noteRow: {
    flexDirection: "row",
    alignItems: "flex-start",
    gap: 4,
  },
  noteTextWrap: {
    flex: 1,
    gap: 2,
  },
  rumorRow: {
    borderWidth: 1,
    borderRadius: 8,
    paddingHorizontal: 10,
    paddingVertical: 8,
    gap: 6,
    marginVertical: 2,
  },
  rumorIcon: {
    marginTop: 1,
  },
  rumorLabel: {
    fontSize: 10,
    fontWeight: "700",
    letterSpacing: 0.6,
  },
  noteText: {
    fontSize: 11,
    lineHeight: 16,
    flex: 1,
  },
  directionBanner: {
    flexDirection: "row",
    alignItems: "center",
    gap: 4,
    backgroundColor: "#E3F4FB",
    borderRadius: 5,
    paddingHorizontal: 7,
    paddingVertical: 3,
    marginTop: 4,
    alignSelf: "flex-start",
  },
  directionText: {
    fontSize: 11,
    fontWeight: "600",
    color: "#0099CC",
  },
  refDirContainer: {
    gap: 3,
    marginTop: 5,
  },
  refDirRow: {
    flexDirection: "row",
    alignItems: "center",
    flexWrap: "wrap",
    gap: 3,
  },
  refDirText: {
    fontSize: 10,
    fontWeight: "600",
  },
  refDirLineTag: {
    borderWidth: 1,
    borderRadius: 4,
    paddingHorizontal: 4,
    paddingVertical: 1,
  },
  refDirLineText: {
    fontSize: 10,
  },
});
