/* ================================================================
   paywall.jsx — Capital Economics publication paywall block.
   Replaces the body of a gated research article for a signed-out
   reader. Sits inside the existing article-page shell, so it owns
   only the content column: teaser → gate card → subordinate
   sign-in line. Header, breadcrumb, title, byline, sidebar and
   footer are NOT designed here (a muted stub stands in as context).

   States: default · invalid email · submitting · already registered.
   The validation message occupies a reserved row, so no state
   changes the block's height (no layout shift).

   Palette: CE navy (#24213a) rule + eyebrow, CE blue primary button
   and body type from the Sprint 1 system. No teal, no green.
================================================================ */
const { Button } = window.CapitalEconomicsDesignSystem_f2a5b2;
const { NS, SERIF } = window;
const { DesignCanvas, DCSection, DCArtboard } = window;

const EMAIL_RE = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;

/* ---- Icons (Lucide subset, 24×24, 2px stroke) ---- */
const PW_ICONS = {
  lock: <><rect width="18" height="11" x="3" y="11" rx="2" /><path d="M7 11V7a5 5 0 0 1 10 0v4" /></>,
  "arrow-right": <><path d="M5 12h14" /><path d="m12 5 7 7-7 7" /></>,
  "alert-circle": <><circle cx="12" cy="12" r="10" /><path d="M12 8v4M12 16h.01" /></>,
  info: <><circle cx="12" cy="12" r="10" /><path d="M12 16v-4M12 8h.01" /></>,
  loader: <path d="M12 2v4M12 18v4M4.93 4.93l2.83 2.83M16.24 16.24l2.83 2.83M2 12h4M18 12h4M4.93 19.07l2.83-2.83M16.24 7.76l2.83-2.83" />,
};
function PwIcon({ name, size = 20, stroke = 2, style, className }) {
  return (
    <svg className={className} style={style} width={size} height={size} viewBox="0 0 24 24" fill="none"
      stroke="currentColor" strokeWidth={stroke} strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
      {PW_ICONS[name]}
    </svg>
  );
}

