// dthas — design-system primitives, browser-ready.
//
// These are the same components that used to ship in the generated `_ds_bundle.js`.
// They're inlined here so the landing page runs from source with no build step:
// React/ReactDOM/Babel are loaded as globals in index.html, and every component
// is registered on `window.DesignSystem_aa2f04` so the section files can read them
// exactly as before (`const { Button } = window.DesignSystem_aa2f04`).
//
// Brand rules live in BRAND.md: pure black & white, Inter + IBM Plex Mono,
// sharp corners, no shadows, the signature black↔white hover inversion.

const { useState } = React;

/* ───────────────────────── core ───────────────────────── */

/**
 * Button — sharp-cornered, hairline-precise.
 * Signature interaction is a full black/white inversion on hover.
 */
function Button({
  children,
  variant = 'primary',
  size = 'md',
  as = 'button',
  href,
  withArrow = false,
  disabled = false,
  onClick,
  type = 'button',
  ...rest
}) {
  const [hover, setHover] = useState(false);
  const [active, setActive] = useState(false);

  const sizes = {
    sm: { padding: '8px 16px', fontSize: '13px' },
    md: { padding: '13px 24px', fontSize: '15px' },
    lg: { padding: '18px 32px', fontSize: '16px' },
  };

  // variant → resting + inverted (hover) colors
  const schemes = {
    primary: {
      base: { background: 'var(--c-black)', color: 'var(--c-white)', borderColor: 'var(--c-black)' },
      hover: { background: 'var(--c-white)', color: 'var(--c-black)', borderColor: 'var(--c-black)' },
    },
    secondary: {
      base: { background: 'transparent', color: 'var(--c-black)', borderColor: 'var(--c-black)' },
      hover: { background: 'var(--c-black)', color: 'var(--c-white)', borderColor: 'var(--c-black)' },
    },
    ghost: {
      base: { background: 'transparent', color: 'var(--c-black)', borderColor: 'transparent' },
      hover: { background: 'transparent', color: 'var(--c-ink-500)', borderColor: 'transparent' },
    },
    // for use on the inverted (black) hero
    inverse: {
      base: { background: 'var(--c-white)', color: 'var(--c-black)', borderColor: 'var(--c-white)' },
      hover: { background: 'transparent', color: 'var(--c-white)', borderColor: 'var(--c-white)' },
    },
  };

  const scheme = schemes[variant] || schemes.primary;
  const colors = hover && !disabled ? scheme.hover : scheme.base;

  const style = {
    display: 'inline-flex',
    alignItems: 'center',
    justifyContent: 'center',
    gap: '10px',
    fontFamily: 'var(--font-sans)',
    fontWeight: 500,
    letterSpacing: '-0.01em',
    lineHeight: 1,
    textDecoration: 'none',
    whiteSpace: 'nowrap',
    border: '1px solid',
    borderRadius: 0,
    cursor: disabled ? 'not-allowed' : 'pointer',
    opacity: disabled ? 0.35 : 1,
    transition: 'background var(--dur-base) var(--ease-out), color var(--dur-base) var(--ease-out), border-color var(--dur-base) var(--ease-out), transform var(--dur-fast) var(--ease-out)',
    transform: active && !disabled ? 'translateY(1px)' : 'none',
    ...sizes[size],
    ...colors,
  };

  const arrow = withArrow ? (
    <span aria-hidden="true" style={{
      transition: 'transform var(--dur-base) var(--ease-out)',
      transform: hover && !disabled ? 'translateX(4px)' : 'none',
      fontSize: '1.1em',
      lineHeight: 0,
    }}>→</span>
  ) : null;

  const handlers = {
    onMouseEnter: () => setHover(true),
    onMouseLeave: () => { setHover(false); setActive(false); },
    onMouseDown: () => setActive(true),
    onMouseUp: () => setActive(false),
    onClick: disabled ? undefined : onClick,
  };

  if (as === 'a') {
    return (
      <a href={href} style={style} {...handlers} {...rest}>
        {children}{arrow}
      </a>
    );
  }

  return (
    <button type={type} style={style} disabled={disabled} {...handlers} {...rest}>
      {children}{arrow}
    </button>
  );
}

/**
 * Tag — monospace technical label used in the capability grid.
 * A bare hairline rectangle; optionally inverts on hover.
 */
function Tag({ children, interactive = false, ...rest }) {
  const [hover, setHover] = useState(false);
  const style = {
    display: 'inline-flex',
    alignItems: 'center',
    fontFamily: 'var(--font-mono)',
    fontSize: 'var(--fs-mono)',
    letterSpacing: 'var(--ls-mono)',
    fontWeight: 400,
    lineHeight: 1,
    padding: '9px 14px',
    border: '1px solid var(--border-hairline)',
    borderRadius: 0,
    color: hover && interactive ? 'var(--c-white)' : 'var(--text-primary)',
    background: hover && interactive ? 'var(--c-black)' : 'transparent',
    borderColor: hover && interactive ? 'var(--c-black)' : 'var(--border-hairline)',
    transition: 'background var(--dur-base) var(--ease-out), color var(--dur-base) var(--ease-out), border-color var(--dur-base) var(--ease-out)',
    cursor: interactive ? 'default' : 'inherit',
    whiteSpace: 'nowrap',
  };
  return (
    <span
      style={style}
      onMouseEnter={() => setHover(true)}
      onMouseLeave={() => setHover(false)}
      {...rest}
    >
      {children}
    </span>
  );
}

