// Saloniq – Authentication & Salon Management (Firebase-backed)
// admin.saloniq.dk         → super-admin panel (opret/administrer saloner)
// {salon}.saloniq.dk       → that salon's login (e.g. hob.saloniq.dk for HOB,
//                            srh.saloniq.dk for SRH, etc.)
//
// Cross-salon isolation applies to EVERY salon, not just one:
//   - SalonLoginPage rejects credentials whose /users/{uid}.salonId doesn't
//     match the current subdomain (defense-in-depth alongside Firestore Rules)
//   - AuthGate detects when an active session belongs to a different salon
//     and shows a 'wrong salon' page instead of silently signing them out
//   - Firestore Security Rules independently enforce per-salon read/write,
//     so even a hand-crafted API request can't cross-load another salon's data
//
// Auth: Firebase Auth (email + password, hashed server-side by Firebase)
// Data: Cloud Firestore — passwords NEVER stored here
// Access: enforced by Firestore Security Rules — see firestore.rules
const FB = window.SaloniqFirebase;

function getSubdomain() {
  const params = new URLSearchParams(window.location.search);
  if (params.get('salon')) return params.get('salon').toLowerCase();
  const host = window.location.hostname;
  if (host === 'localhost' || host === '127.0.0.1') return '__dev__';
  const parts = host.split('.');
  return parts.length >= 3 ? parts[0].toLowerCase() : null;
}

// Detects the public-booking entry-point: booking.saloniq.dk/{salon}.
// Returns the salon-subdomain (e.g. 'srh') or null when we're not on
// that route. Also supports ?booking=srh on localhost for dev.
function getPublicBookingSalon() {
  const params = new URLSearchParams(window.location.search);
  if (params.get('booking')) return params.get('booking').toLowerCase();
  const host = window.location.hostname;
  if (host.split('.')[0].toLowerCase() !== 'booking') return null;
  const m = String(window.location.pathname || '').match(/^\/([a-z0-9][a-z0-9-]*)\/?$/i);
  return m ? m[1].toLowerCase() : null;
}

// ─── Loading screen — shown while Firebase auth state initializes ────────────
function LoadingScreen() {
  return (
    <div style={{
      minHeight: '100vh', display: 'flex', alignItems: 'center', justifyContent: 'center',
      background: '#FBFAF6', fontFamily: "'Manrope', sans-serif",
    }}>
      <div style={{ textAlign: 'center', color: '#888' }}>
        <div style={{
          width: 32, height: 32, margin: '0 auto 14px',
          border: '3px solid #E5E2D5', borderTopColor: '#7B8A6B',
          borderRadius: '50%', animation: 'spin 0.8s linear infinite',
        }} />
        <div style={{ fontSize: 13 }}>Indlæser…</div>
      </div>
      <style>{'@keyframes spin{to{transform:rotate(360deg)}}'}</style>
    </div>
  );
}

// ─── Shared Login Form ────────────────────────────────────────────────────────
// Memoized so it never re-renders when only the parent's state (error/loading)
// changes — keeps the input focused on every keystroke.
const LoginForm = React.memo(function LoginForm({
  title, subtitle, accentColor, onSubmit, error, loading,
  logo, salonName, onForgotPassword,
  remember, onRememberChange, hideRemember,
}) {
  const [email, setEmail] = React.useState('');
  const [password, setPassword] = React.useState('');
  const [showPw, setShowPw] = React.useState(false);

  const ac = accentColor || '#3F4A3A';

  // Header brand: salon's uploaded logo > salon's first letter > Saloniq fallback
  const renderHeaderMark = () => {
    if (logo) {
      return (
        <div style={{
          width: 80, height: 80, margin: '0 auto 18px',
          borderRadius: 16, background: '#fff',
          border: '1px solid #EFEDE5', overflow: 'hidden',
          display: 'flex', alignItems: 'center', justifyContent: 'center',
        }}>
          <img src={logo} alt={salonName || title}
               style={{ maxWidth: '100%', maxHeight: '100%', objectFit: 'contain' }} />
        </div>
      );
    }
    if (salonName) {
      return (
        <div style={{
          width: 64, height: 64, background: ac, borderRadius: 16,
          margin: '0 auto 18px', display: 'flex', alignItems: 'center', justifyContent: 'center',
          fontFamily: "'Fraunces', serif", fontSize: 30, fontWeight: 500, color: '#fff',
        }}>
          {salonName[0].toUpperCase()}
        </div>
      );
    }
    // Saloniq fallback (super-admin / no salon context)
    return (
      <div style={{
        width: 60, height: 60, background: ac, borderRadius: 16,
        margin: '0 auto 18px', display: 'flex', alignItems: 'center', justifyContent: 'center',
        fontFamily: "'Fraunces', serif", fontSize: 30, fontWeight: 500, color: '#fff',
      }}>
        S
      </div>
    );
  };

  return (
    <div style={{
      minHeight: '100vh', display: 'flex', alignItems: 'center', justifyContent: 'center',
      background: 'linear-gradient(145deg, #f5f3ee 0%, #ece8df 100%)',
      fontFamily: "'Manrope', sans-serif",
    }}>
      <div style={{
        width: 400, padding: '48px 40px',
        background: '#fff', borderRadius: 20,
        boxShadow: '0 8px 48px rgba(0,0,0,0.12)',
        animation: 'slideUp 0.3s ease',
      }}>
        <div style={{ textAlign: 'center', marginBottom: 36 }}>
          {renderHeaderMark()}
          <h1 style={{
            fontFamily: "'Fraunces', serif", fontSize: 26, fontWeight: 500,
            margin: '0 0 8px', color: '#1a1a1a',
          }}>{title}</h1>
          {subtitle && (
            <p style={{ margin: 0, fontSize: 14, color: '#888', lineHeight: 1.5 }}>{subtitle}</p>
          )}
        </div>

        <form onSubmit={e => { e.preventDefault(); onSubmit(email, password); }}>
          <div style={{ marginBottom: 14 }}>
            <label style={{
              display: 'block', fontSize: 12, fontWeight: 700, color: '#555',
              marginBottom: 6, textTransform: 'uppercase', letterSpacing: '0.06em',
            }}>Email</label>
            <input
              type="email" value={email} autoFocus
              autoComplete="email"
              onChange={e => setEmail(e.target.value)}
              placeholder="dig@dinsalon.dk"
              style={{
                width: '100%', padding: '12px 14px', boxSizing: 'border-box',
                border: `1.5px solid ${error ? '#FECACA' : '#DDD9CE'}`,
                borderRadius: 10, fontSize: 14, outline: 'none',
                background: '#FBFAF6', fontFamily: 'inherit',
              }}
            />
          </div>

          <div style={{ marginBottom: 24 }}>
            <label style={{
              display: 'block', fontSize: 12, fontWeight: 700, color: '#555',
              marginBottom: 6, textTransform: 'uppercase', letterSpacing: '0.06em',
            }}>Adgangskode</label>
            <div style={{ position: 'relative' }}>
              <input
                type={showPw ? 'text' : 'password'} value={password}
                onChange={e => setPassword(e.target.value)}
                placeholder="Indtast adgangskode"
                style={{
                  width: '100%', padding: '12px 44px 12px 14px', boxSizing: 'border-box',
                  border: `1.5px solid ${error ? '#FECACA' : '#DDD9CE'}`,
                  borderRadius: 10, fontSize: 14, outline: 'none',
                  background: '#FBFAF6', fontFamily: 'inherit',
                }}
              />
              <button type="button" onClick={() => setShowPw(v => !v)}
                title={showPw ? 'Skjul adgangskode' : 'Vis adgangskode'}
                style={{
                  position: 'absolute', right: 8, top: '50%', transform: 'translateY(-50%)',
                  background: 'none', border: 'none', cursor: 'pointer', color: '#aaa',
                  padding: 6, lineHeight: 0,
                }}>
                <IconEye size={18} stroke={showPw ? '#3F4A3A' : '#aaa'} />
              </button>
            </div>
          </div>

          {!hideRemember && (
            <div style={{
              display: 'flex', justifyContent: 'space-between', alignItems: 'center',
              marginBottom: 18,
            }}>
              <label style={{
                display: 'flex', alignItems: 'center', gap: 8,
                fontSize: 13, color: '#555', cursor: 'pointer', userSelect: 'none',
              }}>
                <input
                  type="checkbox"
                  checked={!!remember}
                  onChange={e => onRememberChange?.(e.target.checked)}
                  style={{ accentColor: ac, width: 15, height: 15, cursor: 'pointer' }}
                />
                Husk mig
              </label>
              {onForgotPassword && (
                <button type="button" onClick={onForgotPassword} style={{
                  background: 'none', border: 'none', cursor: 'pointer',
                  fontSize: 13, color: ac, fontWeight: 500, padding: 0,
                  fontFamily: 'inherit', textDecoration: 'underline', textUnderlineOffset: 3,
                }}>Glemt adgangskode?</button>
              )}
            </div>
          )}

          {error && (
            <div style={{
              padding: '10px 14px', background: '#FEF2F2', border: '1px solid #FECACA',
              borderRadius: 8, fontSize: 13, color: '#B91C1C', marginBottom: 18,
            }}>{error}</div>
          )}

          <button type="submit" disabled={loading || !email || !password} style={{
            width: '100%', padding: '13px',
            background: (!email || !password) ? '#D4D0C8' : ac,
            color: '#fff', border: 'none', borderRadius: 10,
            fontSize: 15, fontWeight: 600,
            cursor: (!email || !password) ? 'default' : 'pointer',
            fontFamily: 'inherit', transition: 'background 0.15s',
          }}>
            {loading ? 'Logger ind…' : 'Log ind'}
          </button>
        </form>

        <p style={{ textAlign: 'center', marginTop: 28, fontSize: 12, color: '#ccc' }}>
          <strong style={{ color: '#aaa' }}>Saloniq</strong> · af{' '}
          <a href="https://ooniq.dk" target="_blank" rel="noopener noreferrer"
             style={{ color: '#888', textDecoration: 'none', fontWeight: 600, borderBottom: '1px dotted #bbb' }}>ooniq</a>
        </p>
      </div>
    </div>
  );
});

// ─── Salon Login ──────────────────────────────────────────────────────────────
// Screen shown when a salon has been locked out from too many failed logins.
function LoginBlockedScreen({ salon, minsLeft }) {
  const accent = salon.color || '#3F4A3A';
  const mailto = `mailto:support@ooniq.dk?subject=${encodeURIComponent('Login blokeret – ' + (salon.name || salon.id))}&body=${encodeURIComponent(`Hej Saloniq support,\n\nLoginet til ${salon.name || salon.id} (${salon.subdomain || ''}.saloniq.dk) er blevet blokeret efter for mange forkerte forsøg.\n\nHjælp venligst med at låse op.\n\nMvh\n`)}`;
  return (
    <div style={{
      minHeight: '100vh', display: 'flex', alignItems: 'center', justifyContent: 'center',
      background: 'linear-gradient(145deg, #f5f3ee 0%, #ece8df 100%)',
      fontFamily: "'Manrope', sans-serif", padding: 24,
    }}>
      <div style={{
        width: '100%', maxWidth: 460, background: '#fff', borderRadius: 20,
        padding: '40px 36px', boxShadow: '0 8px 48px rgba(0,0,0,0.12)',
      }}>
        <div style={{
          width: 56, height: 56, margin: '0 auto 18px',
          background: '#FEF2F2', borderRadius: 14,
          display: 'flex', alignItems: 'center', justifyContent: 'center',
          color: '#A03838',
        }}>
          <IconLock size={28} strokeWidth={2} />
        </div>
        <h1 style={{
          fontFamily: 'Fraunces, serif', fontSize: 24, fontWeight: 500,
          margin: '0 0 10px', textAlign: 'center',
        }}>Login blokeret</h1>
        <p style={{ fontSize: 14, color: '#666', lineHeight: 1.6, margin: '0 0 18px', textAlign: 'center' }}>
          Der er foretaget for mange forkerte login-forsøg på <strong>{salon.name}</strong>.
          Loginet er midlertidigt blokeret af sikkerhedsgrunde.
        </p>

        <div style={{
          padding: '12px 14px', marginBottom: 18,
          background: '#FBFAF6', border: '1px solid #EFEDE5',
          borderRadius: 10, fontSize: 13, color: '#666', lineHeight: 1.6, textAlign: 'center',
        }}>
          Prøv igen om <strong style={{ color: '#1a1a1a' }}>ca. {minsLeft} minut{minsLeft === 1 ? '' : 'ter'}</strong>,<br/>
          eller kontakt support for at låse op nu.
        </div>

        <a href={mailto} style={{
          display: 'block', width: '100%', boxSizing: 'border-box',
          padding: '13px', background: accent, color: '#fff',
          border: 'none', borderRadius: 10, fontSize: 14, fontWeight: 600,
          textAlign: 'center', textDecoration: 'none', fontFamily: 'inherit',
        }}>Kontakt support@ooniq.dk</a>
      </div>
    </div>
  );
}

// Login lockout: 3 forkerte forsøg inden for 15 min → block i 1 time.
// Stored i localStorage scoped per salon. UI-deterrent — Firebase Auth har
// sit eget server-side rate-limit som backstop.
const LOCKOUT_THRESHOLD = 3;
const LOCKOUT_WINDOW_MS = 15 * 60_000; // 15 min
const LOCKOUT_DURATION_MS = 60 * 60_000; // 1 time
function getLockoutState(salonId) {
  try {
    const raw = localStorage.getItem('saloniq_login_lockout_' + salonId);
    if (!raw) return { attempts: [], blockedUntil: 0 };
    const parsed = JSON.parse(raw);
    return {
      attempts: Array.isArray(parsed.attempts) ? parsed.attempts : [],
      blockedUntil: Number(parsed.blockedUntil) || 0,
    };
  } catch { return { attempts: [], blockedUntil: 0 }; }
}
function saveLockoutState(salonId, state) {
  try { localStorage.setItem('saloniq_login_lockout_' + salonId, JSON.stringify(state)); }
  catch {}
}
function recordFailedLogin(salonId) {
  const state = getLockoutState(salonId);
  const now = Date.now();
  const recent = state.attempts.filter(t => now - t < LOCKOUT_WINDOW_MS);
  recent.push(now);
  let blockedUntil = state.blockedUntil;
  let justBlocked = false;
  if (recent.length >= LOCKOUT_THRESHOLD && state.blockedUntil <= now) {
    blockedUntil = now + LOCKOUT_DURATION_MS;
    justBlocked = true;
  }
  saveLockoutState(salonId, { attempts: recent, blockedUntil });
  return { attempts: recent.length, blockedUntil, justBlocked };
}
function clearFailedLogins(salonId) {
  saveLockoutState(salonId, { attempts: [], blockedUntil: 0 });
}
function isBlocked(salonId) {
  const s = getLockoutState(salonId);
  return s.blockedUntil > Date.now();
}

function SalonLoginPage({ salon }) {
  const [error, setError] = React.useState('');
  const [loading, setLoading] = React.useState(false);
  const [remember, setRemember] = React.useState(() => {
    const v = localStorage.getItem('saloniq_remember');
    return v === null ? true : v === 'true'; // default ON
  });
  const [forgotOpen, setForgotOpen] = React.useState(false);
  const [blocked, setBlocked] = React.useState(() => isBlocked(salon.id));

  React.useEffect(() => {
    localStorage.setItem('saloniq_remember', String(remember));
  }, [remember]);

  // Tick once a minute so the 'blocked' state updates when the timer expires.
  React.useEffect(() => {
    if (!blocked) return;
    const i = setInterval(() => {
      if (!isBlocked(salon.id)) {
        setBlocked(false);
        clearFailedLogins(salon.id);
      }
    }, 30_000);
    return () => clearInterval(i);
  }, [blocked, salon.id]);

  const handleSubmit = React.useCallback(async (email, password) => {
    if (isBlocked(salon.id)) {
      setBlocked(true);
      return;
    }
    setLoading(true);
    setError('');
    try {
      const cred = await FB.signIn(email, password, { remember });
      // Verify user actually belongs to THIS salon (defense-in-depth alongside Firestore rules)
      if (FB.isSuperAdminEmail(email)) {
        clearFailedLogins(salon.id);
        return;
      }
      const profileDoc = await FB.db.collection('users').doc(cred.user.uid).get();
      const profile = profileDoc.exists ? profileDoc.data() : null;
      if (!profile || profile.salonId !== salon.id) {
        await FB.signOut();
        throw { code: 'saloniq/wrong-salon' };
      }
      clearFailedLogins(salon.id);
      // Success — AuthGate's onAuthChange will pick this up and render the app
    } catch (err) {
      if (err?.code === 'saloniq/wrong-salon') {
        setError(`Denne konto hører til en anden salon. Du forsøger at logge på ${salon.name}.`);
      } else {
        // Record the failed attempt and check if we should lock out
        const result = recordFailedLogin(salon.id);
        if (result.justBlocked) {
          // Fire-and-forget support alert. Failures here shouldn't block
          // showing the lockout screen.
          FB.db.collection('loginLockoutAlerts').add({
            salonId: salon.id,
            salonName: String(salon.name || '').slice(0, 200),
            subdomain: String(salon.subdomain || '').slice(0, 80),
            createdAt: firebase.firestore.FieldValue.serverTimestamp(),
            handled: false,
          }).catch(e => console.warn('loginLockoutAlerts write failed', e?.message));
        }
        if (result.blockedUntil > 0) {
          setBlocked(true);
        } else {
          const remaining = LOCKOUT_THRESHOLD - result.attempts;
          const baseMsg = FB.authErrorMessage(err);
          setError(remaining > 0
            ? `${baseMsg} (${remaining} forsøg tilbage)`
            : baseMsg);
        }
      }
      setLoading(false);
    }
  }, [salon]);

  if (blocked) {
    const s = getLockoutState(salon.id);
    const minsLeft = Math.max(1, Math.ceil((s.blockedUntil - Date.now()) / 60_000));
    return <LoginBlockedScreen salon={salon} minsLeft={minsLeft} />;
  }

  return (
    <>
      <LoginForm
        title={salon.name}
        subtitle={`Log ind for at administrere ${salon.name}`}
        accentColor={salon.color}
        logo={salon.logo}
        salonName={salon.name}
        onSubmit={handleSubmit}
        error={error}
        loading={loading}
        remember={remember}
        onRememberChange={setRemember}
        onForgotPassword={() => setForgotOpen(true)}
      />
      {forgotOpen && <ForgotPasswordDialog accentColor={salon.color} onClose={() => setForgotOpen(false)} />}
    </>
  );
}

// ─── Super Admin Login ────────────────────────────────────────────────────────
function SuperAdminLoginPage() {
  React.useEffect(() => { document.title = 'Saloniq · Admin'; }, []);
  const [error, setError] = React.useState('');
  const [loading, setLoading] = React.useState(false);
  const [remember, setRemember] = React.useState(() => {
    const v = localStorage.getItem('saloniq_remember');
    return v === null ? true : v === 'true';
  });
  const [forgotOpen, setForgotOpen] = React.useState(false);

  React.useEffect(() => {
    localStorage.setItem('saloniq_remember', String(remember));
  }, [remember]);

  const handleSubmit = React.useCallback(async (email, password) => {
    setLoading(true);
    setError('');
    try {
      if (!FB.isSuperAdminEmail(email)) {
        throw { code: 'saloniq/not-super-admin' };
      }
      await FB.signIn(email, password, { remember });
      // Success — AuthGate's onAuthChange picks this up
    } catch (err) {
      if (err?.code === 'saloniq/not-super-admin') {
        setError('Adgang nægtet. Kun autoriseret personale.');
      } else {
        setError(FB.authErrorMessage(err));
      }
      setLoading(false);
    }
  }, [remember]);

  return (
    <>
      <LoginForm
        title="Saloniq Admin"
        subtitle="Superadministratorpanel · kun autoriseret adgang"
        accentColor="#1E293B"
        onSubmit={handleSubmit}
        error={error}
        loading={loading}
        remember={remember}
        onRememberChange={setRemember}
        onForgotPassword={() => setForgotOpen(true)}
      />
      {forgotOpen && <ForgotPasswordDialog accentColor="#1E293B" onClose={() => setForgotOpen(false)} />}
    </>
  );
}

// ─── Forgot-password dialog ───────────────────────────────────────────────────
function ForgotPasswordDialog({ accentColor, onClose }) {
  const [email, setEmail] = React.useState('');
  const [submitting, setSubmitting] = React.useState(false);
  const [done, setDone] = React.useState(false);
  const [error, setError] = React.useState('');

  const submit = async (e) => {
    e?.preventDefault();
    if (!email.trim() || !email.includes('@')) { setError('Indtast en gyldig email'); return; }
    setSubmitting(true);
    setError('');
    try {
      await FB.sendPasswordReset(email);
      setDone(true);
    } catch (err) {
      // Don't reveal whether the email exists — show generic confirmation anyway
      // unless it's a clear network/format error.
      if (err?.code === 'auth/invalid-email') setError('Ugyldig email-adresse');
      else if (err?.code === 'auth/network-request-failed') setError('Ingen forbindelse. Tjek dit netværk.');
      else setDone(true); // pretend success even if user not found
    }
    setSubmitting(false);
  };

  return (
    <div style={{
      position: 'fixed', inset: 0, background: 'rgba(20,20,20,0.55)', zIndex: 1000,
      backdropFilter: 'blur(4px)',
      display: 'flex', alignItems: 'center', justifyContent: 'center',
      padding: 20, fontFamily: "'Manrope', sans-serif",
    }}>
      <div style={{
        background: '#fff', borderRadius: 16, padding: 32,
        width: '100%', maxWidth: 420,
        boxShadow: '0 12px 48px rgba(0,0,0,0.20)',
        animation: 'slideUp 0.25s ease',
      }}>
        {done ? (
          <>
            <div style={{
              width: 56, height: 56, margin: '0 auto 16px',
              background: '#F4F7F0', borderRadius: 14,
              display: 'flex', alignItems: 'center', justifyContent: 'center', color: '#3F5A30',
            }}>
              <IconMail size={26} strokeWidth={1.8} />
            </div>
            <h2 style={{ fontFamily: 'Fraunces, serif', fontSize: 22, fontWeight: 500, margin: '0 0 8px', textAlign: 'center' }}>
              Tjek din email
            </h2>
            <p style={{ fontSize: 14, color: '#666', margin: '0 0 22px', lineHeight: 1.55, textAlign: 'center' }}>
              Hvis <strong>{email}</strong> er knyttet til en konto, har vi sendt et link til at nulstille
              din adgangskode. Linket virker i 1 time.
            </p>
            <button onClick={onClose} style={{
              width: '100%', padding: '12px',
              background: accentColor || '#3F4A3A', color: '#fff',
              border: 'none', borderRadius: 10, fontSize: 14, fontWeight: 600,
              cursor: 'pointer', fontFamily: 'inherit',
            }}>OK</button>
          </>
        ) : (
          <form onSubmit={submit}>
            <h2 style={{ fontFamily: 'Fraunces, serif', fontSize: 22, fontWeight: 500, margin: '0 0 8px' }}>
              Glemt adgangskode?
            </h2>
            <p style={{ fontSize: 14, color: '#666', margin: '0 0 22px', lineHeight: 1.55 }}>
              Indtast din email, så sender vi dig et link hvor du kan vælge en ny adgangskode.
            </p>
            <label style={{ display: 'block', fontSize: 12, fontWeight: 700, color: '#555', marginBottom: 6, textTransform: 'uppercase', letterSpacing: '0.06em' }}>
              Email
            </label>
            <input
              type="email" value={email} autoFocus
              autoComplete="email"
              onChange={e => { setEmail(e.target.value); setError(''); }}
              placeholder="dig@dinsalon.dk"
              style={{
                width: '100%', padding: '12px 14px', boxSizing: 'border-box',
                border: `1.5px solid ${error ? '#FECACA' : '#DDD9CE'}`,
                borderRadius: 10, fontSize: 14, outline: 'none',
                background: '#FBFAF6', fontFamily: 'inherit',
              }}
            />
            {error && (
              <div style={{ marginTop: 10, padding: '8px 12px', background: '#FEF2F2', border: '1px solid #FECACA', borderRadius: 8, fontSize: 13, color: '#B91C1C' }}>
                {error}
              </div>
            )}
            <div style={{ display: 'flex', gap: 10, marginTop: 22 }}>
              <button type="button" onClick={onClose} disabled={submitting} style={{
                flex: 1, padding: '12px', background: '#fff', color: '#666',
                border: '1.5px solid #DDD9CE', borderRadius: 10, fontSize: 14,
                cursor: 'pointer', fontFamily: 'inherit',
              }}>Annuller</button>
              <button type="submit" disabled={submitting || !email.trim()} style={{
                flex: 2, padding: '12px',
                background: (submitting || !email.trim()) ? '#D4D0C8' : (accentColor || '#3F4A3A'),
                color: '#fff', border: 'none', borderRadius: 10, fontSize: 14, fontWeight: 600,
                cursor: (submitting || !email.trim()) ? 'not-allowed' : 'pointer',
                fontFamily: 'inherit',
              }}>{submitting ? 'Sender…' : 'Send link'}</button>
            </div>
          </form>
        )}
      </div>
    </div>
  );
}

// ─── Color helpers ────────────────────────────────────────────────────────────
const clamp = (v, min, max) => Math.max(min, Math.min(max, v));
function hexToRgb(hex) {
  const m = String(hex || '').match(/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i);
  return m ? { r: parseInt(m[1], 16), g: parseInt(m[2], 16), b: parseInt(m[3], 16) } : { r: 63, g: 74, b: 58 };
}
function rgbToHex({ r, g, b }) {
  const toHex = (n) => Math.round(clamp(n, 0, 255)).toString(16).padStart(2, '0');
  return '#' + toHex(r) + toHex(g) + toHex(b);
}

