> ## Documentation Index
> Fetch the complete documentation index at: https://docs.supercycle.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Consignor customer accounts

> What a consignor sees about their balance, earnings, and payouts in their account

export const customerAccountConsignmentScope = () => ({
  AccountCard,
  AccountConTile,
  AccountH2,
  AccountSub,
  RenderWindow
});

export const AccountConsignment = () => {
  const {AccountCard, AccountConTile, AccountH2, AccountSub, RenderWindow} = customerAccountConsignmentScope();
  const money = n => (n < 0 ? "-" : "") + "£" + Math.abs(n).toFixed(2);
  const earned = ACCOUNT_CON_ACTIVITY.filter(a => a.type !== "Payout").reduce((s, a) => s + a.amount, 0);
  const paid = -ACCOUNT_CON_ACTIVITY.filter(a => a.type === "Payout").reduce((s, a) => s + a.amount, 0);
  return <RenderWindow label="Consignment page in customer accounts" url="shopify.com/account/pages/consignment" designWidth={1168} gutter={40} background="#f4f4f4">
      <div className="sc-acct-con">
        <style>{ACCOUNT_CON_CSS}</style>
        <div className="sc-acct-con-header" aria-hidden="true"><span className="sc-acct-con-brand">Supercycle Demo</span><span className="sc-acct-con-avatar">B</span></div>
        <div className="sc-acct-con-shell">
          <nav className="sc-acct-con-nav" aria-hidden="true"><span data-active="">Dashboard</span><span>Orders</span><span>Back to Shop</span><span>Profile</span></nav>
          <div className="sc-acct-con-body">
            <div className="sc-acct-con-title">Consignment</div>
            <div className="sc-acct-con-tiles">
              <AccountConTile label="Balance owed" value={money(earned - paid)} />
              <AccountConTile label="Total earned" value={money(earned)} />
              <AccountConTile label="Consigned items" value={ACCOUNT_CON_ITEMS.length} />
              <AccountConTile label="Total paid out" value={money(paid)} />
            </div>
            <AccountCard gap={8}>
              <AccountH2>Recent activity</AccountH2>
              <div>
                {ACCOUNT_CON_ACTIVITY.map((a, i) => <div key={i} className="sc-acct-con-activity">
                    <div>{a.type}</div>
                    <span className={"sc-acct-con-amount " + (a.amount < 0 ? "sc-acct-con-amount--minus" : "sc-acct-con-amount--plus")}>{a.amount < 0 ? money(a.amount) : "+" + money(a.amount)}</span>
                    <AccountSub>{a.detail}</AccountSub>
                    <span />
                  </div>)}
              </div>
            </AccountCard>
            <AccountCard gap={8}>
              <AccountH2>My items</AccountH2>
              <div>
                {ACCOUNT_CON_ITEMS.map(it => <div key={it.serial} className="sc-acct-con-item">
                    <div style={{
    display: "grid",
    gap: 2
  }}><div style={{
    fontWeight: 600
  }}>{it.title}</div><AccountSub>Rentals completed: {it.completed} · Commission: {it.commission}%</AccountSub></div>
                    <AccountSub>{it.serial}</AccountSub>
                  </div>)}
              </div>
            </AccountCard>
          </div>
        </div>
        <div className="sc-acct-con-footer" aria-hidden="true"><span>Cookie preferences</span><span>Privacy policy</span></div>
      </div>
    </RenderWindow>;
};

export const AccountConTile = ({label, value}) => {
  const {AccountSub} = customerAccountConsignmentScope();
  return <div className="sc-acct-con-tile"><AccountSub>{label}</AccountSub><span className="sc-acct-con-tile-value">{value}</span></div>;
};

export const ACCOUNT_CON_ITEMS = [{
  title: "Horizon Blazer - Small / Sage",
  serial: "SN-77671280-XXGMPE",
  completed: 1,
  commission: 20
}, {
  title: "Classic Denim Jacket - Medium",
  serial: "SN-86003305-JBUXOC",
  completed: 2,
  commission: 20
}];

