// cal-shared.jsx — brand chrome (nav, footer, sticky CTA), icons, hooks

const { useState, useEffect, useRef, useMemo, useCallback, createContext, useContext } = React;

// ────────────────────────────────────────────────────────────
// Tiny icon set (lucide-flavored, hand-tuned SVGs)
// ────────────────────────────────────────────────────────────
const Icon = ({ name, size = 18, stroke = 1.75, className = "", style }) => {
  const paths = ICONS[name];
  if (!paths) return null;
  return (
    <svg
      width={size} height={size} viewBox="0 0 24 24"
      fill="none" stroke="currentColor" strokeWidth={stroke}
      strokeLinecap="round" strokeLinejoin="round"
      className={className} style={style} aria-hidden="true"
    >
      {paths}
    </svg>
  );
};

const ICONS = {
  check: <polyline points="4 12 10 18 20 6" />,
  "check-circle": <><circle cx="12" cy="12" r="9" /><polyline points="8 12 11 15 16 9" /></>,
  arrowRight: <><line x1="4" y1="12" x2="20" y2="12" /><polyline points="14 6 20 12 14 18" /></>,
  arrowLeft: <><line x1="20" y1="12" x2="4" y2="12" /><polyline points="10 6 4 12 10 18" /></>,
  chevronDown: <polyline points="6 9 12 15 18 9" />,
  chevronRight: <polyline points="9 6 15 12 9 18" />,
  shield: <><path d="M12 3l8 3v6c0 4.5-3.5 8.5-8 9-4.5-.5-8-4.5-8-9V6l8-3z" /><polyline points="9 12 11 14 15 10" /></>,
  lock: <><rect x="5" y="11" width="14" height="10" rx="2" /><path d="M8 11V7a4 4 0 0 1 8 0v4" /></>,
  spark: <><path d="M12 3v4M12 17v4M3 12h4M17 12h4M5.6 5.6l2.8 2.8M15.6 15.6l2.8 2.8M5.6 18.4l2.8-2.8M15.6 8.4l2.8-2.8" /></>,
  phone: <path d="M5 4h3l2 5-2 1c1 2 3 4 5 5l1-2 5 2v3c0 1-1 2-2 2C9 20 4 15 4 6c0-1 1-2 1-2z" />,
  mail: <><rect x="3" y="5" width="18" height="14" rx="2" /><polyline points="3 7 12 13 21 7" /></>,
  map: <><path d="M12 21s-7-7.5-7-13a7 7 0 0 1 14 0c0 5.5-7 13-7 13z" /><circle cx="12" cy="8" r="2.5" /></>,
  clock: <><circle cx="12" cy="12" r="9" /><polyline points="12 7 12 12 16 14" /></>,
  user: <><circle cx="12" cy="8" r="4" /><path d="M4 21c0-4 4-7 8-7s8 3 8 7" /></>,
  users: <><circle cx="9" cy="8" r="4" /><path d="M2 21c0-4 3-6 7-6s7 2 7 6" /><path d="M16 4a4 4 0 0 1 0 8" /><path d="M22 21c0-3-2-5-5-5.5" /></>,
  car: <><path d="M5 14l1.5-4.5A2 2 0 0 1 8.4 8h7.2a2 2 0 0 1 1.9 1.5L19 14" /><rect x="3" y="14" width="18" height="5" rx="1.5" /><circle cx="7" cy="19" r="1.5" /><circle cx="17" cy="19" r="1.5" /></>,
  truck: <><rect x="2" y="8" width="11" height="9" rx="1" /><path d="M13 11h4l3 3v3h-7" /><circle cx="7" cy="18" r="2" /><circle cx="17" cy="18" r="2" /></>,
  building: <><rect x="5" y="3" width="14" height="18" rx="1.5" /><path d="M9 7h.01M15 7h.01M9 11h.01M15 11h.01M9 15h.01M15 15h.01" /><path d="M10 21v-4h4v4" /></>,
  briefcase: <><rect x="3" y="7" width="18" height="13" rx="2" /><path d="M9 7V5a2 2 0 0 1 2-2h2a2 2 0 0 1 2 2v2" /><line x1="3" y1="13" x2="21" y2="13" /></>,
  cash: <><rect x="3" y="7" width="18" height="11" rx="2" /><circle cx="12" cy="12.5" r="2.5" /><path d="M6 10v5M18 10v5" /></>,
  trending: <><polyline points="3 17 9 11 13 15 21 7" /><polyline points="15 7 21 7 21 13" /></>,
  calc: <><rect x="5" y="3" width="14" height="18" rx="2" /><line x1="9" y1="7" x2="15" y2="7" /><path d="M9 12h.01M12 12h.01M15 12h.01M9 16h.01M12 16h.01M15 16h.01" /></>,
  edit: <><path d="M4 20l4-1 11-11-3-3-11 11-1 4z" /></>,
  help: <><circle cx="12" cy="12" r="9" /><path d="M9.5 9a2.5 2.5 0 1 1 3.5 2.3c-.7.3-1 .7-1 1.7" /><path d="M12 17h.01" /></>,
  info: <><circle cx="12" cy="12" r="9" /><line x1="12" y1="11" x2="12" y2="16" /><path d="M12 8h.01" /></>,
  search: <><circle cx="11" cy="11" r="7" /><line x1="16.5" y1="16.5" x2="21" y2="21" /></>,
  star: <polygon points="12 3 14.5 9 21 9.5 16 14 17.5 21 12 17.5 6.5 21 8 14 3 9.5 9.5 9" />,
  quote: <><path d="M6 7c-1.5 0-3 1.5-3 4v7h6v-7H6V7zM15 7c-1.5 0-3 1.5-3 4v7h6v-7h-3V7z" /></>,
  google: <><path d="M21 12.2c0-.6 0-1.2-.2-1.8H12v3.4h5.1c-.2 1.2-.9 2.2-1.9 2.9v2.4h3.1c1.8-1.7 2.7-4.1 2.7-6.9z" fill="#4285F4" stroke="none" /><path d="M12 21c2.6 0 4.7-.8 6.3-2.3l-3.1-2.4c-.9.6-2 .9-3.2.9-2.5 0-4.6-1.7-5.3-3.9H3.5v2.4C5.1 18.7 8.3 21 12 21z" fill="#34A853" stroke="none" /><path d="M6.7 13.2c-.2-.6-.3-1.2-.3-1.9s.1-1.3.3-1.9V7H3.5C2.8 8.3 2.4 9.7 2.4 11.3c0 1.6.4 3 1.1 4.3l3.2-2.4z" fill="#FBBC05" stroke="none" /><path d="M12 5.7c1.4 0 2.7.5 3.7 1.4l2.8-2.8C16.7 2.7 14.6 1.9 12 1.9c-3.7 0-6.9 2.3-8.5 5.4l3.2 2.4C7.4 7.4 9.5 5.7 12 5.7z" fill="#EA4335" stroke="none" /></>,
  menu: <><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" /></>,
  x: <><line x1="6" y1="6" x2="18" y2="18" /><line x1="6" y1="18" x2="18" y2="6" /></>,
  zap: <polygon points="13 2 4 14 12 14 11 22 20 10 12 10 13 2" />,
  sliders: <><line x1="4" y1="6" x2="11" y2="6" /><line x1="15" y1="6" x2="20" y2="6" /><circle cx="13" cy="6" r="2" /><line x1="4" y1="12" x2="9" y2="12" /><line x1="13" y1="12" x2="20" y2="12" /><circle cx="11" cy="12" r="2" /><line x1="4" y1="18" x2="15" y2="18" /><line x1="19" y1="18" x2="20" y2="18" /><circle cx="17" cy="18" r="2" /></>,
  download: <><path d="M12 4v11" /><polyline points="7 11 12 16 17 11" /><path d="M5 20h14" /></>,
  external: <><path d="M14 4h6v6" /><line x1="20" y1="4" x2="11" y2="13" /><path d="M18 14v5a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1V7a1 1 0 0 1 1-1h5" /></>,
  fileText: <><path d="M14 3H7a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V8z" /><polyline points="14 3 14 8 19 8" /><line x1="8" y1="13" x2="16" y2="13" /><line x1="8" y1="17" x2="13" y2="17" /></>,
  link: <><path d="M10 13a5 5 0 0 0 7 0l3-3a5 5 0 0 0-7-7l-1.5 1.5" /><path d="M14 11a5 5 0 0 0-7 0l-3 3a5 5 0 0 0 7 7l1.5-1.5" /></>,
};

