/* global React */
// FirstTakes app — screens. Each composes design-system primitives + chrome.

const FT = window.FirstTakesDesignSystem_adb0cc;
const { Button, IconButton, Avatar, Badge, Input, StreakPill, ChallengeCard, VerdictButton, RecordButton, Icon } = FT;

const PROMPT = "Show us your \u2018just woke up\u2019 face \u2014 messy hair, groggy, the real thing.";

const FRIENDS_TAKES = [
  { name: "Maya", streak: 12, ago: "4m", approve: 4, dispute: 0, comments: 2, late: false, contested: false, caption: "day one energy ⚡" },
  { name: "Theo", streak: 0, ago: "11m", approve: 2, dispute: 3, comments: 1, late: false, contested: true },
  { name: "Ivo", streak: 23, ago: "26m", approve: 5, dispute: 0, comments: 0, late: true, contested: false },
];

// ---- Sign in --------------------------------------------------------------
function SignInScreen({ onSignIn }) {
  return (
    <div style={{ display: "flex", flexDirection: "column", height: "100%", padding: "0 24px", boxSizing: "border-box" }}>
      <div style={{ flex: 1, display: "flex", flexDirection: "column", justifyContent: "center", gap: 8 }}>
        <div style={{ display: "flex", alignItems: "center", gap: 12, marginBottom: 6 }}>
          <img src="../../assets/brand/ft-monogram.svg" alt="FT" width={36} height={36} />
          <span style={{ fontFamily: "var(--font-display)", fontWeight: 700, fontSize: 34, letterSpacing: "-1.5px" }}>
            FirstTakes<span style={{ color: "var(--accent)" }}>.</span>
          </span>
        </div>
        <p style={{ font: "var(--text-body)", color: "var(--text-muted)", margin: "0 0 18px" }}>
          One shot. Your first take.
        </p>
        <Input placeholder="Email" type="email" defaultValue="you@firsttakes.app" />
        <Input placeholder="Password" type="password" defaultValue="\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022" style={{ marginTop: 10 }} />
        <Button variant="primary" fullWidth size="lg" style={{ marginTop: 16 }} onClick={onSignIn}>
          Log in
        </Button>
        <div style={{ display: "flex", alignItems: "center", gap: 12, margin: "18px 0" }}>
          <div style={{ flex: 1, height: 1, background: "var(--border)" }} />
          <span style={{ font: "var(--text-caption)", color: "var(--text-muted)" }}>or</span>
          <div style={{ flex: 1, height: 1, background: "var(--border)" }} />
        </div>
        <Button variant="secondary" fullWidth icon="apple" iconFill onClick={onSignIn}>
          Continue with Apple
        </Button>
        <Button variant="secondary" fullWidth style={{ marginTop: 10 }} onClick={onSignIn}>
          <img src="../../assets/icons/google_g.svg" width={18} height={18} alt="" style={{ marginRight: 8 }} />
          Continue with Google
        </Button>
      </div>
      <p style={{ font: "var(--text-micro)", color: "var(--text-muted)", textAlign: "center", marginBottom: 22 }}>
        New here? <span style={{ color: "var(--text)" }}>Create an account</span>
      </p>
    </div>
  );
}