export const ACCOUNT_CON_ACTIVITY = [{
  type: "Payout",
  detail: "Run #2 · Paid on 30 Jun 2026",
  amount: -48.0
}, {
  type: "Earning",
  detail: "Rental SC-1042 · Horizon Blazer",
  amount: 24.0
}, {
  type: "Refund",
  detail: "Rental SC-1031 · Classic Denim Jacket",
  amount: -6.0
}, {
  type: "Earning",
  detail: "Rental SC-1031 · Classic Denim Jacket",
  amount: 30.0
}];

export const ACCOUNT_CON_CSS = `
  .sc-acct-con { font-family: -apple-system, "system-ui", "Segoe UI", Roboto, Helvetica, Arial, sans-serif; color: #000; font-size: 14px; line-height: 18.9px; }
  .sc-acct-con-header { display: flex; align-items: center; justify-content: space-between; height: 64px; }
  .sc-acct-con-brand { font-size: 22px; font-weight: 600; letter-spacing: -0.01em; }
  .sc-acct-con-avatar { width: 32px; height: 32px; border-radius: 50%; background: #fff; display: grid; place-items: center; font-size: 14px; font-weight: 600; box-shadow: 0 0 0 0.5px rgba(0,0,0,.08), 0 2px 12px rgba(0,0,0,.08); }
  .sc-acct-con-shell { display: grid; grid-template-columns: 133px minmax(0, 976px); column-gap: 59px; padding-top: 20px; align-items: start; }
  .sc-acct-con-nav { display: grid; row-gap: 6px; padding: 5px 5px 14px; }
  .sc-acct-con-nav span { font-size: 20px; font-weight: 600; line-height: 24px; color: rgba(0,0,0,.56); }
  .sc-acct-con-nav span[data-active] { color: #000; }
  .sc-acct-con-body { display: grid; gap: 20px; min-width: 0; padding-top: 4px; }
  .sc-acct-con-title { font-size: 20px; font-weight: 600; line-height: 24px; min-height: 48px; display: flex; align-items: center; }
  .sc-acct-con-tiles { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 20px; }
  .sc-acct-con-tile { background: #fff; border-radius: 16px; padding: 16px; box-shadow: 0 0 0 0.5px rgba(0,0,0,.08), 0 2px 12px rgba(0,0,0,.08); display: grid; gap: 6px; }
  .sc-acct-con-tile-value { font-size: 20px; font-weight: 600; line-height: 24px; }
  .sc-acct-con-activity { display: grid; grid-template-columns: 1fr auto; gap: 4px 14px; align-items: center; padding: 10px 0; }
  .sc-acct-con-activity + .sc-acct-con-activity { border-top: 1px solid #dfdfdf; }
  .sc-acct-con-amount { font-weight: 600; }
  .sc-acct-con-amount--plus { color: #108043; }
  .sc-acct-con-amount--minus { color: #dd1d1d; }
  .sc-acct-con-item { display: flex; justify-content: space-between; align-items: flex-start; gap: 14px; padding: 10px 0; }
  .sc-acct-con-item + .sc-acct-con-item { border-top: 1px solid #dfdfdf; }
  .sc-acct-con-footer { display: flex; gap: 14px; padding: 40px 0 16px; font-size: 14px; color: #0071e3; }
`;

export const customerAccountRentalsScope = () => ({
  AccountBtn,
  AccountCard,
  AccountDivider,
  AccountH2,
  AccountH3,
  AccountIcon,
  AccountRow,
  AccountSub,
  RenderReset,
  RenderWindow
});

export const ACCOUNT = {
  text: "#000000",
  subdued: "rgba(0, 0, 0, 0.56)",
  border: "#dfdfdf",
  accent: "#0071e3",
  critical: "#dd1d1d",
  pageBg: "#f4f4f4",
  cardBg: "#ffffff",
  badgeBg: "#f6f6f6",
  font: '-apple-system, "system-ui", "Segoe UI", Roboto, Helvetica, Arial, sans-serif',
  size: {
    xs: 10,
    sm: 12,
    base: 14,
    md: 16,
    lg: 18,
    xl: 20,
    xxl: 22
  },
  space: {
    xs: 4,
    sm: 8,
    md: 10,
    base: 14,
    lg: 16,
    xl: 20,
    xxl: 24
  },
  radius: {
    sm: 8,
    base: 12,
    lg: 16,
    pill: 36
  },
  shadow: "0 0 0 0.5px rgba(0,0,0,.08), 0 2px 12px rgba(0,0,0,.08)"
};