// Color picker for the dark super-admin theme
function ColorPicker({ value, onChange, suggestions }) {
  const hex = value || '#3F4A3A';
  const rgb = hexToRgb(hex);
  const [hexDraft, setHexDraft] = React.useState(hex);

  React.useEffect(() => { setHexDraft(hex); }, [hex]);

  const updateRgb = (channel, v) => {
    const n = clamp(parseInt(v) || 0, 0, 255);
    onChange(rgbToHex({ ...rgb, [channel]: n }));
  };

  const commitHex = () => {
    const cleaned = hexDraft.startsWith('#') ? hexDraft : '#' + hexDraft;
    if (/^#[a-f\d]{6}$/i.test(cleaned)) onChange(cleaned.toLowerCase());
    else setHexDraft(hex); // revert on invalid
  };

  const presets = suggestions || [
    '#3F4A3A', '#1E40AF', '#9333EA', '#BE123C', '#B45309',
    '#0F766E', '#374151', '#C2410C', '#DB2777', '#0EA5E9',
    '#16A34A', '#FACC15',
  ];

  const sliderTrack = (channel) => {
    const left  = { ...rgb, [channel]: 0 };
    const right = { ...rgb, [channel]: 255 };
    return `linear-gradient(to right, ${rgbToHex(left)}, ${rgbToHex(right)})`;
  };

  return (
    <div>
      <div style={{ display: 'flex', gap: 16, alignItems: 'flex-start' }}>
        {/* Big swatch preview */}
        <div style={{
          width: 80, height: 80, borderRadius: 12, background: hex,
          border: '2px solid #334155', flexShrink: 0,
          boxShadow: '0 4px 12px rgba(0,0,0,0.30)',
        }} />

        <div style={{ flex: 1, minWidth: 0 }}>
          {/* HEX */}
          <div style={{ display: 'flex', alignItems: 'center', gap: 10, marginBottom: 10 }}>
            <span style={{ fontSize: 11, color: '#94A3B8', fontWeight: 700, width: 28 }}>HEX</span>
            <input
              type="text"
              value={hexDraft}
              onChange={e => setHexDraft(e.target.value)}
              onBlur={commitHex}
              onKeyDown={e => { if (e.key === 'Enter') { e.preventDefault(); commitHex(); } }}
              spellCheck={false}
              style={{
                flex: 1, padding: '7px 10px',
                background: '#0F172A', border: '1px solid #334155',
                borderRadius: 7, color: '#F8FAFC',
                fontFamily: 'ui-monospace, SF Mono, monospace', fontSize: 13,
                outline: 'none', textTransform: 'lowercase',
              }}
            />
          </div>

          {/* RGB sliders */}
          {['r', 'g', 'b'].map((c) => (
            <div key={c} style={{ display: 'flex', alignItems: 'center', gap: 10, marginBottom: 6 }}>
              <span style={{
                fontSize: 11, color: '#94A3B8', fontWeight: 700, width: 28,
                textTransform: 'uppercase',
              }}>{c}</span>
              <input
                type="range" min={0} max={255} value={rgb[c]}
                onChange={e => updateRgb(c, e.target.value)}
                style={{
                  flex: 1, height: 6, borderRadius: 3, appearance: 'none',
                  background: sliderTrack(c), outline: 'none', cursor: 'pointer',
                }}
              />
              <input
                type="number" min={0} max={255} value={rgb[c]}
                onChange={e => updateRgb(c, e.target.value)}
                style={{
                  width: 52, padding: '5px 6px',
                  background: '#0F172A', border: '1px solid #334155',
                  borderRadius: 5, color: '#F8FAFC', fontSize: 12,
                  outline: 'none', textAlign: 'center',
                }}
              />
            </div>
          ))}
        </div>
      </div>

      {/* Quick-pick swatches */}
      <div style={{ marginTop: 14 }}>
        <div style={{ fontSize: 10, color: '#64748B', fontWeight: 700, marginBottom: 6, letterSpacing: '0.06em', textTransform: 'uppercase' }}>
          Forslag
        </div>
        <div style={{ display: 'flex', gap: 6, flexWrap: 'wrap' }}>
          {presets.map(c => {
            const active = c.toLowerCase() === hex.toLowerCase();
            return (
              <button key={c} type="button" onClick={() => onChange(c.toLowerCase())} style={{
                width: 26, height: 26, borderRadius: 7, background: c, border: 'none',
                cursor: 'pointer', flexShrink: 0,
                outline: active ? '2px solid #6366F1' : '1px solid rgba(255,255,255,0.08)',
                outlineOffset: active ? 2 : 0,
              }} title={c} />
            );
          })}
        </div>
      </div>

      <style>{`
        input[type="range"]::-webkit-slider-thumb {
          appearance: none;
          width: 18px; height: 18px;
          border-radius: 50%;
          background: #fff;
          border: 2px solid #475569;
          cursor: pointer;
          box-shadow: 0 2px 4px rgba(0,0,0,0.3);
        }
        input[type="range"]::-moz-range-thumb {
          width: 18px; height: 18px;
          border-radius: 50%;
          background: #fff;
          border: 2px solid #475569;
          cursor: pointer;
        }
      `}</style>
    </div>
  );
}

// ─── Admin: Create Salon Form ─────────────────────────────────────────────────
// IMPORTANT: this stays at module scope. Defining it inside SalonCreateForm
// would re-create the component on every render, which unmounts the children
// — and that was the cause of the "input loses focus on every keystroke" bug.
function CreateFormSection({ label, children }) {
  return (
    <div style={{
      background: '#1E293B', borderRadius: 14, padding: 24,
      border: '1px solid #334155', marginBottom: 14,
    }}>
      <div style={{
        fontSize: 11, fontWeight: 700, color: '#64748B',
        textTransform: 'uppercase', letterSpacing: '0.1em', marginBottom: 18,
      }}>{label}</div>
      {children}
    </div>
  );
}

function SalonCreateForm({ onCancel, onCreate, existingSubdomains }) {
  const [form, setForm] = React.useState({
    name: '', subdomain: '', color: '#3F4A3A',
    industry: 'frisor',
    ownerName: '', ownerEmail: '', ownerPassword: '',
  });
  const [errors, setErrors] = React.useState({});
  const [submitting, setSubmitting] = React.useState(false);
  const [submitError, setSubmitError] = React.useState('');

  const set = (k, v) => setForm(f => ({ ...f, [k]: v }));

  const validate = () => {
    const e = {};
    if (!form.name.trim()) e.name = 'Navn er påkrævet';
    if (!form.subdomain.trim()) e.subdomain = 'Subdomæne er påkrævet';
    if (form.subdomain && !/^[a-z0-9][a-z0-9-]*$/.test(form.subdomain)) e.subdomain = 'Kun bogstaver, tal og bindestreg';
    if (existingSubdomains.includes(form.subdomain)) e.subdomain = 'Subdomænet er allerede i brug';
    if (!form.ownerEmail.trim() || !form.ownerEmail.includes('@')) e.ownerEmail = 'Gyldig email er påkrævet';
    if (!form.ownerPassword || form.ownerPassword.length < 6) e.ownerPassword = 'Min. 6 tegn';
    return e;
  };

  const handleSubmit = async (e) => {
    e.preventDefault();
    const errs = validate();
    if (Object.keys(errs).length) { setErrors(errs); return; }
    setSubmitting(true);
    setSubmitError('');
    try {
      await onCreate(form);
    } catch (err) {
      setSubmitError(FB.authErrorMessage(err));
      setSubmitting(false);
    }
  };

  const inp = (field, label, type = 'text', hint) => (
    <div style={{ marginBottom: 16 }}>
      <label style={{
        display: 'block', fontSize: 12, fontWeight: 700, color: '#94A3B8',
        marginBottom: 6, textTransform: 'uppercase', letterSpacing: '0.06em',
      }}>{label}</label>
      <input
        type={type}
        value={form[field]}
        onChange={e => set(field, field === 'subdomain'
          ? e.target.value.toLowerCase().replace(/[^a-z0-9-]/g, '')
          : e.target.value)}
        style={{
          width: '100%', padding: '10px 13px', boxSizing: 'border-box',
          background: '#0F172A', border: `1.5px solid ${errors[field] ? '#EF4444' : '#334155'}`,
          borderRadius: 9, fontSize: 14, color: '#F8FAFC', outline: 'none', fontFamily: 'inherit',
        }}
      />
      {hint && !errors[field] && <div style={{ fontSize: 11, color: '#64748B', marginTop: 4 }}>{hint}</div>}
      {errors[field] && <div style={{ fontSize: 11, color: '#EF4444', marginTop: 4 }}>{errors[field]}</div>}
    </div>
  );

  return (
    <div>
      <div style={{ display: 'flex', alignItems: 'center', gap: 14, marginBottom: 28 }}>
        <button onClick={onCancel} style={{
          background: 'none', border: 'none', color: '#64748B', cursor: 'pointer',
          fontSize: 22, lineHeight: 1, padding: 0,
        }}>←</button>
        <h2 style={{ color: '#F8FAFC', fontSize: 20, fontWeight: 600, margin: 0 }}>Opret ny salon</h2>
      </div>

      <form onSubmit={handleSubmit} style={{ maxWidth: 520 }}>
        <CreateFormSection label="Salonoplysninger">
          {inp('name', 'Salonens navn', 'text', 'F.eks. HOB Frisør')}
          {inp('subdomain', 'Subdomæne', 'text', `URL: ${form.subdomain || 'eksempel'}.saloniq.dk`)}
          <div style={{ marginBottom: 16 }}>
            <label style={{
              display: 'block', fontSize: 12, fontWeight: 700, color: '#94A3B8',
              marginBottom: 6, textTransform: 'uppercase', letterSpacing: '0.06em',
            }}>Branche</label>
            <select
              value={form.industry}
              onChange={e => set('industry', e.target.value)}
              style={{
                width: '100%', padding: '10px 13px', boxSizing: 'border-box',
                background: '#0F172A', border: '1.5px solid #334155',
                borderRadius: 9, fontSize: 14, color: '#F8FAFC', outline: 'none', fontFamily: 'inherit',
              }}
            >
              {(window.INDUSTRY_OPTIONS || []).map(o => (
                <option key={o.id} value={o.id}>{o.label}</option>
              ))}
            </select>
            <div style={{ fontSize: 11, color: '#64748B', marginTop: 4 }}>
              Bestemmer hvilket ikon der bruges til 'Ydelser' i salonens app.
            </div>
          </div>
          <div style={{ marginBottom: 4 }}>
            <label style={{
              display: 'block', fontSize: 12, fontWeight: 700, color: '#94A3B8',
              marginBottom: 10, textTransform: 'uppercase', letterSpacing: '0.06em',
            }}>Salonens brandfarve</label>
            <ColorPicker value={form.color} onChange={c => set('color', c)} />
          </div>
        </CreateFormSection>

        <CreateFormSection label="Ejer-konto">
          {inp('ownerName', 'Fulde navn')}
          {inp('ownerEmail', 'Email', 'email', 'Bruges som login')}
          {inp('ownerPassword', 'Adgangskode', 'password', 'Min. 6 tegn — gemmes hashet i Firebase Auth')}
        </CreateFormSection>

        {submitError && (
          <div style={{
            padding: '12px 14px', marginBottom: 12,
            background: '#3B0000', border: '1px solid #7F1D1D',
            borderRadius: 8, fontSize: 13, color: '#FCA5A5',
          }}>{submitError}</div>
        )}

        <div style={{ display: 'flex', gap: 10 }}>
          <button type="button" onClick={onCancel} disabled={submitting} style={{
            flex: 1, padding: '12px', background: '#334155', color: '#94A3B8',
            border: 'none', borderRadius: 10, fontSize: 14, cursor: 'pointer', fontFamily: 'inherit',
            opacity: submitting ? 0.5 : 1,
          }}>Annuller</button>
          <button type="submit" disabled={submitting} style={{
            flex: 2, padding: '12px',
            background: submitting ? '#475569' : '#6366F1',
            color: '#fff', border: 'none', borderRadius: 10, fontSize: 14, fontWeight: 600,
            cursor: submitting ? 'not-allowed' : 'pointer', fontFamily: 'inherit',
          }}>{submitting ? 'Opretter…' : 'Opret salon'}</button>
        </div>
      </form>
    </div>
  );
}

// ─── Admin: Edit Salon Modal ──────────────────────────────────────────────────
function SalonEditModal({ salon, onClose, onSaved }) {
  const [name, setName] = React.useState(salon.name);
  const [color, setColor] = React.useState(salon.color || '#3F4A3A');
  const [industry, setIndustry] = React.useState(salon.industry || 'frisor');
  const [logo, setLogo] = React.useState(salon.logo || null);
  const [smtp, setSmtp] = React.useState({
    host: salon.smtp?.host || '',
    port: salon.smtp?.port || 587,
    user: salon.smtp?.user || '',
    password: salon.smtp?.password || '',
    fromEmail: salon.smtp?.fromEmail || '',
    fromName: salon.smtp?.fromName || '',
  });
  const [users, setUsers] = React.useState([]);
  const [usersLoading, setUsersLoading] = React.useState(true);
  const [saving, setSaving] = React.useState(false);
  const [error, setError] = React.useState('');
  const [actionMsg, setActionMsg] = React.useState('');

  const [addingUser, setAddingUser] = React.useState(false);
  const [newUser, setNewUser] = React.useState({ email: '', password: '', name: '', role: 'staff' });
  const [addingState, setAddingState] = React.useState({ submitting: false, error: '' });
  const fileInputRef = React.useRef(null);

  const inp = { padding: '9px 12px', background: '#1E293B', border: '1px solid #334155', borderRadius: 8, fontSize: 13, color: '#F8FAFC', outline: 'none', fontFamily: 'inherit', boxSizing: 'border-box' };

  const handleLogoFile = async (e) => {
    const file = e.target.files?.[0];
    if (!file) return;
    if (file.size > 8 * 1024 * 1024) {
      setError('Logoet er for stort (max 8 MB før komprimering).');
      return;
    }
    if (!/^image\//.test(file.type)) {
      setError('Filen er ikke et billede.');
      return;
    }
    try {
      const dataUrl = await window.SaloniqResizeImage(file, 400, 0.85);
      setLogo(dataUrl);
      setError('');
    } catch (err) {
      setError('Kunne ikke læse logoet: ' + (err?.message || 'ukendt fejl'));
    }
  };

  const handleResetUserPassword = async (userEmail) => {
    if (!confirm(`Send et adgangskode-reset link til ${userEmail}?`)) return;
    try {
      await FB.sendPasswordReset(userEmail);
      setActionMsg(`Reset-link sendt til ${userEmail}.`);
      setTimeout(() => setActionMsg(''), 4000);
    } catch (err) {
      alert('Kunne ikke sende: ' + FB.authErrorMessage(err));
    }
  };

  const handleResetSalonPin = async () => {
    if (!confirm(`Nulstil PIN-koden for ${salon.name}? Ejer bliver bedt om at vælge en ny PIN ved næste login.`)) return;
    try {
      await FB.resetSalonPin(salon.id);
      setActionMsg('PIN nulstillet — ejer skal vælge en ny ved næste login.');
      setTimeout(() => setActionMsg(''), 4000);
    } catch (err) {
      alert('Kunne ikke nulstille: ' + FB.authErrorMessage(err));
    }
  };

  React.useEffect(() => {
    let cancelled = false;
    FB.listSalonUsers(salon.id).then(list => {
      if (!cancelled) { setUsers(list); setUsersLoading(false); }
    }).catch(() => { if (!cancelled) setUsersLoading(false); });
    return () => { cancelled = true; };
  }, [salon.id]);

  const handleAddUser = async () => {
    if (!newUser.email.trim() || !newUser.password) return;
    setAddingState({ submitting: true, error: '' });
    try {
      const uid = await FB.addSalonUser({ salonId: salon.id, ...newUser });
      setUsers(u => [...u, { id: uid, email: newUser.email.trim().toLowerCase(), salonId: salon.id, role: newUser.role, name: newUser.name || newUser.email }]);
      setNewUser({ email: '', password: '', name: '', role: 'staff' });
      setAddingUser(false);
      setAddingState({ submitting: false, error: '' });
    } catch (err) {
      setAddingState({ submitting: false, error: FB.authErrorMessage(err) });
    }
  };

  const handleRemoveUser = async (uid) => {
    if (!confirm('Fjern brugeren? Brugerens email/adgangskode skal slettes manuelt fra Firebase Auth Console.')) return;
    try {
      await FB.removeSalonUser(uid);
      setUsers(us => us.filter(x => x.id !== uid));
    } catch (err) {
      alert('Kunne ikke fjerne: ' + FB.authErrorMessage(err));
    }
  };

  const handleSave = async () => {
    setSaving(true);
    setError('');
    try {
      // Only persist a non-empty SMTP override; if all key fields are blank
      // we clear it so the salon falls back to Saloniq's default SMTP.
      const smtpOverride = (smtp.host && smtp.user && smtp.password)
        ? {
            host: smtp.host.trim(),
            port: Number(smtp.port) || 587,
            user: smtp.user.trim(),
            password: smtp.password,
            fromEmail: smtp.fromEmail.trim() || '',
            fromName: smtp.fromName.trim() || '',
          }
        : null;
      await FB.updateSalon(salon.id, { name, color, industry, logo: logo || null, smtp: smtpOverride });
      await onSaved({ ...salon, name, color, industry, logo, smtp: smtpOverride });
    } catch (err) {
      setError(FB.authErrorMessage(err));
      setSaving(false);
    }
  };

  return (
    <div style={{
      position: 'fixed', inset: 0, background: 'rgba(0,0,0,0.75)',
      display: 'flex', alignItems: 'center', justifyContent: 'center', zIndex: 999,
    }}>
      <div style={{
        background: '#1E293B', borderRadius: 16, padding: 32,
        width: 520, maxHeight: '88vh', overflow: 'auto',
        border: '1px solid #334155',
      }}>
        <h3 style={{ color: '#F8FAFC', margin: '0 0 22px', fontSize: 18, fontWeight: 600 }}>
          Rediger {salon.name}
        </h3>

        <div style={{ marginBottom: 16 }}>
          <label style={{ display: 'block', fontSize: 12, fontWeight: 700, color: '#94A3B8', marginBottom: 6, textTransform: 'uppercase', letterSpacing: '0.06em' }}>Navn</label>
          <input value={name} onChange={e => setName(e.target.value)} style={{ ...inp, width: '100%' }} />
        </div>

        <div style={{ marginBottom: 16 }}>
          <label style={{ display: 'block', fontSize: 12, fontWeight: 700, color: '#94A3B8', marginBottom: 6, textTransform: 'uppercase', letterSpacing: '0.06em' }}>Branche</label>
          <select value={industry} onChange={e => setIndustry(e.target.value)} style={{ ...inp, width: '100%' }}>
            {(window.INDUSTRY_OPTIONS || []).map(o => (
              <option key={o.id} value={o.id}>{o.label}</option>
            ))}
          </select>
          <div style={{ fontSize: 11, color: '#64748B', marginTop: 4 }}>
            Styrer hvilket ikon der vises på 'Ydelser' i salonens app.
          </div>
        </div>

        <div style={{ marginBottom: 22 }}>
          <label style={{ display: 'block', fontSize: 12, fontWeight: 700, color: '#94A3B8', marginBottom: 10, textTransform: 'uppercase', letterSpacing: '0.06em' }}>Salonens brandfarve</label>
          <ColorPicker value={color} onChange={setColor} />
        </div>

        <div style={{ marginBottom: 22 }}>
          <label style={{ display: 'block', fontSize: 12, fontWeight: 700, color: '#94A3B8', marginBottom: 10, textTransform: 'uppercase', letterSpacing: '0.06em' }}>Logo</label>
          <div style={{ display: 'flex', alignItems: 'center', gap: 14 }}>
            <div style={{
              width: 72, height: 72, borderRadius: 12,
              background: logo ? '#fff' : '#0F172A',
              border: '1.5px solid #334155',
              display: 'flex', alignItems: 'center', justifyContent: 'center',
              overflow: 'hidden', flexShrink: 0,
            }}>
              {logo ? (
                <img src={logo} alt="Logo" style={{ maxWidth: '100%', maxHeight: '100%', objectFit: 'contain' }} />
              ) : (
                <div style={{
                  fontFamily: 'Fraunces, serif', fontSize: 28,
                  color: color, fontWeight: 500,
                }}>{name[0]?.toUpperCase() || 'S'}</div>
              )}
            </div>
            <div style={{ flex: 1 }}>
              <input
                ref={fileInputRef}
                type="file" accept="image/png,image/jpeg,image/svg+xml,image/webp"
                onChange={handleLogoFile} style={{ display: 'none' }}
              />
              <div style={{ display: 'flex', gap: 8 }}>
                <button onClick={() => fileInputRef.current?.click()} style={{
                  background: '#334155', color: '#F8FAFC', border: 'none', borderRadius: 7,
                  padding: '7px 14px', fontSize: 12, cursor: 'pointer', fontFamily: 'inherit',
                }}>{logo ? 'Skift logo' : 'Upload logo'}</button>
                {logo && (
                  <button onClick={() => setLogo(null)} style={{
                    background: 'transparent', color: '#94A3B8', border: '1px solid #334155',
                    borderRadius: 7, padding: '7px 14px', fontSize: 12, cursor: 'pointer', fontFamily: 'inherit',
                  }}>Fjern</button>
                )}
              </div>
              <div style={{ fontSize: 11, color: '#64748B', marginTop: 6, lineHeight: 1.4 }}>
                PNG, JPG eller SVG. Max 500 KB. Vises på salonens login-side.
              </div>
            </div>
          </div>
        </div>

        {/* SMTP override — leave blank to use Saloniq's default mail-server.
            Stored at /salons/{id}.smtp; only the salon's own users + super-
            admin can read or modify. */}
        <div style={{ marginBottom: 22 }}>
          <label style={{ display: 'block', fontSize: 12, fontWeight: 700, color: '#94A3B8', marginBottom: 10, textTransform: 'uppercase', letterSpacing: '0.06em' }}>SMTP / email-afsendelse</label>
          <div style={{ fontSize: 11, color: '#64748B', marginBottom: 10, lineHeight: 1.5 }}>
            Lad felterne stå tomme for at bruge Saloniqs standard mail-server. Udfyld dem hvis salonen vil sende fra sin egen mail-adresse.
          </div>
          <div style={{ display: 'grid', gridTemplateColumns: '2fr 1fr', gap: 8, marginBottom: 8 }}>
            <input placeholder="SMTP-server (fx mail-eu.smtp2go.com)" value={smtp.host}
              onChange={e => setSmtp(s => ({ ...s, host: e.target.value }))} style={inp} />
            <input placeholder="Port" type="number" value={smtp.port}
              onChange={e => setSmtp(s => ({ ...s, port: e.target.value }))} style={inp} />
          </div>
          <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 8, marginBottom: 8 }}>
            <input placeholder="Brugernavn" value={smtp.user}
              onChange={e => setSmtp(s => ({ ...s, user: e.target.value }))} style={inp} />
            <input placeholder="Adgangskode" type="password" value={smtp.password}
              onChange={e => setSmtp(s => ({ ...s, password: e.target.value }))} style={inp} autoComplete="new-password" />
          </div>
          <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 8 }}>
            <input placeholder="Afsender-email (fx booking@dinsalon.dk)" value={smtp.fromEmail}
              onChange={e => setSmtp(s => ({ ...s, fromEmail: e.target.value }))} style={inp} />
            <input placeholder="Afsender-navn (fx Salon Klipperiet)" value={smtp.fromName}
              onChange={e => setSmtp(s => ({ ...s, fromName: e.target.value }))} style={inp} />
          </div>
        </div>

        <div style={{ marginBottom: 22 }}>
          <label style={{ display: 'block', fontSize: 12, fontWeight: 700, color: '#94A3B8', marginBottom: 10, textTransform: 'uppercase', letterSpacing: '0.06em' }}>Sikkerhed</label>
          <button onClick={handleResetSalonPin} style={{
            background: '#3B0000', color: '#FCA5A5', border: '1px solid #7F1D1D',
            borderRadius: 7, padding: '8px 14px', fontSize: 13, cursor: 'pointer',
            fontFamily: 'inherit', display: 'flex', alignItems: 'center', gap: 8,
          }}>
            <IconLock size={14} strokeWidth={1.8} /> Nulstil salon-PIN
          </button>
          <div style={{ fontSize: 11, color: '#64748B', marginTop: 6, lineHeight: 1.4 }}>
            Ejer bliver bedt om at vælge en ny PIN ved næste login.
          </div>
        </div>

        {actionMsg && (
          <div style={{
            marginBottom: 16, padding: '10px 14px',
            background: '#052E16', border: '1px solid #14532D',
            borderRadius: 8, fontSize: 13, color: '#86EFAC',
          }}>✓ {actionMsg}</div>
        )}

        <div style={{ marginBottom: 24 }}>
          <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 12 }}>
            <label style={{ fontSize: 12, fontWeight: 700, color: '#94A3B8', textTransform: 'uppercase', letterSpacing: '0.06em' }}>Brugere</label>
            <button onClick={() => setAddingUser(true)} style={{
              background: '#334155', color: '#94A3B8', border: 'none', borderRadius: 7,
              padding: '5px 12px', fontSize: 12, cursor: 'pointer', fontFamily: 'inherit',
            }}>+ Tilføj</button>
          </div>

          {usersLoading ? (
            <div style={{ textAlign: 'center', padding: 16, color: '#64748B', fontSize: 13 }}>Henter brugere…</div>
          ) : (
            <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
              {users.length === 0 && (
                <div style={{ textAlign: 'center', padding: 14, color: '#64748B', fontSize: 12 }}>Ingen brugere endnu</div>
              )}
              {users.map(u => (
                <div key={u.id} style={{
                  background: '#0F172A', borderRadius: 10, padding: '12px 14px',
                  display: 'flex', justifyContent: 'space-between', alignItems: 'center', gap: 10,
                }}>
                  <div style={{ minWidth: 0, flex: 1 }}>
                    <div style={{ color: '#F8FAFC', fontSize: 14, fontWeight: 500 }}>{u.name || u.email}</div>
                    <div style={{ color: '#64748B', fontSize: 12, marginTop: 2, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
                      {u.email} · {u.role}
                    </div>
                  </div>
                  <div style={{ display: 'flex', gap: 6, flexShrink: 0 }}>
                    <button onClick={() => handleResetUserPassword(u.email)} title="Send adgangskode-reset link" style={{
                      background: '#334155', color: '#94A3B8', border: 'none',
                      borderRadius: 6, padding: '6px 10px', fontSize: 12, cursor: 'pointer', fontFamily: 'inherit',
                    }}>Reset adgangskode</button>
                    {u.role !== 'owner' && (
                      <button onClick={() => handleRemoveUser(u.id)} title="Fjern bruger" style={{
                        background: 'none', color: '#EF4444', border: 'none',
                        cursor: 'pointer', fontSize: 18, padding: '0 4px',
                      }}>×</button>
                    )}
                  </div>
                </div>
              ))}
            </div>
          )}

          {addingUser && (
            <div style={{ marginTop: 10, background: '#0F172A', borderRadius: 10, padding: 14, border: '1px solid #334155' }}>
              <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 8, marginBottom: 8 }}>
                <input placeholder="Navn" value={newUser.name} onChange={e => setNewUser(u => ({ ...u, name: e.target.value }))} style={inp} />
                <input placeholder="Email" type="email" value={newUser.email} onChange={e => setNewUser(u => ({ ...u, email: e.target.value }))} style={inp} />
                <input placeholder="Adgangskode (min. 6 tegn)" type="password" value={newUser.password} onChange={e => setNewUser(u => ({ ...u, password: e.target.value }))} style={inp} />
                <select value={newUser.role} onChange={e => setNewUser(u => ({ ...u, role: e.target.value }))} style={inp}>
                  <option value="staff">Medarbejder</option>
                  <option value="manager">Manager</option>
                </select>
              </div>
              {addingState.error && (
                <div style={{ marginBottom: 8, padding: '8px 12px', background: '#3B0000', color: '#FCA5A5', borderRadius: 6, fontSize: 12 }}>
                  {addingState.error}
                </div>
              )}
              <div style={{ display: 'flex', gap: 8 }}>
                <button onClick={() => setAddingUser(false)} disabled={addingState.submitting} style={{
                  flex: 1, padding: '8px', background: '#334155', color: '#94A3B8',
                  border: 'none', borderRadius: 8, cursor: 'pointer', fontFamily: 'inherit',
                }}>Annuller</button>
                <button onClick={handleAddUser} disabled={addingState.submitting} style={{
                  flex: 2, padding: '8px',
                  background: addingState.submitting ? '#475569' : '#6366F1',
                  color: '#fff', border: 'none', borderRadius: 8, fontWeight: 600,
                  cursor: addingState.submitting ? 'not-allowed' : 'pointer', fontFamily: 'inherit',
                }}>{addingState.submitting ? 'Opretter…' : 'Tilføj bruger'}</button>
              </div>
            </div>
          )}
        </div>

        {error && (
          <div style={{ marginBottom: 12, padding: '10px 14px', background: '#3B0000', color: '#FCA5A5', borderRadius: 8, fontSize: 13 }}>{error}</div>
        )}

        <div style={{ display: 'flex', gap: 10 }}>
          <button onClick={onClose} disabled={saving} style={{
            flex: 1, padding: '12px', background: '#334155', color: '#94A3B8',
            border: 'none', borderRadius: 10, cursor: 'pointer', fontFamily: 'inherit',
          }}>Annuller</button>
          <button onClick={handleSave} disabled={saving} style={{
            flex: 2, padding: '12px',
            background: saving ? '#475569' : '#6366F1',
            color: '#fff', border: 'none', borderRadius: 10, fontWeight: 600,
            cursor: saving ? 'not-allowed' : 'pointer', fontFamily: 'inherit',
          }}>{saving ? 'Gemmer…' : 'Gem ændringer'}</button>
        </div>
      </div>
    </div>
  );
}

