/* iColleges UI kit — reusable components shared across guideline + pages.
   Depends on tokens.css for CSS variables.
   Load order:  React → ReactDOM → Babel → logo.jsx → ui-kit.jsx → page script. */

/* ─────────────────────────────────────────────────────────────────
   Icon system — line icons in a single <Icon name="…" /> component.
   Stroke 1.6, round caps, 24-grid; size prop controls width/height.
───────────────────────────────────────────────────────────────── */
const ICON_PATHS = {
  search:   "M10.5 4a6.5 6.5 0 1 1 0 13 6.5 6.5 0 0 1 0-13Zm5 11.5 4.5 4.5",
  pin:      "M12 21s7-6.2 7-11a7 7 0 1 0-14 0c0 4.8 7 11 7 11Zm0-8.5a2.5 2.5 0 1 1 0-5 2.5 2.5 0 0 1 0 5Z",
  filter:   "M4 5h16M7 12h10M10 19h4",
  sort:     "M7 5v14m0 0-3-3m3 3 3-3M17 19V5m0 0-3 3m3-3 3 3",
  star:     "m12 4 2.4 5 5.6.8-4 3.9.9 5.5L12 16.6 7 19.2l1-5.5-4-3.9 5.6-.8L12 4Z",
  check:    "m5 12 4 4 10-10",
  chevdown: "m6 9 6 6 6-6",
  chevright:"m9 6 6 6-6 6",
  close:    "M6 6l12 12M6 18 18 6",
  user:     "M12 12a4 4 0 1 0 0-8 4 4 0 0 0 0 8Zm-7 8a7 7 0 1 1 14 0",
  building: "M5 21V5h14v16M5 21h14M9 9h2m2 0h2M9 13h2m2 0h2M9 17h2m2 0h2",
  graduation:"M3 9l9-4 9 4-9 4-9-4Zm4 2v4c0 1.7 2.7 3 6 3s6-1.3 6-3v-4",
  rouble:   "M8 5h5a4 4 0 0 1 0 8H6m2-8v14m-2-6h8",
  bed:      "M3 18V8M3 14h18M21 18V12a3 3 0 0 0-3-3H10v5",
  spark:    "M12 4v3m0 10v3M4 12h3m10 0h3M6.3 6.3l2.1 2.1m7.2 7.2 2.1 2.1M6.3 17.7l2.1-2.1m7.2-7.2 2.1-2.1",
  compass:  "M12 21a9 9 0 1 0 0-18 9 9 0 0 0 0 18Zm4-13-2 6-6 2 2-6 6-2Z",
  heart:    "M12 20s-7-4.5-7-10a4 4 0 0 1 7-2.6A4 4 0 0 1 19 10c0 5.5-7 10-7 10Z",
  scales:   "M12 4v16M5 20h14M7 8 4 16h6L7 8Zm10 0-3 8h6l-3-8ZM6 4h12",
  calendar: "M5 7h14v13H5zM5 7V5h14v2M9 3v4m6-4v4M5 11h14",
  clock:    "M12 21a9 9 0 1 0 0-18 9 9 0 0 0 0 18Zm0-13v5l3 2",
  arrowR:   "M5 12h14m-5-5 5 5-5 5",
  plus:     "M12 5v14M5 12h14",
  trophy:   "M8 4h8v4a4 4 0 0 1-8 0V4Zm-2 1H4v2a3 3 0 0 0 3 3m11-5h2v2a3 3 0 0 1-3 3M10 14h4v2h-4zM8 20h8",
  bolt:     "M13 3 5 14h6l-1 7 8-11h-6l1-7Z",
  grid:     "M4 4h7v7H4zM13 4h7v7h-7zM4 13h7v7H4zM13 13h7v7h-7z",
  list:     "M4 6h16M4 12h16M4 18h16",
};
function Icon({ name, size = 20, color = "currentColor", strokeWidth = 1.6, style }) {
  const d = ICON_PATHS[name];
  if (!d) return null;
  return (
    <svg
      width={size}
      height={size}
      viewBox="0 0 24 24"
      fill="none"
      stroke={color}
      strokeWidth={strokeWidth}
      strokeLinecap="round"
      strokeLinejoin="round"
      style={style}
      aria-hidden
    >
      <path d={d} />
    </svg>
  );
}

/* ─────────────────────────────────────────────────────────────────
   Buttons
───────────────────────────────────────────────────────────────── */
function Button({
  children,
  variant = "primary",      // primary | secondary | ghost
  size = "md",              // sm | md | lg
  iconLeft,
  iconRight,
  disabled,
  onClick,
  style,
  full,
  type = "button",
  as: As = "button",
  href,
}) {
  const pad = { sm: "0 12px", md: "0 18px", lg: "0 22px" }[size];
  const h   = { sm: 32, md: 40, lg: 48 }[size];
  const fs  = { sm: 13, md: 15, lg: 16 }[size];

  const base = {
    display: "inline-flex",
    alignItems: "center",
    justifyContent: "center",
    gap: 8,
    height: h,
    padding: pad,
    borderRadius: "var(--r-md)",
    fontFamily: "var(--font-text)",
    fontWeight: 500,
    fontSize: fs,
    letterSpacing: "-0.005em",
    lineHeight: 1,
    cursor: disabled ? "not-allowed" : "pointer",
    opacity: disabled ? 0.5 : 1,
    border: "1px solid transparent",
    transition: "background .15s ease, border-color .15s ease, color .15s ease",
    width: full ? "100%" : "auto",
    textDecoration: "none",
    whiteSpace: "nowrap",
  };
  const styles = {
    primary:   { ...base, background: "var(--teal)",       color: "#fff",            borderColor: "var(--teal)" },
    secondary: { ...base, background: "transparent",       color: "var(--ink)",      borderColor: "var(--line-strong)" },
    ghost:     { ...base, background: "transparent",       color: "var(--teal-dark)",borderColor: "transparent", padding: pad },
  }[variant];

  const props = {
    onClick: disabled ? undefined : onClick,
    style: { ...styles, ...style },
    className: `btn btn-${variant} btn-${size}`,
    disabled,
  };
  if (As === "a") return <a href={href} {...props}>{iconLeft && <Icon name={iconLeft} size={size==="sm"?14:16} />}{children}{iconRight && <Icon name={iconRight} size={size==="sm"?14:16} />}</a>;
  return (
    <button type={type} {...props}>
      {iconLeft && <Icon name={iconLeft} size={size==="sm"?14:16} />}
      {children}
      {iconRight && <Icon name={iconRight} size={size==="sm"?14:16} />}
    </button>
  );
}

