// cms-skin-daylight.jsx
// ─────────────────────────────────────────────────────────────────────────
// A SECOND skin: "Daylight Editorial".
//
// This file proves the platform's core promise — the same content document
// renders through an entirely different presentation with zero data changes.
// It honours the identical component contract as cms-skin.jsx:
//     ({ content, theme, colors })  for each of the nine module types,
// reading the very same content fields (content.headline, content.projects[],
// content.team[], …). Only the *look* differs.
//
// Aesthetic: the deliberate opposite of "Editorial Noir". Where Noir is dark,
// cinematic and kinetic (condensed grotesk + monospace, film grain, full-bleed
// video, amber-on-black), Daylight is a bright print-monograph — warm paper,
// ink type, a high-contrast literary serif (Newsreader) paired with a clean
// grotesk (Spline Sans), hairline rules, big index numerals, and media shown
// as framed plates with captions beneath. Same accent colour, same data.
//
// Registered via CMS.defineSkin("daylight", …) at the foot of the file, so the
// admin's Skin selector lists it automatically. Load AFTER cms-skin.jsx.
// ─────────────────────────────────────────────────────────────────────────

const { useState, useEffect, useRef } = React;

// ── Palette + type tokens (the skin's own identity) ────────────────
const PAPER   = "#F6F1E7";   // warm off-white
const PAPER2  = "#ECE5D7";   // deeper warm panel
const INK     = "#262017";   // warm near-black
const INK_70  = "rgba(38,32,23,0.70)";
const INK_55  = "rgba(38,32,23,0.55)";
const INK_40  = "rgba(38,32,23,0.42)";
const HAIR    = "rgba(38,32,23,0.16)";
const HAIR_SOFT = "rgba(38,32,23,0.09)";
const SERIF = "'Newsreader', Georgia, 'Times New Roman', serif";
const SANS  = "'Spline Sans', system-ui, -apple-system, sans-serif";

// Accent tint helper — color-mix on the (hex) accent; modern browsers support it.
const tint = (accent, pct) => `color-mix(in oklab, ${accent} ${pct}%, transparent)`;
const onAccentInk = "#231E16"; // dark text that sits on an accent block

// ── Shared text helpers (re-implemented for this skin's scope) ─────
// Emphasise *asterisk-wrapped* spans — same authoring convention as Noir, so
// the exact same content lights up here, just in this skin's serif italic.
function dlAccented(text, accent) {
  const parts = String(text == null ? "" : text).split(/(\*[^*\n]+\*)/g);
  return parts.map((chunk, i) =>
    /^\*[^*\n]+\*$/.test(chunk)
      ? <em key={i} style={{ color: accent, fontStyle: "italic", fontWeight: 500 }}>{chunk.slice(1, -1)}</em>
      : <React.Fragment key={i}>{chunk}</React.Fragment>
  );
}
function dlLines(text) {
  const lines = String(text == null ? "" : text).split("\n");
  return lines.map((ln, i) => (
    <React.Fragment key={i}>{ln}{i < lines.length - 1 ? <br /> : null}</React.Fragment>
  ));
}
function dlInitials(name) {
  return String(name || "").trim().split(/\s+/).map((w) => w[0]).slice(0, 2).join("").toUpperCase() || "?";
}
function dlFocal(obj) {
  const o = (obj && typeof obj === "object") ? obj : {};
  return `${(typeof o.focalX === "number" ? o.focalX : 0.5) * 100}% ${(typeof o.focalY === "number" ? o.focalY : 0.5) * 100}%`;
}
function dlNum(i) { return String(i + 1).padStart(2, "0"); }

// ── Responsive hook ────────────────────────────────────────────────
function useDlViewport() {
  const get = () => (typeof window !== "undefined" ? window.innerWidth : 1280);
  const [w, setW] = useState(get);
  useEffect(() => {
    let raf = 0;
    const onResize = () => { cancelAnimationFrame(raf); raf = requestAnimationFrame(() => setW(get())); };
    window.addEventListener("resize", onResize);
    return () => { window.removeEventListener("resize", onResize); cancelAnimationFrame(raf); };
  }, []);
  return { w, mobile: w <= 820, narrow: w <= 560 };
}
const dlPad = (narrow) => (narrow ? "84px 22px" : "132px 64px");

// A small uppercase tracked label (the daylight equivalent of Noir's mono eyebrow).
function DlKicker({ children, color, style }) {
  if (!String(children || "").trim()) return null;
  return (
    <span style={{ fontFamily: SANS, fontSize: 12, fontWeight: 600, letterSpacing: "0.22em", textTransform: "uppercase", color: color || INK_40, ...style }}>
      {children}
    </span>
  );
}

// A thin rule with an accent tick at the left — recurring section divider.
function DlRule({ accent, style }) {
  return (
    <div style={{ display: "flex", alignItems: "center", gap: 0, ...style }}>
      <span style={{ width: 28, height: 2, background: accent }} />
      <span style={{ flex: 1, height: 1, background: HAIR }} />
    </div>
  );
}

// ── Wordmark (ink) with the trailing dot in accent ─────────────────
// Reuses the brand path; layers an accent-filled copy clipped to just the dot.
function DlWordmark({ height = 30, accent }) {
  const VB_W = 161.26669, VB_H = 32.844387;
  const aspect = VB_W / VB_H;
  const CLIP_TOP = 98.25, CLIP_BOT = 94.2;
  const draw = (fill, clip) => (
    <svg viewBox={`0 0 ${VB_W} ${VB_H}`} style={{ position: "absolute", inset: 0, width: "100%", height: "100%", display: "block", clipPath: clip }}>
      <g transform="translate(-18.146622,-121.99224)">
        <path d={window.FG_WORDMARK_PATH} fill={fill} fillRule="evenodd" />
      </g>
    </svg>
  );
  return (
    <div style={{ position: "relative", height, width: height * aspect, flexShrink: 0 }}>
      {draw(INK, "none")}
      {draw(accent, `polygon(${CLIP_TOP}% 0%, 110% 0%, 110% 100%, ${CLIP_BOT}% 100%)`)}
    </div>
  );
}

// ── Body background guard ──────────────────────────────────────────
// The global <body> is dark (Noir's default). Whenever this skin is mounted,
// paint the page paper so overscroll / gaps never flash dark; restore on swap.
function useDlPaperBody() {
  useEffect(() => {
    const b = document.body.style;
    const prevBg = b.background, prevColor = b.color;
    b.background = PAPER; b.color = INK;
    return () => { b.background = prevBg; b.color = prevColor; };
  }, []);
}