/* One-time CSS for the pieces the DS components don't cover. */
let pwCSSInjected = false;
function injectPwCSS() {
  if (pwCSSInjected || typeof document === "undefined") return;
  pwCSSInjected = true;
  const css = `
  .pw-block { font-family: ${NS}; color: var(--text-primary); container-type: inline-size; }

  /* --- Teaser (article body continuing behind the gate) --- */
  .pw-teaser { position: relative; }
  .pw-standfirst { font-family: ${SERIF}; font-weight: 500; font-size: 22px; line-height: 1.45; letter-spacing: -0.01em; color: var(--text-primary); margin: 0 0 22px; }
  .pw-body { font-family: ${SERIF}; font-size: 18.5px; line-height: 1.72; color: var(--grey-700); margin: 0; }
  .pw-fade { -webkit-mask-image: linear-gradient(to bottom, #000 0, #000 45%, transparent 96%); mask-image: linear-gradient(to bottom, #000 0, #000 45%, transparent 96%); }

  /* --- Gate card --- */
  .pw-gate { position: relative; background: var(--surface-subtle); border: 1px solid var(--border-subtle); border-top: 3px solid var(--ce-navy); border-radius: var(--radius-md, 6px); padding: 32px 34px 26px; }
  .pw-eyebrow { display: inline-flex; align-items: center; gap: 8px; font-weight: 700; font-size: 11.5px; letter-spacing: 0.14em; text-transform: uppercase; color: var(--ce-navy); margin: 0 0 16px; }
  .pw-eyebrow svg { color: var(--ce-navy); }
  .pw-heading { font-family: ${SERIF}; font-weight: 600; font-size: 30px; line-height: 1.12; letter-spacing: -0.02em; color: var(--text-primary); margin: 0 0 10px; }
  .pw-support { font-size: 16.5px; line-height: 1.55; color: var(--text-secondary); margin: 0 0 24px; max-width: 46ch; }

  /* --- Form row: field 2/3 + button, aligned at the base --- */
  .pw-form { display: flex; align-items: flex-end; gap: 12px; }
  .pw-fieldcol { flex: 2 1 0; min-width: 0; }
  .pw-btncol { flex: 1 1 0; }
  .pw-label { display: block; font-weight: 600; font-size: 13px; color: var(--text-secondary); margin: 0 0 7px; }
  .pw-input { width: 100%; height: 50px; box-sizing: border-box; padding: 0 14px; font-family: ${NS}; font-size: 16px; color: var(--text-primary); background: var(--surface-card); border: 1px solid var(--border-default); border-radius: var(--radius-md, 6px); outline: 0; transition: border-color 140ms cubic-bezier(0.2,0,0,1), box-shadow 140ms cubic-bezier(0.2,0,0,1); }
  .pw-input::placeholder { color: var(--text-muted); }
  .pw-input:focus { border-color: var(--brand); box-shadow: var(--ring-focus, 0 0 0 3px rgba(74,102,179,0.28)); }
  .pw-input.pw-invalid { border-color: var(--negative-600); }
  .pw-input.pw-invalid:focus { box-shadow: 0 0 0 3px rgba(231,79,78,0.22); }
  .pw-btncol .ce-btn { width: 100%; height: 50px; }

  /* --- Reserved message row: fixed height => no layout shift --- */
  .pw-msg { min-height: 24px; margin: 9px 0 0; display: flex; align-items: flex-start; gap: 7px; font-size: 13.5px; line-height: 1.4; }
  .pw-msg-err { color: var(--negative-600); }
  .pw-msg-info { color: var(--text-secondary); }
  .pw-msg svg { flex: 0 0 auto; margin-top: 1px; }
  .pw-msg a { color: var(--text-link); font-weight: 700; text-decoration: none; }
  .pw-msg a:hover { text-decoration: underline; }

  /* --- Fine print --- */
  .pw-fine1 { font-size: 14px; font-weight: 600; color: var(--text-secondary); margin: 12px 0 0; }
  .pw-fine2 { font-size: 12.5px; color: var(--text-muted); margin: 5px 0 0; }
  .pw-fine2 a { color: var(--text-muted); text-decoration: underline; text-underline-offset: 2px; }
  .pw-fine2 a:hover { color: var(--text-secondary); }

  /* --- Proof row --- */
  .pw-proof { display: flex; flex-wrap: wrap; align-items: center; gap: 10px 18px; margin: 24px 0 0; padding: 20px 0 0; border-top: 1px solid var(--border-subtle); }
  .pw-proof-item { font-size: 13.5px; color: var(--text-secondary); }
  .pw-proof-item strong { color: var(--text-primary); font-weight: 700; }
  .pw-proof-div { width: 1px; height: 13px; background: var(--border-default); }

  /* --- Subordinate sign-in line --- */
  .pw-signin { text-align: center; font-size: 13.5px; color: var(--text-muted); margin: 20px 0 0; }
  .pw-signin a { color: var(--text-secondary); font-weight: 600; text-decoration: underline; text-underline-offset: 2px; }
  .pw-signin a:hover { color: var(--text-link); }

  /* --- Full trial form (Business email + name + country + company + phone) --- */
  .pw-field { margin: 0 0 15px; }
  .pw-field:last-of-type { margin-bottom: 0; }
  .pw-req { color: var(--negative-600); margin-left: 3px; font-weight: 700; }
  .pw-optional { color: var(--text-muted); font-weight: 500; margin-left: 5px; }
  .pw-selectwrap { position: relative; }
  .pw-selectwrap svg { position: absolute; right: 14px; top: 50%; transform: translateY(-50%); color: var(--text-muted); pointer-events: none; }
  .pw-select { width: 100%; height: 50px; box-sizing: border-box; padding: 0 40px 0 14px; font-family: ${NS}; font-size: 16px; color: var(--text-primary); background: var(--surface-card); border: 1px solid var(--border-default); border-radius: var(--radius-md, 6px); outline: 0; appearance: none; -webkit-appearance: none; cursor: pointer; transition: border-color 140ms cubic-bezier(0.2,0,0,1), box-shadow 140ms cubic-bezier(0.2,0,0,1); }
  .pw-select:focus { border-color: var(--brand); box-shadow: var(--ring-focus, 0 0 0 3px rgba(74,102,179,0.28)); }
  .pw-select[data-placeholder="true"] { color: var(--text-muted); }
  .pw-select.pw-invalid, .pw-input.pw-invalid { border-color: var(--negative-600); }
  .pw-fielderr { min-height: 17px; font-size: 12.5px; line-height: 1.35; color: var(--negative-600); margin-top: 5px; display: flex; align-items: flex-start; gap: 5px; }
  .pw-fielderr svg { flex: 0 0 auto; margin-top: 1px; }
  .pw-namegrid { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
  .pw-fullbtn { margin-top: 20px; }
  .pw-fullbtn .ce-btn { width: 100%; height: 52px; }
  .pw-formmsg { min-height: 24px; margin: 10px 0 0; display: flex; align-items: flex-start; gap: 7px; font-size: 13.5px; line-height: 1.4; }
  .pw-formmsg svg { flex: 0 0 auto; margin-top: 1px; }
  .pw-formmsg-ok { color: var(--text-secondary); }
  .pw-formmsg-ok strong { color: var(--text-primary); }
  .pw-formmsg a { color: var(--text-link); font-weight: 700; text-decoration: none; }
  .pw-formmsg a:hover { text-decoration: underline; }

  .pw-spin { animation: pwspin 0.7s linear infinite; }
  @keyframes pwspin { to { transform: rotate(360deg); } }

  /* --- Mobile: field + button stack, proof row wraps to two lines.
     Container query (not viewport) so it fires inside the 375px artboard. --- */
  @container (max-width: 540px) {
    .pw-gate { padding: 26px 22px 22px; }
    .pw-heading { font-size: 25px; }
    .pw-standfirst { font-size: 19px; }
    .pw-body { font-size: 17px; }
    .pw-form { flex-direction: column; align-items: stretch; gap: 14px; }
    .pw-btncol { flex: none; }
    .pw-namegrid { grid-template-columns: 1fr; gap: 0; }
  }
  `;
  const el = document.createElement("style");
  el.setAttribute("data-ce", "paywall");
  el.textContent = css;
  document.head.appendChild(el);
}

