// scanqr.jsx — The QR Generation experience for Herely.
// Updated to show the Home Page style cards for investor demo.

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

const HARDCODED_CODES = ["HERELY", "G7K29X", "L4B12P"];

const Arrow = () => (
  <svg className="arrow" viewBox="0 0 14 14" fill="none">
    <path d="M2 7h10M8 3l4 4-4 4" stroke="currentColor" strokeWidth="1.4" strokeLinecap="round" strokeLinejoin="round" />
  </svg>
);

const QRIcon = ({ size = 18 }) => (
  <svg viewBox="0 0 24 24" width={size} height={size} fill="none">
    <rect x="3" y="3" width="7" height="7" rx="1.5" stroke="currentColor" strokeWidth="1.4" />
    <rect x="14" y="3" width="7" height="7" rx="1.5" stroke="currentColor" strokeWidth="1.4" />
    <rect x="3" y="14" width="7" height="7" rx="1.5" stroke="currentColor" strokeWidth="1.4" />
    <rect x="6" y="6" width="1.5" height="1.5" fill="currentColor" />
    <rect x="17" y="6" width="1.5" height="1.5" fill="currentColor" />
    <rect x="6" y="17" width="1.5" height="1.5" fill="currentColor" />
    <path d="M14 14h3M14 18h2M19 14v3M14 21h7M17 17h4" stroke="currentColor" strokeWidth="1.4" strokeLinecap="round" />
  </svg>
);

const KeyIcon = ({ size = 18 }) => (
  <svg viewBox="0 0 24 24" width={size} height={size} fill="none">
    <circle cx="8" cy="14" r="4" stroke="currentColor" strokeWidth="1.4" />
    <path d="M11 12l9-9M16 8l3 3M19 5l2 2" stroke="currentColor" strokeWidth="1.4" strokeLinecap="round" />
  </svg>
);

const CheckIcon = ({ size = 14 }) => (
  <svg viewBox="0 0 16 16" width={size} height={size} fill="none">
    <path d="M3 8.5l3.5 3.5L13 5" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round" />
  </svg>
);

const CloseIcon = () => (
  <svg viewBox="0 0 16 16" width="13" height="13" fill="none">
    <path d="M3 3l10 10M13 3L3 13" stroke="currentColor" strokeWidth="1.4" strokeLinecap="round" />
  </svg>
);

const HomeIcon = () => (
  <svg viewBox="0 0 16 16" width="13" height="13" fill="none">
    <path d="M3 7l5-4.5L13 7v6.5H9.5V10H6.5v3.5H3V7z" stroke="currentColor" strokeWidth="1.3" strokeLinecap="round" strokeLinejoin="round"/>
  </svg>
);

function Greeting({ userName, mood, time, onNavigate }) {
  const hr = time.getHours();
  const greet = hr < 5 ? "Still up" : hr < 12 ? "Good morning" : hr < 18 ? "Good afternoon" : "Good evening";
  const timeStr = time.toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" });
  const moodItem = (window.MOODS && window.MOODS.find((item) => item.key === mood)) || { label: "Lit 🔥" };
  const moodCol = window.moodColor ? window.moodColor(mood) : "#3A7FCC";
  
  return (
    <header className="greet rv">
      <div className="row1" style={{display: "flex", alignItems: "center", gap: "16px"}}>
        <a href="/home" onClick={(e) => { e.preventDefault(); if(onNavigate) onNavigate("/home"); }} className="btn-nav-home" style={{marginBottom: 0}}>
          <HomeIcon /> Home
        </a>
        <span className="eyebrow" style={{marginBottom: 0}}>{timeStr}</span>
        <span className="pill-state" style={{ display: "inline-flex", alignItems: "center", gap: 8 }}>
          <span style={{ width: 7, height: 7, borderRadius: "50%", background: moodCol, boxShadow: "0 0 0 3px " + moodCol + "33" }}></span>
          You · {moodItem.label.toLowerCase()}
        </span>
      </div>
      <h1>
        {greet}, <span className="ed">{userName}.</span>
      </h1>
      <p className="lede">
        The room is quietly waiting. Scan a code, type one in, or step into something you've been in before.
      </p>
    </header>
  );
}

