/* Phone using IOSDevice frame.
   Statically pinned. Three screen states: lockChaos, opening (transition), bobChat.
   Bob speaks in Source Serif 4 per v3 brand guide rule. */

const { useMemo: usePhoneMemo } = React;

function Phone({ beat, beatProgress, chatProgress, t }) {
  let lockOpacity = 1;
  let chatOpacity = 0;

  if (beat === 'chaos') {
    lockOpacity = 1;
    chatOpacity = 0;
  } else if (beat === 'ask') {
    const opening = smootherStep(clamp01(beatProgress / 0.52));
    lockOpacity = 1 - opening;
    chatOpacity = opening;
  } else {
    lockOpacity = 0;
    chatOpacity = 1;
  }

  // Phone is anchored. No shake, no parallax. The notifications are what
  // move; the device they're competing with is the still point.
  return (
    <div className="phone-wrap">
      <IOSDevice width={320} height={660} dark={false}>
        <div style={{ position: 'absolute', inset: 0, opacity: lockOpacity, transition: 'opacity .7s cubic-bezier(.22, 1, .36, 1)' }}>
          <LockScreen progress={beat === 'chaos' ? beatProgress : 1} t={t} />
        </div>
        <div style={{ position: 'absolute', inset: 0, opacity: chatOpacity, transition: 'opacity .75s cubic-bezier(.22, 1, .36, 1)' }}>
          <BobChat beat={beat} beatProgress={beatProgress} chatProgress={chatProgress} t={t} />
        </div>
      </IOSDevice>
    </div>
  );
}