// ---- Take card (feed) -----------------------------------------------------
// Mirrors the app's _TakeCard: 4:5 portrait media, the poster's streak pill
// next to their name, relative time, an optional caption under the media.
function TakeCard({ take, mine, mediaIndex }) {
  const [vote, setVote] = React.useState(null);
  const a = take.approve + (vote === "approve" ? 1 : 0);
  const d = take.dispute + (vote === "dispute" ? 1 : 0);
  return (
    <div style={{ background: "var(--surface)", borderRadius: "var(--radius-card)", padding: 10, marginBottom: 12 }}>
      <div style={{ display: "flex", alignItems: "center", gap: 10, marginBottom: 8 }}>
        <Avatar name={mine ? "You" : take.name} size={28} />
        <span style={{ font: "var(--text-body-strong)" }}>{mine ? "You" : take.name}</span>
        {take.streak > 0 && <StreakPill count={take.streak} />}
        <span style={{ flex: 1 }} />
        {take.ago && <span style={{ font: "var(--text-micro)", color: "var(--text-muted)" }}>{take.ago}</span>}
        {take.contested && <Badge tone="live">contested</Badge>}
        <IconButton icon="more_vert" size={20} color="var(--text)" label="More" />
      </div>
      <window.MediaTile aspect="4 / 5" mediaSlot={"feed:" + (mediaIndex || 0)}>
        {take.late && (
          <div style={{ position: "absolute", left: 8, bottom: 8 }}>
            <Badge tone="overlay">LATE</Badge>
          </div>
        )}
        <div style={{ position: "absolute", right: 8, bottom: 8, width: 28, height: 28, borderRadius: "50%", background: "rgba(0,0,0,0.45)", display: "flex", alignItems: "center", justifyContent: "center" }}>
          <Icon name="volume_off" size={16} color="#fff" />
        </div>
      </window.MediaTile>
      {take.caption && (
        <p style={{ font: "var(--text-caption)", color: "var(--text)", margin: "8px 2px 0" }}>{take.caption}</p>
      )}
      <div style={{ display: "flex", alignItems: "center", gap: 6, marginTop: 8 }}>
        <VerdictButton type="approve" count={a} active={vote === "approve"} onClick={() => setVote(vote === "approve" ? null : "approve")} />
        <VerdictButton type="dispute" count={d} active={vote === "dispute"} onClick={() => setVote(vote === "dispute" ? null : "dispute")} />
        <div style={{ flex: 1 }} />
        <button style={{ display: "inline-flex", alignItems: "center", gap: 6, background: "none", border: "none", cursor: "pointer", color: "var(--text-muted)", font: "var(--text-caption)", padding: "4px 8px" }}>
          <Icon name="mode_comment" size={18} color="currentColor" />
          {take.comments > 0 ? `Comment \u00b7 ${take.comments}` : "Comment"}
        </button>
      </div>
    </div>
  );
}

// ---- Feed / Today ---------------------------------------------------------
// Once posted, the app hides the challenge card behind a bolt "peek" toggle in
// the header; the marketing still keeps the card visible ("All done for today").
function FeedScreen({ posted, onRecord, onOpenChallenge }) {
  return (
    <div style={{ position: "relative", height: "100%", overflowY: "auto" }}>
      <window.AppHeader
        title="FirstTakes"
        streak={7}
        actions={posted ? <IconButton icon="bolt" iconFill size={22} color="var(--accent)" label="Today's take" /> : null}
      />
      <div style={{ position: "relative", padding: "8px 16px 110px" }}>
        <ChallengeCard prompt={(window.FTMedia && window.FTMedia.prompt) || PROMPT} remaining="47:12 left" posted={posted} onRecord={onRecord} onOpen={onOpenChallenge} />
        {posted ? (
          <div style={{ marginTop: 18 }}>
            <div className="ft-eyebrow" style={{ marginBottom: 10 }}>Friends' takes</div>
            {FRIENDS_TAKES.map((t, i) => (
              <TakeCard key={t.name} take={t} mediaIndex={i} />
            ))}
          </div>
        ) : (
          <div style={{ marginTop: 90, display: "flex", flexDirection: "column", alignItems: "center", textAlign: "center", padding: "0 24px" }}>
            <Icon name="lock" size={36} color="var(--text)" />
            <p style={{ font: "var(--text-body-strong)", margin: "12px 0 4px" }}>Post your take to unlock</p>
            <p style={{ font: "var(--text-caption)", color: "var(--text-muted)", margin: "0 0 16px" }}>
              See what your friends posted today
            </p>
            <Button variant="primary" onClick={onRecord}>Record yours</Button>
          </div>
        )}
      </div>
    </div>
  );
}