// ── Nav ─────────────────────────────────────────────────────────────
function Nav({ content, theme, colors }) {
  const [scrolled, setScrolled] = useState(false);
  const { narrow } = useDlViewport();
  useDlPaperBody();
  useEffect(() => {
    const h = () => setScrolled(window.scrollY > 60);
    window.addEventListener("scroll", h, { passive: true });
    return () => window.removeEventListener("scroll", h);
  }, []);
  return (
    <nav style={{
      position: "fixed", top: "var(--fg-nav-top, 0px)", left: 0, right: "var(--fg-dock-right, 0px)", zIndex: 100,
      display: "flex", alignItems: "center", justifyContent: "space-between",
      padding: narrow ? "0 22px" : "0 64px", height: narrow ? 64 : 78,
      background: scrolled ? tint(PAPER, 100) : "transparent",
      backgroundColor: scrolled ? PAPER : "transparent",
      borderBottom: scrolled ? `1px solid ${HAIR}` : "1px solid transparent",
      transition: "background-color 0.4s, border-color 0.4s",
    }}>
      <DlWordmark height={narrow ? 24 : 28} accent={colors.accent} />
      {!narrow && (
        <div style={{ display: "flex", gap: 38, alignItems: "center" }}>
          {(content.links || []).map((l) => (
            <a key={l} href={`#${l.toLowerCase()}`} style={{
              fontFamily: SANS, fontSize: 12.5, fontWeight: 500, color: INK_70, textDecoration: "none",
              letterSpacing: "0.14em", textTransform: "uppercase", paddingBottom: 3,
              borderBottom: "1px solid transparent", transition: "color 0.2s, border-color 0.2s",
            }}
            onMouseEnter={(e) => { e.currentTarget.style.color = INK; e.currentTarget.style.borderColor = colors.accent; }}
            onMouseLeave={(e) => { e.currentTarget.style.color = INK_70; e.currentTarget.style.borderColor = "transparent"; }}
            >{l}</a>
          ))}
        </div>
      )}
    </nav>
  );
}

// ── Hero ────────────────────────────────────────────────────────────
// Editorial split: oversized serif headline on paper (left), a framed media
// "plate" (right) holding the showreel — contained, not full-bleed.
function Hero({ content, theme, colors }) {
  const [visible, setVisible] = useState(false);
  const { mobile, narrow } = useDlViewport();
  useEffect(() => { const t = setTimeout(() => setVisible(true), 100); return () => clearTimeout(t); }, []);
  const hw = Math.max(300, Math.min(640, theme.headlineWeight || 460));
  const hasVideo = !!(content.videoUrl && String(content.videoUrl).trim());

  const ease = "opacity 1s ease, transform 1s cubic-bezier(0.16,1,0.3,1)";
  const rise = (d) => ({ opacity: visible ? 1 : 0, transform: visible ? "none" : "translateY(22px)", transition: ease, transitionDelay: `${d}ms` });

  return (
    <section style={{
      minHeight: "100vh", boxSizing: "border-box", background: PAPER,
      padding: narrow ? "108px 22px 64px" : "132px 64px 72px",
      display: "grid", gridTemplateColumns: mobile ? "1fr" : "1.05fr 0.95fr",
      gap: mobile ? 44 : "clamp(40px, 6vw, 96px)", alignItems: "center",
    }}>
      {/* Left — type */}
      <div>
        <div style={{ display: "flex", alignItems: "center", gap: 14, marginBottom: 30, ...rise(40) }}>
          <span style={{ width: 8, height: 8, borderRadius: "50%", background: colors.accent }} />
          <DlKicker color={INK_55}>{content.eyebrow}</DlKicker>
        </div>
        <h1 style={{
          fontFamily: SERIF, fontWeight: hw, fontSize: "clamp(44px, 6vw, 92px)",
          lineHeight: 1.08, letterSpacing: "-0.015em", color: INK, textWrap: "balance",
          marginBottom: 52, ...rise(140),
        }}>
          {dlAccented(content.headline, colors.accent)}
        </h1>
        <div style={{ display: "flex", gap: 14, alignItems: "center", flexWrap: "wrap", ...rise(260) }}>
          {(content.primaryCta || "").trim() ? (
          <a href="#work" style={{
            display: "inline-flex", alignItems: "center", gap: 10, padding: "15px 30px",
            background: colors.accent, color: onAccentInk, textDecoration: "none",
            fontFamily: SANS, fontWeight: 600, fontSize: 13.5, letterSpacing: "0.1em", textTransform: "uppercase",
            transition: "transform 0.2s, opacity 0.2s",
          }}
          onMouseEnter={(e) => { e.currentTarget.style.transform = "translateY(-2px)"; e.currentTarget.style.opacity = "0.9"; }}
          onMouseLeave={(e) => { e.currentTarget.style.transform = "none"; e.currentTarget.style.opacity = "1"; }}
          >{content.primaryCta}</a>
          ) : null}
          {(content.secondaryCta || "").trim() ? (
          <a href="#about" style={{
            display: "inline-flex", alignItems: "center", gap: 8, padding: "15px 30px",
            border: `1px solid ${HAIR}`, color: INK_70, textDecoration: "none",
            fontFamily: SANS, fontWeight: 500, fontSize: 13.5, letterSpacing: "0.1em", textTransform: "uppercase",
            transition: "border-color 0.2s, color 0.2s",
          }}
          onMouseEnter={(e) => { e.currentTarget.style.borderColor = colors.accent; e.currentTarget.style.color = INK; }}
          onMouseLeave={(e) => { e.currentTarget.style.borderColor = HAIR; e.currentTarget.style.color = INK_70; }}
          >{content.secondaryCta}</a>
          ) : null}
        </div>
      </div>

      {/* Right — framed media plate */}
      <div style={{ ...rise(200) }}>
        <div style={{ display: "flex", alignItems: "baseline", justifyContent: "space-between", marginBottom: 12 }}>
          <DlKicker color={INK_40}>( 01 ) Showreel</DlKicker>
          <DlKicker color={INK_40}>{new Date().getFullYear()}</DlKicker>
        </div>
        <div style={{
          position: "relative", aspectRatio: "4 / 3", border: `1px solid ${HAIR}`, background: PAPER2,
          overflow: "hidden", boxShadow: "0 30px 70px -40px rgba(38,32,23,0.5)",
        }}>
          {hasVideo ? (
            <video key={content.videoUrl} autoPlay muted loop playsInline preload="auto" src={content.videoUrl}
              onError={(e) => { e.currentTarget.style.display = "none"; }}
              style={{ position: "absolute", inset: 0, width: "100%", height: "100%", objectFit: "cover" }} />
          ) : (
            <>
              <div style={{ position: "absolute", inset: 0, background: `radial-gradient(120% 120% at 30% 20%, ${tint(colors.accent, 22)} 0%, transparent 60%)` }} />
              <svg width="100%" height="100%" style={{ position: "absolute", inset: 0 }}>
                <defs>
                  <pattern id="dlHeroBed" width="26" height="26" patternUnits="userSpaceOnUse" patternTransform="rotate(26)">
                    <line x1="0" y1="0" x2="0" y2="26" stroke={HAIR_SOFT} strokeWidth="1" />
                  </pattern>
                </defs>
                <rect width="100%" height="100%" fill="url(#dlHeroBed)" />
              </svg>
              <div style={{ position: "absolute", inset: 0, display: "flex", alignItems: "center", justifyContent: "center", color: tint(colors.accent, 70) }}>
                <svg width="64" height="64" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.3" strokeLinecap="round" strokeLinejoin="round">
                  <circle cx="12" cy="12" r="9" /><path d="M10 8l6 4-6 4z" />
                </svg>
              </div>
            </>
          )}
        </div>
        <div style={{ display: "flex", alignItems: "center", gap: 10, marginTop: 12 }}>
          <span style={{ width: 5, height: 5, borderRadius: "50%", background: colors.accent }} />
          <span style={{ fontFamily: SANS, fontSize: 12, color: INK_40, letterSpacing: "0.04em" }}>Selected motion work, 2024–{String(new Date().getFullYear()).slice(2)}</span>
        </div>
      </div>
    </section>
  );
}