/* ---- Muted article context (NOT part of this block's design) ----
   A greyed title/byline stub so the teaser + gate read in situ. */
function ArticleContext() {
  return (
    <div style={{ opacity: 0.9, marginBottom: 30 }}>
      <div style={{ fontWeight: 700, fontSize: 11, letterSpacing: "0.14em", textTransform: "uppercase", color: "var(--text-muted)", marginBottom: 14 }}>
        Global Economics · Monetary Policy
      </div>
      <h1 style={{ fontFamily: SERIF, fontWeight: 600, fontSize: 34, lineHeight: 1.16, letterSpacing: "-0.02em", color: "var(--text-primary)", margin: "0 0 16px" }}>
        The hiking cycle is over, but cuts will come slowly
      </h1>
      <div style={{ fontSize: 14, color: "var(--text-muted)", display: "flex", flexWrap: "wrap", gap: "4px 10px", alignItems: "center" }}>
        <span style={{ color: "var(--text-secondary)", fontWeight: 600 }}>Neil Shearing</span>
        <span>·</span><span>Group Chief Economist</span>
        <span>·</span><span>12 August 2026</span>
        <span>·</span><span>6 min read</span>
      </div>
    </div>
  );
}

const PROOF = [
  <span key="c"><strong>1,500+</strong> institutional clients</span>,
  <span key="e"><strong>70+</strong> economists</span>,
  <span key="y">Independent since <strong>1999</strong></span>,
];

const COUNTRIES = [
  "United Kingdom", "United States", "Canada", "Ireland", "France", "Germany", "Netherlands",
  "Switzerland", "Spain", "Italy", "Sweden", "Norway", "Denmark", "Luxembourg",
  "United Arab Emirates", "Saudi Arabia", "Qatar", "Singapore", "Hong Kong SAR", "Japan",
  "Australia", "New Zealand", "South Africa", "Other",
];

/* ---- One field: label (+ required/optional marker), control, and a
   reserved error line so validation never shifts the form. ---- */
function PwField({ id, label, required, optional, error, children }) {
  return (
    <div className="pw-field">
      <label className="pw-label" htmlFor={id}>
        {label}
        {required && <span className="pw-req" aria-hidden="true">*</span>}
        {optional && <span className="pw-optional">(optional)</span>}
      </label>
      {children}
      <div className="pw-fielderr" aria-live="polite">
        {error && <><PwIcon name="alert-circle" size={13} />{error}</>}
      </div>
    </div>
  );
}