export const AccountRow = ({label, value, strong}) => <div style={{
  display: "flex",
  justifyContent: "space-between",
  gap: 14,
  fontWeight: strong ? 600 : 400
}}>
    <span style={{
  color: strong ? ACCOUNT.text : ACCOUNT.subdued
}}>{label}</span>
    <span>{value}</span>
  </div>;

export const AccountBadge = ({children}) => <span style={{
  display: "inline-flex",
  alignItems: "center",
  height: 22,
  padding: "0 6px",
  borderRadius: ACCOUNT.radius.pill,
  background: ACCOUNT.badgeBg,
  fontSize: ACCOUNT.size.sm,
  fontWeight: 600,
  lineHeight: "16.2px"
}}>
    {children}
  </span>;

export const AccountDivider = () => <div style={{
  height: 1,
  background: ACCOUNT.border
}} />;

export const AccountSub = ({children, size = ACCOUNT.size.base}) => <div style={{
  fontSize: size,
  color: ACCOUNT.subdued,
  lineHeight: size === 12 ? "16.2px" : "18.9px"
}}>{children}</div>;

export const AccountH3 = ({children}) => <div style={{
  fontSize: ACCOUNT.size.md,
  fontWeight: 600,
  lineHeight: "19.2px"
}}>{children}</div>;

export const AccountH2 = ({children}) => <div style={{
  fontSize: ACCOUNT.size.md,
  fontWeight: 600,
  lineHeight: "19.2px"
}}>{children}</div>;

export const AccountCard = ({children, gap = ACCOUNT.space.lg}) => <div style={{
  background: ACCOUNT.cardBg,
  borderRadius: ACCOUNT.radius.lg,
  boxShadow: ACCOUNT.shadow,
  padding: ACCOUNT.space.lg,
  display: "grid",
  gap
}}>
    {children}
  </div>;

export const AccountBtn = ({kind = "secondary", children, onClick, disabled, full = true}) => {
  const kinds = {
    primary: {
      background: ACCOUNT.accent,
      color: "#ffffff",
      boxShadow: "none"
    },
    secondary: {
      background: "transparent",
      color: ACCOUNT.accent,
      boxShadow: "inset 0 0 0 1px " + ACCOUNT.border
    },
    critical: {
      background: "#ffffff",
      color: ACCOUNT.critical,
      boxShadow: "inset 0 0 0 1px " + ACCOUNT.critical
    },
    plain: {
      background: "transparent",
      color: ACCOUNT.accent,
      boxShadow: "none",
      fontWeight: 400,
      padding: "14px 0"
    }
  };
  return <button type="button" className={onClick && !disabled && kind !== "plain" ? "scr-pressable" : undefined} onClick={disabled ? undefined : onClick} aria-disabled={disabled || undefined} style={{
    font: "inherit",
    fontSize: ACCOUNT.size.base,
    fontWeight: 600,
    lineHeight: "18.9px",
    padding: ACCOUNT.space.base,
    border: 0,
    borderRadius: ACCOUNT.radius.base,
    cursor: disabled ? "default" : "pointer",
    width: full ? "100%" : undefined,
    opacity: disabled ? 0.5 : 1,
    ...kinds[kind]
  }}>
      {children}
    </button>;
};

