/* ================================================================
   credit-paywall.jsx — Capital Economics credit paywall block.
   Sibling to the signed-out publication paywall (paywall.jsx): same
   teaser → gate family, same tokens, navy rule + blue-50 tint, blue
   primary button. Shown to a SIGNED-IN trialist who hits a piece
   they have not unlocked. The one job is: spend a credit and read.

   States on the canvas:
     A  Credits remaining (7/10) — live: Spend → loading → unlocked
     A  Spend loading (static)
     B  Running low (2/10) — balance emphasised, full-access promoted
     C  Credits exhausted (0/10) — spent notice + full-access primary
     C  Full access submitted (static)
     D  Trial expired — expiry notice + full-access primary
     •  Post-unlock: confirmation bar atop the now-visible article

   No teal, no green, no gamified meter, no confirmation modal.
================================================================ */
const { Button } = window.CapitalEconomicsDesignSystem_f2a5b2;
const { NS, SERIF } = window;
const { DesignCanvas, DCSection, DCArtboard } = window;

const CP_ICONS = {
  "arrow-right": <><path d="M5 12h14" /><path d="m12 5 7 7-7 7" /></>,
  check: <path d="M20 6 9 17l-5-5" />,
  "check-circle": <><path d="M22 11.08V12a10 10 0 1 1-5.93-9.14" /><path d="m9 11 3 3L22 4" /></>,
  clock: <><circle cx="12" cy="12" r="10" /><path d="M12 6v6l4 2" /></>,
  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 CpIcon({ 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">
      {CP_ICONS[name]}
    </svg>
  );
}

let cpCSSInjected = false;
function injectCpCSS() {
  if (cpCSSInjected || typeof document === "undefined") return;
  cpCSSInjected = true;
  const css = `
  .cp-block { font-family: ${NS}; color: var(--text-primary); container-type: inline-size; }

  /* --- Teaser (shared with the signed-out block) --- */
  .cp-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 12px; }
  .cp-meta { font-family: ${NS}; font-size: 13px; color: var(--text-muted); letter-spacing: 0.01em; margin: 0 0 22px; display: flex; align-items: center; gap: 8px; }
  .cp-meta .cp-dot-sep { width: 3px; height: 3px; border-radius: 50%; background: var(--border-strong); }
  .cp-body { font-family: ${SERIF}; font-size: 18.5px; line-height: 1.72; color: var(--grey-700); margin: 0; }
  .cp-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%); }

  /* --- Credit balance indicator --- */
  .cp-balance { display: flex; align-items: center; gap: 13px; flex-wrap: wrap; margin: 0 0 20px; }
  .cp-dots { display: inline-flex; gap: 5px; align-items: center; }
  .cp-dot { width: 9px; height: 9px; border-radius: 50%; }
  .cp-dot--on { background: var(--ce-navy); }
  .cp-dot--off { background: transparent; box-shadow: inset 0 0 0 1.6px var(--border-strong); }
  .cp-balance-text { font-size: 13.5px; font-weight: 600; color: var(--text-secondary); }
  .cp-balance-text strong { color: var(--ce-navy); font-weight: 700; }
  .cp-balance--low .cp-balance-text { color: var(--ce-navy); font-weight: 700; }
  .cp-balance--low .cp-dot--on { background: var(--ce-blue); }

  /* --- Unlock card (states A/B) --- */
  .cp-card { 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: 30px 34px 28px; }
  .cp-heading { font-family: ${SERIF}; font-weight: 600; font-size: 29px; line-height: 1.14; letter-spacing: -0.02em; color: var(--text-primary); margin: 0 0 9px; }
  .cp-support { font-size: 16.5px; line-height: 1.55; color: var(--text-secondary); margin: 0 0 24px; max-width: 48ch; }
  .cp-actionwrap { text-align: center; margin: 4px 0 0; }
  .cp-actionwrap .ce-btn { min-width: 300px; height: 54px; font-size: 16.5px; }
  .cp-clock { text-align: center; font-size: 13px; color: var(--text-muted); margin: 15px 0 0; display: flex; align-items: center; justify-content: center; gap: 7px; }
  .cp-clock svg { color: var(--text-muted); }

  /* --- Secondary full-access line (A: text link, B: outline button) --- */
  .cp-secondary { text-align: center; font-size: 13.5px; color: var(--text-muted); margin: 20px 0 0; }
  .cp-secondary a { color: var(--text-secondary); font-weight: 700; text-decoration: none; }
  .cp-secondary a:hover { color: var(--text-link); text-decoration: underline; }
  .cp-secondary-btn { display: flex; flex-direction: column; align-items: center; gap: 9px; margin: 22px 0 0; }
  .cp-secondary-btn span { font-size: 13.5px; color: var(--text-secondary); }

  /* --- Spent / expired notice (states C/D) — quiet, not a card --- */
  .cp-notice { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; padding: 16px 2px; margin: 0 0 22px; border-top: 1px solid var(--border-subtle); border-bottom: 1px solid var(--border-subtle); font-size: 13.5px; color: var(--text-muted); }
  .cp-notice .cp-dot--off { box-shadow: inset 0 0 0 1.6px var(--border-default); }
  .cp-notice-text { color: var(--text-secondary); font-weight: 600; }
  .cp-notice a { color: var(--text-secondary); font-weight: 600; text-decoration: underline; text-underline-offset: 2px; }
  .cp-notice a:hover { color: var(--text-link); }
  .cp-notice svg { color: var(--text-muted); flex: 0 0 auto; }

  /* --- Full-access card (states C/D, now primary) --- */
  .cp-facard { 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 30px; }
  .cp-label { display: block; font-weight: 600; font-size: 13px; color: var(--text-secondary); margin: 0 0 7px; }
  .cp-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); }
  .cp-input::placeholder { color: var(--text-muted); }
  .cp-input:focus { border-color: var(--brand); box-shadow: var(--ring-focus, 0 0 0 3px rgba(74,102,179,0.28)); }
  .cp-fafield { margin: 0 0 20px; }
  .cp-fabtn .ce-btn { width: 100%; height: 52px; }
  .cp-reassure { font-size: 13px; color: var(--text-muted); margin: 14px 0 0; text-align: center; }

  /* --- Full-access submitted confirmation (in place) --- */
  .cp-done { text-align: center; padding: 6px 0 2px; }
  .cp-done-mark { width: 46px; height: 46px; border-radius: 50%; background: var(--brand-subtle); color: var(--ce-blue); display: inline-flex; align-items: center; justify-content: center; margin: 0 auto 16px; }
  .cp-done h3 { font-family: ${SERIF}; font-weight: 600; font-size: 24px; line-height: 1.16; letter-spacing: -0.015em; color: var(--text-primary); margin: 0 0 10px; }
  .cp-done p { font-size: 15px; line-height: 1.55; color: var(--text-secondary); margin: 0 auto; max-width: 44ch; }

  /* --- Post-unlock: confirmation bar atop the article --- */
  .cp-unlockbar { display: flex; align-items: center; gap: 10px; background: var(--surface-subtle); border: 1px solid var(--border-subtle); border-left: 3px solid var(--ce-blue); border-radius: var(--radius-md, 6px); padding: 12px 16px; font-size: 14px; color: var(--text-secondary); margin: 0 0 30px; }
  .cp-unlockbar strong { color: var(--text-primary); font-weight: 700; }
  .cp-unlockbar svg { color: var(--ce-blue); flex: 0 0 auto; }
  .cp-article p { font-family: ${SERIF}; font-size: 18.5px; line-height: 1.72; color: var(--grey-700); margin: 0 0 20px; }

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

  /* --- Mobile (container query, fires inside the 375px artboard) --- */
  @container (max-width: 540px) {
    .cp-card, .cp-facard { padding: 26px 22px 24px; }
    .cp-heading { font-size: 25px; }
    .cp-standfirst { font-size: 19px; }
    .cp-body, .cp-article p { font-size: 17px; }
    .cp-balance { flex-direction: column; align-items: flex-start; gap: 9px; }
    .cp-actionwrap .ce-btn { min-width: 0; width: 100%; }
  }
  `;
  const el = document.createElement("style");
  el.setAttribute("data-ce", "credit-paywall");
  el.textContent = css;
  document.head.appendChild(el);
}

/* ---- Credit dots: ten small dots, filled for remaining ---- */
function CreditDots({ remaining, total = 10 }) {
  return (
    <span className="cp-dots" role="img" aria-label={remaining + " of " + total + " credits remaining"}>
      {Array.from({ length: total }).map((_, i) => (
        <span key={i} className={"cp-dot " + (i < remaining ? "cp-dot--on" : "cp-dot--off")} />
      ))}
    </span>
  );
}

/* ---- Teaser: standfirst + metadata + opening sentences, fading ---- */
function Teaser() {
  return (
    <div className="cp-teaser cp-fade">
      <p className="cp-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="cp-meta">
        <span>12 min read</span><span className="cp-dot-sep" aria-hidden="true" /><span>4 charts</span>
      </p>
      <p className="cp-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, and the last leg of disinflation is proving
        stickier than the headline numbers suggest.
      </p>
    </div>
  );
}

const TRIAL_END = "21 August";

/* ---- Unlock card (states A & B) ---- */
function UnlockCard({ remaining, low, loading, onSpend }) {
  return (
    <div className="cp-card">
      <div className={"cp-balance" + (low ? " cp-balance--low" : "")}>
        <CreditDots remaining={remaining} />
        <span className="cp-balance-text"><strong>{remaining}</strong> of 10 credits remaining</span>
      </div>
      <h2 className="cp-heading">Unlock this publication</h2>
      <p className="cp-support">Costs 1 credit. Yours to read for the rest of your trial.</p>
      <div className="cp-actionwrap">
        <Button variant="primary" size="lg" disabled={loading} onClick={onSpend}
          iconEnd={loading ? <CpIcon name="loader" size={18} className="cp-spin" /> : <CpIcon name="arrow-right" size={18} />}>
          {loading ? "Unlocking…" : "Spend 1 credit and read"}
        </Button>
      </div>
      <p className="cp-clock"><CpIcon name="clock" size={14} />Trial ends {TRIAL_END}</p>
    </div>
  );
}

/* ---- Full-access card (states C & D) ---- */
function FullAccessCard({ submitted, onSubmit }) {
  const [regions, setRegions] = React.useState("");
  const [loading, setLoading] = React.useState(false);
  const [done, setDone] = React.useState(!!submitted);
  const submit = (e) => {
    e.preventDefault();
    setLoading(true);
    setTimeout(() => { setLoading(false); setDone(true); }, 1500);
  };
  if (done) {
    return (
      <div className="cp-facard">
        <div className="cp-done">
          <span className="cp-done-mark"><CpIcon name="check" size={22} stroke={2.4} /></span>
          <h3>Request received</h3>
          <p>A member of our team will be in touch within one working day to set up your full access.</p>
        </div>
      </div>
    );
  }
  return (
    <div className="cp-facard">
      <h2 className="cp-heading">Read everything, without limits</h2>
      <p className="cp-support">
        A full trial gives you unrestricted access to all Capital Economics analysis, data and forecasts, with
        alerts on.
      </p>
      <form onSubmit={submit} noValidate>
        <div className="cp-fafield">
          <label className="cp-label" htmlFor="cp-regions">Which regions or asset classes do you need? (optional)</label>
          <input id="cp-regions" className="cp-input" type="text" name="regions"
            placeholder="e.g. US rates, China, EM FX" value={regions} onChange={(e) => setRegions(e.target.value)} />
        </div>
        <div className="cp-fabtn">
          <Button type="submit" variant="primary" size="lg" disabled={loading}
            iconEnd={loading ? <CpIcon name="loader" size={18} className="cp-spin" /> : <CpIcon name="arrow-right" size={18} />}>
            {loading ? "Sending…" : "Request full access"}
          </Button>
        </div>
      </form>
      <p className="cp-reassure">A member of our team will be in touch within one working day.</p>
    </div>
  );
}

/* ---- Post-unlock: confirmation bar + the now-visible article ---- */
function UnlockedArticle({ remaining }) {
  return (
    <div className="cp-block">
      <div className="cp-unlockbar" role="status">
        <CpIcon name="check-circle" size={18} />
        <span><strong>Unlocked.</strong> {remaining} of 10 credits remaining.</span>
      </div>
      <div className="cp-article">
        <p style={{ fontWeight: 500, fontSize: 22, lineHeight: 1.45, color: "var(--text-primary)" }}>
          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>
          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.
        </p>
        <p>
          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>
    </div>
  );
}

/* ================================================================
   CreditPaywall — variant drives the state; `live` A runs the real
   spend → loading → unlock flow. `demo` forces a static micro-state.
================================================================ */
const VARIANTS = {
  A: { remaining: 7, low: false, kind: "unlock" },
  B: { remaining: 2, low: true, kind: "unlock" },
  C: { remaining: 0, low: false, kind: "full", notice: "credits" },
  D: { remaining: 6, low: false, kind: "full", notice: "expired" },
};
function CreditPaywall({ variant = "A", live = false, demo = null }) {
  const cfg = VARIANTS[variant];
  const [loading, setLoading] = React.useState(demo === "loading");
  const [unlocked, setUnlocked] = React.useState(demo === "unlocked");
  const [faOpen, setFaOpen] = React.useState(false);

  const onSpend = () => {
    setLoading(true);
    setTimeout(() => { setLoading(false); setUnlocked(true); }, 1500);
  };

  if (unlocked) return <UnlockedArticle remaining={cfg.remaining - 1} />;

  return (
    <div className="cp-block">
      <Teaser />

      {cfg.kind === "unlock" ? (
        <>
          <div className="cp-card-wrap" style={{ marginTop: -6 }}>
            <UnlockCard remaining={cfg.remaining} low={cfg.low} loading={loading} onSpend={live ? onSpend : undefined} />
          </div>
          {!faOpen && (cfg.low ? (
            <div className="cp-secondary-btn">
              <span>Need unlimited access?</span>
              <Button variant="secondary" size="md" onClick={() => setFaOpen(true)} iconEnd={<CpIcon name="arrow-right" size={16} />}>Request full access</Button>
            </div>
          ) : (
            <p className="cp-secondary">
              Need unlimited access? <a href="#full-access" onClick={(e) => { e.preventDefault(); setFaOpen(true); }}>Request full access</a>
            </p>
          ))}
          {faOpen && (
            <div style={{ marginTop: 22 }}>
              <FullAccessCard />
            </div>
          )}
        </>
      ) : (
        <>
          <div className="cp-notice" style={{ marginTop: -6 }} role="status">
            {cfg.notice === "expired" ? (
              <>
                <CpIcon name="clock" size={16} />
                <span className="cp-notice-text">Your trial ended on {TRIAL_END}.</span>
                <a href="#unlocked">You can still read the publications you unlocked</a>
              </>
            ) : (
              <>
                <CreditDots remaining={0} />
                <span className="cp-notice-text">All 10 trial credits used.</span>
                <a href="#unlocked">You can still read the 10 publications you unlocked</a>
              </>
            )}
          </div>
          <FullAccessCard submitted={demo === "submitted"} />
        </>
      )}
    </div>
  );
}

/* ---- Frames ---- */
function DeskCol({ variant, live, demo, width = 720 }) {
  return (
    <div style={{ background: "var(--surface-page)", padding: "40px 40px 44px", minHeight: "100%" }}>
      <div style={{ maxWidth: width, margin: "0 auto" }}>
        <CreditPaywall variant={variant} live={live} demo={demo} />
      </div>
    </div>
  );
}
function MobCol({ variant, demo }) {
  return (
    <div style={{ background: "var(--surface-page)", padding: "24px 18px 30px", minHeight: "100%" }}>
      <CreditPaywall variant={variant} demo={demo} />
    </div>
  );
}

function App() {
  injectCpCSS();
  return (
    <DesignCanvas>
      <DCSection id="desktop" title="Credit paywall — signed-in trialist (desktop)" subtitle="Sibling of the signed-out paywall. Spend a credit and read is the single visual centre. Full access stays subordinate until credits run out.">
        <DCArtboard id="a" label="A · Credits remaining (live — spend to unlock)" width={800} height={940}>
          <DeskCol variant="A" live />
        </DCArtboard>
        <DCArtboard id="a-load" label="A · Spend button loading" width={800} height={940}>
          <DeskCol variant="A" demo="loading" />
        </DCArtboard>
        <DCArtboard id="b" label="B · Running low (2 of 10)" width={800} height={980}>
          <DeskCol variant="B" />
        </DCArtboard>
        <DCArtboard id="c" label="C · Credits exhausted" width={800} height={1060}>
          <DeskCol variant="C" />
        </DCArtboard>
        <DCArtboard id="c-done" label="C · Full access request submitted" width={800} height={900}>
          <DeskCol variant="C" demo="submitted" />
        </DCArtboard>
        <DCArtboard id="d" label="D · Trial expired" width={800} height={1040}>
          <DeskCol variant="D" />
        </DCArtboard>
        <DCArtboard id="unlocked" label="Post-unlock · confirmation atop the article" width={800} height={620}>
          <DeskCol variant="A" demo="unlocked" />
        </DCArtboard>
      </DCSection>

      <DCSection id="mobile" title="375px mobile" subtitle="Credit dots and balance text stack; primary button goes full width.">
        <DCArtboard id="m-a" label="A · Credits remaining" width={375} height={1000}>
          <MobCol variant="A" />
        </DCArtboard>
        <DCArtboard id="m-c" label="C · Credits exhausted" width={375} height={1200}>
          <MobCol variant="C" />
        </DCArtboard>
      </DCSection>
    </DesignCanvas>
  );
}

Object.assign(window, { CreditPaywall, injectCpCSS });

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