/* ─────────────────────────────────────────────────────────────────
   Input + Select
───────────────────────────────────────────────────────────────── */
function Input({
  value, onChange, placeholder, iconLeft, iconRight, size = "md",
  type = "text", style, full, ...rest
}) {
  const h = { sm: 32, md: 40, lg: 48 }[size];
  const pl = iconLeft ? 38 : 14;
  const pr = iconRight ? 38 : 14;
  const isControlled = typeof onChange === "function";
  return (
    <label style={{ position: "relative", display: full ? "block" : "inline-block", width: full ? "100%" : "auto" }}>
      {iconLeft && (
        <span style={{ position: "absolute", left: 12, top: "50%", transform: "translateY(-50%)", color: "var(--ink-2)" }}>
          <Icon name={iconLeft} size={size==="sm"?14:18} />
        </span>
      )}
      <input
        type={type}
        {...(isControlled
          ? { value: value ?? "", onChange }
          : (value !== undefined ? { defaultValue: value } : {}))}
        placeholder={placeholder}
        style={{
          height: h,
          width: "100%",
          padding: `0 ${pr}px 0 ${pl}px`,
          borderRadius: "var(--r-md)",
          border: "1px solid var(--line-strong)",
          background: "var(--white)",
          fontSize: 15,
          fontFamily: "inherit",
          color: "var(--ink)",
          outline: "none",
          transition: "border-color .15s ease, box-shadow .15s ease",
          ...style,
        }}
        onFocus={(e) => { e.target.style.borderColor = "var(--teal)"; e.target.style.boxShadow = "var(--focus-ring)"; }}
        onBlur={(e) => { e.target.style.borderColor = "var(--line-strong)"; e.target.style.boxShadow = "none"; }}
        {...rest}
      />
      {iconRight && (
        <span style={{ position: "absolute", right: 12, top: "50%", transform: "translateY(-50%)", color: "var(--ink-2)" }}>
          <Icon name={iconRight} size={size==="sm"?14:18} />
        </span>
      )}
    </label>
  );
}

/* ────────────────────────────────────────────────────────────────────
   Dropdown — кастомный селект со своим попапом (вместо нативного <select>).
   API совместимый с Select: value, onChange (вызывается с {target: {value}}), options.
─────────────────────────────────────────────────────────────────── */
function Dropdown({
  value, onChange, options = [], placeholder = "Выберите",
  size = "md", full = false, iconLeft, label, multi = false,
  searchable = false, searchPlaceholder = "Поиск…",
}) {
  const [open, setOpen] = React.useState(false);
  const [hover, setHover] = React.useState(-1);
  const [query, setQuery] = React.useState("");
  const wrapRef = React.useRef(null);
  const popRef = React.useRef(null);
  const searchRef = React.useRef(null);

  /* Фильтруем опции по поисковому запросу (если searchable) */
  const filteredOptions = React.useMemo(() => {
    if (!searchable || !query) return options;
    const q = query.toLowerCase().trim();
    return options.filter(o => {
      const lbl = typeof o === "string" ? o : (o.label || "");
      return lbl.toLowerCase().includes(q);
    });
  }, [options, query, searchable]);

  React.useEffect(() => {
    if (open && searchable && searchRef.current) {
      setTimeout(() => searchRef.current && searchRef.current.focus(), 30);
    }
    if (!open) setQuery("");
  }, [open, searchable]);

  const isSelectedVal = (v) => multi
    ? Array.isArray(value) && value.includes(v)
    : value === v;

  const emit = (v) => {
    if (!multi) {
      onChange && onChange({ target: { value: v } });
      setOpen(false);
      return;
    }
    const cur = Array.isArray(value) ? value : [];
    const next = cur.includes(v) ? cur.filter(x => x !== v) : [...cur, v];
    onChange && onChange({ target: { value: next } });
  };

  React.useEffect(() => {
    if (!open) return;
    const onDocClick = (e) => {
      if (wrapRef.current && !wrapRef.current.contains(e.target)) setOpen(false);
    };
    const onKey = (e) => {
      if (e.key === "Escape") setOpen(false);
      if (e.key === "ArrowDown") { e.preventDefault(); setHover(h => Math.min(h + 1, filteredOptions.length - 1)); }
      if (e.key === "ArrowUp")   { e.preventDefault(); setHover(h => Math.max(h - 1, 0)); }
      if (e.key === "Enter" && hover >= 0) {
        const o = filteredOptions[hover];
        const v = typeof o === "string" ? o : o.value;
        emit(v);
      }
    };
    document.addEventListener("mousedown", onDocClick);
    document.addEventListener("keydown", onKey);
    return () => {
      document.removeEventListener("mousedown", onDocClick);
      document.removeEventListener("keydown", onKey);
    };
  }, [open, hover, options, onChange, value, multi]);

  const h = { sm: 32, md: 40, lg: 48 }[size];
  const fs = { sm: 13, md: 15, lg: 16 }[size];

  let selectedLabel, isEmpty;
  if (multi) {
    const arr = Array.isArray(value) ? value : [];
    isEmpty = arr.length === 0;
    if (isEmpty) selectedLabel = label || placeholder;
    else if (arr.length === 1) {
      const o = options.find(x => (typeof x === "string" ? x : x.value) === arr[0]);
      selectedLabel = o ? (typeof o === "string" ? o : o.label) : arr[0];
    } else {
      selectedLabel = arr.length + " выбрано";
    }
  } else {
    const selected = options.find(o => (typeof o === "string" ? o : o.value) === value);
    isEmpty = !selected;
    selectedLabel = selected ? (typeof selected === "string" ? selected : selected.label) : (label || placeholder);
  }
  const hasActive = multi ? (Array.isArray(value) && value.length > 0) : !!value;

  return (
    <div ref={wrapRef} style={{
      position: "relative", display: full ? "block" : "inline-block",
      width: full ? "100%" : "auto", fontFamily: "inherit",
    }}>
      <button type="button" onClick={() => { setOpen(o => !o); setHover(-1); }}
        style={{
          appearance: "none",
          height: h,
          padding: iconLeft ? "0 36px 0 38px" : "0 36px 0 14px",
          width: full ? "100%" : "auto",
          minWidth: 160,
          border: "1px solid " + (open ? "var(--teal)" : (hasActive ? "var(--teal)" : "var(--line-strong)")),
          background: hasActive && !open ? "var(--teal-light)" : "var(--white)",
          borderRadius: "var(--r-md)",
          fontSize: fs, fontFamily: "inherit",
          color: isEmpty ? "var(--ink-2)" : (hasActive ? "var(--teal-deep)" : "var(--ink)"),
          fontWeight: hasActive && !isEmpty ? 600 : 400,
          textAlign: "left",
          cursor: "pointer",
          boxShadow: open ? "var(--focus-ring)" : "none",
          position: "relative",
          transition: "border-color .15s, box-shadow .15s",
          whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis",
        }}>
        {iconLeft && (
          <span style={{ position: "absolute", left: 12, top: "50%",
              transform: "translateY(-50%)", color: "var(--ink-2)" }}>
            <Icon name={iconLeft} size={16} />
          </span>
        )}
        {selectedLabel}
        <span style={{ position: "absolute", right: 12, top: "50%",
            transform: "translateY(-50%) rotate(" + (open ? 180 : 0) + "deg)",
            color: "var(--ink-2)",
            transition: "transform .2s ease" }}>
          <Icon name="chevdown" size={16} />
        </span>
      </button>
      {open && (
        <div ref={popRef} role="listbox"
          style={{
            position: "absolute", top: "calc(100% + 6px)", left: 0,
            minWidth: "100%", width: "max-content", maxWidth: 340,
            background: "var(--white)",
            border: "1px solid var(--line)",
            borderRadius: "var(--r-md)",
            boxShadow: "var(--shadow-3)",
            padding: 6, zIndex: 50,
            maxHeight: 360, overflowY: "auto",
            animation: "dropdown-in .15s ease-out",
          }}>
          {searchable && (
            <div style={{
              padding: "4px 4px 8px 4px",
              position: "sticky", top: -6, background: "var(--white)", zIndex: 1,
              marginBottom: 2, borderBottom: "1px solid var(--line)",
            }}>
              <input ref={searchRef} type="text" value={query}
                onChange={(e) => { setQuery(e.target.value); setHover(0); }}
                placeholder={searchPlaceholder}
                style={{
                  width: "100%", boxSizing: "border-box",
                  height: 32, padding: "0 10px",
                  border: "1px solid var(--line-strong)",
                  borderRadius: "var(--r-sm)",
                  fontSize: 13, fontFamily: "inherit", color: "var(--ink)",
                  outline: "none",
                }} />
            </div>
          )}
          {filteredOptions.length === 0 && (
            <div style={{ padding: "12px 10px", fontSize: 13, color: "var(--ink-2)", textAlign: "center" }}>
              Ничего не найдено
            </div>
          )}
          {filteredOptions.map((o, i) => {
            const v = typeof o === "string" ? o : o.value;
            const l = typeof o === "string" ? o : o.label;
            const isSelected = isSelectedVal(v);
            const isHover = hover === i;
            return (
              <div key={i} role="option" aria-selected={isSelected}
                onMouseEnter={() => setHover(i)}
                onClick={() => emit(v)}
                style={{
                  display: "flex", alignItems: "center", gap: 8,
                  padding: "9px 10px 9px 10px",
                  borderRadius: "var(--r-sm)",
                  fontSize: 14, lineHeight: 1.25,
                  color: isSelected ? "var(--teal-deep)" : "var(--ink)",
                  background: isSelected
                    ? "var(--teal-light)"
                    : (isHover ? "var(--base)" : "transparent"),
                  fontWeight: isSelected ? 600 : 500,
                  cursor: "pointer",
                  whiteSpace: "nowrap",
                  transition: "background .12s ease",
                }}>
                {multi ? (
                  <span style={{
                    width: 16, height: 16, flexShrink: 0, borderRadius: 4,
                    border: "1.5px solid " + (isSelected ? "var(--teal)" : "var(--line-strong)"),
                    background: isSelected ? "var(--teal)" : "transparent",
                    color: "#fff",
                    display: "inline-flex", alignItems: "center", justifyContent: "center",
                    transition: "background .12s, border-color .12s",
                  }}>
                    {isSelected && <Icon name="check" size={11} />}
                  </span>
                ) : (
                  <span style={{
                    width: 16, height: 16, flexShrink: 0,
                    display: "inline-flex", alignItems: "center", justifyContent: "center",
                    color: isSelected ? "var(--teal)" : "transparent",
                  }}>
                    <Icon name="check" size={14} />
                  </span>
                )}
                <span>{l}</span>
              </div>
            );
          })}
        </div>
      )}
      <style>{`
        @keyframes dropdown-in {
          from { opacity: 0; transform: translateY(-4px); }
          to   { opacity: 1; transform: translateY(0); }
        }
      `}</style>
    </div>
  );
}