// ─── Super Admin Panel ────────────────────────────────────────────────────────
function SuperAdminPanel({ onLogout, currentUserEmail }) {
  React.useEffect(() => { document.title = 'Saloniq · Admin'; }, []);
  const [salons, setSalons] = React.useState(null); // null = loading
  const [view, setView] = React.useState('list');
  const [editing, setEditing] = React.useState(null);
  const [deleting, setDeleting] = React.useState(null);
  const [deletingState, setDeletingState] = React.useState({ submitting: false, error: '' });
  const [search, setSearch] = React.useState('');
  const [letterFilter, setLetterFilter] = React.useState(null); // null | 'A'..'Å' | '#'

  const reload = React.useCallback(async () => {
    try {
      const list = await FB.listSalons();
      setSalons(list);
    } catch (err) {
      console.error('Failed to load salons', err);
      setSalons([]);
    }
  }, []);

  React.useEffect(() => { reload(); }, [reload]);

  const handleCreate = async (data) => {
    await FB.createSalonWithOwner({
      salonName: data.name,
      subdomain: data.subdomain,
      color: data.color,
      industry: data.industry,
      ownerEmail: data.ownerEmail,
      ownerPassword: data.ownerPassword,
      ownerName: data.ownerName,
    });
    await reload();
    setView('list');
  };

  const handleToggleActive = async (salon) => {
    try {
      await FB.setSalonActive(salon.id, !salon.active);
      setSalons(list => list.map(x => x.id === salon.id ? { ...x, active: !salon.active } : x));
    } catch (err) {
      alert('Kunne ikke opdatere: ' + FB.authErrorMessage(err));
    }
  };

  const confirmDelete = async () => {
    if (!deleting) return;
    setDeletingState({ submitting: true, error: '' });
    try {
      await FB.deleteSalon(deleting.id);
      setSalons(list => list.filter(x => x.id !== deleting.id));
      setDeleting(null);
      setDeletingState({ submitting: false, error: '' });
    } catch (err) {
      setDeletingState({ submitting: false, error: FB.authErrorMessage(err) });
    }
  };

  if (salons === null) return <LoadingScreen />;

  const statItems = [
    { label: 'Saloner i alt', value: salons.length, color: '#818CF8' },
    { label: 'Aktive', value: salons.filter(s => s.active).length, color: '#34D399' },
    { label: 'Inaktive', value: salons.filter(s => !s.active).length, color: '#FBBF24' },
  ];

  const ALPHABET = ['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','Æ','Ø','Å','#'];

  const firstLetterOf = (name) => {
    const ch = (name || '').trim().charAt(0).toUpperCase();
    if (/[A-ZÆØÅ]/.test(ch)) return ch;
    return '#';
  };

  const sortedSalons = [...salons].sort((a, b) =>
    (a.name || '').localeCompare(b.name || '', 'da', { sensitivity: 'base' })
  );

  const availableLetters = new Set(sortedSalons.map(s => firstLetterOf(s.name)));

  const q = search.trim().toLowerCase();
  const filteredSortedSalons = sortedSalons.filter(s => {
    if (q) {
      const hay = `${s.name || ''} ${s.subdomain || ''}`.toLowerCase();
      if (!hay.includes(q)) return false;
    }
    if (letterFilter) {
      if (firstLetterOf(s.name) !== letterFilter) return false;
    }
    return true;
  });

  return (
    <div style={{ minHeight: '100vh', background: '#0F172A', fontFamily: "'Manrope', sans-serif", color: '#F8FAFC' }}>
      {/* Topbar */}
      <div style={{
        height: 60, background: '#1E293B', borderBottom: '1px solid #334155',
        padding: '0 32px', display: 'flex', alignItems: 'center', justifyContent: 'space-between',
      }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
          <div style={{
            width: 32, height: 32, background: '#6366F1', borderRadius: 9,
            display: 'flex', alignItems: 'center', justifyContent: 'center',
            fontFamily: 'Fraunces, serif', fontSize: 18, fontWeight: 500, color: '#fff',
          }}>S</div>
          <span style={{ fontWeight: 700, fontSize: 16 }}>Saloniq</span>
          <span style={{ color: '#475569', fontSize: 13 }}>/ Superadmin</span>
        </div>
        <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
          <span style={{ fontSize: 13, color: '#64748B' }}>{currentUserEmail || 'Superadmin'}</span>
          <button onClick={onLogout} style={{
            background: '#334155', color: '#94A3B8', border: 'none',
            borderRadius: 8, padding: '7px 16px', fontSize: 13, cursor: 'pointer', fontFamily: 'inherit',
          }}>Log ud</button>
        </div>
      </div>

      <div style={{ maxWidth: 1080, margin: '0 auto', padding: '36px 32px' }}>
        {view === 'list' && (
          <>
            {/* Stats strip */}
            <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 14, marginBottom: 32 }}>
              {statItems.map(s => (
                <div key={s.label} style={{
                  background: '#1E293B', borderRadius: 14, padding: '22px 24px', border: '1px solid #334155',
                }}>
                  <div style={{ fontSize: 30, fontWeight: 700, color: s.color, fontFamily: 'Fraunces, serif' }}>{s.value}</div>
                  <div style={{ fontSize: 13, color: '#94A3B8', marginTop: 4 }}>{s.label}</div>
                </div>
              ))}
            </div>

            <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 16 }}>
              <h2 style={{ margin: 0, fontSize: 18, fontWeight: 600 }}>Registrerede saloner</h2>
              <button onClick={() => setView('new')} style={{
                background: '#6366F1', color: '#fff', border: 'none',
                borderRadius: 10, padding: '10px 20px', fontSize: 14, fontWeight: 600,
                cursor: 'pointer', fontFamily: 'inherit',
              }}>+ Opret ny salon</button>
            </div>

            {/* Search + filter row */}
            <div style={{ display: 'flex', alignItems: 'center', gap: 10, marginBottom: 14 }}>
              <div style={{ position: 'relative', flex: 1 }}>
                <input
                  type="text"
                  value={search}
                  onChange={(e) => setSearch(e.target.value)}
                  placeholder="Søg efter salon-navn eller subdomæne…"
                  style={{
                    width: '100%', background: '#1E293B', color: '#F8FAFC',
                    border: '1px solid #334155', borderRadius: 10,
                    padding: '11px 36px 11px 38px', fontSize: 14, fontFamily: 'inherit',
                    outline: 'none',
                  }}
                  onFocus={(e) => e.target.style.borderColor = '#6366F1'}
                  onBlur={(e) => e.target.style.borderColor = '#334155'}
                />
                <span style={{
                  position: 'absolute', left: 13, top: '50%', transform: 'translateY(-50%)',
                  color: '#64748B', fontSize: 15, pointerEvents: 'none',
                }}>⌕</span>
                {search && (
                  <button onClick={() => setSearch('')} style={{
                    position: 'absolute', right: 8, top: '50%', transform: 'translateY(-50%)',
                    background: 'transparent', border: 'none', color: '#64748B',
                    cursor: 'pointer', fontSize: 16, padding: 4, lineHeight: 1,
                  }} title="Ryd søgning">×</button>
                )}
              </div>
              {(search || letterFilter) && (
                <button onClick={() => { setSearch(''); setLetterFilter(null); }} style={{
                  background: '#334155', color: '#94A3B8', border: 'none', borderRadius: 8,
                  padding: '10px 14px', fontSize: 13, cursor: 'pointer', fontFamily: 'inherit',
                  whiteSpace: 'nowrap',
                }}>Nulstil filter</button>
              )}
              <span style={{ fontSize: 13, color: '#64748B', whiteSpace: 'nowrap' }}>
                {filteredSortedSalons.length} af {salons.length}
              </span>
            </div>

            {/* Main grid: salon list + alphabet sidebar */}
            <div style={{ display: 'flex', gap: 14, alignItems: 'flex-start' }}>
              <div style={{ flex: 1, display: 'flex', flexDirection: 'column', gap: 10 }}>
              {salons.length === 0 && (
                <div style={{ textAlign: 'center', padding: '60px 0', color: '#475569' }}>
                  Ingen saloner endnu. Opret den første salon ovenfor.
                </div>
              )}
              {salons.length > 0 && filteredSortedSalons.length === 0 && (
                <div style={{ textAlign: 'center', padding: '60px 0', color: '#64748B', background: '#1E293B', borderRadius: 14, border: '1px dashed #334155' }}>
                  <div style={{ fontSize: 15, marginBottom: 6, color: '#94A3B8' }}>Ingen saloner matcher dit filter.</div>
                  <div style={{ fontSize: 13 }}>
                    {search && <span>Søgning: "<span style={{ color: '#CBD5E1' }}>{search}</span>"</span>}
                    {search && letterFilter && <span> · </span>}
                    {letterFilter && <span>Bogstav: <span style={{ color: '#CBD5E1' }}>{letterFilter}</span></span>}
                  </div>
                  <button onClick={() => { setSearch(''); setLetterFilter(null); }} style={{
                    marginTop: 14, background: '#334155', color: '#CBD5E1', border: 'none',
                    borderRadius: 8, padding: '8px 16px', fontSize: 13, cursor: 'pointer', fontFamily: 'inherit',
                  }}>Nulstil filter</button>
                </div>
              )}
              {filteredSortedSalons.map(s => (
                <div key={s.id} style={{
                  background: '#1E293B', borderRadius: 14, padding: '18px 22px',
                  border: '1px solid #334155',
                  display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 16,
                }}>
                  <div style={{ display: 'flex', alignItems: 'center', gap: 14 }}>
                    <div style={{
                      width: 42, height: 42, borderRadius: 11, background: s.color || '#3F4A3A',
                      display: 'flex', alignItems: 'center', justifyContent: 'center',
                      color: '#fff', fontWeight: 700, fontSize: 18, fontFamily: 'Fraunces, serif',
                    }}>{s.name[0]}</div>
                    <div>
                      <div style={{ fontWeight: 600, fontSize: 15 }}>{s.name}</div>
                      <div style={{ color: '#64748B', fontSize: 13, marginTop: 2 }}>
                        {s.subdomain}.saloniq.dk{s.createdAt?.toDate ? ` · oprettet ${formatDanishShortDate(s.createdAt.toDate())}` : ''}
                      </div>
                    </div>
                  </div>
                  <div style={{ display: 'flex', alignItems: 'center', gap: 8, flexShrink: 0 }}>
                    <span style={{
                      padding: '4px 10px', borderRadius: 20, fontSize: 12, fontWeight: 600,
                      background: s.active ? '#052E16' : '#3B0000',
                      color: s.active ? '#4ADE80' : '#F87171',
                    }}>{s.active ? 'Aktiv' : 'Inaktiv'}</span>
                    <button onClick={() => handleToggleActive(s)} style={{
                      background: '#334155', color: '#94A3B8', border: 'none', borderRadius: 8,
                      padding: '7px 13px', fontSize: 13, cursor: 'pointer', fontFamily: 'inherit',
                    }}>{s.active ? 'Deaktiver' : 'Aktiver'}</button>
                    <button onClick={() => setEditing(s)} style={{
                      background: '#334155', color: '#94A3B8', border: 'none', borderRadius: 8,
                      padding: '7px 13px', fontSize: 13, cursor: 'pointer', fontFamily: 'inherit',
                    }}>Rediger</button>
                    <button onClick={async () => {
                      // Bed brugeren vælge branche så vi kan loade det
                      // korrekte datasæt (frisør / negle / massage / ...).
                      const opts = (window.INDUSTRY_OPTIONS || []);
                      const labels = opts.map((o, i) => `${i + 1}. ${o.label}`).join('\n');
                      const def = opts.findIndex(o => o.id === (s.industry || 'frisor'));
                      const picked = prompt(
                        `Vælg branche-datasæt til ${s.name}:\n${labels}\n\nIndtast nummer (eller branche-id):`,
                        String(def >= 0 ? def + 1 : 1));
                      if (!picked) return;
                      let industry = opts[0]?.id;
                      const idx = parseInt(picked, 10);
                      if (!isNaN(idx) && opts[idx - 1]) industry = opts[idx - 1].id;
                      else if (opts.find(o => o.id === picked.toLowerCase())) industry = picked.toLowerCase();
                      if (!confirm(`Seed '${industry}'-demo-data ind i ${s.name}? Eksisterende data overskrives.`)) return;
                      try {
                        const fn = firebase.app().functions('europe-west1').httpsCallable('seedDemoSalon');
                        const r = await fn({ salonId: s.id, industry });
                        const c = r.data?.counts || {};
                        alert(`Demo-data (${industry}) tilføjet til ${s.name}:\n` +
                          `· ${c.staff || 0} medarbejdere\n` +
                          `· ${c.services || 0} ydelser\n` +
                          `· ${c.products || 0} produkter\n` +
                          `· ${c.customers || 0} kunder\n` +
                          `· ${c.bookings || 0} bookinger\n` +
                          `· ${c.sales || 0} salg`);
                      } catch (err) {
                        alert('Kunne ikke seede: ' + (err?.message || err));
                      }
                    }} style={{
                      background: '#1E3A2A', color: '#86EFAC', border: '1px solid #14532D', borderRadius: 8,
                      padding: '7px 13px', fontSize: 13, cursor: 'pointer', fontFamily: 'inherit',
                    }} title="Seed demo-data ind i denne salon">Seed demo</button>
                    <button onClick={() => setDeleting(s)} style={{
                      background: '#3B0000', color: '#F87171', border: 'none', borderRadius: 8,
                      padding: '7px 13px', fontSize: 13, cursor: 'pointer', fontFamily: 'inherit',
                    }}>Slet</button>
                  </div>
                </div>
              ))}
              </div>

              {/* Alphabet sidebar */}
              {salons.length > 0 && (
                <div style={{
                  display: 'flex', flexDirection: 'column', gap: 3,
                  background: '#1E293B', borderRadius: 12, padding: '10px 6px',
                  border: '1px solid #334155',
                  position: 'sticky', top: 16, flexShrink: 0,
                  maxHeight: 'calc(100vh - 32px)', overflowY: 'auto',
                }}>
                  <button
                    onClick={() => setLetterFilter(null)}
                    title="Vis alle"
                    style={{
                      background: letterFilter === null ? '#6366F1' : 'transparent',
                      color: letterFilter === null ? '#fff' : '#94A3B8',
                      border: 'none', borderRadius: 6,
                      width: 28, height: 22, fontSize: 11, fontWeight: 600,
                      cursor: 'pointer', fontFamily: 'inherit',
                      marginBottom: 4,
                    }}
                  >Alle</button>
                  {ALPHABET.map(letter => {
                    const has = availableLetters.has(letter);
                    const isActive = letterFilter === letter;
                    return (
                      <button
                        key={letter}
                        onClick={() => has && setLetterFilter(isActive ? null : letter)}
                        disabled={!has}
                        title={has ? `Vis saloner der starter med ${letter}` : `Ingen saloner med ${letter}`}
                        style={{
                          background: isActive ? '#6366F1' : 'transparent',
                          color: isActive ? '#fff' : (has ? '#CBD5E1' : '#334155'),
                          border: 'none', borderRadius: 6,
                          width: 28, height: 24, fontSize: 12, fontWeight: 600,
                          cursor: has ? 'pointer' : 'default', fontFamily: 'inherit',
                          opacity: has ? 1 : 0.5,
                          transition: 'background 0.12s, color 0.12s',
                        }}
                      >{letter}</button>
                    );
                  })}
                </div>
              )}
            </div>
          </>
        )}

        {view === 'new' && (
          <SalonCreateForm
            onCancel={() => setView('list')}
            onCreate={handleCreate}
            existingSubdomains={salons.map(s => s.subdomain)}
          />
        )}
      </div>

      {/* Delete confirm */}
      {deleting && (
        <div style={{
          position: 'fixed', inset: 0, background: 'rgba(0,0,0,0.75)',
          display: 'flex', alignItems: 'center', justifyContent: 'center', zIndex: 999,
        }}>
          <div style={{
            background: '#1E293B', borderRadius: 16, padding: 32,
            width: 420, border: '1px solid #334155',
          }}>
            <h3 style={{ color: '#F8FAFC', margin: '0 0 10px' }}>Slet salon?</h3>
            <p style={{ color: '#94A3B8', margin: '0 0 16px', fontSize: 14, lineHeight: 1.6 }}>
              Er du sikker på du vil slette <strong style={{ color: '#F8FAFC' }}>{deleting.name}</strong>?{' '}
              Salonens data slettes. Brugere i Firebase Auth skal slettes manuelt fra Console.
            </p>
            {deletingState.error && (
              <div style={{ marginBottom: 14, padding: '10px 14px', background: '#3B0000', color: '#FCA5A5', borderRadius: 8, fontSize: 13 }}>{deletingState.error}</div>
            )}
            <div style={{ display: 'flex', gap: 10 }}>
              <button onClick={() => setDeleting(null)} disabled={deletingState.submitting} style={{
                flex: 1, padding: '11px', background: '#334155', color: '#94A3B8',
                border: 'none', borderRadius: 10, cursor: 'pointer', fontFamily: 'inherit',
              }}>Annuller</button>
              <button onClick={confirmDelete} disabled={deletingState.submitting} style={{
                flex: 1, padding: '11px',
                background: deletingState.submitting ? '#7F1D1D' : '#DC2626',
                color: '#fff', border: 'none', borderRadius: 10, fontWeight: 600,
                cursor: deletingState.submitting ? 'not-allowed' : 'pointer', fontFamily: 'inherit',
              }}>{deletingState.submitting ? 'Sletter…' : 'Slet permanent'}</button>
            </div>
          </div>
        </div>
      )}

      {editing && (
        <SalonEditModal
          salon={editing}
          onClose={() => setEditing(null)}
          onSaved={async (updated) => { setEditing(null); await reload(); }}
        />
      )}
    </div>
  );
}

// ─── Salon Name Prompt (Step 1 of login) ──────────────────────────────────────
function SalonNamePrompt({ onCancel }) {
  const [salonName, setSalonName] = React.useState('');
  const [error, setError] = React.useState('');
  const [loading, setLoading] = React.useState(false);

  const submit = async (e) => {
    e?.preventDefault();
    const cleaned = salonName.trim().toLowerCase().replace(/[^a-z0-9-]/g, '');
    if (!cleaned) { setError('Indtast salonens navn'); return; }
    setLoading(true);
    setError('');
    try {
      const salon = await FB.getSalonBySubdomain(cleaned);
      if (!salon) {
        setError(`Vi kunne ikke finde "${salonName}". Tjek stavemåden.`);
        setLoading(false);
        return;
      }
      if (!salon.active) {
        setError(`${salon.name} er midlertidigt deaktiveret. Kontakt support.`);
        setLoading(false);
        return;
      }
      // Redirect to salon's URL — login itself happens at the subdomain
      const host = window.location.hostname;
      if (host === 'localhost' || host === '127.0.0.1') {
        window.location.href = window.location.pathname + '?salon=' + cleaned;
      } else {
        const parts = host.split('.');
        const base = parts.length >= 3 ? parts.slice(-2).join('.') : host;
        window.location.href = `${window.location.protocol}//${cleaned}.${base}`;
      }
    } catch (err) {
      setError('Kunne ikke nå serveren. Tjek dit netværk.');
      setLoading(false);
    }
  };

  return (
    <div style={{
      minHeight: '100vh', display: 'flex', alignItems: 'center', justifyContent: 'center',
      background: 'linear-gradient(145deg, #f5f3ee 0%, #ece8df 100%)',
      fontFamily: "'Manrope', sans-serif",
    }}>
      <button onClick={onCancel} style={{
        position: 'fixed', top: 24, left: 24, zIndex: 10,
        background: 'rgba(255,255,255,0.92)', border: '1.5px solid #DDD9CE',
        borderRadius: 10, padding: '8px 14px', fontSize: 13, fontWeight: 600,
        color: '#3F4A3A', cursor: 'pointer', fontFamily: "'Manrope', sans-serif",
        backdropFilter: 'blur(8px)',
      }}>← Tilbage</button>

      <div style={{
        width: 460, padding: '48px 44px',
        background: '#fff', borderRadius: 20,
        boxShadow: '0 8px 48px rgba(0,0,0,0.12)',
        animation: 'slideUp 0.3s ease',
      }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 10, justifyContent: 'center', marginBottom: 36 }}>
          <div style={{
            width: 36, height: 36, background: '#3F4A3A', borderRadius: 10,
            display: 'flex', alignItems: 'center', justifyContent: 'center',
            fontFamily: 'Fraunces, serif', fontSize: 20, color: '#fff', fontWeight: 500,
          }}>S</div>
          <span style={{ fontFamily: 'Fraunces, serif', fontSize: 22, fontWeight: 500 }}>Saloniq</span>
        </div>

        <h1 style={{
          fontFamily: 'Fraunces, serif', fontSize: 28, fontWeight: 500,
          margin: '0 0 10px', textAlign: 'center', lineHeight: 1.25,
        }}>Velkommen tilbage</h1>
        <p style={{
          margin: '0 0 32px', fontSize: 14, color: '#888',
          textAlign: 'center', lineHeight: 1.5,
        }}>Indtast navnet på din salon, så sender vi dig videre til din login-side.</p>

        <form onSubmit={submit}>
          <label style={{
            display: 'block', fontSize: 12, fontWeight: 700, color: '#555',
            marginBottom: 8, textTransform: 'uppercase', letterSpacing: '0.06em',
          }}>Salon-navn</label>

          <div style={{
            display: 'flex', alignItems: 'center',
            border: `1.5px solid ${error ? '#FECACA' : '#DDD9CE'}`,
            borderRadius: 10, background: '#FBFAF6',
            transition: 'border-color 120ms',
          }}>
            <input
              type="text" autoFocus
              value={salonName}
              onChange={e => { setSalonName(e.target.value); setError(''); }}
              placeholder="f.eks. klipperiet"
              style={{
                flex: 1, padding: '13px 14px',
                border: 'none', borderRadius: 10,
                fontSize: 15, outline: 'none',
                background: 'transparent', fontFamily: 'inherit',
              }}
            />
            <span style={{
              padding: '0 14px 0 4px', fontSize: 14, color: '#aaa', whiteSpace: 'nowrap',
            }}>.saloniq.dk</span>
          </div>

          {error && (
            <div style={{
              padding: '10px 14px', marginTop: 10,
              background: '#FEF2F2', border: '1px solid #FECACA',
              borderRadius: 8, fontSize: 13, color: '#B91C1C',
            }}>{error}</div>
          )}

          <button type="submit" disabled={!salonName.trim() || loading} style={{
            marginTop: 22, width: '100%', padding: '13px',
            background: (!salonName.trim() || loading) ? '#D4D0C8' : '#3F4A3A',
            color: '#fff', border: 'none', borderRadius: 10,
            fontSize: 15, fontWeight: 600,
            cursor: (!salonName.trim() || loading) ? 'default' : 'pointer',
            fontFamily: 'inherit', transition: 'background 0.15s',
          }}>{loading ? 'Søger…' : 'Fortsæt →'}</button>
        </form>

        <p style={{ marginTop: 24, fontSize: 13, color: '#888', textAlign: 'center', lineHeight: 1.5 }}>
          Har du ikke en konto?{' '}
          <a href="mailto:hello@ooniq.dk" style={{ color: '#3F4A3A', fontWeight: 600, textDecoration: 'none' }}>Kontakt os</a>
        </p>
      </div>
    </div>
  );
}