function QRPreview() {
  return (
    <div className="qr-preview" aria-hidden style={{ padding: 0, overflow: "hidden", background: "#fff" }}>
      <img 
        src="https://api.qrserver.com/v1/create-qr-code/?size=82x82&data=https://www.herely.ai/join/studio-1&color=0B0B0D&bgcolor=FFFFFF" 
        alt="QR Code"
        style={{ width: "100%", height: "100%", objectFit: "cover" }}
      />
    </div>
  );
}


function ScanCard({ onOpen }) {
  return (
    <button className="action-card is-scan rv d1" onClick={onOpen} style={{ textAlign: "left", cursor: "pointer", appearance: "none" }}>
      <div className="ah">
        <div className="tag"><span className="dt"></span>Primary · fastest</div>
        <QRPreview />
      </div>
      <h2>Scan a room <span className="ed">code.</span></h2>
      <p className="body">Point your camera at the Herely mark posted in the space. You'll be in before the kettle boils.</p>
      <div className="foot">
        <span className="btn btn-primary" style={{ pointerEvents: "none" }}>
          <QRIcon size={15} /> Open scanner <Arrow />
        </span>
        <span className="mono">Cmd · K</span>
      </div>
    </button>
  );
}

function CodeCard({ onSubmit, disabled }) {
  const [vals, setVals] = useState(["", "", "", "", "", ""]);
  const [err, setErr] = useState(false);
  const [ok, setOk] = useState(false);
  const [shake, setShake] = useState(false);
  const refs = useRef([]);

  const set = (i, value) => {
    const c = String(value).replace(/[^a-z0-9]/gi, "").toUpperCase().slice(0, 1);
    setVals((prev) => {
      const next = prev.slice();
      next[i] = c;
      return next;
    });
    setErr(false);
    if (c && i < 5) refs.current[i + 1]?.focus();
  };

  const code = vals.join("");
  const complete = code.length === 6;

  const submit = async () => {
    if (!complete || ok || disabled) return;
    try {
      setOk(true);
      setErr(false);
      if (onSubmit) {
        const success = await onSubmit(code);
        if (!success) throw new Error("Invalid code");
      }
    } catch (error) {
      setOk(false);
      setErr(true);
      setShake(true);
      setTimeout(() => setShake(false), 420);
    }
  };

  const onKey = (i, e) => {
    if (e.key === "Backspace" && !vals[i] && i > 0) {
      refs.current[i - 1]?.focus();
      setVals((prev) => {
        const next = prev.slice();
        next[i - 1] = "";
        return next;
      });
    } else if (e.key === "ArrowLeft" && i > 0) {
      refs.current[i - 1]?.focus();
    } else if (e.key === "ArrowRight" && i < 5) {
      refs.current[i + 1]?.focus();
    } else if (e.key === "Enter") {
      submit();
    }
  };

  const onPaste = (e) => {
    const text = (e.clipboardData?.getData("text") || "").replace(/[^a-z0-9]/gi, "").toUpperCase().slice(0, 6);
    if (!text) return;
    e.preventDefault();
    const next = ["", "", "", "", "", ""];
    for (let index = 0; index < text.length; index += 1) next[index] = text[index];
    setVals(next);
    refs.current[Math.min(text.length, 5)]?.focus();
  };

  return (
    <div className={"action-card is-code rv d2 " + (shake ? "shake" : "") }>
      <div className="ah">
        <div className="tag"><span className="dt"></span>Have a code? Type it in</div>
        <KeyIcon />
      </div>
      <h2>Enter with a <span className="ed">code.</span></h2>
      <div className="code-input" onPaste={onPaste}>
        {[0, 1, 2].map((i) => (
          <input
            key={i}
            ref={(el) => { refs.current[i] = el; }}
            className={"code-cell " + (vals[i] ? "filled " : "") + (err ? "err" : "")}
            value={vals[i]}
            onChange={(e) => set(i, e.target.value)}
            onKeyDown={(e) => onKey(i, e)}
            inputMode="text"
            autoComplete="off"
            maxLength={1}
            aria-label={"Code character " + (i + 1)}
          />
        ))}
        <span className="code-sep">·</span>
        {[3, 4, 5].map((i) => (
          <input
            key={i}
            ref={(el) => { refs.current[i] = el; }}
            className={"code-cell " + (vals[i] ? "filled " : "") + (err ? "err" : "")}
            value={vals[i]}
            onChange={(e) => set(i, e.target.value)}
            onKeyDown={(e) => onKey(i, e)}
            inputMode="text"
            autoComplete="off"
            maxLength={1}
            aria-label={"Code character " + (i + 1)}
          />
        ))}
      </div>
      <div className={"code-msg " + (err ? "err" : ok ? "ok" : "")}>{err ? "Code not recognized — try again" : ok ? "Match found · joining…" : complete ? "Ready · press enter to join" : "Six characters · letters & numbers"}</div>
      <div className="foot">
        <button className="btn btn-primary" disabled={!complete || ok || disabled} onClick={submit}>
          {ok ? <><CheckIcon /> Joining</> : <>Join room <Arrow /></>}
        </button>
        <span className="mono" title="Try: HERELY">Try · HERELY</span>
      </div>
    </div>
  );
}

