// Form field components for the registration form.
// All dark-theme, grotesque-led, editorial. One CSS block at top scopes
// styles to the .reg root so nothing leaks.

if (typeof document !== "undefined" && !document.getElementById("reg-fields-css")) {
  const s = document.createElement("style");
  s.id = "reg-fields-css";
  s.textContent = `
    .reg-row { display: flex; flex-direction: column; gap: 10px; }

    .reg-label {
      font-family: var(--mono);
      font-size: 10.5px; letter-spacing: .18em;
      text-transform: uppercase;
      color: rgba(243,239,233,0.6);
      display: flex; align-items: baseline; gap: 10px;
    }
    .reg-label .req {
      color: rgba(243,239,233,0.32); font-weight: 400;
    }
    .reg-help {
      font-size: 12px; color: rgba(243,239,233,0.45);
      font-family: var(--mono); letter-spacing: .02em;
      margin-top: 4px;
    }
    .reg-error {
      color: #e7754c; font-size: 11.5px; letter-spacing: .04em;
      font-family: var(--mono); margin-top: 4px;
    }

    /* Text input — thin underline */
    .reg-input {
      appearance: none; -webkit-appearance: none;
      width: 100%; box-sizing: border-box;
      background: transparent;
      border: none;
      border-bottom: 1px solid rgba(243,239,233,0.22);
      padding: 12px 0 10px;
      font: inherit;
      font-family: var(--font-body);
      font-size: clamp(20px, 1.8vw, 26px);
      color: #f3efe9;
      outline: none;
      transition: border-color .2s;
    }
    .reg-input::placeholder { color: rgba(243,239,233,0.22); }
    .reg-input:focus { border-bottom-color: #f3efe9; }
    .reg-input.error { border-bottom-color: #e7754c; }

    /* Number+unit row */
    .reg-numgroup { display: flex; align-items: baseline; gap: 16px; }
    .reg-numgroup .reg-input { flex: 1 1 auto; min-width: 0; }
    .reg-toggle {
      display: inline-flex; padding: 2px;
      background: rgba(243,239,233,0.06);
      border-radius: 999px;
      font-family: var(--mono); font-size: 11px;
      letter-spacing: .12em; text-transform: uppercase;
    }
    .reg-toggle button {
      appearance: none; border: 0; cursor: pointer;
      padding: 6px 14px;
      background: transparent;
      color: rgba(243,239,233,0.55);
      border-radius: 999px;
      font: inherit;
      transition: background .15s, color .15s;
    }
    .reg-toggle button[data-on="1"] {
      background: #f3efe9; color: #0c0c0c;
    }

    /* Chips */
    .reg-chips { display: flex; flex-wrap: wrap; gap: 8px; }
    .reg-chip {
      appearance: none; border: 1px solid rgba(243,239,233,0.22);
      background: transparent; color: rgba(243,239,233,0.78);
      padding: 9px 14px; border-radius: 999px;
      font-family: var(--font-body); font-size: 13.5px;
      letter-spacing: .01em;
      cursor: pointer;
      transition: background .15s, color .15s, border-color .15s, transform .12s;
    }
    .reg-chip:hover { border-color: rgba(243,239,233,0.5); transform: translateY(-1px); }
    .reg-chip[data-on="1"] {
      background: #f3efe9; color: #0c0c0c; border-color: #f3efe9;
    }
    .reg-chip[data-on="1"]:hover { transform: translateY(-1px); }

    /* Custom dropdown */
    .reg-select {
      position: relative; width: 100%;
    }
    .reg-select-button {
      appearance: none; width: 100%; box-sizing: border-box;
      background: transparent; cursor: pointer;
      border: none;
      border-bottom: 1px solid rgba(243,239,233,0.22);
      padding: 12px 30px 10px 0;
      font-family: var(--font-body);
      font-size: clamp(20px, 1.8vw, 26px);
      color: #f3efe9;
      text-align: left;
      display: flex; align-items: baseline; justify-content: space-between;
      gap: 12px;
      transition: border-color .2s;
    }
    .reg-select-button:focus { outline: none; border-bottom-color: #f3efe9; }
    .reg-select-button.placeholder { color: rgba(243,239,233,0.32); }
    .reg-select-caret {
      flex: 0 0 auto;
      width: 14px; height: 14px;
      color: rgba(243,239,233,0.45);
      transition: transform .2s, color .2s;
    }
    .reg-select.open .reg-select-caret { transform: rotate(180deg); color: #f3efe9; }
    .reg-select-pop {
      position: absolute; top: calc(100% + 8px); left: 0; right: 0;
      max-height: 320px; overflow-y: auto;
      background: #181715;
      border: 1px solid rgba(243,239,233,0.16);
      border-radius: 8px;
      box-shadow: 0 12px 40px rgba(0,0,0,0.45);
      z-index: 50;
      padding: 6px;
      opacity: 0; pointer-events: none;
      transform: translateY(-4px);
      transition: opacity .15s, transform .15s;
    }
    .reg-select.open .reg-select-pop {
      opacity: 1; pointer-events: auto; transform: translateY(0);
    }
    .reg-select-pop::-webkit-scrollbar { width: 8px; }
    .reg-select-pop::-webkit-scrollbar-thumb {
      background: rgba(243,239,233,0.15); border-radius: 4px;
      border: 2px solid transparent; background-clip: content-box;
    }
    .reg-option {
      width: 100%;
      appearance: none; border: 0; background: transparent;
      color: #f3efe9; text-align: left; cursor: pointer;
      font-family: var(--font-body); font-size: 15px;
      padding: 10px 14px; border-radius: 5px;
      display: flex; justify-content: space-between; gap: 12px;
      transition: background .12s;
    }
    .reg-option:hover { background: rgba(243,239,233,0.06); }
    .reg-option[aria-selected="true"] { background: rgba(243,239,233,0.1); }
    .reg-option-sub {
      color: rgba(243,239,233,0.42); font-size: 12px;
      font-family: var(--mono); letter-spacing: .04em; text-transform: uppercase;
    }

    /* TextArea */
    .reg-textarea {
      appearance: none; width: 100%; box-sizing: border-box;
      background: transparent;
      border: 1px solid rgba(243,239,233,0.18);
      border-radius: 4px;
      padding: 16px 18px;
      font: inherit; font-family: var(--font-body);
      font-size: 16px; line-height: 1.55;
      color: #f3efe9;
      resize: vertical; min-height: 120px;
      outline: none;
      transition: border-color .2s;
    }
    .reg-textarea::placeholder { color: rgba(243,239,233,0.22); }
    .reg-textarea:focus { border-color: rgba(243,239,233,0.55); }

    /* File upload */
    .reg-drop {
      border: 1.5px dashed rgba(243,239,233,0.26);
      border-radius: 8px;
      padding: 56px 24px;
      display: flex; flex-direction: column; align-items: center; gap: 14px;
      text-align: center; cursor: pointer;
      transition: border-color .15s, background .15s;
    }
    .reg-drop:hover, .reg-drop[data-active="1"] {
      border-color: #f3efe9;
      background: rgba(243,239,233,0.04);
    }
    .reg-drop input { display: none; }
    .reg-drop-title { font-family: var(--font-body); font-size: 17px; color: #f3efe9; }
    .reg-drop-sub {
      font-family: var(--mono); font-size: 11px; letter-spacing: .14em;
      text-transform: uppercase; color: rgba(243,239,233,0.5);
    }
    .reg-media-grid {
      display: grid;
      grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
      gap: 8px;
      margin-top: 16px;
    }
    .reg-media-tile {
      position: relative; aspect-ratio: 3 / 4; overflow: hidden;
      background: #1a1816; border-radius: 4px;
    }
    .reg-media-tile img, .reg-media-tile video {
      width: 100%; height: 100%; object-fit: cover; display: block;
    }
    .reg-media-x {
      position: absolute; top: 6px; right: 6px;
      width: 22px; height: 22px; border-radius: 11px;
      background: rgba(10,10,10,0.7); color: #f3efe9;
      border: 0; cursor: pointer;
      display: flex; align-items: center; justify-content: center;
      font-size: 13px; line-height: 1;
      opacity: 0; transition: opacity .15s;
    }
    .reg-media-tile:hover .reg-media-x { opacity: 1; }
    .reg-media-kind {
      position: absolute; bottom: 6px; left: 6px;
      font-family: var(--mono); font-size: 9px; letter-spacing: .14em;
      text-transform: uppercase; color: rgba(243,239,233,0.85);
      background: rgba(10,10,10,0.5); padding: 2px 6px; border-radius: 4px;
    }
  `;
  document.head.appendChild(s);
}

