// YomiAI — accurate Material 3 recreations from the Flutter source

function MIcon({ name, size = 24, color = 'currentColor' }) {
  // Material-symbol-style rounded icons — filled/outline variants matching Flutter's Icons set
  const s = size;
  const paths = {
    lock: <path d="M6 10V8a6 6 0 1112 0v2h1a2 2 0 012 2v8a2 2 0 01-2 2H5a2 2 0 01-2-2v-8a2 2 0 012-2h1zm2 0h8V8a4 4 0 10-8 0v2zm4 4a2 2 0 00-1 3.73V19a1 1 0 002 0v-1.27A2 2 0 0012 14z" fill={color}/>,
    lock_open: <path d="M18 8a6 6 0 00-11.65-2 1 1 0 101.93.5A4 4 0 0116 8v2H5a2 2 0 00-2 2v8a2 2 0 002 2h14a2 2 0 002-2v-8a2 2 0 00-2-2h-1V8zm-6 6a2 2 0 011 3.73V19a1 1 0 01-2 0v-1.27A2 2 0 0112 14z" fill={color}/>,
    lock_outline: <g><path d="M6 10V8a6 6 0 1112 0v2h1a2 2 0 012 2v8a2 2 0 01-2 2H5a2 2 0 01-2-2v-8a2 2 0 012-2h1zm2 0h8V8a4 4 0 10-8 0v2zm-3 2v8h14v-8H5z" fill={color}/></g>,
    lock_open_outline: <g><path d="M18 8a6 6 0 00-11.65-2 1 1 0 101.93.5A4 4 0 0116 8v2H5a2 2 0 00-2 2v8a2 2 0 002 2h14a2 2 0 002-2v-8a2 2 0 00-2-2h-1V8zm1 4v8H5v-8h14z" fill={color}/></g>,
    rss_feed: <g><circle cx="6.18" cy="17.82" r="2.18" fill={color}/><path d="M4 4.44v2.83c7.03 0 12.73 5.7 12.73 12.73h2.83c0-8.59-6.97-15.56-15.56-15.56zm0 5.66v2.83c3.9 0 7.07 3.17 7.07 7.07h2.83c0-5.47-4.43-9.9-9.9-9.9z" fill={color}/></g>,
    auto_awesome: <path d="M19 9l1.25-2.75L23 5l-2.75-1.25L19 1l-1.25 2.75L15 5l2.75 1.25L19 9zM11 6L8.5 11.5 3 14l5.5 2.5L11 22l2.5-5.5L19 14l-5.5-2.5L11 6zM19 15l-1.25 2.75L15 19l2.75 1.25L19 23l1.25-2.75L23 19l-2.75-1.25L19 15z" fill={color}/>,
    article: <path d="M19 3H5a2 2 0 00-2 2v14a2 2 0 002 2h14a2 2 0 002-2V5a2 2 0 00-2-2zm-5 14H7v-2h7v2zm3-4H7v-2h10v2zm0-4H7V7h10v2z" fill={color}/>,
    add: <path d="M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z" fill={color}/>,
    bookmark_border: <path d="M17 3H7a2 2 0 00-2 2v16l7-3 7 3V5a2 2 0 00-2-2zm0 15l-5-2.18L7 18V5h10v13z" fill={color}/>,
    bookmark: <path d="M17 3H7a2 2 0 00-2 2v16l7-3 7 3V5a2 2 0 00-2-2z" fill={color}/>,
    share: <path d="M18 16.08c-.76 0-1.44.3-1.96.77L8.91 12.7a3.27 3.27 0 000-1.4l7.05-4.11c.54.5 1.25.81 2.04.81a3 3 0 100-6 3 3 0 00-3 3c0 .24.04.47.09.7L8.04 9.81a3 3 0 100 4.38l7.12 4.16c-.05.21-.08.43-.08.65a2.92 2.92 0 105.92 0 2.92 2.92 0 00-3-2.92z" fill={color}/>,
    drag_handle: <path d="M20 9H4v2h16V9zM4 15h16v-2H4v2z" fill={color}/>,
    open_in_browser: <path d="M19 4H5a2 2 0 00-2 2v12a2 2 0 002 2h4v-2H5V8h14v10h-4v2h4a2 2 0 002-2V6a2 2 0 00-2-2zm-7 6l-4 4h3v6h2v-6h3l-4-4z" fill={color}/>,
    rss_feed_outline: <g><path d="M4 4.44v2.83c7.03 0 12.73 5.7 12.73 12.73h2.83c0-8.59-6.97-15.56-15.56-15.56zm0 5.66v2.83c3.9 0 7.07 3.17 7.07 7.07h2.83c0-5.47-4.43-9.9-9.9-9.9zm1.18 7.72a1.59 1.59 0 100 3.18 1.59 1.59 0 000-3.18z" fill="none" stroke={color} strokeWidth="1.6"/></g>,
    auto_awesome_outline: <path d="M19 9l1.25-2.75L23 5l-2.75-1.25L19 1l-1.25 2.75L15 5l2.75 1.25L19 9zM11 6L8.5 11.5 3 14l5.5 2.5L11 22l2.5-5.5L19 14l-5.5-2.5L11 6zm0 4.79L11.83 13l2.21.83-2.21.83L11 16.79l-.83-2.13L8.04 13l2.13-.83L11 10.79z" fill={color}/>,
    settings_outline: <path d="M19.14 12.94c.04-.31.06-.63.06-.94 0-.32-.02-.64-.07-.94l2.03-1.58a.49.49 0 00.12-.61l-1.92-3.32a.49.49 0 00-.59-.22l-2.39.96c-.5-.38-1.03-.7-1.62-.94l-.36-2.54A.48.48 0 0014 2h-4a.48.48 0 00-.49.42l-.36 2.54c-.59.24-1.13.57-1.62.94l-2.39-.96a.48.48 0 00-.59.22L2.63 8.48a.49.49 0 00.12.61L4.78 10.67c-.05.3-.07.62-.07.94 0 .31.02.63.06.94l-2.03 1.58a.49.49 0 00-.12.61l1.92 3.32a.49.49 0 00.59.22l2.39-.96c.5.38 1.03.7 1.62.94l.36 2.54c.05.24.26.42.49.42h4c.24 0 .44-.18.49-.42l.36-2.54c.59-.24 1.13-.57 1.62-.94l2.39.96a.48.48 0 00.59-.22l1.92-3.32a.49.49 0 00-.12-.61l-2.03-1.58zM12 15.5a3.5 3.5 0 110-7 3.5 3.5 0 010 7z" fill="none" stroke={color} strokeWidth="1.5"/>,
    settings: <path d="M19.14 12.94c.04-.31.06-.63.06-.94 0-.32-.02-.64-.07-.94l2.03-1.58a.49.49 0 00.12-.61l-1.92-3.32a.49.49 0 00-.59-.22l-2.39.96c-.5-.38-1.03-.7-1.62-.94l-.36-2.54A.48.48 0 0014 2h-4a.48.48 0 00-.49.42l-.36 2.54c-.59.24-1.13.57-1.62.94l-2.39-.96a.48.48 0 00-.59.22L2.63 8.48a.49.49 0 00.12.61L4.78 10.67c-.05.3-.07.62-.07.94 0 .31.02.63.06.94l-2.03 1.58a.49.49 0 00-.12.61l1.92 3.32a.49.49 0 00.59.22l2.39-.96c.5.38 1.03.7 1.62.94l.36 2.54c.05.24.26.42.49.42h4c.24 0 .44-.18.49-.42l.36-2.54c.59-.24 1.13-.57 1.62-.94l2.39.96a.48.48 0 00.59-.22l1.92-3.32a.49.49 0 00-.12-.61l-2.03-1.58zM12 15.5a3.5 3.5 0 110-7 3.5 3.5 0 010 7z" fill={color}/>,
    widgets: <path d="M13 13v8h8v-8h-8zM3 21h8v-8H3v8zM3 3v8h8V3H3zm13.66-1.31L11 7.34 16.66 13l5.66-5.66-5.66-5.65z" fill={color}/>,
    insights: <path d="M19 3H5a2 2 0 00-2 2v14a2 2 0 002 2h14a2 2 0 002-2V5a2 2 0 00-2-2zM9 17H7v-5h2v5zm4 0h-2V7h2v10zm4 0h-2v-3h2v3z" fill={color}/>,
    label_outline: <path d="M17.63 5.84C17.27 5.33 16.67 5 16 5L5 5.01C3.9 5.01 3 5.9 3 7v10c0 1.1.9 1.99 2 1.99L16 19c.67 0 1.27-.33 1.63-.84L22 12l-4.37-6.16zM16 17H5V7h11l3.55 5L16 17z" fill={color}/>,
    search: <path d="M15.5 14h-.79l-.28-.27a6.5 6.5 0 10-.7.7l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0A4.5 4.5 0 1114 9.5 4.49 4.49 0 019.5 14z" fill={color}/>,
    close: <path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12 19 6.41z" fill={color}/>,
    fingerprint: <path d="M17.81 4.47c-.08 0-.16-.02-.23-.06C15.66 3.42 14 3 12.01 3c-1.98 0-3.86.47-5.57 1.41-.24.13-.54.04-.68-.2-.13-.24-.04-.55.2-.68C7.82 2.52 9.86 2 12.01 2c2.13 0 3.99.47 6.03 1.52.25.13.34.43.21.67-.09.18-.26.28-.44.28zM3.5 9.72c-.1 0-.2-.03-.29-.09a.5.5 0 01-.12-.7c.96-1.36 2.18-2.43 3.63-3.17C9.75 4.22 14.26 4.21 17.28 5.76c1.45.74 2.67 1.8 3.63 3.16a.5.5 0 01-.12.7.5.5 0 01-.7-.12c-.87-1.23-1.98-2.2-3.29-2.87-2.73-1.39-6.83-1.39-9.56.01-1.31.68-2.43 1.65-3.29 2.88-.08.13-.22.2-.36.2zm6.25 12.07c-.13 0-.26-.05-.35-.15-.87-.86-1.34-1.41-2.01-2.61-.69-1.23-1.06-2.72-1.06-4.32 0-2.96 2.53-5.38 5.63-5.38s5.63 2.42 5.63 5.38a.5.5 0 01-.5.5c-.28 0-.5-.22-.5-.5 0-2.4-2.08-4.38-4.63-4.38s-4.63 1.98-4.63 4.38c0 1.44.32 2.75.93 3.83.64 1.14 1.08 1.63 1.85 2.41.19.2.19.51 0 .71-.11.1-.24.13-.36.13z" fill={color}/>,
    error_outline: <path d="M11 15h2v2h-2v-2zm0-8h2v6h-2V7zm.99-5C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zM12 20c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8z" fill={color}/>,
    chevron_left: <path d="M15.41 7.41L14 6l-6 6 6 6 1.41-1.41L10.83 12z" fill={color}/>,
    more: <path d="M6 10c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm12 0c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm-6 0c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2z" fill={color}/>,
    circle: <circle cx="12" cy="12" r="5" fill={color}/>,
    block: <path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zM4 12c0-4.42 3.58-8 8-8 1.85 0 3.55.63 4.9 1.69L5.69 16.9A7.95 7.95 0 014 12zm8 8c-1.85 0-3.55-.63-4.9-1.69L18.31 7.1A7.95 7.95 0 0120 12c0 4.42-3.58 8-8 8z" fill={color}/>,
    all_inclusive: <path d="M18.6 6.62c-1.44 0-2.8.56-3.77 1.53L7.8 14.39c-.64.64-1.49.99-2.4.99-1.87 0-3.39-1.51-3.39-3.38S3.53 8.62 5.4 8.62c.91 0 1.76.35 2.44 1.03l1.13 1 1.51-1.34L9.22 8.2A5.37 5.37 0 005.4 6.62C2.42 6.62 0 9.04 0 12s2.42 5.38 5.4 5.38c1.44 0 2.8-.56 3.77-1.53l7.03-6.24c.64-.64 1.49-.99 2.4-.99 1.87 0 3.39 1.51 3.39 3.38s-1.52 3.38-3.39 3.38c-.9 0-1.76-.35-2.44-1.03l-1.14-1.01-1.51 1.34 1.27 1.12a5.386 5.386 0 003.82 1.57c2.98 0 5.4-2.41 5.4-5.38s-2.42-5.37-5.4-5.37z" fill={color}/>,
    download: <path d="M19 9h-4V3H9v6H5l7 7 7-7zM5 18v2h14v-2H5z" fill={color}/>,
    cloud_off: <path d="M19.35 10.04A7.49 7.49 0 0012 4c-1.33 0-2.57.36-3.65.97l1.49 1.49C10.51 6.17 11.23 6 12 6a5.5 5.5 0 015.5 5.5v.5H19a3 3 0 012.22 5.02l1.42 1.42A4.97 4.97 0 0024 14.5a4.97 4.97 0 00-4.65-4.46zM3 5.27l2.75 2.74C2.56 8.15 0 10.77 0 14a6 6 0 006 6h11.73l2 2L21 20.73 4.27 4 3 5.27zM7.73 10l8 8H6a4 4 0 01-.46-7.97l2.19-.03z" fill={color}/>,
    translate: <path d="M12.87 15.07l-2.54-2.51.03-.03A17.52 17.52 0 0014.07 6H17V4h-7V2H8v2H1v2h11.17C11.5 7.92 10.44 9.75 9 11.35 8.07 10.32 7.3 9.19 6.69 8h-2c.73 1.63 1.73 3.17 2.98 4.56l-5.09 5.02L4 19l5-5 3.11 3.11.76-2.04zM18.5 10h-2L12 22h2l1.12-3h4.75L21 22h2l-4.5-12zm-2.62 7l1.62-4.33L19.12 17h-3.24z" fill={color}/>,
    home: <path d="M10 20v-6h4v6h5v-8h3L12 3 2 12h3v8z" fill={color}/>,
    home_outline: <path d="M12 5.69l5 4.5V18h-2v-6H9v6H7v-7.81l5-4.5M12 3L2 12h3v8h6v-6h2v6h6v-8h3L12 3z" fill={color}/>,
    view_quilt: <path d="M10 5v6h11V5H10zM3 19h8V5H3v14zm9 0h9v-6h-9v6z" fill={color}/>,
    view_quilt_outline: <path d="M3 5v14h18V5H3zm7 2h9v4h-9V7zm0 6h9v4h-9v-4zM5 7h3v10H5V7z" fill={color}/>,
    done_all: <path d="M18 7l-1.41-1.41-6.34 6.34 1.41 1.41L18 7zm4.24-1.41L11.66 16.17 7.48 12l-1.41 1.41L11.66 19l12-12-1.42-1.41zM.41 13.41L6 19l1.41-1.41L1.83 12 .41 13.41z" fill={color}/>,
    filter_alt: <path d="M4.25 5.61C6.27 8.2 10 13 10 13v6c0 .55.45 1 1 1h2c.55 0 1-.45 1-1v-6s3.72-4.8 5.74-7.39A1 1 0 0018.95 4H5.04a1 1 0 00-.79 1.61z" fill={color}/>,
    filter_alt_outline: <path d="M19.79 5.61A1 1 0 0018.95 4H5.04a1 1 0 00-.79 1.61L10 13v6c0 .55.45 1 1 1h2c.55 0 1-.45 1-1v-6l5.79-7.39zM12 12.36L7.5 6h9L12 12.36z" fill={color}/>,
    history: <path d="M13 3a9 9 0 00-9 9H1l3.89 3.89.07.14L9 12H6a7 7 0 117 7c-1.93 0-3.68-.79-4.94-2.06l-1.42 1.42A8.95 8.95 0 0013 21a9 9 0 000-18zm-1 5v5l4.28 2.54.72-1.21-3.5-2.08V8H12z" fill={color}/>,
    summarize: <path d="M19 3H5a2 2 0 00-2 2v14a2 2 0 002 2h14a2 2 0 002-2V5a2 2 0 00-2-2zm-5 4h3v2h-3V7zm-7 0h5v6H7V7zm10 10H7v-2h10v2zm0-4h-3v-2h3v2z" fill={color}/>,
    chevron_right: <path d="M8.59 16.59L10 18l6-6-6-6-1.41 1.41L13.17 12z" fill={color}/>,
    refresh: <path d="M17.65 6.35A7.958 7.958 0 0012 4a8 8 0 100 16c3.73 0 6.84-2.55 7.73-6h-2.08A5.99 5.99 0 0112 18a6 6 0 110-12c1.66 0 3.14.69 4.22 1.78L13 11h7V4l-2.35 2.35z" fill={color}/>,
    notifications_active: <path d="M7.58 4.08L6.15 2.65C3.75 4.48 2.17 7.3 2.03 10.5h2a8.45 8.45 0 013.55-6.42zm12.39 6.42h2c-.15-3.2-1.73-6.02-4.12-7.85l-1.42 1.43a8.495 8.495 0 013.54 6.42zM18 11.2c0-3.07-1.64-5.64-4.5-6.32V4.2a1.5 1.5 0 10-3 0v.68C7.63 5.56 6 8.12 6 11.2V16l-2 2v1h16v-1l-2-2v-4.8zM12 22c.14 0 .27-.01.4-.04a2.013 2.013 0 001.4-1.06c.08-.16.19-.34.19-.55h-4a2 2 0 002 1.65z" fill={color}/>,
    notifications_outline: <path d="M12 22a2 2 0 002-2h-4a2 2 0 002 2zm6-6v-5c0-3.07-1.64-5.64-4.5-6.32V4a1.5 1.5 0 00-3 0v.68C7.63 5.36 6 7.92 6 11v5l-2 2v1h16v-1l-2-2zm-2 1H8v-6c0-2.48 1.51-4.5 4-4.5s4 2.02 4 4.5v6z" fill={color}/>,
    summarize_outline: <path d="M19 3H5a2 2 0 00-2 2v14a2 2 0 002 2h14a2 2 0 002-2V5a2 2 0 00-2-2zm0 16H5V5h14v14zm-7-2h5v-2h-5v2zm-5 0h3v-6H7v6zm0-8h10V7H7v2z" fill={color}/>,
    inbox_outline: <path d="M19 3H5c-1.11 0-2 .89-2 2v14c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V5a2 2 0 00-2-2zm0 12h-4l-1 2h-4l-1-2H5V5h14v10z" fill={color}/>,
    expand_more: <path d="M16.59 8.59L12 13.17 7.41 8.59 6 10l6 6 6-6z" fill={color}/>,
    edit: <path d="M3 17.25V21h3.75L17.81 9.94l-3.75-3.75L3 17.25zM20.71 7.04a.996.996 0 000-1.41l-2.34-2.34a.996.996 0 00-1.41 0l-1.83 1.83 3.75 3.75 1.83-1.83z" fill={color}/>,
  };
  return <svg width={s} height={s} viewBox="0 0 24 24" fill="none" style={{flexShrink:0}}>{paths[name]}</svg>;
}