export const AccountIcon = ({name, size = 18, color = ACCOUNT.text}) => {
  const common = {
    width: size,
    height: size,
    viewBox: "0 0 20 20",
    fill: "none",
    xmlns: "http://www.w3.org/2000/svg",
    "aria-hidden": true
  };
  if (name === "clock") return <svg {...common}>
        <circle cx="10" cy="10" r="7.25" stroke={color} strokeWidth="1.5" />
        <path d="M10 5.75V10l2.75 1.75" stroke={color} strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" />
      </svg>;
  if (name === "check") return <svg {...common}>
        <circle cx="10" cy="10" r="7.25" stroke={color} strokeWidth="1.5" />
        <path d="M6.5 10.2l2.3 2.3 4.7-4.9" stroke={color} strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" />
      </svg>;
  if (name === "back") return <svg {...common}>
        <path d="M11.5 4.5L6 10l5.5 5.5" stroke={color} strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" />
        <path d="M6.5 10H15" stroke={color} strokeWidth="1.5" strokeLinecap="round" />
      </svg>;
  if (name === "image") return <svg {...common}>
        <rect x="3" y="4.5" width="14" height="11" rx="1.5" stroke={color} strokeWidth="1.4" />
        <circle cx="7.5" cy="8.5" r="1.4" stroke={color} strokeWidth="1.4" />
        <path d="M4 14l4-3.5 2.5 2.2 2.5-2 3.5 3.3" stroke={color} strokeWidth="1.4" strokeLinecap="round" strokeLinejoin="round" />
      </svg>;
  if (name === "close") return <svg {...common}>
        <path d="M5.5 5.5l9 9M14.5 5.5l-9 9" stroke={color} strokeWidth="1.5" strokeLinecap="round" />
      </svg>;
  return null;
};