function Select({ value, onChange, options = [], placeholder, size = "md", full }) {
  const isControlled = typeof onChange === "function";
  return (
    <label style={{ position: "relative", display: full ? "block" : "inline-block" }}>
      <select
        {...(isControlled ? { value: value ?? "", onChange } : { defaultValue: value ?? "" })}
        style={{
          appearance: "none",
          height: { sm: 32, md: 40, lg: 48 }[size],
          padding: "0 38px 0 14px",
          borderRadius: "var(--r-md)",
          border: "1px solid var(--line-strong)",
          background: "var(--white)",
          fontSize: 15,
          fontFamily: "inherit",
          color: value ? "var(--ink)" : "var(--ink-2)",
          minWidth: 160,
          width: full ? "100%" : undefined,
          cursor: "pointer",
        }}>
        {placeholder && <option value="">{placeholder}</option>}
        {options.map((o, i) => {
          const v = typeof o === "string" ? o : o.value;
          const l = typeof o === "string" ? o : o.label;
          return <option key={i} value={v}>{l}</option>;
        })}
      </select>
      <span style={{ position: "absolute", right: 12, top: "50%", transform: "translateY(-50%)", color: "var(--ink-2)", pointerEvents: "none" }}>
        <Icon name="chevdown" size={16} />
      </span>
    </label>
  );
}

/* ─────────────────────────────────────────────────────────────────
   Chip — pill toggle. active = teal fill.
───────────────────────────────────────────────────────────────── */
function Chip({ children, active, onClick, icon, removable, onRemove, style }) {
  return (
    <button onClick={onClick}
      style={{
        display: "inline-flex", alignItems: "center", gap: 6,
        height: 32, padding: "0 12px",
        borderRadius: "var(--r-pill)",
        fontSize: 13, fontWeight: 500, lineHeight: 1, fontFamily: "inherit",
        background: active ? "var(--teal)" : "var(--white)",
        color:      active ? "#fff"        : "var(--ink)",
        border: `1px solid ${active ? "var(--teal)" : "var(--line-strong)"}`,
        cursor: "pointer",
        ...style,
      }}>
      {icon && <Icon name={icon} size={14} />}
      {children}
      {removable && (
        <span onClick={(e)=>{e.stopPropagation(); onRemove&&onRemove();}}
          style={{display:"inline-flex", marginLeft: 4, opacity: 0.8}}>
          <Icon name="close" size={12} />
        </span>
      )}
    </button>
  );
}