// Material color scheme derived from seed #4A90D9
const M3 = {
  light: {
    primary: '#265EA7',
    onPrimary: '#FFFFFF',
    primaryContainer: '#D4E3FF',
    onPrimaryContainer: '#001C38',
    surface: '#F8F9FF',
    surfaceContainerLow: '#F2F3FA',
    surfaceContainer: '#EDEEF6',
    surfaceContainerHigh: '#E7E8F0',
    surfaceContainerHighest: '#E1E2EA',
    onSurface: '#1A1C1E',
    onSurfaceVariant: '#43474E',
    outline: '#73777F',
    outlineVariant: '#C3C6CF',
    scrim: 'rgba(0,0,0,0.32)',
    error: '#BA1A1A',
    amber: '#F59E0B',
  },
  dark: {
    primary: '#A6C8FF',
    onPrimary: '#00315E',
    primaryContainer: '#004785',
    onPrimaryContainer: '#D4E3FF',
    surface: '#111318',
    surfaceContainerLow: '#181B20',
    surfaceContainer: '#1D2024',
    surfaceContainerHigh: '#272A2F',
    surfaceContainerHighest: '#32353A',
    onSurface: '#E3E2E6',
    onSurfaceVariant: '#C3C6CF',
    outline: '#8D9199',
    outlineVariant: '#43474E',
    scrim: 'rgba(0,0,0,0.45)',
    error: '#FFB4AB',
    amber: '#FFC857',
  },
};