// ---- Record ---------------------------------------------------------------
function RecordScreen({ onClose, onPosted }) {
  const [recording, setRecording] = React.useState(false);
  const [progress, setProgress] = React.useState(0);
  const [done, setDone] = React.useState(false);
  const raf = React.useRef(null);

  const tick = React.useRef(null);
  const start = () => {
    if (recording) {
      setRecording(false);
      cancelAnimationFrame(raf.current);
      return;
    }
    setRecording(true);
    const t0 = performance.now() - progress * 5000;
    const loop = (now) => {
      const p = Math.min((now - t0) / 5000, 1);
      setProgress(p);
      if (p >= 1) {
        setRecording(false);
        setDone(true);
        return;
      }
      raf.current = requestAnimationFrame(loop);
    };
    raf.current = requestAnimationFrame(loop);
  };
  React.useEffect(() => () => cancelAnimationFrame(raf.current), []);

  const remaining = Math.ceil((1 - progress) * 5);

  // Matches the app's record screen: the camera preview is letterboxed to the
  // feed's 4:5 crop with solid black bars, the prompt sits at the very top over
  // the black bar, and the status pill / option pills row lives under the
  // segment bar. The rule-of-thirds grid draws only inside the 4:5 band.
  return (
    <div style={{ position: "absolute", inset: 0, background: "#000", zIndex: 40, display: "flex", flexDirection: "column" }}>
      {/* camera viewport (placeholder), black-barred to the 4:5 feed crop */}
      <div style={{ position: "absolute", left: 0, right: 0, top: "50%", transform: "translateY(-50%)", aspectRatio: "4 / 5", background: "radial-gradient(130% 100% at 50% 0%, #2c2c2c 0%, #141414 70%, #000 100%)" }}>
        {/* rule-of-thirds grid */}
        {[1, 2].map((n) => (
          <React.Fragment key={n}>
            <div style={{ position: "absolute", top: 0, bottom: 0, left: `${(n * 100) / 3}%`, width: 1, background: "rgba(255,255,255,0.22)" }} />
            <div style={{ position: "absolute", left: 0, right: 0, top: `${(n * 100) / 3}%`, height: 1, background: "rgba(255,255,255,0.22)" }} />
          </React.Fragment>
        ))}
      </div>
      <window.StatusBar />
      <div style={{ position: "relative", flex: 1, display: "flex", flexDirection: "column", padding: 20 }}>
        {/* challenge prompt \u2014 at the very top, over the black crop bar */}
        <div style={{ alignSelf: "stretch", background: "rgba(0,0,0,0.5)", border: "1px solid var(--border)", borderRadius: "var(--radius-field)", padding: "8px 12px" }}>
          <span style={{ font: "var(--text-caption)", color: "#fff" }}>{PROMPT}</span>
        </div>
        {/* segment / progress bar */}
        <div style={{ height: 4, borderRadius: 999, background: "rgba(255,255,255,0.24)", overflow: "hidden", marginTop: 12 }}>
          <div style={{ height: "100%", width: `${progress * 100}%`, background: "var(--accent)" }} />
        </div>
        <div style={{ display: "flex", justifyContent: "space-between", marginTop: 12 }}>
          <span style={{ display: "inline-flex", alignItems: "center", gap: 6, background: "rgba(0,0,0,0.5)", borderRadius: 999, padding: "6px 10px" }}>
            <Icon name="fiber_manual_record" size={10} fill color={recording ? "var(--live)" : "var(--text-muted)"} />
            <span className="ft-num" style={{ color: "#fff", fontSize: 13 }}>0:0{remaining}</span>
          </span>
          <div style={{ display: "flex", gap: 8 }}>
            {[["timer_off", "#fff"], ["flash_off", "#fff"], ["grid_3x3", "var(--accent)"]].map(([ic, color]) => (
              <span key={ic} style={{ display: "inline-flex", background: "rgba(0,0,0,0.5)", borderRadius: 999, padding: 8 }}>
                <Icon name={ic} size={18} color={color} />
              </span>
            ))}
          </div>
        </div>
        <div style={{ flex: 1 }} />
        {/* lens selector */}
        <div style={{ display: "flex", justifyContent: "center" }}>
          <div style={{ display: "flex", gap: 2, background: "rgba(0,0,0,0.4)", borderRadius: 999, padding: 4 }}>
            {["0.5\u00d7", "1\u00d7", "2\u00d7"].map((z, i) => (
              <span key={z} style={{ width: 36, height: 36, borderRadius: "50%", display: "flex", alignItems: "center", justifyContent: "center", background: i === 1 ? "#fff" : "transparent", color: i === 1 ? "#000" : "#fff", font: "500 11px/1 var(--font-ui)" }}>{z}</span>
            ))}
          </div>
        </div>
        {/* controls */}
        <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", marginTop: 16, marginBottom: 8 }}>
          <IconButton icon={done ? "restart_alt" : "close"} size={26} color="#fff" label="Close" onClick={done ? () => { setDone(false); setProgress(0); } : onClose} />
          <RecordButton recording={recording} progress={progress} onClick={start} />
          {done ? (
            <button onClick={onPosted} style={{ width: 52, height: 52, borderRadius: "50%", border: "none", background: "var(--accent)", display: "flex", alignItems: "center", justifyContent: "center", cursor: "pointer" }}>
              <Icon name="check" size={28} color="#000" />
            </button>
          ) : (
            <IconButton icon="cameraswitch" size={26} color="#fff" label="Flip" />
          )}
        </div>
      </div>
    </div>
  );
}