/* Lock screen. wallpaper + clock + small notification stack (the chaos echo). */
function LockScreen({ progress, t }) {
  const lines = [
    { app: 'Messages',   icon: 'imessage',  title: 'Margo',          body: 'two drafts ready. second is shorter', time: 'now' },
    { app: 'Slack',      icon: 'slack',     title: '#ship-it · Quinn', body: 'PR-1184 ready',                     time: '2m'  },
    { app: 'Calendar',   icon: 'calendar',  title: 'Eng standup',    body: 'in 5 min · Zoom',                      time: '5m'  },
    { app: 'Mail',       icon: 'mail',      title: 'Vendor renewal', body: 'Re: contract terms for Q3',            time: '14m' },
    { app: 'Reminders',  icon: 'reminders', title: 'Pick up Jamie',  body: '14:30 · school pickup',                time: '20m' },
    { app: 'WhatsApp',   icon: 'whatsapp',  title: 'Mom',            body: 'are you coming sunday?',               time: '1h'  },
  ];
  return (
    <div style={{ position: 'absolute', inset: 0, overflow: 'hidden', borderRadius: 46 }}>
      {/* Wallpaper */}
      <div style={{
        position: 'absolute', inset: 0,
        background: 'radial-gradient(ellipse at 30% 20%, rgba(65,182,230,0.65), transparent 50%), radial-gradient(ellipse at 70% 70%, rgba(0,119,182,0.55), transparent 55%), linear-gradient(180deg, #0a3a5e 0%, #1a5d8a 50%, #2c7eb0 100%)',
      }}/>
      {/* Time / date */}
      <div style={{ position: 'absolute', top: 70, left: 0, right: 0, textAlign: 'center', color: '#fff', pointerEvents: 'none' }}>
        <div style={{ font: '500 14px Inter, sans-serif', opacity: 0.95 }}>Monday, April 27</div>
        <div style={{ font: '200 78px/1 Inter, sans-serif', letterSpacing: '-0.04em', marginTop: 2, textShadow: '0 1px 30px rgba(0,0,0,0.2)' }}>9:41</div>
      </div>
      {/* Notification stack */}
      <div style={{ position: 'absolute', left: 12, right: 12, bottom: 36, display: 'flex', flexDirection: 'column-reverse', gap: 6 }}>
        {lines.map((n, i) => (
          <div key={i} style={{
            display: 'flex', alignItems: 'flex-start', gap: 9,
            padding: '9px 11px',
            background: 'rgba(255,255,255,0.18)',
            backdropFilter: 'blur(20px) saturate(180%)',
            WebkitBackdropFilter: 'blur(20px) saturate(180%)',
            border: '0.5px solid rgba(255,255,255,0.25)',
            borderRadius: 16,
          }}>
            <NotifIcon kind={n.icon} />
            <div style={{ flex: 1, minWidth: 0 }}>
              <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline', gap: 8 }}>
                <span style={{ font: '600 12.5px Inter, sans-serif', color: '#fff', letterSpacing: '-0.005em', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{n.title}</span>
                <span style={{ font: '500 10.5px Inter, sans-serif', color: 'rgba(255,255,255,0.7)', flexShrink: 0 }}>{n.time}</span>
              </div>
              <div style={{ font: '400 11.5px/1.3 Inter, sans-serif', color: 'rgba(255,255,255,0.92)', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis', marginTop: 1 }}>{n.body}</div>
            </div>
          </div>
        ))}
        <div style={{ textAlign: 'center', font: '500 11px Inter, sans-serif', color: 'rgba(255,255,255,0.65)', padding: '4px 0', letterSpacing: '0.02em' }}>
          + 18 more notifications
        </div>
      </div>
    </div>
  );
}

function BobGlyph() {
  return (
    <svg className="bob-glyph" viewBox="0 0 1000 1000" aria-hidden="true">
      <g fillRule="evenodd" fill="currentColor">
        <path d="M290.58 199.46 L296.47 200.71 L311.09 207.64 L313.21 209.58 L314.12 213.17 L314.17 596.61 L315.14 602.92 L317.25 603.90 L321.06 602.22 L339.74 582.88 L350.55 573.61 L367.27 561.89 L380.05 554.64 L411.51 542.25 L444.94 535.08 L467.55 532.78 L491.15 532.70 L514.75 535.09 L531.46 538.74 L546.21 543.56 L563.91 550.69 L582.59 560.24 L595.37 568.51 L610.12 580.16 L633.23 604.49 L653.53 635.94 L664.39 659.53 L672.43 684.11 L681.63 727.37 L685.79 776.53 L685.75 821.76 L683.34 828.09 L672.06 829.55 L540.32 829.62 L535.10 828.66 L533.37 825.64 L532.48 819.80 L532.43 712.63 L531.39 697.88 L527.90 677.23 L522.31 662.48 L513.35 648.72 L496.64 629.21 L487.22 620.70 L478.37 614.74 L464.60 607.86 L448.87 603.14 L434.12 600.69 L417.41 600.55 L397.75 603.69 L386.93 606.78 L374.15 612.64 L364.32 618.96 L354.48 627.12 L343.87 638.88 L337.20 648.72 L330.20 662.48 L320.20 691.98 L315.31 722.46 L314.19 739.17 L314.14 810.95 L312.64 828.09 L309.20 829.58 L254.20 830.61 L164.78 829.58 L161.68 828.66 L160.51 826.55 L159.54 349.82 L158.17 339.99 L155.03 330.16 L150.20 321.47 L145.05 316.82 L127.36 308.27 L90.97 299.77 L90.02 295.73 L90.05 262.35 L91.54 258.44 L95.90 256.44 L184.39 233.39 L251.25 212.49 L283.69 200.72 Z"></path>
        <circle cx="832.09" cy="752.14" r="78.16"></circle>
      </g>
    </svg>
  );
}

/* Bob's chat surface. Welcome backdrop + bubbles in Source Serif 4 (Bob's voice).
   User bubbles stay Inter on Chi Blue. */
function BobChat({ beat, beatProgress, chatProgress, t }) {
  let userText = '';
  let userSent = false;
  let bobTyping = false;
  let bobMsg1 = false;
  let bobMsg2 = false;
  let bobMsg3 = false;
  let composerHasFocus = false;

  const fullUserText = "hey bob, what needs me today?";

  // Per-typing flags for each Bob message. Replaces the single bobTyping
  // flag so each Bob reply gets its own typing indicator with a duration
  // proportional to that reply's character count. Gaps between messages
  // intentionally vary so the cadence reads as human, not metronomic.
  let bobTyping1 = false;
  let bobTyping2 = false;
  let bobTyping3 = false;

  if (beat === 'ask') {
    composerHasFocus = true;
    const typeP = clamp01((beatProgress - 0.05) / 0.65);
    const charsToShow = Math.floor(easeOutCubic(typeP) * fullUserText.length);
    userText = fullUserText.slice(0, charsToShow);
    userSent = beatProgress > 0.78;
    if (userSent) userText = fullUserText;
  } else if (beat === 'response' || beat === 'focus') {
    userText = fullUserText;
    userSent = true;

    // chatProgress is 0..1 across the combined response+focus region
    // (overall t = 0.62 → 1.00). Sub-stages laid out with varied widths
    // so the cadence isn't perfectly even. msg1 is the longest reply
    // (74 chars), so its typing window is the widest. Final dwell after
    // msg3 leaves time to read.
    //
    //   0.00 → 0.30   bobTyping1 (initial reading + writing msg1)
    //   0.30          bobMsg1 appears
    //   0.30 → 0.42   pause (Bob "thinks" — slightly longer than msg2)
    //   0.42 → 0.62   bobTyping2 (writing msg2, ~50 chars)
    //   0.62          bobMsg2 appears
    //   0.62 → 0.74   longer pause (the "rest can wait" beat — Bob hesitates)
    //   0.74 → 0.85   bobTyping3 (writing msg3, ~31 chars, shortest)
    //   0.85          bobMsg3 appears
    //   0.85 → 1.00   final dwell (read time)
    const cp = chatProgress;
    bobTyping1 = cp < 0.30;
    bobMsg1    = cp >= 0.30;
    bobTyping2 = cp >= 0.42 && cp < 0.62;
    bobMsg2    = cp >= 0.62;
    bobTyping3 = cp >= 0.74 && cp < 0.85;
    bobMsg3    = cp >= 0.85;
  }

  const bobTypingAny = bobTyping1 || bobTyping2 || bobTyping3;
  const hasAnyMessages = userSent || bobTypingAny || bobMsg1 || bobMsg2 || bobMsg3;

  return (
    <div className="bob-shell">
      {/* Top chrome */}
      <div className="bob-topchrome">
        <button className="bob-icon-btn" aria-label="Menu">
          <svg viewBox="0 0 18 12" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round">
            <path d="M1 1.5h16M1 6h16M1 10.5h11"/>
          </svg>
        </button>
        <div className="bob-titlestack">
          <span className="bob-title">Bob</span>
          <svg className="bob-title-chev" viewBox="0 0 10 6" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round">
            <path d="M1 1l4 4 4-4"/>
          </svg>
        </div>
        <button className="bob-icon-btn" aria-label="New chat">
          <svg viewBox="0 0 18 18" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round">
            <path d="M14.5 1.5l2 2-9 9-3 1 1-3z"/>
          </svg>
        </button>
      </div>

      {/* Empty-state welcome backdrop */}
      <div className="bob-welcome" style={{ opacity: hasAnyMessages ? 0 : 1 }}>
        <div className="bob-mark"><BobGlyph /></div>
        <div className="bob-welcome-copy">
          What's the most important thing today?
        </div>
      </div>

      {/* Message feed */}
      <div className="bob-feed">
        {/* Date separator. Anchors the top of the thread once messages arrive,
            so the screen reads as a populated chat, not an empty app. */}
        {hasAnyMessages && (
          <div className="bob-date-sep">
            <span className="bob-date-strong">Today</span>
            <span> 9:41 AM</span>
          </div>
        )}

        {/* User bubble appears all at once on send. Typing happens in the
            composer below. The bubble does NOT mirror the typing. */}
        {userSent && (
          <div className="bob-row right">
            <div className="bob-bubble user user-pop">{fullUserText}</div>
          </div>
        )}
        {/* Delivered indicator under user bubble. Standard iMessage element. */}
        {userSent && (
          <div className="bob-delivered">Delivered</div>
        )}

        {bobTyping1 && (
          <div className="bob-row left">
            <div className="bob-typing">
              <span className="spin"></span>
              <span>Reading the pile</span>
            </div>
          </div>
        )}
        {bobMsg1 && (
          <div className="bob-row left">
            <div className="bob-bubble bob fade-in">You've got a lot on your plate. Let's start with what matters right now.</div>
          </div>
        )}
        {bobTyping2 && (
          <div className="bob-row left">
            <div className="bob-typing">
              <span className="spin"></span>
              <span>Typing</span>
            </div>
          </div>
        )}
        {bobMsg2 && (
          <div className="bob-row left">
            <div className="bob-bubble bob fade-in">
              I drafted a response to the vendor.
              <span className="bob-bubble-link"> Tap to view <span className="arr">&rarr;</span></span>
            </div>
          </div>
        )}
        {bobTyping3 && (
          <div className="bob-row left">
            <div className="bob-typing">
              <span className="spin"></span>
              <span>Typing</span>
            </div>
          </div>
        )}
        {bobMsg3 && (
          <div className="bob-row left">
            <div className="bob-bubble bob fade-in">The rest can wait til tomorrow.</div>
          </div>
        )}
      </div>

      {/* Composer island */}
      <div className="bob-composer-wrap">
        <button className="bob-plus" aria-label="Add">
          <svg viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round">
            <path d="M8 2v12M2 8h12"/>
          </svg>
        </button>
        <div className={`bob-composer-pill ${composerHasFocus ? 'focused' : ''}`}>
          <div className="bob-composer-text">
            {beat === 'ask' && userText && !userSent ? (
              <span>{userText}<span className="caret-blink">|</span></span>
            ) : (
              <span className="bob-composer-prompt">Hey Bob...</span>
            )}
          </div>
          {composerHasFocus && userText && !userSent ? (
            <div className="bob-send-btn">
              <svg viewBox="0 0 30 30" fill="currentColor">
                <circle cx="15" cy="15" r="15"/>
                <path d="M15 8 l5 5 h-3 v6 h-4 v-6 h-3 z" fill="#fff"/>
              </svg>
            </div>
          ) : (
            <div className="bob-mic-btn">
              <svg viewBox="0 0 16 18" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round">
                <rect x="5" y="1" width="6" height="10" rx="3"/>
                <path d="M2 8a6 6 0 0 0 12 0M8 14v3M5 17h6"/>
              </svg>
            </div>
          )}
        </div>
      </div>
    </div>
  );
}

(function injectPhoneStyles(){
  if (document.getElementById('phone-styles')) return;
  const css = `
    .phone-wrap{ position: relative; z-index: 20; will-change: transform; }
    .bob-shell{
      /* Explicit-size container clipped to the iPhone screen shape. The screen
         is 320x660 with 46px corners; we mirror that exactly so nothing in the
         chat surface can render outside the device frame. */
      position: absolute;
      top: 0; left: 0;
      width: 320px;
      height: 660px;
      display: flex; flex-direction: column;
      background: linear-gradient(135deg, #F5F1EA 0%, #ECE6DC 100%);
      overflow: hidden;
      border-radius: 46px;
      clip-path: inset(0 round 46px);
      contain: strict;
    }
    .bob-topchrome{
      display: flex; align-items: center; justify-content: space-between;
      padding: 54px 16px 8px;
      flex-shrink: 0;
    }
    .bob-icon-btn{
      width: 36px; height: 36px;
      display: flex; align-items: center; justify-content: center;
      background: rgba(250,250,250,0.9);
      border: 0.5px solid rgba(0,0,0,0.06);
      border-radius: 999px;
      color: #1F1A14;
      box-shadow: 0 1px 3px rgba(0,0,0,0.04);
    }
    .bob-icon-btn svg{ width: 18px; height: 18px; }
    .bob-titlestack{ display: inline-flex; align-items: center; gap: 4px; color: #1F1A14; }
    .bob-title{ font: 500 16px 'Inter', sans-serif; letter-spacing: -0.01em; }
    .bob-title-chev{ width: 9px; height: 5px; opacity: 0.55; }

    .bob-welcome{
      position: absolute; left: 0; right: 0;
      top: 48%; transform: translateY(-68%);
      display: flex; flex-direction: column;
      align-items: center; gap: 14px;
      padding: 0 30px;
      transition: opacity .35s ease;
      pointer-events: none;
      z-index: 1;
    }
    .bob-mark{
      color: #1F1A14;
      --dot: #C8102E;
      display: flex; align-items: center; justify-content: center;
    }
    .bob-glyph{ width: 58px; height: 58px; display: block; }
    .bob-glyph circle{ fill: var(--dot); }
    .bob-welcome-copy{
      font: 400 18px/1.45 'Source Serif 4', Georgia, serif;
      color: #1F1A14;
      letter-spacing: -0.005em;
      text-align: center;
      max-width: 22ch;
    }

    .bob-feed{
      flex: 1;
      display: flex; flex-direction: column;
      gap: 10px;
      padding: 12px 14px 4px;
      justify-content: flex-end;
      overflow: hidden;
      position: relative;
      z-index: 2;
    }
    .bob-row{ display: flex; }
    .bob-row.right{ justify-content: flex-end; padding-left: 32px; }
    .bob-row.left{ justify-content: flex-start; padding-right: 32px; }

    /* iMessage-style date separator. Sits above the first bubble, centered, mono. */
    .bob-date-sep{
      display: flex; justify-content: center; align-items: baseline; gap: 6px;
      font: 500 11px 'Inter', sans-serif;
      color: rgba(31, 26, 20, 0.42);
      letter-spacing: -0.005em;
      padding: 8px 0 4px;
      animation: dateSepIn .5s cubic-bezier(.2,.7,.3,1) backwards;
    }
    .bob-date-sep .bob-date-strong{
      font-weight: 600;
      color: rgba(31, 26, 20, 0.62);
    }
    @keyframes dateSepIn{
      from{ opacity: 0; }
      to{ opacity: 1; }
    }

    /* "Delivered" indicator. Right-aligned under the user bubble, very small. */
    .bob-delivered{
      align-self: flex-end;
      font: 500 10px 'Inter', sans-serif;
      color: rgba(31, 26, 20, 0.45);
      letter-spacing: 0.01em;
      padding: 0 4px;
      margin-top: -4px;
      animation: dateSepIn .35s cubic-bezier(.2,.7,.3,1) .15s backwards;
    }

    .bob-bubble{
      max-width: 230px;
      padding: 10px 14px;
      border-radius: 22px;
      font: 500 14px/1.5 'Inter', sans-serif;
      letter-spacing: -0.003em;
      word-wrap: break-word;
    }
    .bob-bubble.user{ background: #41B6E6; color: #fff; }
    .bob-bubble.user.pending{ opacity: 0.55; }
    .bob-bubble.bob{
      background: rgba(250,250,250,0.92);
      color: #1F1A14;
      font-family: 'Source Serif 4', Georgia, serif;
      font-weight: 400;
      font-size: 15.5px;
      line-height: 1.45;
      box-shadow: 0 1px 0 rgba(255,255,255,0.75) inset, 0 8px 18px rgba(31,26,20,0.05);
    }
    .bob-bubble-link{
      display: inline-block;
      margin-top: 4px;
      font-family: 'Inter', sans-serif;
      font-size: 13.5px;
      font-weight: 500;
      color: #41B6E6;
      letter-spacing: -0.005em;
    }
    .bob-bubble-link .arr{
      display: inline-block;
      transition: transform .2s ease;
    }

    .bob-typing{
      display: inline-flex; align-items: center; gap: 8px;
      padding: 10px 14px; border-radius: 22px;
      background: rgba(250,250,250,0.78);
      backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px);
      font: 500 13px 'Inter', sans-serif;
      color: #6B6258;
    }
    .bob-typing .spin{
      width: 12px; height: 12px;
      border: 1.6px solid rgba(107,98,88,0.25);
      border-top-color: #6B6258;
      border-radius: 50%;
      animation: bobSpin .9s linear infinite;
    }
    @keyframes bobSpin{ to{ transform: rotate(360deg); } }

    .bob-composer-wrap{
      display: flex; align-items: flex-end; gap: 8px;
      /* Bottom inset matches Swift bottomComposerInset = 30 + 8 home indicator clearance */
      padding: 6px 16px 38px;
      flex-shrink: 0;
      position: relative;
      z-index: 3;
    }
    .bob-plus{
      width: 36px; height: 36px;
      flex-shrink: 0;
      display: flex; align-items: center; justify-content: center;
      background: rgba(250,250,250,0.9);
      border: 0.5px solid rgba(0,0,0,0.06);
      border-radius: 999px;
      color: #1F1A14;
      box-shadow: 0 1px 3px rgba(0,0,0,0.05);
    }
    .bob-plus svg{ width: 14px; height: 14px; }
    .bob-composer-pill{
      flex: 1;
      min-width: 0;
      min-height: 36px;
      max-height: 100px;
      display: flex; align-items: center; gap: 4px;
      padding: 7px 6px 7px 16px;
      border-radius: 22px;
      background: rgba(250,250,250,0.95);
      border: 0.5px solid rgba(0,0,0,0.08);
      box-shadow: 0 4px 14px rgba(0,0,0,0.04);
      overflow: hidden;
    }
    .bob-composer-pill.focused{ border-color: rgba(65,182,230,0.4); }
    .bob-composer-text{
      flex: 1 1 0;
      min-width: 0;
      max-height: 86px;
      font: 400 15px/1.35 'Inter', sans-serif;
      color: #1F1A14;
      overflow: hidden;
      white-space: pre-wrap;
      word-break: break-word;
      padding: 0;
    }
    .bob-composer-prompt{ color: #A89E91; }
    .bob-mic-btn, .bob-send-btn{
      width: 32px; height: 32px;
      flex: 0 0 32px;
      align-self: flex-end;
      display: flex; align-items: center; justify-content: center;
      color: #1F1A14;
    }
    .bob-mic-btn svg{ width: 18px; height: 18px; }
    .bob-send-btn{ color: #41B6E6; }
    .bob-send-btn svg{ width: 30px; height: 30px; }

    .fade-in{ animation: bubbleIn .55s cubic-bezier(.2,.7,.3,1) backwards; }
    .fade-in.delay-1{ animation-delay: .25s; }
    .fade-in.delay-2{ animation-delay: .50s; }
    @keyframes bubbleIn{
      from{ opacity: 0; transform: translateY(8px) scale(.96); }
      to{ opacity: 1; transform: translateY(0) scale(1); }
    }
    /* User bubble pop: lifts up from the composer area into the thread.
       Slightly more emphatic than bob's fade-in because it's the moment of
       send — the user's intent landing. */
    .user-pop{ animation: userPop .42s cubic-bezier(.18,.84,.32,1.18) backwards; transform-origin: 95% 100%; }
    @keyframes userPop{
      from{ opacity: 0; transform: translateY(14px) scale(.82); }
      60% { opacity: 1; transform: translateY(-1px) scale(1.02); }
      to  { opacity: 1; transform: translateY(0) scale(1); }
    }
    .caret-blink{
      display: inline-block;
      animation: blink 1s steps(2) infinite;
      font-weight: 300; color: #41B6E6; margin-left: 1px;
    }
    @keyframes blink{ 0%, 50%{ opacity: 1; } 50.01%, 100%{ opacity: 0; } }
  `;
  const tag = document.createElement('style');
  tag.id = 'phone-styles';
  tag.textContent = css;
  document.head.appendChild(tag);
})();

window.Phone = Phone;