// ── Ticker ──────────────────────────────────────────────────────────
function Ticker({ content, colors }) {
  const items = content.items || [];
  const repeated = [...items, ...items, ...items];
  return (
    <div style={{ borderTop: `1px solid ${HAIR}`, borderBottom: `1px solid ${HAIR}`, padding: "20px 0", overflow: "hidden", background: PAPER }}>
      <style>{`@keyframes dlTicker { from { transform: translateX(0) } to { transform: translateX(-33.33%) } }`}</style>
      <div style={{ display: "flex", gap: 44, whiteSpace: "nowrap", animation: "dlTicker 26s linear infinite", width: "max-content" }}>
        {repeated.map((item, i) => (
          <span key={i} style={{ display: "inline-flex", alignItems: "center", gap: 44 }}>
            <span style={{ fontFamily: SERIF, fontStyle: "italic", fontSize: 19, fontWeight: 400, color: INK_70 }}>{item}</span>
            <span style={{ width: 5, height: 5, transform: "rotate(45deg)", background: colors.accent, display: "inline-block", flexShrink: 0 }} />
          </span>
        ))}
      </div>
    </div>
  );
}

// ── Project lightbox — paper chrome, dark media stage ──────────────
function DlLightbox({ project, colors, onClose }) {
  const hasVideo = !!(project.video && String(project.video).trim());
  const coverUrl = ((project.cover && project.cover.url) || "").trim();
  const focal = dlFocal(project.cover);
  const details = Array.isArray(project.details) ? project.details.filter((d) => d && (d.item || d.value)) : [];
  const gallery = Array.isArray(project.gallery) ? project.gallery.filter((g) => g && (g.url || "").trim()) : [];

  const slides = [];
  if (hasVideo) slides.push({ type: "video", url: project.video, poster: coverUrl });
  gallery.forEach((g) => slides.push(g.type === "video"
    ? { type: "video", url: g.url, caption: g.caption || "" }
    : { type: "image", url: g.url, caption: g.caption || "" }));
  const count = slides.length;

  const [idx, setIdx] = useState(0);
  const clamp = (n) => Math.max(0, Math.min(count - 1, n));
  const go = (n) => setIdx((c) => clamp(typeof n === "function" ? n(c) : n));
  const videoRefs = useRef({});
  const drag = useRef(null);

  useEffect(() => {
    const onKey = (e) => {
      if (e.key === "Escape") onClose();
      else if (e.key === "ArrowRight") go((c) => c + 1);
      else if (e.key === "ArrowLeft") go((c) => c - 1);
    };
    window.addEventListener("keydown", onKey);
    const prev = document.body.style.overflow; document.body.style.overflow = "hidden";
    return () => { window.removeEventListener("keydown", onKey); document.body.style.overflow = prev; };
  }, [onClose, count]);

  useEffect(() => {
    Object.entries(videoRefs.current).forEach(([k, v]) => { if (v && Number(k) !== idx) { try { v.pause(); } catch (e) {} } });
  }, [idx]);

  const onDown = (e) => { drag.current = { x: e.clientX, moved: 0 }; };
  const onMove = (e) => { if (drag.current) drag.current.moved = e.clientX - drag.current.x; };
  const onUp = () => { const d = drag.current; drag.current = null; if (!d) return; if (d.moved < -50) go((c) => c + 1); else if (d.moved > 50) go((c) => c - 1); };
  const noGrab = (e) => e.preventDefault();

  const arrow = (side, disabled) => ({
    position: "absolute", top: "50%", [side]: 12, transform: "translateY(-50%)",
    width: 44, height: 44, borderRadius: "50%", zIndex: 3,
    display: count > 1 ? "flex" : "none", alignItems: "center", justifyContent: "center",
    border: `1px solid rgba(246,241,231,0.5)`, background: "rgba(246,241,231,0.88)",
    color: INK, fontSize: 22, lineHeight: 1, cursor: disabled ? "default" : "pointer",
    opacity: disabled ? 0.3 : 1, transition: "opacity 0.2s",
  });

  return (
    <div onClick={onClose} style={{
      position: "fixed", inset: 0, zIndex: 1000, display: "flex", flexDirection: "column",
      alignItems: "center", justifyContent: "center", padding: "clamp(16px, 5vw, 56px)", gap: 16,
      background: "rgba(246,241,231,0.82)", backdropFilter: "blur(16px)", WebkitBackdropFilter: "blur(16px)",
      animation: "dlFade 0.25s ease",
    }}>
      <style>{`@keyframes dlFade { from { opacity: 0 } to { opacity: 1 } }`}</style>

      <div style={{ width: "min(1080px, 100%)", display: "flex", alignItems: "flex-end", justifyContent: "space-between", gap: 16 }}>
        <div>
          <div style={{ fontFamily: SERIF, fontSize: "clamp(24px,3vw,38px)", fontWeight: 500, letterSpacing: "-0.01em", color: INK, lineHeight: 1.05 }}>{project.title}</div>
          <div style={{ fontFamily: SANS, fontSize: 12.5, letterSpacing: "0.04em", color: INK_55, marginTop: 5 }}>
            {[project.type, project.client, project.year].filter(Boolean).join("  ·  ")}
          </div>
        </div>
        <button onClick={onClose} aria-label="Close" style={{
          flexShrink: 0, width: 42, height: 42, borderRadius: "50%", border: `1px solid ${HAIR}`,
          background: "transparent", color: INK_70, fontSize: 17, cursor: "pointer",
          display: "flex", alignItems: "center", justifyContent: "center", transition: "border-color 0.2s, color 0.2s",
        }}
        onMouseEnter={(e) => { e.currentTarget.style.borderColor = colors.accent; e.currentTarget.style.color = INK; }}
        onMouseLeave={(e) => { e.currentTarget.style.borderColor = HAIR; e.currentTarget.style.color = INK_70; }}
        >✕</button>
      </div>

      <div onClick={(e) => e.stopPropagation()} style={{ width: "min(1080px, 100%)", display: "flex", flexDirection: "column", gap: 16, paddingBottom: "clamp(12px, 5vh, 48px)" }}>
        <div onPointerDown={onDown} onPointerMove={onMove} onPointerUp={onUp} onPointerCancel={onUp} onContextMenu={noGrab}
          style={{ aspectRatio: "16 / 9", background: "#1B1813", overflow: "hidden", position: "relative",
            border: `1px solid ${HAIR}`, boxShadow: "0 40px 100px -50px rgba(38,32,23,0.7)", touchAction: "pan-y", userSelect: "none" }}>
          {count === 0 ? (
            coverUrl ? <img src={coverUrl} alt={project.title} draggable={false} onContextMenu={noGrab} style={{ width: "100%", height: "100%", objectFit: "cover", objectPosition: focal }} />
              : <div style={{ position: "absolute", inset: 0, display: "flex", alignItems: "center", justifyContent: "center", fontFamily: SANS, fontSize: 12, letterSpacing: "0.1em", textTransform: "uppercase", color: tint(PAPER, 40) }}>No media yet</div>
          ) : (
            <div style={{ display: "flex", height: "100%", width: "100%", transform: `translateX(-${idx * 100}%)`, transition: "transform 0.45s cubic-bezier(0.16,1,0.3,1)" }}>
              {slides.map((s, i) => (
                <div key={i} style={{ flex: "0 0 100%", height: "100%", display: "flex", alignItems: "center", justifyContent: "center", background: "#1B1813" }}>
                  {s.type === "video" ? (
                    <video ref={(el) => { videoRefs.current[i] = el; }} src={s.url} poster={s.poster || undefined}
                      controls autoPlay={i === 0} playsInline controlsList="nodownload noremoteplayback" disablePictureInPicture onContextMenu={noGrab}
                      style={{ width: "100%", height: "100%", objectFit: "contain", background: "#000" }} />
                  ) : (
                    <img src={s.url} alt={s.caption || project.title} draggable={false} onContextMenu={noGrab}
                      style={{ maxWidth: "100%", maxHeight: "100%", objectFit: "contain", userSelect: "none", pointerEvents: "none" }} />
                  )}
                </div>
              ))}
            </div>
          )}
          <button onClick={() => go((c) => c - 1)} disabled={idx === 0} aria-label="Previous" style={arrow("left", idx === 0)}>‹</button>
          <button onClick={() => go((c) => c + 1)} disabled={idx === count - 1} aria-label="Next" style={arrow("right", idx === count - 1)}>›</button>
          {count > 1 && (
            <div style={{ position: "absolute", bottom: 12, right: 14, zIndex: 3, fontFamily: SANS, fontSize: 11, letterSpacing: "0.08em",
              color: INK, background: "rgba(246,241,231,0.88)", padding: "4px 9px", borderRadius: 999 }}>{idx + 1} / {count}</div>
          )}
        </div>

        {count > 0 && (
          <div style={{ minHeight: 20, textAlign: "center", fontFamily: SERIF, fontStyle: "italic", fontSize: 16, color: INK_55, textWrap: "balance" }}>
            {slides[idx] && slides[idx].type === "image" ? slides[idx].caption : ""}
          </div>
        )}

        {count > 1 && (
          <div style={{ display: "flex", gap: 8, justifyContent: "center", flexWrap: "wrap" }}>
            {slides.map((s, i) => {
              const thumb = s.type === "image" ? s.url : s.poster;
              return (
                <button key={i} onClick={() => go(i)} aria-label={`View ${i + 1}`} style={{
                  width: 66, height: 42, overflow: "hidden", padding: 0, cursor: "pointer", position: "relative",
                  border: `2px solid ${i === idx ? colors.accent : HAIR}`, background: PAPER2, opacity: i === idx ? 1 : 0.6, transition: "opacity 0.2s, border-color 0.2s",
                }}>
                  {thumb ? <img src={thumb} alt="" draggable={false} style={{ width: "100%", height: "100%", objectFit: "cover" }} /> : null}
                  {s.type === "video" && <span style={{ position: "absolute", inset: 0, display: "flex", alignItems: "center", justifyContent: "center", color: "#fff", fontSize: 12, textShadow: "0 1px 3px rgba(0,0,0,0.6)" }}>▶</span>}
                </button>
              );
            })}
          </div>
        )}

        {details.length > 0 && (
          <div style={{ display: "grid", gridTemplateColumns: "auto 1fr", columnGap: 26, rowGap: 10, width: "100%", maxWidth: 720, marginTop: 4 }}>
            {details.map((d, i) => (
              <React.Fragment key={i}>
                <div style={{ fontFamily: SANS, fontSize: 11, fontWeight: 600, letterSpacing: "0.12em", textTransform: "uppercase", color: INK_40, paddingTop: 3, whiteSpace: "nowrap" }}>{d.item}</div>
                <div style={{ fontFamily: SERIF, fontSize: 16, lineHeight: 1.5, color: INK }}>{d.value}</div>
              </React.Fragment>
            ))}
          </div>
        )}
      </div>
    </div>
  );
}