// ---- Friends --------------------------------------------------------------
function FriendsScreen() {
  const requests = [{ name: "Sora" }];
  const friends = [
    { name: "Maya", handle: "mayab" },
    { name: "Theo", handle: "theo.k" },
    { name: "Ivo", handle: "ivo" },
    { name: "Lena", handle: "lena_p" },
  ];
  const row = (p, trailing) => (
    <div key={p.name} style={{ display: "flex", alignItems: "center", gap: 12, padding: "8px 0" }}>
      <Avatar name={p.name} size={32} />
      <div style={{ flex: 1 }}>
        <div style={{ font: "var(--text-body-strong)" }}>{p.name}</div>
        {p.handle && <div style={{ font: "var(--text-micro)", color: "var(--text-muted)" }}>@{p.handle}</div>}
      </div>
      {trailing}
    </div>
  );
  return (
    <div style={{ height: "100%", overflowY: "auto" }}>
      <window.AppHeader title="Friends" />
      <div style={{ padding: "4px 20px 110px" }}>
        <Input placeholder="Search by handle" icon="search" />
        <div className="ft-eyebrow" style={{ margin: "18px 0 2px" }}>{"Requests \u00b7 1"}</div>
        {requests.map((p) => row(p, (
          <div style={{ display: "flex", alignItems: "center", gap: 4 }}>
            <Button variant="primary" size="sm">Accept</Button>
            <IconButton icon="close" size={20} color="var(--text-muted)" label="Decline" />
          </div>
        )))}
        <div className="ft-eyebrow" style={{ margin: "16px 0 2px" }}>Your friends</div>
        {friends.map((p) => row(p, (
          <IconButton icon="person_remove" size={20} color="var(--text-muted)" label="Remove" />
        )))}
      </div>
    </div>
  );
}

// ---- Profile --------------------------------------------------------------
// Mirrors the app's ProfileScreen: "Your roll" header (bell + settings), the
// identity block with a streak pill, three lifetime stat pills, the roll meta
// line, and the archive as a **roll of film** — one column of 4:5 frames
// between sprocket gutters, newest first, ending after 14 because that is the
// retention window (RETENTION_DAYS in the app).
//
// Frame media still comes from MediaTile / mediaSlot, so the photos picked in
// the Tweaks panel fill the frames exactly as they did in the old grid. Slots
// are reused modulo the six named archive slots so per-slot assignments stick.

// Palette that only exists inside the roll (AppRoll in lib/app/theme.dart).
// A stop below the app surfaces, so the strip reads as an object lying on the
// screen rather than a list of cards.
const ROLL = {
  well: "#0f0f0f",
  film: "#161616",
  hole: "#0A0A0A",
  frame: "#1c1c1c",
  unexposed: "#0c0c0c",
  line: "rgba(255,255,255,.05)",
  dash: "rgba(255,255,255,.10)",
  edge: "#6a6a6a",
  dead: "#3a3a3a",
  ring: "rgba(242,183,5,.55)",
  gutter: 48,
};