// ─── Marketing Landing Page ───────────────────────────────────────────────────
function MarketingLandingPage() {
  const [showSalonPrompt, setShowSalonPrompt] = React.useState(false);
  const [activeFeature, setActiveFeature] = React.useState(null);
  const [activeBookingIdx, setActiveBookingIdx] = React.useState(null);

  // Allow normal document scrolling on the marketing page
  // (the booking app sets body overflow:hidden globally; we override it here)
  React.useEffect(() => {
    const prevHtml = document.documentElement.style.overflow;
    const prevBody = document.body.style.overflow;
    document.documentElement.style.overflow = 'auto';
    document.body.style.overflow = 'auto';
    return () => {
      document.documentElement.style.overflow = prevHtml;
      document.body.style.overflow = prevBody;
    };
  }, []);

  const scrollTo = (id) => {
    const el = document.getElementById(id);
    if (el) el.scrollIntoView({ behavior: 'smooth', block: 'start' });
  };

  if (showSalonPrompt) {
    return <SalonNamePrompt onCancel={() => setShowSalonPrompt(false)} />;
  }

  const openLogin = () => setShowSalonPrompt(true);

  const Logo = ({ size = 32, light, withTagline }) => (
    <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
      <div
        role="button"
        tabIndex={0}
        title="Tilbage til toppen"
        onClick={() => window.scrollTo({ top: 0, behavior: 'smooth' })}
        onKeyDown={e => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); window.scrollTo({ top: 0, behavior: 'smooth' }); } }}
        style={{ display: 'flex', alignItems: 'center', gap: 10, cursor: 'pointer' }}
      >
        <div style={{
          width: size, height: size, background: light ? '#fff' : '#3F4A3A', borderRadius: size * 0.28,
          display: 'flex', alignItems: 'center', justifyContent: 'center',
          fontFamily: 'Fraunces, serif', fontSize: size * 0.55, fontWeight: 500,
          color: light ? '#3F4A3A' : '#fff',
        }}>S</div>
        <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'flex-start', lineHeight: 1.1 }}>
          <span style={{
            fontFamily: 'Fraunces, serif', fontSize: size === 28 ? 19 : 22, fontWeight: 500,
            color: light ? '#fff' : '#1a1a1a', letterSpacing: '-0.01em',
          }}>Saloniq</span>
          {withTagline && (
            <span style={{
              fontSize: 10, color: light ? 'rgba(255,255,255,0.55)' : '#888',
              fontWeight: 500, letterSpacing: '0.04em', marginTop: 2,
            }}>
              af{' '}
              <a
                href="https://ooniq.dk"
                target="_blank"
                rel="noopener noreferrer"
                onClick={e => e.stopPropagation()}
                style={{
                  color: 'inherit', textDecoration: 'none',
                  borderBottom: light ? '1px dotted rgba(255,255,255,0.4)' : '1px dotted #bbb',
                }}
              >ooniq</a>
            </span>
          )}
        </div>
      </div>
    </div>
  );

  const navAction = (id) => (e) => { e.preventDefault(); scrollTo(id); };

  return (
    <div style={{
      background: '#FBFAF6',
      fontFamily: "'Manrope', sans-serif", color: '#1a1a1a',
    }}>
      {/* ── Sticky Header ──────────────────────────────────── */}
      <header style={{
        position: 'sticky', top: 0, zIndex: 50,
        background: 'rgba(251,250,246,0.85)',
        backdropFilter: 'blur(12px)',
        borderBottom: '1px solid rgba(239,237,229,0.6)',
      }}>
        <div style={{
          maxWidth: 1180, margin: '0 auto', padding: '18px 32px',
          display: 'flex', alignItems: 'center', justifyContent: 'space-between',
        }}>
          <Logo withTagline />
          <nav style={{ display: 'flex', alignItems: 'center', gap: 28 }}>
            <a href="#funktioner" onClick={navAction('funktioner')} style={navLink}>Funktioner</a>
            <a href="#hvorfor" onClick={navAction('hvorfor')} style={navLink}>Hvorfor Saloniq</a>
            <a href="#skraeddersyet" onClick={navAction('skraeddersyet')} style={navLink}>Skræddersyet</a>
            <a href="#kontakt" onClick={navAction('kontakt')} style={navLink}>Kontakt</a>
            <button onClick={() => openLogin()} style={{
              background: '#3F4A3A', color: '#fff', border: 'none', borderRadius: 10,
              padding: '10px 22px', fontSize: 14, fontWeight: 600, cursor: 'pointer',
              fontFamily: 'inherit', transition: 'background 120ms',
            }}
            onMouseEnter={e => e.currentTarget.style.background = '#2A332A'}
            onMouseLeave={e => e.currentTarget.style.background = '#3F4A3A'}>
              Log ind
            </button>
          </nav>
        </div>
      </header>

      {/* ── Hero ─────────────────────────────────────────── */}
      <section style={{
        maxWidth: 1180, margin: '0 auto', padding: '60px 32px 100px',
        display: 'grid', gridTemplateColumns: '1.05fr 1fr', gap: 80, alignItems: 'center',
      }}>
        <div>
          <div style={{
            display: 'inline-block', padding: '6px 14px',
            background: '#F4F7F0', border: '1px solid #DCE6CC',
            borderRadius: 20, fontSize: 12, fontWeight: 600,
            color: '#3F5A30', letterSpacing: '0.04em', marginBottom: 24,
          }}>BOOKINGSYSTEM TIL FRISØRER & SKØNHEDSKLINIKKER</div>

          <h1 style={{
            fontFamily: 'Fraunces, serif', fontSize: 64, fontWeight: 400,
            lineHeight: 1.05, letterSpacing: '-0.02em', margin: 0, color: '#1a1a1a',
          }}>
            Eleganse,<br/>
            <span style={{ fontStyle: 'italic', color: '#7B8A6B' }}>gjort til hverdag.</span>
          </h1>

          <p style={{
            marginTop: 26, fontSize: 18, lineHeight: 1.6, color: '#555',
            maxWidth: 480,
          }}>
            Saloniq er bookingsystemet bygget til frisører, neglesaloner,
            hudplejeklinikker og andre skønhedsvirksomheder. Smukke kalendere,
            automatiske SMS-bekræftelser, kundekartotek og statistik —
            alt sammen i én rolig flade som dit team faktisk har lyst til at bruge.
          </p>

          <div style={{ display: 'flex', gap: 14, marginTop: 36 }}>
            <button onClick={() => openLogin()} style={{
              background: '#3F4A3A', color: '#fff', border: 'none', borderRadius: 12,
              padding: '15px 28px', fontSize: 15, fontWeight: 600, cursor: 'pointer',
              fontFamily: 'inherit', display: 'flex', alignItems: 'center', gap: 8,
              boxShadow: '0 4px 14px rgba(63,74,58,0.25)',
              transition: 'all 160ms',
            }}
            onMouseEnter={e => { e.currentTarget.style.background = '#2A332A'; e.currentTarget.style.transform = 'translateY(-1px)'; }}
            onMouseLeave={e => { e.currentTarget.style.background = '#3F4A3A'; e.currentTarget.style.transform = 'none'; }}>
              Log ind på din konto →
            </button>
            <a href="#funktioner" onClick={navAction('funktioner')} style={{
              background: '#fff', color: '#3F4A3A', border: '1.5px solid #DDD9CE', borderRadius: 12,
              padding: '14px 28px', fontSize: 15, fontWeight: 600, cursor: 'pointer',
              fontFamily: 'inherit', textDecoration: 'none',
              display: 'flex', alignItems: 'center', gap: 8,
            }}>Se funktioner</a>
          </div>

          <div style={{ marginTop: 32, fontSize: 13, color: '#888' }}>
            <span style={{ color: '#3F5A30', fontWeight: 600 }}>✓</span> Ingen binding ·
            <span style={{ color: '#3F5A30', fontWeight: 600, marginLeft: 14 }}>✓</span> Dansk support ·
            <span style={{ color: '#3F5A30', fontWeight: 600, marginLeft: 14 }}>✓</span> GDPR-sikret
          </div>
        </div>

        {/* Hero visual: stylized calendar mockup */}
        <div style={{ position: 'relative' }}>
          <div style={{
            background: '#fff', borderRadius: 20, padding: 24,
            border: '1px solid #EFEDE5',
            boxShadow: '0 24px 60px rgba(40,40,30,0.10), 0 4px 12px rgba(40,40,30,0.04)',
            transform: 'perspective(1200px) rotateY(-8deg) rotateX(2deg)',
          }}>
            <div style={{
              display: 'flex', justifyContent: 'space-between', alignItems: 'center',
              paddingBottom: 14, borderBottom: '1px solid #EFEDE5', marginBottom: 16,
            }}>
              <div>
                <div style={{ fontFamily: 'Fraunces, serif', fontSize: 18, fontWeight: 500 }}>Torsdag 6. juni</div>
                <div style={{ fontSize: 12, color: '#888' }}>4 medarbejdere · 14 bookinger</div>
              </div>
              <div style={{ display: 'flex', gap: 4 }}>
                {['#E8C8B4','#B4D2E8','#D8C0E0','#C8DCB4'].map(c => (
                  <div key={c} style={{ width: 24, height: 24, borderRadius: '50%', background: c, border: '2px solid #fff' }} />
                ))}
              </div>
            </div>
            {/* Booking rows — klikker man udvides den selv (in-place) */}
            {[
              { time: '09:00', name: 'Mathias Knudsen', svc: 'Herreklip', col: '#FFB3B3', dur: 30, price: 350, phone: '+45 50 92 02 01', staff: 'Caroline' },
              { time: '09:30', name: 'Laura Sørensen',  svc: 'Helfarve + Dameklip', col: '#CFB8E8', dur: 105, price: 1220, phone: '+45 50 92 02 01', staff: 'Jakob' },
              { time: '11:30', name: 'Kirsten Andersen', svc: 'Behandling', col: '#CFB8E8', dur: 30, price: 395, phone: '+45 50 92 02 01', staff: 'Caroline' },
              { time: '13:45', name: 'Anders Thomsen', svc: 'Herreklip', col: '#FFB3B3', dur: 30, price: 350, phone: '+45 50 92 02 01', staff: 'Caroline' },
            ].map((b, i) => {
              const isActive = i === activeBookingIdx;
              return (
                <div key={i}
                  onClick={() => setActiveBookingIdx(isActive ? null : i)}
                  style={{
                    marginBottom: 6,
                    background: isActive ? '#1F2A2E' : '#FBFAF6',
                    borderRadius: 10,
                    borderLeft: `3px solid ${b.col}`,
                    cursor: 'pointer',
                    overflow: 'hidden',
                    transition: 'background 200ms ease',
                  }}
                  onMouseEnter={e => { if (!isActive) e.currentTarget.style.background = '#F1EEE5'; }}
                  onMouseLeave={e => { if (!isActive) e.currentTarget.style.background = '#FBFAF6'; }}>
                  {/* Compact header row */}
                  <div style={{ display: 'flex', alignItems: 'center', gap: 12, padding: '10px 12px' }}>
                    <div style={{
                      fontSize: 12, fontWeight: 600, width: 50,
                      color: isActive ? 'rgba(255,255,255,0.7)' : '#666',
                    }}>{b.time}</div>
                    <div style={{ flex: 1 }}>
                      <div style={{ fontSize: 13, fontWeight: 500, color: isActive ? '#fff' : '#1a1a1a' }}>{b.name}</div>
                      <div style={{ fontSize: 11, color: isActive ? 'rgba(255,255,255,0.6)' : '#888' }}>{b.svc} · {b.dur} min</div>
                    </div>
                    <div style={{
                      fontSize: 10, padding: '2px 8px', borderRadius: 10, fontWeight: 600,
                      background: isActive ? 'rgba(201,216,181,0.15)' : '#F4F7F0',
                      color: isActive ? '#C9D8B5' : '#3F5A30',
                    }}>BEKRÆFTET</div>
                  </div>

                  {/* Expanded body — kun når aktiv */}
                  {isActive && (
                    <div style={{
                      padding: '0 14px 14px', color: '#fff',
                      animation: 'slideUp 180ms ease',
                    }}>
                      <div style={{
                        height: 1, background: 'rgba(255,255,255,0.08)', margin: '4px 0 12px',
                      }} />
                      <div style={{
                        fontSize: 11, color: 'rgba(255,255,255,0.55)', marginBottom: 10,
                      }}>{b.phone}</div>
                      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 10, fontSize: 11 }}>
                        <div>
                          <div style={{ color: 'rgba(255,255,255,0.5)', textTransform: 'uppercase', letterSpacing: '0.06em', marginBottom: 3 }}>Varighed</div>
                          <div style={{ fontWeight: 500 }}>{b.dur} min</div>
                        </div>
                        <div>
                          <div style={{ color: 'rgba(255,255,255,0.5)', textTransform: 'uppercase', letterSpacing: '0.06em', marginBottom: 3 }}>Hos</div>
                          <div style={{ fontWeight: 500 }}>{b.staff}</div>
                        </div>
                        <div>
                          <div style={{ color: 'rgba(255,255,255,0.5)', textTransform: 'uppercase', letterSpacing: '0.06em', marginBottom: 3 }}>Pris</div>
                          <div style={{ fontWeight: 500 }}>{b.price} kr</div>
                        </div>
                      </div>
                      <div style={{
                        marginTop: 10, padding: '6px 10px',
                        background: 'rgba(201,216,181,0.10)', borderRadius: 6,
                        fontSize: 11, color: '#C9D8B5',
                      }}>
                        ✓ SMS + email-bekræftelse sendt
                      </div>
                    </div>
                  )}
                </div>
              );
            })}
          </div>

          {/* Floating notification card */}
          <div style={{
            position: 'absolute', bottom: -30, left: -40,
            background: '#fff', borderRadius: 14, padding: '14px 18px',
            border: '1px solid #EFEDE5',
            boxShadow: '0 12px 32px rgba(40,40,30,0.12)',
            display: 'flex', alignItems: 'center', gap: 12,
            maxWidth: 280,
          }}>
            <div style={{
              width: 36, height: 36, borderRadius: 10, background: '#F4F7F0',
              display: 'flex', alignItems: 'center', justifyContent: 'center',
              color: '#3F5A30',
            }}>
              <IconPlus size={18} strokeWidth={2.5} />
            </div>
            <div>
              <div style={{ fontSize: 12, fontWeight: 600 }}>Ny online booking</div>
              <div style={{ fontSize: 11, color: '#888', marginTop: 1 }}>Mads har booket Skægtrim · i morgen kl. 14</div>
            </div>
          </div>
        </div>
      </section>

      {/* ── Trust strip ──────────────────────────────────── */}
      <section style={{
        background: '#fff', borderTop: '1px solid #EFEDE5', borderBottom: '1px solid #EFEDE5',
        padding: '32px 32px',
      }}>
        <div style={{
          maxWidth: 1180, margin: '0 auto',
          display: 'flex', justifyContent: 'space-around', alignItems: 'center', flexWrap: 'wrap', gap: 24,
        }}>
          {[
            ['400+', 'aktive saloner'],
            ['180k', 'bookinger om måneden'],
            ['98%', 'kundetilfredshed'],
            ['24/7', 'online booking til dine kunder'],
          ].map(([n, l]) => (
            <div key={l} style={{ textAlign: 'center' }}>
              <div style={{ fontFamily: 'Fraunces, serif', fontSize: 32, fontWeight: 500, color: '#3F4A3A' }}>{n}</div>
              <div style={{ fontSize: 13, color: '#888', marginTop: 4 }}>{l}</div>
            </div>
          ))}
        </div>
      </section>

      {/* ── Features ─────────────────────────────────────── */}
      <section id="funktioner" style={{ maxWidth: 1180, margin: '0 auto', padding: '100px 32px' }}>
        <div style={{ textAlign: 'center', marginBottom: 56, maxWidth: 640, marginLeft: 'auto', marginRight: 'auto' }}>
          <div style={{ fontSize: 12, fontWeight: 700, color: '#7B8A6B', letterSpacing: '0.1em', marginBottom: 14 }}>FUNKTIONER</div>
          <h2 style={{
            fontFamily: 'Fraunces, serif', fontSize: 44, fontWeight: 400,
            margin: 0, lineHeight: 1.15, letterSpacing: '-0.01em',
          }}>
            Alt din salon har brug for, <span style={{ fontStyle: 'italic', color: '#7B8A6B' }}>intet du ikke har.</span>
          </h2>
          <p style={{ marginTop: 18, fontSize: 16, color: '#666', lineHeight: 1.6 }}>
            Bygget sammen med frisører, klinikejere og terapeuter fra hele landet,
            så hver detalje passer til måden, I rent faktisk arbejder på.
          </p>
        </div>

        <div style={{
          display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(260px, 1fr))', gap: 18,
        }}>
          {FEATURES.map(f => {
            const Ic = f.icon;
            return (
              <button key={f.id} onClick={() => setActiveFeature(f)} style={{
                background: '#fff', borderRadius: 16, padding: '28px 24px',
                border: '1px solid #EFEDE5', transition: 'all 200ms',
                textAlign: 'left', cursor: 'pointer', fontFamily: 'inherit',
                position: 'relative',
              }}
              onMouseEnter={e => {
                e.currentTarget.style.transform = 'translateY(-3px)';
                e.currentTarget.style.boxShadow = '0 12px 32px rgba(40,40,30,0.08)';
                e.currentTarget.style.borderColor = '#C2D6B4';
              }}
              onMouseLeave={e => {
                e.currentTarget.style.transform = 'none';
                e.currentTarget.style.boxShadow = 'none';
                e.currentTarget.style.borderColor = '#EFEDE5';
              }}>
                <div style={{
                  width: 48, height: 48, borderRadius: 12, background: '#F4F7F0',
                  display: 'flex', alignItems: 'center', justifyContent: 'center',
                  color: '#3F5A30', marginBottom: 18,
                }}>
                  <Ic size={22} strokeWidth={1.8} />
                </div>
                <div style={{ fontFamily: 'Fraunces, serif', fontSize: 20, fontWeight: 500, marginBottom: 8 }}>{f.title}</div>
                <div style={{ fontSize: 14, color: '#666', lineHeight: 1.6 }}>{f.text}</div>
                <div style={{
                  marginTop: 14, fontSize: 12, fontWeight: 600, color: '#3F4A3A',
                  display: 'flex', alignItems: 'center', gap: 4,
                }}>
                  Se demo
                  <IconArrowR size={12} />
                </div>
              </button>
            );
          })}
        </div>
      </section>

      {/* ── Why ──────────────────────────────────────────── */}
      <section id="hvorfor" style={{
        background: '#1F2A2E', color: '#fff', padding: '90px 32px',
      }}>
        <div style={{
          maxWidth: 1180, margin: '0 auto',
          display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 80, alignItems: 'center',
        }}>
          <div>
            <div style={{ fontSize: 12, fontWeight: 700, color: '#C9D8B5', letterSpacing: '0.1em', marginBottom: 14 }}>HVORFOR SALONIQ</div>
            <h2 style={{
              fontFamily: 'Fraunces, serif', fontSize: 44, fontWeight: 400,
              margin: 0, lineHeight: 1.15, color: '#fff', letterSpacing: '-0.01em',
            }}>
              Software, der <span style={{ fontStyle: 'italic', color: '#C9D8B5' }}>passer til salonen</span> — ikke omvendt.
            </h2>
            <p style={{ marginTop: 22, fontSize: 16, lineHeight: 1.7, color: 'rgba(255,255,255,0.75)' }}>
              Vi tror på, at en booking-app skal opleves som en del af virksomhedens æstetik. Saloniq er bygget af ooniq —
              et lille hold med omhu for typografi, farve og flow — så hver klik føles let, og hver kunde-interaktion bliver smukkere.
            </p>
            <ul style={{ listStyle: 'none', padding: 0, margin: '28px 0 0', display: 'flex', flexDirection: 'column', gap: 14 }}>
              {[
                'Designet med danske salonejere — ikke amerikanske software-teams',
                'Passer til frisører, neglesaloner, hudpleje, makeup-artister og andre kliniker',
                'Hver virksomhed får sit eget subdomæne (fx hob.saloniq.dk)',
                'Ingen onboarding-fees, ingen lange kontrakter',
                'Dansk support — vi svarer som mennesker, ikke chatbots',
              ].map(t => (
                <li key={t} style={{ display: 'flex', gap: 12, fontSize: 15, color: 'rgba(255,255,255,0.85)' }}>
                  <span style={{
                    width: 22, height: 22, borderRadius: '50%', background: '#C9D8B5',
                    display: 'flex', alignItems: 'center', justifyContent: 'center',
                    color: '#1F2A2E', fontSize: 13, fontWeight: 700, flexShrink: 0, marginTop: 1,
                  }}>✓</span>
                  {t}
                </li>
              ))}
            </ul>
          </div>

          <div>
            <div style={{
              background: 'linear-gradient(135deg, rgba(201,216,181,0.06) 0%, rgba(201,216,181,0.02) 100%)',
              border: '1px solid rgba(201,216,181,0.2)',
              borderRadius: 20, padding: '40px 36px',
              position: 'relative',
            }}>
              <div style={{
                fontFamily: 'Fraunces, serif', fontSize: 60, color: '#C9D8B5',
                position: 'absolute', top: 12, left: 24, lineHeight: 1, opacity: 0.5,
              }}>"</div>
              <p style={{
                fontFamily: 'Fraunces, serif', fontSize: 24, fontWeight: 400,
                lineHeight: 1.4, color: '#fff', margin: '20px 0 0', fontStyle: 'italic',
              }}>
                Vi har sparet flere timer hver uge siden vi skiftede til Saloniq. Mine medarbejdere
                forstår det med det samme — og kunderne elsker SMS'erne.
              </p>
              <div style={{ marginTop: 28, display: 'flex', alignItems: 'center', gap: 12 }}>
                <div style={{
                  width: 44, height: 44, borderRadius: '50%', background: '#E8C8B4',
                  display: 'flex', alignItems: 'center', justifyContent: 'center',
                  fontWeight: 600, color: '#3F4A3A',
                }}>CH</div>
                <div>
                  <div style={{ fontSize: 14, fontWeight: 600, color: '#fff' }}>Caroline Hansen</div>
                  <div style={{ fontSize: 13, color: 'rgba(255,255,255,0.6)' }}>Salon Klipperiet, København</div>
                </div>
              </div>
            </div>
          </div>
        </div>
      </section>

      {/* ── Skræddersyet (custom solutions) ──────────────── */}
      <section id="skraeddersyet" style={{
        background: 'linear-gradient(180deg, #FBFAF6 0%, #F4F0E5 100%)',
        padding: '100px 32px',
        position: 'relative',
        overflow: 'hidden',
      }}>
        {/* Decorative blob */}
        <div style={{
          position: 'absolute', top: -80, right: -80, width: 280, height: 280,
          borderRadius: '50%', background: 'radial-gradient(circle, rgba(201,168,40,0.08) 0%, rgba(201,168,40,0) 70%)',
          pointerEvents: 'none',
        }} />

        <div style={{ maxWidth: 1180, margin: '0 auto', position: 'relative' }}>
          {/* Heading */}
          <div style={{ maxWidth: 760, marginBottom: 48 }}>
            <div style={{
              display: 'inline-flex', alignItems: 'center', gap: 8,
              padding: '6px 14px', background: '#FEF6DC', border: '1px solid #F0DC9C',
              borderRadius: 20, fontSize: 12, fontWeight: 600,
              color: '#8A6B1F', letterSpacing: '0.04em', marginBottom: 24,
            }}>
              <IconSparkle size={13} strokeWidth={1.8} />
              SKRÆDDERSYET TIL DIN SALON
            </div>

            <h2 style={{
              fontFamily: 'Fraunces, serif', fontSize: 48, fontWeight: 400,
              margin: 0, lineHeight: 1.1, letterSpacing: '-0.02em',
            }}>
              Lavet på mål til <span style={{ fontStyle: 'italic', color: '#7B8A6B' }}>netop din salon.</span>
            </h2>

            <p style={{ marginTop: 20, fontSize: 17, lineHeight: 1.65, color: '#555', maxWidth: 620 }}>
              Saloniq er den standardløsning der virker for de fleste. Men hvis din salon arbejder på en helt særlig måde,
              eller hvis du drømmer om noget Saloniq ikke har — så bygger <strong>ooniq</strong> det også.
              Vi er det hold der har lavet Saloniq, og vi laver gerne specialløsninger til dig.
            </p>
            <p style={{ marginTop: 14, fontSize: 15, color: '#777', maxWidth: 620, lineHeight: 1.6 }}>
              Du behøver ikke vide noget om teknik. Du fortæller os hvordan du gerne vil arbejde — så finder vi ud af resten.
            </p>
          </div>

          {/* Examples grid */}
          <div style={{ marginBottom: 56 }}>
            <div style={{ fontSize: 12, fontWeight: 700, color: '#7B8A6B', letterSpacing: '0.1em', marginBottom: 20 }}>
              EKSEMPLER PÅ HVAD VI KAN
            </div>
            <div style={{
              display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(260px, 1fr))', gap: 16,
            }}>
              {[
                {
                  icon: IconPalette,
                  title: 'Dit eget look',
                  text: 'Salonens egne farver, logo og fonte gennem hele systemet — så det matcher resten af din brand.',
                },
                {
                  icon: IconLink,
                  title: 'Snak med dit kassesystem',
                  text: 'Vi kobler bookingerne sammen med dit kassesystem (fx for at sende fakturaen automatisk), regnskabsprogram eller webshop.',
                },
                {
                  icon: IconUsers,
                  title: 'Kundekort der passer dig',
                  text: 'Skal kundekortet vise hudtype, allergier, hårfarve-koder eller noget helt andet? Vi tilføjer præcist de felter du har brug for.',
                },
                {
                  icon: IconCalendar,
                  title: 'Klippekort & abonnement',
                  text: '10-turs klippekort, månedsabonnement på behandlinger eller medlemsfordele — vi sætter det op i din salon.',
                },
                {
                  icon: IconBell,
                  title: 'Egen booking-app',
                  text: 'En app dine kunder downloader fra App Store og Google Play — med din salons navn og ikon. Faste kunder elsker det.',
                },
                {
                  icon: IconMail,
                  title: 'Smarte automatiske beskeder',
                  text: 'Tak-mails efter besøg, fødselsdagshilsen med rabat, "tid til at booke igen"-påmindelser — på dansk og i din tone.',
                },
              ].map(ex => {
                const Ic = ex.icon;
                return (
                  <div key={ex.title} style={{
                    background: '#fff', borderRadius: 14, padding: '22px 22px',
                    border: '1px solid #EFEDE5',
                  }}>
                    <div style={{
                      width: 40, height: 40, borderRadius: 10, background: '#FEF6DC',
                      display: 'flex', alignItems: 'center', justifyContent: 'center',
                      color: '#8A6B1F', marginBottom: 14,
                    }}>
                      <Ic size={20} strokeWidth={1.8} />
                    </div>
                    <div style={{ fontFamily: 'Fraunces, serif', fontSize: 18, fontWeight: 500, marginBottom: 6 }}>{ex.title}</div>
                    <div style={{ fontSize: 13, color: '#666', lineHeight: 1.55 }}>{ex.text}</div>
                  </div>
                );
              })}
            </div>
          </div>

          {/* Process timeline */}
          <div style={{
            background: '#fff', borderRadius: 20, padding: '40px 36px',
            border: '1px solid #EFEDE5', marginBottom: 32,
          }}>
            <div style={{ fontSize: 12, fontWeight: 700, color: '#7B8A6B', letterSpacing: '0.1em', marginBottom: 8 }}>
              SÅDAN FOREGÅR DET
            </div>
            <h3 style={{
              fontFamily: 'Fraunces, serif', fontSize: 26, fontWeight: 400,
              margin: '0 0 28px', lineHeight: 1.2,
            }}>
              Fra første kop kaffe til <span style={{ fontStyle: 'italic', color: '#7B8A6B' }}>færdig løsning.</span>
            </h3>

            <div style={{
              display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(190px, 1fr))', gap: 20,
            }}>
              {[
                {
                  num: '1',
                  title: 'Kaffemøde',
                  text: 'Vi mødes (eller Zoomer). Du fortæller om din salon, vi lytter. Helt gratis og uforpligtende.',
                  icon: IconCoffee,
                },
                {
                  num: '2',
                  title: 'Forslag på papir',
                  text: 'Vi sender dig en plan med tydelig pris og tidsplan. Ingen tekniske ord, kun hvad du får og hvad det koster.',
                  icon: IconEdit,
                },
                {
                  num: '3',
                  title: 'Vi bygger',
                  text: 'Du behøver ikke gøre noget. Vi holder dig opdateret undervejs så du ved hvor langt vi er.',
                  icon: IconSettings,
                },
                {
                  num: '4',
                  title: 'Du arbejder smartere',
                  text: 'Vi sætter det hele op i din salon, lærer dit team det, og er der hvis noget skal justeres.',
                  icon: IconCheck,
                },
              ].map((step, i) => {
                const Ic = step.icon;
                return (
                  <div key={step.num} style={{ position: 'relative' }}>
                    <div style={{
                      display: 'flex', alignItems: 'center', gap: 12, marginBottom: 12,
                    }}>
                      <div style={{
                        width: 32, height: 32, borderRadius: '50%',
                        background: '#3F4A3A', color: '#fff',
                        display: 'flex', alignItems: 'center', justifyContent: 'center',
                        fontFamily: 'Fraunces, serif', fontWeight: 500, fontSize: 14,
                      }}>{step.num}</div>
                      <div style={{ color: '#7B8A6B' }}>
                        <Ic size={16} strokeWidth={1.8} />
                      </div>
                    </div>
                    <div style={{ fontSize: 14, fontWeight: 600, marginBottom: 6 }}>{step.title}</div>
                    <div style={{ fontSize: 13, color: '#666', lineHeight: 1.55 }}>{step.text}</div>
                  </div>
                );
              })}
            </div>
          </div>

          {/* Pricing reassurance + CTA */}
          <div style={{
            background: '#1F2A2E', color: '#fff', borderRadius: 20,
            padding: '40px 36px',
            display: 'grid', gridTemplateColumns: '1.5fr 1fr', gap: 40, alignItems: 'center',
          }}>
            <div>
              <div style={{ fontSize: 12, fontWeight: 700, color: '#C9D8B5', letterSpacing: '0.1em', marginBottom: 12 }}>
                INGEN OVERRASKELSER
              </div>
              <h3 style={{
                fontFamily: 'Fraunces, serif', fontSize: 26, fontWeight: 400,
                margin: '0 0 14px', color: '#fff', lineHeight: 1.25,
              }}>
                Du får altid en <span style={{ fontStyle: 'italic', color: '#C9D8B5' }}>fast pris</span> efter første møde.
              </h3>
              <p style={{ fontSize: 14, lineHeight: 1.7, color: 'rgba(255,255,255,0.78)', margin: 0 }}>
                Mindre tilpasninger starter fra et par tusinde kroner. Komplette specialløsninger
                er typisk større investeringer, men vi laver altid en aftale der passer til
                din størrelse — og du betaler ikke for noget før vi har sagt god for det.
              </p>
            </div>

            <div style={{ textAlign: 'center' }}>
              <a
                href="mailto:hello@ooniq.dk?subject=Skr%C3%A6ddersyet%20Saloniq-l%C3%B8sning"
                style={{
                  display: 'inline-flex', alignItems: 'center', gap: 10,
                  background: '#C9D8B5', color: '#1F2A2E', textDecoration: 'none',
                  borderRadius: 12, padding: '16px 28px', fontWeight: 600, fontSize: 15,
                  fontFamily: 'inherit',
                  boxShadow: '0 8px 24px rgba(201,216,181,0.20)',
                  transition: 'transform 160ms',
                }}
                onMouseEnter={e => e.currentTarget.style.transform = 'translateY(-1px)'}
                onMouseLeave={e => e.currentTarget.style.transform = 'none'}>
                <IconCoffee size={18} strokeWidth={1.8} />
                Book et gratis kaffemøde
              </a>
              <div style={{ marginTop: 14, fontSize: 13, color: 'rgba(255,255,255,0.55)' }}>
                Eller ring direkte på <strong style={{ color: '#fff' }}>50 92 02 01</strong>
              </div>
            </div>
          </div>
        </div>
      </section>

      {/* ── Bottom CTA ───────────────────────────────────── */}
      <section style={{
        maxWidth: 800, margin: '0 auto', padding: '100px 32px', textAlign: 'center',
      }}>
        <h2 style={{
          fontFamily: 'Fraunces, serif', fontSize: 48, fontWeight: 400,
          margin: 0, lineHeight: 1.15, letterSpacing: '-0.01em',
        }}>
          Klar til at give din salon
          <br/>
          <span style={{ fontStyle: 'italic', color: '#7B8A6B' }}>den software, den fortjener?</span>
        </h2>
        <p style={{ marginTop: 22, fontSize: 16, color: '#666', lineHeight: 1.6 }}>
          Log ind på din konto og kom i gang på under 2 minutter.
        </p>
        <button onClick={() => openLogin()} style={{
          marginTop: 36, background: '#3F4A3A', color: '#fff', border: 'none', borderRadius: 12,
          padding: '17px 40px', fontSize: 16, fontWeight: 600, cursor: 'pointer',
          fontFamily: 'inherit', boxShadow: '0 6px 18px rgba(63,74,58,0.25)',
          transition: 'all 160ms',
        }}
        onMouseEnter={e => { e.currentTarget.style.background = '#2A332A'; e.currentTarget.style.transform = 'translateY(-2px)'; }}
        onMouseLeave={e => { e.currentTarget.style.background = '#3F4A3A'; e.currentTarget.style.transform = 'none'; }}>
          Log ind på din konto →
        </button>
      </section>

      {/* ── Footer ───────────────────────────────────────── */}
      <footer id="kontakt" style={{
        borderTop: '1px solid #EFEDE5', padding: '40px 32px',
        background: '#fff',
      }}>
        <div style={{
          maxWidth: 1180, margin: '0 auto',
          display: 'flex', justifyContent: 'space-between', alignItems: 'center', flexWrap: 'wrap', gap: 16,
        }}>
          <Logo size={28} withTagline />
          <div style={{ display: 'flex', gap: 28, fontSize: 13, color: '#888', flexWrap: 'wrap' }}>
            <span>hello@ooniq.dk</span>
            <span>+45 50 92 02 01</span>
            <span>© {new Date().getFullYear()} Saloniq</span>
          </div>
        </div>
      </footer>

      {activeFeature && (
        <FeaturePreviewModal
          feature={activeFeature}
          onClose={() => setActiveFeature(null)}
        />
      )}
    </div>
  );
}