/**
 * Overline — monospace eyebrow label used to mark sections.
 * Often prefixed with an em dash or an index numeral.
 */
function Overline({ children, index, as = 'div', ...rest }) {
  const Comp = as;
  const style = {
    fontFamily: 'var(--font-mono)',
    fontSize: 'var(--fs-overline)',
    letterSpacing: 'var(--ls-wide)',
    textTransform: 'uppercase',
    color: 'var(--text-secondary)',
    fontWeight: 400,
    lineHeight: 1,
    display: 'inline-flex',
    alignItems: 'center',
    gap: '10px',
  };
  return (
    <Comp style={style} {...rest}>
      {index ? <span style={{ color: 'var(--text-primary)' }}>{index}</span> : null}
      <span>{children}</span>
    </Comp>
  );
}

/**
 * Card — a hairline-bordered, sharp-cornered container.
 * The default surface for grouped content. Optional `hoverInvert`
 * flips it to the black surface on hover.
 */
function Card({ children, hoverInvert = false, padding = '32px', as = 'div', ...rest }) {
  const [hover, setHover] = useState(false);
  const inverted = hoverInvert && hover;
  const Comp = as;
  const style = {
    boxSizing: 'border-box',
    background: inverted ? 'var(--c-black)' : 'var(--surface-raised)',
    color: inverted ? 'var(--c-white)' : 'var(--text-primary)',
    border: '1px solid',
    borderColor: inverted ? 'var(--c-black)' : 'var(--border-hairline)',
    borderRadius: 0,
    padding,
    transition: 'background var(--dur-base) var(--ease-out), color var(--dur-base) var(--ease-out), border-color var(--dur-base) var(--ease-out)',
    ...rest.style,
  };
  const { style: _drop, ...domRest } = rest;
  return (
    <Comp
      style={style}
      onMouseEnter={() => setHover(true)}
      onMouseLeave={() => setHover(false)}
      {...domRest}
    >
      {children}
    </Comp>
  );
}

/* ─────────────────────── editorial ─────────────────────── */

/**
 * ServiceCard — a numbered offering tile for the services grid.
 * Index numeral, title, short description, hover inversion to black.
 */
function ServiceCard({ index, title, description, lead = false, ...rest }) {
  const [hover, setHover] = useState(false);
  const style = {
    boxSizing: 'border-box',
    position: 'relative',
    display: 'flex',
    flexDirection: 'column',
    minHeight: lead ? '320px' : '260px',
    padding: lead ? '36px' : '32px',
    background: hover ? 'var(--c-black)' : 'var(--c-white)',
    color: hover ? 'var(--c-white)' : 'var(--c-black)',
    border: '1px solid',
    borderColor: hover ? 'var(--c-black)' : 'var(--border-hairline)',
    borderRadius: 0,
    transition: 'background var(--dur-base) var(--ease-out), color var(--dur-base) var(--ease-out), border-color var(--dur-base) var(--ease-out)',
    cursor: 'default',
    ...rest.style,
  };
  const { style: _s, ...domRest } = rest;

  return (
    <article
      style={style}
      onMouseEnter={() => setHover(true)}
      onMouseLeave={() => setHover(false)}
      {...domRest}
    >
      <div style={{
        display: 'flex',
        justifyContent: 'space-between',
        alignItems: 'baseline',
        fontFamily: 'var(--font-mono)',
        fontSize: 'var(--fs-mono)',
        letterSpacing: 'var(--ls-mono)',
        color: hover ? 'var(--c-paper-700)' : 'var(--text-secondary)',
        transition: 'color var(--dur-base) var(--ease-out)',
      }}>
        <span>{index}</span>
      </div>

      <h3 style={{
        margin: 'auto 0 0',
        paddingTop: '24px',
        fontSize: lead ? 'clamp(1.6rem, 2.4vw, 2.1rem)' : 'var(--fs-h3)',
        lineHeight: 1.12,
        letterSpacing: '-0.02em',
        fontWeight: 500,
      }}>
        {title}
      </h3>

      <p style={{
        margin: '14px 0 0',
        fontSize: 'var(--fs-small)',
        lineHeight: 1.55,
        color: hover ? 'var(--c-paper-700)' : 'var(--text-secondary)',
        maxWidth: '40ch',
        transition: 'color var(--dur-base) var(--ease-out)',
      }}>
        {description}
      </p>
    </article>
  );
}

/**
 * WorkItem — a numbered editorial list row for the selected-work strip.
 * Index, title and a meta/discipline label, divided by hairlines.
 * The row's title shifts right slightly on hover.
 */