// ─── Text ──────────────────────────────────────────────────────────────
function RegText({ label, value, onChange, placeholder, required, autoFocus, error, help }) {
  return (
    <div className="reg-row">
      <label className="reg-label">
        <span>{label}</span>{required && <span className="req">required</span>}
      </label>
      <input
        type="text"
        className={"reg-input" + (error ? " error" : "")}
        value={value || ""}
        onChange={(e) => onChange(e.target.value)}
        placeholder={placeholder}
        autoFocus={autoFocus}
      />
      {help && !error && <div className="reg-help">{help}</div>}
      {error && <div className="reg-error">{error}</div>}
    </div>
  );
}

// ─── Date ──────────────────────────────────────────────────────────────
function RegDate({ label, value, onChange, required, error, help }) {
  return (
    <div className="reg-row">
      <label className="reg-label">
        <span>{label}</span>{required && <span className="req">required</span>}
      </label>
      <input
        type="date"
        className={"reg-input" + (error ? " error" : "")}
        value={value || ""}
        onChange={(e) => onChange(e.target.value)}
        style={{ colorScheme: "dark" }}
      />
      {help && !error && <div className="reg-help">{help}</div>}
      {error && <div className="reg-error">{error}</div>}
    </div>
  );
}

// ─── Height (number + cm/ft toggle, stored as cm) ──────────────────────
function RegHeight({ value, onChange, required, error }) {
  // value is always stored in cm. Display can be cm or ft/in.
  const [unit, setUnit] = React.useState("cm");
  const cm = value || "";

  // Local "feet, inches" representation for the ft mode.
  const ftIn = (() => {
    if (!cm) return { ft: "", in: "" };
    const totalIn = Number(cm) / 2.54;
    const ft = Math.floor(totalIn / 12);
    const inch = Math.round(totalIn - ft * 12);
    return { ft, in: inch };
  })();

  const setCm = (raw) => {
    const n = Number(String(raw).replace(/[^0-9.]/g, ""));
    if (!Number.isFinite(n) || n === 0) { onChange(""); return; }
    onChange(Math.round(n));
  };
  const setFromFt = (ft, inch) => {
    const f = Number(ft) || 0;
    const i = Number(inch) || 0;
    if (!f && !i) { onChange(""); return; }
    onChange(Math.round((f * 12 + i) * 2.54));
  };

  return (
    <div className="reg-row">
      <label className="reg-label">
        <span>Height</span>{required && <span className="req">required</span>}
      </label>
      <div className="reg-numgroup">
        {unit === "cm" ? (
          <input
            type="text" inputMode="numeric"
            className={"reg-input" + (error ? " error" : "")}
            value={cm}
            onChange={(e) => setCm(e.target.value)}
            placeholder="178"
            style={{ maxWidth: 160 }}
          />
        ) : (
          <>
            <input
              type="text" inputMode="numeric"
              className={"reg-input" + (error ? " error" : "")}
              value={ftIn.ft}
              onChange={(e) => setFromFt(e.target.value, ftIn.in)}
              placeholder="5"
              style={{ maxWidth: 80 }}
              aria-label="Feet"
            />
            <span style={{ color:"rgba(243,239,233,0.5)", fontFamily:"var(--mono)", fontSize:13, letterSpacing:".14em", textTransform:"uppercase" }}>ft</span>
            <input
              type="text" inputMode="numeric"
              className={"reg-input" + (error ? " error" : "")}
              value={ftIn.in}
              onChange={(e) => setFromFt(ftIn.ft, e.target.value)}
              placeholder="10"
              style={{ maxWidth: 80 }}
              aria-label="Inches"
            />
            <span style={{ color:"rgba(243,239,233,0.5)", fontFamily:"var(--mono)", fontSize:13, letterSpacing:".14em", textTransform:"uppercase" }}>in</span>
          </>
        )}
        <div className="reg-toggle" style={{ marginLeft:"auto" }}>
          <button data-on={unit === "cm" ? "1" : "0"} onClick={() => setUnit("cm")}>cm</button>
          <button data-on={unit === "ft" ? "1" : "0"} onClick={() => setUnit("ft")}>ft / in</button>
        </div>
      </div>
      <div className="reg-help">
        Saved as centimetres ({cm ? `${cm} cm` : "—"}). The profile shows it formatted automatically.
      </div>
      {error && <div className="reg-error">{error}</div>}
    </div>
  );
}