const navLink = {
  textDecoration: 'none', color: '#1a1a1a', fontSize: 14, fontWeight: 500,
  transition: 'color 120ms',
};

// ─── FEATURES catalog ─────────────────────────────────────────────────────────
const FEATURES = [
  {
    id: 'onlinebooking',
    icon: IconLink,
    title: 'Online booking 24/7',
    text: 'Kunderne booker selv på dit eget booking-link. Fanger nye kunder mens du sover.',
    description: 'Hver salon får et unikt link (fx booking.saloniq.dk/dinsalon). Kunderne vælger ydelse, behandler, dato og tid på 60 sekunder. Bookingen lander direkte i din kalender og en bekræftelse er allerede sendt før de lægger telefonen fra sig.',
    selling: true,
  },
  {
    id: 'calendar',
    icon: IconCalendar,
    title: 'Smuk kalender',
    text: 'Drag-and-drop bookinger, multi-medarbejder visning, kombinerede services med automatiske mellemrum.',
    description: 'Kalenderen viser alle medarbejdere side-om-side. Træk en booking for at flytte den, klik et slot for at oprette en ny. Mellemrum mellem services (fx farve-pause) markeres automatisk, så frisøren kan tage en kunde mere ind i pausen.',
    selling: true,
  },
  {
    id: 'stats',
    icon: IconChart,
    title: 'Indsigt der sælger mere',
    text: 'Omsætning, nye vs. faste kunder, kønsfordeling — alt sammen med ét klik.',
    description: 'Se omsætning pr. dag/uge/måned/år eller pr. medarbejder. En smiley fortæller dig om I er på vej til at ramme målet. Find ud af hvor mange nye kunder I lige har taget ind, og hvilke ydelser der trækker mest.',
    selling: true,
  },
  {
    id: 'pos',
    icon: IconReceipt,
    title: 'Kasse + kvitteringer',
    text: 'Indbygget kassesystem med rabat, lager og email-kvittering.',
    description: 'Når kunden er færdig sendes bookingen direkte til kassen med ét klik. Tilføj produkter, giv rabat i kr eller %, vælg betalingsmetode. Kvittering printes på 80mm thermal eller sendes som brandet email.',
    selling: true,
  },
  {
    id: 'customers',
    icon: IconUsers,
    title: 'Kundekartotek',
    text: 'Historik, opskrifter, allergier — alt det jeres team har brug for at huske.',
    description: 'Hver kunde har profil med kontakt, besøgsantal og foretrukken behandler. Farve-opskrifter gemmes så I altid kan ramme samme nuance igen. Noter er synlige for hele teamet med ét blik.',
    selling: true,
  },
  {
    id: 'sms',
    icon: IconMail,
    title: 'Automatiske bekræftelser',
    text: 'Brandede bekræftelser og påmindelser. Kunden kan selv aflyse via link.',
    description: 'Når en booking oprettes modtager kunden en bekræftelse i salonens egen tone. Påmindelse 24 timer og 2 timer før reducerer no-shows. Selv-aflysning via link betyder ingen telefonopkald midt i en behandling.',
    selling: true,
  },
  {
    id: 'inventory',
    icon: IconBox,
    title: 'Lager med advarsler',
    text: 'Lageret tæller automatisk ned ved hvert salg. Aldrig løbe tør for voks igen.',
    description: 'Hver gang du sælger en flaske shampoo trækkes den fra lageret. Når et produkt rammer under 10 stk får du en gul advarsel; under 5 stk popper en bekræftelses-besked op så I husker at bestille hjem.',
    selling: false,
  },
  {
    id: 'departments',
    icon: IconBuilding,
    title: 'Flere afdelinger',
    text: 'Kører du flere saloner? Hver afdeling får sin egen kalender og vagtplan.',
    description: 'Opret afdelinger og tildel medarbejdere. Filtrer kalenderen pr. afdeling, så hver lokation har sit eget overblik. Indikatorer i mini-kalenderen viser hvor der er bookinger.',
    selling: false,
  },
  {
    id: 'pin',
    icon: IconLock,
    title: 'PIN-beskyttelse',
    text: 'Følsomme handlinger kræver PIN — med fleksibel timeout.',
    description: 'Når en medarbejder vil ændre priser, slette bookinger eller redigere personaledata, kræves en PIN. Du vælger hvor længe låsen er åben — 5 minutter, 1 time, eller indtil fanen lukkes.',
    selling: false,
  },
];

// ─── Feature Preview Modal ────────────────────────────────────────────────────
function FeaturePreviewModal({ feature, onClose }) {
  React.useEffect(() => {
    const prev = document.body.style.overflow;
    document.body.style.overflow = 'hidden';
    const onEsc = (e) => { if (e.key === 'Escape') onClose(); };
    window.addEventListener('keydown', onEsc);
    return () => {
      document.body.style.overflow = prev;
      window.removeEventListener('keydown', onEsc);
    };
  }, [onClose]);

  const Preview = {
    calendar: CalendarPreview,
    sms: SmsPreview,
    customers: CustomersPreview,
    stats: StatsPreview,
    departments: DepartmentsPreview,
    pin: PinPreview,
  }[feature.id];

  const Ic = feature.icon;

  return (
    <div style={{
      position: 'fixed', inset: 0, background: 'rgba(20,20,20,0.55)', zIndex: 1000,
      backdropFilter: 'blur(6px)',
      display: 'flex', alignItems: 'center', justifyContent: 'center',
      padding: 32, animation: 'fadeIn 200ms',
      fontFamily: "'Manrope', sans-serif",
    }}>
      <div style={{
        background: '#FBFAF6', borderRadius: 20,
        width: '100%', maxWidth: 1100, height: '88vh', maxHeight: 760,
        display: 'flex', flexDirection: 'column',
        boxShadow: '0 24px 80px rgba(0,0,0,0.30)',
        overflow: 'hidden',
        animation: 'slideUp 250ms ease',
      }}>
        {/* Header */}
        <div style={{
          padding: '20px 28px', borderBottom: '1px solid #EFEDE5',
          background: '#fff',
          display: 'flex', alignItems: 'center', gap: 18,
        }}>
          <div style={{
            width: 44, height: 44, borderRadius: 11, background: '#F4F7F0',
            display: 'flex', alignItems: 'center', justifyContent: 'center',
            color: '#3F5A30', flexShrink: 0,
          }}>
            <Ic size={22} strokeWidth={1.8} />
          </div>
          <div style={{ flex: 1, minWidth: 0 }}>
            <div style={{ fontFamily: 'Fraunces, serif', fontSize: 22, fontWeight: 500 }}>{feature.title}</div>
            <div style={{ fontSize: 13, color: '#666', marginTop: 2, lineHeight: 1.5 }}>{feature.description}</div>
          </div>
          <div style={{
            padding: '4px 10px', borderRadius: 16, fontSize: 11, fontWeight: 700,
            background: '#FEF3C7', color: '#92400E', letterSpacing: '0.04em',
            textTransform: 'uppercase', flexShrink: 0,
          }}>Demo · skrivebeskyttet</div>
          <button onClick={onClose} style={{
            background: '#F4F2EA', border: 'none', borderRadius: 10,
            width: 36, height: 36, cursor: 'pointer', color: '#666',
            display: 'flex', alignItems: 'center', justifyContent: 'center',
            flexShrink: 0,
          }}
          onMouseEnter={e => e.currentTarget.style.background = '#E5E2D5'}
          onMouseLeave={e => e.currentTarget.style.background = '#F4F2EA'}>
            <IconX size={18} />
          </button>
        </div>

        {/* Body */}
        <div style={{ flex: 1, overflow: 'hidden', position: 'relative' }}>
          {Preview && <Preview />}
        </div>
      </div>
    </div>
  );
}

// ─── Preview: Calendar ────────────────────────────────────────────────────────
const PREVIEW_STAFF = [
  { id: 's1', name: 'Caroline', initials: 'CH', tone: '#E8C8B4' },
  { id: 's2', name: 'Jakob',    initials: 'JC', tone: '#B4D2E8' },
  { id: 's3', name: 'Katrine',  initials: 'KJ', tone: '#D8C0E0' },
];
const PREVIEW_BOOKINGS = [
  { id: 'b1', staffId: 's1', start: 9*60,    dur: 30, title: 'Herreklip', customer: 'Mathias Knudsen', phone: '+45 50 92 02 01', price: 350, color: { bg: '#FFB3B3', border: '#E14F4F', text: '#5A0E0E' } },
  { id: 'b2', staffId: 's1', start: 10*60+30, dur: 30, title: 'Herreklip', customer: 'Henrik Madsen',   phone: '+45 50 92 02 01', price: 350, color: { bg: '#FFB3B3', border: '#E14F4F', text: '#5A0E0E' } },
  { id: 'b3', staffId: 's1', start: 13*60,    dur: 30, title: 'Behandling', customer: 'Kirsten Andersen', phone: '+45 50 92 02 01', price: 395, color: { bg: '#CFB8E8', border: '#7E5BB3', text: '#2D1A50' } },
  { id: 'b4', staffId: 's2', start: 9*60,     dur: 105, title: 'Helfarve + Dameklip', customer: 'Laura Sørensen', phone: '+45 50 92 02 01', price: 1220, color: { bg: '#CFB8E8', border: '#7E5BB3', text: '#2D1A50' } },
  { id: 'b5', staffId: 's2', start: 12*60+15, dur: 30, title: 'Herreklip', customer: 'Patrick Hansen', phone: '+45 50 92 02 01', price: 350, color: { bg: '#FFB3B3', border: '#E14F4F', text: '#5A0E0E' } },
  { id: 'b6', staffId: 's2', start: 14*60,    dur: 60, title: 'Dameklip', customer: 'Hanne Alling', phone: '+45 50 92 02 01', price: 525, color: { bg: '#B5E3B5', border: '#4FA84F', text: '#1A4A1A' } },
  { id: 'b7', staffId: 's3', start: 11*60,    dur: 30, title: 'Herreklip', customer: 'Thomas Juul', phone: '+45 50 92 02 01', price: 350, color: { bg: '#FFB3B3', border: '#E14F4F', text: '#5A0E0E' } },
  { id: 'b8', staffId: 's3', start: 14*60,    dur: 105, title: 'Striber + Dameklip', customer: 'Cecilie Larsen', phone: '+45 50 92 02 01', price: 1375, color: { bg: '#F2B8D2', border: '#C25D89', text: '#511A36' } },
];

function CalendarPreview() {
  const [selected, setSelected] = React.useState(null);
  const HOUR_HEIGHT = 80;
  const START_HOUR = 9;
  const END_HOUR = 17;
  const fmt = (mins) => `${String(Math.floor(mins/60)).padStart(2,'0')}:${String(mins%60).padStart(2,'0')}`;

  return (
    <div style={{ display: 'flex', height: '100%', background: '#FBFAF6' }}>
      {/* Calendar */}
      <div style={{ flex: 1, overflow: 'auto', padding: 20 }}>
        <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 16 }}>
          <div>
            <div style={{ fontFamily: 'Fraunces, serif', fontSize: 20, fontWeight: 500 }}>Torsdag 6. juni 2024</div>
            <div style={{ fontSize: 12, color: '#888' }}>Eksempel-salon · {PREVIEW_BOOKINGS.length} bookinger</div>
          </div>
          <div style={{ display: 'flex', gap: 8 }}>
            <button disabled style={{ width: 32, height: 32, borderRadius: 8, border: '1px solid #DDD9CE', background: '#fff', color: '#aaa', cursor: 'not-allowed' }}>‹</button>
            <button disabled style={{ padding: '4px 12px', borderRadius: 8, border: '1px solid #DDD9CE', background: '#fff', color: '#aaa', cursor: 'not-allowed', fontSize: 13 }}>I dag</button>
            <button disabled style={{ width: 32, height: 32, borderRadius: 8, border: '1px solid #DDD9CE', background: '#fff', color: '#aaa', cursor: 'not-allowed' }}>›</button>
          </div>
        </div>

        <div style={{ display: 'flex', background: '#fff', borderRadius: 12, border: '1px solid #EFEDE5', overflow: 'hidden' }}>
          {/* Time column */}
          <div style={{ width: 56, borderRight: '1px solid #EFEDE5', flexShrink: 0 }}>
            <div style={{ height: 40, borderBottom: '1px solid #EFEDE5' }} />
            {Array.from({ length: END_HOUR - START_HOUR }).map((_, i) => (
              <div key={i} style={{
                height: HOUR_HEIGHT, borderBottom: '1px solid #F4F2EA',
                fontSize: 11, color: '#888', padding: '4px 8px', textAlign: 'right',
              }}>{START_HOUR + i}:00</div>
            ))}
          </div>

          {/* Staff columns */}
          {PREVIEW_STAFF.map((staff, sIdx) => (
            <div key={staff.id} style={{
              flex: 1, position: 'relative',
              borderRight: sIdx < PREVIEW_STAFF.length - 1 ? '1px solid #F4F2EA' : 'none',
            }}>
              {/* Header */}
              <div style={{
                height: 40, borderBottom: '1px solid #EFEDE5',
                display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 8,
                background: '#FBFAF6',
              }}>
                <div style={{
                  width: 24, height: 24, borderRadius: '50%', background: staff.tone,
                  display: 'flex', alignItems: 'center', justifyContent: 'center',
                  fontSize: 10, fontWeight: 700, color: '#3F4A3A',
                }}>{staff.initials}</div>
                <span style={{ fontSize: 13, fontWeight: 500 }}>{staff.name}</span>
              </div>

              {/* Hour grid */}
              {Array.from({ length: END_HOUR - START_HOUR }).map((_, i) => (
                <div key={i} style={{ height: HOUR_HEIGHT, borderBottom: '1px solid #F4F2EA' }} />
              ))}

              {/* Bookings */}
              {PREVIEW_BOOKINGS.filter(b => b.staffId === staff.id).map(b => {
                const top = ((b.start - START_HOUR*60) / 60) * HOUR_HEIGHT;
                const height = (b.dur / 60) * HOUR_HEIGHT;
                const isSelected = selected?.id === b.id;
                return (
                  <div key={b.id}
                    onClick={() => setSelected(b)}
                    style={{
                      position: 'absolute', top: top + 40 + 2, left: 4, right: 4, height: height - 4,
                      background: b.color.bg, borderLeft: `3px solid ${b.color.border}`,
                      borderRadius: 6, padding: '5px 8px',
                      cursor: 'pointer', overflow: 'hidden',
                      outline: isSelected ? '2px solid #1F2A2E' : 'none', outlineOffset: -1,
                      transition: 'transform 120ms',
                      display: 'flex', flexDirection: 'column', gap: 1,
                    }}
                    onMouseEnter={e => e.currentTarget.style.transform = 'scale(1.02)'}
                    onMouseLeave={e => e.currentTarget.style.transform = 'none'}>
                    <div style={{
                      fontSize: 11, fontWeight: 600, color: b.color.text, lineHeight: 1.2,
                      whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis',
                    }}>
                      {fmt(b.start)} · {b.customer}
                    </div>
                    <div style={{
                      fontSize: 10, color: b.color.text, opacity: 0.75, lineHeight: 1.2,
                      whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis',
                    }}>
                      {b.title}
                    </div>
                  </div>
                );
              })}
            </div>
          ))}
        </div>

        <div style={{
          marginTop: 14, fontSize: 12, color: '#888', textAlign: 'center',
          display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 6,
        }}>
          <IconInfo size={13} stroke="#888" /> Klik en booking for at se detaljerne i panelet til højre
        </div>
      </div>

      {/* Detail panel */}
      <div style={{
        width: 320, flexShrink: 0, background: '#fff', borderLeft: '1px solid #EFEDE5',
        padding: '24px 22px', overflow: 'auto',
      }}>
        {selected ? (
          <>
            <div style={{
              fontSize: 11, fontWeight: 700, color: '#888',
              letterSpacing: '0.08em', textTransform: 'uppercase', marginBottom: 6,
            }}>Booking-detaljer</div>
            <div style={{ fontFamily: 'Fraunces, serif', fontSize: 22, fontWeight: 500, marginBottom: 4 }}>{selected.customer}</div>
            <div style={{ fontSize: 13, color: '#666' }}>{selected.phone}</div>

            <div style={{ marginTop: 22, padding: '16px 0', borderTop: '1px solid #EFEDE5', borderBottom: '1px solid #EFEDE5' }}>
              <div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: 12 }}>
                <span style={{ fontSize: 12, color: '#888' }}>Tid</span>
                <span style={{ fontSize: 13, fontWeight: 500 }}>{fmt(selected.start)}–{fmt(selected.start + selected.dur)}</span>
              </div>
              <div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: 12 }}>
                <span style={{ fontSize: 12, color: '#888' }}>Varighed</span>
                <span style={{ fontSize: 13, fontWeight: 500 }}>{selected.dur} min</span>
              </div>
              <div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: 12 }}>
                <span style={{ fontSize: 12, color: '#888' }}>Hos</span>
                <span style={{ fontSize: 13, fontWeight: 500 }}>{PREVIEW_STAFF.find(s => s.id === selected.staffId)?.name}</span>
              </div>
              <div style={{ display: 'flex', justifyContent: 'space-between' }}>
                <span style={{ fontSize: 12, color: '#888' }}>Service</span>
                <span style={{ fontSize: 13, fontWeight: 500, textAlign: 'right' }}>{selected.title}</span>
              </div>
            </div>

            <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline', marginTop: 18 }}>
              <span style={{ fontSize: 13, color: '#888' }}>Pris</span>
              <span style={{ fontFamily: 'Fraunces, serif', fontSize: 24, fontWeight: 500 }}>{selected.price} kr</span>
            </div>

            <div style={{ marginTop: 18, padding: '10px 14px', background: '#F4F7F0', border: '1px solid #DCE6CC', borderRadius: 8, fontSize: 12, color: '#3F5A30' }}>
              ✓ Bekræftelse sendt på SMS og email
            </div>

            <button disabled style={{
              marginTop: 24, width: '100%', padding: 12,
              background: '#D4D0C8', color: '#fff', border: 'none', borderRadius: 8,
              fontSize: 14, fontWeight: 600, cursor: 'not-allowed', fontFamily: 'inherit',
            }}>Send besked til kunden</button>
          </>
        ) : (
          <div style={{ paddingTop: 100, textAlign: 'center', color: '#aaa', fontSize: 13 }}>
            Klik på en booking i kalenderen for at se detaljerne her.
          </div>
        )}
      </div>
    </div>
  );
}

// ─── Preview: SMS ─────────────────────────────────────────────────────────────
function SmsPreview() {
  const [active, setActive] = React.useState(0);
  const messages = [
    {
      kind: 'Bekræftelse · sendes ved booking',
      time: 'I dag 10:14',
      body: `Hej Mathias,\n\nDin tid er bekræftet:\nTorsdag 6. juni kl. 09:00\nHerreklip hos Caroline\nSalon Eksempel\n\nSe/aflys: saloniq.dk/k/A4F2\n— Salon Eksempel`,
    },
    {
      kind: 'Påmindelse · 24 timer før',
      time: 'I morgen 09:00',
      body: `Hej Mathias 👋\n\nHusk din tid i morgen kl. 09:00 hos Caroline.\n\nKan du ikke komme? Aflys gratis indtil 9 timer før: saloniq.dk/k/A4F2`,
    },
    {
      kind: 'Påmindelse · 2 timer før',
      time: 'Torsdag 07:00',
      body: `Hej Mathias!\n\nVi ses kl. 09:00 hos Caroline. Indtil da — kør forsigtigt ☕`,
    },
  ];

  return (
    <div style={{ display: 'flex', height: '100%', background: '#FBFAF6' }}>
      {/* Message list */}
      <div style={{ width: 320, flexShrink: 0, background: '#fff', borderRight: '1px solid #EFEDE5', overflow: 'auto', padding: '20px 0' }}>
        <div style={{ padding: '0 22px 16px', borderBottom: '1px solid #EFEDE5' }}>
          <div style={{ fontFamily: 'Fraunces, serif', fontSize: 18, fontWeight: 500 }}>Beskeder til Mathias</div>
          <div style={{ fontSize: 12, color: '#888', marginTop: 2 }}>+45 50 92 02 01 · 3 sendt</div>
        </div>
        {messages.map((m, i) => (
          <button key={i} onClick={() => setActive(i)} style={{
            display: 'block', width: '100%', textAlign: 'left',
            padding: '14px 22px', background: i === active ? '#F4F2EA' : 'transparent',
            border: 'none', borderBottom: '1px solid #F4F2EA',
            borderLeft: i === active ? '3px solid #7B8A6B' : '3px solid transparent',
            paddingLeft: i === active ? 19 : 22,
            cursor: 'pointer', fontFamily: 'inherit',
          }}>
            <div style={{ fontSize: 12, fontWeight: 600, color: '#3F4A3A' }}>{m.kind.split(' · ')[0]}</div>
            <div style={{ fontSize: 11, color: '#888', marginTop: 3 }}>{m.kind.split(' · ')[1]}</div>
            <div style={{ fontSize: 11, color: '#aaa', marginTop: 6 }}>{m.time}</div>
          </button>
        ))}
      </div>

      {/* Phone preview */}
      <div style={{ flex: 1, display: 'flex', alignItems: 'center', justifyContent: 'center', overflow: 'auto', padding: 30 }}>
        <div style={{
          width: 320, background: '#1F2A2E', borderRadius: 36,
          padding: 14, boxShadow: '0 30px 60px rgba(0,0,0,0.30)',
        }}>
          <div style={{ background: '#fff', borderRadius: 26, overflow: 'hidden', minHeight: 480 }}>
            <div style={{
              background: '#F4F2EA', padding: '12px 16px',
              borderBottom: '1px solid #EFEDE5',
              display: 'flex', alignItems: 'center', gap: 10,
            }}>
              <div style={{
                width: 32, height: 32, borderRadius: '50%', background: '#3F4A3A',
                display: 'flex', alignItems: 'center', justifyContent: 'center',
                fontFamily: 'Fraunces, serif', color: '#fff', fontSize: 13, fontWeight: 500,
              }}>K</div>
              <div>
                <div style={{ fontSize: 13, fontWeight: 600 }}>Salon Eksempel</div>
                <div style={{ fontSize: 11, color: '#888' }}>SMS</div>
              </div>
            </div>
            <div style={{ padding: 18 }}>
              <div style={{ fontSize: 11, color: '#888', textAlign: 'center', marginBottom: 12 }}>{messages[active].time}</div>
              <div style={{
                background: '#E5E5EA', borderRadius: 18, padding: '10px 14px',
                fontSize: 13, lineHeight: 1.5, color: '#1a1a1a', whiteSpace: 'pre-line',
              }}>{messages[active].body}</div>
            </div>
          </div>
        </div>
      </div>
    </div>
  );
}