/* ─────────────────────────────────────────────────────────────────
   Badge — small label with tone.  tone: "neutral" | "pos" | "warn" |
   "info" | "brand" | category names (it/design/media/eng).
───────────────────────────────────────────────────────────────── */
const BADGE_TONES = {
  neutral:{ bg: "var(--status-neutral-light)", fg: "var(--ink)" },
  pos:    { bg: "var(--status-pos-light)",     fg: "#3F6014" },
  warn:   { bg: "var(--status-warn-light)",    fg: "var(--amber-dark)" },
  brand:  { bg: "var(--teal-light)",           fg: "var(--teal-deep)" },
  it:     { bg: "var(--blue-light)",           fg: "var(--blue-dark)" },
  design: { bg: "var(--pink-light)",           fg: "var(--pink-dark)" },
  media:  { bg: "var(--purple-light)",         fg: "var(--purple-dark)" },
  eng:    { bg: "var(--amber-light)",          fg: "var(--amber-dark)" },
};
function Badge({ children, tone = "neutral", icon, style }) {
  const t = BADGE_TONES[tone] || BADGE_TONES.neutral;
  return (
    <span style={{
      display: "inline-flex", alignItems: "center", gap: 4,
      padding: "3px 8px",
      background: t.bg, color: t.fg,
      borderRadius: 6,
      fontSize: 12, fontWeight: 500, lineHeight: 1.3,
      whiteSpace: "nowrap",
      ...style,
    }}>
      {icon && <Icon name={icon} size={12} />}
      {children}
    </span>
  );
}

/* ─────────────────────────────────────────────────────────────────
   ChanceBadge — the signature element.
   level: "very-high" | "high" | "medium" | "low"
───────────────────────────────────────────────────────────────── */
const CHANCE_DEF = {
  "very-high": { label: "Очень высокий шанс",  pct: 90,
    bg: "var(--status-pos-light)",  fg: "#3F6014", bar: "#7BB527" },
  "high":      { label: "Высокий шанс",         pct: 75,
    bg: "var(--status-pos-light)",  fg: "#3F6014", bar: "#7BB527" },
  "medium":    { label: "Средний шанс",         pct: 50,
    bg: "var(--amber-light)",       fg: "var(--amber-dark)", bar: "#D9941F" },
  "low":       { label: "Низкий шанс",          pct: 25,
    bg: "var(--status-neutral-light)", fg: "#5C5C68", bar: "#9A9AA8" },
};
function ChanceBadge({ level = "high", compact = false }) {
  const c = CHANCE_DEF[level];
  if (compact) {
    return (
      <span style={{ display:"inline-flex", alignItems:"center", gap:6,
          background:c.bg, color:c.fg, padding:"4px 10px", borderRadius:"var(--r-pill)",
          fontSize:12, fontWeight:600, whiteSpace:"nowrap" }}>
        <span style={{width:6, height:6, borderRadius:999, background:c.bar}} />
        {c.label}
      </span>
    );
  }
  return (
    <div style={{
      background: c.bg, color: c.fg,
      borderRadius: "var(--r-md)",
      padding: "10px 12px",
      display: "flex", flexDirection: "column", gap: 6,
      minWidth: 160,
    }}>
      <div style={{display:"flex", justifyContent:"space-between", alignItems:"center",
          fontSize: 12, fontWeight: 600}}>
        <span>{c.label}</span>
        <span style={{fontFamily:"var(--font-mono)"}}>{c.pct}%</span>
      </div>
      <div style={{height:6, borderRadius: 999, background:"rgba(0,0,0,0.08)", overflow:"hidden"}}>
        <div style={{width:`${c.pct}%`, height:"100%", background:c.bar, borderRadius:999}}/>
      </div>
    </div>
  );
}

/* ─────────────────────────────────────────────────────────────────
   CategoryTile — placeholder for category illustration.
   Solid bg in category light tone + big letter (or icon) + counter.
───────────────────────────────────────────────────────────────── */
const CATEGORIES = {
  it:       { label: "IT и разработка",      hue: "it",     letter: "IT", icon: "bolt",       count: 320 },
  design:   { label: "Дизайн и творчество",  hue: "design", letter: "D",  icon: "spark",      count: 180 },
  media:    { label: "Медиа и блогинг",      hue: "media",  letter: "M",  icon: "spark",      count:  95 },
  med:      { label: "Медицина",             hue: "brand",  letter: "Мед", icon: "heart",     count: 240 },
  eng:      { label: "Инженерия и техника",  hue: "eng",    letter: "Инж", icon: "compass",   count: 410 },
  food:     { label: "Кухня и сервис",       hue: "warn",   letter: "Кух", icon: "star",      count: 165 },
  edu:      { label: "Педагогика",           hue: "brand",  letter: "Пед", icon: "graduation",count: 130 },
  law:      { label: "Право и экономика",    hue: "media",  letter: "Юэ", icon: "scales",    count: 140 },
  auto:     { label: "Авто и транспорт",     hue: "it",     letter: "Авт", icon: "compass",   count:  98 },
  beauty:   { label: "Красота",              hue: "design", letter: "Крас", icon: "spark",     count:  72 },
  sport:    { label: "Спорт",                hue: "pos",    letter: "Спорт", icon: "trophy",    count:  64 },
  agri:     { label: "Агро и сельское хозяйство", hue: "pos", letter: "Агро", icon: "star",  count: 110 },
};
function CategoryTile({ cat = "it", size = "md", showCount = true, onClick }) {
  const c = CATEGORIES[cat] || CATEGORIES.it;
  const tone = BADGE_TONES[c.hue];
  const dim = { sm: 88, md: 160, lg: 220 }[size];
  return (
    <button onClick={onClick}
      style={{
        display:"flex", flexDirection:"column", alignItems:"flex-start", justifyContent:"space-between",
        background:"var(--white)",
        border:"1px solid var(--line)", borderRadius:"var(--r-lg)",
        padding: dim < 100 ? 12 : 16, width: "100%",
        textAlign:"left", cursor:"pointer", fontFamily:"inherit",
        gap: 12, minHeight: dim,
      }}>
      <div style={{
          width: dim < 100 ? 36 : 56, height: dim < 100 ? 36 : 56,
          borderRadius: "var(--r-md)",
          background: tone.bg, color: tone.fg,
          display:"flex", alignItems:"center", justifyContent:"center",
        }}>
        <Icon name={c.icon} size={dim < 100 ? 18 : 28} />
      </div>
      <div>
        <div style={{ fontFamily:"var(--font-display)", fontWeight:600, fontSize:16, color:"var(--ink)",
            lineHeight: 1.25, marginBottom: 4 }}>{c.label}</div>
        {showCount && <div style={{ fontSize: 13, color: "var(--ink-2)" }}>{c.count} колледжей</div>}
      </div>
    </button>
  );
}

/* ─────────────────────────────────────────────────────────────────
   CategoryMark — large hero-style category illustration.
   Same shape as CategoryTile's icon but on the full hero scale.
───────────────────────────────────────────────────────────────── */
function CategoryMark({ cat = "it", size = 180, radius = 24 }) {
  const c = CATEGORIES[cat] || CATEGORIES.it;
  const tone = BADGE_TONES[c.hue];
  return (
    <div style={{
      width: size, height: size, borderRadius: radius,
      background: tone.bg, color: tone.fg, position: "relative",
      display: "flex", alignItems: "center", justifyContent: "center",
      overflow: "hidden", flexShrink: 0,
    }}>
      <div style={{ position: "absolute", inset: 0, opacity: 0.4,
        backgroundImage: `repeating-linear-gradient(135deg, transparent 0 18px, ${tone.fg}1F 18px 19px)` }} />
      <div style={{ position: "relative", display: "flex", flexDirection: "column",
        alignItems: "center", gap: size * 0.06 }}>
        <Icon name={c.icon} size={size * 0.30} />
        <span style={{
          fontFamily: "var(--font-display)", fontWeight: 700,
          fontSize: size * 0.18, letterSpacing: "-0.02em", lineHeight: 1,
        }}>{c.letter}</span>
      </div>
    </div>
  );
}