function palette(dark, accent) {
  const base = dark ? M3.dark : M3.light;
  // When user picks a different accent, remap primary + container
  const p = {...base};
  p.primary = accent;
  // derive softer container from accent
  p.primaryContainer = dark
    ? `color-mix(in oklch, ${accent} 30%, ${base.surface})`
    : `color-mix(in oklch, ${accent} 18%, #ffffff)`;
  p.onPrimaryContainer = dark ? '#FFFFFF' : '#001C38';
  return p;
}

// ─── i18n helper ───
function getScreens(lang) {
  const i18n = (typeof window !== 'undefined') && window.__YOMI_I18N__;
  if (i18n && i18n.SCREENS && i18n.SCREENS[lang]) return i18n.SCREENS[lang];
  // Safe fallback — will never hit in practice
  return {};
}
function screenFontFamily(lang) {
  return lang === 'en'
    ? '-apple-system, "SF Pro Text", "Inter", system-ui, sans-serif'
    : '"Noto Sans JP", -apple-system, system-ui';
}

// ─── Material 3 AppBar ───
function M3AppBar({ leading, title, actions, p, elevated = false, ff = '"Noto Sans JP", -apple-system, system-ui' }) {
  return (
    <div style={{
      height: 56, display: 'flex', alignItems: 'center',
      padding: '0 4px',
      background: elevated ? p.surfaceContainer : p.surface,
      color: p.onSurface,
      position: 'relative', zIndex: 2,
      borderBottom: elevated ? `1px solid ${p.outlineVariant}` : 'none',
    }}>
      <div style={{width:48, display:'flex', justifyContent:'center'}}>{leading}</div>
      <div style={{
        flex: 1, textAlign: 'center',
        fontFamily: ff,
        fontSize: 18, fontWeight: 500, letterSpacing: 0,
        color: p.onSurface,
        whiteSpace: 'nowrap',
        overflow: 'hidden',
        textOverflow: 'ellipsis',
        minWidth: 0,
      }}>{title}</div>
      <div style={{display:'flex', gap:0, paddingRight:4, minWidth: 48, justifyContent: 'flex-end'}}>{actions}</div>
    </div>
  );
}

function M3IconButton({ icon, onClick, color, size = 24, disabled = false }) {
  return (
    <button onClick={onClick} disabled={disabled} style={{
      width: 48, height: 48, border: 'none', background: 'transparent',
      display: 'grid', placeItems: 'center', cursor: disabled ? 'default' : 'pointer',
      color: color || 'currentColor', padding: 0,
      borderRadius: 24, opacity: disabled ? 0.5 : 1,
    }}>
      <MIcon name={icon} size={size} color={color || 'currentColor'}/>
    </button>
  );
}