// ─── Preview: Customers ───────────────────────────────────────────────────────
const PREVIEW_CUSTOMERS = [
  { id: 'c1', name: 'Mathias Knudsen', phone: '+45 50 92 02 01', email: 'mathias.k@ooniq.dk', visits: 8, last: 'Herreklip', fav: 'Caroline', notes: 'Foretrækker fade i siderne. Allergisk over for parfumeret shampoo.' },
  { id: 'c2', name: 'Laura Sørensen', phone: '+45 50 92 02 01', email: 'laura.s@ooniq.dk', visits: 14, last: 'Helfarve', fav: 'Jakob', notes: 'Vil altid have helfarve, mørkebrun (6.0). Drikker kaffe med mælk.' },
  { id: 'c3', name: 'Henrik Madsen', phone: '+45 50 92 02 01', email: 'henrik.madsen@ooniq.dk', visits: 22, last: 'Herreklip', fav: 'Caroline', notes: '' },
  { id: 'c4', name: 'Kirsten Andersen', phone: '+45 50 92 02 01', email: 'kirsten.a@ooniq.dk', visits: 33, last: 'Behandling', fav: 'Caroline', notes: 'Stamkunde siden 2015. Foretrækker olivenfarve.' },
  { id: 'c5', name: 'Cecilie Larsen', phone: '+45 50 92 02 01', email: 'cecilie.l@ooniq.dk', visits: 17, last: 'Dameklip', fav: 'Katrine', notes: 'Bestiller altid hårvask + behandling.' },
];

function CustomersPreview() {
  const [selected, setSelected] = React.useState(PREVIEW_CUSTOMERS[0]);

  return (
    <div style={{ display: 'flex', height: '100%', background: '#FBFAF6' }}>
      <div style={{ width: 360, flexShrink: 0, background: '#fff', borderRight: '1px solid #EFEDE5', overflow: 'auto' }}>
        <div style={{ padding: '20px 22px 14px', borderBottom: '1px solid #EFEDE5' }}>
          <div style={{ fontFamily: 'Fraunces, serif', fontSize: 20, fontWeight: 500 }}>Kunder</div>
          <div style={{ fontSize: 12, color: '#888', marginTop: 2 }}>{PREVIEW_CUSTOMERS.length} aktive</div>
        </div>
        {PREVIEW_CUSTOMERS.map(c => {
          const isActive = c.id === selected.id;
          return (
            <button key={c.id} onClick={() => setSelected(c)} style={{
              display: 'flex', alignItems: 'center', gap: 12, width: '100%', textAlign: 'left',
              padding: '12px 22px', borderBottom: '1px solid #F4F2EA',
              background: isActive ? '#F4F2EA' : 'transparent',
              borderLeft: isActive ? '3px solid #7B8A6B' : '3px solid transparent',
              paddingLeft: isActive ? 19 : 22,
              border: 'none', cursor: 'pointer', fontFamily: 'inherit',
            }}>
              <div style={{
                width: 36, height: 36, borderRadius: '50%', background: '#E8DBC8',
                display: 'flex', alignItems: 'center', justifyContent: 'center',
                fontSize: 12, fontWeight: 600, color: '#3F4A3A',
              }}>{c.name.split(' ').map(w => w[0]).slice(0,2).join('')}</div>
              <div style={{ flex: 1, minWidth: 0 }}>
                <div style={{ fontSize: 14, fontWeight: 500 }}>{c.name}</div>
                <div style={{ fontSize: 11, color: '#888', marginTop: 2 }}>{c.phone}</div>
              </div>
              <div style={{ textAlign: 'right' }}>
                <div style={{ fontSize: 11, color: '#888' }}>{c.visits} besøg</div>
                <div style={{ fontSize: 11, color: '#7B8A6B', fontWeight: 500, marginTop: 2 }}>♥ {c.fav}</div>
              </div>
            </button>
          );
        })}
      </div>

      <div style={{ flex: 1, overflow: 'auto', padding: '28px 36px' }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 16, marginBottom: 24 }}>
          <div style={{
            width: 56, height: 56, borderRadius: '50%', background: '#E8DBC8',
            display: 'flex', alignItems: 'center', justifyContent: 'center',
            fontFamily: 'Fraunces, serif', fontSize: 18, fontWeight: 500, color: '#3F4A3A',
          }}>{selected.name.split(' ').map(w => w[0]).slice(0,2).join('')}</div>
          <div>
            <h2 style={{ fontFamily: 'Fraunces, serif', fontSize: 24, fontWeight: 500, margin: 0 }}>{selected.name}</h2>
            <div style={{ fontSize: 12, color: '#888', marginTop: 4 }}>{selected.phone} · {selected.email}</div>
          </div>
        </div>

        <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 10, marginBottom: 24 }}>
          {[
            ['Besøg', selected.visits],
            ['Sidste service', selected.last],
            ['Foretrukken', selected.fav],
          ].map(([l, v]) => (
            <div key={l} style={{ background: '#fff', border: '1px solid #EFEDE5', borderRadius: 10, padding: 14 }}>
              <div style={{ fontSize: 11, color: '#888', textTransform: 'uppercase', letterSpacing: '0.05em', fontWeight: 600 }}>{l}</div>
              <div style={{ fontSize: 16, fontWeight: 600, fontFamily: 'Fraunces, serif', marginTop: 4 }}>{v}</div>
            </div>
          ))}
        </div>

        <div style={{ fontSize: 13, fontWeight: 600, marginBottom: 8 }}>Noter</div>
        <div style={{
          background: '#fff', border: '1px solid #EFEDE5', borderRadius: 10,
          padding: '14px 16px', fontSize: 13, color: selected.notes ? '#444' : '#aaa',
          lineHeight: 1.5, fontStyle: selected.notes ? 'normal' : 'italic',
        }}>
          {selected.notes || 'Ingen noter endnu'}
        </div>

        <div style={{ marginTop: 18, fontSize: 13, fontWeight: 600, marginBottom: 8 }}>Seneste besøg</div>
        <div style={{ background: '#fff', border: '1px solid #EFEDE5', borderRadius: 10, padding: 16, fontSize: 13, color: '#666' }}>
          {selected.last} hos {selected.fav} — for 4 uger siden
        </div>
      </div>
    </div>
  );
}

// ─── Preview: Stats ───────────────────────────────────────────────────────────
function StatsPreview() {
  const services = [
    { name: 'Herreklip', count: 38, color: '#E14F4F' },
    { name: 'Dameklip', count: 24, color: '#4FA84F' },
    { name: 'Helfarve', count: 12, color: '#7E5BB3' },
    { name: 'Striber/folie', count: 9, color: '#C25D89' },
    { name: 'Behandling', count: 14, color: '#7E5BB3' },
    { name: 'Børneklip', count: 6, color: '#3D7DB8' },
    { name: 'Pensionistklip', count: 5, color: '#C9A828' },
  ];
  const max = Math.max(...services.map(s => s.count));

  return (
    <div style={{ height: '100%', overflow: 'auto', padding: '28px 36px', background: '#FBFAF6' }}>
      <h2 style={{ fontFamily: 'Fraunces, serif', fontSize: 24, fontWeight: 500, margin: '0 0 4px' }}>
        Statistik · denne uge
      </h2>
      <div style={{ fontSize: 12, color: '#888', marginBottom: 22 }}>3.–9. juni 2024</div>

      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', gap: 12, marginBottom: 22 }}>
        {[
          ['Bookinger', '108', '+12% vs. sidste uge', '#3F5A30'],
          ['Omsætning', '54.820 kr', '+8%', '#3F5A30'],
          ['Aktive kunder', '94', '+3', '#3F5A30'],
          ['Fyldningsgrad', '78%', '+4 pp', '#3F5A30'],
        ].map(([l, v, sub, col]) => (
          <div key={l} style={{ background: '#fff', border: '1px solid #EFEDE5', borderRadius: 12, padding: 18 }}>
            <div style={{ fontSize: 11, color: '#888', fontWeight: 600, textTransform: 'uppercase', letterSpacing: '0.04em' }}>{l}</div>
            <div style={{ fontSize: 24, fontWeight: 600, fontFamily: 'Fraunces, serif', marginTop: 6 }}>{v}</div>
            <div style={{ fontSize: 11, color: col, marginTop: 4, fontWeight: 600 }}>{sub}</div>
          </div>
        ))}
      </div>

      <div style={{ background: '#fff', border: '1px solid #EFEDE5', borderRadius: 12, padding: 22 }}>
        <div style={{ fontSize: 14, fontWeight: 600, marginBottom: 18 }}>Ydelser fordelt</div>
        <div style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
          {services.map(s => (
            <div key={s.name} style={{ display: 'grid', gridTemplateColumns: '160px 1fr 50px', gap: 12, alignItems: 'center' }}>
              <div style={{ fontSize: 13, fontWeight: 500 }}>{s.name}</div>
              <div style={{ background: '#F4F2EA', borderRadius: 4, height: 20, position: 'relative', overflow: 'hidden' }}>
                <div style={{ background: s.color, height: '100%', width: `${(s.count / max) * 100}%`, transition: 'width 600ms', borderRadius: 4 }} />
              </div>
              <div style={{ fontSize: 13, fontWeight: 600, textAlign: 'right' }}>{s.count}</div>
            </div>
          ))}
        </div>
      </div>
    </div>
  );
}

// ─── Preview: Departments ─────────────────────────────────────────────────────
function DepartmentsPreview() {
  const departments = [
    { id: 'osterbro',  name: 'Østerbro' },
    { id: 'vesterbro', name: 'Vesterbro' },
    { id: 'norrebro',  name: 'Nørrebro' },
  ];
  const staff = [
    { id: 's1', name: 'Caroline Hansen', role: 'Senior frisør', tone: '#E8C8B4', deptId: 'osterbro' },
    { id: 's2', name: 'Jakob Carlsen',   role: 'Frisør',         tone: '#B4D2E8', deptId: 'vesterbro' },
    { id: 's3', name: 'Katrine Jensen',  role: 'Senior frisør',  tone: '#D8C0E0', deptId: 'norrebro' },
    { id: 's4', name: 'Christian Holm',  role: 'Frisør',         tone: '#C8DCB4', deptId: 'osterbro' },
    { id: 's5', name: 'Mette Lund',      role: 'Junior frisør',  tone: '#F0CFC0', deptId: 'vesterbro' },
  ];
  const [selectedId, setSelectedId] = React.useState('osterbro');
  const selected = departments.find(d => d.id === selectedId);
  const inDept = (id) => staff.filter(s => s.deptId === id);

  return (
    <div style={{ display: 'flex', height: '100%', background: '#FBFAF6' }}>
      <div style={{ width: 280, flexShrink: 0, background: '#fff', borderRight: '1px solid #EFEDE5' }}>
        <div style={{ padding: '20px 20px 14px', borderBottom: '1px solid #EFEDE5' }}>
          <div style={{ fontFamily: 'Fraunces, serif', fontSize: 20, fontWeight: 500 }}>Afdelinger</div>
          <div style={{ fontSize: 12, color: '#888', marginTop: 2 }}>{departments.length} afdelinger</div>
        </div>
        {departments.map(d => {
          const isActive = d.id === selectedId;
          return (
            <button key={d.id} onClick={() => setSelectedId(d.id)} style={{
              display: 'flex', alignItems: 'center', width: '100%', textAlign: 'left',
              padding: '14px 20px', borderBottom: '1px solid #F4F2EA',
              background: isActive ? '#F4F2EA' : 'transparent',
              borderLeft: isActive ? '3px solid #7B8A6B' : '3px solid transparent',
              paddingLeft: isActive ? 17 : 20,
              border: 'none', cursor: 'pointer', fontFamily: 'inherit',
            }}>
              <div style={{ flex: 1 }}>
                <div style={{ fontSize: 14, fontWeight: 500 }}>{d.name}</div>
                <div style={{ fontSize: 12, color: '#888', marginTop: 2 }}>{inDept(d.id).length} medarbejdere</div>
              </div>
              <div style={{
                width: 24, height: 24, borderRadius: '50%', background: '#F4F2EA',
                display: 'flex', alignItems: 'center', justifyContent: 'center',
                fontSize: 12, fontWeight: 600, color: '#7B8A6B',
              }}>{inDept(d.id).length}</div>
            </button>
          );
        })}
      </div>

      <div style={{ flex: 1, overflow: 'auto', padding: '28px 36px' }}>
        <h2 style={{ fontFamily: 'Fraunces, serif', fontSize: 26, fontWeight: 500, margin: '0 0 22px' }}>
          {selected?.name}
        </h2>
        <div style={{ fontSize: 13, fontWeight: 600, marginBottom: 14 }}>Medarbejdere i denne afdeling</div>
        <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(220px, 1fr))', gap: 10 }}>
          {staff.map(s => {
            const inThis = s.deptId === selectedId;
            return (
              <div key={s.id} style={{
                display: 'flex', alignItems: 'center', gap: 12,
                padding: '12px 14px',
                background: inThis ? '#F4F7F0' : '#fff',
                border: `1.5px solid ${inThis ? '#C2D6B4' : '#EFEDE5'}`,
                borderRadius: 12,
                opacity: inThis ? 1 : 0.55,
              }}>
                <div style={{
                  width: 36, height: 36, borderRadius: '50%', background: s.tone,
                  display: 'flex', alignItems: 'center', justifyContent: 'center',
                  fontSize: 11, fontWeight: 700, color: '#3F4A3A',
                }}>{s.name.split(' ').map(w => w[0]).slice(0,2).join('')}</div>
                <div style={{ flex: 1, minWidth: 0 }}>
                  <div style={{ fontSize: 13, fontWeight: 500 }}>{s.name}</div>
                  <div style={{ fontSize: 11, color: '#888', marginTop: 2 }}>{s.role}</div>
                </div>
                {inThis && (
                  <div style={{
                    width: 22, height: 22, borderRadius: '50%', background: '#3F4A3A',
                    display: 'flex', alignItems: 'center', justifyContent: 'center',
                  }}>
                    <IconCheck size={12} stroke="#fff" />
                  </div>
                )}
              </div>
            );
          })}
        </div>
      </div>
    </div>
  );
}

// ─── Preview: PIN ─────────────────────────────────────────────────────────────
function PinPreview() {
  const [step, setStep] = React.useState('locked'); // 'locked' | 'entered' | 'timeout'
  const [digits, setDigits] = React.useState(['', '', '', '', '', '']);
  const targetPin = '123456';

  const handlePress = (d) => {
    if (step !== 'locked') return;
    const idx = digits.findIndex(x => x === '');
    if (idx === -1) return;
    const next = [...digits];
    next[idx] = d;
    setDigits(next);
    if (idx === 5) {
      setTimeout(() => {
        if (next.join('') === targetPin) setStep('entered');
        else setDigits(['', '', '', '', '', '']);
      }, 200);
    }
  };
  const handleBack = () => {
    if (step !== 'locked') return;
    const idx = digits.map(x => x).lastIndexOf(digits.find(x => x !== '')) ;
    const newDigits = [...digits];
    for (let i = newDigits.length - 1; i >= 0; i--) {
      if (newDigits[i] !== '') { newDigits[i] = ''; setDigits(newDigits); return; }
    }
  };

  return (
    <div style={{ height: '100%', background: '#FBFAF6', overflow: 'auto', padding: 30 }}>
      <div style={{ display: 'flex', gap: 24, maxWidth: 800, margin: '0 auto', flexWrap: 'wrap' }}>
        {/* PIN dialog */}
        <div style={{
          background: '#fff', borderRadius: 20, padding: 32,
          width: 360, border: '1px solid #EFEDE5',
          boxShadow: '0 8px 30px rgba(0,0,0,0.08)',
        }}>
          {step === 'locked' && (
            <>
              <div style={{ textAlign: 'center', marginBottom: 22 }}>
                <div style={{
                  width: 56, height: 56, margin: '0 auto 14px',
                  background: '#FEF3C7', borderRadius: 14,
                  display: 'flex', alignItems: 'center', justifyContent: 'center',
                  color: '#92400E',
                }}>
                  <IconLock size={26} strokeWidth={1.8} />
                </div>
                <div style={{ fontSize: 11, color: '#92400E', fontWeight: 700, letterSpacing: '0.08em', textTransform: 'uppercase' }}>Adgang kræves</div>
                <h3 style={{ fontFamily: 'Fraunces, serif', fontSize: 18, fontWeight: 500, margin: '8px 0 4px' }}>Indtast PIN</h3>
                <p style={{ fontSize: 12, color: '#888', margin: 0 }}>For at redigere priser kræves en 6-cifret PIN.</p>
                <p style={{ fontSize: 11, color: '#aaa', marginTop: 6 }}>(Demo: prøv 1-2-3-4-5-6)</p>
              </div>
              <div style={{ display: 'flex', justifyContent: 'center', gap: 8, marginBottom: 22 }}>
                {digits.map((d, i) => (
                  <div key={i} style={{
                    width: 36, height: 44, borderRadius: 8,
                    border: '1.5px solid #DDD9CE', background: '#FBFAF6',
                    display: 'flex', alignItems: 'center', justifyContent: 'center',
                    fontSize: 18, fontWeight: 600, color: '#1a1a1a',
                  }}>{d ? '•' : ''}</div>
                ))}
              </div>
              <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 8 }}>
                {[1,2,3,4,5,6,7,8,9].map(n => (
                  <button key={n} onClick={() => handlePress(String(n))} style={pinBtn}>{n}</button>
                ))}
                <button onClick={handleBack} style={{ ...pinBtn, fontSize: 14, color: '#A03838' }}>←</button>
                <button onClick={() => handlePress('0')} style={pinBtn}>0</button>
                <button onClick={() => setDigits(['', '', '', '', '', ''])} style={{ ...pinBtn, fontSize: 12, color: '#888' }}>Ryd</button>
              </div>
            </>
          )}
          {step === 'entered' && (
            <div style={{ textAlign: 'center', padding: '20px 0' }}>
              <div style={{
                width: 56, height: 56, margin: '0 auto 14px',
                background: '#F4F7F0', borderRadius: 14,
                display: 'flex', alignItems: 'center', justifyContent: 'center',
                color: '#3F5A30',
              }}>
                <IconCheck size={26} strokeWidth={2} />
              </div>
              <div style={{ fontSize: 11, color: '#3F5A30', fontWeight: 700, letterSpacing: '0.08em', textTransform: 'uppercase' }}>PIN godkendt</div>
              <h3 style={{ fontFamily: 'Fraunces, serif', fontSize: 18, fontWeight: 500, margin: '8px 0 16px' }}>Hvor længe skal låsen være åben?</h3>
              <div style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>
                {[
                  '1 minut',
                  '5 minutter',
                  '15 minutter',
                  '1 time',
                  'Indtil jeg lukker fanen',
                ].map(t => (
                  <button key={t} onClick={() => { setStep('timeout'); setTimeout(() => { setStep('locked'); setDigits(['', '', '', '', '', '']); }, 1500); }} style={{
                    padding: '10px 14px', background: '#fff', border: '1.5px solid #E5E2D5',
                    borderRadius: 8, cursor: 'pointer', fontFamily: 'inherit', fontSize: 13, fontWeight: 500,
                    textAlign: 'left',
                  }}>{t}</button>
                ))}
              </div>
            </div>
          )}
          {step === 'timeout' && (
            <div style={{ textAlign: 'center', padding: '40px 0' }}>
              <div style={{ fontFamily: 'Fraunces, serif', fontSize: 18, fontWeight: 500 }}>Lås åbnet ✓</div>
              <p style={{ fontSize: 12, color: '#888', marginTop: 6 }}>Demoen genstarter om et øjeblik…</p>
            </div>
          )}
        </div>

        {/* Explanation */}
        <div style={{ flex: '1 1 280px', maxWidth: 360 }}>
          <div style={{ fontSize: 11, fontWeight: 700, color: '#7B8A6B', letterSpacing: '0.1em', marginBottom: 8 }}>SÅDAN VIRKER DET</div>
          <h3 style={{ fontFamily: 'Fraunces, serif', fontSize: 22, fontWeight: 500, margin: '0 0 14px', lineHeight: 1.3 }}>
            Beskyt det vigtige uden at bremse hverdagen.
          </h3>
          <ul style={{ listStyle: 'none', padding: 0, margin: 0, fontSize: 14, color: '#555', lineHeight: 1.7 }}>
            {[
              'Kræves når en medarbejder vil ændre priser, slette bookinger eller redigere personalets data',
              'Vælg selv timeout fra 1 minut til hele dagen',
              'Slip for at logge ind igen for hver lille handling',
              'Logges sammen med brugeren der godkendte',
            ].map(t => (
              <li key={t} style={{ display: 'flex', gap: 10, marginBottom: 12 }}>
                <span style={{ color: '#3F5A30', fontWeight: 700, flexShrink: 0 }}>✓</span>
                {t}
              </li>
            ))}
          </ul>
        </div>
      </div>
    </div>
  );
}

const pinBtn = {
  padding: '14px 0', background: '#FBFAF6', border: '1.5px solid #E5E2D5',
  borderRadius: 8, cursor: 'pointer', fontFamily: 'inherit',
  fontSize: 18, fontWeight: 500,
};

// ─── Customer cancel/reschedule public page ──────────────────────────────────
// Reachable at {salon}.saloniq.dk/aflys-XXXXXXXX. Bypasses auth entirely so
// customers don't get a login screen — they should land directly on a page
// where they can cancel or request a reschedule, and nothing else.
function getCancelSlugFromPath() {
  // Path looks like "/aflys-a6bd1cbe" or "/aflys-a6bd1cbe/" — anything else
  // returns null and the normal app routing kicks in.
  const m = String(window.location.pathname || '').match(/^\/(aflys-[a-f0-9]{4,32})\/?$/i);
  return m ? m[1].toLowerCase() : null;
}