// ── Work — editorial plate grid, captions beneath ─────────────────
function parseRatio(str) {
  const m = String(str || "3:2").split(/[:/]/).map(Number);
  const n = (m[0] && m[1]) ? m[0] / m[1] : 1.5;
  return n > 0 ? n : 1.5;
}

function WorkPlate({ project, index, colors, onOpen }) {
  const [hovered, setHovered] = useState(false);
  const [failed, setFailed] = useState(false);
  const coverUrl = ((project.cover && project.cover.url) || "").trim();
  const showCover = !!coverUrl && !failed;
  const focal = dlFocal(project.cover);
  const hasVideo = !!(project.video && String(project.video).trim());
  const gallery = Array.isArray(project.gallery) ? project.gallery.filter((g) => g && (g.url || "").trim()) : [];
  const details = Array.isArray(project.details) ? project.details.filter((d) => d && (d.item || d.value)) : [];
  const openable = hasVideo || gallery.length > 0 || details.length > 0;
  const open = () => { if (openable) onOpen(project); };

  return (
    <div
      onMouseEnter={() => setHovered(true)} onMouseLeave={() => setHovered(false)}
      onClick={open} role={openable ? "button" : undefined} tabIndex={openable ? 0 : undefined}
      onKeyDown={(e) => { if (openable && (e.key === "Enter" || e.key === " ")) { e.preventDefault(); open(); } }}
      aria-label={openable ? `View ${project.title}` : undefined}
      style={{ cursor: openable ? "pointer" : "default" }}
    >
      <div style={{
        position: "relative", aspectRatio: "var(--dl-ratio, 1.5)", overflow: "hidden",
        border: `1px solid ${hovered ? tint(colors.accent, 70) : HAIR}`, background: PAPER2, transition: "border-color 0.3s",
      }}>
        {showCover ? (
          <img src={coverUrl} alt={project.title} onError={() => setFailed(true)}
            style={{ position: "absolute", inset: 0, width: "100%", height: "100%", objectFit: "cover", objectPosition: focal,
              transform: hovered ? "scale(1.04)" : "scale(1)", transition: "transform 0.7s cubic-bezier(0.16,1,0.3,1)" }} />
        ) : (
          <>
            <svg width="100%" height="100%" style={{ position: "absolute", inset: 0 }}>
              <defs>
                <pattern id={`dlw${index}`} width="22" height="22" patternUnits="userSpaceOnUse" patternTransform="rotate(28)">
                  <line x1="0" y1="0" x2="0" y2="22" stroke={HAIR_SOFT} strokeWidth="1" />
                </pattern>
              </defs>
              <rect width="100%" height="100%" fill={`url(#dlw${index})`} />
            </svg>
            <div style={{ position: "absolute", inset: 0, display: "flex", alignItems: "center", justifyContent: "center",
              fontFamily: SANS, fontSize: 11, letterSpacing: "0.14em", textTransform: "uppercase", color: INK_40, textAlign: "center" }}>
              {String(project.type || "")}<br />add cover image
            </div>
          </>
        )}
      </div>
      {/* caption beneath, plate style */}
      <div style={{ display: "flex", alignItems: "baseline", gap: 14, marginTop: 16 }}>
        <span style={{ fontFamily: SANS, fontSize: 12, fontWeight: 600, color: tint(colors.accent, 95), letterSpacing: "0.04em", lineHeight: 1.4 }}>{dlNum(index)}</span>
        <div style={{ flex: 1, minWidth: 0 }}>
          <div style={{ display: "flex", alignItems: "baseline", justifyContent: "space-between", gap: 12 }}>
            <span style={{ fontFamily: SERIF, fontSize: "clamp(20px,2vw,26px)", fontWeight: 500, color: INK, letterSpacing: "-0.01em",
              borderBottom: `1px solid ${hovered ? colors.accent : "transparent"}`, transition: "border-color 0.3s", paddingBottom: 1 }}>{project.title}</span>
            <span style={{ fontFamily: SANS, fontSize: 12, color: INK_40, whiteSpace: "nowrap" }}>{project.year}</span>
          </div>
          <div style={{ fontFamily: SANS, fontSize: 13, color: INK_55, marginTop: 4 }}>
            {[project.type, project.client].filter(Boolean).join("  ·  ")}
          </div>
        </div>
      </div>
    </div>
  );
}

