/* the turn - Today. The verdict surface. One primary call + one backup,
   forward-looking peek, conditions + collapsible 7-day Ahead strip.
   Primary card has three selectable layouts (Tweaks): band / instrument / split. */
const { VerdictBand, SafetyFlag, Button: TButton } = window.TheTurnDesignSystem_583d9e;

/* ---- shared atoms ---- */
function KnownList({ items }) {
  if (!items || !items.length) return null;
  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
      {items.map((t, i) => (
        <div key={i} style={{ display: 'flex', alignItems: 'flex-start', gap: 9 }}>
          <span style={{ flex: '0 0 auto', width: 18, height: 18, borderRadius: '50%', marginTop: 1, display: 'grid', placeItems: 'center', background: 'color-mix(in srgb, var(--verdict-go) 20%, var(--bg))', border: '1.5px solid var(--verdict-go)' }}>
            <svg width="11" height="11" viewBox="0 0 12 12" fill="none"><path d="M2.5 6.2l2.3 2.3 4.7-5" stroke="var(--verdict-go)" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" /></svg>
          </span>
          <span style={{ fontSize: 14, color: 'var(--text)', lineHeight: 1.35 }}>{t}</span>
        </div>
      ))}
    </div>
  );
}
function WhyList({ items }) {
  return (
    <ul style={{ listStyle: 'none', margin: 0, padding: 0, display: 'flex', flexDirection: 'column', gap: 7 }}>
      {items.map((t, i) => (
        <li key={i} style={{ display: 'flex', alignItems: 'flex-start', gap: 9, fontSize: 14, color: 'var(--text-dim)', lineHeight: 1.4 }}>
          <span style={{ flex: '0 0 auto', width: 5, height: 5, borderRadius: '50%', background: 'var(--text-label)', marginTop: 7 }} />
          {t}
        </li>
      ))}
    </ul>
  );
}
function ChecksList({ items }) {
  if (!items || !items.length) return null;
  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
      {items.map((t, i) => (
        <div key={i} style={{ display: 'flex', alignItems: 'flex-start', gap: 9 }}>
          <span style={{ flex: '0 0 auto', width: 18, height: 18, borderRadius: '50%', marginTop: 1, display: 'grid', placeItems: 'center', border: '1.5px dashed var(--text-label)' }}>
            <span style={{ width: 4, height: 4, borderRadius: '50%', background: 'var(--text-label)' }} />
          </span>
          <span style={{ fontSize: 14, color: 'var(--text-dim)', lineHeight: 1.35 }}>{t}</span>
        </div>
      ))}
    </div>
  );
}
function SpeciesRow({ ids, onSpecies, color }) {
  if (!ids || !ids.length) return null;
  return (
    <div style={{ display: 'flex', gap: 8, flexWrap: 'wrap' }}>
      {ids.map(id => <SpeciesChip key={id} id={id} onClick={onSpecies} color={color || 'var(--text-label)'} />)}
    </div>
  );
}
function FactRow({ label, value, reason, badge }) {
  return (
    <div style={{ display: 'flex', gap: 14, padding: '11px 0', borderTop: '1px solid var(--hairline)' }}>
      <span className="overline" style={{ flex: '0 0 76px', paddingTop: 2 }}>{label}</span>
      <span style={{ flex: 1, minWidth: 0 }}>
        <span style={{ display: 'flex', alignItems: 'center', gap: 8, flexWrap: 'wrap' }}>
          <span style={{ fontFamily: 'var(--font-display)', fontWeight: 700, fontSize: 16, color: 'var(--text)', textTransform: 'capitalize' }}>{value}</span>
          {badge}
        </span>
        {reason && <span style={{ display: 'block', fontSize: 13, color: 'var(--text-dim)', marginTop: 2, lineHeight: 1.35 }}>{reason}</span>}
      </span>
    </div>
  );
}