// ─── Dropdown — accepts strings or {value, sub} ────────────────────────
function RegDropdown({ label, value, options, onChange, placeholder = "Select…", required, error, help }) {
  const [open, setOpen] = React.useState(false);
  const ref = React.useRef(null);
  React.useEffect(() => {
    if (!open) return;
    const off = (e) => { if (!ref.current?.contains(e.target)) setOpen(false); };
    const onKey = (e) => { if (e.key === "Escape") setOpen(false); };
    document.addEventListener("pointerdown", off, true);
    document.addEventListener("keydown", onKey);
    return () => {
      document.removeEventListener("pointerdown", off, true);
      document.removeEventListener("keydown", onKey);
    };
  }, [open]);

  const norm = options.map((o) => typeof o === "string" ? { value: o } : o);
  const display = value || placeholder;
  const placeholderState = !value;

  return (
    <div className="reg-row">
      <label className="reg-label">
        <span>{label}</span>{required && <span className="req">required</span>}
      </label>
      <div className={"reg-select" + (open ? " open" : "")} ref={ref}>
        <button
          type="button"
          className={"reg-select-button" + (placeholderState ? " placeholder" : "") + (error ? " error" : "")}
          onClick={() => setOpen((o) => !o)}
        >
          <span>{display}</span>
          <svg className="reg-select-caret" viewBox="0 0 14 14" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round">
            <path d="M3 5l4 4 4-4"/>
          </svg>
        </button>
        <div className="reg-select-pop" role="listbox">
          {norm.map((o) => (
            <button
              key={o.value}
              type="button"
              className="reg-option"
              role="option"
              aria-selected={o.value === value}
              onClick={() => { onChange(o.value); setOpen(false); }}
            >
              <span>{o.value}</span>
              {o.sub && <span className="reg-option-sub">{o.sub}</span>}
            </button>
          ))}
        </div>
      </div>
      {help && !error && <div className="reg-help">{help}</div>}
      {error && <div className="reg-error">{error}</div>}
    </div>
  );
}