function Work({ content, theme, colors }) {
  const [active, setActive] = useState(null);
  const { narrow, mobile } = useDlViewport();
  const ratio = parseRatio(theme && theme.coverRatio);
  const projects = content.projects || [];
  const minCol = mobile ? "100%" : "min(100%, 340px)";
  return (
    <section id="work" style={{ padding: dlPad(narrow), background: PAPER, "--dl-ratio": String(ratio) }}>
      <div style={{ marginBottom: 56 }}>
        <DlKicker color={tint(colors.accent, 95)}>{content.eyebrow}</DlKicker>
        <h2 style={{ fontFamily: SERIF, fontSize: "clamp(38px,5vw,68px)", fontWeight: 460, letterSpacing: "-0.02em", lineHeight: 1.02, color: INK, marginTop: 14 }}>{content.heading}</h2>
        <DlRule accent={colors.accent} style={{ marginTop: 28 }} />
      </div>
      <div style={{ display: "grid", gridTemplateColumns: `repeat(auto-fit, minmax(${minCol}, 1fr))`, gap: narrow ? "40px 20px" : "56px 40px" }}>
        {projects.map((p, i) => <WorkPlate key={i} project={p} index={i} colors={colors} onOpen={setActive} />)}
      </div>
      {active && <DlLightbox project={active} colors={colors} onClose={() => setActive(null)} />}
    </section>
  );
}