/* ─────────────────────────────────────────────────────────────────
   MetricCard — 4-up row inside college card / page hero
───────────────────────────────────────────────────────────────── */
function MetricCard({ label, value, unit, icon, tone = "neutral", style }) {
  return (
    <div style={{
      background: "var(--white)", border: "1px solid var(--line)",
      borderRadius: "var(--r-md)", padding: 12,
      display:"flex", flexDirection:"column", gap: 4,
      minWidth: 0, ...style,
    }}>
      <div style={{display:"flex", alignItems:"center", gap:6, color:"var(--ink-2)"}}>
        {icon && <Icon name={icon} size={14} />}
        <span style={{fontSize: 11, textTransform:"uppercase", letterSpacing:"0.06em",
            fontFamily:"var(--font-mono)"}}>{label}</span>
      </div>
      <div style={{ fontFamily:"var(--font-display)", fontWeight: 600, fontSize: 20,
          letterSpacing: "-0.01em", color: "var(--ink)" }}>
        {value}
        {unit && <span style={{ fontSize: 13, color:"var(--ink-2)", fontWeight:500, marginLeft: 4 }}>{unit}</span>}
      </div>
    </div>
  );
}

/* ─────────────────────────────────────────────────────────────────
   CollegeCard — main aggregator component.
   props:
     view: "grid" | "list"
     name, type, premium, photo, price, metrics, chance, badges,
     onCompare, compared, onFav, favorited
   Стили инжектятся один раз через ensureCollegeCardCSS().
───────────────────────────────────────────────────────────────── */
const __cc_state = { injected: false };
function ensureCollegeCardCSS() {
  if (__cc_state.injected || typeof document === "undefined") return;
  __cc_state.injected = true;
  const s = document.createElement("style");
  s.id = "cc-card-styles";
  s.textContent = `
    .cc {
      position: relative;
      background: var(--white);
      border: 1px solid var(--line);
      border-radius: 20px;
      overflow: hidden;
      display: flex; flex-direction: column;
      text-decoration: none; color: inherit;
      transition: transform .35s cubic-bezier(.2,.7,.2,1),
                  box-shadow .3s ease, border-color .25s ease;
      cursor: pointer;
    }
    .cc:hover {
      transform: translateY(-6px);
      box-shadow: 0 28px 56px -20px rgba(4,52,44,0.22), 0 6px 14px rgba(4,52,44,0.06);
      border-color: var(--teal);
    }
    .cc.cc-premium { border-color: var(--teal); box-shadow: 0 0 0 1px var(--teal); }
    .cc.cc-premium:hover { box-shadow: 0 0 0 1px var(--teal), 0 28px 56px -20px rgba(4,52,44,0.22); }

    /* PHOTO */
    .cc-photo {
      position: relative; overflow: hidden;
      background: var(--blue-light);
    }
    .cc-photo .stripes {
      position: absolute; inset: 0; opacity: 0.35;
      transition: transform .6s cubic-bezier(.2,.7,.2,1), opacity .3s;
    }
    .cc:hover .cc-photo .stripes { transform: scale(1.08); opacity: 0.45; }
    .cc-photo .ph-glyph {
      position: absolute; inset: 0;
      display: flex; align-items: center; justify-content: center;
      flex-direction: column; gap: 6px;
      transition: transform .5s cubic-bezier(.2,.7,.2,1);
    }
    .cc:hover .cc-photo .ph-glyph { transform: scale(1.06); }
    .cc-photo .ph-glyph .ico {
      font-family: var(--font-display); font-weight: 700;
      font-size: 56px; letter-spacing: -0.02em; line-height: 1;
      opacity: 0.85;
    }
    .cc-photo .ph-glyph .lbl {
      font-family: var(--font-mono); font-size: 10px;
      letter-spacing: 0.08em; text-transform: uppercase; opacity: 0.65;
    }
    .cc-photo .ph-overlay {
      position: absolute; inset: 0;
      background: linear-gradient(180deg, transparent 0%, transparent 50%, rgba(0,0,0,0.32) 100%);
      pointer-events: none;
      opacity: 0; transition: opacity .25s ease;
    }
    .cc:hover .cc-photo .ph-overlay { opacity: 1; }

    /* Photo badges */
    .cc-tag {
      position: absolute; z-index: 2;
      display: inline-flex; align-items: center; gap: 6px;
      font-size: 12px; font-weight: 600;
      padding: 6px 10px; border-radius: 999px;
      backdrop-filter: blur(8px);
      white-space: nowrap;
    }
    .cc-tag.tg-premium {
      top: 12px; left: 12px;
      background: var(--teal); color: #fff;
      font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.08em;
      text-transform: uppercase; font-weight: 700;
    }
    .cc-tag.tg-budget {
      bottom: 12px; left: 12px;
      background: rgba(255,255,255,0.95); color: var(--status-pos);
      box-shadow: 0 4px 12px rgba(0,0,0,0.08);
    }
    .cc-tag.tg-chance {
      bottom: 12px; left: 12px;
      background: rgba(255,255,255,0.95);
      box-shadow: 0 4px 12px rgba(0,0,0,0.08);
    }
    .cc-fav {
      position: absolute; top: 12px; right: 12px; z-index: 2;
      width: 36px; height: 36px; border-radius: 999px;
      border: 0; cursor: pointer;
      background: rgba(255,255,255,0.95); color: var(--ink-2);
      display: inline-flex; align-items: center; justify-content: center;
      backdrop-filter: blur(8px);
      box-shadow: 0 4px 12px rgba(0,0,0,0.08);
      transition: transform .2s ease, color .2s ease;
    }
    .cc-fav:hover { transform: scale(1.08); color: var(--pink-dark); }
    .cc-fav.on { color: var(--pink-dark); }

    /* BODY */
    .cc-body { display: flex; flex-direction: column; gap: 14px; padding: 20px; flex: 1; }
    /* В grid-виде прибиваем метрики, шанс и кнопки к низу — три карточки выравниваются */
    .cc-grid .cc-metrics { margin-top: auto; }
    .cc-badges { display: flex; gap: 6px; flex-wrap: wrap; }
    .cc-name {
      font-family: var(--font-display);
      font-size: 22px; line-height: 1.18;
      letter-spacing: -0.02em; font-weight: 600; color: var(--ink);
      margin: 0;
      transition: color .2s ease;
    }
    .cc:hover .cc-name { color: var(--teal-deep); }
    .cc-addr {
      display: flex; align-items: center; gap: 6px;
      color: var(--ink-2); font-size: 14px; line-height: 1.4;
    }
    .cc-addr .pin {
      color: var(--teal); flex-shrink: 0;
    }

    /* Metric strip */
    .cc-metrics {
      display: grid; grid-template-columns: repeat(4, 1fr);
      padding: 16px 0;
      border-top: 1px solid var(--line);
      border-bottom: 1px solid var(--line);
      gap: 8px;
    }
    .cc-metric { display: flex; flex-direction: column; align-items: center; gap: 2px; min-width: 0; }
    .cc-metric .lbl {
      font-family: var(--font-mono); font-size: 10px;
      letter-spacing: 0.06em; text-transform: uppercase;
      color: var(--ink-2); font-weight: 500;
    }
    .cc-metric .val {
      font-family: var(--font-display);
      font-weight: 700; font-size: 24px;
      letter-spacing: -0.025em; line-height: 1;
      color: var(--ink);
    }
    .cc-metric .val.pos { color: var(--status-pos); }
    .cc-metric .val.muted { color: var(--ink-3); font-weight: 600; }
    .cc-metric .val.small { font-size: 16px; }

    /* Footer actions */
    .cc-actions { display: flex; gap: 10px; }
    .cc-actions .btn-cmp {
      flex: 0 0 auto;
      height: 44px; min-width: 44px; padding: 0 14px;
      border: 1px solid var(--line-strong);
      border-radius: var(--r-md);
      background: var(--white); color: var(--ink-2);
      font-family: inherit; font-size: 13px; font-weight: 500;
      cursor: pointer;
      display: inline-flex; align-items: center; justify-content: center; gap: 6px;
      transition: all .2s ease;
    }
    .cc-actions .btn-cmp:hover { border-color: var(--teal); color: var(--teal-deep); }
    .cc-actions .btn-cmp.on {
      background: var(--teal-light); border-color: var(--teal);
      color: var(--teal-deep); font-weight: 600;
    }
    .cc-actions .btn-more {
      flex: 1;
      height: 44px; padding: 0 20px;
      border: 0; border-radius: var(--r-md);
      background: var(--ink); color: #fff;
      font-family: inherit; font-size: 15px; font-weight: 600;
      cursor: pointer;
      display: inline-flex; align-items: center; justify-content: center; gap: 8px;
      transition: background .2s ease, gap .2s ease;
    }
    .cc-actions .btn-more:hover { background: var(--teal-deep); gap: 12px; }
    .cc-actions .btn-more .arr {
      display: inline-flex; transition: transform .25s ease;
    }
    .cc:hover .cc-actions .btn-more { background: var(--teal-deep); }
    .cc:hover .cc-actions .btn-more .arr { transform: translateX(3px); }

    .cc-cmp-added {
      display: flex; align-items: center; gap: 6px;
      color: var(--status-pos); background: var(--status-pos-light);
      padding: 8px 12px; border-radius: var(--r-md);
      font-size: 13px; font-weight: 500;
    }

    /* GRID layout (default) */
    .cc-grid .cc-photo { height: 220px; }

    /* LIST layout */
    .cc-list {
      flex-direction: row;
      align-items: stretch;
    }
    .cc-list .cc-photo {
      width: 320px; flex-shrink: 0; min-height: 100%;
    }
    .cc-list .cc-body {
      padding: 24px 28px; gap: 16px; min-width: 0;
    }
    .cc-list .cc-head-row {
      display: grid; grid-template-columns: 1fr auto; gap: 24px; align-items: start;
    }
    .cc-list .cc-name { font-size: 24px; }
    .cc-list .cc-metrics { padding: 14px 0; }
    .cc-list .cc-actions { margin-top: auto; }
    .cc-list .price-block {
      text-align: right; min-width: 140px;
    }
    .cc-list .price-block .big {
      font-family: var(--font-display);
      font-weight: 700; font-size: 28px;
      letter-spacing: -0.02em; line-height: 1;
      color: var(--ink);
    }
    .cc-list .price-block .small { font-size: 13px; color: var(--ink-2); margin-top: 4px; }
    .cc-list .price-block.budget .big { color: var(--status-pos); }
    @media (max-width: 800px) {
      .cc-list { flex-direction: column; }
      .cc-list .cc-photo { width: 100%; height: 200px; }
      .cc-list .cc-head-row { grid-template-columns: 1fr; }
      .cc-list .price-block { text-align: left; }
    }
  `;
  document.head.appendChild(s);
}