function CustomerCancelPublicPage({ salon, slug }) {
  const [tokenState, setTokenState] = React.useState({ loading: true, data: null, error: null });
  const [action, setAction] = React.useState('cancel'); // 'cancel' | 'reschedule'
  const [reason, setReason] = React.useState('');
  const [message, setMessage] = React.useState('');
  const [submitting, setSubmitting] = React.useState(false);
  const [done, setDone] = React.useState(false);
  const [error, setError] = React.useState('');

  // Brand the browser tab with the salon's actual name.
  React.useEffect(() => {
    if (salon?.name) document.title = 'Saloniq · ' + salon.name;
  }, [salon?.name]);

  const accent = salon.color || '#3F4A3A';

  // Look up the token-doc that the salon wrote when this booking was created.
  // It carries just enough data to greet the customer and show the booking,
  // without exposing phone, email, address or notes.
  React.useEffect(() => {
    let cancelled = false;
    FB.getCancelToken(slug).then(data => {
      if (cancelled) return;
      if (!data) { setTokenState({ loading: false, data: null, error: 'not-found' }); return; }
      // Defensive: if the token belongs to a different salon, reject it
      if (data.salonId !== salon.id) { setTokenState({ loading: false, data: null, error: 'not-found' }); return; }
      setTokenState({ loading: false, data, error: null });
    }).catch(err => {
      if (!cancelled) setTokenState({ loading: false, data: null, error: err?.message || 'load-failed' });
    });
    return () => { cancelled = true; };
  }, [slug, salon.id]);

  const reasons = action === 'cancel'
    ? ['Jeg er syg', 'Andet er kommet i vejen', 'Vil booke en anden tid', 'Andet']
    : ['Andet tidspunkt passer bedre', 'Er forhindret', 'Andet'];

  const submit = async (e) => {
    e?.preventDefault();
    if (submitting || !tokenState.data) return;
    setSubmitting(true);
    setError('');
    try {
      await FB.submitCancelRequest({
        salonId: salon.id, slug,
        bookingId: tokenState.data.bookingId,
        customerName: tokenState.data.customerName,
        customerPhone: '',
        action, reason, message,
      });
      setDone(true);
    } catch (err) {
      console.error('Failed to submit cancel request', err);
      setError('Kunne ikke sende din besked. Prøv igen, eller ring til salonen.');
      setSubmitting(false);
    }
  };

  // Allow normal page scroll on this view (the booking app forces overflow:hidden)
  React.useEffect(() => {
    const prevHtml = document.documentElement.style.overflow;
    const prevBody = document.body.style.overflow;
    document.documentElement.style.overflow = 'auto';
    document.body.style.overflow = 'auto';
    return () => {
      document.documentElement.style.overflow = prevHtml;
      document.body.style.overflow = prevBody;
    };
  }, []);

  // Render booking details from the token-doc
  const fmtTime = (m) => `${String(Math.floor(m/60)).padStart(2,'0')}:${String(m%60).padStart(2,'0')}`;
  const tok = tokenState.data;
  const firstName = (tok?.customerName || '').split(' ')[0];
  const dateText = (() => {
    if (!tok?.dateISO) return '';
    try {
      const [y, m, d] = tok.dateISO.split('-').map(Number);
      return formatDanishDate(new Date(y, m - 1, d));
    } catch { return tok.dateISO; }
  })();

  return (
    <div style={{
      minHeight: '100vh', background: '#FBFAF6',
      fontFamily: "'Manrope', sans-serif", color: '#1a1a1a',
      padding: '40px 20px 80px',
    }}>
      <div style={{ maxWidth: 480, margin: '0 auto' }}>
        {/* Salon header — when a logo is uploaded it represents the salon
            on its own and we don't repeat the name underneath. The name
            still appears as a fallback when no logo has been uploaded. */}
        <div style={{ textAlign: 'center', marginBottom: 28 }}>
          {salon.logo ? (
            <img src={salon.logo} alt={salon.name}
              style={{ maxWidth: 200, maxHeight: 100, objectFit: 'contain', marginBottom: 8 }} />
          ) : (
            <>
              <div style={{
                width: 56, height: 56, margin: '0 auto 12px',
                background: accent, color: '#fff', borderRadius: 14,
                display: 'flex', alignItems: 'center', justifyContent: 'center',
                fontFamily: 'Fraunces, serif', fontSize: 26, fontWeight: 500,
              }}>{(salon.name || 'S')[0].toUpperCase()}</div>
              <div style={{ fontFamily: 'Fraunces, serif', fontSize: 26, fontWeight: 500 }}>{salon.name}</div>
            </>
          )}
          {salon.address && <div style={{ fontSize: 12, color: '#888', marginTop: 4 }}>{salon.address}</div>}
        </div>

        {tokenState.loading ? (
          <div style={{ textAlign: 'center', padding: '40px 0', color: '#888', fontSize: 13 }}>
            Henter din aftale…
          </div>
        ) : tokenState.error || !tok ? (
          <div style={{
            background: '#fff', border: '1px solid #FECACA', borderRadius: 14,
            padding: '32px 28px', textAlign: 'center',
          }}>
            <h2 style={{ fontFamily: 'Fraunces, serif', fontSize: 22, fontWeight: 500, margin: '0 0 10px' }}>
              Linket virker ikke længere
            </h2>
            <p style={{ fontSize: 14, color: '#666', lineHeight: 1.6, margin: '0 0 14px' }}>
              Aftalen er enten allerede aflyst eller afsluttet. Hvis du har brug for at ændre en aftale, så kontakt salonen direkte{salon.phone ? <> på <strong style={{ color: '#444' }}>{salon.phone}</strong></> : ''}.
            </p>
          </div>
        ) : done ? (
          <div style={{
            background: '#fff', border: '1px solid #DCE6CC', borderRadius: 14,
            padding: '32px 28px', textAlign: 'center',
          }}>
            <div style={{
              width: 56, height: 56, margin: '0 auto 16px',
              background: '#F4F7F0', borderRadius: 14,
              display: 'flex', alignItems: 'center', justifyContent: 'center', color: '#3F5A30',
            }}>
              <IconCheck size={26} strokeWidth={2} />
            </div>
            <h2 style={{ fontFamily: 'Fraunces, serif', fontSize: 22, fontWeight: 500, margin: '0 0 10px' }}>
              Tak{firstName ? `, ${firstName}` : ''} — din besked er sendt
            </h2>
            <p style={{ fontSize: 14, color: '#666', lineHeight: 1.6, margin: '0 0 14px' }}>
              {salon.name} har nu modtaget din anmodning {action === 'cancel' ? 'om aflysning' : 'om ombooking'} og kontakter dig hvis der er spørgsmål.
            </p>
            <p style={{ fontSize: 13, color: '#888', lineHeight: 1.5, margin: 0 }}>
              Du kan lukke denne side nu.
            </p>
          </div>
        ) : (
          <>
            {/* Greeting + booking summary card */}
            <div style={{
              background: '#fff', border: '1px solid #EFEDE5', borderRadius: 14,
              padding: '24px 24px 20px', marginBottom: 14,
            }}>
              <div style={{ fontSize: 12, fontWeight: 700, color: accent, letterSpacing: '0.08em', textTransform: 'uppercase', marginBottom: 6 }}>
                Din aftale
              </div>
              <h1 style={{ fontFamily: 'Fraunces, serif', fontSize: 24, fontWeight: 500, margin: '0 0 4px', lineHeight: 1.25 }}>
                Hej{firstName ? ` ${firstName}` : ''}
              </h1>
              <p style={{ fontSize: 13, color: '#666', lineHeight: 1.55, margin: '0 0 16px' }}>
                Vil du aflyse eller flytte din tid?
              </p>

              <div style={{ background: '#FBFAF6', border: '1px solid #EFEDE5', borderRadius: 10, padding: '14px 16px', display: 'flex', flexDirection: 'column', gap: 8, fontSize: 13 }}>
                {tok.serviceTitle && (
                  <div style={{ display: 'flex', justifyContent: 'space-between' }}>
                    <span style={{ color: '#888' }}>Service</span>
                    <span style={{ fontWeight: 500 }}>{tok.serviceTitle}</span>
                  </div>
                )}
                {tok.staffName && (
                  <div style={{ display: 'flex', justifyContent: 'space-between' }}>
                    <span style={{ color: '#888' }}>Hos</span>
                    <span style={{ fontWeight: 500 }}>{tok.staffName}</span>
                  </div>
                )}
                {dateText && (
                  <div style={{ display: 'flex', justifyContent: 'space-between' }}>
                    <span style={{ color: '#888' }}>Dato</span>
                    <span style={{ fontWeight: 500 }}>{dateText}</span>
                  </div>
                )}
                <div style={{ display: 'flex', justifyContent: 'space-between' }}>
                  <span style={{ color: '#888' }}>Tid</span>
                  <span style={{ fontWeight: 500 }}>
                    {fmtTime(tok.startMin)}{tok.durationMin ? `–${fmtTime(tok.startMin + tok.durationMin)}` : ''}
                  </span>
                </div>
                {tok.priceKr > 0 && (
                  <div style={{ display: 'flex', justifyContent: 'space-between' }}>
                    <span style={{ color: '#888' }}>Pris</span>
                    <span style={{ fontWeight: 500 }}>{tok.priceKr} kr</span>
                  </div>
                )}
              </div>
            </div>

            {/* Action form */}
            <form onSubmit={submit} style={{
              background: '#fff', border: '1px solid #EFEDE5', borderRadius: 14,
              padding: '24px 24px',
            }}>
              {/* Action toggle */}
              <div style={{
                display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 8, marginBottom: 18,
                padding: 4, background: '#FBFAF6', border: '1px solid #EFEDE5', borderRadius: 10,
              }}>
                {[
                  { id: 'cancel',     label: 'Aflys min tid' },
                  { id: 'reschedule', label: 'Flyt min tid'  },
                ].map(opt => (
                  <button key={opt.id} type="button" onClick={() => { setAction(opt.id); setReason(''); }} style={{
                    padding: '10px', borderRadius: 8, fontFamily: 'inherit', fontSize: 13, fontWeight: 600,
                    cursor: 'pointer', border: 'none',
                    background: action === opt.id ? accent : 'transparent',
                    color: action === opt.id ? '#fff' : '#666',
                    transition: 'all 120ms',
                  }}>{opt.label}</button>
                ))}
              </div>

              <label style={{ display: 'block', fontSize: 12, fontWeight: 600, color: '#555', marginBottom: 6 }}>
                Årsag (valgfrit)
              </label>
              <div style={{ display: 'flex', flexWrap: 'wrap', gap: 6 }}>
                {reasons.map(r => (
                  <button key={r} type="button" onClick={() => setReason(r === reason ? '' : r)} style={{
                    padding: '8px 12px', borderRadius: 18, fontSize: 12, fontFamily: 'inherit', cursor: 'pointer',
                    background: reason === r ? accent : '#fff',
                    color: reason === r ? '#fff' : '#444',
                    border: `1px solid ${reason === r ? accent : '#DDD9CE'}`,
                    fontWeight: reason === r ? 600 : 500,
                  }}>{r}</button>
                ))}
              </div>

              <label style={{ display: 'block', fontSize: 12, fontWeight: 600, color: '#555', marginTop: 14, marginBottom: 6 }}>
                Besked til salonen (valgfrit)
              </label>
              <textarea value={message} onChange={e => setMessage(e.target.value)} rows={3}
                placeholder={action === 'cancel'
                  ? 'Fx hvornår du gerne vil booke en ny tid…'
                  : 'Hvilke dage/tidspunkter passer dig bedre?'}
                style={{ ...publicInputStyle, resize: 'vertical', minHeight: 80, fontFamily: 'inherit' }} />

              {error && (
                <div style={{
                  marginTop: 14, padding: '10px 14px',
                  background: '#FEF2F2', border: '1px solid #FECACA',
                  borderRadius: 8, fontSize: 13, color: '#B91C1C',
                }}>{error}</div>
              )}

              <button type="submit" disabled={submitting} style={{
                marginTop: 22, width: '100%', padding: '14px',
                background: submitting ? '#D4D0C8' : accent, color: '#fff',
                border: 'none', borderRadius: 10, fontSize: 15, fontWeight: 600,
                cursor: submitting ? 'not-allowed' : 'pointer', fontFamily: 'inherit',
              }}>{submitting ? 'Sender…' : (action === 'cancel' ? 'Bekræft aflysning' : 'Send ombookings-anmodning')}</button>

              {salon.phone && (
                <div style={{ marginTop: 16, textAlign: 'center', fontSize: 12, color: '#888' }}>
                  Eller ring direkte: <strong style={{ color: '#444' }}>{salon.phone}</strong>
                </div>
              )}
            </form>
          </>
        )}

        <div style={{ marginTop: 24, textAlign: 'center', fontSize: 11, color: '#aaa', letterSpacing: '0.04em' }}>
          SALONIQ · AF OONIQ
        </div>
      </div>
    </div>
  );
}

const publicInputStyle = {
  width: '100%', padding: '12px 14px', boxSizing: 'border-box',
  border: '1.5px solid #DDD9CE', borderRadius: 10, fontSize: 14,
  outline: 'none', background: '#FBFAF6', fontFamily: 'inherit',
};

// ─── Public booking page ──────────────────────────────────────────────────────
// Reachable at booking.saloniq.dk/{salon}. No login required. Reads from
// /salonPublic/{id} (mirror written by the mirrorSalonPublic Cloud Function)
// and submits via the submitPublicBooking callable function. Customers see
// the salon's bookable staff, services, and available time slots — and
// receive an email confirmation with the same cancel-link mechanism that
// staff-created bookings use.
function PublicBookingPage({ salonSlug }) {
  const [phase, setPhase] = React.useState('loading'); // 'loading' | 'ready' | 'not-found' | 'done' | 'error'
  const [salon, setSalon] = React.useState(null);
  const [publicData, setPublicData] = React.useState(null);
  const [step, setStep] = React.useState(1); // 1 service · 2 staff · 3 date · 4 time · 5 contact
  const [picked, setPicked] = React.useState({ gender: null, serviceIds: [], staffId: null, date: null, start: null });
  const [contact, setContact] = React.useState({ name: '', email: '', phone: '', phoneCountry: 'DK', note: '' });
  const [submitting, setSubmitting] = React.useState(false);
  const [errorMsg, setErrorMsg] = React.useState('');

  // Allow page-scroll (booking app forces overflow:hidden globally)
  React.useEffect(() => {
    const prevHtml = document.documentElement.style.overflow;
    const prevBody = document.body.style.overflow;
    document.documentElement.style.overflow = 'auto';
    document.body.style.overflow = 'auto';
    return () => {
      document.documentElement.style.overflow = prevHtml;
      document.body.style.overflow = prevBody;
    };
  }, []);

  // Brand the browser tab with the salon's actual name once loaded.
  React.useEffect(() => {
    if (salon?.name) document.title = 'Saloniq · ' + salon.name;
  }, [salon?.name]);

  // Load both the salon doc (for branding) and the public mirror (for data)
  React.useEffect(() => {
    let cancelled = false;
    (async () => {
      try {
        const s = await FB.getSalonBySubdomain(salonSlug);
        if (cancelled) return;
        if (!s) { setPhase('not-found'); return; }
        if (!s.active) { setPhase('not-found'); return; }
        setSalon(s);
        const pubDoc = await FB.db.collection('salonPublic').doc(s.id).get();
        if (cancelled) return;
        if (!pubDoc.exists) {
          setPhase('not-found');
          return;
        }
        setPublicData(pubDoc.data());
        setPhase('ready');
      } catch (err) {
        console.error('Failed loading public booking data', err);
        if (!cancelled) setPhase('error');
      }
    })();
    return () => { cancelled = true; };
  }, [salonSlug]);

  if (phase === 'loading') return <LoadingScreen />;
  if (phase === 'error') {
    return (
      <div style={publicPageWrap}>
        <div style={{ textAlign: 'center', maxWidth: 360, padding: 24, color: '#A03838' }}>
          Kunne ikke hente salon-data. Prøv at genindlæse siden.
        </div>
      </div>
    );
  }
  if (phase === 'not-found') {
    return (
      <div style={publicPageWrap}>
        <div style={{ textAlign: 'center', maxWidth: 360, padding: 24 }}>
          <h2 style={{ fontFamily: 'Fraunces, serif', fontWeight: 500 }}>Salon ikke fundet</h2>
          <p style={{ color: '#888' }}>{salonSlug} kan ikke modtage online bookinger lige nu.</p>
        </div>
      </div>
    );
  }
  if (phase === 'done') {
    return <PublicBookingDone salon={salon} contact={contact} />;
  }

  const accent = salon.color || '#3F4A3A';
  const services = publicData.services || [];
  const staff = (publicData.staff || []);
  const totalDur = picked.serviceIds.reduce((sum, id) => {
    const s = services.find(x => x.id === id);
    return sum + (s ? (s.duration || 0) + (s.pauseAfter || 0) : 0);
  }, 0);

  // Build slot list for the picked date + staff + services
  const buildSlots = () => {
    if (!picked.date || !picked.staffId || picked.serviceIds.length === 0) return [];
    const dt = new Date(picked.date + 'T00:00:00');
    const dayName = DAY_NAMES[dt.getDay()];
    const isOpen = publicData.openDays ? !!publicData.openDays[dayName] : (dayName !== 'Søndag');
    if (!isOpen) return [];
    const hours = publicData.openHours?.[dayName];
    const parseHHMM = (str) => {
      const m = String(str || '').match(/^(\d{1,2}):(\d{2})/);
      return m ? parseInt(m[1], 10) * 60 + parseInt(m[2], 10) : null;
    };
    // Parse staff schedule fx '9-17' / '9–18' / '10:00-16:30' / 'Fri'.
    const parseStaffShift = (s) => {
      if (!s) return null;
      const str = String(s).trim();
      if (!str || /^fri$/i.test(str)) return null;
      const m = str.match(/^\s*(\d{1,2})(?::(\d{2}))?\s*[-–]\s*(\d{1,2})(?::(\d{2}))?\s*$/);
      if (!m) return null;
      const fromH = parseInt(m[1], 10);
      const fromM = m[2] ? parseInt(m[2], 10) : 0;
      const toH = parseInt(m[3], 10);
      const toM = m[4] ? parseInt(m[4], 10) : 0;
      if ([fromH, fromM, toH, toM].some(n => isNaN(n))) return null;
      return { fromMin: fromH * 60 + fromM, toMin: toH * 60 + toM };
    };

    const salonOpen = parseHHMM(hours?.open) ?? 9 * 60;
    const salonClose = parseHHMM(hours?.close) ?? 18 * 60;

    // Intersect salonens åbningstid med medarbejderens vagtplan.
    const staffMember = staff.find(s => s.id === picked.staffId);
    const staffDayKey = ['son','man','tir','ons','tor','fre','lor'][dt.getDay()];
    const shift = staffMember?.schedule ? parseStaffShift(staffMember.schedule[staffDayKey]) : null;
    // Hvis medarbejderen har en vagtplan og ikke arbejder den dag → ingen slots.
    if (staffMember?.schedule && !shift) return [];
    const open = shift ? Math.max(salonOpen, shift.fromMin) : salonOpen;
    const close = shift ? Math.min(salonClose, shift.toMin) : salonClose;
    const latestStart = close - totalDur;
    if (latestStart < open) return [];

    // Build proposed segments helper
    const proposedSegs = (start) => {
      const segs = [];
      let t = start;
      for (const id of picked.serviceIds) {
        const s = services.find(x => x.id === id);
        if (!s) continue;
        segs.push({ start: t, end: t + (s.duration || 0) });
        t += (s.duration || 0) + (s.pauseAfter || 0);
      }
      return segs;
    };

    // Existing busy intervals for this staff on this date
    const busy = [];
    (publicData.bookings || [])
      .filter(b => b.staffId === picked.staffId && b.date === picked.date)
      .forEach(b => {
        let bt = b.start || 0;
        const ids = b.serviceIds || [];
        for (const id of ids) {
          const s = services.find(x => x.id === id);
          if (!s) continue;
          const dur = s.duration || 0;
          busy.push({ start: bt, end: bt + dur });
          bt += dur + (s.pauseAfter || 0);
        }
      });

    const slots = [];
    for (let t = open; t <= latestStart; t += 15) {
      const segs = proposedSegs(t);
      const conflict = segs.some(seg => busy.some(b => seg.start < b.end && seg.end > b.start));
      if (!conflict) slots.push(t);
    }
    return slots;
  };

  const submit = async () => {
    setSubmitting(true);
    setErrorMsg('');
    try {
      const fn = firebase.app().functions('europe-west1').httpsCallable('submitPublicBooking');
      // Sammensæt landekode + nummer; trim duplikat-prefix hvis kunden har
      // skrevet den ind alligevel.
      const country = COUNTRY_CODES.find(c => c.code === contact.phoneCountry) || COUNTRY_CODES[0];
      const rawPhone = contact.phone.trim().replace(/^\+?\d{1,4}\s*/, '');
      const fullPhone = `${country.dial} ${rawPhone}`.trim();
      await fn({
        salonId: salon.id,
        staffId: picked.staffId,
        serviceIds: picked.serviceIds,
        date: picked.date,
        start: picked.start,
        customerName: contact.name,
        customerEmail: contact.email,
        customerPhone: fullPhone,
        customerGender: picked.gender || null,
        note: contact.note,
      });
      setPhase('done');
    } catch (err) {
      console.error('submitPublicBooking failed', err);
      setErrorMsg(err?.message || 'Kunne ikke gennemføre bookingen. Prøv igen.');
      setSubmitting(false);
    }
  };

  const stepLabel = ['Vælg ydelse', 'Vælg behandler', 'Vælg dato', 'Vælg tid', 'Bekræft'][step - 1];

  // Filter services based on chosen gender — 'unisex' og matchende køn.
  const filteredServices = React.useMemo(() => {
    if (!picked.gender) return services;
    return services.filter(s => !s.gender || s.gender === 'unisex' || s.gender === picked.gender);
  }, [services, picked.gender]);

  // Gender-prelude før selve step-flowet
  if (!picked.gender) {
    return (
      <div style={publicPageWrap}>
        <div style={{ maxWidth: 540, margin: '0 auto' }}>
          <PublicSalonHeader salon={salon} />
          <h1 style={{ fontFamily: 'Fraunces, serif', fontSize: 26, fontWeight: 500, margin: '0 0 8px' }}>
            Velkommen
          </h1>
          <p style={{ fontSize: 14, color: '#666', lineHeight: 1.55, margin: '0 0 20px' }}>
            Hvem skal bookes ind?
          </p>
          <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 10 }}>
            {[
              { id: 'female', label: 'Dame' },
              { id: 'male',   label: 'Herre' },
            ].map(g => (
              <button key={g.id} onClick={() => setPicked(p => ({ ...p, gender: g.id }))} style={{
                padding: '32px 18px', borderRadius: 14,
                background: '#fff', border: '2px solid #EFEDE5',
                fontFamily: 'Fraunces, serif', fontSize: 22, fontWeight: 500,
                cursor: 'pointer', color: '#1a1a1a',
                transition: 'all 160ms',
              }}
              onMouseEnter={e => { e.currentTarget.style.borderColor = accent; e.currentTarget.style.background = '#F4F7F0'; }}
              onMouseLeave={e => { e.currentTarget.style.borderColor = '#EFEDE5'; e.currentTarget.style.background = '#fff'; }}>
                {g.label}
              </button>
            ))}
          </div>
          <div style={{ marginTop: 24, textAlign: 'center', fontSize: 11, color: '#aaa', letterSpacing: '0.04em' }}>
            SALONIQ · AF OONIQ
          </div>
        </div>
      </div>
    );
  }

  return (
    <div style={publicPageWrap}>
      <div style={{ maxWidth: 540, margin: '0 auto' }}>
        <PublicSalonHeader salon={salon} />

        {/* Step indicator */}
        <div style={{ display: 'flex', gap: 6, marginBottom: 20 }}>
          {[1, 2, 3, 4, 5].map(n => (
            <div key={n} style={{
              flex: 1, height: 4, borderRadius: 2,
              background: n <= step ? accent : '#EFEDE5',
              transition: 'background 200ms',
            }} />
          ))}
        </div>
        <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 12 }}>
          <div style={{ fontSize: 12, fontWeight: 700, color: accent, letterSpacing: '0.08em', textTransform: 'uppercase' }}>
            Trin {step} af 5 · {picked.gender === 'male' ? 'Herre' : 'Dame'}
          </div>
          <button onClick={() => setPicked(p => ({ ...p, gender: null, serviceIds: [] }))} style={{
            background: 'transparent', border: 'none', color: '#888',
            fontSize: 12, cursor: 'pointer', fontFamily: 'inherit', padding: 0,
            textDecoration: 'underline',
          }}>Skift</button>
        </div>
        <h1 style={{ fontFamily: 'Fraunces, serif', fontSize: 26, fontWeight: 500, margin: '0 0 18px' }}>
          {stepLabel}
        </h1>

        {step === 1 && (
          <PublicStepServices services={filteredServices} picked={picked} setPicked={setPicked} accent={accent} onNext={() => setStep(2)} />
        )}
        {step === 2 && (
          <PublicStepStaff staff={staff} picked={picked} setPicked={setPicked} accent={accent}
            onBack={() => setStep(1)} onNext={() => setStep(3)} />
        )}
        {step === 3 && (
          <PublicStepDate publicData={publicData} picked={picked} setPicked={setPicked} accent={accent}
            onBack={() => setStep(2)} onNext={() => setStep(4)} />
        )}
        {step === 4 && (
          <PublicStepTime slots={buildSlots()} picked={picked} setPicked={setPicked} accent={accent} salon={salon}
            onBack={() => setStep(3)} onNext={() => setStep(5)} />
        )}
        {step === 5 && (
          <PublicStepConfirm
            salon={salon} services={services} staff={staff} publicData={publicData}
            picked={picked} contact={contact} setContact={setContact}
            submitting={submitting} errorMsg={errorMsg}
            accent={accent} onBack={() => setStep(4)} onSubmit={submit}
          />
        )}

        <div style={{ marginTop: 24, textAlign: 'center', fontSize: 11, color: '#aaa', letterSpacing: '0.04em' }}>
          SALONIQ · AF OONIQ
        </div>
      </div>
    </div>
  );
}

const publicPageWrap = {
  minHeight: '100vh', background: '#FBFAF6',
  fontFamily: "'Manrope', sans-serif", color: '#1a1a1a',
  padding: '40px 20px 80px',
};

const PublicSalonHeader = ({ salon }) => (
  <div style={{ textAlign: 'center', marginBottom: 28 }}>
    {salon.logo ? (
      <img src={salon.logo} alt={salon.name}
        style={{ maxWidth: 200, maxHeight: 100, objectFit: 'contain', marginBottom: 8 }} />
    ) : (
      <div style={{
        width: 56, height: 56, margin: '0 auto 12px',
        background: salon.color || '#3F4A3A', color: '#fff', borderRadius: 14,
        display: 'flex', alignItems: 'center', justifyContent: 'center',
        fontFamily: 'Fraunces, serif', fontSize: 26, fontWeight: 500,
      }}>{(salon.name || 'S')[0].toUpperCase()}</div>
    )}
    {!salon.logo && (
      <div style={{ fontFamily: 'Fraunces, serif', fontSize: 24, fontWeight: 500 }}>{salon.name}</div>
    )}
    {salon.address && <div style={{ fontSize: 12, color: '#888', marginTop: 4 }}>{salon.address}</div>}
  </div>
);

const PublicStepServices = ({ services, picked, setPicked, accent, onNext }) => {
  const toggle = (id) => {
    setPicked(p => ({
      ...p,
      serviceIds: p.serviceIds.includes(id)
        ? p.serviceIds.filter(x => x !== id)
        : [...p.serviceIds, id],
    }));
  };
  return (
    <div>
      {services.length === 0 ? (
        <div style={publicCardStyle}>Salonen har ikke oprettet nogen ydelser endnu.</div>
      ) : (
        <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
          {services.map(s => {
            const active = picked.serviceIds.includes(s.id);
            return (
              <button key={s.id} type="button" onClick={() => toggle(s.id)} style={{
                ...publicCardStyle,
                cursor: 'pointer', textAlign: 'left',
                background: active ? '#F4F7F0' : '#fff',
                border: `1.5px solid ${active ? accent : '#EFEDE5'}`,
                display: 'flex', alignItems: 'center', gap: 12,
              }}>
                <div style={{
                  width: 22, height: 22, borderRadius: '50%', flexShrink: 0,
                  border: `2px solid ${active ? accent : '#DDD9CE'}`,
                  background: active ? accent : '#fff',
                  display: 'flex', alignItems: 'center', justifyContent: 'center',
                }}>
                  {active && <IconCheck size={12} stroke="#fff" strokeWidth={3} />}
                </div>
                <div style={{ flex: 1 }}>
                  <div style={{ fontSize: 15, fontWeight: 600 }}>{s.name}</div>
                  <div style={{ fontSize: 12, color: '#888', marginTop: 2 }}>
                    {s.duration} min{s.pauseAfter ? ` + ${s.pauseAfter} min mellemrum` : ''}
                  </div>
                </div>
              </button>
            );
          })}
        </div>
      )}
      <PublicStepNav onNext={onNext} nextDisabled={picked.serviceIds.length === 0} accent={accent} />
    </div>
  );
};

const PublicStepStaff = ({ staff, picked, setPicked, accent, onBack, onNext }) => (
  <div>
    {staff.length === 0 ? (
      <div style={publicCardStyle}>Ingen behandlere er åbne for online booking.</div>
    ) : (
      <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
        {staff.map(s => {
          const active = picked.staffId === s.id;
          return (
            <button key={s.id} type="button" onClick={() => setPicked(p => ({ ...p, staffId: s.id }))} style={{
              ...publicCardStyle,
              cursor: 'pointer', textAlign: 'left',
              background: active ? '#F4F7F0' : '#fff',
              border: `1.5px solid ${active ? accent : '#EFEDE5'}`,
              display: 'flex', alignItems: 'center', gap: 12,
            }}>
              <div style={{
                width: 44, height: 44, borderRadius: '50%', flexShrink: 0,
                background: s.photo ? `url(${s.photo}) center/cover` : (s.tone || '#E8DBC8'),
                display: 'flex', alignItems: 'center', justifyContent: 'center',
                fontFamily: 'Fraunces, serif', fontSize: 18, fontWeight: 500, color: '#3F4A3A',
              }}>
                {!s.photo && (s.name || '?').split(' ').map(w => w[0]).slice(0, 2).join('')}
              </div>
              <div style={{ flex: 1 }}>
                <div style={{ fontSize: 15, fontWeight: 600 }}>{s.name}</div>
                {s.role && <div style={{ fontSize: 12, color: '#888', marginTop: 2 }}>{s.role}</div>}
              </div>
            </button>
          );
        })}
      </div>
    )}
    <PublicStepNav onBack={onBack} onNext={onNext} nextDisabled={!picked.staffId} accent={accent} />
  </div>
);