/* ================================================================
   FullTrialForm — the complete trial-request form used on the live
   article page: Business email, First/Last name, Country, Company
   (all required) and Telephone (optional). Validates required
   fields + email format on submit and on blur once touched; each
   field carries a reserved error line (no layout shift). On a valid
   submit it enters the loading state, then confirms.
================================================================ */
const REQUIRED_MSG = {
  email: "Enter your business email address.",
  first: "Enter your first name.",
  last: "Enter your last name.",
  country: "Select your country.",
  company: "Enter your company name.",
};
function FullTrialForm({ live = false }) {
  const [v, setV] = React.useState({ email: "", first: "", last: "", country: "", company: "", phone: "" });
  const [errs, setErrs] = React.useState({});
  const [loading, setLoading] = React.useState(false);
  const [done, setDone] = React.useState(false);
  const [submitted, setSubmitted] = React.useState(false);

  const fieldError = (k, val) => {
    const t = (val || "").trim();
    if (k === "phone") return "";
    if (!t) return REQUIRED_MSG[k];
    if (k === "email" && !EMAIL_RE.test(t)) return "Enter a valid business email address.";
    return "";
  };
  const set = (k) => (e) => {
    const val = e.target.value;
    setV((s) => ({ ...s, [k]: val }));
    if (submitted) setErrs((s) => ({ ...s, [k]: fieldError(k, val) }));
  };
  const validateAll = () => {
    const next = {};
    ["email", "first", "last", "country", "company"].forEach((k) => {
      const e = fieldError(k, v[k]); if (e) next[k] = e;
    });
    setErrs(next);
    return Object.keys(next).length === 0;
  };
  const onSubmit = (e) => {
    e.preventDefault();
    setSubmitted(true);
    setDone(false);
    if (!validateAll()) return;
    setLoading(true);
    setTimeout(() => { setLoading(false); setDone(true); }, 1600);
  };
  const onBlur = (k) => () => { if (submitted) setErrs((s) => ({ ...s, [k]: fieldError(k, v[k]) })); };

  return (
    <form onSubmit={onSubmit} noValidate>
      <PwField id="pw-f-email" label="Business email" required error={errs.email}>
        <input id="pw-f-email" className={"pw-input" + (errs.email ? " pw-invalid" : "")}
          type="email" name="email" inputMode="email" autoComplete="email" placeholder="you@firm.com"
          value={v.email} aria-invalid={!!errs.email} autoFocus={live}
          onChange={set("email")} onBlur={onBlur("email")} />
      </PwField>

      <div className="pw-namegrid">
        <PwField id="pw-f-first" label="First name" required error={errs.first}>
          <input id="pw-f-first" className={"pw-input" + (errs.first ? " pw-invalid" : "")}
            type="text" name="given-name" autoComplete="given-name"
            value={v.first} aria-invalid={!!errs.first} onChange={set("first")} onBlur={onBlur("first")} />
        </PwField>
        <PwField id="pw-f-last" label="Last name" required error={errs.last}>
          <input id="pw-f-last" className={"pw-input" + (errs.last ? " pw-invalid" : "")}
            type="text" name="family-name" autoComplete="family-name"
            value={v.last} aria-invalid={!!errs.last} onChange={set("last")} onBlur={onBlur("last")} />
        </PwField>
      </div>

      <PwField id="pw-f-country" label="Country" required error={errs.country}>
        <div className="pw-selectwrap">
          <select id="pw-f-country" className={"pw-select" + (errs.country ? " pw-invalid" : "")}
            name="country" autoComplete="country-name" value={v.country}
            data-placeholder={v.country ? "false" : "true"} aria-invalid={!!errs.country}
            onChange={set("country")} onBlur={onBlur("country")}>
            <option value="">- Select a value -</option>
            {COUNTRIES.map((c) => <option key={c} value={c}>{c}</option>)}
          </select>
          <PwIcon name="chevron-down" size={18} />
        </div>
      </PwField>

      <PwField id="pw-f-company" label="Company name" required error={errs.company}>
        <input id="pw-f-company" className={"pw-input" + (errs.company ? " pw-invalid" : "")}
          type="text" name="organization" autoComplete="organization"
          value={v.company} aria-invalid={!!errs.company} onChange={set("company")} onBlur={onBlur("company")} />
      </PwField>

      <PwField id="pw-f-phone" label="Telephone" optional error={undefined}>
        <input id="pw-f-phone" className="pw-input" type="tel" name="tel" autoComplete="tel"
          value={v.phone} onChange={set("phone")} />
      </PwField>

      <div className="pw-fullbtn">
        <Button type="submit" variant="primary" size="lg" disabled={loading}
          iconEnd={loading ? <PwIcon name="loader" size={18} className="pw-spin" /> : <PwIcon name="arrow-right" size={18} />}>
          {loading ? "Starting…" : "Start free trial"}
        </Button>
      </div>

      <div className="pw-formmsg" role="status" aria-live="polite">
        {done && (
          <span className="pw-formmsg-ok" style={{ display: "inline-flex", gap: 7, alignItems: "flex-start" }}>
            <PwIcon name="info" size={15} style={{ color: "var(--ce-blue)" }} />
            <span><strong>Trial started.</strong> Check your inbox to confirm your email, then this piece unlocks straight away.</span>
          </span>
        )}
      </div>
    </form>
  );
}

