<?xml version="1.0" encoding="UTF-8"?>
<mxfile host="drawio" version="30.2.4">
  <diagram id="architecture-poster" name="Runtime Architecture">
    <mxGraphModel dx="1600" dy="1000" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="1600" pageHeight="1000" math="0" shadow="0">
      <root>
        <mxCell id="0" />
        <mxCell id="1" parent="0" />
        <mxCell id="title" value="plex-tui runtime architecture&#xa;How launch, browsing, artwork, auth, and playback fit together" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f5f5f5;strokeColor=#666666;fontSize=22;fontStyle=1;align=center;verticalAlign=middle;" vertex="1" parent="1">
          <mxGeometry x="40" y="20" width="1470" height="70" as="geometry" />
        </mxCell>
        <mxCell id="user_lane" value="User &amp; entrypoints" style="swimlane;startSize=30;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;fontStyle=1;" vertex="1" parent="1">
          <mxGeometry x="40" y="120" width="250" height="640" as="geometry" />
        </mxCell>
        <mxCell id="core_lane" value="Textual app core" style="swimlane;startSize=30;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;fontStyle=1;" vertex="1" parent="1">
          <mxGeometry x="330" y="120" width="350" height="640" as="geometry" />
        </mxCell>
        <mxCell id="plex_lane" value="Plex integration" style="swimlane;startSize=30;whiteSpace=wrap;html=1;fillColor=#ffe6cc;strokeColor=#d79b00;fontStyle=1;" vertex="1" parent="1">
          <mxGeometry x="720" y="120" width="330" height="300" as="geometry" />
        </mxCell>
        <mxCell id="media_lane" value="Rendering &amp; playback" style="swimlane;startSize=30;whiteSpace=wrap;html=1;fillColor=#e1d5e7;strokeColor=#9673a6;fontStyle=1;" vertex="1" parent="1">
          <mxGeometry x="720" y="470" width="330" height="290" as="geometry" />
        </mxCell>
        <mxCell id="external_lane" value="External systems &amp; local files" style="swimlane;startSize=30;whiteSpace=wrap;html=1;fillColor=#f5f5f5;strokeColor=#666666;fontStyle=1;" vertex="1" parent="1">
          <mxGeometry x="1090" y="120" width="420" height="640" as="geometry" />
        </mxCell>
        <mxCell id="terminal" value="Terminal user&#xa;keyboard, env, shell" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" vertex="1" parent="user_lane">
          <mxGeometry x="40" y="70" width="170" height="70" as="geometry" />
        </mxCell>
        <mxCell id="cli" value="__main__.py&#xa;argparse entrypoint" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" vertex="1" parent="user_lane">
          <mxGeometry x="40" y="190" width="170" height="70" as="geometry" />
        </mxCell>
        <mxCell id="cli_helpers" value="Read-only CLI&#xa;status, libraries, continue watching, search" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" vertex="1" parent="user_lane">
          <mxGeometry x="40" y="310" width="170" height="90" as="geometry" />
        </mxCell>
        <mxCell id="tui_start" value="No command&#xa;start TUI" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" vertex="1" parent="user_lane">
          <mxGeometry x="40" y="470" width="170" height="70" as="geometry" />
        </mxCell>
        <mxCell id="app" value="PlexTuiApp&#xa;app.py owns screens, bindings, workers" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;fontStyle=1;" vertex="1" parent="core_lane">
          <mxGeometry x="70" y="70" width="210" height="80" as="geometry" />
        </mxCell>
        <mxCell id="views" value="Textual views&#xa;sidebar, media list/grid, details, footer, help" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" vertex="1" parent="core_lane">
          <mxGeometry x="70" y="200" width="210" height="90" as="geometry" />
        </mxCell>
        <mxCell id="browse_state" value="Browse state&#xa;page windows, selected item, search source, bulk selections" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" vertex="1" parent="core_lane">
          <mxGeometry x="70" y="340" width="210" height="90" as="geometry" />
        </mxCell>
        <mxCell id="workers" value="Textual workers &amp; timers&#xa;detail refresh, artwork prefetch, search, playback status" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" vertex="1" parent="core_lane">
          <mxGeometry x="70" y="480" width="210" height="90" as="geometry" />
        </mxCell>
        <mxCell id="config" value="AppConfig&#xa;defaults, env overrides, save/load" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#ffe6cc;strokeColor=#d79b00;" vertex="1" parent="plex_lane">
          <mxGeometry x="30" y="70" width="125" height="80" as="geometry" />
        </mxCell>
        <mxCell id="auth" value="LoginSession&#xa;OAuth, server choice, token save" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#ffe6cc;strokeColor=#d79b00;" vertex="1" parent="plex_lane">
          <mxGeometry x="175" y="70" width="125" height="80" as="geometry" />
        </mxCell>
        <mxCell id="service" value="PlexService&#xa;libraries, search, playlists, details" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#ffe6cc;strokeColor=#d79b00;fontStyle=1;" vertex="1" parent="plex_lane">
          <mxGeometry x="95" y="190" width="140" height="80" as="geometry" />
        </mxCell>
        <mxCell id="models" value="models.py&#xa;LibraryItem, MediaItem, MediaDetails" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#e1d5e7;strokeColor=#9673a6;" vertex="1" parent="media_lane">
          <mxGeometry x="25" y="65" width="130" height="80" as="geometry" />
        </mxCell>
        <mxCell id="artwork" value="artwork.py&#xa;fetch, cache, block art, Kitty/Ghostty" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#e1d5e7;strokeColor=#9673a6;" vertex="1" parent="media_lane">
          <mxGeometry x="175" y="65" width="130" height="80" as="geometry" />
        </mxCell>
        <mxCell id="player" value="player.py&#xa;stream URL, mpv launch, IPC controls, progress monitor" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#e1d5e7;strokeColor=#9673a6;" vertex="1" parent="media_lane">
          <mxGeometry x="95" y="180" width="150" height="80" as="geometry" />
        </mxCell>
        <mxCell id="files" value="Config, cache, debug log&#xa;config.toml, artwork cache, debug.log" style="shape=cylinder3;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" vertex="1" parent="external_lane">
          <mxGeometry x="40" y="65" width="145" height="95" as="geometry" />
        </mxCell>
        <mxCell id="browser" value="Browser + Plex account&#xa;OAuth login and server resources" style="rounded=1;whiteSpace=wrap;html=1;dashed=1;fillColor=#f5f5f5;strokeColor=#666666;" vertex="1" parent="external_lane">
          <mxGeometry x="235" y="75" width="145" height="75" as="geometry" />
        </mxCell>
        <mxCell id="plex_server" value="Plex Media Server&#xa;libraries, hubs, search, metadata, stream URLs" style="rounded=1;whiteSpace=wrap;html=1;dashed=1;fillColor=#f5f5f5;strokeColor=#666666;fontStyle=1;" vertex="1" parent="external_lane">
          <mxGeometry x="130" y="225" width="170" height="90" as="geometry" />
        </mxCell>
        <mxCell id="mpv" value="mpv process&#xa;external window or terminal video output" style="rounded=1;whiteSpace=wrap;html=1;dashed=1;fillColor=#f5f5f5;strokeColor=#666666;" vertex="1" parent="external_lane">
          <mxGeometry x="130" y="385" width="170" height="80" as="geometry" />
        </mxCell>
        <mxCell id="terminal_render" value="Terminal renderer&#xa;Textual/Rich UI; optional Kitty/Ghostty images" style="rounded=1;whiteSpace=wrap;html=1;dashed=1;fillColor=#f5f5f5;strokeColor=#666666;" vertex="1" parent="external_lane">
          <mxGeometry x="130" y="535" width="170" height="80" as="geometry" />
        </mxCell>
        <mxCell id="legend" value="Solid arrows: direct runtime calls or data flow&#xa;Dashed boxes: external systems/processes&#xa;Poster omits tests/release automation; this is the app runtime path" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;align=left;spacing=10;" vertex="1" parent="1">
          <mxGeometry x="40" y="800" width="1470" height="90" as="geometry" />
        </mxCell>
        <mxCell id="e1" value="launch" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;endArrow=block;" edge="1" parent="1" source="terminal" target="cli">
          <mxGeometry relative="1" as="geometry" />
        </mxCell>
        <mxCell id="e2" value="helper command" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;endArrow=block;" edge="1" parent="1" source="cli" target="cli_helpers">
          <mxGeometry relative="1" as="geometry" />
        </mxCell>
        <mxCell id="e3" value="no command" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;endArrow=block;exitX=1;exitY=0.5;entryX=1;entryY=0.5;" edge="1" parent="1" source="cli" target="tui_start">
          <mxGeometry relative="1" as="geometry">
            <Array as="points">
              <mxPoint x="310" y="345" />
              <mxPoint x="310" y="625" />
            </Array>
          </mxGeometry>
        </mxCell>
        <mxCell id="e4" value="run()" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;endArrow=block;exitX=1;exitY=0.5;entryX=0;entryY=0.5;" edge="1" parent="1" source="tui_start" target="app">
          <mxGeometry relative="1" as="geometry" />
        </mxCell>
        <mxCell id="e5" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;endArrow=block;exitX=1;exitY=0.5;entryX=0;entryY=0.5;" edge="1" parent="1" source="cli_helpers" target="service">
          <mxGeometry relative="1" as="geometry" />
        </mxCell>
        <mxCell id="e6" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;endArrow=block;" edge="1" parent="1" source="app" target="views">
          <mxGeometry relative="1" as="geometry" />
        </mxCell>
        <mxCell id="e7" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;endArrow=block;" edge="1" parent="1" source="views" target="browse_state">
          <mxGeometry relative="1" as="geometry" />
        </mxCell>
        <mxCell id="e8" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;endArrow=block;" edge="1" parent="1" source="app" target="workers">
          <mxGeometry relative="1" as="geometry" />
        </mxCell>
        <mxCell id="e9" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;endArrow=block;exitX=1;exitY=0.25;entryX=0;entryY=0.5;" edge="1" parent="1" source="app" target="config">
          <mxGeometry relative="1" as="geometry" />
        </mxCell>
        <mxCell id="e10" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;endArrow=block;exitX=1;exitY=0.2;entryX=0;entryY=0.5;" edge="1" parent="1" source="app" target="auth">
          <mxGeometry relative="1" as="geometry" />
        </mxCell>
        <mxCell id="e11" value="browse/search/playlists" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;endArrow=block;exitX=1;exitY=0.5;entryX=0;entryY=0.5;" edge="1" parent="1" source="app" target="service">
          <mxGeometry relative="1" as="geometry" />
        </mxCell>
        <mxCell id="e12" value="OAuth URL" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;endArrow=block;exitX=1;exitY=0;entryX=0;entryY=0.5;" edge="1" parent="1" source="auth" target="browser">
          <mxGeometry relative="1" as="geometry">
            <Array as="points">
              <mxPoint x="1060" y="155" />
              <mxPoint x="1290" y="155" />
            </Array>
          </mxGeometry>
        </mxCell>
        <mxCell id="e13" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;endArrow=block;exitX=0.5;exitY=1;entryX=0.5;entryY=1;" edge="1" parent="1" source="auth" target="config">
          <mxGeometry relative="1" as="geometry">
            <Array as="points">
              <mxPoint x="957" y="300" />
              <mxPoint x="813" y="300" />
            </Array>
          </mxGeometry>
        </mxCell>
        <mxCell id="e15" value="PlexAPI calls" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;endArrow=block;exitX=1;exitY=0.5;entryX=0;entryY=0.5;" edge="1" parent="1" source="service" target="plex_server">
          <mxGeometry relative="1" as="geometry" />
        </mxCell>
        <mxCell id="e16" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;endArrow=block;exitX=0.5;exitY=1;entryX=0.5;entryY=0;" edge="1" parent="1" source="service" target="models">
          <mxGeometry relative="1" as="geometry" />
        </mxCell>
        <mxCell id="e17" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;endArrow=block;exitX=0;exitY=0.5;entryX=1;entryY=0.65;" edge="1" parent="1" source="models" target="app">
          <mxGeometry relative="1" as="geometry" />
        </mxCell>
        <mxCell id="e18" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;endArrow=block;exitX=1;exitY=0.75;entryX=0;entryY=0.5;" edge="1" parent="1" source="app" target="artwork">
          <mxGeometry relative="1" as="geometry" />
        </mxCell>
        <mxCell id="e19" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;endArrow=block;exitX=1;exitY=0.35;entryX=0;entryY=0.75;" edge="1" parent="1" source="artwork" target="plex_server">
          <mxGeometry relative="1" as="geometry" />
        </mxCell>
        <mxCell id="e21" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;endArrow=block;exitX=1;exitY=0.8;entryX=0;entryY=0.5;" edge="1" parent="1" source="artwork" target="terminal_render">
          <mxGeometry relative="1" as="geometry" />
        </mxCell>
        <mxCell id="e22" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;endArrow=block;exitX=1;exitY=0.85;entryX=0;entryY=0.5;" edge="1" parent="1" source="app" target="player">
          <mxGeometry relative="1" as="geometry" />
        </mxCell>
        <mxCell id="e23" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;endArrow=block;exitX=1;exitY=0.25;entryX=0;entryY=0.85;" edge="1" parent="1" source="player" target="plex_server">
          <mxGeometry relative="1" as="geometry" />
        </mxCell>
        <mxCell id="e24" value="mpv IPC" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;endArrow=block;exitX=1;exitY=0.5;entryX=0;entryY=0.5;" edge="1" parent="1" source="player" target="mpv">
          <mxGeometry relative="1" as="geometry" />
        </mxCell>
        <mxCell id="e25" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;endArrow=block;dashed=1;exitX=0;exitY=0.65;entryX=1;entryY=0.9;" edge="1" parent="1" source="mpv" target="app">
          <mxGeometry relative="1" as="geometry" />
        </mxCell>
      </root>
    </mxGraphModel>
  </diagram>
</mxfile>