// The film edges: a base strip with a hole punched every 33px. The app paints
// these with a CustomPainter phased by the scroll offset so the rhythm never
// restarts; a repeating gradient gets the same continuous result here.
const sprockets = {
  width: ROLL.gutter,
  flexShrink: 0,
  background:
    "repeating-linear-gradient(180deg, " + ROLL.hole + " 0 15px, transparent 15px 33px) 16px 0 / 16px 100% no-repeat, " +
    ROLL.film,
};

function StatPill({ value, label }) {
  return (
    <div style={{ flex: 1, padding: "10px 0", textAlign: "center", background: "var(--surface-2)", borderRadius: "var(--radius-card)" }}>
      <div className="ft-num" style={{ fontSize: 18, fontWeight: 700, color: "var(--text)" }}>{value}</div>
      <div style={{ font: "var(--text-micro)", color: "var(--text-muted)", marginTop: 2 }}>{label}</div>
    </div>
  );
}

// One slot: gutters, the frame, then the date + prompt printed in the
// interframe band beneath it. The prompt shows on empty days too — seeing the
// question you didn't answer is the point of the gap.
function RollSlot({ frame }) {
  const today = frame.today;
  const missed = frame.state === "missed";
  return (
    <div style={{ display: "flex", alignItems: "stretch", borderBottom: "1px solid " + ROLL.line }}>
      <div style={sprockets} />
      <div style={{ flex: 1, padding: "12px 8px 14px" }}>
        {frame.state === "exposed" ? (
          <window.MediaTile
            radius={4}
            aspect="4 / 5"
            mediaSlot={"archive:" + frame.slot}
            style={today ? { boxShadow: "0 0 0 1.5px " + ROLL.ring } : undefined}
          >
            <span style={{ position: "absolute", top: 5, left: 6, font: "var(--text-micro)", fontFamily: "var(--font-mono)", color: "rgba(255,255,255,.5)" }}>
              {String(frame.n).padStart(2, "0")}
            </span>
            <Icon name="play_circle" size={30} fill color="rgba(255,255,255,.55)" />
            {frame.late && <div style={{ position: "absolute", top: 5, right: 6 }}><Badge tone="overlay">LATE</Badge></div>}
          </window.MediaTile>
        ) : (
          <div
            style={{
              position: "relative",
              width: "100%",
              aspectRatio: "4 / 5",
              borderRadius: 4,
              background: ROLL.unexposed,
              // Today wears a thin amber ring; a day nobody shot is dashed.
                // Only ever a day nobody shot — today is posted in this mockup,
              // so it renders as an exposed frame wearing the ring instead.
              border: "1px dashed " + ROLL.dash,
              display: "flex",
              flexDirection: "column",
              alignItems: "center",
              justifyContent: "center",
              gap: 8,
            }}
          >
            <Icon name="block" size={22} color={ROLL.dead} />
            <span style={{ fontFamily: "var(--font-mono)", fontSize: 9, letterSpacing: 1.4, color: ROLL.dead }}>
              UNEXPOSED
            </span>
          </div>
        )}
        <div style={{ display: "flex", alignItems: "center", gap: 8, marginTop: 6, height: 14 }}>
          <span style={{ fontFamily: "var(--font-mono)", fontSize: 9.5, color: ROLL.edge }}>{frame.date}</span>
          <span
            style={{
              flex: 1,
              minWidth: 0,
              fontFamily: "var(--font-mono)",
              fontSize: 9.5,
              color: missed ? ROLL.dead : "var(--accent)",
              whiteSpace: "nowrap",
              overflow: "hidden",
              textOverflow: "ellipsis",
            }}
          >
            {missed ? "no take \u2014 the day is gone" : frame.prompt}
          </span>
        </div>
      </div>
      <div style={sprockets} />
    </div>
  );
}