// ─── FilterChip row ───
function FilterChipRow({ chips, selected, onSelect, p, ff = '"Noto Sans JP", system-ui', showSearchButton = false }) {
  return (
    <div style={{
      height: 48, display: 'flex', alignItems: 'center', gap: 8,
      padding: '0 12px', overflowX: 'auto',
      background: p.surface,
      scrollbarWidth: 'none',
    }}>
      {showSearchButton && (
        <div style={{
          flexShrink: 0,
          height: 32, padding: '0 12px',
          borderRadius: 8,
          border: `1px solid ${p.outline}`,
          background: 'transparent',
          display: 'flex', alignItems: 'center', gap: 6,
          cursor: 'pointer',
        }}>
          <MIcon name="search" size={18} color={p.onSurfaceVariant}/>
        </div>
      )}
      {chips.map((c, i) => {
        const sel = selected === c.id;
        return (
          <div key={c.id} onClick={() => onSelect(c.id)} style={{
            flexShrink: 0,
            height: 32, padding: sel ? '0 12px 0 8px' : '0 16px',
            borderRadius: 8,
            border: sel ? 'none' : `1px solid ${p.outline}`,
            background: sel ? p.primaryContainer : 'transparent',
            color: sel ? p.onPrimaryContainer : p.onSurface,
            display: 'flex', alignItems: 'center', gap: 6,
            fontFamily: ff,
            fontSize: 14, fontWeight: 500, letterSpacing: 0.1,
            cursor: 'pointer',
          }}>
            {sel && (
              <svg width="18" height="18" viewBox="0 0 24 24"><path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z" fill={p.onPrimaryContainer}/></svg>
            )}
            {c.label}
          </div>
        );
      })}
    </div>
  );
}

// ─── M3 ListTile (matches latest ArticleListTile — thumbnail on right) ───
function ArticleTile({ article, p, showAiBadge, aiReason, onClick, ff = '"Noto Sans JP", system-ui' }) {
  return (
    <div onClick={onClick} style={{
      display: 'flex', gap: 12, alignItems: 'flex-start',
      padding: '12px 16px',
      cursor: 'pointer',
      background: 'transparent',
      opacity: article.isRead ? 0.55 : 1,
    }}>
      {/* Body on left */}
      <div style={{flex: 1, minWidth: 0}}>
        {showAiBadge && (
          <div style={{
            display: 'inline-flex', alignItems: 'center', gap: 3,
            padding: '2px 6px',
            border: `1px solid ${p.primary}`,
            borderRadius: 4,
            marginBottom: 6,
          }}>
            <MIcon name="auto_awesome" size={10} color={p.primary}/>
            <span style={{
              fontFamily: ff,
              fontSize: 10, fontWeight: 700, color: p.primary,
              letterSpacing: 0.4,
            }}>AI</span>
          </div>
        )}
        {showAiBadge && aiReason && (
          <div style={{
            display: 'inline-block', marginLeft: 6,
            fontFamily: ff,
            fontSize: 11, color: p.onSurfaceVariant,
            whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis',
            maxWidth: 160, verticalAlign: 'middle',
          }}>{aiReason}</div>
        )}
        <div style={{
          fontFamily: ff,
          fontSize: 15, lineHeight: 1.45,
          color: p.onSurface,
          fontWeight: article.isRead ? 500 : 600,
          display: '-webkit-box', WebkitLineClamp: 2, WebkitBoxOrient: 'vertical', overflow: 'hidden',
        }}>{article.title}</div>
        <div style={{
          display: 'flex', alignItems: 'center', gap: 6,
          marginTop: 6,
        }}>
          {/* favicon placeholder */}
          <div style={{
            width: 14, height: 14, borderRadius: 3,
            background: `oklch(${p.onSurface === '#E3E2E6' ? 0.45 : 0.75} 0.06 ${article.faviconHue || 220})`,
            flexShrink: 0,
          }}/>
          <span style={{
            fontFamily: ff,
            fontSize: 11, color: p.onSurfaceVariant,
            whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis',
            maxWidth: 120,
          }}>{article.feed}</span>
          <div style={{
            width: 3, height: 3, borderRadius: 2,
            background: p.outline, flexShrink: 0,
          }}/>
          <span style={{
            fontFamily: ff,
            fontSize: 11, color: p.onSurfaceVariant,
            flexShrink: 0,
          }}>{article.time}</span>
          {!article.isRead && (
            <div style={{
              width: 6, height: 6, borderRadius: 3,
              background: p.primary, flexShrink: 0,
            }}/>
          )}
        </div>
      </div>
      {/* Thumbnail 84x84 on right */}
      <div style={{
        width: 84, height: 84, flexShrink: 0,
        borderRadius: 14,
        background: `linear-gradient(135deg, ${article.c1}, ${article.c2})`,
        display: 'grid', placeItems: 'center',
      }}>
        <MIcon name="article" size={28} color={p.onPrimaryContainer}/>
      </div>
    </div>
  );
}

// ─── Large App Bar (matches LargeSliverAppBar, expanded state) ───
function M3LargeAppBar({ title, actions, p, ff = '"Noto Sans JP", system-ui' }) {
  return (
    <div style={{ background: p.surface, padding: '0 4px' }}>
      {/* Top action row */}
      <div style={{
        height: 56, display: 'flex', alignItems: 'center', justifyContent: 'flex-end',
        paddingRight: 4,
      }}>
        {actions}
      </div>
      {/* Big title row */}
      <div style={{
        padding: '8px 20px 16px',
        fontFamily: ff,
        fontSize: 32, fontWeight: 800, letterSpacing: -0.25,
        color: p.onSurface,
        lineHeight: 1.1,
      }}>{title}</div>
    </div>
  );
}

// ─── Home digest card (filled primaryContainer strip) ───
function HomeDigestCard({ p, ff, t }) {
  return (
    <div style={{ padding: '14px 16px' }}>
      <div style={{
        background: p.primaryContainer,
        borderRadius: 18,
        padding: '12px 14px',
        display: 'flex', alignItems: 'center', gap: 10,
        cursor: 'pointer',
      }}>
        <MIcon name="auto_awesome" size={22} color={p.onPrimaryContainer}/>
        <div style={{ flex: 1, minWidth: 0 }}>
          <div style={{
            fontFamily: ff,
            fontSize: 12, fontWeight: 700,
            color: p.onPrimaryContainer,
            lineHeight: 1.4,
          }}>{t.digestCardTitle}</div>
          <div style={{
            fontFamily: ff,
            fontSize: 12, color: p.onPrimaryContainer,
            opacity: 0.85, lineHeight: 1.4,
            whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis',
          }}>{t.digestCardSubtitle}</div>
        </div>
        <MIcon name="chevron_right" size={22} color={p.onPrimaryContainer}/>
      </div>
    </div>
  );
}

// ─── FAB ───
function FAB({ p, icon='add', onClick, extended = false, label, bottom = 16, ff = '"Noto Sans JP", system-ui' }) {
  return (
    <div onClick={onClick} style={{
      position: 'absolute', right: 16, bottom,
      height: 56, minWidth: 56,
      padding: extended ? '0 20px 0 16px' : 0,
      borderRadius: 16,
      background: p.primaryContainer,
      color: p.onPrimaryContainer,
      display: 'flex', alignItems: 'center', gap: 8, justifyContent: 'center',
      boxShadow: '0 3px 5px rgba(0,0,0,0.2), 0 1px 18px rgba(0,0,0,0.12)',
      cursor: 'pointer', zIndex: 10,
    }}>
      <MIcon name={icon} size={24} color={p.onPrimaryContainer}/>
      {extended && (
        <span style={{
          fontFamily: ff,
          fontSize: 14, fontWeight: 500, letterSpacing: 0.1,
        }}>{label}</span>
      )}
    </div>
  );
}