// ── About + Team ────────────────────────────────────────────────────
function DlProfileCard({ member, colors, onClose }) {
  const url = ((member.headshot && member.headshot.url) || "").trim();
  const focal = dlFocal(member.headshot);
  const facts = Array.isArray(member.stats) ? member.stats.filter((s) => s && (s.item || s.value)) : [];
  useEffect(() => {
    const onKey = (e) => { if (e.key === "Escape") onClose(); };
    window.addEventListener("keydown", onKey);
    const prev = document.body.style.overflow; document.body.style.overflow = "hidden";
    return () => { window.removeEventListener("keydown", onKey); document.body.style.overflow = prev; };
  }, [onClose]);
  return (
    <div onClick={onClose} style={{
      position: "fixed", inset: 0, zIndex: 1100, display: "flex", alignItems: "center", justifyContent: "center",
      padding: "clamp(16px, 5vw, 48px)", background: "rgba(246,241,231,0.82)", backdropFilter: "blur(16px)", WebkitBackdropFilter: "blur(16px)", animation: "dlFade 0.25s ease",
    }}>
      <style>{`@keyframes dlFade { from { opacity: 0 } to { opacity: 1 } }`}</style>
      <div onClick={(e) => e.stopPropagation()} style={{
        width: "min(680px, 100%)", display: "flex", flexWrap: "wrap", background: PAPER,
        border: `1px solid ${HAIR}`, overflow: "hidden", position: "relative", boxShadow: "0 50px 120px -50px rgba(38,32,23,0.6)",
      }}>
        <button onClick={onClose} aria-label="Close" style={{
          position: "absolute", top: 14, right: 14, zIndex: 2, width: 36, height: 36, borderRadius: "50%",
          border: `1px solid ${HAIR}`, background: "rgba(246,241,231,0.7)", color: INK_70, fontSize: 15, cursor: "pointer",
          display: "flex", alignItems: "center", justifyContent: "center",
        }}>✕</button>
        <div style={{ flex: "1 1 220px", minWidth: 200, aspectRatio: "3 / 4", background: PAPER2, position: "relative" }}>
          {url ? <img src={url} alt={member.name} style={{ width: "100%", height: "100%", objectFit: "cover", objectPosition: focal }} />
            : <div style={{ position: "absolute", inset: 0, display: "flex", alignItems: "center", justifyContent: "center", fontFamily: SERIF, fontWeight: 500, fontSize: 64, color: INK_40 }}>{dlInitials(member.name)}</div>}
        </div>
        <div style={{ flex: "1 1 300px", minWidth: 260, padding: "36px 32px" }}>
          <div style={{ fontFamily: SERIF, fontWeight: 500, fontSize: "clamp(28px,3.4vw,38px)", letterSpacing: "-0.01em", color: INK, lineHeight: 1.04 }}>{member.name}</div>
          {member.title && <div style={{ fontFamily: SANS, fontSize: 12, fontWeight: 600, letterSpacing: "0.12em", textTransform: "uppercase", color: tint(colors.accent, 95), marginTop: 8 }}>{member.title}</div>}
          {member.bio && <p style={{ fontFamily: SANS, fontSize: 14.5, fontWeight: 300, lineHeight: 1.7, color: INK_70, marginTop: 18, textWrap: "pretty" }}>{member.bio}</p>}
          {facts.length > 0 && (
            <div style={{ marginTop: 24, borderTop: `1px solid ${HAIR}`, paddingTop: 18, display: "grid", gridTemplateColumns: "auto 1fr", columnGap: 18, rowGap: 10 }}>
              {facts.map((f, i) => (
                <React.Fragment key={i}>
                  <div style={{ fontFamily: SANS, fontSize: 10.5, fontWeight: 600, letterSpacing: "0.1em", textTransform: "uppercase", color: INK_40, paddingTop: 2, whiteSpace: "nowrap" }}>{f.item}</div>
                  <div style={{ fontFamily: SERIF, fontSize: 15, color: INK }}>{f.value}</div>
                </React.Fragment>
              ))}
            </div>
          )}
        </div>
      </div>
    </div>
  );
}

function DlTeamMember({ member, colors, onOpen }) {
  const [hovered, setHovered] = useState(false);
  const url = ((member.headshot && member.headshot.url) || "").trim();
  const focal = dlFocal(member.headshot);
  return (
    <button
      onClick={onOpen} onMouseEnter={() => setHovered(true)} onMouseLeave={() => setHovered(false)}
      aria-label={`${member.name} — see profile`}
      style={{ appearance: "none", border: 0, background: "transparent", padding: 0, cursor: "pointer", textAlign: "left", width: "clamp(140px, 18vw, 184px)" }}
    >
      <div style={{
        position: "relative", aspectRatio: "3 / 4", overflow: "hidden", background: PAPER2,
        border: `1px solid ${hovered ? tint(colors.accent, 70) : HAIR}`, transition: "border-color 0.3s, transform 0.3s",
        transform: hovered ? "translateY(-4px)" : "none",
      }}>
        {url ? <img src={url} alt={member.name} style={{ width: "100%", height: "100%", objectFit: "cover", objectPosition: focal,
            transform: hovered ? "scale(1.04)" : "scale(1)", transition: "transform 0.6s cubic-bezier(0.16,1,0.3,1)" }} />
          : <div style={{ position: "absolute", inset: 0, display: "flex", alignItems: "center", justifyContent: "center", fontFamily: SERIF, fontWeight: 500, fontSize: 40, color: INK_40 }}>{dlInitials(member.name)}</div>}
      </div>
      <div style={{ marginTop: 14 }}>
        <div style={{ fontFamily: SERIF, fontSize: 20, fontWeight: 500, color: INK, letterSpacing: "-0.01em",
          borderBottom: `1px solid ${hovered ? colors.accent : "transparent"}`, display: "inline-block", transition: "border-color 0.3s", paddingBottom: 1 }}>{member.name}</div>
        {member.title && <div style={{ fontFamily: SANS, fontSize: 11.5, fontWeight: 600, letterSpacing: "0.1em", textTransform: "uppercase", color: INK_40, marginTop: 5 }}>{member.title}</div>}
      </div>
    </button>
  );
}

function About({ content, colors }) {
  const [profile, setProfile] = useState(null);
  const { narrow } = useDlViewport();
  const team = Array.isArray(content.team) ? content.team.filter((m) => m && (m.name || (m.headshot && m.headshot.url))) : [];
  const stats = Array.isArray(content.stats) ? content.stats : [];
  return (
    <section id="about" style={{ padding: dlPad(narrow), background: PAPER2, borderTop: `1px solid ${HAIR}` }}>
      <div style={{ maxWidth: 1180, margin: "0 auto" }}>
        <DlKicker color={tint(colors.accent, 95)}>{content.eyebrow}</DlKicker>
        <div style={{ display: "grid", gridTemplateColumns: narrow ? "1fr" : "1.25fr 0.75fr", gap: narrow ? 32 : "clamp(40px,6vw,96px)", marginTop: 24, alignItems: "start" }}>
          <p style={{ fontFamily: SERIF, fontWeight: 360, fontSize: "clamp(28px,3.6vw,48px)", lineHeight: 1.18, letterSpacing: "-0.01em", color: INK, textWrap: "pretty" }}>
            {dlAccented(content.lead, colors.accent)}
          </p>
          <p style={{ fontFamily: SANS, fontWeight: 300, fontSize: 16, lineHeight: 1.8, color: INK_70, textWrap: "pretty", paddingTop: 8 }}>
            {content.body}
          </p>
        </div>

        {team.length > 0 && (
          <div style={{ marginTop: 80 }}>
            <DlRule accent={colors.accent} style={{ marginBottom: 28 }} />
            <DlKicker color={INK_40} style={{ display: "block", marginBottom: 28 }}>The team</DlKicker>
            <div style={{ display: "flex", flexWrap: "wrap", gap: "clamp(22px, 3vw, 44px)" }}>
              {team.map((m, i) => <DlTeamMember key={i} member={m} colors={colors} onOpen={() => setProfile(m)} />)}
            </div>
          </div>
        )}

        {stats.length > 0 && (
          <div style={{ marginTop: 80, display: "flex", flexWrap: "wrap", gap: 0, borderTop: `1px solid ${HAIR}` }}>
            {stats.map((s, i) => (
              <div key={i} style={{ flex: "1 1 180px", padding: "30px 0", borderRight: i < stats.length - 1 ? `1px solid ${HAIR}` : "none", paddingRight: 24, marginRight: 24 }}>
                <div style={{ fontFamily: SERIF, fontSize: "clamp(40px,5vw,60px)", fontWeight: 360, lineHeight: 1, color: colors.accent }}>{s.num}</div>
                <div style={{ fontFamily: SANS, fontSize: 13, color: INK_55, marginTop: 10, letterSpacing: "0.02em" }}>{s.label}</div>
              </div>
            ))}
          </div>
        )}
      </div>
      {profile && <DlProfileCard member={profile} colors={colors} onClose={() => setProfile(null)} />}
    </section>
  );
}