function CollegeCard({
  name = "Колледж №1",
  city = "Москва",
  metro = "Чистые пруды",
  type = "Государственный",
  badges = [],
  price,
  hasBudget = true,
  programs = 4,
  budgetSeats = 25,
  avgScore = 4.2,
  dorm = true,
  chance = "high",
  premium = false,
  category = "it",
  view = "grid",       // "grid" | "list"
  href = "/college/sample/",
  photoSrc = null,     // реальное фото (если есть)
  onCompare,
  compared,
  onFav,
  favorited,
}) {
  React.useLayoutEffect(ensureCollegeCardCSS, []);

  const c = CATEGORIES[category] || CATEGORIES.it;
  const tone = BADGE_TONES[c.hue];
  const chanceDef = CHANCE_DEF[chance];

  const isList = view === "list";

  /* Card click → перейти на страницу колледжа, кроме случаев когда кликнули по интерактиву внутри */
  function handleCardClick(e) {
    const t = e.target.closest("button, a, [data-stop]");
    if (t && t !== e.currentTarget) return;
    window.location.href = href;
  }

  const photo = (
    <div className="cc-photo" style={{ background: tone.bg, color: tone.fg }}>
      {photoSrc ? (
        <img src={photoSrc} alt={`Фото ${name}`}
          style={{position:'absolute', inset:0, width:'100%', height:'100%', objectFit:'cover'}}
          onError={(e) => { e.target.style.display = 'none'; }} />
      ) : (
        <>
          <div className="stripes" style={{
            backgroundImage: `repeating-linear-gradient(135deg, transparent 0 14px, ${tone.fg}1F 14px 15px)`,
          }} />
          <div className="ph-glyph" style={{ color: tone.fg }}>
            <span className="ico">{c.letter}</span>
            <span className="lbl">фото колледжа</span>
          </div>
        </>
      )}
      <div className="ph-overlay" />
      {premium && <span className="cc-tag tg-premium">★ Реклама</span>}
      <button className={"cc-fav" + (favorited ? " on" : "")}
        data-stop onClick={(e) => { e.stopPropagation(); onFav && onFav(); }}
        title={favorited ? "Убрать из избранного" : "В избранное"}>
        <Icon name="heart" size={16} />
      </button>
      {!isList && (
        hasBudget ? (
          <span className="cc-tag tg-budget">
            <Icon name="check" size={12} /> Есть бюджет
          </span>
        ) : (
          <span className="cc-tag tg-budget" style={{ color: "var(--ink)" }}>
            <Icon name="rouble" size={12} /> от {price?.toLocaleString("ru")} ₽
          </span>
        )
      )}
    </div>
  );

  const metrics = (
    <div className="cc-metrics">
      <div className="cc-metric">
        <span className="lbl">Ср. балл</span>
        <span className="val">{avgScore.toFixed(1)}</span>
      </div>
      <div className="cc-metric">
        <span className="lbl">Бюджет</span>
        <span className={"val " + (budgetSeats > 0 ? "pos" : "muted")}>
          {budgetSeats > 0 ? budgetSeats : "—"}
        </span>
      </div>
      <div className="cc-metric">
        <span className="lbl">Программ</span>
        <span className="val">{programs}</span>
      </div>
      <div className="cc-metric">
        <span className="lbl">Общежитие</span>
        <span className={"val small " + (dorm ? "" : "muted")}>{dorm ? "Есть" : "Нет"}</span>
      </div>
    </div>
  );

  const actions = (
    <div className="cc-actions">
      <button className={"btn-cmp" + (compared ? " on" : "")}
        data-stop onClick={(e) => { e.stopPropagation(); onCompare && onCompare(); }}>
        <Icon name={compared ? "close" : "plus"} size={14} />
        {compared ? "Убрать" : "Сравнить"}
      </button>
      <a className="btn-more" href={href} data-stop>
        Подробнее
        <span className="arr"><Icon name="arrowR" size={16} /></span>
      </a>
    </div>
  );

  if (isList) {
    return (
      <article className={"cc cc-list" + (premium ? " cc-premium" : "")} onClick={handleCardClick}>
        {photo}
        <div className="cc-body">
          <div className="cc-head-row">
            <div style={{display:"flex", flexDirection:"column", gap: 8, minWidth: 0}}>
              <div className="cc-badges">
                <Badge tone="brand">{type}</Badge>
                {badges.slice(0, 2).map((b, i) => <Badge key={i} tone="neutral">{b}</Badge>)}
              </div>
              <h3 className="cc-name">{name}</h3>
              <div className="cc-addr">
                <span className="pin"><Icon name="pin" size={14} /></span>
                {city} · м. {metro}
              </div>
              <div data-stop><ChanceBadge level={chance} compact /></div>
            </div>
            <div className={"price-block" + (hasBudget ? " budget" : "")}>
              {hasBudget ? (
                <>
                  <div className="big">Бюджет</div>
                  <div className="small">{budgetSeats} мест · от 0 ₽</div>
                </>
              ) : (
                <>
                  <div className="big">от {(price/1000)?.toFixed(0)} <span style={{fontSize: 14, color:"var(--ink-2)", fontWeight: 500}}>тыс. ₽</span></div>
                  <div className="small">платное, год</div>
                </>
              )}
            </div>
          </div>
          {metrics}
          {compared && (
            <div className="cc-cmp-added">
              <Icon name="check" size={14} /> Добавлено в сравнение
            </div>
          )}
          {actions}
        </div>
      </article>
    );
  }

  /* GRID */
  return (
    <article className={"cc cc-grid" + (premium ? " cc-premium" : "")} onClick={handleCardClick}>
      {photo}
      <div className="cc-body">
        <div className="cc-badges">
          <Badge tone="brand">{type}</Badge>
          {badges.slice(0, 1).map((b, i) => <Badge key={i} tone="neutral">{b}</Badge>)}
        </div>
        <h3 className="cc-name">{name}</h3>
        <div className="cc-addr">
          <span className="pin"><Icon name="pin" size={14} /></span>
          {city} · м. {metro}
        </div>
        {metrics}
        <div data-stop><ChanceBadge level={chance} compact /></div>
        {compared && (
          <div className="cc-cmp-added">
            <Icon name="check" size={14} /> Добавлено в сравнение
          </div>
        )}
        {actions}
      </div>
    </article>
  );
}
/* ─────────────────────────────────────────────────────────────────
   Breadcrumbs
───────────────────────────────────────────────────────────────── */
function Breadcrumbs({ items = [] }) {
  return (
    <nav aria-label="breadcrumbs" style={{display:"flex", alignItems:"center", gap: 6,
        fontSize: 13, color: "var(--ink-2)", flexWrap:"wrap"}}>
      {items.map((it, i) => (
        <React.Fragment key={i}>
          {i > 0 && <Icon name="chevright" size={12} style={{opacity:.5}} />}
          {it.href && i !== items.length - 1
            ? <a href={it.href} style={{color:"var(--ink-2)"}}>{it.label}</a>
            : <span style={{color: i === items.length - 1 ? "var(--ink)" : undefined}}>{it.label}</span>}
        </React.Fragment>
      ))}
    </nav>
  );
}