function ProfileScreen() {
  // Fourteen slots: today posted (ringed), a run behind it, one day missed, one
  // posted late. Only exposed frames consume a photo slot.
  const prompts = [
    "Show something in the wrong colour",
    "Your best news-anchor stare",
    "Find something older than your phone",
    "React to the worst sound you know",
    "Your face when the plan gets cancelled",
    "A hand gesture only you understand",
    "The nearest plant, real or fake",
    "Rate your mood 1 to 5 with your face",
    "Point at the most boring thing you see",
    "Show a gift someone gave you",
    "Your hardest concentrating face",
    "Find a straight line and follow it",
    "Show something in the wrong colour",
    "Your last screenshot, no context",
  ];
  let slot = 0;
  const frames = prompts.map((prompt, i) => {
    // Today is already posted, which is what the nav's check means too — an
    // unshot top frame next to a "posted" nav contradicts itself, and a store
    // slide should lead with the film, not an empty plate.
    const state = i === 3 ? "missed" : "exposed";
    return {
      n: 14 - i,
      date: "AUG " + String(17 - i).padStart(2, "0"),
      prompt,
      state,
      today: i === 0,
      late: i === 4,
      slot: state === "exposed" ? slot++ % 6 : null,
    };
  });
  const exposed = frames.filter((f) => f.state === "exposed").length;

  return (
    <div style={{ height: "100%", overflowY: "auto" }}>
      {/* Pinned in the app, where it collapses to avatar + name as the film
          scrolls. Sticky here so the mockup hints at the same behaviour. */}
      <div style={{ position: "sticky", top: 0, zIndex: 2, background: "var(--bg)" }}>
        <window.AppHeader
          title="Your roll"
          actions={
            <React.Fragment>
              <span style={{ position: "relative", display: "inline-flex" }}>
                <IconButton icon="notifications" size={22} color="var(--text-muted)" label="Notifications" />
                <span style={{ position: "absolute", right: 0, top: 2, minWidth: 16, boxSizing: "border-box", padding: "1px 5px", borderRadius: 999, background: "var(--accent)", border: "1.5px solid var(--bg)", color: "var(--on-accent)", font: "700 10px/1.2 var(--font-ui)", textAlign: "center" }}>2</span>
              </span>
              <IconButton icon="settings" size={22} color="var(--text-muted)" label="Settings" />
            </React.Fragment>
          }
        />
      </div>

      <div style={{ padding: "4px 20px 0", display: "flex", flexDirection: "column", alignItems: "center" }}>
        <Avatar name="Briek" size={60} />
        <div style={{ fontFamily: "var(--font-display)", fontSize: 17, fontWeight: 700, color: "var(--text)", marginTop: 8 }}>Briek</div>
        {/* The streak is the live number, so it keeps the flame and the only
            amber up here; the lifetime totals sit below as plain numerals. */}
        <div style={{ display: "flex", alignItems: "center", gap: 8, marginTop: 6 }}>
          <span style={{ font: "var(--text-caption)", color: "var(--text-muted)" }}>@briek</span>
          <StreakPill count={7} size="large" />
        </div>
        <div style={{ display: "flex", gap: 6, width: "100%", marginTop: 14 }}>
          <StatPill value={128} label="thumbs up" />
          <StatPill value={19} label="longest run" />
          <StatPill value={96} label="takes ever" />
        </div>
        <div style={{ display: "flex", alignItems: "center", width: "100%", gap: 8, margin: "12px 0 8px" }}>
          <span style={{ flex: 1, font: "600 10px/1.2 var(--font-ui)", letterSpacing: 1.4, color: "var(--text-muted)" }}>
            ROLL 17 &middot; {exposed} OF 14 FRAMES
          </span>
          <span style={{ fontFamily: "var(--font-mono)", fontSize: 9.5, color: "var(--text-muted)" }}>AUG 04 ROLLS OFF IN 13H</span>
        </div>
      </div>

      {/* The roll itself. Ends after 14 frames and says so — there is nothing
          older to page to, which is the whole point of the surface. */}
      <div style={{ background: ROLL.well, borderTop: "1px solid var(--border)", borderBottom: "1px solid var(--border)" }}>
        {frames.map((f) => <RollSlot key={f.date} frame={f} />)}
        <div style={{ display: "flex", alignItems: "stretch" }}>
          <div style={sprockets} />
          <div style={{ flex: 1, padding: "16px 8px 32px" }}>
            <div style={{ padding: "12px 0", textAlign: "center", borderRadius: 10, background: "rgba(242,183,5,.10)", border: "1px solid rgba(242,183,5,.30)", fontFamily: "var(--font-mono)", fontSize: 9.5, letterSpacing: 1.2, color: "var(--accent)" }}>
              END OF ROLL &middot; 14 DAYS, THEN GONE
            </div>
          </div>
          <div style={sprockets} />
        </div>
      </div>
      <div style={{ height: 150 }} />
    </div>
  );
}