// ────────────────────────────────────────────────────────────
// Tiny hash-based router
// ────────────────────────────────────────────────────────────
const RouteCtx = createContext({ path: "/", go: () => {} });

function getHashLocation() {
  const h = window.location.hash || "#/";
  const raw = h.replace(/^#/, "") || "/";
  // Split path and inner anchor (hash-router URL shape: #/path#section)
  const idx = raw.indexOf("#");
  if (idx === -1) return { path: raw, anchor: "" };
  return { path: raw.slice(0, idx) || "/", anchor: raw.slice(idx + 1) };
}

function scrollToAnchor(anchor) {
  if (!anchor) {
    window.scrollTo({ top: 0, behavior: "instant" });
    return;
  }
  // The target element may not exist yet if the destination page hasn't
  // mounted. Retry on rAF until we find it (or give up after ~500ms).
  let attempts = 0;
  const tick = () => {
    const el = document.getElementById(anchor);
    if (el) {
      el.scrollIntoView({ behavior: "smooth", block: "start" });
      return;
    }
    if (++attempts < 30) requestAnimationFrame(tick);
  };
  requestAnimationFrame(tick);
}

function RouterRoot({ children }) {
  const initial = getHashLocation();
  const [path, setPath] = useState(initial.path);
  const [anchor, setAnchor] = useState(initial.anchor);
  useEffect(() => {
    const onChange = () => {
      const next = getHashLocation();
      setPath(next.path);
      setAnchor(next.anchor);
      scrollToAnchor(next.anchor);
    };
    window.addEventListener("hashchange", onChange);
    // Initial mount: honour an anchor if the page was loaded with one
    if (initial.anchor) scrollToAnchor(initial.anchor);
    return () => window.removeEventListener("hashchange", onChange);
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);
  const go = useCallback((to) => {
    if (to.startsWith("#")) to = to.slice(1);
    window.location.hash = "#" + to;
  }, []);
  return <RouteCtx.Provider value={{ path, anchor, go }}>{children}</RouteCtx.Provider>;
}

function useRoute() { return useContext(RouteCtx); }

function Link({ to, className = "", children, onClick, ...rest }) {
  const { go } = useRoute();
  return (
    <a
      href={`#${to}`} className={className}
      onClick={(e) => { e.preventDefault(); onClick && onClick(e); go(to); }}
      {...rest}
    >
      {children}
    </a>
  );
}

// ────────────────────────────────────────────────────────────
// Brand mark — CAL wordmark with custom mark
// ────────────────────────────────────────────────────────────
function BrandMark({ size = "md", inverse = false, showDomain = false }) {
  const h = size === "lg" ? 64 : size === "sm" ? 36 : 52;
  return (
    <div className="brand" style={{ color: inverse ? "var(--text-inverse)" : "var(--text)" }}>
      <img
        src={(typeof window !== 'undefined' && window.__resources && window.__resources.calLogo) || "assets/cal-logo.png"}
        alt="Canadian Auto Loan"
        className="brand-logo"
        style={{ height: h, width: "auto", display: "block" }}
      />
      {showDomain && (
        <div className="brand-domain">CanadianAuto.Loans</div>
      )}
    </div>
  );
}

// ────────────────────────────────────────────────────────────
// Nav
// ────────────────────────────────────────────────────────────
function Nav({ trustPlacement = "section" }) {
  const { path } = useRoute();
  const [open, setOpen] = useState(false);
  const isActive = (p) => path === p || (p !== "/" && path.startsWith(p));
  return (
    <header className="nav">
      <div className="container nav-inner">
        <Link to="/" aria-label="Canadian Auto Loans home">
          <BrandMark />
        </Link>
        <nav className="nav-links" aria-label="Primary">
          <Link to="/" className={isActive("/") && path === "/" ? "active" : ""}>Home</Link>
          <Link to="/financing" className={isActive("/financing") ? "active" : ""}>How it works</Link>
          <Link to="/about" className={isActive("/about") ? "active" : ""}>About &amp; contact</Link>
        </nav>
        <div className="nav-cta">
          <div className="nav-phone">
            <Icon name="phone" size={14} style={{display:"inline",verticalAlign:"-2px",marginRight:6}} />
            <b>(613) 700-8641</b>
          </div>
          <Link to="/apply" className="btn btn-primary">Start application</Link>
          <button
            className="btn btn-ghost btn-sm"
            style={{ display: "none" }}
            id="menu-btn"
            onClick={() => setOpen(true)}
            aria-label="Open menu"
          >
            <Icon name="menu" size={20} />
          </button>
        </div>
      </div>
      <style>{`
        @media (max-width: 880px) {
          #menu-btn { display: inline-flex !important; }
          .nav-cta .btn-primary { display: none; }
        }
      `}</style>
      {open && (
        <div className="mobile-menu" onClick={() => setOpen(false)}>
          <div className="mobile-menu-inner" onClick={(e) => e.stopPropagation()}>
            <div style={{display:"flex",justifyContent:"space-between",alignItems:"center",marginBottom:24}}>
              <BrandMark />
              <button className="btn btn-ghost btn-sm" onClick={() => setOpen(false)}><Icon name="x" /></button>
            </div>
            <nav style={{display:"flex",flexDirection:"column",gap:4}}>
              <Link to="/" onClick={() => setOpen(false)} className="mobile-link">Home</Link>
              <Link to="/financing" onClick={() => setOpen(false)} className="mobile-link">How it works</Link>
              <Link to="/about" onClick={() => setOpen(false)} className="mobile-link">About &amp; contact</Link>
            </nav>
            <hr className="hairline" style={{margin:"20px 0"}} />
            <Link to="/apply" onClick={() => setOpen(false)} className="btn btn-primary btn-lg btn-block">Start application</Link>
            <div className="mt-6 small">
              <div style={{display:"flex",gap:8,alignItems:"center",marginBottom:6}}><Icon name="phone" size={14}/><b>(613) 700-8641</b></div>
              <div style={{display:"flex",gap:8,alignItems:"center"}}><Icon name="clock" size={14}/>Mon–Fri, 10 AM – 5 PM</div>
            </div>
          </div>
          <style>{`
            .mobile-menu { position: fixed; inset: 0; z-index: 100; background: rgba(20,15,55,.4); animation: fadeUp .2s ease both; }
            .mobile-menu-inner { background: var(--surface); height: 100vh; width: min(360px, 90vw); padding: 24px; display: flex; flex-direction: column; }
            .mobile-link { padding: 14px 12px; border-radius: 10px; font-size: 17px; font-weight: 500; }
            .mobile-link:hover { background: var(--surface-muted); }
          `}</style>
        </div>
      )}
    </header>
  );
}

// ────────────────────────────────────────────────────────────
// Footer (with mandatory dealer-status line)
// ────────────────────────────────────────────────────────────
function Footer() {
  return (
    <footer className="footer">
      <div className="container">
        <div className="footer-cols">
          <div>
            <BrandMark size="lg" showDomain={true} />
            <p className="mt-4 muted" style={{maxWidth: 320, fontSize: 14.5, lineHeight: 1.55}}>
              A Canadian auto dealership helping drivers in Ontario and Quebec get into a vehicle, with financing arranged through our lender partners.
            </p>
            <div className="mt-4" style={{display:"flex",gap:10,flexWrap:"wrap"}}>
              <a className="gchip" href="#" aria-label="Read our Google reviews">
                <Icon name="google" size={14} stroke={0} />
                <StarRating value={4.1} />
                <b>4.1</b> <span className="soft">· 214 reviews</span>
              </a>
            </div>
          </div>
          <div>
            <h5>Get a loan</h5>
            <ul>
              <li><Link to="/apply">Start application</Link></li>
              <li><Link to="/financing">How it works</Link></li>
              <li><Link to="/financing#calculator">Payment estimator</Link></li>
              <li><Link to="/financing#what-youll-need">What you'll need</Link></li>
            </ul>
          </div>
          <div>
            <h5>Company</h5>
            <ul>
              <li><Link to="/about">About us</Link></li>
              <li><Link to="/about#team">Our team</Link></li>
              <li><Link to="/about#contact">Contact &amp; hours</Link></li>
            </ul>
          </div>
          <div>
            <h5>Legal</h5>
            <ul>
              <li><Link to="/privacy">Privacy policy</Link></li>
              <li><Link to="/credit-consent">Credit check consent</Link></li>
            </ul>
          </div>
        </div>

        <div className="footer-bottom">
          <p className="broker-line">
            <b>Canadian Auto Loan is an Ontario-based auto dealership</b> serving Ontario and Quebec. We sell vehicles and arrange financing on your behalf with our network of Canadian lenders. We are not a lender.
          </p>
          <div className="soft">© 2026 Canadian Auto Loan. All rights reserved.</div>
        </div>
      </div>
    </footer>
  );
}

// ────────────────────────────────────────────────────────────
// Sticky mobile CTA
// ────────────────────────────────────────────────────────────
function StickyMobileCTA({ enabled, hideOnApply }) {
  const { path, go } = useRoute();
  if (!enabled) return null;
  if (hideOnApply && path.startsWith("/apply")) return null;
  return (
    <div className="sticky-cta enabled">
      <div className="sticky-cta-meta">
        <b>Free 3-minute application</b>
        Soft credit check · won't affect your score
      </div>
      <button className="btn btn-primary" onClick={() => go("/apply")}>
        Apply now
        <Icon name="arrowRight" size={16} />
      </button>
    </div>
  );
}

// ────────────────────────────────────────────────────────────
// Shared: testimonials data (real reviews per brief)
// ────────────────────────────────────────────────────────────
// IMPORTANT (legal/marketing): These names are real Google reviewers but the
// `text` and `short` fields are paraphrases. Replace BOTH fields verbatim with
// the actual Google review text before launch — Competition Act misleading-
// advertising risk if quotes attributed to named individuals aren't accurate.
const TESTIMONIALS = [
  {
    name: "Alexander G.",
    role: "Ottawa, ON",
    stars: 5,
    text: "Elizabeth was patient with all my questions about my credit. They got me approved when two banks turned me down. The car was delivered to my door three days later — no dealership pressure, no surprises.",
    short: "Approved when two banks said no. Delivered to my door three days later.",
    initials: "AG",
    tint: 0,
  },
  {
    name: "Rylin F.",
    role: "Gatineau, QC",
    stars: 5,
    text: "I was nervous about applying because of a bankruptcy on my record. The team was upfront about what was possible and what wasn't. Got a reasonable rate and a clean SUV.",
    short: "Honest about my bankruptcy. Still got me a fair rate.",
    initials: "RF",
    tint: 1,
  },
  {
    name: "Jacob Genereux",
    role: "Kingston, ON",
    stars: 5,
    text: "Mark walked me through everything before delivery. First-time buyer, no co-signer. They explained the financing setup clearly so I knew exactly how it worked.",
    short: "First-time buyer, no co-signer. They made the financing make sense.",
    initials: "JG",
    tint: 2,
  },
  {
    name: "Dee Marie",
    role: "Cornwall, ON",
    stars: 5,
    text: "Honest people. Nick made sure the vehicle matched what we discussed. I'd send my sister here.",
    short: "Honest people. The vehicle matched what we discussed.",
    initials: "DM",
    tint: 0,
  },
  {
    name: "Heather Brown",
    role: "Brockville, ON",
    stars: 5,
    text: "After being declined twice elsewhere, I almost didn't apply. So glad I did. They found a lender who looked at my full picture, not just a number.",
    short: "Declined twice elsewhere. CAL looked at the whole picture, not just a number.",
    initials: "HB",
    tint: 1,
  },
];

const TINT_BG = [
  "linear-gradient(135deg, oklch(0.88 0.09 25), oklch(0.8 0.12 30))",
  "linear-gradient(135deg, oklch(0.94 0.05 80), oklch(0.9 0.07 50))",
  "linear-gradient(135deg, oklch(0.93 0.05 155), oklch(0.88 0.07 175))",
];

function ReviewCard({ t, compact }) {
  return (
    <div className="card card-pad" style={{ height: "100%", display: "flex", flexDirection: "column", gap: 14 }}>
      <div style={{display:"flex",justifyContent:"space-between",alignItems:"center"}}>
        <div style={{display:"flex",gap:10,alignItems:"center"}}>
          <div style={{
            width: 38, height: 38, borderRadius: "50%",
            background: TINT_BG[t.tint],
            color: "white", fontWeight: 600, fontSize: 13,
            display: "grid", placeItems: "center",
            letterSpacing: "-0.01em",
          }}>{t.initials}</div>
          <div style={{lineHeight:1.2}}>
            <div style={{fontWeight:600, fontSize: 14.5}}>{t.name}</div>
            <div className="small">{t.role}</div>
          </div>
        </div>
        <Icon name="google" size={18} stroke={0} />
      </div>
      <div style={{color: "oklch(0.7 0.16 75)", fontSize: 14, letterSpacing: 1.5}}>★★★★★</div>
      <p style={{margin:0, fontSize: compact ? 14.5 : 15.5, lineHeight: 1.55, color: "var(--text)"}}>
        "{t.text}"
      </p>
    </div>
  );
}

// ────────────────────────────────────────────────────────────
// Shared mini components: bullet, stat, etc.
// ────────────────────────────────────────────────────────────
function CheckBullet({ children, dim }) {
  return (
    <li style={{display:"flex",gap:12,alignItems:"flex-start",padding:"6px 0", color: dim ? "var(--text-muted)" : "var(--text)"}}>
      <span style={{
        width: 22, height: 22, borderRadius: "50%",
        background: "var(--primary-tint)", color: "var(--primary)",
        display: "grid", placeItems: "center", flex: "0 0 22px",
        marginTop: 1,
      }}>
        <Icon name="check" size={13} stroke={2.5} />
      </span>
      <span style={{lineHeight: 1.5}}>{children}</span>
    </li>
  );
}

function Stat({ value, label, sub }) {
  return (
    <div>
      <div className="tnum" style={{fontSize: 36, fontWeight: 700, letterSpacing: "-0.02em", lineHeight: 1}}>
        {value}
      </div>
      <div className="mt-2 small" style={{lineHeight:1.4}}>
        {label}{sub && <span className="soft"> · {sub}</span>}
      </div>
    </div>
  );
}

function StarRating({ value, max = 5, size = 13 }) {
  const rounded = Math.round(value);
  return (
    <span
      className="stars"
      style={{ color: "oklch(0.7 0.16 75)", letterSpacing: 1, fontSize: size, whiteSpace: "nowrap" }}
      aria-label={`${value} out of ${max} stars`}
    >
      {Array.from({ length: max }, (_, i) => (
        <span key={i} style={{ opacity: i < rounded ? 1 : 0.25 }}>★</span>
      ))}
    </span>
  );
}

// ────────────────────────────────────────────────────────────
// Custom Select — listbox pattern. Replaces native <select>.
// Options: [{value, label, hint?}] or strings.
// Keyboard: Enter/Space to open, ↑↓ to navigate, Enter to select, Esc to close.
// ────────────────────────────────────────────────────────────
function CalSelect({ value, onChange, options, placeholder = "Select…", className = "" }) {
  const [open, setOpen] = useState(false);
  const [activeIdx, setActiveIdx] = useState(-1);
  const [drop, setDrop] = useState("down");
  const btnRef = useRef(null);
  const listRef = useRef(null);
  const rootRef = useRef(null);

  const opts = (options || []).map(o => typeof o === "string" ? { value: o, label: o } : o);
  const current = opts.find(o => o.value === value);

  // Close on outside click
  useEffect(() => {
    if (!open) return;
    const onDoc = (e) => {
      if (rootRef.current && !rootRef.current.contains(e.target)) setOpen(false);
    };
    document.addEventListener("mousedown", onDoc);
    return () => document.removeEventListener("mousedown", onDoc);
  }, [open]);

  // Set active index on open to current selection; pick direction.
  useEffect(() => {
    if (open) {
      const idx = opts.findIndex(o => o.value === value);
      setActiveIdx(idx >= 0 ? idx : 0);
      // Cap list height matches CSS max-height: 280px
      const POP_H = Math.min(280, 60 + opts.length * 44);
      const r = btnRef.current?.getBoundingClientRect();
      if (r) {
        const spaceBelow = window.innerHeight - r.bottom;
        const spaceAbove = r.top;
        setDrop(spaceBelow < POP_H && spaceAbove > spaceBelow ? "up" : "down");
      }
    }
  }, [open]);

  const onKeyDown = (e) => {
    if (!open) {
      if (e.key === "Enter" || e.key === " " || e.key === "ArrowDown") {
        e.preventDefault();
        setOpen(true);
      }
      return;
    }
    if (e.key === "Escape") { e.preventDefault(); setOpen(false); btnRef.current?.focus(); }
    else if (e.key === "ArrowDown") { e.preventDefault(); setActiveIdx(i => Math.min(opts.length - 1, i + 1)); }
    else if (e.key === "ArrowUp") { e.preventDefault(); setActiveIdx(i => Math.max(0, i - 1)); }
    else if (e.key === "Home") { e.preventDefault(); setActiveIdx(0); }
    else if (e.key === "End") { e.preventDefault(); setActiveIdx(opts.length - 1); }
    else if (e.key === "Enter") {
      e.preventDefault();
      if (activeIdx >= 0) { onChange(opts[activeIdx].value); setOpen(false); btnRef.current?.focus(); }
    }
  };

  return (
    <div ref={rootRef} className={`cal-select ${className}`} data-open={open || undefined} data-drop={drop}>
      <button
        ref={btnRef}
        type="button"
        className="cal-select-trigger"
        aria-haspopup="listbox"
        aria-expanded={open}
        onClick={() => setOpen(o => !o)}
        onKeyDown={onKeyDown}
      >
        <span className={`cal-select-value ${current ? "" : "is-placeholder"}`}>
          {current ? current.label : placeholder}
        </span>
        <Icon name="chevronDown" size={16} className="cal-select-chevron" />
      </button>
      {open && (
        <ul
          ref={listRef}
          className="cal-select-list anim-fadeup"
          role="listbox"
          tabIndex={-1}
          onKeyDown={onKeyDown}
        >
          {opts.map((o, i) => (
            <li
              key={o.value}
              className="cal-select-option"
              role="option"
              aria-selected={o.value === value}
              data-active={i === activeIdx || undefined}
              data-selected={o.value === value || undefined}
              onMouseEnter={() => setActiveIdx(i)}
              onClick={() => { onChange(o.value); setOpen(false); btnRef.current?.focus(); }}
            >
              <span className="cal-select-option-label">{o.label}</span>
              {o.hint && <span className="cal-select-option-hint tnum">{o.hint}</span>}
              {o.value === value && <Icon name="check" size={15} stroke={2.5} style={{color:"var(--primary)",flex:"0 0 15px"}}/>}
            </li>
          ))}
        </ul>
      )}
    </div>
  );
}

// ────────────────────────────────────────────────────────────
// Export to global
// ────────────────────────────────────────────────────────────
Object.assign(window, {
  Icon, RouterRoot, useRoute, Link, BrandMark, Nav, Footer, StickyMobileCTA,
  TESTIMONIALS, TINT_BG, ReviewCard, CheckBullet, Stat, StarRating, CalSelect,
});