// ─────────────────────────────────────────────────────
// HOME SCREEN — accurate recreation (LargeAppBar + Digest card + AI section)
// ─────────────────────────────────────────────────────
function YomiHome({ dark = false, accent = '#4A90D9', selectedTab = 0, onTabSelect, lang = 'ja', showDigestCard = true }) {
  const p = palette(dark, accent);
  const t = getScreens(lang);
  const ff = screenFontFamily(lang);

  const chips = [
    { id: 'all', label: t.chipAll },
    { id: 'tech', label: t.chipTech },
    { id: 'biz', label: t.chipBiz },
    { id: 'design', label: t.chipDesign },
  ];
  const [sel, setSel] = useState('all');

  // AI recommended (top section)
  const aiItems = [
    { title: t.ai1Title, feed: t.ai1Feed, time: t.ai1Time, reason: t.ai1Reason, c1:'oklch(0.78 0.10 260)', c2:'oklch(0.86 0.10 30)', faviconHue: 260, isRead: false },
    { title: t.ai2Title, feed: t.ai2Feed, time: t.ai2Time, reason: t.ai2Reason, c1:'oklch(0.78 0.10 200)', c2:'oklch(0.86 0.08 320)', faviconHue: 200, isRead: false },
  ];
  // Regular articles
  const articles = [
    { title: t.art1Title, feed: t.art1Feed, time: t.art1Time, c1:'oklch(0.80 0.10 220)', c2:'oklch(0.85 0.09 50)', faviconHue: 220, isRead: false },
    { title: t.art2Title, feed: t.art2Feed, time: t.art2Time, c1:'oklch(0.80 0.10 300)', c2:'oklch(0.85 0.09 200)', faviconHue: 300, isRead: false },
    { title: t.art3Title, feed: t.art3Feed, time: t.art3Time, c1:'oklch(0.80 0.10 20)', c2:'oklch(0.85 0.09 140)', faviconHue: 20, isRead: true },
    { title: t.art4Title, feed: t.art4Feed, time: t.art4Time, c1:'oklch(0.80 0.10 140)', c2:'oklch(0.85 0.09 260)', faviconHue: 140, isRead: true },
  ];

  return (
    <div style={{background: p.surface, height: '100%', display: 'flex', flexDirection: 'column', position: 'relative'}}>
      <div style={{height: 54, flexShrink: 0}}/>
      <M3LargeAppBar
        p={p}
        title={t.appBarHome}
        actions={<>
          <M3IconButton icon="done_all" color={p.onSurface}/>
          <M3IconButton icon="filter_alt_outline" color={p.onSurface}/>
          <M3IconButton icon="rss_feed" color={p.onSurface}/>
        </>}
        ff={ff}
      />
      <FilterChipRow chips={chips} selected={sel} onSelect={setSel} p={p} ff={ff} showSearchButton/>

      <div style={{flex: 1, overflow: 'auto', background: p.surface}}>
        {sel === 'all' && showDigestCard && <HomeDigestCard p={p} ff={ff} t={t}/>}
        {sel === 'all' && (
          <>
            {/* AI section header */}
            <div style={{
              padding: '12px 16px 4px',
              display: 'flex', alignItems: 'center', gap: 6,
            }}>
              <MIcon name="auto_awesome" size={18} color={p.primary}/>
              <span style={{
                fontFamily: ff,
                fontSize: 14, fontWeight: 600, color: p.primary, letterSpacing: 0.1,
                whiteSpace: 'nowrap',
              }}>{t.aiRecommendLabel}</span>
            </div>
            {aiItems.map((a, i) => (
              <ArticleTile key={'ai'+i} article={a} p={p} showAiBadge aiReason={a.reason} ff={ff}/>
            ))}
            <div style={{height: 1, background: p.outlineVariant, margin: '0 16px'}}/>
          </>
        )}

        {articles.map((a, i) => (
          <ArticleTile key={i} article={a} p={p} ff={ff}/>
        ))}
        <div style={{height: 72}}/>
      </div>

      <FAB p={p} bottom={104}/>
      <M3NavBar p={p} selected={selectedTab} onSelect={onTabSelect} lang={lang}/>
    </div>
  );
}

// ─────────────────────────────────────────────────────
// SUBSCRIBED FEEDS — matches feed_management_screen.dart + reader_feed_pane.dart
// LargeAppBar + "すべて" virtual row + collapsible category sections + feed rows
// ─────────────────────────────────────────────────────
function YomiCategoryScreen({ dark = false, accent = '#4A90D9', unlocked = false, lang = 'ja' }) {
  const p = palette(dark, accent);
  const t = getScreens(lang);
  const ff = screenFontFamily(lang);

  const groups = [
    {
      id: 'tech',
      name: t.cat1,
      locked: false,
      feeds: [
        { id: 'f1', title: 'TechCrunch JP', unread: 12, hue: 200 },
        { id: 'f2', title: 'Zenn', unread: 8, hue: 280 },
        { id: 'f3', title: 'Qiita Trend', unread: 3, hue: 160 },
      ],
    },
    {
      id: 'biz',
      name: t.cat2,
      locked: false,
      feeds: [
        { id: 'f4', title: '日経XTECH', unread: 5, hue: 30 },
        { id: 'f5', title: 'NewsPicks', unread: 0, hue: 90 },
      ],
    },
    {
      id: 'private',
      name: t.cat3,
      locked: true,
      pulse: true,
      feeds: [
        { id: 'f6', title: 'Personal Blog', unread: 2, hue: 320 },
      ],
    },
    {
      id: 'news',
      name: t.cat5,
      locked: false,
      feeds: [
        { id: 'f7', title: 'NHK NEWS WEB', unread: 14, hue: 0 },
      ],
    },
  ];

  // Apply lock visibility
  const visibleGroups = groups.filter(g => unlocked || !g.locked);
  const totalUnread = visibleGroups.reduce((s, g) => s + g.feeds.reduce((a, f) => a + f.unread, 0), 0);

  return (
    <div style={{background: p.surface, height: '100%', display: 'flex', flexDirection: 'column', position: 'relative'}}>
      <div style={{height: 54, flexShrink: 0}}/>
      <M3LargeAppBar
        p={p}
        title={t.subscribedFeedsTitle}
        actions={<M3IconButton icon="edit" color={p.onSurface}/>}
        ff={ff}
      />

      <div style={{flex: 1, overflow: 'auto', padding: '12px 0'}}>
        {/* "すべて" virtual row */}
        <FeedListRow
          p={p} ff={ff}
          icon="inbox_outline"
          label={t.allFeedsLabel}
          unread={totalUnread}
          isVirtual
        />
        <div style={{ height: 1, background: p.outlineVariant, margin: '12px 0' }}/>

        {/* Category sections */}
        {visibleGroups.map((g, gi) => {
          const groupUnread = g.feeds.reduce((s, f) => s + f.unread, 0);
          const showPulse = g.pulse && !unlocked;
          return (
            <div key={g.id}>
              {/* Category header */}
              <div style={{
                position: 'relative',
                padding: '12px 16px',
                display: 'flex', alignItems: 'center', gap: 6,
                background: showPulse ? `${p.primary}0d` : 'transparent',
              }}>
                <MIcon name="expand_more" size={18} color={p.onSurfaceVariant}/>
                {g.locked && (
                  <MIcon name={(unlocked && g.pulse) ? 'lock_open' : 'lock'} size={14} color={p.primary}/>
                )}
                <span style={{
                  flex: 1, fontFamily: ff,
                  fontSize: 14, fontWeight: 700,
                  color: p.primary,
                  whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis',
                }}>{g.name}</span>
                {groupUnread > 0 && (
                  <UnreadBadge count={groupUnread} muted p={p} ff={ff}/>
                )}
                {showPulse && (
                  <span style={{
                    position: 'absolute', right: 8, top: 8, width: 28, height: 28,
                    borderRadius: 14,
                    animation: 'pulse-ring 1.8s ease-out infinite',
                    pointerEvents: 'none',
                  }}/>
                )}
              </div>
              {/* Feed rows */}
              {g.feeds.map((f, fi) => (
                <div key={f.id} style={{
                  display: 'flex', alignItems: 'center', gap: 12,
                  padding: '10px 16px 10px 32px',
                  cursor: 'pointer',
                }}>
                  {/* favicon */}
                  <div style={{
                    width: 18, height: 18, borderRadius: 4,
                    background: `oklch(0.78 0.10 ${f.hue})`,
                    display: 'grid', placeItems: 'center',
                    flexShrink: 0,
                  }}>
                    <MIcon name="rss_feed" size={12} color={p.onPrimary}/>
                  </div>
                  <span style={{
                    flex: 1, fontFamily: ff,
                    fontSize: 14,
                    fontWeight: f.unread > 0 ? 600 : 400,
                    color: p.onSurface,
                    whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis',
                  }}>{f.title}</span>
                  {f.unread > 0 && <UnreadBadge count={f.unread} p={p} ff={ff}/>}
                </div>
              ))}
            </div>
          );
        })}
        <div style={{ height: 58 }}/>
      </div>

      <style>{`@keyframes pulse-ring { 0% { box-shadow: 0 0 0 0 ${p.primary}55; } 70% { box-shadow: 0 0 0 14px ${p.primary}00; } 100% { box-shadow: 0 0 0 0 ${p.primary}00; } }`}</style>
    </div>
  );
}