/* The mouth IS the estuary verdict. Last logged state + age at verdict level:
   lime while open and fresh, amber once stale (48h rule) or not fully open -
   "the call rests on a 3-day-old look at the mouth" must be visible at 05:00. */
function MouthChip({ m }) {
  if (!m) return null;
  const stale = !m.fresh;
  const open = m.state === 'open';
  const c = (open && !stale) ? 'var(--verdict-go)' : 'var(--verdict-caution)';
  const age = m.ageDays === 0 ? 'today' : m.ageDays === 1 ? '1d ago' : `${m.ageDays}d ago`;
  return (
    <span style={{
      display: 'inline-flex', alignItems: 'center', gap: 5, height: 24, padding: '0 9px',
      borderRadius: 'var(--r-pill)', flex: '0 0 auto',
      border: `1.5px ${stale ? 'dashed' : 'solid'} ${c}`, color: c,
      background: `color-mix(in srgb, ${c} 10%, transparent)`,
      fontFamily: 'var(--font-mono)', fontSize: 10, fontWeight: 700, letterSpacing: '0.08em', whiteSpace: 'nowrap', textTransform: 'uppercase',
    }}>MOUTH {m.state} · {age}</span>
  );
}

/* A hard safety gate is a verdict, never prose. Red is reserved for danger in
   the tokens and almost unused - this is where it gets spent. */
function KayakGateChip({ gates }) {
  if (!gates || !gates.length) return null;
  const CODE = { wind: 'WIND', gusts: 'GUSTS', 'swell-period': 'SWELL' };
  const label = gates.map(g => CODE[g.code] || String(g.code).toUpperCase()).join(' + ');
  return (
    <span title={gates.map(g => g.detail).join(' · ')} style={{
      display: 'inline-flex', alignItems: 'center', gap: 5, height: 24, padding: '0 9px',
      borderRadius: 'var(--r-pill)', flex: '0 0 auto',
      border: '1.5px solid var(--verdict-danger)', color: 'var(--verdict-danger)',
      background: 'color-mix(in srgb, var(--verdict-danger) 10%, transparent)',
      fontFamily: 'var(--font-mono)', fontSize: 10, fontWeight: 700, letterSpacing: '0.08em', whiteSpace: 'nowrap',
    }}>⊘ KAYAK GATED · {label}</span>
  );
}
function Subhead({ children, style = {} }) {
  return <div className="overline" style={{ margin: '0 0 9px', ...style }}>{children}</div>;
}

/* ---- detail block shared below the hero (layouts A & C) ---- */
function CallDetail({ call, onSpecies }) {
  const c = VERDICT[call.verdict].color;
  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 18 }}>
      <div style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
        <FactRowGroup>
          <FactRow label="platform" value={PLATFORM_LABEL[call.platform.mode]} reason={call.platform.reason} badge={<KayakGateChip gates={call.platform.gates} />} />
          <FactRow label="method" value={METHOD_LABEL[call.method.mode]} reason={call.method.reason} />
        </FactRowGroup>
      </div>
      <div>
        <Subhead>what you're after</Subhead>
        <SpeciesRow ids={call.species} onSpecies={onSpecies} color={c} />
      </div>
      {call.known && call.known.length > 0 && (
        <div>
          <Subhead style={{ color: 'var(--verdict-go)' }}>from your own logbook</Subhead>
          <KnownList items={call.known} />
        </div>
      )}
      <div>
        <Subhead>the read</Subhead>
        <WhyList items={call.why} />
      </div>
      {call.checks && call.checks.length > 0 && (
        <div>
          <Subhead>eyes-on when you land</Subhead>
          <ChecksList items={call.checks} />
        </div>
      )}
    </div>
  );
}
function FactRowGroup({ children }) {
  return <div style={{ borderBottom: '1px solid var(--hairline)' }}>{children}</div>;
}

/* ============================================================
   LAYOUT A - Band hero (signature VerdictBand component)
   ============================================================ */