// ── Services — numbered editorial index ────────────────────────────
const DL_SVC_ICONS = {
  film:      <g><rect x="2" y="3" width="20" height="18" rx="2" /><path d="M7 3v18M17 3v18M2 8h5M2 16h5M17 8h5M17 16h5M7 12h10" /></g>,
  camera:    <g><path d="M2 7a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v10a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2z" /><path d="M15 10l5-3v10l-5-3" /></g>,
  clapper:   <g><path d="M3 8h18v11a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1z" /><path d="M3 8l1.5-3.5 4 1.2 1-2.4 4 1.2 1-2.4 4 1.2L20 4" /></g>,
  megaphone: <g><path d="M3 11v2a1 1 0 0 0 1 1h2l9 5V5L6 10H4a1 1 0 0 0-1 1z" /><path d="M18 8a4 4 0 0 1 0 8" /></g>,
  scissors:  <g><circle cx="6" cy="6" r="3" /><circle cx="6" cy="18" r="3" /><path d="M8.1 8.1L20 18M8.1 15.9L20 6" /></g>,
  sparkle:   <g><path d="M12 3l2 6 6 2-6 2-2 6-2-6-6-2 6-2z" /></g>,
  globe:     <g><circle cx="12" cy="12" r="9" /><path d="M3 12h18M12 3c2.5 2.5 2.5 15 0 18M12 3c-2.5 2.5-2.5 15 0 18" /></g>,
  play:      <g><circle cx="12" cy="12" r="9" /><path d="M10 8l6 4-6 4z" /></g>,
};
function DlSvcIcon({ name, size = 22 }) {
  const g = DL_SVC_ICONS[name] || DL_SVC_ICONS.film;
  return <svg viewBox="0 0 24 24" width={size} height={size} fill="none" stroke="currentColor" strokeWidth="1.4" strokeLinecap="round" strokeLinejoin="round" style={{ display: "block" }}>{g}</svg>;
}

function DlServiceRow({ item, index, colors, last }) {
  const [hovered, setHovered] = useState(false);
  const { mobile } = useDlViewport();
  const imgUrl = ((item.image && item.image.url) || "").trim();
  return (
    <div
      onMouseEnter={() => setHovered(true)} onMouseLeave={() => setHovered(false)}
      style={{
        display: "grid", gridTemplateColumns: mobile ? "auto 1fr" : "auto auto 1fr auto", gap: mobile ? "4px 18px" : "0 36px",
        alignItems: "start", padding: mobile ? "28px 0" : "38px 0", borderBottom: last ? "none" : `1px solid ${HAIR}`,
        paddingLeft: hovered ? 12 : 0, transition: "padding-left 0.35s cubic-bezier(0.16,1,0.3,1)",
      }}
    >
      <span style={{ fontFamily: SERIF, fontSize: mobile ? 18 : 22, fontWeight: 400, color: INK_40, lineHeight: 1.2, fontVariantNumeric: "tabular-nums" }}>{dlNum(index)}</span>
      <span style={{ color: hovered ? colors.accent : INK_55, transition: "color 0.3s", paddingTop: 2, display: mobile ? "none" : "block" }}><DlSvcIcon name={item.icon} size={24} /></span>
      <div>
        <div style={{ fontFamily: SERIF, fontSize: "clamp(24px,2.6vw,34px)", fontWeight: 460, letterSpacing: "-0.01em", color: INK, lineHeight: 1.06,
          display: "inline-block", borderBottom: `1px solid ${hovered ? colors.accent : "transparent"}`, transition: "border-color 0.3s", paddingBottom: 2 }}>{item.label}</div>
        <p style={{ fontFamily: SANS, fontSize: 15, fontWeight: 300, lineHeight: 1.65, color: INK_55, marginTop: 12, maxWidth: 560, textWrap: "pretty" }}>{item.desc}</p>
      </div>
      {!mobile && (
        <div style={{ width: 132, aspectRatio: "4 / 3", overflow: "hidden", border: `1px solid ${HAIR}`, background: PAPER2, position: "relative", flexShrink: 0 }}>
          {imgUrl ? <img src={imgUrl} alt={item.label} style={{ width: "100%", height: "100%", objectFit: "cover", objectPosition: dlFocal(item.image) }} />
            : <div style={{ position: "absolute", inset: 0, display: "flex", alignItems: "center", justifyContent: "center", color: tint(colors.accent, 55) }}><DlSvcIcon name={item.icon} size={30} /></div>}
        </div>
      )}
    </div>
  );
}

function Services({ content, colors }) {
  const items = content.items || [];
  const { narrow } = useDlViewport();
  return (
    <section style={{ padding: dlPad(narrow), background: PAPER, borderTop: `1px solid ${HAIR}` }}>
      <div style={{ maxWidth: 1180, margin: "0 auto" }}>
        <DlKicker color={tint(colors.accent, 95)}>{content.eyebrow}</DlKicker>
        <DlRule accent={colors.accent} style={{ marginTop: 20, marginBottom: 8 }} />
        <div>
          {items.map((item, i) => <DlServiceRow key={i} item={item} index={i} colors={colors} last={i === items.length - 1} />)}
        </div>
      </div>
    </section>
  );
}