/* ─────────────────────────────────────────────────────────────────
   TopBar / SiteHeader — shared by all 4 pages
───────────────────────────────────────────────────────────────── */
function SiteHeader({ active = "home" }) {
  const [compareCount, setCompareCount] = React.useState(0);
  const [favCount, setFavCount] = React.useState(0);
  const [mobileOpen, setMobileOpen] = React.useState(false);

  React.useEffect(() => {
    const update = () => {
      try {
        const cmp = JSON.parse(localStorage.getItem("ic_compared") || "[]");
        setCompareCount(Array.isArray(cmp) ? cmp.length : 0);
      } catch { setCompareCount(0); }
      try {
        const fav = JSON.parse(localStorage.getItem("ic_favorites") || "[]");
        setFavCount(Array.isArray(fav) ? fav.length : 0);
      } catch { setFavCount(0); }
    };
    update();
    window.addEventListener("storage", update);
    window.addEventListener("ic:compareChanged", update);
    window.addEventListener("ic:favoritesChanged", update);
    return () => {
      window.removeEventListener("storage", update);
      window.removeEventListener("ic:compareChanged", update);
      window.removeEventListener("ic:favoritesChanged", update);
    };
  }, []);

  React.useEffect(() => {
    if (mobileOpen) document.body.classList.add("nav-mobile-open");
    else document.body.classList.remove("nav-mobile-open");
  }, [mobileOpen]);

  const links = [
    { id: "catalog",   label: "Каталог",    href: "/catalog/" },
    { id: "prof",      label: "Профессии",  href: "/profession/" },
    { id: "programs",  label: "Программы",  href: "/programs/" },
    { id: "test",      label: "Тест",       href: "#" },
    { id: "compare",   label: "Сравнение",  href: "/compare/",   badge: compareCount },
    { id: "favorites", label: "Избранное",  href: "/favorites/", badge: favCount, heart: true },
    { id: "blog",      label: "Блог",       href: "/blog/" },
  ];
  return (
    <header className="site-header" style={{
      position:"sticky", top:0, zIndex: 10,
      background: "rgba(247, 248, 246, 0.92)",
      backdropFilter: "blur(12px)",
      borderBottom: "1px solid var(--line)",
    }}>
      <div className="site-header-row" style={{
        maxWidth: 1240, margin: "0 auto",
        display:"flex", alignItems:"center", justifyContent:"space-between",
        padding: "14px 24px", gap: 24,
      }}>
        <a href="/" className="site-logo" style={{display:"inline-flex", textDecoration:"none"}}>
          <LogoLockup size={32} dot="check" />
        </a>
        <nav className="site-nav" style={{display:"flex", gap: 4}}>
          {links.map(l => (
            <a key={l.id} href={l.href}
              style={{
                padding: "8px 12px", borderRadius: "var(--r-md)",
                fontSize: 14, fontWeight: 500, color: "var(--ink)",
                textDecoration:"none",
                display: "inline-flex", alignItems: "center", gap: 6,
                background: active === l.id ? "var(--teal-light)" : "transparent",
              }}>
              {l.heart && (
                <Icon name="heart" size={14} color={l.badge > 0 ? "var(--pink-dark)" : "currentColor"} />
              )}
              {l.label}
              {l.badge > 0 && (
                <span style={{
                  background: l.heart ? "var(--pink-dark)" : "var(--teal)", color: "#fff",
                  fontSize: 11, fontWeight: 700,
                  minWidth: 20, height: 20, padding: "0 6px",
                  borderRadius: 999, display: "inline-flex",
                  alignItems: "center", justifyContent: "center",
                  lineHeight: 1, fontFamily: "var(--font-mono)",
                }}>{l.badge}</span>
              )}
            </a>
          ))}
        </nav>
        <div className="site-header-right" style={{display:"flex", alignItems:"center", gap: 8}}>
          <button type="button" className="hdr-search-btn" id="hdr-search-btn" aria-label="Поиск по сайту" aria-expanded="false" title="Поиск (Ctrl/⌘+K)">
            <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><circle cx="11" cy="11" r="8"/><line x1="21" y1="21" x2="16.65" y2="16.65"/></svg>
          </button>
          <div className="site-city-btn"><Button variant="ghost" size="sm" iconLeft="pin">Москва</Button></div>
          <div className="site-cta-btn"><Button variant="primary" size="sm">Подобрать колледж</Button></div>
          <button
            type="button"
            className="site-burger"
            aria-label={mobileOpen ? "Закрыть меню" : "Открыть меню"}
            aria-expanded={mobileOpen ? "true" : "false"}
            onClick={() => setMobileOpen(o => !o)}>
            {mobileOpen
              ? <svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round"><line x1="6" y1="6" x2="18" y2="18"/><line x1="18" y1="6" x2="6" y2="18"/></svg>
              : <svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round"><line x1="4" y1="7"  x2="20" y2="7"/><line x1="4" y1="12" x2="20" y2="12"/><line x1="4" y1="17" x2="20" y2="17"/></svg>}
          </button>
        </div>
      </div>

      {/* мобильное меню */}
      <div className={"site-mobile-drawer" + (mobileOpen ? " is-open" : "")}>
        <nav className="site-mobile-nav">
          {links.map(l => (
            <a key={l.id} href={l.href} className="site-mobile-link"
               style={{ background: active === l.id ? "var(--teal-light)" : "transparent" }}>
              {l.heart && <Icon name="heart" size={16} color={l.badge > 0 ? "var(--pink-dark)" : "currentColor"} />}
              <span>{l.label}</span>
              {l.badge > 0 && (
                <span className="site-mobile-badge" style={{ background: l.heart ? "var(--pink-dark)" : "var(--teal)" }}>{l.badge}</span>
              )}
            </a>
          ))}
          <div className="site-mobile-cta">
            <Button variant="ghost" size="sm" iconLeft="pin">Москва</Button>
            <Button variant="primary" size="sm">Подобрать колледж</Button>
          </div>
        </nav>
      </div>

      <div className="hdr-search-overlay" id="hdr-search-overlay" hidden>
        <div className="hdr-search-box">
          <svg className="hdr-search-ico" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><circle cx="11" cy="11" r="8"/><line x1="21" y1="21" x2="16.65" y2="16.65"/></svg>
          <input type="search" id="hdr-search-input" placeholder="Найти колледж, профессию, код ОКСО или город" autoComplete="off" spellCheck="false" />
          <button type="button" className="hdr-search-close" id="hdr-search-close" aria-label="Закрыть поиск">×</button>
        </div>
        <div className="hdr-search-results" id="hdr-search-results" hidden></div>
      </div>
    </header>
  );
}

function SiteFooter() {
  return (
    <footer style={{ background: "var(--ink)", color: "rgba(255,255,255,0.85)", marginTop: 64 }}>
      <div style={{ maxWidth: 1240, margin: "0 auto", padding: "48px 24px",
          display:"grid", gridTemplateColumns:"repeat(4, 1fr)", gap: 32 }}>
        <div>
          <LogoLockup size={28} dot="check" variant="color" textColor="#fff" />
          <p style={{ fontSize: 13, color: "rgba(255,255,255,0.55)", marginTop: 12, maxWidth: 240 }}>
            Независимый агрегатор колледжей России. Данные из открытых источников.
          </p>
        </div>
        {[
          { t: "Профессии", l: ["IT и разработка","Дизайн","Медиа и блогинг","Медицина","Инженерия","Все профессии"] },
          { t: "Города",    l: ["Москва","Санкт-Петербург","Казань","Новосибирск","Все 85 регионов"] },
          { t: "О сервисе", l: ["Как мы считаем шанс","Источники данных","Реклама на портале","Контакты"] },
        ].map((col, i) => (
          <div key={i}>
            <h4 style={{fontSize: 13, fontFamily:"var(--font-mono)", letterSpacing: "0.06em",
                textTransform:"uppercase", color:"rgba(255,255,255,0.55)", marginBottom: 12}}>{col.t}</h4>
            <ul style={{listStyle:"none", padding: 0, margin: 0, display:"flex",
                flexDirection:"column", gap: 8, fontSize: 14}}>
              {col.l.map((x, j) => <li key={j}><a href="#" style={{color:"#fff", opacity:.85}}>{x}</a></li>)}
            </ul>
          </div>
        ))}
      </div>
      <div style={{ borderTop:"1px solid rgba(255,255,255,0.1)", padding: "16px 24px",
          textAlign:"center", fontSize: 12, color: "rgba(255,255,255,0.5)"}}>
        © 2026 iColleges · icolleges.ru
      </div>
    </footer>
  );
}

/* Expose */
Object.assign(window, {
  Icon, ICON_PATHS, Button, Input, Select, Dropdown, Chip, Badge, ChanceBadge,
  CategoryTile, CategoryMark, CATEGORIES, BADGE_TONES, MetricCard, CollegeCard,
  Breadcrumbs, SiteHeader, SiteFooter,
});