function PrimaryBand({ call, area, onSpecies, standout = true }) {
  // Species headline (e.g. "Go - leervis") is only used when we have field-
  // validated confidence in the species hypothesis for this area. For DIY
  // SCOUT (lifecycle: none/scouted) the species is just a target list, not a
  // forecast - leading with it overpromises. Default to verdict + place.
  const speciesConfident = call.lifecycle === 'validated' || call.lifecycle === 'guide';
  const topSpName = (() => {
    const id = call.species?.[0];
    if (!id) return null;
    const sp = speciesById(id);
    return sp?.common?.toLowerCase() ?? String(id).replace(/-/g, ' ');
  })();
  const placeShort = area?.sub ? area.sub.split(/\s*\/\s*/)[0] : (area?.name?.split(/\s*\/\s*/)[0] ?? '');
  const heroPhrase =
    call.verdict === 'go'    ? (speciesConfident && topSpName ? `Go - ${topSpName}` : `Go${placeShort ? ` · ${placeShort}` : ''}`) :
    call.verdict === 'scout' ? `Worth a scout${placeShort ? ` · ${placeShort}` : ''}` :
                                'Skip - bait day';
  // When the day genuinely separates the marks (big swell, clear gap, field
  // history) this is "the best play". When the bay's conditions are shared
  // and the marks are level, it's honestly just "where I'd start".
  const leadLabel = standout ? 'best play' : "where I'd start";
  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 16 }}>
      <div style={{ display: 'flex', alignItems: 'center', gap: 8, flexWrap: 'wrap' }}>
        <VerdictBadge verdict={call.verdict} />
        <PostureBadge posture={call.posture} />
        <MouthChip m={call.mouth} />
        <ConfidenceBadge lifecycle={call.lifecycle} style={{ marginLeft: 'auto' }} />
      </div>
      <VerdictBand
        verdict={call.verdict} confidence={call.confidence}
        dateline={`${leadLabel} · ${area.name}`}
        phrase={heroPhrase}
        window={call.window}
        where={`${PLATFORM_LABEL[call.platform.mode]} · ${METHOD_LABEL[call.method.mode]} · ${area.distKm}km ${area.bearing}`}
        why={call.why[0]}
        confidenceNote={call.known && call.known[0]}
        media={<FishIcon species={call.species[0]} size={188} color={VERDICT[call.verdict].color} />}
      />
      <CallDetail call={call} onSpecies={onSpecies} />
    </div>
  );
}

/* ============================================================
   LAYOUT B - Instrument stack (chartplotter readout)
   ============================================================ */