// ---- Prompt board ---------------------------------------------------------
// The daily prompt as a split-flap departure board, shown as a sheet over the
// feed — this is the challenge popout, not a screen you navigate to.
//
// Geometry is lifted from AppBoard in lib/app/theme.dart: 14 columns, a 44px
// label gutter on every row, flaps butted at 2px. Blank slots are *rendered*,
// not omitted; that is what makes it read as a mechanism with a fixed number
// of positions rather than a row of word tiles.
const BOARD = {
  panel: "#0d0d0d",
  label: "#3f3f3f",
  caption: "#5a5a5a",
  // A flap is two faces meeting at a near-black hinge. Hard stops, never a
  // soft blend — a smooth gradient here reads as a plastic tile.
  filled: "linear-gradient(180deg,#242424 0 48%,#050505 48% 52%,#191919 52% 100%)",
  blank: "linear-gradient(180deg,#161616 0 48%,#070707 48% 52%,#121212 52% 100%)",
  inner: "inset 0 0 0 .5px rgba(255,255,255,.05)",
  columns: 14,
  gutter: 44,
  gap: 2,
};

function Flap({ glyph, color }) {
  const blank = !glyph || glyph === " ";
  return (
    <span
      style={{
        flex: 1,
        height: 30,
        borderRadius: 2,
        background: blank ? BOARD.blank : BOARD.filled,
        boxShadow: BOARD.inner,
        display: "flex",
        alignItems: "center",
        justifyContent: "center",
        fontFamily: "var(--font-display)",
        fontWeight: 700,
        fontSize: 14,
        lineHeight: 1,
        color: color || "var(--text)",
      }}
    >
      {blank ? "" : glyph}
    </span>
  );
}

// One row: the label in its gutter, then exactly BOARD.columns flaps. The text
// is padded out so trailing positions are blank flaps rather than empty space.
function BoardRow({ label, glyphs, color }) {
  const cells = (glyphs || "").padEnd(BOARD.columns).slice(0, BOARD.columns).split("");
  return (
    <div style={{ display: "flex", alignItems: "center", gap: 8, marginBottom: 3 }}>
      <span style={{ width: BOARD.gutter, flex: "none", fontFamily: "var(--font-mono)", fontSize: 8.5, fontWeight: 500, letterSpacing: 1.2, color: BOARD.label }}>
        {label}
      </span>
      <span style={{ flex: 1, display: "flex", gap: BOARD.gap }}>
        {cells.map((c, i) => <Flap key={i} glyph={c} color={color} />)}
      </span>
    </div>
  );
}

function BoardStrip({ gutter, left, right, size = 8.5 }) {
  const st = { fontFamily: "var(--font-mono)", fontSize: size, fontWeight: 500, letterSpacing: 1.2, color: BOARD.label };
  return (
    <div style={{ display: "flex", alignItems: "center", gap: 8 }}>
      {/* "NO. 229" is a hair wider than the 44px gutter once tracking counts;
          let it run into the gap rather than wrap onto a second line. */}
      <span style={{ width: BOARD.gutter, flex: "none", whiteSpace: "nowrap", ...st }}>{gutter}</span>
      <span style={{ flex: 1, ...st }}>{left}</span>
      {right && <span style={st}>{right}</span>}
    </div>
  );
}