export const AccountConvertToPurchase = () => {
  const {AccountBtn, AccountCard, AccountDivider, AccountH2, AccountH3, AccountIcon, AccountRow, AccountSub, RenderReset, RenderWindow} = customerAccountRentalsScope();
  const [modal, setModal] = useState(false);
  const [purchased, setPurchased] = useState(false);
  const money = n => "$" + n.toFixed(2);
  const RESALE = 420;
  const PAID = 63.99;
  const TODAY = RESALE - PAID;
  const purchase = () => {
    setPurchased(true);
    setModal(false);
  };
  const reset = () => {
    setPurchased(false);
    setModal(false);
  };
  return <RenderWindow label="Example rental page in customer accounts" url="shopify.com/account/pages/rentals/1042" designWidth={1168} gutter={40} background="#f4f4f4" actions={purchased && <RenderReset onClick={reset} />} overlay={({zoom}) => modal && <div className="sc-acct sc-acct-overlay" role="dialog" aria-modal="true" aria-label="Purchase this item">
            <div className="sc-acct-modal" style={{
    zoom,
    width: 480
  }}>
              <div className="sc-acct-modal-head">
                <div style={{
    fontSize: 20,
    fontWeight: 600,
    lineHeight: "24px"
  }}>Purchase this item</div>
                <button type="button" className="sc-acct-modal-x" aria-label="Close" onClick={() => setModal(false)}>
                  <AccountIcon name="close" size={18} />
                </button>
              </div>
              <div className="sc-acct-modal-body">
                <AccountSub>Keep this item for good. We'll charge the difference between the resale price and what you've already paid.</AccountSub>
                <div className="sc-acct-figures sc-acct-modal-figures">
                  <div>
                    <AccountSub>Resale value</AccountSub>
                    <AccountH3>{money(RESALE)}</AccountH3>
                  </div>
                  <div>
                    <AccountSub>Already paid</AccountSub>
                    <AccountH3>{money(PAID)}</AccountH3>
                  </div>
                  <div>
                    <AccountSub>Pay today</AccountSub>
                    <AccountH3>{money(TODAY)}</AccountH3>
                  </div>
                </div>
              </div>
              <div className="sc-acct-modal-foot">
                <AccountBtn kind="plain" full={false} onClick={() => setModal(false)}>
                  Cancel
                </AccountBtn>
                <AccountBtn kind="primary" full={false} onClick={purchase}>
                  Purchase this item
                </AccountBtn>
              </div>
            </div>
          </div>}>
      <div className="sc-acct">
      <style>{`
        .sc-acct { font-family: -apple-system, "system-ui", "Segoe UI", Roboto, Helvetica, Arial, sans-serif; color: #000; font-size: 14px; line-height: 18.9px; }
        .sc-acct-header { display: flex; align-items: center; justify-content: space-between; height: 64px; }
        .sc-acct-brand { font-size: 22px; font-weight: 600; letter-spacing: -0.01em; }
        .sc-acct-avatar { width: 32px; height: 32px; border-radius: 50%; background: #fff; color: #000; display: grid; place-items: center; font-size: 14px; font-weight: 600; box-shadow: 0 0 0 0.5px rgba(0,0,0,.08), 0 2px 12px rgba(0,0,0,.08); }
        .sc-acct-shell { display: grid; grid-template-columns: 133px minmax(0, 976px); column-gap: 59px; padding-top: 20px; align-items: start; }
        .sc-acct-nav { display: grid; row-gap: 6px; padding: 5px 5px 14px; }
        .sc-acct-nav span { font-size: 20px; font-weight: 600; line-height: 24px; color: rgba(0,0,0,.56); }
        .sc-acct-nav span[data-active] { color: #000; }
        .sc-acct-body { display: grid; gap: 20px; min-width: 0; padding-top: 4px; }
        .sc-acct-pagehead { display: grid; grid-template-columns: minmax(0, 1fr) auto; column-gap: 14px; align-items: start; min-height: 48px; }
        .sc-acct-pagehead-title { display: grid; grid-template-columns: 18px 1fr; column-gap: 8px; row-gap: 0; align-items: center; }
        .sc-acct-title { font-size: 20px; font-weight: 600; line-height: 24px; }
        .sc-acct-grid { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); gap: 20px; align-items: start; }
        .sc-acct-col-primary { grid-column: span 7; display: grid; gap: 20px; }
        .sc-acct-col-secondary { grid-column: span 5; display: grid; gap: 16px; }
        .sc-acct-thumb { width: 64px; height: 64px; border-radius: 12px; background: #f4f4f4; box-shadow: inset 0 0 0 1px #dfdfdf; display: grid; place-items: center; color: rgba(0,0,0,.56); }
        .sc-acct-footer { display: flex; gap: 14px; padding: 40px 0 16px; font-size: 14px; color: #0071e3; }
        /* Modal, measured on the live account: gray #f4f4f4 dialog, 1px #d4d4d4 border, 16px radius,
           480px max, 14px 20px head and foot padding, actions right-aligned with an 8px gap,
           rgba(0,0,0,.6) blurred backdrop. */
        .sc-acct-overlay { position: absolute; inset: 0; background: rgba(0,0,0,.6); backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px); display: grid; place-items: center; padding: 24px; z-index: 5; }
        .sc-acct-modal { width: 100%; max-width: 480px; background: #f4f4f4; border: 1px solid #d4d4d4; border-radius: 16px; overflow: hidden;
          box-shadow: 0 1px 2px -.5px rgba(0,0,0,.05), 0 2px 4px -1px rgba(0,0,0,.08), 0 3px 6px -1.5px rgba(0,0,0,.08), 0 8px 16px -6px rgba(0,0,0,.06), 0 24px 40px -12px rgba(0,0,0,.06), 0 32px 48px -12px rgba(0,0,0,.06); }
        .sc-acct-modal-head { display: flex; align-items: center; justify-content: space-between; padding: 14px 20px 0; }
        .sc-acct-modal-x { width: 26px; height: 26px; border-radius: 12px; border: 0; background: #f4f4f4; cursor: pointer; display: grid; place-items: center; padding: 4px; }
        .sc-acct-modal-x:hover { background: #e8e8e8; }
        .sc-acct-modal-body { padding: 14px 20px 0; display: grid; gap: 14px; }
        .sc-acct-modal-figures { background: #fff; border: 1px solid #dedede; border-radius: 12px; padding: 14px; }
        .sc-acct-modal-foot { display: flex; justify-content: flex-end; align-items: center; gap: 8px; padding: 14px 20px; }
        .sc-acct-figures { display: grid; grid-template-columns: repeat(3, 1fr); gap: 14px; }
      `}</style>

            <div className="sc-acct-header" aria-hidden="true">
              <span className="sc-acct-brand">Summit store</span>
              <span className="sc-acct-avatar">M</span>
            </div>

            <div className="sc-acct-shell">
              <nav className="sc-acct-nav" aria-hidden="true">
                <span data-active="">Dashboard</span>
                <span>Orders</span>
                <span>Back to Shop</span>
                <span>Profile</span>
              </nav>

              <div className="sc-acct-body">
                <div className="sc-acct-pagehead">
                  <div className="sc-acct-pagehead-title">
                    <AccountIcon name="back" />
                    <div className="sc-acct-title">Rental SC-1042</div>
                    <span />
                    <AccountSub>Created 10 January 9:14am</AccountSub>
                  </div>
                  <AccountBtn kind="secondary" full={false}>
                    View order
                  </AccountBtn>
                </div>

                <div className="sc-acct-grid">
                  <div className="sc-acct-col-primary">
                    <AccountCard>
                      <div style={{
    display: "grid",
    gridTemplateColumns: "auto 1fr",
    columnGap: 14,
    alignItems: "center"
  }}>
                        <span className="sc-acct-thumb">
                          <AccountIcon name="image" size={22} color="rgba(0,0,0,.56)" />
                        </span>
                        <div style={{
    display: "grid",
    gap: 4
  }}>
                          <AccountH2>All-mountain ski set</AccountH2>
                          <AccountSub>170 cm</AccountSub>
                        </div>
                      </div>
                    </AccountCard>

                    <AccountCard>
                      <div style={{
    display: "grid",
    gridTemplateColumns: "18px 1fr",
    columnGap: 14,
    rowGap: 4,
    alignItems: "center"
  }}>
                        <AccountIcon name={purchased ? "check" : "clock"} color={purchased ? ACCOUNT.text : ACCOUNT.text} />
                        <AccountH2>{purchased ? "Complete" : "Return in 12 days"}</AccountH2>
                        <span />
                        <AccountSub>{purchased ? "Converted to purchase" : "Return by 24 Jan"}</AccountSub>
                      </div>
                      <AccountDivider />
                      <AccountSub>
                        {purchased ? "This item is yours to keep. Pay the outstanding balance below to complete your purchase." : "This item is due to be returned on 24 Jan. Follow the return instructions in your account to complete the process."}
                      </AccountSub>
                      {!purchased && <div style={{
    display: "grid",
    gap: 14
  }}>
                          <AccountBtn kind="secondary">Return</AccountBtn>
                          <AccountBtn kind="secondary" onClick={() => setModal(true)}>
                            Purchase this item
                          </AccountBtn>
                        </div>}
                    </AccountCard>

                    <AccountCard>
                      <div style={{
    display: "grid",
    gap: 4
  }}>
                        <AccountH2>Payments</AccountH2>
                        <AccountSub>{purchased ? money(TODAY) + " outstanding" : "You have no outstanding charges"}</AccountSub>
                      </div>
                      <AccountDivider />
                      <div style={{
    display: "grid",
    gap: 6
  }}>
                        <AccountRow label="Rental, 10 to 24 Jan" value={money(PAID)} />
                        {purchased && <AccountRow label="Purchase" value={money(TODAY)} />}
                      </div>
                      <AccountDivider />
                      <div style={{
    display: "grid",
    gap: 6
  }}>
                        <AccountRow label="Paid" value={money(PAID)} strong />
                        <AccountRow label="Outstanding" value={money(purchased ? TODAY : 0)} strong />
                      </div>
                      {purchased && <AccountBtn kind="primary">Pay {money(TODAY)}</AccountBtn>}
                    </AccountCard>
                  </div>

                  <div className="sc-acct-col-secondary">
                    <AccountCard>
                      <AccountH2>Schedule</AccountH2>
                      <div style={{
    display: "grid",
    gridTemplateColumns: "1fr 1fr",
    gap: 14
  }}>
                        <div>
                          <AccountSub>Delivery</AccountSub>
                          <div>10 Jan 2026</div>
                        </div>
                        <div>
                          <AccountSub>Return</AccountSub>
                          <div>24 Jan 2026</div>
                        </div>
                      </div>
                    </AccountCard>
                    <AccountCard>
                      <AccountH2>Address</AccountH2>
                      <div>
                        <div style={{
    marginBottom: 4
  }}>Shipping address</div>
                        <AccountSub>Lisa Lendme</AccountSub>
                        <AccountSub>18 Ridge Road</AccountSub>
                        <AccountSub>Chamonix</AccountSub>
                        <AccountSub>74400</AccountSub>
                        <AccountSub>France</AccountSub>
                      </div>
                    </AccountCard>
                  </div>
                </div>
              </div>
            </div>

            <div className="sc-acct-footer" aria-hidden="true">
              <span>Cookie preferences</span>
              <span>Privacy policy</span>
            </div>
      </div>
    </RenderWindow>;
};