function PrimaryInstrument({ call, area, onSpecies }) {
  const c = VERDICT[call.verdict].color;
  const low = call.confidence === 'low';
  return (
    <div style={{
      border: `2px ${low ? 'dashed' : 'solid'} ${c}`, borderRadius: 'var(--r-lg)', overflow: 'hidden',
      background: 'var(--surface)',
    }}>
      {/* hero zone */}
      <div style={{ padding: 'var(--space-5) var(--space-5) var(--space-4)', background: low ? 'transparent' : `color-mix(in srgb, ${c} 12%, var(--bg))`, position: 'relative', overflow: 'hidden' }}>
        <div aria-hidden="true" style={{ position: 'absolute', right: -22, top: '50%', transform: 'translateY(-50%)', opacity: 0.12 }}>
          <FishIcon species={call.species[0]} size={150} color={c} />
        </div>
        <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 12 }}>
          <VerdictBadge verdict={call.verdict} size="lg" />
          <span style={{ marginLeft: 'auto', fontFamily: 'var(--font-mono)', fontSize: 13, color: 'var(--text-label)' }}>score <b style={{ color: 'var(--text)', fontSize: 18 }}>{call.score}</b></span>
        </div>
        <h1 style={{ fontFamily: 'var(--font-display)', fontWeight: 700, fontSize: 34, lineHeight: 1.04, letterSpacing: '-0.02em', color: 'var(--text)', margin: 0, position: 'relative' }}>{call.line}</h1>
        <div className="metric" style={{ marginTop: 10, fontSize: 16, color: c }}>{call.window}</div>
        <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginTop: 12, flexWrap: 'wrap' }}>
          <PostureBadge posture={call.posture} />
          <MouthChip m={call.mouth} />
          <ConfidenceBadge lifecycle={call.lifecycle} />
        </div>
      </div>
      {/* instrument rows */}
      <div style={{ padding: '4px var(--space-5) var(--space-5)' }}>
        <FactRow label="where" value={area.name} reason={`${area.sub} · ${area.distKm}km ${area.bearing}`} />
        <FactRow label="platform" value={PLATFORM_LABEL[call.platform.mode]} reason={call.platform.reason} badge={<KayakGateChip gates={call.platform.gates} />} />
        <FactRow label="method" value={METHOD_LABEL[call.method.mode]} reason={call.method.reason} />
        <div style={{ padding: '14px 0 4px', borderTop: '1px solid var(--hairline)' }}>
          <Subhead>what you're after</Subhead>
          <SpeciesRow ids={call.species} onSpecies={onSpecies} color={c} />
        </div>
        {call.known && call.known.length > 0 && (
          <div style={{ marginTop: 16 }}>
            <Subhead style={{ color: 'var(--verdict-go)' }}>from your own logbook</Subhead>
            <KnownList items={call.known} />
          </div>
        )}
        <div style={{ marginTop: 16 }}>
          <Subhead>the read</Subhead>
          <WhyList items={call.why} />
        </div>
        {call.checks && call.checks.length > 0 && (
          <div style={{ marginTop: 16 }}>
            <Subhead>eyes-on when you land</Subhead>
            <ChecksList items={call.checks} />
          </div>
        )}
      </div>
    </div>
  );
}

/* ============================================================
   LAYOUT C - Split header (colour cap + calm detail card)
   ============================================================ */
function PrimarySplit({ call, area, onSpecies }) {
  const c = VERDICT[call.verdict].color;
  const low = call.confidence === 'low';
  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 14 }}>
      {/* colour cap */}
      <div style={{
        borderRadius: 'var(--r-lg)', padding: 'var(--space-5)',
        border: `2.5px ${low ? 'dashed' : 'solid'} ${c}`,
        background: low ? 'transparent' : `color-mix(in srgb, ${c} 16%, var(--bg))`,
        boxShadow: (call.verdict === 'go' && !low) ? 'var(--glow-go)' : 'none',
        position: 'relative', overflow: 'hidden',
      }}>
        <div aria-hidden="true" style={{ position: 'absolute', right: -26, bottom: -16, opacity: 0.13 }}>
          <FishIcon species={call.species[0]} size={150} color={c} />
        </div>
        <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
          <VerdictBadge verdict={call.verdict} size="lg" />
          <span style={{ marginLeft: 'auto', fontFamily: 'var(--font-mono)', fontSize: 12, color: 'var(--text-label)' }}>score <b style={{ color: 'var(--text)', fontSize: 16 }}>{call.score}</b></span>
        </div>
        <h1 style={{ fontFamily: 'var(--font-display)', fontWeight: 700, fontSize: 'clamp(30px, 8vw, 40px)', lineHeight: 1.04, letterSpacing: '-0.02em', color: c, margin: '14px 0 0', textWrap: 'balance' }}>{call.line}</h1>
        <div className="metric" style={{ marginTop: 12, fontSize: 17, color: 'var(--text)' }}>{call.window}</div>
        <div style={{ fontSize: 15, color: 'var(--text-dim)', marginTop: 3 }}>{area.name} · {area.distKm}km {area.bearing}</div>
      </div>
      {/* posture + confidence sit between */}
      <div style={{ display: 'flex', alignItems: 'center', gap: 8, flexWrap: 'wrap' }}>
        <PostureBadge posture={call.posture} />
        <MouthChip m={call.mouth} />
        <ConfidenceBadge lifecycle={call.lifecycle} style={{ marginLeft: 'auto' }} />
      </div>
      {/* calm detail card */}
      <div style={{ background: 'var(--surface)', border: '1px solid var(--border)', borderRadius: 'var(--r-md)', padding: 'var(--space-5)' }}>
        <CallDetail call={call} onSpecies={onSpecies} />
      </div>
    </div>
  );
}