// ─── Multi-chip select ─────────────────────────────────────────────────
function RegMultiChip({ label, value, options, onChange, required, error, help }) {
  const list = value || [];
  const toggle = (v) => {
    if (list.includes(v)) onChange(list.filter((x) => x !== v));
    else onChange([...list, v]);
  };
  return (
    <div className="reg-row">
      <label className="reg-label">
        <span>{label}</span>{required && <span className="req">required</span>}
      </label>
      <div className="reg-chips">
        {options.map((o) => (
          <button
            key={o}
            type="button"
            className="reg-chip"
            data-on={list.includes(o) ? "1" : "0"}
            onClick={() => toggle(o)}
          >{o}</button>
        ))}
      </div>
      {help && !error && <div className="reg-help">{help}</div>}
      {error && <div className="reg-error">{error}</div>}
    </div>
  );
}

// ─── Radio (single-choice chip group) ──────────────────────────────────
function RegRadio({ label, value, options, onChange, required, error, help }) {
  return (
    <div className="reg-row">
      <label className="reg-label">
        <span>{label}</span>{required && <span className="req">required</span>}
      </label>
      <div className="reg-chips">
        {options.map((o) => (
          <button
            key={o}
            type="button"
            className="reg-chip"
            data-on={value === o ? "1" : "0"}
            onClick={() => onChange(o)}
          >{o}</button>
        ))}
      </div>
      {help && !error && <div className="reg-help">{help}</div>}
      {error && <div className="reg-error">{error}</div>}
    </div>
  );
}