/* ================================================================
   PaywallBlock — `state` drives the four designed states. The
   `default` artboard runs live (real blur validation + submit).
   `fullForm` swaps the single-field CTA for the complete trial
   request (Business email + name + country + company + phone).
================================================================ */
function PaywallBlock({ state = "default", live = false, showContext = true, fullForm = false }) {
  const [email, setEmail] = React.useState(state === "invalid" ? "trader@" : state === "registered" ? "j.okafor@meridiancap.com" : "");
  const [err, setErr] = React.useState(state === "invalid" ? "Enter a valid business email address." : "");
  const [registered, setRegistered] = React.useState(state === "registered");
  const [loading, setLoading] = React.useState(state === "submitting");
  const [touched, setTouched] = React.useState(false);

  const validate = () => {
    const v = email.trim();
    if (!v) { setErr("Enter your business email address."); return false; }
    if (!EMAIL_RE.test(v)) { setErr("Enter a valid business email address."); return false; }
    setErr(""); return true;
  };
  const onSubmit = (e) => {
    e.preventDefault();
    setTouched(true);
    setRegistered(false);
    if (!validate()) return;
    setLoading(true);
    // Demo: an "existing" address routes to sign-in; otherwise it "starts".
    setTimeout(() => {
      setLoading(false);
      if (/@meridiancap\.com$/i.test(email.trim())) setRegistered(true);
    }, 1600);
  };

  const invalid = !!err;

  return (
    <div className="pw-block">
      {showContext && <ArticleContext />}

      {/* 1 — Teaser: standfirst + opening sentences, fading out */}
      <div className="pw-teaser pw-fade" aria-hidden="false">
        <p className="pw-standfirst">
          Markets have moved on from the question of whether central banks are done tightening. The debate now
          is about the pace of the descent — and here the consensus is too aggressive.
        </p>
        <p className="pw-body">
          The hiking cycle that defined 2022 and 2023 is firmly behind us. Every major central bank we cover has
          either paused or begun to ease, and the incoming data support that shift: core inflation is drifting back
          towards target across the advanced economies, and labour markets, while still tight, are loosening at the
          margin. But the market has run ahead of itself. Pricing implies four cuts from the Fed over the next twelve
          months; we expect one further cut this year and a slower path thereafter, because the last leg of
          disinflation is proving stickier than the headline numbers suggest.
        </p>
      </div>

      {/* 2 — Gate card */}
      <div className="pw-gate" style={{ marginTop: -8 }}>
        <div className="pw-eyebrow">
          <PwIcon name="lock" size={14} stroke={2.2} />
          Subscriber content
        </div>
        <h2 className="pw-heading">Read this in full, free</h2>
        <p className="pw-support">
          Start a free trial and use one of 10 starter credits to unlock this piece.
        </p>

        {fullForm ? <FullTrialForm live={live} /> : (
        <form onSubmit={onSubmit} noValidate>
          <div className="pw-form">
            <div className="pw-fieldcol">
              <label className="pw-label" htmlFor={"pw-email-" + state}>Business email</label>
              <input
                id={"pw-email-" + state}
                className={"pw-input" + (invalid ? " pw-invalid" : "")}
                type="email" name="email" inputMode="email" autoComplete="email"
                placeholder="you@firm.com" value={email}
                aria-invalid={invalid} aria-describedby={"pw-msg-" + state}
                autoFocus={live}
                onChange={(e) => { setEmail(e.target.value); setTouched(true); if (err) setErr(""); }}
                onBlur={() => { if (touched) validate(); }}
              />
            </div>
            <div className="pw-btncol">
              <Button type="submit" variant="primary" size="lg" disabled={loading}
                iconEnd={loading ? <PwIcon name="loader" size={18} className="pw-spin" /> : <PwIcon name="arrow-right" size={18} />}>
                {loading ? "Starting…" : "Start free trial"}
              </Button>
            </div>
          </div>

          {/* Reserved message row — fixed height, no layout shift */}
          <div className="pw-msg" id={"pw-msg-" + state} role={invalid ? "alert" : "status"} aria-live="polite">
            {invalid ? (
              <span className="pw-msg-err" style={{ display: "inline-flex", gap: 7, alignItems: "flex-start" }}>
                <PwIcon name="alert-circle" size={15} />{err}
              </span>
            ) : registered ? (
              <span className="pw-msg-info" style={{ display: "inline-flex", gap: 7, alignItems: "flex-start" }}>
                <PwIcon name="info" size={15} />
                <span>This email already has an account. <a href="#signin">Sign in to read this</a> — we'll bring you straight back.</span>
              </span>
            ) : null}
          </div>
        </form>
        )}

        <p className="pw-fine1">Free. 10 articles. No card required.</p>
        <p className="pw-fine2">
          By continuing you agree to our <a href="#terms">Terms</a> and <a href="#privacy">Privacy Policy</a>.
        </p>

        {/* Proof row */}
        <div className="pw-proof">
          {PROOF.map((item, i) => (
            <React.Fragment key={i}>
              {i > 0 && <span className="pw-proof-div" aria-hidden="true" />}
              <span className="pw-proof-item">{item}</span>
            </React.Fragment>
          ))}
        </div>
      </div>

      {/* 3 — Subordinate sign-in line */}
      <p className="pw-signin">
        Already a client or trialist? <a href="#signin">Sign in to read this</a>
      </p>
    </div>
  );
}