/* ---- backup call (visually demoted) ---- */
function BackupCall({ call, area, onSpecies, onArea }) {
  const c = VERDICT[call.verdict].color;
  return (
    <div style={{ background: 'var(--surface)', border: '1px solid var(--border)', borderRadius: 'var(--r-md)', padding: 'var(--space-5)' }}>
      <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 12 }}>
        <span className="overline">plan b</span>
        <span style={{ width: 7, height: 7, borderRadius: '50%', background: c }} />
        <ConfidenceBadge lifecycle={call.lifecycle} showLabel={false} style={{ marginLeft: 'auto' }} />
      </div>
      <button onClick={() => onArea(area.id)} style={{ background: 'none', border: 'none', padding: 0, cursor: 'pointer', textAlign: 'left', display: 'block', width: '100%' }}>
        <div style={{ display: 'flex', alignItems: 'baseline', gap: 10 }}>
          <h2 style={{ fontFamily: 'var(--font-display)', fontWeight: 700, fontSize: 22, color: c, margin: 0 }}>{call.line}</h2>
        </div>
        <div className="metric" style={{ fontSize: 14, color: 'var(--text)', marginTop: 6 }}>{call.window}</div>
      </button>
      <div style={{ display: 'flex', gap: 7, flexWrap: 'wrap', marginTop: 12 }}>
        <TagChip icon={<NavGlyph name="explore" size={13} />}>{PLATFORM_LABEL[call.platform.mode]}</TagChip>
        <TagChip>{METHOD_LABEL[call.method.mode]}</TagChip>
        <span style={{ flex: 1 }} />
      </div>
      <div style={{ marginTop: 12 }}>
        <SpeciesRow ids={call.species} onSpecies={onSpecies} color={c} />
      </div>
      {call.known && call.known[0] && (
        <div style={{ marginTop: 12, fontSize: 13, color: 'var(--verdict-go)', display: 'flex', alignItems: 'center', gap: 7 }}>
          <span style={{ width: 6, height: 6, borderRadius: '50%', background: 'var(--verdict-go)' }} />{call.known[0]}
        </div>
      )}
    </div>
  );
}

/* ---- forward peek ---- */
function ForwardPeek({ primary, onExplore }) {
  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 10 }}>
      <div style={{ display: 'flex', alignItems: 'center', gap: 10, padding: '13px 16px', background: 'var(--surface)', border: '1px solid var(--border)', borderRadius: 'var(--r-md)' }}>
        <Icon name="clock" size={18} color="var(--text-label)" />
        <span style={{ fontSize: 14, color: 'var(--text-dim)' }}>{primary.tomorrow}</span>
      </div>
      {primary.betterDay && (
        <button onClick={onExplore} style={{ display: 'flex', alignItems: 'center', gap: 10, padding: '13px 16px', background: 'color-mix(in srgb, var(--keyline) 7%, var(--surface))', border: '1px solid var(--border-strong)', borderRadius: 'var(--r-md)', cursor: 'pointer', textAlign: 'left' }}>
          <span style={{ width: 7, height: 7, borderRadius: '50%', background: 'var(--verdict-go)', flex: '0 0 auto' }} />
          <span style={{ fontSize: 14, color: 'var(--text)', fontWeight: 600 }}>{primary.betterDay}</span>
          <Icon name="chevron" size={16} color="var(--text-label)" style={{ marginLeft: 'auto' }} />
        </button>
      )}
    </div>
  );
}