function WorkItem({ index, title, meta, ...rest }) {
  const [hover, setHover] = useState(false);
  const { style: _s, ...domRest } = rest;
  return (
    <div
      onMouseEnter={() => setHover(true)}
      onMouseLeave={() => setHover(false)}
      style={{
        display: 'grid',
        gridTemplateColumns: 'auto 1fr auto',
        alignItems: 'center',
        gap: 'clamp(16px, 4vw, 56px)',
        padding: 'clamp(20px, 3vw, 32px) 0',
        borderTop: '1px solid var(--border-hairline)',
        cursor: 'default',
        ...rest.style,
      }}
      {...domRest}
    >
      <span style={{
        fontFamily: 'var(--font-mono)',
        fontSize: 'var(--fs-mono)',
        letterSpacing: 'var(--ls-mono)',
        color: 'var(--text-secondary)',
      }}>{index}</span>

      <h3 style={{
        margin: 0,
        fontSize: 'clamp(1.25rem, 2.4vw, 2rem)',
        lineHeight: 1.1,
        letterSpacing: '-0.02em',
        fontWeight: 400,
        transform: hover ? 'translateX(8px)' : 'none',
        transition: 'transform var(--dur-base) var(--ease-out)',
      }}>{title}</h3>

      <span style={{
        fontFamily: 'var(--font-mono)',
        fontSize: 'var(--fs-caption)',
        letterSpacing: 'var(--ls-mono)',
        color: 'var(--text-secondary)',
        textAlign: 'right',
        whiteSpace: 'nowrap',
      }}>{meta}</span>
    </div>
  );
}

/* ───────────────────────── forms ───────────────────────── */

/**
 * Input — an underline-only text field. No box, no radius;
 * a single hairline baseline that thickens to full ink on focus.
 */
function Input({ label, id, type = 'text', value, onChange, placeholder, required, name, ...rest }) {
  const [focus, setFocus] = useState(false);
  const fieldId = id || name || (label ? label.toLowerCase().replace(/\s+/g, '-') : undefined);
  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: '8px' }}>
      {label && (
        <label htmlFor={fieldId} style={{
          fontFamily: 'var(--font-mono)',
          fontSize: 'var(--fs-overline)',
          letterSpacing: 'var(--ls-wide)',
          textTransform: 'uppercase',
          color: 'var(--text-secondary)',
        }}>
          {label}{required && <span aria-hidden="true"> *</span>}
        </label>
      )}
      <input
        id={fieldId}
        name={name}
        type={type}
        value={value}
        onChange={onChange}
        placeholder={placeholder}
        required={required}
        onFocus={() => setFocus(true)}
        onBlur={() => setFocus(false)}
        style={{
          width: '100%',
          boxSizing: 'border-box',
          fontFamily: 'var(--font-sans)',
          fontSize: 'var(--fs-body)',
          color: 'var(--text-primary)',
          background: 'transparent',
          border: 0,
          borderBottom: `${focus ? '2px' : '1px'} solid ${focus ? 'var(--c-black)' : 'var(--border-hairline)'}`,
          borderRadius: 0,
          padding: '10px 0',
          outline: 'none',
          transition: 'border-color var(--dur-base) var(--ease-out)',
        }}
        {...rest}
      />
    </div>
  );
}

/**
 * Textarea — underline-only multiline field, matching Input.
 */
function Textarea({ label, id, value, onChange, placeholder, required, name, rows = 4, ...rest }) {
  const [focus, setFocus] = useState(false);
  const fieldId = id || name || (label ? label.toLowerCase().replace(/\s+/g, '-') : undefined);
  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: '8px' }}>
      {label && (
        <label htmlFor={fieldId} style={{
          fontFamily: 'var(--font-mono)',
          fontSize: 'var(--fs-overline)',
          letterSpacing: 'var(--ls-wide)',
          textTransform: 'uppercase',
          color: 'var(--text-secondary)',
        }}>
          {label}{required && <span aria-hidden="true"> *</span>}
        </label>
      )}
      <textarea
        id={fieldId}
        name={name}
        value={value}
        onChange={onChange}
        placeholder={placeholder}
        required={required}
        rows={rows}
        onFocus={() => setFocus(true)}
        onBlur={() => setFocus(false)}
        style={{
          width: '100%',
          boxSizing: 'border-box',
          fontFamily: 'var(--font-sans)',
          fontSize: 'var(--fs-body)',
          lineHeight: 1.5,
          color: 'var(--text-primary)',
          background: 'transparent',
          border: 0,
          borderBottom: `${focus ? '2px' : '1px'} solid ${focus ? 'var(--c-black)' : 'var(--border-hairline)'}`,
          borderRadius: 0,
          padding: '10px 0',
          outline: 'none',
          resize: 'vertical',
          transition: 'border-color var(--dur-base) var(--ease-out)',
        }}
        {...rest}
      />
    </div>
  );
}

/* ─────────────── register the namespace the page reads ─────────────── */
window.DesignSystem_aa2f04 = {
  Button, Tag, Overline, Card,
  ServiceCard, WorkItem,
  Input, Textarea,
};