export const renderKitScope = () => ({
  RenderStyles
});

export const RENDER_CSS = `
  .scr { width: 100%; min-width: 0; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; }
  .scr button { margin: 0; appearance: none; text-align: center; }
  .scr button:focus-visible { outline: 2px solid #0071e3; outline-offset: 2px; }

  /* Browser window: neutral traffic dots, centered URL, the docs' layered shadow. */
  .scr-window { position: relative; width: 100%; margin: 0 auto; display: flex; flex-direction: column; border-radius: 10px; overflow: hidden; touch-action: pan-y;
    box-shadow: 0 0 0 1px rgba(11,13,24,.06), 0 1px 2px rgba(11,13,24,.024), 0 3px 6px rgba(11,13,24,.03), 0 8px 14px rgba(11,13,24,.035), 0 16px 28px rgba(11,13,24,.04); }
  .scr-titlebar { flex: none; display: flex; align-items: center; gap: 6px; padding: 9px 12px; border-bottom: 1px solid #ebebeb; background: #fff; }
  .scr-dot { width: 9px; height: 9px; border-radius: 50%; background: #e3e3e3; }
  .scr-url { margin: 0 auto; min-width: 0; max-width: calc(100% - 48px); font-size: 11px; color: #85817a; background: #f3f2ee; border-radius: 6px; padding: 3px 10px; line-height: 1.2; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .scr-page { position: relative; overflow: hidden; }
  /* container-name: scr is what polaris-css.jsx's @container queries measure,
     so a phone viewport cannot switch the page to a mobile layout. */
  .scr-zoom { margin: 0 auto; box-sizing: border-box; container-type: inline-size; container-name: scr; }

  /* Reset: quiet text control in the chrome, shown once a render has moved on from its resting state. */
  .scr-reset { font-size: 11px; color: #85817a; background: none; border: 0; cursor: pointer; padding: 2px 4px; font-family: inherit; }
  .scr-reset:hover { color: #1a1a1a; }

  /* Tablet: iPad in landscape, near-black bezel, camera on the left edge, iPadOS status bar. */
  .scr-tablet { position: relative; width: 100%; margin: 0 auto; box-sizing: border-box; padding: 12px 12px 12px 20px; background: #1c1c1e; border-radius: 24px; touch-action: pan-y;
    box-shadow: inset 0 0 0 1px rgba(255,255,255,.1), 0 12px 28px rgba(11,13,24,.18); }
  .scr-camera { position: absolute; left: 7px; top: 50%; width: 5px; height: 5px; transform: translateY(-50%); border-radius: 50%; background: #3a3a3c; box-shadow: inset 0 0 0 1px #111; }
  .scr-screen { position: relative; overflow: hidden; border-radius: 12px; background: #000; }
  .scr-tablet .scr-reset { position: absolute; right: 16px; top: 14px; z-index: 7; color: rgba(255,255,255,.55); }
  .scr-tablet .scr-reset:hover { color: #fff; }

  /* Main buttons the reader can press ripple softly so it's clear what responds. Plain text
     links and decorative controls don't. Paused on hover, off under reduced motion. */
  .scr-pressable { position: relative; }
  .scr-pressable::after { content: ""; position: absolute; inset: 0; border-radius: inherit; pointer-events: none; animation: scr-ripple 2.4s ease-out infinite; }
  @keyframes scr-ripple {
    0% { box-shadow: 0 0 0 0 var(--scr-ripple, rgba(0, 113, 227, .45)); }
    60% { box-shadow: 0 0 0 10px transparent; }
    100% { box-shadow: 0 0 0 0 transparent; }
  }
  .scr-pressable:hover::after { animation: none; }
  @media (prefers-reduced-motion: reduce) { .scr-pressable::after { animation: none; } }
`;