/* ---- Article-column frame: paywall on the page surface at the
   width of the article content column. ---- */
function ArtColumn({ state, live = false, width = 720 }) {
  return (
    <div style={{ background: "var(--surface-page)", padding: "40px 40px 44px", minHeight: "100%" }}>
      <div style={{ maxWidth: width, margin: "0 auto" }}>
        <PaywallBlock state={state} live={live} />
      </div>
    </div>
  );
}
function MobileColumn({ state, width = 375 }) {
  return (
    <div style={{ background: "var(--surface-page)", padding: "24px 18px 30px", minHeight: "100%" }}>
      <PaywallBlock state={state} />
    </div>
  );
}

Object.assign(window, { PaywallBlock, injectPwCSS });

function App() {
  injectPwCSS();
  return (
    <DesignCanvas>
      <DCSection id="desktop" title="Publication paywall — desktop" subtitle="At article-column width. Teaser fades into the gate card; sign-in stays subordinate below.">
        <DCArtboard id="d-default" label="Default (live — try the field)" width={800} height={1120}>
          <ArtColumn state="default" live />
        </DCArtboard>
        <DCArtboard id="d-invalid" label="Invalid email" width={800} height={1120}>
          <ArtColumn state="invalid" />
        </DCArtboard>
        <DCArtboard id="d-submitting" label="Submitting" width={800} height={1120}>
          <ArtColumn state="submitting" />
        </DCArtboard>
        <DCArtboard id="d-registered" label="Email already registered" width={800} height={1120}>
          <ArtColumn state="registered" />
        </DCArtboard>
      </DCSection>

      <DCSection id="mobile" title="375px mobile" subtitle="Field and button stack full width; proof row wraps to two lines.">
        <DCArtboard id="m-default" label="Default" width={375} height={1440}>
          <MobileColumn state="default" />
        </DCArtboard>
        <DCArtboard id="m-invalid" label="Invalid email" width={375} height={1440}>
          <MobileColumn state="invalid" />
        </DCArtboard>
        <DCArtboard id="m-registered" label="Already registered" width={375} height={1460}>
          <MobileColumn state="registered" />
        </DCArtboard>
      </DCSection>
    </DesignCanvas>
  );
}

if (!window.__PW_LIB_ONLY) {
  ReactDOM.createRoot(document.getElementById("root")).render(<App />);
}