// ── Values — numbered principles ───────────────────────────────────
function DlValueRow({ value, colors, last }) {
  const [hovered, setHovered] = useState(false);
  const { mobile } = useDlViewport();
  return (
    <div
      onMouseEnter={() => setHovered(true)} onMouseLeave={() => setHovered(false)}
      style={{
        display: "grid", gridTemplateColumns: mobile ? "1fr" : "auto minmax(0,0.85fr) minmax(0,1.15fr)",
        gap: mobile ? 14 : "clamp(28px,5vw,72px)", alignItems: "start", padding: mobile ? "34px 0" : "50px 0",
        borderBottom: last ? "none" : `1px solid ${HAIR}`, paddingLeft: hovered ? 12 : 0, transition: "padding-left 0.35s cubic-bezier(0.16,1,0.3,1)",
      }}
    >
      <span style={{ fontFamily: SERIF, fontSize: "clamp(34px,4vw,56px)", fontWeight: 360, color: tint(colors.accent, 92), lineHeight: 0.9, fontVariantNumeric: "tabular-nums" }}>{value.index}</span>
      <div>
        <DlKicker color={INK_40} style={{ display: "block", marginBottom: 12 }}>{value.label}</DlKicker>
        <h3 style={{ fontFamily: SERIF, fontWeight: 460, fontSize: "clamp(24px,2.8vw,38px)", lineHeight: 1.08, letterSpacing: "-0.01em", color: INK, textWrap: "balance" }}>{value.title}</h3>
      </div>
      <p style={{ fontFamily: SANS, fontSize: 16, fontWeight: 300, lineHeight: 1.78, color: INK_70, maxWidth: 540, textWrap: "pretty", paddingTop: mobile ? 0 : 6 }}>{value.body}</p>
    </div>
  );
}

function Values({ content, colors }) {
  const items = content.items || [];
  const { narrow } = useDlViewport();
  return (
    <section id="values" style={{ padding: dlPad(narrow), background: PAPER2, borderTop: `1px solid ${HAIR}` }}>
      <div style={{ maxWidth: 1180, margin: "0 auto" }}>
        <DlKicker color={tint(colors.accent, 95)}>{content.eyebrow}</DlKicker>
        <h2 style={{ fontFamily: SERIF, fontSize: "clamp(38px,5vw,68px)", fontWeight: 460, letterSpacing: "-0.02em", lineHeight: 1.02, color: INK, marginTop: 14 }}>{content.heading}</h2>
        <DlRule accent={colors.accent} style={{ marginTop: 28 }} />
        <div>
          {items.map((v, i) => <DlValueRow key={i} value={v} colors={colors} last={i === items.length - 1} />)}
        </div>
      </div>
    </section>
  );
}

// ── Contact ─────────────────────────────────────────────────────────
function DlObfuscatedEmail({ email, colors, narrow }) {
  const safe = String(email || "");
  const at = safe.indexOf("@");
  const dom = at >= 0 ? safe.slice(at + 1) : "";
  const dot = dom.lastIndexOf(".");
  const user = at >= 0 ? safe.slice(0, at) : safe;
  const host = dot >= 0 ? dom.slice(0, dot) : dom;
  const tld = dot >= 0 ? dom.slice(dot + 1) : "";
  const reveal = (e) => { const a = e.currentTarget; if (!a.getAttribute("href")) a.setAttribute("href", "mailto:" + safe); };
  return (
    <a tabIndex={0} role="link" aria-label="Email us"
      onMouseEnter={(e) => { reveal(e); e.currentTarget.style.transform = "translateY(-2px)"; e.currentTarget.style.opacity = "0.9"; }}
      onMouseLeave={(e) => { e.currentTarget.style.transform = "none"; e.currentTarget.style.opacity = "1"; }}
      onFocus={reveal} onTouchStart={reveal} onKeyDown={(e) => { if (e.key === "Enter") reveal(e); }}
      style={{
        display: "inline-block", padding: narrow ? "16px 34px" : "18px 46px", background: colors.accent, color: onAccentInk,
        fontFamily: SANS, fontWeight: 600, fontSize: 16, letterSpacing: "0.04em", textDecoration: "none",
        transition: "transform 0.2s, opacity 0.2s", cursor: "pointer",
      }}>
      <span>{user}</span><span className="fg-at" aria-hidden="true"></span><span>{host}</span><span className="fg-dot" aria-hidden="true"></span><span>{tld}</span>
    </a>
  );
}

function Contact({ content, colors }) {
  const { narrow } = useDlViewport();
  return (
    <section id="contact" style={{ padding: dlPad(narrow), background: PAPER, borderTop: `1px solid ${HAIR}`, textAlign: "center" }}>
      <div style={{ maxWidth: 880, margin: "0 auto" }}>
        <div style={{ display: "flex", alignItems: "center", justifyContent: "center", gap: 12, marginBottom: 30 }}>
          <span style={{ width: 7, height: 7, borderRadius: "50%", background: colors.accent }} />
          <DlKicker color={INK_55}>{content.eyebrow}</DlKicker>
        </div>
        <h2 style={{ fontFamily: SERIF, fontSize: "clamp(46px,7vw,96px)", fontWeight: 380, letterSpacing: "-0.02em", lineHeight: 0.98, color: INK, marginBottom: 36, textWrap: "balance" }}>
          {dlLines(content.heading)}
        </h2>
        <p style={{ fontFamily: SANS, fontSize: 17, fontWeight: 300, color: INK_55, marginBottom: 48, lineHeight: 1.65 }}>
          {dlLines(content.body)}
        </p>
        <DlObfuscatedEmail email={content.email} colors={colors} narrow={narrow} />
      </div>
    </section>
  );
}

// ── Footer ──────────────────────────────────────────────────────────
function Footer({ content, colors }) {
  const year = new Date().getFullYear();
  const { narrow } = useDlViewport();
  return (
    <footer style={{
      padding: narrow ? "28px 22px" : "36px 64px", borderTop: `1px solid ${HAIR}`, background: PAPER,
      display: "flex", alignItems: "center", justifyContent: "space-between", gap: 16, flexWrap: "wrap",
    }}>
      <DlWordmark height={22} accent={colors.accent} />
      <span style={{ fontFamily: SANS, fontSize: 12, color: INK_40, letterSpacing: "0.04em" }}>© {year} {content.name || "flairground"}</span>
    </footer>
  );
}

// ── Register the skin ───────────────────────────────────────────────
window.CMS.defineSkin("daylight", {
  label: "Daylight Editorial",
  components: { nav: Nav, hero: Hero, ticker: Ticker, work: Work, about: About, services: Services, values: Values, contact: Contact, footer: Footer },
});