const PublicStepDate = ({ publicData, picked, setPicked, accent, onBack, onNext }) => {
  // Show the next 21 days, greyed out when the salon is closed that weekday
  const days = [];
  for (let i = 0; i < 21; i++) {
    const d = new Date();
    d.setDate(d.getDate() + i);
    const iso = `${d.getFullYear()}-${String(d.getMonth()+1).padStart(2,'0')}-${String(d.getDate()).padStart(2,'0')}`;
    const dayName = DAY_NAMES[d.getDay()];
    const isOpen = publicData.openDays ? !!publicData.openDays[dayName] : (dayName !== 'Søndag');
    days.push({ iso, label: d.getDate(), monthLabel: d.toLocaleDateString('da-DK', { month: 'short' }), weekday: dayName.slice(0, 3), isOpen });
  }
  return (
    <div>
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(7, 1fr)', gap: 6 }}>
        {days.map(d => {
          const active = picked.date === d.iso;
          return (
            <button key={d.iso} type="button" disabled={!d.isOpen}
              onClick={() => d.isOpen && setPicked(p => ({ ...p, date: d.iso, start: null }))}
              style={{
                padding: '10px 4px', borderRadius: 8, fontFamily: 'inherit',
                background: active ? accent : '#fff',
                color: active ? '#fff' : (d.isOpen ? '#1a1a1a' : '#ccc'),
                border: `1px solid ${active ? accent : '#EFEDE5'}`,
                cursor: d.isOpen ? 'pointer' : 'not-allowed',
                opacity: d.isOpen ? 1 : 0.5,
              }}>
              <div style={{ fontSize: 10, opacity: 0.7 }}>{d.weekday}</div>
              <div style={{ fontSize: 16, fontWeight: 700 }}>{d.label}</div>
              <div style={{ fontSize: 10, opacity: 0.7 }}>{d.monthLabel}</div>
            </button>
          );
        })}
      </div>
      <PublicStepNav onBack={onBack} onNext={onNext} nextDisabled={!picked.date} accent={accent} />
    </div>
  );
};

const PublicStepTime = ({ slots, picked, setPicked, accent, salon, onBack, onNext }) => {
  const fmt = (m) => `${String(Math.floor(m/60)).padStart(2,'0')}:${String(m%60).padStart(2,'0')}`;
  return (
    <div>
      {slots.length === 0 ? (
        <div style={{ ...publicCardStyle, textAlign: 'center', color: '#888' }}>
          Ingen ledige tider den valgte dag. Vælg en anden dato.
          {salon.phone && <div style={{ marginTop: 10, fontSize: 13 }}>Eller ring til salonen: <strong style={{ color: '#444' }}>{salon.phone}</strong></div>}
        </div>
      ) : (
        <div style={{ display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', gap: 6 }}>
          {slots.map(t => {
            const active = picked.start === t;
            return (
              <button key={t} type="button" onClick={() => setPicked(p => ({ ...p, start: t }))} style={{
                padding: '10px 4px', borderRadius: 8, fontFamily: 'inherit', fontSize: 14, fontWeight: 600,
                background: active ? accent : '#fff',
                color: active ? '#fff' : '#1a1a1a',
                border: `1px solid ${active ? accent : '#EFEDE5'}`,
                cursor: 'pointer',
              }}>{fmt(t)}</button>
            );
          })}
        </div>
      )}
      <PublicStepNav onBack={onBack} onNext={onNext} nextDisabled={picked.start === null} accent={accent} />
    </div>
  );
};

// Landekoder med flag-emoji + dial-code + forventet antal cifre (uden landekode).
// length kan være en array af tilladte længder.
const COUNTRY_CODES = [
  { code: 'DK', name: 'Danmark',         dial: '+45',  flag: '🇩🇰', length: 8 },
  { code: 'SE', name: 'Sverige',         dial: '+46',  flag: '🇸🇪', length: [7, 9] },
  { code: 'NO', name: 'Norge',           dial: '+47',  flag: '🇳🇴', length: 8 },
  { code: 'FI', name: 'Finland',         dial: '+358', flag: '🇫🇮', length: [6, 9] },
  { code: 'IS', name: 'Island',          dial: '+354', flag: '🇮🇸', length: 7 },
  { code: 'DE', name: 'Tyskland',        dial: '+49',  flag: '🇩🇪', length: [7, 11] },
  { code: 'GB', name: 'Storbritannien',  dial: '+44',  flag: '🇬🇧', length: 10 },
  { code: 'NL', name: 'Holland',         dial: '+31',  flag: '🇳🇱', length: 9 },
  { code: 'FR', name: 'Frankrig',        dial: '+33',  flag: '🇫🇷', length: 9 },
  { code: 'ES', name: 'Spanien',         dial: '+34',  flag: '🇪🇸', length: 9 },
  { code: 'IT', name: 'Italien',         dial: '+39',  flag: '🇮🇹', length: [9, 10] },
  { code: 'PL', name: 'Polen',           dial: '+48',  flag: '🇵🇱', length: 9 },
  { code: 'US', name: 'USA',             dial: '+1',   flag: '🇺🇸', length: 10 },
  { code: 'AT', name: 'Østrig',          dial: '+43',  flag: '🇦🇹', length: [10, 13] },
  { code: 'BE', name: 'Belgien',         dial: '+32',  flag: '🇧🇪', length: [8, 9] },
  { code: 'CH', name: 'Schweiz',         dial: '+41',  flag: '🇨🇭', length: 9 },
  { code: 'CZ', name: 'Tjekkiet',        dial: '+420', flag: '🇨🇿', length: 9 },
  { code: 'EE', name: 'Estland',         dial: '+372', flag: '🇪🇪', length: [7, 8] },
  { code: 'GR', name: 'Grækenland',      dial: '+30',  flag: '🇬🇷', length: 10 },
  { code: 'IE', name: 'Irland',          dial: '+353', flag: '🇮🇪', length: 9 },
  { code: 'LV', name: 'Letland',         dial: '+371', flag: '🇱🇻', length: 8 },
  { code: 'LT', name: 'Litauen',         dial: '+370', flag: '🇱🇹', length: 8 },
  { code: 'PT', name: 'Portugal',        dial: '+351', flag: '🇵🇹', length: 9 },
  { code: 'RO', name: 'Rumænien',        dial: '+40',  flag: '🇷🇴', length: 9 },
  { code: 'SK', name: 'Slovakiet',       dial: '+421', flag: '🇸🇰', length: 9 },
  { code: 'TR', name: 'Tyrkiet',         dial: '+90',  flag: '🇹🇷', length: 10 },
  { code: 'UA', name: 'Ukraine',         dial: '+380', flag: '🇺🇦', length: 9 },
  { code: 'HU', name: 'Ungarn',          dial: '+36',  flag: '🇭🇺', length: 9 },
];

// Tjek om et nummer matcher landets forventede længde. Returner true/false.
function isPhoneValidForCountry(rawPhone, countryCode) {
  const country = COUNTRY_CODES.find(c => c.code === countryCode) || COUNTRY_CODES[0];
  const digits = String(rawPhone || '').replace(/\D/g, '');
  if (Array.isArray(country.length)) {
    return digits.length >= country.length[0] && digits.length <= country.length[1];
  }
  return digits.length === country.length;
}

const PhoneInputWithCountry = ({ country, onCountryChange, phone, onPhoneChange }) => {
  const [open, setOpen] = React.useState(false);
  const [search, setSearch] = React.useState('');
  const ref = React.useRef(null);

  React.useEffect(() => {
    if (!open) return;
    const onDoc = (e) => { if (ref.current && !ref.current.contains(e.target)) setOpen(false); };
    document.addEventListener('mousedown', onDoc);
    return () => document.removeEventListener('mousedown', onDoc);
  }, [open]);

  const active = COUNTRY_CODES.find(c => c.code === country) || COUNTRY_CODES[0];
  const filtered = search.trim()
    ? COUNTRY_CODES.filter(c =>
        c.name.toLowerCase().includes(search.toLowerCase()) ||
        c.dial.includes(search.replace(/^\+/, ''))
      )
    : COUNTRY_CODES;

  return (
    <div style={{ display: 'flex', gap: 8, position: 'relative' }} ref={ref}>
      <button type="button" onClick={() => setOpen(o => !o)} style={{
        display: 'flex', alignItems: 'center', gap: 6,
        padding: '12px 12px', border: '1.5px solid #DDD9CE', borderRadius: 10,
        background: '#FBFAF6', fontSize: 14, fontFamily: 'inherit', cursor: 'pointer',
        minWidth: 110, flexShrink: 0,
      }}>
        <span style={{ fontSize: 18, lineHeight: 1 }}>{active.flag}</span>
        <span style={{ fontWeight: 600 }}>{active.dial}</span>
        <span style={{ color: '#888', fontSize: 11, marginLeft: 'auto' }}>▾</span>
      </button>
      <input
        type="tel" value={phone}
        onChange={e => onPhoneChange(e.target.value)}
        placeholder={active.code === 'DK' ? '12 34 56 78' : 'telefonnummer'}
        style={{
          flex: 1, padding: '12px 14px', boxSizing: 'border-box',
          border: '1.5px solid #DDD9CE', borderRadius: 10, fontSize: 14,
          outline: 'none', background: '#FBFAF6', fontFamily: 'inherit',
        }}
      />
      {open && (
        <div style={{
          position: 'absolute', top: '100%', left: 0, marginTop: 4, zIndex: 20,
          background: '#fff', border: '1px solid #DDD9CE', borderRadius: 10,
          boxShadow: '0 12px 32px rgba(0,0,0,0.15)', width: 280, maxHeight: 320,
          overflow: 'hidden', display: 'flex', flexDirection: 'column',
        }}>
          <input
            autoFocus type="text" value={search}
            onChange={e => setSearch(e.target.value)}
            placeholder="Søg land…"
            style={{
              padding: '10px 12px', border: 'none', borderBottom: '1px solid #EFEDE5',
              outline: 'none', fontSize: 13, fontFamily: 'inherit',
            }}
          />
          <div style={{ overflow: 'auto', flex: 1 }}>
            {filtered.length === 0 ? (
              <div style={{ padding: 14, fontSize: 12, color: '#888', textAlign: 'center' }}>
                Ingen lande matcher
              </div>
            ) : filtered.map(c => (
              <button key={c.code} type="button" onClick={() => { onCountryChange(c.code); setOpen(false); setSearch(''); }} style={{
                display: 'flex', alignItems: 'center', gap: 10, width: '100%',
                padding: '9px 12px', textAlign: 'left',
                background: c.code === country ? '#F4F2EA' : 'transparent',
                border: 'none', cursor: 'pointer', fontFamily: 'inherit', fontSize: 13,
              }}
              onMouseEnter={e => { if (c.code !== country) e.currentTarget.style.background = '#FBFAF6'; }}
              onMouseLeave={e => { if (c.code !== country) e.currentTarget.style.background = 'transparent'; }}>
                <span style={{ fontSize: 18, lineHeight: 1 }}>{c.flag}</span>
                <span style={{ flex: 1, fontWeight: c.code === country ? 600 : 400 }}>{c.name}</span>
                <span style={{ color: '#888', fontSize: 12, fontFamily: 'ui-monospace, SF Mono, monospace' }}>{c.dial}</span>
              </button>
            ))}
          </div>
        </div>
      )}
    </div>
  );
};

const PublicStepConfirm = ({ salon, services, staff, publicData, picked, contact, setContact, submitting, errorMsg, accent, onBack, onSubmit }) => {
  const stf = staff.find(s => s.id === picked.staffId);
  const svcs = picked.serviceIds.map(id => services.find(s => s.id === id)).filter(Boolean);
  const fmt = (m) => `${String(Math.floor(m/60)).padStart(2,'0')}:${String(m%60).padStart(2,'0')}`;
  const totalDur = svcs.reduce((sum, s) => sum + (s.duration || 0) + (s.pauseAfter || 0), 0);
  const dateLabel = (() => {
    try {
      const [y, m, d] = picked.date.split('-').map(Number);
      return formatDanishDate(new Date(y, m - 1, d));
    } catch { return picked.date; }
  })();

  const emailOk = /.+@.+\..+/.test(contact.email);
  const phoneOk = isPhoneValidForCountry(contact.phone, contact.phoneCountry || 'DK');
  const nameOk = contact.name.trim().length >= 2;
  const canSubmit = !submitting && emailOk && phoneOk && nameOk;

  return (
    <div>
      <div style={{ ...publicCardStyle, marginBottom: 14 }}>
        <div style={{ fontSize: 11, color: '#888', fontWeight: 600, letterSpacing: '0.06em', textTransform: 'uppercase', marginBottom: 8 }}>
          Din aftale
        </div>
        <div style={{ display: 'flex', flexDirection: 'column', gap: 6, fontSize: 13 }}>
          <div style={{ display: 'flex', justifyContent: 'space-between' }}><span style={{ color: '#888' }}>Service</span><span style={{ fontWeight: 500 }}>{svcs.map(s => s.name).join(' + ')}</span></div>
          <div style={{ display: 'flex', justifyContent: 'space-between' }}><span style={{ color: '#888' }}>Hos</span><span style={{ fontWeight: 500 }}>{stf?.name || ''}</span></div>
          <div style={{ display: 'flex', justifyContent: 'space-between' }}><span style={{ color: '#888' }}>Dato</span><span style={{ fontWeight: 500 }}>{dateLabel}</span></div>
          <div style={{ display: 'flex', justifyContent: 'space-between' }}><span style={{ color: '#888' }}>Tid</span><span style={{ fontWeight: 500 }}>{fmt(picked.start)}–{fmt(picked.start + totalDur)}</span></div>
        </div>
      </div>

      <div style={publicCardStyle}>
        <label style={publicLabelStyle}>Dit navn *</label>
        <input value={contact.name} onChange={e => setContact(c => ({ ...c, name: e.target.value }))}
          placeholder="Fornavn Efternavn" style={publicInputStyle} />

        <label style={{ ...publicLabelStyle, marginTop: 14 }}>Email *</label>
        <input type="email" value={contact.email} onChange={e => setContact(c => ({ ...c, email: e.target.value }))}
          placeholder="dig@email.dk" style={publicInputStyle} />

        <label style={{ ...publicLabelStyle, marginTop: 14 }}>Telefon *</label>
        <PhoneInputWithCountry
          country={contact.phoneCountry || 'DK'}
          onCountryChange={(code) => setContact(c => ({ ...c, phoneCountry: code }))}
          phone={contact.phone}
          onPhoneChange={(p) => setContact(c => ({ ...c, phone: p }))}
        />
        {contact.phone && !phoneOk && (() => {
          const country = COUNTRY_CODES.find(c => c.code === (contact.phoneCountry || 'DK')) || COUNTRY_CODES[0];
          const expected = Array.isArray(country.length)
            ? `${country.length[0]}–${country.length[1]} cifre`
            : `${country.length} cifre`;
          const digits = String(contact.phone).replace(/\D/g, '').length;
          return (
            <div style={{ fontSize: 11, color: '#A03838', marginTop: 4 }}>
              {country.name} kræver {expected}. Du har indtastet {digits}.
            </div>
          );
        })()}

        <label style={{ ...publicLabelStyle, marginTop: 14 }}>Besked til salonen (valgfrit)</label>
        <textarea value={contact.note} onChange={e => setContact(c => ({ ...c, note: e.target.value }))} rows={3}
          placeholder="Allergier, særlige ønsker, mv."
          style={{ ...publicInputStyle, resize: 'vertical', minHeight: 80, fontFamily: 'inherit' }} />
      </div>

      {errorMsg && (
        <div style={{
          marginTop: 14, padding: '10px 14px',
          background: '#FEF2F2', border: '1px solid #FECACA',
          borderRadius: 8, fontSize: 13, color: '#B91C1C',
        }}>{errorMsg}</div>
      )}

      <PublicStepNav
        onBack={onBack}
        onNext={onSubmit}
        nextLabel={submitting ? 'Bekræfter…' : 'Bekræft booking'}
        nextDisabled={!canSubmit}
        accent={accent}
      />
    </div>
  );
};

const PublicBookingDone = ({ salon, contact }) => (
  <div style={publicPageWrap}>
    <div style={{ maxWidth: 480, margin: '0 auto' }}>
      <PublicSalonHeader salon={salon} />
      <div style={{ ...publicCardStyle, textAlign: 'center', padding: '32px 28px' }}>
        <div style={{
          width: 56, height: 56, margin: '0 auto 16px',
          background: '#F4F7F0', borderRadius: 14,
          display: 'flex', alignItems: 'center', justifyContent: 'center', color: '#3F5A30',
        }}>
          <IconCheck size={26} strokeWidth={2} />
        </div>
        <h2 style={{ fontFamily: 'Fraunces, serif', fontSize: 22, fontWeight: 500, margin: '0 0 10px' }}>
          Tak{contact.name ? `, ${contact.name.split(' ')[0]}` : ''} — din booking er bekræftet
        </h2>
        <p style={{ fontSize: 14, color: '#666', lineHeight: 1.6, margin: '0 0 14px' }}>
          Du modtager en bekræftelse på <strong>{contact.email}</strong> med detaljer og et link til at aflyse eller flytte, hvis det skulle blive nødvendigt.
        </p>
        <p style={{ fontSize: 13, color: '#888', lineHeight: 1.5, margin: 0 }}>
          Vi glæder os til at se dig.
        </p>
      </div>
      <div style={{ marginTop: 24, textAlign: 'center', fontSize: 11, color: '#aaa', letterSpacing: '0.04em' }}>
        SALONIQ · AF OONIQ
      </div>
    </div>
  </div>
);

const PublicStepNav = ({ onBack, onNext, nextLabel = 'Næste', nextDisabled, accent }) => (
  <div style={{ display: 'flex', gap: 10, marginTop: 22 }}>
    {onBack && (
      <button type="button" onClick={onBack} style={{
        padding: '12px 18px', background: '#fff', border: '1.5px solid #DDD9CE',
        borderRadius: 10, fontSize: 14, fontWeight: 600, cursor: 'pointer',
        fontFamily: 'inherit', color: '#666',
      }}>← Tilbage</button>
    )}
    <button type="button" onClick={onNext} disabled={nextDisabled} style={{
      flex: 1, padding: '12px 18px',
      background: nextDisabled ? '#D4D0C8' : accent, color: '#fff',
      border: 'none', borderRadius: 10, fontSize: 15, fontWeight: 600,
      cursor: nextDisabled ? 'not-allowed' : 'pointer', fontFamily: 'inherit',
    }}>{nextLabel}</button>
  </div>
);

const publicCardStyle = {
  background: '#fff', border: '1px solid #EFEDE5', borderRadius: 14,
  padding: '18px 18px',
};
const publicLabelStyle = {
  display: 'block', fontSize: 12, fontWeight: 600, color: '#555', marginBottom: 6,
};

// ─── Auth Gate ────────────────────────────────────────────────────────────────
// Wraps the entire app and controls who can see what based on subdomain + session.
// Salon-session key is scoped to the subdomain so hob.saloniq.dk != haircompany.saloniq.dk.
function AuthGate({ children }) {
  const subdomain = getSubdomain();
  const cancelSlug = getCancelSlugFromPath();
  const publicBookingSalonSlug = getPublicBookingSalon();
  const [auth, setAuth] = React.useState({ loading: true });
  const [salonState, setSalonState] = React.useState({ loading: true, data: null });

  // Subscribe to Firebase auth state
  React.useEffect(() => FB.onAuthChange(state => setAuth({ loading: false, ...state })), []);

  // Logout via window event
  React.useEffect(() => {
    const handler = () => FB.signOut();
    window.addEventListener('saloniq-logout', handler);
    return () => window.removeEventListener('saloniq-logout', handler);
  }, []);

  // Fetch salon for current subdomain (when applicable)
  React.useEffect(() => {
    if (!subdomain || subdomain === 'admin' || subdomain === '__dev__') {
      setSalonState({ loading: false, data: null });
      return;
    }
    let cancelled = false;
    FB.getSalonBySubdomain(subdomain).then(s => {
      if (!cancelled) setSalonState({ loading: false, data: s });
    }).catch(err => {
      console.error('Failed to load salon', err);
      if (!cancelled) setSalonState({ loading: false, data: null, error: err });
    });
    return () => { cancelled = true; };
  }, [subdomain]);

  // ── booking.saloniq.dk/{salon} — public booking, no login at all ─────────
  if (publicBookingSalonSlug) {
    return <PublicBookingPage salonSlug={publicBookingSalonSlug} />;
  }

  if (auth.loading) return <LoadingScreen />;

  // ── Admin subdomain ──────────────────────────────────────────────────────
  if (subdomain === 'admin') {
    if (!auth.user || !auth.isSuperAdmin) {
      return <SuperAdminLoginPage />;
    }
    return (
      <SuperAdminPanel
        currentUserEmail={auth.user.email}
        onLogout={() => FB.signOut()}
      />
    );
  }

  // ── Main domain / localhost — marketing only, never authenticates ────────
  if (subdomain === '__dev__' || subdomain === null) {
    window.__SALONIQ_SALON__ = null;
    return <MarketingLandingPage />;
  }

  // ── Salon subdomain ──────────────────────────────────────────────────────
  if (salonState.loading) return <LoadingScreen />;

  const salon = salonState.data;
  if (!salon) {
    return (
      <div style={{
        minHeight: '100vh', display: 'flex', alignItems: 'center', justifyContent: 'center',
        fontFamily: "'Manrope', sans-serif", background: '#FBFAF6',
      }}>
        <div style={{ textAlign: 'center', maxWidth: 400 }}>
          <h2 style={{ fontFamily: 'Fraunces, serif', fontWeight: 500, color: '#1a1a1a' }}>Salon ikke fundet</h2>
          <p style={{ color: '#888' }}><strong>{subdomain}</strong>.saloniq.dk er ikke registreret.</p>
        </div>
      </div>
    );
  }

  // Customer-facing cancel link — bypass login entirely. The customer gets
  // a public form regardless of whether they're signed in or not.
  if (cancelSlug) {
    return <CustomerCancelPublicPage salon={salon} slug={cancelSlug} />;
  }

  if (!salon.active) {
    return (
      <div style={{
        minHeight: '100vh', display: 'flex', alignItems: 'center', justifyContent: 'center',
        fontFamily: "'Manrope', sans-serif", background: '#FBFAF6',
      }}>
        <div style={{ textAlign: 'center' }}>
          <h2 style={{ fontFamily: 'Fraunces, serif', fontWeight: 500 }}>{salon.name}</h2>
          <p style={{ color: '#888' }}>Kontoen er midlertidigt suspenderet. Kontakt Saloniq support.</p>
        </div>
      </div>
    );
  }

  // Per-salon access check:
  //  - super-admin: full access to any salon
  //  - regular user: must have profile.salonId === salon.id
  const hasAccess = auth.user && (auth.isSuperAdmin || (auth.profile && auth.profile.salonId === salon.id));
  if (!hasAccess) {
    // Signed in as a different salon's user → show an explicit cross-salon
    // error rather than silently signing them out (which would leave them
    // confused on the login page wondering why they got logged out).
    if (auth.user && auth.profile && auth.profile.salonId !== salon.id) {
      return <WrongSalonScreen
        currentSalon={salon}
        userSalonId={auth.profile.salonId}
        userEmail={auth.user.email}
      />;
    }
    return <SalonLoginPage salon={salon} />;
  }

  // Expose for downstream components
  window.__SALONIQ_SALON__ = salon;
  window.__SALONIQ_USER__ = {
    username: auth.user.email,
    email: auth.user.email,
    role: auth.profile?.role || (auth.isSuperAdmin ? 'superadmin' : 'user'),
  };

  return <>{children}</>;
}

// ─── Wrong-salon screen ───────────────────────────────────────────────────────
// Shown when an authenticated user lands on a salon subdomain that doesn't
// match their account. Explains why they can't access this salon and offers
// to log out so they can sign in to the right one.
function WrongSalonScreen({ currentSalon, userSalonId, userEmail }) {
  const [loading, setLoading] = React.useState(false);

  return (
    <div style={{
      minHeight: '100vh', display: 'flex', alignItems: 'center', justifyContent: 'center',
      background: 'linear-gradient(145deg, #f5f3ee 0%, #ece8df 100%)',
      fontFamily: "'Manrope', sans-serif", padding: 24,
    }}>
      <div style={{
        width: '100%', maxWidth: 460, background: '#fff', borderRadius: 20,
        padding: '40px 36px', boxShadow: '0 8px 48px rgba(0,0,0,0.12)',
      }}>
        <div style={{
          width: 56, height: 56, margin: '0 auto 18px',
          background: '#FEF3C7', borderRadius: 14,
          display: 'flex', alignItems: 'center', justifyContent: 'center',
          color: '#92400E',
        }}>
          <svg width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
            <rect x="3" y="11" width="18" height="11" rx="2" ry="2"/>
            <path d="M7 11V7a5 5 0 0 1 10 0v4"/>
          </svg>
        </div>
        <h1 style={{
          fontFamily: 'Fraunces, serif', fontSize: 24, fontWeight: 500,
          margin: '0 0 10px', textAlign: 'center', lineHeight: 1.3,
        }}>Du er logget ind på en anden salon</h1>

        <p style={{ fontSize: 14, color: '#666', lineHeight: 1.6, margin: '0 0 22px', textAlign: 'center' }}>
          Kontoen <strong style={{ color: '#1a1a1a' }}>{userEmail}</strong> er knyttet til{' '}
          <strong style={{ color: '#1a1a1a' }}>{userSalonId}</strong>.
          <br/>Du kan ikke tilgå <strong style={{ color: '#1a1a1a' }}>{currentSalon.name}</strong> med denne konto.
        </p>

        <div style={{
          padding: '12px 14px', marginBottom: 22,
          background: '#FBFAF6', border: '1px solid #EFEDE5',
          borderRadius: 10, fontSize: 13, color: '#666', lineHeight: 1.6,
        }}>
          <strong>For at fortsætte:</strong>
          <ol style={{ margin: '8px 0 0', paddingLeft: 18 }}>
            <li>Log ud nedenfor</li>
            <li>Log ind igen med en {currentSalon.name}-konto</li>
            <li>Eller gå tilbage til <a href={'https://' + userSalonId + '.saloniq.dk'} style={{ color: '#3F4A3A' }}>{userSalonId}.saloniq.dk</a></li>
          </ol>
        </div>

        <div style={{ display: 'flex', gap: 10 }}>
          <button onClick={() => { window.location.href = 'https://' + userSalonId + '.saloniq.dk'; }} style={{
            flex: 1, padding: '12px', background: '#fff', color: '#3F4A3A',
            border: '1.5px solid #DDD9CE', borderRadius: 10, fontSize: 14, fontWeight: 600,
            cursor: 'pointer', fontFamily: 'inherit',
          }}>Til min salon</button>
          <button onClick={async () => {
            setLoading(true);
            await FB.signOut();
          }} disabled={loading} style={{
            flex: 1, padding: '12px',
            background: loading ? '#475569' : (currentSalon.color || '#3F4A3A'),
            color: '#fff', border: 'none', borderRadius: 10, fontSize: 14, fontWeight: 600,
            cursor: loading ? 'not-allowed' : 'pointer', fontFamily: 'inherit',
          }}>{loading ? 'Logger ud…' : 'Log ud'}</button>
        </div>
      </div>
    </div>
  );
}

Object.assign(window, { AuthGate });