function FeedListRow({ p, ff, icon, label, unread, isVirtual = false }) {
  return (
    <div style={{
      display: 'flex', alignItems: 'center', gap: 12,
      padding: '14px 16px',
      cursor: 'pointer',
    }}>
      <MIcon name={icon} size={24} color={p.primary}/>
      <span style={{
        flex: 1, fontFamily: ff,
        fontSize: 16, fontWeight: 600,
        color: p.onSurface,
      }}>{label}</span>
      {unread > 0 && <UnreadBadge count={unread} p={p} ff={ff}/>}
    </div>
  );
}

function UnreadBadge({ count, muted = false, p, ff }) {
  const bg = muted ? p.surfaceContainerHighest : p.primaryContainer;
  const fg = muted ? p.onSurfaceVariant : p.onPrimaryContainer;
  return (
    <div style={{
      minWidth: 24, height: 20,
      padding: '0 6px',
      background: bg,
      borderRadius: 10,
      display: 'grid', placeItems: 'center',
      fontFamily: ff,
      fontSize: 11, fontWeight: 700,
      color: fg,
    }}>{count > 999 ? '999+' : count}</div>
  );
}

// Compatibility alias (for gallery that used old name)
function YomiLockScreen(props) { return <YomiCategoryScreen {...props}/>; }

// ─────────────────────────────────────────────────────
// Material 3 NavigationBar — 4 destinations matching shell_screen.dart
// Home · Digest · Recommend · Settings (labels always visible, height 64)
// ─────────────────────────────────────────────────────
function M3NavBar({ p, selected = 0, onSelect = () => {}, lang = 'ja' }) {
  const t = getScreens(lang);
  const ff = screenFontFamily(lang);
  const items = [
    { icon: 'home_outline', selIcon: 'home', label: t.navHome },
    { icon: 'view_quilt_outline', selIcon: 'view_quilt', label: t.navDigest },
    { icon: 'auto_awesome_outline', selIcon: 'auto_awesome', label: t.navRecommend },
    { icon: 'settings_outline', selIcon: 'settings', label: t.navSettings },
  ];
  return (
    <div style={{
      flexShrink: 0,
      background: p.surfaceContainer,
      display: 'flex', alignItems: 'flex-start', justifyContent: 'space-around',
      paddingTop: 8, paddingBottom: 32,
      borderTop: 'none',
    }}>
      {items.map((it, i) => {
        const sel = i === selected;
        return (
          <div key={i} onClick={() => onSelect(i)} style={{
            flex: 1, position: 'relative',
            height: 48,
            display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 2,
            cursor: 'pointer',
          }}>
            <div style={{
              width: 56, height: 28, borderRadius: 14,
              background: sel ? p.primaryContainer : 'transparent',
              display: 'grid', placeItems: 'center',
              transition: 'background 0.2s ease',
            }}>
              <MIcon name={sel ? it.selIcon : it.icon} size={20} color={sel ? p.onPrimaryContainer : p.onSurfaceVariant}/>
            </div>
            <div style={{
              fontFamily: ff,
              fontSize: 11, letterSpacing: 0.3,
              fontWeight: sel ? 700 : 500,
              color: sel ? p.onSurface : p.onSurfaceVariant,
            }}>{it.label}</div>
          </div>
        );
      })}
    </div>
  );
}

// ─────────────────────────────────────────────────────
// Biometric dialog (Android-style Material 3)
// ─────────────────────────────────────────────────────
function BiometricSheet({ accent = '#4A90D9', dark = false, lang = 'ja' }) {
  const p = palette(dark, accent);
  const t = getScreens(lang);
  const ff = screenFontFamily(lang);
  return (
    <div style={{
      position: 'absolute', inset: 0, zIndex: 100,
      background: p.scrim,
      display: 'flex', alignItems: 'center', justifyContent: 'center',
      padding: 24,
    }}>
      <div style={{
        width: '100%', maxWidth: 320,
        background: p.surfaceContainerHigh,
        borderRadius: 28,
        padding: '24px 24px 16px',
        textAlign: 'center',
        color: p.onSurface,
      }}>
        <div style={{
          width: 64, height: 64, borderRadius: 32,
          background: p.primaryContainer,
          display: 'grid', placeItems: 'center', margin: '0 auto 16px',
          animation: 'scan-pulse 1.8s ease-in-out infinite',
        }}>
          <MIcon name="fingerprint" size={32} color={p.primary}/>
        </div>
        <div style={{
          fontFamily: ff,
          fontSize: 18, fontWeight: 500, letterSpacing: 0, marginBottom: 8,
        }}>{t.bioTitle}</div>
        <div style={{
          fontFamily: ff,
          fontSize: 13, color: p.onSurfaceVariant, letterSpacing: 0.2,
        }}>{t.bioBody}</div>
        <div style={{
          marginTop: 20, display: 'flex', justifyContent: 'flex-end',
        }}>
          <div style={{
            padding: '10px 16px',
            fontFamily: ff,
            fontSize: 14, color: p.primary, fontWeight: 500, letterSpacing: 0.1,
          }}>{t.bioCancel}</div>
        </div>
      </div>
      <style>{`@keyframes scan-pulse { 0%,100% { transform: scale(1);} 50% { transform: scale(1.08);} }`}</style>
    </div>
  );
}