function PromptBoardScreen() {
  // Wrapped exactly as wrapPrompt does: greedy, on word boundaries, 14 columns
  // over at most 4 rows. Rows the prompt doesn't fill stay as blank flaps.
  const promptRows = ["SHOW SOMETHING", "IN THE WRONG", "COLOUR", ""];
  return (
    <div style={{ position: "relative", height: "100%", overflow: "hidden" }}>
      {/* The feed it opens over, dimmed — the board is a popout, not a page. */}
      <div style={{ position: "absolute", inset: 0 }}>
        <FeedScreen posted={false} onRecord={() => {}} onOpenChallenge={() => {}} />
      </div>
      <div style={{ position: "absolute", inset: 0, background: "var(--scrim)" }} />

      <div style={{ position: "absolute", left: 0, right: 0, bottom: 0, background: "var(--bg)", borderRadius: "var(--radius-sheet) var(--radius-sheet) 0 0", paddingBottom: 20 }}>
        {/* The sheet's own dismiss affordance, which is why the board carries
            no close button of its own. */}
        <div style={{ display: "flex", justifyContent: "center", padding: "12px 0 4px" }}>
          <span style={{ width: 36, height: 4, borderRadius: 999, background: "var(--surface-2)" }} />
        </div>

        <div style={{ height: 48, display: "flex", alignItems: "center", padding: "0 20px" }}>
          <span style={{ fontFamily: "var(--font-display)", fontWeight: 700, fontSize: 17, color: "var(--text)" }}>
            FirstTakes<span style={{ color: "var(--accent)" }}>.</span>
          </span>
          <span style={{ flex: 1 }} />
          <span style={{ width: 6, height: 6, borderRadius: 999, background: "var(--live)", marginRight: 6 }} />
          <span style={{ font: "600 9.5px/1 var(--font-ui)", letterSpacing: 1.5, color: "var(--text-muted)" }}>BOARD UPDATED</span>
        </div>

        <div style={{ margin: "0 16px", padding: 12, background: BOARD.panel, borderRadius: "var(--radius-overlay)", border: "1px solid var(--border)", boxShadow: "var(--shadow-floating)" }}>
          <BoardStrip gutter="NO. 229" left="TODAY'S TAKE" right={"0:05 \u00b7 ONE SHOT"} />
          <div style={{ height: 8 }} />
          {promptRows.map((r, i) => (
            <BoardRow key={i} label={i === 0 ? "PROMPT" : ""} glyphs={r} />
          ))}
          {/* Amber lives in the countdown row and the wordmark's period. */}
          <BoardRow label="CLOSES" glyphs="41:08" color="var(--accent)" />
          <BoardRow label="STATUS" glyphs="SEALED" />
          <div style={{ height: 12 }} />
          <div style={{ height: 1, background: "var(--border)" }} />
          <div style={{ height: 8 }} />
          <BoardStrip gutter="" left="SAME BOARD FOR ALL 6 FRIENDS" size={9} />
        </div>

        <div style={{ padding: "20px 20px 0", font: "var(--text-caption)", fontSize: 12.5, lineHeight: 1.45, color: "var(--text-muted)" }}>
          Everyone&rsquo;s clock started on the same flip. Five seconds, one continuous take, no retakes.
        </div>

        <div style={{ padding: "24px 20px 0" }}>
          <button type="button" style={{ width: "100%", height: 54, border: 0, borderRadius: 999, background: "var(--text)", color: "var(--bg)", font: "600 16px/1 var(--font-ui)", display: "inline-flex", alignItems: "center", justifyContent: "center", gap: 8, cursor: "default" }}>
            <Icon name="videocam" size={20} fill color="var(--bg)" />
            One shot. Go.
          </button>
          <div style={{ marginTop: 12, textAlign: "center", font: "11px/1.4 var(--font-ui)", color: BOARD.caption }}>
            Five seconds, recorded in one go. No retakes, no edits.
          </div>
        </div>
      </div>
    </div>
  );
}

Object.assign(window, { SignInScreen, FeedScreen, RecordScreen, FriendsScreen, ProfileScreen, PromptBoardScreen, TakeCard });
