// Mosaic site — STORY page (direction S1, de-boxed, framings pushed up)
// Exports: StoryPage

const Measure = ({ children, w = 720, style }) => (
  <div style={{ maxWidth: w, margin: "0 auto", ...style }}>{children}</div>
);

const RecordGroup = ({ story, group, idx, mode, open, onToggle }) => {
  const f = story.framings[group.f];
  const c = framingColor(f, group.f, mode);
  return (
    <div className="recgroup">
      <button className="ghead" onClick={onToggle}>
        <span style={{ width: 10, height: 10, borderRadius: 3, background: c, display: "inline-block", flexShrink: 0 }}></span>
        <span className="gtitle">{f.t}</span>
        <span className="micro">{group.items.length} item{group.items.length > 1 ? "s" : ""}</span>
        <span className="micro" style={{ fontSize: 14 }}>{open ? "−" : "+"}</span>
      </button>
      {open && group.items.map((it, i) => (
        <div className="recitem" key={i}>
          <span className="d">{it.d}</span>
          <span className="s"><SFav id={it.s} size={16} />{FAVS[it.s].n}</span>
          <span className="h">{it.h}</span>
        </div>
      ))}
    </div>
  );
};

const StoryPage = ({ id, mode, onBack, onOpenStory }) => {
  const story = SITE_STORIES.find((s) => s.id === id) || SITE_STORIES[0];
  const idx = SITE_STORIES.indexOf(story);
  const next = SITE_STORIES[(idx + 1) % SITE_STORIES.length];
  const allSrcs = [...new Set(story.framings.flatMap((f) => f.srcs))];
  const totalSources = story.framings.reduce((s, f) => s + f.n, 0);
  const rec = recordOf(story);
  const [openGroups, setOpenGroups] = React.useState({ 0: true });

  return (
    <FadeIn>
      <div className="storyhead">
        <button className="backlink" onClick={onBack}>← All stories</button>
        <span className="micro">Story {idx + 1} of {SITE_STORIES.length}</span>
      </div>

      {/* HERO — collage cover with overlaid kicker / title / moodline */}
      <div className="shero">
        <div className="shero-art">
          <SArt id={story.id} seed={story.seed} radius={0} style={{ position: "absolute", inset: 0, width: "100%", height: "100%" }} />
        </div>
        <div className="shero-scrim"></div>
        <div className="shero-content">
          <div className="shero-kicker">{story.tags} · updated {story.upd} · {totalSources} sources · {story.framings.length} framings</div>
          <h1 className="display shero-title">{story.title}</h1>
          {story.dek && <p className="shero-dek">{story.dek}</p>}
          <div className="shero-mood">
            <STicks story={story} mode={mode} />
            <span className="micro">{tickLabel(story, mode)}</span>
          </div>
        </div>
      </div>
      <div className="micro" style={{ maxWidth: 920, margin: "8px auto 0", fontStyle: "italic", textAlign: "right" }}>Illustration: Mosaic — conceptual, not a depiction of real events.</div>

      {/* HOW IT'S FRAMED — wide feature, grouped directly under the hero (the two wide sections together) */}
      <Measure w={920} style={{ marginTop: 30 }}>
        <div className="kicker" style={{ padding: "10px 0 12px" }}>How it's framed</div>
        <LensColumns story={story} mode={mode} />
        <div className="micro" style={{ paddingTop: 14 }}>Columns are narratives — a source sits under the framing its coverage advances on this story, not its label.</div>
      </Measure>

      {/* reading column — lede + everything else, all at the narrow measure (width steps once, here) */}
      <Measure style={{ marginTop: 34 }}>
        <div className="hairStrong"></div>
        <p className="dek" style={{ margin: "20px 0 0" }}>{story.standfirst}</p>
        <div style={{ display: "flex", alignItems: "center", gap: 12, marginTop: 16, flexWrap: "wrap" }}>
          <SFavRow ids={allSrcs} size={17} max={8} />
          <span className="micro">{totalSources} sources across {story.framings.length} framings</span>
        </div>

        {/* Flexible markdown body (dossier prose: what happened · why it matters · fault · blind · next · record).
            Renders any sections without UI changes. Falls back to the structured blocks below if absent. */}
        {story.body_md ? (<MD md={story.body_md} />) : (<React.Fragment>

        {/* fault line — inline, no tinted box */}
        <div className="hair" style={{ marginTop: 22 }}></div>
        <div style={{ padding: "18px 0 20px" }}>
          <div className="kicker" style={{ marginBottom: 8 }}>The fault line</div>
          <div style={{ fontSize: 17.5, lineHeight: 1.5, fontStyle: "italic", color: "var(--text-primary)", letterSpacing: "-0.02em" }}>{story.fault}</div>
        </div>

        {/* facts — plain checklist */}
        <div className="hair"></div>
        <div style={{ padding: "18px 0 22px" }}>
          <div className="kicker" style={{ marginBottom: 12 }}>The facts — what everyone agrees on</div>
          <div className="factgrid">
            {story.facts.map((f, i) => (
              <div className="factline" key={i}><b>✓</b><span>{f}</span></div>
            ))}
          </div>
        </div>

        <div className="hair"></div>

        {/* history */}
        {story.history && (
          <div style={{ marginBottom: 30 }}>
            <div className="kicker" style={{ marginBottom: 12 }}>The story so far</div>
            <div className="hchips">
              {story.history.map((h, i) => (
                <React.Fragment key={i}>
                  {i > 0 && <span className="hconn"></span>}
                  <span className={"hchip" + (i === story.history.length - 1 ? " now" : "")}>
                    <span className="micro" style={{ fontWeight: 600, color: "var(--text-primary)", display: "block" }}>{h.d}</span>
                    <span className="ticks" style={{ gap: 2, margin: "6px 0", display: "inline-flex" }}>
                      {mode === "neutral"
                        ? NEUTRAL_PALETTE.map((c, j) => <i key={j} style={{ width: Math.max(4, Math.round(h.r[j] / 7)) * 3, height: 5, borderRadius: 99, background: c }}></i>)
                        : ["#FF601C", "#FFC200", "#00AA47"].map((c, j) => <i key={j} style={{ width: Math.max(4, Math.round(h.r[j] / 7)) * 3, height: 5, borderRadius: 99, background: c }}></i>)}
                    </span>
                    <span className="micro" style={{ fontSize: 10.5, display: "block" }}>{h.l}</span>
                  </span>
                </React.Fragment>
              ))}
            </div>
          </div>
        )}

        {/* blind spot — plain */}
        <div className="hair"></div>
        <div style={{ padding: "16px 0 22px", fontSize: 13.5, lineHeight: "20px", color: "var(--text-secondary)" }}>
          <strong style={{ color: "var(--text-primary)" }}>⊘ The blind spot.</strong> {story.blind}
        </div>

        {/* full record */}
        <div className="hairStrong"></div>
        <div className="kicker" style={{ padding: "16px 0 10px" }}>
          The full record · {rec.reduce((s, g) => s + g.items.length, 0)} items, grouped by framing
        </div>
        {rec.map((g, i) => (
          <RecordGroup key={i} story={story} group={g} idx={i} mode={mode}
            open={!!openGroups[i]} onToggle={() => setOpenGroups({ ...openGroups, [i]: !openGroups[i] })} />
        ))}

        </React.Fragment>)}

        {/* footer */}
        <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", borderTop: "1px solid var(--border-subtle)", marginTop: 26, padding: "18px 0 44px" }}>
          <button className="backlink" onClick={onBack}>← All stories</button>
          <button className="backlink" onClick={() => onOpenStory(next.id)}>Next in {next.cat}: {next.title} →</button>
        </div>
      </Measure>
    </FadeIn>
  );
};

Object.assign(window, { StoryPage });