// ─────────────────────────────────────────────────────
// ARTICLE DETAIL — matches article_detail_panel.dart (Reader screen)
// AppBar with translate/bookmark/browser/share + category label + title +
// meta row + hero 16:9 + full-content toggle + AI summary card + body +
// related articles
// ─────────────────────────────────────────────────────
function YomiArticle({ dark = false, accent = '#4A90D9', lang = 'ja' }) {
  const p = palette(dark, accent);
  const t = getScreens(lang);
  const ff = screenFontFamily(lang);
  const monoFf = 'JetBrains Mono, monospace';
  return (
    <div style={{background: p.surface, height: '100%', display: 'flex', flexDirection: 'column', position: 'relative'}}>
      <div style={{height: 54, flexShrink: 0}}/>
      <M3AppBar
        p={p}
        leading={<M3IconButton icon="chevron_left" color={p.onSurface}/>}
        actions={<>
          <M3IconButton icon="translate" color={p.onSurface}/>
          <M3IconButton icon="bookmark" color={p.amber}/>
          <M3IconButton icon="open_in_browser" color={p.onSurface}/>
          <M3IconButton icon="share" color={p.onSurface}/>
        </>}
        title=""
        ff={ff}
      />

      <div style={{flex: 1, overflow: 'auto'}}>
        <div style={{ padding: '16px 20px 0' }}>
          {/* Category label (UPPERCASE primary) */}
          <div style={{
            marginBottom: 8,
            fontFamily: monoFf,
            fontSize: 12, fontWeight: 700,
            color: p.primary,
            letterSpacing: 0.48,
          }}>{t.articleCategoryLabel}</div>

          {/* Title 24px w700 */}
          <div style={{
            fontFamily: ff,
            fontSize: 24, fontWeight: 700, color: p.onSurface,
            lineHeight: 1.4,
          }}>{t.articleTitle}</div>

          {/* Meta row: favicon + feed + · + time */}
          <div style={{
            marginTop: 12, display: 'flex', alignItems: 'center', gap: 8,
          }}>
            <div style={{
              width: 12, height: 12, borderRadius: 3,
              background: 'oklch(0.65 0.10 200)', flexShrink: 0,
            }}/>
            <span style={{
              fontFamily: ff,
              fontSize: 12, color: p.onSurfaceVariant,
              maxWidth: 160,
              whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis',
            }}>{t.articleFeed}</span>
            <span style={{ color: p.outline, fontSize: 12, marginLeft: 2 }}>·</span>
            <span style={{
              fontFamily: ff,
              fontSize: 12, color: p.onSurfaceVariant,
            }}>{t.articleTime}</span>
          </div>

          {/* 16:9 hero with rounded 16 */}
          <div style={{
            marginTop: 16,
            width: '100%', aspectRatio: '16/9',
            borderRadius: 16, overflow: 'hidden',
            background: `repeating-linear-gradient(135deg, ${dark ? '#2a3340' : '#DCE7F5'}, ${dark ? '#2a3340' : '#DCE7F5'} 12px, ${dark ? '#232b37' : '#CFDFF0'} 12px, ${dark ? '#232b37' : '#CFDFF0'} 24px)`,
            position: 'relative',
          }}>
            <span style={{
              position: 'absolute', bottom: 8, left: 12,
              fontFamily: monoFf, fontSize: 10,
              color: dark ? 'rgba(255,255,255,0.5)' : 'rgba(0,0,0,0.4)',
            }}>{t.articleHeroLabel}</span>
          </div>

          {/* Full-content toggle row */}
          <div style={{
            marginTop: 8, marginBottom: 4,
            padding: '4px 0',
            display: 'flex', alignItems: 'center', gap: 8,
          }}>
            <MIcon name="article" size={18} color={p.primary}/>
            <span style={{
              flex: 1, fontFamily: ff,
              fontSize: 14, fontWeight: 600, color: p.primary,
            }}>{t.articleFullContent}</span>
            <MIcon name="error_outline" size={20} color={p.primary}/>
            {/* Material-style switch */}
            <div style={{
              width: 52, height: 32, borderRadius: 16,
              background: p.primary,
              padding: '2px',
              display: 'flex', alignItems: 'center', justifyContent: 'flex-end',
              flexShrink: 0,
            }}>
              <div style={{
                width: 24, height: 24, borderRadius: 12,
                background: p.onPrimary,
              }}/>
            </div>
          </div>

          {/* AI Summary card (tertiaryContainer) */}
          <div style={{
            marginTop: 12, marginBottom: 16,
            padding: 14,
            background: `color-mix(in oklch, ${accent} 22%, ${dark ? '#1a1c1e' : '#ffffff'})`,
            borderRadius: 16,
          }}>
            <div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
              <MIcon name="auto_awesome" size={14} color={p.onSurface}/>
              <span style={{
                fontFamily: ff,
                fontSize: 11, fontWeight: 700, letterSpacing: 0.4,
                color: p.onSurface,
              }}>{t.articleSummaryTitle}</span>
              <div style={{ flex: 1 }}/>
              <MIcon name="refresh" size={16} color={p.onSurface}/>
            </div>
            <div style={{ marginTop: 8 }}>
              {t.articleSummaryBullets.map((b, i) => (
                <div key={i} style={{
                  paddingTop: 4, paddingLeft: 4,
                  display: 'flex', alignItems: 'flex-start', gap: 0,
                }}>
                  <span style={{
                    fontFamily: ff, fontSize: 14, color: p.onSurface,
                    lineHeight: 1.7,
                  }}>・</span>
                  <span style={{
                    fontFamily: ff, fontSize: 13, color: p.onSurface,
                    lineHeight: 1.7,
                    flex: 1,
                  }}>{b}</span>
                </div>
              ))}
            </div>
          </div>

          {/* Article body placeholder lines */}
          <div style={{display: 'flex', flexDirection: 'column', gap: 10, paddingBottom: 16}}>
            {[95, 100, 88, 95, 78, 90, 72, 98, 60, 85].map((w, i) => (
              <div key={i} style={{
                height: 10, width: `${w}%`, borderRadius: 4,
                background: p.surfaceContainerHigh,
              }}/>
            ))}
          </div>
        </div>

        {/* Related articles section */}
        <div style={{
          marginTop: 8,
          borderTop: `1px solid ${p.outlineVariant}`,
          padding: '20px 20px 66px',
        }}>
          <div style={{ display: 'flex', alignItems: 'center', gap: 6, marginBottom: 12 }}>
            <MIcon name="article" size={14} color={p.primary}/>
            <span style={{
              fontFamily: ff,
              fontSize: 12, fontWeight: 700, color: p.primary, letterSpacing: 0.72,
            }}>{t.articleRelatedLabel}</span>
          </div>
          {t.articleRelated.map((r, i) => (
            <div key={i} style={{
              padding: '10px 0',
              borderTop: i > 0 ? `1px solid ${p.outlineVariant}` : 'none',
              display: 'flex', gap: 12, alignItems: 'center',
            }}>
              <div style={{ flex: 1, minWidth: 0 }}>
                <div style={{
                  fontFamily: ff, fontSize: 13, fontWeight: 600,
                  color: p.onSurface, lineHeight: 1.4,
                  display: '-webkit-box', WebkitLineClamp: 2, WebkitBoxOrient: 'vertical', overflow: 'hidden',
                }}>{r.title}</div>
                <div style={{
                  marginTop: 2,
                  fontFamily: ff, fontSize: 11, color: p.onSurfaceVariant,
                  whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis',
                }}>{r.feed} · {r.time}</div>
              </div>
              <div style={{
                width: 64, height: 48, borderRadius: 8,
                background: `linear-gradient(135deg, oklch(0.80 0.10 ${r.hue}), oklch(0.85 0.09 ${(r.hue + 60) % 360}))`,
                flexShrink: 0,
              }}/>
            </div>
          ))}
        </div>
      </div>
    </div>
  );
}

// ─────────────────────────────────────────────────────
// RECOMMENDATION SCREEN — matches recommendation_screen.dart
// ─────────────────────────────────────────────────────
function YomiRecommendScreen({ dark = false, accent = '#4A90D9', lang = 'ja', selectedTab = 2, onTabSelect }) {
  const p = palette(dark, accent);
  const t = getScreens(lang);
  const ff = screenFontFamily(lang);
  const feeds = [
    { title: t.feed1Title, url: t.feed1Url, reason: t.feed1Reason },
    { title: t.feed2Title, url: t.feed2Url, reason: t.feed2Reason },
    { title: t.feed3Title, url: t.feed3Url, reason: t.feed3Reason },
  ];
  return (
    <div style={{background: p.surface, height: '100%', display: 'flex', flexDirection: 'column', position: 'relative'}}>
      <div style={{height: 54, flexShrink: 0}}/>
      <M3LargeAppBar
        p={p}
        title={t.recommendTitle}
        actions={<M3IconButton icon="insights" color={p.onSurface}/>}
        ff={ff}
      />

      <div style={{flex: 1, overflow: 'auto', padding: '8px 8px 24px'}}>
        {feeds.map((f, i) => (
          <div key={i} style={{
            margin: '8px 8px',
            padding: 16,
            borderRadius: 12,
            background: p.surfaceContainer,
            display: 'flex', flexDirection: 'column', gap: 10,
          }}>
            <div style={{display: 'flex', alignItems: 'center', gap: 10}}>
              <div style={{
                width: 40, height: 40, borderRadius: 8,
                background: p.primaryContainer,
                display: 'grid', placeItems: 'center',
              }}>
                <MIcon name="rss_feed" size={20} color={p.primary}/>
              </div>
              <div style={{flex: 1, minWidth: 0}}>
                <div style={{
                  fontFamily: ff,
                  fontSize: 15, fontWeight: 500, color: p.onSurface,
                }}>{f.title}</div>
                <div style={{
                  fontFamily: 'JetBrains Mono, monospace',
                  fontSize: 11, color: p.onSurfaceVariant, marginTop: 2,
                }}>{f.url}</div>
              </div>
            </div>
            <div style={{
              display: 'flex', alignItems: 'center', gap: 6,
              padding: '6px 10px',
              background: `${p.primary}14`,
              borderRadius: 8,
            }}>
              <MIcon name="auto_awesome" size={14} color={p.primary}/>
              <span style={{
                fontFamily: ff,
                fontSize: 12, color: p.primary, letterSpacing: 0.1,
              }}>{f.reason}</span>
            </div>
            <div style={{display: 'flex', justifyContent: 'flex-end'}}>
              <div style={{
                height: 36, padding: '0 16px', borderRadius: 18,
                background: p.primary, color: p.onPrimary,
                display: 'flex', alignItems: 'center', gap: 6,
                fontFamily: ff,
                fontSize: 13, fontWeight: 500, letterSpacing: 0.1,
              }}>
                <MIcon name="add" size={16} color={p.onPrimary}/>
                {t.recommendAdd}
              </div>
            </div>
          </div>
        ))}
      </div>

      <M3NavBar p={p} selected={selectedTab} onSelect={onTabSelect} lang={lang}/>
    </div>
  );
}