function Toast({ msg, show }) {
  return (
    <div className={"toast " + (show ? "in" : "") }>
      <span className="d"></span>{msg}
    </div>
  );
}

function MoodSelector({ value, onChange }) {
  const localMoods = window.MOODS || [
    { key: "lit",         label: "Lit 🔥",         color: "#FF5E3A" },
    { key: "mellow",      label: "Mellow 🌊",      color: "#4DA6FF" },
    { key: "magnetic",    label: "Magnetic ✨",    color: "#FFD700" },
    { key: "present",     label: "Present 🎯",     color: "#00C49A" },
    { key: "adventurous", label: "Adventurous 🌀", color: "#A855F7" },
  ];
  return (
    <div className="mood-card rv d3">
      <div className="left">
        <span className="eyebrow">Your signal</span>
        <h3>Set your mood — quietly.</h3>
        <p className="body">
          This is the only thing others see before mutual interest. No name, no photo — just a soft texture of what you're open to right now.
        </p>
      </div>
      <div className="mood-row">
        {localMoods.map((mood) => (
          <button
            key={mood.key}
            className={"mood-chip " + (value === mood.key ? "on" : "")}
            style={{ "--c": mood.color }}
            onClick={() => onChange(mood.key)}
          >
            <span className="swatch"></span>
            {mood.label}
          </button>
        ))}
      </div>
    </div>
  );
}