export const useRenderZoom = (ref, designWidth) => {
  const [zoom, setZoom] = useState(0.6);
  useEffect(() => {
    const el = ref.current;
    if (!el || typeof ResizeObserver === "undefined") return undefined;
    const fit = () => setZoom(Math.max(0.2, Math.min(1, el.clientWidth / designWidth)));
    fit();
    const ro = new ResizeObserver(fit);
    ro.observe(el);
    return () => ro.disconnect();
  }, [designWidth]);
  return zoom;
};

export const RenderReset = ({onClick, className}) => <button type="button" className={"scr-reset" + (className ? " " + className : "")} onClick={onClick}>
    Reset
  </button>;

export const RenderStyles = () => <style>{RENDER_CSS}</style>;

export const RenderWindow = ({url, label, designWidth = 1168, gutter = 40, background = "#ffffff", actions, overlay, children}) => {
  const {RenderStyles} = renderKitScope();
  const ref = useRef(null);
  const total = designWidth + gutter * 2;
  const zoom = useRenderZoom(ref, total);
  const body = typeof children === "function" ? children({
    zoom
  }) : children;
  return <div className="not-prose scr" aria-label={label}>
      <RenderStyles />
      <div className="scr-window" ref={ref}>
        <div className="scr-titlebar">
          <span className="scr-dot" />
          <span className="scr-dot" />
          <span className="scr-dot" />
          <span className="scr-url">{url}</span>
          {actions}
        </div>
        <div className="scr-page" style={{
    background
  }}>
          <div className="scr-zoom" style={{
    zoom,
    width: total,
    padding: "0 " + gutter + "px"
  }}>
            {body}
          </div>
          {typeof overlay === "function" ? overlay({
    zoom
  }) : overlay}
        </div>
      </div>
    </div>;
};