// ─────────────────────────────────────────────────────
// DIGEST SCREEN — matches digest_screen.dart (mobile Pro view)
// LargeAppBar + summary strip + topic cards
// ─────────────────────────────────────────────────────
function YomiDigestScreen({ dark = false, accent = '#4A90D9', lang = 'ja', selectedTab = 1, onTabSelect }) {
  const p = palette(dark, accent);
  const t = getScreens(lang);
  const ff = screenFontFamily(lang);
  const topics = t.digestTopics || [];

  return (
    <div style={{background: p.surface, height: '100%', display: 'flex', flexDirection: 'column', position: 'relative'}}>
      <div style={{height: 54, flexShrink: 0}}/>
      <M3LargeAppBar
        p={p}
        title={t.digestTitle}
        actions={<M3IconButton icon="history" color={p.onSurface}/>}
        ff={ff}
      />

      <div style={{flex: 1, overflow: 'auto'}}>
        {/* Summary strip */}
        <div style={{
          padding: '4px 20px 12px',
          display: 'flex', alignItems: 'center', gap: 8,
        }}>
          <span style={{
            flex: 1, fontFamily: ff, fontSize: 12,
            color: p.onSurfaceVariant,
            whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis',
          }}>{t.digestSummaryDate} · {t.digestSummaryCount}</span>
          <div style={{
            display: 'flex', alignItems: 'center', gap: 4,
            color: p.primary,
          }}>
            <MIcon name="refresh" size={14} color={p.primary}/>
            <span style={{
              fontFamily: ff, fontSize: 12, fontWeight: 600, color: p.primary,
            }}>{t.digestRegenerate}</span>
          </div>
        </div>

        {/* Topic cards */}
        {topics.map((topic, i) => (
          <div key={i} style={{
            margin: '8px 16px',
            background: p.surfaceContainerLow || p.surfaceContainer,
            border: `1px solid ${p.outlineVariant}`,
            borderRadius: 18,
            overflow: 'hidden',
          }}>
            <div style={{ padding: '16px 16px 8px' }}>
              <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
                {/* Importance badge */}
                <div style={{
                  display: 'inline-flex', alignItems: 'center', gap: 4,
                  padding: '3px 8px', borderRadius: 6,
                  background: topic.importance === 'critical'
                    ? `${p.error}22`
                    : topic.importance === 'high'
                    ? `${p.primary}22`
                    : p.surfaceContainerHigh,
                  color: topic.importance === 'critical'
                    ? p.error
                    : topic.importance === 'high'
                    ? p.primary
                    : p.onSurfaceVariant,
                }}>
                  <span style={{
                    fontFamily: ff, fontSize: 10, fontWeight: 700, letterSpacing: 0.4,
                  }}>{topic.importanceLabel}</span>
                </div>
                <span style={{
                  fontFamily: ff, fontSize: 16, fontWeight: 700, color: p.onSurface,
                  lineHeight: 1.35,
                  flex: 1, minWidth: 0,
                }}>{topic.title}</span>
              </div>
              <div style={{
                marginTop: 8,
                fontFamily: ff, fontSize: 13, color: p.onSurface,
                lineHeight: 1.6,
                opacity: 0.85,
              }}>{topic.summary}</div>
              <div style={{
                marginTop: 12, display: 'flex', alignItems: 'center', gap: 6,
              }}>
                <MIcon name="article" size={12} color={p.primary}/>
                <span style={{
                  fontFamily: ff, fontSize: 11, fontWeight: 700,
                  color: p.primary, letterSpacing: 0.72,
                }}>{t.digestRelatedArticles}</span>
              </div>
            </div>
            <div style={{ height: 1, background: p.outlineVariant, margin: '0 16px' }}/>
            {topic.articles.map((a, j) => (
              <div key={j} style={{
                padding: '10px 16px',
                display: 'flex', gap: 12, alignItems: 'center',
                borderTop: j > 0 ? `1px solid ${p.outlineVariant}` : 'none',
              }}>
                <div style={{ flex: 1, minWidth: 0 }}>
                  <div style={{
                    fontFamily: ff, fontSize: 13, fontWeight: 600,
                    color: p.onSurface, lineHeight: 1.4,
                    display: '-webkit-box', WebkitLineClamp: 2, WebkitBoxOrient: 'vertical', overflow: 'hidden',
                  }}>{a.title}</div>
                  <div style={{
                    marginTop: 2,
                    fontFamily: ff, fontSize: 11, color: p.onSurfaceVariant,
                    whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis',
                  }}>{a.feed} · {a.time}</div>
                </div>
                <div style={{
                  width: 64, height: 48, borderRadius: 8,
                  background: `linear-gradient(135deg, oklch(0.80 0.10 ${a.hue}), oklch(0.85 0.09 ${(a.hue + 60) % 360}))`,
                  flexShrink: 0,
                }}/>
              </div>
            ))}
          </div>
        ))}
        <div style={{ height: 80 }}/>
      </div>

      <M3NavBar p={p} selected={selectedTab} onSelect={onTabSelect} lang={lang}/>
    </div>
  );
}

// Legacy placeholder component that lp.jsx might still reference
function ImgPlaceholder({ w = '100%', h = 88, hue = 240, dark = false, label }) {
  const bg1 = `oklch(${dark ? 0.30 : 0.92} 0.03 ${hue})`;
  const bg2 = `oklch(${dark ? 0.26 : 0.88} 0.04 ${hue})`;
  return (
    <div style={{
      width: w, height: h, borderRadius: 6,
      background: `repeating-linear-gradient(135deg, ${bg1}, ${bg1} 8px, ${bg2} 8px, ${bg2} 16px)`,
      flexShrink: 0, position: 'relative', overflow: 'hidden',
    }}>
      {label && <span style={{
        position:'absolute', bottom:4, left:6,
        fontFamily:'JetBrains Mono, monospace', fontSize:8,
        color: dark?'rgba(255,255,255,0.6)':'rgba(0,0,0,0.4)',
      }}>{label}</span>}
    </div>
  );
}

// "Icon" legacy export (used by lp.jsx — remap to MIcon)
function Icon({ name, size = 16, color = 'currentColor', stroke }) {
  const map = {
    sparkle: 'auto_awesome', lock: 'lock', unlock: 'lock_open',
    cloud: 'cloud_off', bookmark: 'bookmark_border',
    download: 'download', search: 'search',
    home: 'article', grid: 'widgets', settings: 'insights',
    fingerprint: 'fingerprint', chevron: 'chevron_left', close: 'close',
    clock: 'article', check: 'auto_awesome', plus: 'add',
    rss: 'rss_feed',
  };
  return <MIcon name={map[name] || name} size={size} color={color}/>;
}

Object.assign(window, {
  MIcon, Icon, ImgPlaceholder, palette, M3,
  YomiHome, YomiCategoryScreen, YomiLockScreen, YomiArticle, YomiRecommendScreen,
  YomiDigestScreen,
  BiometricSheet, M3NavBar, M3LargeAppBar, HomeDigestCard,
});