function ScanQR({ onNavigate }) {
  const [selectedMood, setSelectedMood] = useState("lit");
  const [now, setNow] = useState(() => new Date());
  const [toast, setToast] = useState({ show: false, msg: "" });
  const [scanOpen, setScanOpen] = useState(false);

  const showToast = (msg) => {
    setToast({ show: true, msg });
    window.setTimeout(() => setToast((current) => ({ ...current, show: false })), 2400);
  };

  const handleMoodChange = (nextMood) => {
    setSelectedMood(nextMood);
    const moodItem = (window.MOODS && window.MOODS.find((item) => item.key === nextMood)) || { label: nextMood };
    showToast("Mood set · " + moodItem.label.toLowerCase());
  };
  
  useEffect(() => {
    const timer = window.setInterval(() => setNow(new Date()), 30000);
    return () => window.clearInterval(timer);
  }, []);

  useEffect(() => {
    const els = document.querySelectorAll(".rv");
    requestAnimationFrame(function () {
      requestAnimationFrame(function () {
        els.forEach(function (el) { el.classList.add("in"); });
      });
    });
  }, []);

  const handleCodeSubmit = (code) => {
    return new Promise((resolve, reject) => {
      const upper = code.toUpperCase();
      if (HARDCODED_CODES.includes(upper)) {
        setTimeout(() => {
          // PILOT FIX #1: go through real pilot check-in, NOT fake /join/studio-1
          window.location.href = `/NYC51`;
          resolve(true);
        }, 800);
      } else {
        setTimeout(() => reject(new Error("Invalid")), 400);
      }
    });
  };

  return (
    <div className="scanqr-experience midnight">
      {typeof window !== 'undefined' && window.HeroAmbient && <window.HeroAmbient midnight={true} />}
      <div className="hero-vignette"></div>
      
      <div className="wrap scanqr-inner" style={{ justifyContent: "center", paddingTop: "calc(64px + 40px)", paddingBottom: "80px", display: "flex", flexDirection: "column", flex: 1, zIndex: 10 }}>
        
        <div className="scanqr-grid">
          <div style={{ gridColumn: "1 / -1" }}>
            <Greeting userName="Samay" mood={selectedMood} time={now} onNavigate={onNavigate} />
          </div>

          <div className="actions">
            <ScanCard onOpen={() => setScanOpen(true)} />
            <CodeCard onSubmit={handleCodeSubmit} />
            <MoodSelector value={selectedMood} onChange={handleMoodChange} />
          </div>
        </div>

      </div>

      <Toast msg={toast.msg} show={toast.show} />

      <ScanModal
        open={scanOpen}
        onClose={() => setScanOpen(false)}
        onScanned={(roomId, code, rawValue) => {
          setScanOpen(false);
          // Extract room code from QR URL or use raw code
          const upper = (code || "").toUpperCase();
          const target = HARDCODED_CODES.includes(upper) ? upper : "HERELY";
          showToast("Match found · Redirecting...");
          setTimeout(() => {
            window.location.href = `/NYC51`;
          }, 600);
        }}
      />


      <style>{`
        .scanqr-experience {
          min-height: 100dvh;
          min-height: 100svh;
          background: var(--bg);
          color: var(--ink);
          display: flex;
          flex-direction: column;
          position: relative;
          overflow: hidden;
        }

        /* Greet */
        .greet { display: flex; flex-direction: column; gap: 12px; }
        .greet .row1 { display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; margin-bottom: 8px; }
        .greet h1 { margin: 0; font-size: clamp(38px, 5.4vw, 78px); line-height: 0.95; letter-spacing: -0.035em; font-weight: 400; max-width: none; white-space: nowrap; }
        .greet .lede { max-width: 54ch; opacity: 0.7; font-size: 16px; margin-top: 8px; line-height: 1.5; }
        .eyebrow { font: 500 11px/1 var(--mono); letter-spacing: 0.08em; text-transform: uppercase; color: var(--mute); }
        .pill-state { display: inline-flex; align-items: center; padding: 6px 12px; background: rgba(255,255,255,0.05); border-radius: 999px; font: 500 11px/1 var(--mono); letter-spacing: 0.05em; text-transform: uppercase; color: var(--mute); border: 1px solid var(--line); }

        /* Action Cards */
        .action-card { border: 1px solid var(--line); border-radius: 24px; background: color-mix(in oklab, #121217 92%, transparent); padding: 24px; min-height: 280px; display: flex; flex-direction: column; gap: 16px; overflow: hidden; position: relative; box-shadow: 0 14px 40px rgba(11,11,13,0.05); transition: all 0.3s ease; }
        .action-card h2 { margin: 0; font-size: clamp(28px, 3vw, 44px); line-height: 1.04; letter-spacing: -0.03em; font-weight: 400; }
        .action-card .body { margin: 0; color: var(--mute); font-size: 15px; line-height: 1.55; max-width: 40ch; }
        .ah { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; }
        .tag { display: inline-flex; align-items: center; gap: 6px; font-family: var(--mono); font-size: 10.5px; letter-spacing: 0.08em; text-transform: uppercase; color: var(--mute); padding: 5px 9px; border: 1px solid var(--line); border-radius: 999px; background: rgba(255,255,255,0.02); }
        .dt { width: 6px; height: 6px; border-radius: 50%; background: var(--m-teal); }
        .qr-preview { width: 82px; height: 82px; display: grid; grid-template-columns: repeat(7, 1fr); gap: 3px; flex: 0 0 auto; padding: 4px; border-radius: 18px; background: rgba(255,255,255,0.03); border: 1px solid var(--line); }
        .qr-preview span { border-radius: 2px; background: var(--ink); }
        .qr-preview span.off { background: var(--line); }
        .foot { margin-top: auto; display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; padding-top: 16px; }

        /* Code Input */
        .code-input { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)) auto repeat(3, minmax(0, 1fr)); gap: 10px; align-items: center; }
        .code-cell { height: 48px; border: 1px solid var(--line); border-radius: 12px; background: var(--bg-2); color: var(--ink); text-align: center; font: 500 20px/1 var(--sans); text-transform: uppercase; transition: all 0.2s ease; outline: none; }
        .code-cell:focus { border-color: var(--m-blue); background: color-mix(in oklab, var(--m-blue) 10%, transparent); box-shadow: 0 0 0 3px color-mix(in oklab, var(--m-blue) 20%, transparent); }
        .code-cell.filled { border-color: color-mix(in oklab, var(--ink) 40%, transparent); }
        .code-cell.err { border-color: var(--m-red); background: color-mix(in oklab, var(--m-red) 10%, transparent); color: var(--m-red); }
        .code-sep { font-weight: 500; color: var(--mute); opacity: 0.5; }
        .code-msg { font: 500 12px/1.5 var(--sans); color: var(--mute); min-height: 18px; margin-top: 4px; }
        .code-msg.err { color: var(--m-red); }
        .code-msg.ok { color: var(--m-teal); }
        
        .shake { animation: shake 0.4s cubic-bezier(0.36, 0.07, 0.19, 0.97) both; }
        @keyframes shake {
          10%, 90% { transform: translateX(-2px); }
          20%, 80% { transform: translateX(3px); }
          30%, 50%, 70% { transform: translateX(-5px); }
          40%, 60% { transform: translateX(5px); }
        }

        /* Mood Selector */
        .mood-card { display: flex; flex-direction: column; align-items: flex-start; justify-content: space-between; gap: 18px; padding: 24px; border: 1px solid var(--line); border-radius: 24px; background: color-mix(in oklab, #121217 92%, transparent); min-height: 280px; box-shadow: 0 14px 40px rgba(11,11,13,0.05); }
        .mood-card h3 { margin: 10px 0 0; font-size: clamp(24px, 2.8vw, 38px); line-height: 1.04; letter-spacing: -0.03em; font-weight: 400; }
        .mood-card .body { margin: 10px 0 0; color: var(--mute); max-width: 44ch; }
        .mood-row { display: flex; gap: 10px; flex-wrap: wrap; justify-content: flex-start; margin-top: auto; }
        .mood-chip { appearance: none; display: inline-flex; align-items: center; gap: 8px; border-radius: 999px; border: 1px solid var(--line); background: transparent; color: var(--ink); padding: 10px 14px; font: 500 13px/1 var(--sans); cursor: pointer; transition: transform 0.2s ease, border-color 0.2s ease, background 0.2s ease, color 0.2s ease; }
        .mood-chip:hover { transform: translateY(-1px); border-color: var(--ink); }
        .mood-chip.on { background: var(--ink); color: var(--bg); border-color: var(--ink); }
        .mood-chip .swatch { width: 9px; height: 9px; border-radius: 50%; box-shadow: none; background: var(--c); }
        
        /* Toast */
        .toast { position: fixed; left: 50%; bottom: 28px; transform: translateX(-50%) translateY(20px); opacity: 0; z-index: 9999; background: rgba(11,11,13,0.92); color: #F4F2EE; padding: 12px 16px; border-radius: 999px; display: inline-flex; align-items: center; gap: 8px; font: 500 13px/1 var(--sans); box-shadow: 0 12px 32px rgba(0,0,0,0.28); transition: opacity 0.2s ease, transform 0.2s ease; }
        .toast.in { opacity: 1; transform: translateX(-50%) translateY(0); }
        .toast .d { width: 7px; height: 7px; border-radius: 50%; background: var(--m-teal); box-shadow: 0 0 0 4px rgba(0,196,154,0.15); }

        /* Modal */
        .modal-back { position: fixed; inset: 0; z-index: 9998; background: rgba(11,11,13,0.58); display: flex; align-items: center; justify-content: center; padding: 20px; opacity: 0; pointer-events: none; transition: opacity 0.2s ease; }
        .modal-back.in { opacity: 1; pointer-events: auto; }
        .modal { width: min(900px, 100%); border-radius: 28px; background: var(--bg); color: var(--ink); border: 1px solid var(--line); box-shadow: 0 40px 120px rgba(0,0,0,0.32); padding: 22px; display: flex; flex-direction: column; gap: 16px; }
        .head { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; }
        .ttl { font-size: 22px; line-height: 1.05; letter-spacing: -0.02em; font-weight: 500; }
        .sub { margin-top: 4px; color: var(--mute); font-size: 13px; }
        .modal-close { appearance: none; border: 1px solid var(--line); background: transparent; color: var(--ink); width: 34px; height: 34px; border-radius: 50%; display: inline-flex; align-items: center; justify-content: center; cursor: pointer; }
        .viewfinder { position: relative; min-height: 420px; border-radius: 24px; overflow: hidden; border: 1px solid var(--line); background: #111; }
        .vf-video { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; opacity: 0.9; }
        .vf-grid { position: absolute; inset: 0; background-image: linear-gradient(rgba(255,255,255,0.05) 1px, transparent 1px), linear-gradient(90deg, rgba(255,255,255,0.05) 1px, transparent 1px); background-size: 48px 48px; mix-blend-mode: overlay; pointer-events: none; }
        .vf-corners { position: absolute; inset: 18px; pointer-events: none; }
        .vf-corner { position: absolute; width: 26px; height: 26px; border-color: var(--m-teal); border-style: solid; opacity: 0.95; }
        .vf-corner.tl { left: 0; top: 0; border-width: 2px 0 0 2px; border-top-left-radius: 18px; }
        .vf-corner.tr { right: 0; top: 0; border-width: 2px 2px 0 0; border-top-right-radius: 18px; }
        .vf-corner.bl { left: 0; bottom: 0; border-width: 0 0 2px 2px; border-bottom-left-radius: 18px; }
        .vf-corner.br { right: 0; bottom: 0; border-width: 0 2px 2px 0; border-bottom-right-radius: 18px; }
        .vf-laser { position: absolute; left: 14%; right: 14%; top: 50%; height: 2px; background: linear-gradient(90deg, transparent, var(--m-teal), transparent); box-shadow: 0 0 22px var(--m-teal); animation: laser 1.8s ease-in-out infinite; }
        @keyframes laser { 0%, 100% { transform: translateY(-20px); opacity: 0.45; } 50% { transform: translateY(20px); opacity: 1; } }
        .vf-foundqr { position: absolute; inset: auto 18px 18px auto; width: 120px; height: 120px; padding: 8px; border-radius: 16px; background: rgba(255,255,255,0.96); display: grid; grid-template-columns: repeat(11, 1fr); gap: 2px; opacity: 0; transform: scale(0.96); transition: opacity 0.2s ease, transform 0.2s ease; }
        .vf-foundqr.show { opacity: 1; transform: scale(1); }
        .vf-foundqr span { background: #0B0B0D; border-radius: 1px; }
        .vf-foundqr span.off { background: rgba(11,11,13,0.16); }
        .vf-status { position: absolute; left: 16px; bottom: 16px; display: inline-flex; align-items: center; gap: 8px; padding: 8px 12px; border-radius: 999px; background: rgba(11,11,13,0.62); color: #F4F2EE; font: 500 11px/1 var(--mono); letter-spacing: 0.08em; text-transform: uppercase; }
        .vf-status .d { width: 7px; height: 7px; border-radius: 50%; background: var(--m-teal); box-shadow: 0 0 0 4px rgba(0,196,154,0.18); }
        .vf-status.found { background: rgba(0,196,154,0.18); }
        .vf-fallback { position: absolute; inset: auto 16px 16px auto; max-width: 240px; background: rgba(11,11,13,0.72); color: #fff; padding: 14px; border-radius: 16px; display: flex; flex-direction: column; gap: 10px; }
        .vf-fallback p { margin: 0; font-size: 13px; line-height: 1.5; }
        .modal-foot { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; padding-top: 16px; }
        .hint { color: var(--mute); font: 500 11px/1 var(--mono); letter-spacing: 0.08em; text-transform: uppercase; }

        .rv { opacity: 0; transform: translateY(10px); transition: opacity 0.8s ease, transform 0.8s ease; }
        .rv.in { opacity: 1; transform: translateY(0); }
        .rv.d1 { transition-delay: 0.1s; }
        .rv.d2 { transition-delay: 0.2s; }
        .rv.d3 { transition-delay: 0.3s; }

        .scanqr-grid { display: grid; grid-template-columns: repeat(12, 1fr); gap: 24px; max-width: 1120px; margin: auto; width: 100%; }
        .actions { grid-column: 1 / -1; display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 18px; margin-top: 12px; }

        @media (max-width: 1080px) {
          .actions { grid-template-columns: repeat(2, minmax(0, 1fr)); }
        }
        @media (max-width: 768px) {
          .actions { grid-template-columns: 1fr; }
          .scanqr-grid { grid-template-columns: 1fr; }
          .scanqr-inner { padding-top: calc(64px + 20px); }
        }
      `}</style>
    </div>
  );
}

Object.assign(window, { ScanQR });