Consignors can follow their own performance without you sending updates. When a consignor is linked to a Shopify customer, a **Consignment** page appears in that customer's account with their balance, recent activity, payouts, and items. The page is read-only, so consignors see their numbers but change nothing.

***

## Give a consignor access

<Steps>
  <Step title="Link a customer">
    On the [consignor's page](/documentation/manage/consignment/consignors), set **Customer** to the Shopify customer the consignor logs in with.
  </Step>

  <Step title="Let them log in">
    The consignor logs in to your store's customer accounts. **Consignment** appears on their dashboard.
  </Step>
</Steps>

<Note>
  A consignor only sees their details while they're linked to an active consignor. Archiving the consignor hides the page, and a customer who isn't a consignor sees **Consignment isn't set up for this account yet**.
</Note>

***

## What the consignor sees

The consignor gets two surfaces, the same way membership appears in customer accounts: a summary card on their dashboard, and a fuller **Consignment** page with stats, activity, and items.

<Frame type="glass" caption="The Consignment page: the balance owed, what the items have earned, and the payouts you've recorded.">
  <AccountConsignment />
</Frame>

### Summary card

The card on the dashboard is the at-a-glance version. It shows the balance owed, as **\[amount] owed to you** or **You're all settled up** when nothing is outstanding, a line summarizing their items and earnings, the total paid out to date, and the latest payouts you've recorded with their dates and amounts.

### Stats

The **Consignment** page leads with four figures: **Balance owed**, **Total earned**, **Consigned items**, and **Total paid out**.

### Recent activity

A reverse-chronological feed of everything that has moved the balance:

* **Earnings** from rentals, with the cycle and item, as a positive green amount.
* **Refunds**, as a negative red amount.
* **Payouts** you've recorded, as a negative amount with the payout run and the date you paid.

Before any items have been rented, the feed reads **Earnings will appear here once your items are rented**.

### My items

Each consigned item with its title, serial number, completed rentals, and commission rate. A consignor with more items than fit sees the first batch and a count of the total.

***

## Considerations

* The page relies on Shopify [customer accounts](/documentation/online-store/portal), so the consignor needs an account on your store.
* Everything on it mirrors the admin. Recording a payout or assigning an item changes what the consignor sees the next time they open the page, with nothing to publish or send.