// ─── TextArea ──────────────────────────────────────────────────────────
function RegTextArea({ label, value, onChange, placeholder, required, error, help, rows = 5 }) {
  return (
    <div className="reg-row">
      <label className="reg-label">
        <span>{label}</span>{required && <span className="req">required</span>}
      </label>
      <textarea
        className="reg-textarea"
        value={value || ""}
        onChange={(e) => onChange(e.target.value)}
        placeholder={placeholder}
        rows={rows}
      />
      {help && !error && <div className="reg-help">{help}</div>}
      {error && <div className="reg-error">{error}</div>}
    </div>
  );
}

// ─── File upload (drag-drop, multi, with previews) ─────────────────────
//
// Returns items shaped { src (objectURL), file, w, h, kind, name }. The
// caller persists in state. On submit we hand over the file blobs to the
// agency; image dimensions are measured client-side so the gallery packs
// rows without ever cropping.
function RegFileUpload({ label, value, onChange, min = 5, max = 15, required, error, help }) {
  const list = value || [];
  const [active, setActive] = React.useState(false);
  const inputRef = React.useRef(null);

  const measure = (file) => new Promise((res) => {
    const url = URL.createObjectURL(file);
    const isVideo = /^video\//.test(file.type);
    if (isVideo) {
      const v = document.createElement("video");
      v.preload = "metadata";
      v.muted = true;
      v.onloadedmetadata = () => {
        res({ src: url, file, w: v.videoWidth || 720, h: v.videoHeight || 1280, kind: "video", name: file.name });
      };
      v.onerror = () => res({ src: url, file, w: 720, h: 1280, kind: "video", name: file.name });
      v.src = url;
    } else {
      const img = new Image();
      img.onload = () => res({ src: url, file, w: img.naturalWidth, h: img.naturalHeight, kind: "image", name: file.name });
      img.onerror = () => res({ src: url, file, w: 400, h: 600, kind: "image", name: file.name });
      img.src = url;
    }
  });

  const addFiles = async (files) => {
    const remaining = max - list.length;
    const arr = Array.from(files).slice(0, remaining)
      .filter((f) => /^image\/|^video\//.test(f.type));
    const measured = await Promise.all(arr.map(measure));
    onChange([...list, ...measured]);
  };

  const removeAt = (i) => {
    const next = list.slice();
    URL.revokeObjectURL(next[i].src);
    next.splice(i, 1);
    onChange(next);
  };

  return (
    <div className="reg-row">
      <label className="reg-label">
        <span>{label}</span>
        {required && <span className="req">min {min}</span>}
      </label>
      <div
        className="reg-drop"
        data-active={active ? "1" : "0"}
        onClick={() => inputRef.current?.click()}
        onDragOver={(e) => { e.preventDefault(); setActive(true); }}
        onDragLeave={() => setActive(false)}
        onDrop={(e) => {
          e.preventDefault();
          setActive(false);
          if (e.dataTransfer?.files?.length) addFiles(e.dataTransfer.files);
        }}
      >
        <svg width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" style={{color:"rgba(243,239,233,0.7)"}}>
          <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/>
          <polyline points="17 8 12 3 7 8"/>
          <line x1="12" y1="3" x2="12" y2="15"/>
        </svg>
        <div className="reg-drop-title">
          {list.length === 0
            ? "Drop your photos and videos here"
            : `Add more (${list.length} / ${max})`}
        </div>
        <div className="reg-drop-sub">
          {list.length === 0
            ? `Minimum ${min} · maximum ${max} · JPG, PNG, MP4, MOV`
            : "JPG, PNG, MP4, MOV"}
        </div>
        <input
          ref={inputRef}
          type="file"
          accept="image/*,video/*"
          multiple
          onChange={(e) => { if (e.target.files?.length) addFiles(e.target.files); e.target.value = ""; }}
        />
      </div>

      {list.length > 0 && (
        <div className="reg-media-grid">
          {list.map((item, i) => (
            <div key={item.src} className="reg-media-tile">
              {item.kind === "video" ? (
                <video src={item.src} muted playsInline/>
              ) : (
                <img src={item.src} alt=""/>
              )}
              <span className="reg-media-kind">
                {item.kind === "video" ? "Video" : `${item.w}×${item.h}`}
              </span>
              <button
                type="button"
                className="reg-media-x"
                aria-label="Remove"
                onClick={(e) => { e.stopPropagation(); removeAt(i); }}
              >×</button>
            </div>
          ))}
        </div>
      )}

      {help && !error && <div className="reg-help">{help}</div>}
      {error && <div className="reg-error">{error}</div>}
    </div>
  );
}

// ─── Yes/No + optional details ─────────────────────────────────────────
function RegYesNoDetails({ label, value, onChange, detailLabel, required }) {
  // value shape: { has: boolean, detail: string }
  const v = value || { has: false, detail: "" };
  return (
    <div className="reg-row">
      <label className="reg-label">
        <span>{label}</span>{required && <span className="req">required</span>}
      </label>
      <div className="reg-chips">
        <button type="button" className="reg-chip" data-on={v.has === false ? "1" : "0"} onClick={() => onChange({ has: false, detail: "" })}>None</button>
        <button type="button" className="reg-chip" data-on={v.has === true  ? "1" : "0"} onClick={() => onChange({ has: true, detail: v.detail })}>Yes</button>
      </div>
      {v.has && (
        <div style={{ marginTop: 14 }}>
          <input
            type="text"
            className="reg-input"
            value={v.detail || ""}
            onChange={(e) => onChange({ has: true, detail: e.target.value })}
            placeholder={detailLabel || "Describe briefly"}
            style={{ fontSize: 18 }}
          />
        </div>
      )}
    </div>
  );
}

// ─── Date — three dropdowns (day / month / year) ───────────────────────
// Stores an ISO date string ("YYYY-MM-DD") so the rest of the form is
// unchanged. Native <input type=date> looks too utilitarian against the
// rest of this form's editorial chrome.
const REG_MONTHS = [
  "January", "February", "March", "April", "May", "June",
  "July", "August", "September", "October", "November", "December",
];

function RegDateParts({ label, value, onChange, required, error, help, minAge = 16, maxAge = 65 }) {
  const parts = (() => {
    if (!value) return { y: "", m: "", d: "" };
    const [y, m, d] = value.split("-");
    return { y: y || "", m: m || "", d: d || "" };
  })();

  const commit = (y, m, d) => {
    if (!y || !m || !d) { onChange(""); return; }
    // Clamp day to month's length so e.g. picking Feb 30 falls back to Feb 28.
    const last = new Date(Number(y), Number(m), 0).getDate();
    const dN = Math.min(Number(d), last);
    onChange(`${y}-${String(m).padStart(2, "0")}-${String(dN).padStart(2, "0")}`);
  };

  const days = Array.from({ length: 31 }, (_, i) => String(i + 1));
  const months = REG_MONTHS.map((name, i) => ({ value: String(i + 1).padStart(2, "0"), label: name }));
  const thisYear = new Date().getFullYear();
  const years = Array.from({ length: maxAge - minAge + 1 },
    (_, i) => String(thisYear - minAge - i));

  return (
    <div className="reg-row">
      <label className="reg-label">
        <span>{label}</span>{required && <span className="req">required</span>}
      </label>
      <div style={{ display:"grid", gridTemplateColumns:"1fr 1.4fr 1fr", gap: 18 }}>
        <DateDropdown
          placeholder="Day"
          value={parts.d}
          options={days}
          onChange={(v) => commit(parts.y, parts.m, v)}
        />
        <DateDropdown
          placeholder="Month"
          value={parts.m}
          renderValue={(v) => v ? REG_MONTHS[Number(v) - 1] : ""}
          options={months.map((m) => ({ value: m.value, label: m.label }))}
          onChange={(v) => commit(parts.y, v, parts.d)}
        />
        <DateDropdown
          placeholder="Year"
          value={parts.y}
          options={years}
          onChange={(v) => commit(v, parts.m, parts.d)}
        />
      </div>
      {help && !error && <div className="reg-help">{help}</div>}
      {error && <div className="reg-error">{error}</div>}
    </div>
  );
}

// Compact dropdown variant used by the date picker. Same chrome as RegDropdown
// but renders just the bare value (no label row), accepts string or
// {value,label} options, and supports a renderValue for displaying month names.
function DateDropdown({ value, placeholder, options, onChange, renderValue }) {
  const [open, setOpen] = React.useState(false);
  const ref = React.useRef(null);
  React.useEffect(() => {
    if (!open) return;
    const off = (e) => { if (!ref.current?.contains(e.target)) setOpen(false); };
    const onKey = (e) => { if (e.key === "Escape") setOpen(false); };
    document.addEventListener("pointerdown", off, true);
    document.addEventListener("keydown", onKey);
    return () => {
      document.removeEventListener("pointerdown", off, true);
      document.removeEventListener("keydown", onKey);
    };
  }, [open]);

  const norm = options.map((o) =>
    typeof o === "string" ? { value: o, label: o } : o
  );
  const selected = norm.find((o) => o.value === value);
  const display = selected
    ? (renderValue ? renderValue(value) : selected.label)
    : placeholder;

  return (
    <div className={"reg-select" + (open ? " open" : "")} ref={ref}>
      <button
        type="button"
        className={"reg-select-button" + (!value ? " placeholder" : "")}
        onClick={() => setOpen((o) => !o)}
      >
        <span>{display}</span>
        <svg className="reg-select-caret" viewBox="0 0 14 14" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round">
          <path d="M3 5l4 4 4-4"/>
        </svg>
      </button>
      <div className="reg-select-pop" role="listbox">
        {norm.map((o) => (
          <button
            key={o.value}
            type="button"
            className="reg-option"
            role="option"
            aria-selected={o.value === value}
            onClick={() => { onChange(o.value); setOpen(false); }}
          >
            <span>{o.label}</span>
          </button>
        ))}
      </div>
    </div>
  );
}

// ─── Size with region toggle (dress / shoe) ────────────────────────────
//
// Stores the canonical EU value (a string like "36" or "39.5"); the
// component handles converting on the fly when the user toggles to US / UK.
// Sizing tables ship with the component as window.REG_SIZE_TABLES.
window.REG_SIZE_TABLES = {
  dress: {
    EU: ["32", "34", "36", "38", "40", "42", "44", "46", "48"],
    US: ["0",  "2",  "4",  "6",  "8",  "10", "12", "14", "16"],
    UK: ["4",  "6",  "8",  "10", "12", "14", "16", "18", "20"],
  },
  shoe: {
    EU: ["35", "36", "37", "38", "39", "40", "41", "42", "43"],
    US: ["5",  "6",  "7",  "8",  "8.5","9.5","10", "11", "12"],
    UK: ["2.5","3.5","4.5","5.5","6",  "7",  "7.5","8.5","9.5"],
  },
};

function RegSizeWithRegion({ label, value, table, onChange, required, error, help }) {
  // Region used purely for display — the canonical stored value is always EU.
  const [region, setRegion] = React.useState("EU");
  const eu = value || ""; // canonical EU string
  const idx = table.EU.indexOf(eu);
  const displayValue = idx >= 0 ? table[region][idx] : "";

  return (
    <div className="reg-row">
      <label className="reg-label">
        <span>{label}</span>{required && <span className="req">required</span>}
      </label>
      <div style={{ display:"flex", alignItems:"baseline", gap: 16 }}>
        <div style={{ flex: "1 1 auto", minWidth: 0 }}>
          <DateDropdown
            placeholder={`Select… (${region})`}
            value={displayValue}
            options={table[region]}
            onChange={(v) => {
              // Reverse-lookup the chosen value's index in the current region
              // and emit the EU equivalent so storage stays canonical.
              const i = table[region].indexOf(v);
              onChange(i >= 0 ? table.EU[i] : "");
            }}
          />
        </div>
        <div className="reg-toggle" style={{ flex:"0 0 auto" }}>
          {["EU", "US", "UK"].map((r) => (
            <button
              key={r}
              type="button"
              data-on={region === r ? "1" : "0"}
              onClick={() => setRegion(r)}
            >{r}</button>
          ))}
        </div>
      </div>
      <div className="reg-help">
        {eu
          ? `EU ${table.EU[idx]} · US ${table.US[idx]} · UK ${table.UK[idx]}`
          : "The profile shows all three regions side by side."}
      </div>
      {error && <div className="reg-error">{error}</div>}
    </div>
  );
}

Object.assign(window, {
  RegText, RegDate, RegHeight, RegDropdown, RegMultiChip, RegRadio,
  RegTextArea, RegFileUpload, RegYesNoDetails,
  RegDateParts, RegSizeWithRegion,
});