/* ============================================================
   Also worth a look - compact rail of the next 3 ranked spots after
   primary + backup, so Today doesn't feel like a single-spot view
   ============================================================ */
function AlsoWorthALook({ primary, backup, onArea }) {
  const T = window.TURN;
  const skip = new Set([primary?.areaId, backup?.areaId].filter(Boolean));
  const more = (T.areas || [])
    .filter(a => !a.gatedOut && !skip.has(a.id))
    .slice(0, 3);
  if (more.length === 0) return null;
  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
      <div className="overline" style={{ fontSize: 10 }}>also worth a look</div>
      <div style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>
        {more.map(a => (
          <button key={a.id} onClick={() => onArea(a.id)} style={{
            display: 'flex', alignItems: 'center', gap: 12, padding: '10px 12px',
            background: 'var(--surface)', border: '1px solid var(--border)',
            borderRadius: 'var(--r-md)', cursor: 'pointer', color: 'var(--text)', textAlign: 'left',
          }}>
            <VerdictDot verdict={a.today.verdict} size={10} confidence={a.today.confidence} />
            <span style={{ flex: 1, minWidth: 0 }}>
              <span style={{ display: 'block', fontFamily: 'var(--font-display)', fontWeight: 700, fontSize: 14, color: 'var(--text)', lineHeight: 1.15, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{a.name}</span>
              <span style={{ display: 'block', fontFamily: 'var(--font-mono)', fontSize: 10.5, color: 'var(--text-label)', marginTop: 2 }}>
                {a.distKm}km {a.bearing} · {a.today.platform} · {a.today.method}
              </span>
            </span>
            <span style={{ fontFamily: 'var(--font-mono)', fontSize: 11, fontWeight: 700, color: 'var(--text-dim)' }}>{a.today.score}</span>
            <Icon name="chevron" size={14} color="var(--text-label)" />
          </button>
        ))}
      </div>
    </div>
  );
}

/* ============================================================
   Today screen
   ============================================================ */
function Today({ layout = 'band', onSpecies, onArea, onLog, onExplore, onConditions, aheadOpen, setAheadOpen, aheadActive, setAheadActive }) {
  const T = window.TURN;
  const primary = T.today.primary;
  const backup = T.today.backup;
  const pArea = areaById(primary.areaId);
  const bArea = areaById(backup.areaId);
  const Layout = layout === 'instrument' ? PrimaryInstrument : layout === 'split' ? PrimarySplit : PrimaryBand;

  return (
    <div style={{ padding: '4px var(--gutter) 0', display: 'flex', flexDirection: 'column', gap: 16 }}>
      {/* location / freshness */}
      <div style={{ display: 'flex', alignItems: 'flex-end', justifyContent: 'space-between' }}>
        <div>
          <div style={{ fontFamily: 'var(--font-display)', fontWeight: 700, fontSize: 22, color: 'var(--text)', letterSpacing: '-0.02em' }}>{T.conditions.place}</div>
          <div className="overline" style={{ marginTop: 2 }}>{T.conditions.dateLine}</div>
        </div>
        <span style={{ display: 'inline-flex', alignItems: 'center', gap: 6, fontFamily: 'var(--font-mono)', fontSize: 11, color: 'var(--text-label)' }}>
          <span style={{ width: 6, height: 6, borderRadius: '50%', background: 'var(--text-label)' }} />cached {T.conditions.refreshed}
        </span>
      </div>

      <ConditionsStrip c={T.conditions} onClick={onConditions} />
      <AheadStrip ahead={T.ahead} open={aheadOpen} onToggle={() => setAheadOpen(o => !o)} active={aheadActive} onPick={setAheadActive} />

      {/* THE DAY READ - the high-confidence statement (the conditions), shown
          before any single-spot pick. This is what the app is actually sure of. */}
      {T.today.read && (
        <div style={{ display: 'flex', gap: 11, alignItems: 'flex-start', padding: '14px 16px', background: 'color-mix(in srgb, var(--verdict-go) 8%, var(--surface))', border: '1px solid color-mix(in srgb, var(--verdict-go) 30%, var(--border))', borderRadius: 'var(--r-md)' }}>
          <span style={{ flex: '0 0 auto', width: 8, height: 8, borderRadius: '50%', background: 'var(--verdict-go)', marginTop: 6 }} />
          <div>
            <div className="overline" style={{ fontSize: 10, marginBottom: 3 }}>today's read</div>
            <div style={{ fontFamily: 'var(--font-display)', fontWeight: 700, fontSize: 17, color: 'var(--text)', lineHeight: 1.25, letterSpacing: '-0.01em' }}>{T.today.read}</div>
          </div>
        </div>
      )}

      {/* PRIMARY CALL */}
      <Layout call={primary} area={pArea} onSpecies={onSpecies} standout={T.today.standout} />

      {/* primary actions */}
      <div style={{ display: 'flex', gap: 10 }}>
        <TButton variant="primary" size="fat" full onClick={() => onLog(primary.areaId)} icon={<Icon name="plus" size={20} />}>Log this trip</TButton>
      </div>
      <button onClick={() => onArea(primary.areaId)} style={{ alignSelf: 'flex-start', background: 'none', border: 'none', cursor: 'pointer', color: 'var(--text-label)', fontFamily: 'var(--font-mono)', fontSize: 11, letterSpacing: '.1em', textTransform: 'uppercase', padding: '16px 12px', margin: '-14px -12px', minHeight: 48, display: 'inline-flex', alignItems: 'center', gap: 6 }}>
        the full rundown <Icon name="chevron" size={14} />
      </button>

      {/* LEVEL-DAY FRAMING - when the bay's conditions are shared and the marks
          are bunched, say so: the call is local, not the engine's to make. */}
      {!T.today.standout && T.today.contenders > 1 && (
        <p style={{ margin: '2px 2px', fontSize: 13, color: 'var(--text-dim)', lineHeight: 1.45 }}>
          <span style={{ color: 'var(--text)', fontWeight: 700 }}>{T.today.contenders} marks are level today</span> — the bay shares one set of conditions, so it's close. Your read on mouth state, kelp and what you fancy makes the call.
        </p>
      )}

      {/* BACKUP */}
      <BackupCall call={backup} area={bArea} onSpecies={onSpecies} onArea={onArea} />

      {/* ALSO WORTH A LOOK - next 3 ranked spots beyond primary + backup */}
      <AlsoWorthALook primary={primary} backup={backup} onArea={onArea} />

      {/* FORWARD PEEK */}
      <ForwardPeek primary={primary} onExplore={onExplore} />

      {/* see all in explore */}
      <button onClick={onExplore} style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 12, padding: '15px 18px', background: 'var(--surface)', border: '1px solid var(--border)', borderRadius: 'var(--r-md)', cursor: 'pointer', color: 'var(--text)' }}>
        <span style={{ fontWeight: 600, fontSize: 15 }}>Suss the rest of the coast</span>
        <Icon name="chevron" size={18} color="var(--text-label)" />
      </button>

      {/* honest safety footer - the call is a guide, the water is the authority */}
      <p style={{ margin: '6px 2px 0', fontSize: 11.5, color: 'var(--text-label)', lineHeight: 1.45 }}>
        A read on the conditions, not a guarantee. The sea changes fast — judge the swell and your exit yourself, never turn your back on it, and fish within your depth. If it looks dangerous, it is.
      </p>
      <div style={{ height: 8 }} />
    </div>
  );
}

Object.assign(window, { Today });
