Ctrl K
ComunidadGuías…

project/prototypes/artifact-server-ui-atlas.html

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
<!doctype html>
<html lang="en" class="dark">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Artifact Server · UI Atlas</title>
  <style>
    :root {
      --bg: #fafafa;
      --fg: #161616;
      --panel: #ffffff;
      --muted: #f2f2f3;
      --muted-fg: #68686f;
      --border: #dcdce0;
      --input: #cfcfd4;
      --primary: #5b4fe8;
      --primary-fg: #ffffff;
      --danger: #c9363e;
      --success: #147d56;
      --warning: #a25d0c;
      --catalog-bg: #ececef;
      --catalog-fg: #242428;
      --catalog-border: #d0d0d5;
      --shadow: 0 18px 60px rgba(0,0,0,.2);
      color-scheme: light;
    }

    html.dark {
      --bg: #09090b;
      --fg: #f4f4f5;
      --panel: #0d0d10;
      --muted: #18181b;
      --muted-fg: #a1a1aa;
      --border: #2b2b31;
      --input: #36363e;
      --primary: #8b80f9;
      --primary-fg: #111014;
      --danger: #fb7185;
      --success: #50d19b;
      --warning: #f0ae55;
      --catalog-bg: #18181b;
      --catalog-fg: #f4f4f5;
      --catalog-border: #303037;
      --shadow: 0 22px 70px rgba(0,0,0,.5);
      color-scheme: dark;
    }

    * { box-sizing: border-box; }
    html, body { margin: 0; min-height: 100%; }
    body {
      background: var(--bg);
      color: var(--fg);
      font-family: Geist, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
      font-size: 14px;
      -webkit-font-smoothing: antialiased;
    }
    button, input, select, textarea { font: inherit; }
    button, a, select { -webkit-tap-highlight-color: transparent; }
    a { color: inherit; text-decoration: none; }
    button { color: inherit; }
    button:focus-visible, a:focus-visible, select:focus-visible, input:focus-visible {
      outline: 2px solid color-mix(in srgb, var(--primary) 70%, transparent);
      outline-offset: 2px;
    }
    [hidden] { display: none !important; }

    /* Review harness chrome, deliberately separate from the product UI. */
    .atlas-bar {
      position: fixed;
      inset: 0 0 auto 0;
      z-index: 10000;
      height: 52px;
      display: flex;
      align-items: center;
      gap: 16px;
      padding: 0 18px;
      border-bottom: 1px solid var(--catalog-border);
      background: color-mix(in srgb, var(--catalog-bg) 92%, transparent);
      color: var(--catalog-fg);
      -webkit-backdrop-filter: blur(18px);
      backdrop-filter: blur(18px);
      font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
    }
    .atlas-id { display: flex; align-items: center; gap: 10px; min-width: 222px; }
    .atlas-mark { width: 8px; height: 8px; background: #7d70f4; box-shadow: 9px 0 0 #7d70f4; }
    .atlas-id strong { font-size: 13px; letter-spacing: -.01em; }
    .atlas-id span { color: color-mix(in srgb, var(--catalog-fg) 55%, transparent); font: 10px ui-monospace, monospace; letter-spacing: .13em; text-transform: uppercase; }
    .atlas-modes { display: flex; align-self: stretch; }
    .atlas-mode {
      border: 0;
      border-bottom: 2px solid transparent;
      background: transparent;
      padding: 0 14px;
      color: color-mix(in srgb, var(--catalog-fg) 58%, transparent);
      cursor: pointer;
      font-size: 12px;
      font-weight: 650;
    }
    .atlas-mode:hover { color: var(--catalog-fg); }
    .atlas-mode[data-active] { border-bottom-color: #7d70f4; color: var(--catalog-fg); }
    .atlas-page-nav { display: flex; align-items: center; gap: 6px; min-width: 0; overflow-x: auto; scrollbar-width: none; }
    .atlas-page-nav::-webkit-scrollbar { display: none; }
    .atlas-page {
      flex: none;
      height: 30px;
      border: 1px solid transparent;
      background: transparent;
      padding: 0 9px;
      color: color-mix(in srgb, var(--catalog-fg) 56%, transparent);
      cursor: pointer;
      font-size: 11px;
    }
    .atlas-page:hover { color: var(--catalog-fg); }
    .atlas-page[data-active] { border-color: var(--catalog-border); background: color-mix(in srgb, var(--catalog-fg) 7%, transparent); color: var(--catalog-fg); }
    .atlas-count { margin-left: auto; flex: none; color: color-mix(in srgb, var(--catalog-fg) 45%, transparent); font: 10px ui-monospace, monospace; }
    .atlas-stage { min-height: 100vh; padding-top: 52px; }

    /* Shared product system, matched to apps/web. */
    .product-shell { min-height: calc(100vh - 52px); background: var(--bg); color: var(--fg); }
    .app-header { border-bottom: 1px solid var(--border); background: var(--bg); }
    .app-header-inner {
      width: min(100%, 1280px);
      min-height: 70px;
      margin: 0 auto;
      padding: 15px 32px;
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: 28px;
    }
    .app-brand-row, .app-user-row, .app-nav, .row { display: flex; align-items: center; }
    .app-brand-row { gap: 20px; min-width: 0; }
    .app-brand { font-family: "Noto Sans", -apple-system, sans-serif; font-weight: 700; letter-spacing: -.025em; white-space: nowrap; }
    .divider-v { width: 1px; height: 20px; flex: none; background: var(--border); }
    .project-picker {
      width: 190px;
      height: 36px;
      border: 1px solid var(--input);
      border-radius: 0;
      padding: 0 34px 0 12px;
      background: var(--bg);
      color: var(--fg);
      appearance: auto;
    }
    .app-nav { gap: 2px; }
    .nav-link, .btn {
      min-height: 34px;
      border: 1px solid transparent;
      border-radius: 0;
      background: transparent;
      padding: 0 12px;
      display: inline-flex;
      align-items: center;
      justify-content: center;
      gap: 7px;
      font-size: 12px;
      font-weight: 650;
      line-height: 1;
      cursor: pointer;
      white-space: nowrap;
    }
    .nav-link { color: var(--muted-fg); }
    .nav-link:hover, .nav-link.active { background: var(--muted); color: var(--fg); }
    .btn { border-color: var(--input); background: var(--bg); }
    .btn:hover { background: var(--muted); }
    .btn.primary { border-color: var(--primary); background: var(--primary); color: var(--primary-fg); }
    .btn.primary:hover { filter: brightness(1.05); }
    .btn.ghost { border-color: transparent; }
    .btn.danger { border-color: color-mix(in srgb, var(--danger) 45%, var(--border)); color: var(--danger); }
    .btn.sm { min-height: 30px; padding-inline: 9px; font-size: 11px; }
    .btn.icon { width: 34px; padding: 0; }
    .user-meta { min-width: 0; text-align: right; }
    .user-id { max-width: 150px; overflow: hidden; text-overflow: ellipsis; font: 11px ui-monospace, SFMono-Regular, Menlo, monospace; white-space: nowrap; }
    .user-role { margin-top: 3px; color: var(--muted-fg); font-size: 11px; text-transform: capitalize; }
    .badge {
      display: inline-flex;
      align-items: center;
      min-height: 24px;
      border: 1px solid var(--border);
      padding: 2px 8px;
      color: var(--muted-fg);
      font: 10px ui-monospace, SFMono-Regular, Menlo, monospace;
      letter-spacing: .08em;
      text-transform: uppercase;
      white-space: nowrap;
    }
    .badge.primary { border-color: color-mix(in srgb, var(--primary) 45%, var(--border)); background: color-mix(in srgb, var(--primary) 9%, transparent); color: var(--primary); }
    .badge.success { border-color: color-mix(in srgb, var(--success) 38%, var(--border)); color: var(--success); }
    .badge.warning { border-color: color-mix(in srgb, var(--warning) 40%, var(--border)); color: var(--warning); }
    .badge.danger { border-color: color-mix(in srgb, var(--danger) 40%, var(--border)); color: var(--danger); }
    .main { width: min(100%, 1280px); margin: 0 auto; padding: 44px 32px 84px; }
    .stack { display: flex; flex-direction: column; gap: 32px; }
    .page-header { display: flex; align-items: flex-end; justify-content: space-between; gap: 28px; border-bottom: 1px solid var(--border); padding-bottom: 28px; }
    .eyebrow { margin: 0 0 10px; color: var(--primary); font: 700 11px ui-monospace, SFMono-Regular, Menlo, monospace; letter-spacing: .18em; text-transform: uppercase; }
    h1, h2, h3, p { margin-top: 0; }
    h1, h2, h3 { font-family: "Noto Sans", -apple-system, BlinkMacSystemFont, sans-serif; }
    h1 { margin-bottom: 8px; font-size: clamp(29px, 3vw, 42px); line-height: 1.08; letter-spacing: -.04em; }
    h2 { margin-bottom: 8px; font-size: 18px; letter-spacing: -.025em; }
    h3 { margin-bottom: 6px; font-size: 14px; letter-spacing: -.015em; }
    .lede { max-width: 760px; margin: 0; color: var(--muted-fg); line-height: 1.65; }
    .header-actions { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 8px; }
    .panel { border: 1px solid var(--border); background: var(--bg); }
    .panel-pad { padding: 22px; }
    .muted { color: var(--muted-fg); }
    .mono { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; }
    .tiny { font-size: 11px; }
    .small { font-size: 12px; }
    .text-link { color: var(--primary); cursor: pointer; }
    .text-link:hover { text-decoration: underline; }
    .filter-bar { display: flex; align-items: end; gap: 12px; padding-bottom: 20px; border-bottom: 1px solid var(--border); }
    .field { display: grid; gap: 7px; }
    .field.grow { flex: 1; }
    .label { font-size: 12px; font-weight: 650; }
    .input {
      width: 100%; height: 38px; border: 1px solid var(--input); border-radius: 0; background: var(--bg); color: var(--fg); padding: 0 11px;
    }
    .input::placeholder { color: color-mix(in srgb, var(--muted-fg) 70%, transparent); }
    .table-wrap { overflow-x: auto; border: 1px solid var(--border); }
    table { width: 100%; border-collapse: collapse; text-align: left; }
    th { height: 42px; padding: 0 15px; border-bottom: 1px solid var(--border); background: color-mix(in srgb, var(--muted) 62%, transparent); color: var(--muted-fg); font-size: 10px; letter-spacing: .15em; text-transform: uppercase; white-space: nowrap; }
    td { padding: 16px 15px; border-bottom: 1px solid var(--border); vertical-align: top; }
    tr:last-child td { border-bottom: 0; }
    tbody tr:hover { background: color-mix(in srgb, var(--muted) 46%, transparent); }
    .td-title { margin-bottom: 6px; font-family: "Noto Sans", sans-serif; font-weight: 700; }
    .tag-row, .action-row { display: flex; flex-wrap: wrap; gap: 7px; }
    .action-row { justify-content: flex-end; }
    .projects-grid { display: grid; grid-template-columns: repeat(2, minmax(0,1fr)); border: 1px solid var(--border); }
    .project-card { min-width: 0; padding: 22px; border-right: 1px solid var(--border); border-bottom: 1px solid var(--border); }
    .project-card:nth-child(2n) { border-right: 0; }
    .project-card:nth-last-child(-n+2) { border-bottom: 0; }
    .project-top { display: flex; align-items: flex-start; justify-content: space-between; gap: 18px; }
    .git-block { margin-top: 20px; padding-top: 17px; border-top: 1px solid var(--border); }
    .git-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
    .git-actions { margin-top: 13px; }
    .tabs { display: flex; gap: 2px; border-bottom: 1px solid var(--border); overflow-x: auto; }
    .tab { position: relative; min-height: 40px; border: 0; background: transparent; color: var(--muted-fg); padding: 0 13px; cursor: pointer; font-size: 12px; font-weight: 650; white-space: nowrap; }
    .tab.active { color: var(--fg); }
    .tab.active::after { content: ""; position: absolute; inset: auto 8px -1px; height: 2px; background: var(--primary); }
    .detail-grid { display: grid; grid-template-columns: minmax(0,1fr) 320px; gap: 32px; padding-top: 24px; }
    .section-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 18px; }
    .meta { margin: 0; }
    .meta-row { display: grid; grid-template-columns: 160px minmax(0,1fr); gap: 18px; padding: 12px 0; border-top: 1px solid var(--border); }
    .meta-row dt { color: var(--muted-fg); font-size: 12px; }
    .meta-row dd { min-width: 0; margin: 0; }
    .manage-stack { display: grid; gap: 10px; }
    .manage-stack .btn { width: 100%; }
    .version-list { border: 1px solid var(--border); }
    .version-row { display: grid; grid-template-columns: 1fr auto; gap: 16px; padding: 18px; border-bottom: 1px solid var(--border); }
    .version-row:last-child { border-bottom: 0; }
    .review-canvas { display: grid; grid-template-columns: minmax(0,1fr) 360px; min-height: 580px; border: 1px solid var(--border); }
    .artifact-preview { overflow: hidden; background: #f4f2ed; color: #171719; }
    .preview-top { height: 50px; display: flex; align-items: center; justify-content: space-between; padding: 0 24px; border-bottom: 1px solid #d6d2c9; background: #fff; font-size: 12px; }
    .preview-body { padding: 54px 56px; }
    .preview-kicker { color: #6659d9; font: 700 10px ui-monospace, monospace; letter-spacing: .16em; text-transform: uppercase; }
    .preview-title { max-width: 640px; margin: 16px 0 22px; font: 650 clamp(34px, 5vw, 68px)/.98 Georgia, serif; letter-spacing: -.045em; }
    .preview-copy { max-width: 590px; color: #5d5b58; font-size: 16px; line-height: 1.65; }
    .preview-grid { display: grid; grid-template-columns: repeat(3,1fr); margin-top: 44px; border: 1px solid #d6d2c9; background: #fff; }
    .preview-card { min-height: 120px; padding: 20px; border-right: 1px solid #d6d2c9; }
    .preview-card:last-child { border: 0; }
    .comment-rail { display: flex; flex-direction: column; border-left: 1px solid var(--border); background: var(--bg); }
    .comment-head { display: flex; align-items: center; justify-content: space-between; padding: 15px; border-bottom: 1px solid var(--border); }
    .comment-list { display: grid; gap: 0; overflow: auto; }
    .comment { padding: 17px; border-bottom: 1px solid var(--border); }
    .comment-meta { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-bottom: 10px; }
    .comment p { margin: 0; line-height: 1.55; }
    .avatar { width: 26px; height: 26px; display: inline-grid; place-items: center; background: var(--muted); border: 1px solid var(--border); font-size: 10px; font-weight: 700; }
    .bulk-bar { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 12px; padding: 15px; border: 1px solid var(--border); }
    .check { width: 15px; height: 15px; accent-color: var(--primary); }
    .signin { min-height: calc(100vh - 52px); display: grid; place-items: center; padding: 24px; background: var(--bg); }
    .signin-card { width: min(100%, 520px); padding: 34px; border: 1px solid var(--border); }
    .signin-card h1 { margin-top: 10px; }
    .signin-card .btn { margin-top: 22px; }
    .notice { border: 1px solid color-mix(in srgb, var(--primary) 35%, var(--border)); background: color-mix(in srgb, var(--primary) 7%, transparent); padding: 15px; line-height: 1.55; }
    .secret-prefix { display: block; max-width: 230px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

    /* Lightweight dialog behavior for the mockups. */
    .dialog-layer { position: fixed; inset: 52px 0 0; z-index: 20000; display: none; place-items: center; padding: 24px; background: rgba(0,0,0,.64); }
    .dialog-layer.open { display: grid; }
    .dialog { width: min(100%, 520px); max-height: min(760px, calc(100vh - 100px)); overflow: auto; border: 1px solid var(--border); background: var(--bg); padding: 24px; box-shadow: var(--shadow); }
    .dialog h2 { font-size: 22px; }
    .dialog p { color: var(--muted-fg); line-height: 1.6; }
    .dialog-form { display: grid; gap: 16px; margin: 22px 0; }
    .dialog-footer { display: flex; justify-content: flex-end; gap: 8px; padding-top: 18px; border-top: 1px solid var(--border); }
    .capability { display: grid; grid-template-columns: auto 1fr; gap: 10px; border: 1px solid var(--border); padding: 12px; }

    /* Three intentionally structural shell directions. */
    .direction-stage { min-height: calc(100vh - 52px); }
    .direction-note { color: var(--muted-fg); font-size: 12px; line-height: 1.55; }
    .rail-shell { min-height: calc(100vh - 52px); display: grid; grid-template-columns: 248px minmax(0,1fr); }
    .rail-sidebar { position: sticky; top: 52px; height: calc(100vh - 52px); display: flex; flex-direction: column; border-right: 1px solid var(--border); background: var(--bg); }
    .rail-brand { height: 70px; display: flex; align-items: center; padding: 0 21px; border-bottom: 1px solid var(--border); font-family: "Noto Sans", sans-serif; font-weight: 700; }
    .rail-project { margin: 17px; padding: 13px; border: 1px solid var(--border); }
    .rail-project small { display: block; margin-bottom: 6px; color: var(--muted-fg); font: 9px ui-monospace, monospace; letter-spacing: .15em; text-transform: uppercase; }
    .side-nav { display: grid; gap: 3px; padding: 0 11px; }
    .side-label { margin: 20px 10px 7px; color: var(--muted-fg); font: 9px ui-monospace, monospace; letter-spacing: .16em; text-transform: uppercase; }
    .side-link { display: flex; align-items: center; gap: 11px; min-height: 38px; padding: 0 10px; color: var(--muted-fg); font-size: 12px; font-weight: 600; }
    .side-link.active { background: var(--muted); color: var(--fg); }
    .side-link svg { width: 15px; height: 15px; }
    .rail-user { margin-top: auto; padding: 16px 18px; border-top: 1px solid var(--border); }
    .rail-top { min-height: 70px; display: flex; align-items: center; justify-content: space-between; padding: 0 32px; border-bottom: 1px solid var(--border); }
    .rail-main { min-width: 0; }
    .rail-content { padding: 38px 32px 90px; }
    .shell-content { width: min(100%, 1120px); margin: 0 auto; }

    .layer-global { min-height: 44px; display: flex; align-items: center; justify-content: space-between; padding: 0 28px; border-bottom: 1px solid var(--border); background: color-mix(in srgb, var(--muted) 48%, var(--bg)); }
    .layer-global .row { gap: 16px; }
    .layer-project { min-height: 66px; display: flex; align-items: center; justify-content: space-between; padding: 0 28px; border-bottom: 1px solid var(--border); }
    .layer-project-name { display: flex; align-items: baseline; gap: 12px; font-family: "Noto Sans", sans-serif; font-size: 18px; font-weight: 700; }
    .layer-project-name small { color: var(--muted-fg); font: 10px ui-monospace, monospace; letter-spacing: .1em; text-transform: uppercase; }
    .layer-tabs { display: flex; align-self: stretch; }
    .layer-tab { position: relative; display: flex; align-items: center; padding: 0 16px; color: var(--muted-fg); font-size: 12px; font-weight: 650; }
    .layer-tab.active { color: var(--fg); }
    .layer-tab.active::after { content: ""; position: absolute; inset: auto 14px -1px; height: 2px; background: var(--primary); }

    .dock-shell { min-height: calc(100vh - 52px); display: grid; grid-template-columns: 58px 218px minmax(0,1fr); }
    .icon-dock { position: sticky; top: 52px; height: calc(100vh - 52px); display: flex; flex-direction: column; align-items: center; padding: 12px 0; border-right: 1px solid var(--border); background: color-mix(in srgb, var(--muted) 45%, var(--bg)); }
    .dock-logo { width: 34px; height: 34px; display: grid; place-items: center; margin-bottom: 18px; border: 1px solid var(--border); font: 800 12px "Noto Sans", sans-serif; }
    .dock-icon { width: 38px; height: 38px; display: grid; place-items: center; margin-bottom: 5px; border: 0; background: transparent; color: var(--muted-fg); }
    .dock-icon.active { background: var(--bg); color: var(--fg); box-shadow: 0 0 0 1px var(--border) inset; }
    .dock-icon svg { width: 16px; height: 16px; }
    .dock-bottom { margin-top: auto; }
    .context-rail { position: sticky; top: 52px; height: calc(100vh - 52px); display: flex; flex-direction: column; border-right: 1px solid var(--border); }
    .context-head { padding: 22px 18px 18px; border-bottom: 1px solid var(--border); }
    .context-head small { color: var(--muted-fg); font: 9px ui-monospace, monospace; letter-spacing: .14em; text-transform: uppercase; }
    .context-head h2 { margin: 7px 0 2px; }
    .context-list { display: grid; padding: 12px 9px; }
    .context-link { min-height: 37px; display: flex; align-items: center; justify-content: space-between; padding: 0 10px; color: var(--muted-fg); font-size: 12px; }
    .context-link.active { background: var(--muted); color: var(--fg); }
    .count { min-width: 22px; padding: 2px 5px; border: 1px solid var(--border); text-align: center; font: 9px ui-monospace, monospace; }
    .dock-main { min-width: 0; }
    .dock-top { height: 62px; display: flex; align-items: center; justify-content: space-between; padding: 0 28px; border-bottom: 1px solid var(--border); }
    .crumbs { color: var(--muted-fg); font-size: 12px; }
    .crumbs strong { color: var(--fg); }
    .dock-content { padding: 34px 28px 90px; }

    /* Artifact Stage: one viewer shell, shown in three meaningful states. */
    .viewer-shell {
      position: relative;
      height: calc(100vh - 52px);
      min-height: 560px;
      overflow: hidden;
      display: flex;
      flex-direction: column;
      background: #e8e5de;
      color: #171719;
    }
    .viewer-toolbar {
      position: relative;
      z-index: 20;
      height: 44px;
      flex: 0 0 44px;
      display: grid;
      grid-template-columns: minmax(0,1fr) auto minmax(0,1fr);
      align-items: center;
      gap: 12px;
      padding: 0 9px;
      border-bottom: 1px solid var(--border);
      background: color-mix(in srgb, var(--bg) 94%, transparent);
      color: var(--fg);
      -webkit-backdrop-filter: blur(16px);
      backdrop-filter: blur(16px);
    }
    .viewer-toolbar-left,
    .viewer-toolbar-center,
    .viewer-toolbar-right { display: flex; align-items: center; min-width: 0; }
    .viewer-toolbar-left { gap: 4px; }
    .viewer-toolbar-center { justify-content: center; gap: 8px; }
    .viewer-toolbar-right { justify-content: flex-end; gap: 3px; }
    .viewer-title-block { min-width: 0; display: flex; align-items: baseline; gap: 8px; }
    .viewer-title {
      overflow: hidden;
      color: var(--fg);
      font-size: 12px;
      font-weight: 680;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
    .viewer-project { color: var(--muted-fg); font-size: 11px; white-space: nowrap; }
    .viewer-icon {
      position: relative;
      width: 32px;
      height: 32px;
      flex: none;
      display: inline-grid;
      place-items: center;
      border: 1px solid transparent;
      background: transparent;
      color: var(--muted-fg);
      cursor: pointer;
    }
    .viewer-icon:hover { background: var(--muted); color: var(--fg); }
    .viewer-icon.active { border-color: var(--border); background: var(--muted); color: var(--fg); }
    .viewer-icon svg { width: 16px; height: 16px; }
    .viewer-icon .control-count {
      position: absolute;
      top: 1px;
      right: 0;
      min-width: 14px;
      height: 14px;
      padding: 0 3px;
      display: grid;
      place-items: center;
      border: 1px solid var(--bg);
      background: var(--primary);
      color: var(--primary-fg);
      font: 700 8px ui-monospace, monospace;
    }
    .viewer-version {
      min-height: 25px;
      display: inline-flex;
      align-items: center;
      gap: 6px;
      padding: 0 8px;
      border: 1px solid var(--border);
      background: var(--bg);
      color: var(--muted-fg);
      font: 10px ui-monospace, monospace;
      white-space: nowrap;
    }
    .viewer-version strong { color: var(--fg); font-weight: 700; }
    .viewer-drift {
      min-height: 25px;
      display: inline-flex;
      align-items: center;
      gap: 6px;
      padding: 0 8px;
      border: 1px solid color-mix(in srgb, var(--warning) 40%, var(--border));
      color: var(--warning);
      font-size: 10px;
      white-space: nowrap;
    }
    .viewer-drift::before { content: ""; width: 5px; height: 5px; background: currentColor; border-radius: 50%; }
    .viewer-body { position: relative; min-height: 0; flex: 1; display: grid; grid-template-columns: minmax(0,1fr); }
    .viewer-body.comments-open { grid-template-columns: minmax(0,1fr) 352px; }
    .viewer-body.versions-open { grid-template-columns: 304px minmax(0,1fr); }
    .viewer-surface { position: relative; min-width: 0; min-height: 0; overflow: hidden; background: #e8e5de; }
    .viewer-document {
      height: 100%;
      overflow: auto;
      padding: clamp(42px, 7vh, 76px) clamp(28px, 7vw, 110px) 110px;
      background: #f1eee7;
      color: #171719;
      scrollbar-color: #bdb8ad transparent;
    }
    .document-masthead {
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: 20px;
      padding-bottom: 18px;
      border-bottom: 1px solid #cbc6bb;
      font: 700 10px ui-monospace, monospace;
      letter-spacing: .15em;
      text-transform: uppercase;
    }
    .document-masthead span:last-child { color: #77736b; font-weight: 500; }
    .document-kicker {
      margin: clamp(46px, 8vh, 86px) 0 16px;
      color: #6659d9;
      font: 700 10px ui-monospace, monospace;
      letter-spacing: .18em;
      text-transform: uppercase;
    }
    .document-title {
      max-width: 940px;
      margin: 0;
      font: 650 clamp(46px, 7vw, 104px)/.92 Georgia, "Times New Roman", serif;
      letter-spacing: -.055em;
    }
    .document-intro {
      max-width: 700px;
      margin: 32px 0 0;
      color: #5d5a54;
      font-size: clamp(16px, 1.55vw, 22px);
      line-height: 1.55;
    }
    .document-process {
      display: grid;
      grid-template-columns: repeat(3,minmax(0,1fr));
      margin-top: clamp(58px, 10vh, 112px);
      border: 1px solid #cbc6bb;
      background: #f8f6f1;
    }
    .document-step { min-height: 170px; padding: 24px; border-right: 1px solid #cbc6bb; }
    .document-step:last-child { border-right: 0; }
    .document-step > span { color: #77736b; font: 10px ui-monospace, monospace; }
    .document-step h3 { margin: 46px 0 8px; font: 650 18px Georgia, serif; }
    .document-step p { margin: 0; color: #6b675f; font-size: 13px; line-height: 1.5; }
    .annotation-pin {
      position: absolute;
      z-index: 8;
      width: 28px;
      height: 28px;
      display: grid;
      place-items: center;
      border: 2px solid #fff;
      border-radius: 50%;
      background: #6759df;
      color: #fff;
      box-shadow: 0 3px 14px rgba(35,28,92,.3);
      font: 700 10px ui-monospace, monospace;
      cursor: pointer;
    }
    .annotation-pin.one { top: 34%; left: 54%; }
    .annotation-pin.two { top: 71%; left: 29%; }
    .annotation-pin.three { top: 76%; left: 69%; }
    .viewer-panel {
      min-width: 0;
      min-height: 0;
      display: flex;
      flex-direction: column;
      background: var(--bg);
      color: var(--fg);
    }
    .comments-panel { border-left: 1px solid var(--border); }
    .versions-panel { border-right: 1px solid var(--border); }
    .viewer-panel-header {
      min-height: 48px;
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: 12px;
      padding: 0 12px 0 16px;
      border-bottom: 1px solid var(--border);
    }
    .viewer-panel-header h2 { margin: 0; font-size: 13px; }
    .viewer-panel-scroll { min-height: 0; overflow: auto; }
    .viewer-panel-section { padding: 15px 16px 9px; color: var(--muted-fg); font: 700 9px ui-monospace, monospace; letter-spacing: .15em; text-transform: uppercase; }
    .viewer-comment { padding: 16px; border-bottom: 1px solid var(--border); }
    .viewer-comment.selected { box-shadow: 3px 0 0 var(--primary) inset; background: color-mix(in srgb, var(--primary) 7%, transparent); }
    .viewer-comment p { margin: 10px 0 0; color: var(--fg); font-size: 12px; line-height: 1.55; }
    .viewer-comment-location { margin-top: 11px; color: var(--muted-fg); font-size: 10px; }
    .viewer-compose { margin-top: auto; padding: 12px; border-top: 1px solid var(--border); }
    .viewer-compose textarea { width: 100%; min-height: 66px; resize: vertical; border: 1px solid var(--input); background: var(--bg); color: var(--fg); padding: 9px; }
    .viewer-compose-actions { display: flex; justify-content: flex-end; gap: 6px; margin-top: 8px; }
    .artifact-jump,
    .version-jump {
      width: 100%;
      min-height: 43px;
      display: grid;
      grid-template-columns: minmax(0,1fr) auto;
      align-items: center;
      gap: 12px;
      border: 0;
      border-bottom: 1px solid var(--border);
      background: transparent;
      color: var(--fg);
      padding: 8px 16px;
      text-align: left;
      cursor: pointer;
    }
    .artifact-jump:hover,
    .version-jump:hover { background: var(--muted); }
    .artifact-jump.active,
    .version-jump.active { box-shadow: 3px 0 0 var(--primary) inset; background: color-mix(in srgb, var(--primary) 7%, transparent); }
    .jump-name { display: block; overflow: hidden; font-size: 12px; font-weight: 650; text-overflow: ellipsis; white-space: nowrap; }
    .jump-meta { display: block; margin-top: 3px; color: var(--muted-fg); font: 9px ui-monospace, monospace; }
    .jump-count { color: var(--muted-fg); font: 9px ui-monospace, monospace; }
    .focus-return {
      position: absolute;
      z-index: 40;
      top: 10px;
      right: 10px;
      display: none;
      min-height: 32px;
      border: 1px solid rgba(255,255,255,.2);
      background: rgba(10,10,12,.78);
      color: #fff;
      padding: 0 10px;
      font-size: 11px;
      cursor: pointer;
      -webkit-backdrop-filter: blur(10px);
      backdrop-filter: blur(10px);
    }
    .viewer-shell.focus .viewer-toolbar,
    .viewer-shell.focus .viewer-panel { display: none; }
    .viewer-shell.focus .viewer-body { grid-template-columns: minmax(0,1fr); }
    .viewer-shell.focus .focus-return { display: inline-flex; align-items: center; }

    /* Prototype picker: canonical harness chrome. */
    .proto-picker {
      position: fixed;
      bottom: 24px;
      left: 50%;
      transform: translateX(-50%);
      z-index: 2147483647;
      display: flex;
      align-items: center;
      gap: 2px;
      padding: 4px;
      border-radius: 999px;
      background: rgba(10, 10, 10, 0.82);
      -webkit-backdrop-filter: blur(12px) saturate(1.4);
      backdrop-filter: blur(12px) saturate(1.4);
      box-shadow:
        0 0 0 1px rgba(255, 255, 255, 0.08) inset,
        0 8px 24px rgba(0, 0, 0, 0.24),
        0 2px 6px rgba(0, 0, 0, 0.12);
      font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
      font-size: 13px;
      line-height: 1;
      -webkit-font-smoothing: antialiased;
      user-select: none;
      -webkit-user-select: none;
    }
    .proto-picker-highlight {
      position: absolute;
      top: 4px;
      left: 0;
      height: 28px;
      border-radius: 999px;
      background: rgba(255, 255, 255, 0.12);
      will-change: transform;
    }
    .proto-picker[data-ready] .proto-picker-highlight {
      transition:
        transform 250ms cubic-bezier(0.23, 1, 0.32, 1),
        width 250ms cubic-bezier(0.23, 1, 0.32, 1);
    }
    @media (prefers-reduced-motion: reduce) {
      .proto-picker[data-ready] .proto-picker-highlight { transition: none; }
    }
    .proto-picker-item {
      position: relative;
      display: flex;
      align-items: center;
      height: 28px;
      padding: 0 12px;
      border: 0;
      border-radius: 999px;
      background: transparent;
      color: rgba(255, 255, 255, 0.55);
      font: inherit;
      cursor: pointer;
      transition: color 150ms ease-out;
    }
    .proto-picker-item:hover { color: rgba(255, 255, 255, 0.85); }
    .proto-picker-item:active { transform: scale(0.97); }
    .proto-picker-item:focus-visible { outline: 2px solid rgba(255, 255, 255, 0.4); outline-offset: 2px; }
    .proto-picker-item[data-active] { color: #fff; }
    .proto-picker-divider { width: 1px; height: 16px; margin: 0 4px; background: rgba(255, 255, 255, 0.12); }
    .proto-picker-replay { padding: 0 10px; font-size: 14px; }
    .proto-picker[data-position="top"] { bottom: auto; top: 24px; }

    @media (max-width: 1080px) {
      .app-header-inner { align-items: flex-start; flex-direction: column; gap: 12px; }
      .app-user-row { width: 100%; justify-content: space-between; }
      .review-canvas { grid-template-columns: 1fr; }
      .comment-rail { border-left: 0; border-top: 1px solid var(--border); }
      .dock-shell { grid-template-columns: 58px minmax(0,1fr); }
      .context-rail { display: none; }
      .viewer-toolbar { grid-template-columns: minmax(0,1fr) auto; }
      .viewer-toolbar-center { display: none; }
      .viewer-body.comments-open { grid-template-columns: minmax(0,1fr) 320px; }
      .viewer-body.versions-open { grid-template-columns: 304px minmax(0,1fr); }
    }
    @media (max-width: 760px) {
      .atlas-id { min-width: 0; }
      .atlas-id span, .atlas-count, .atlas-page-nav { display: none; }
      .atlas-bar { justify-content: space-between; }
      .app-header-inner, .main { padding-left: 18px; padding-right: 18px; }
      .app-nav { overflow-x: auto; max-width: 100%; }
      .user-meta, .app-user-row .divider-v, .app-user-row > .badge { display: none; }
      .page-header { align-items: flex-start; flex-direction: column; }
      .projects-grid { grid-template-columns: 1fr; }
      .project-card { border-right: 0; }
      .project-card:nth-last-child(-n+2) { border-bottom: 1px solid var(--border); }
      .project-card:last-child { border-bottom: 0; }
      .detail-grid { grid-template-columns: 1fr; }
      .meta-row { grid-template-columns: 1fr; gap: 5px; }
      .rail-shell { grid-template-columns: 1fr; }
      .rail-sidebar { display: none; }
      .layer-global { overflow-x: auto; }
      .layer-project { align-items: flex-start; flex-direction: column; padding-top: 15px; }
      .layer-tabs { min-height: 48px; max-width: 100%; overflow-x: auto; }
      .dock-shell { grid-template-columns: 1fr; }
      .icon-dock { display: none; }
      .preview-body { padding: 34px 24px; }
      .preview-grid { grid-template-columns: 1fr; }
      .preview-card { border-right: 0; border-bottom: 1px solid #d6d2c9; }
      .viewer-toolbar { padding-inline: 5px; }
      .viewer-project, .viewer-toolbar-right .viewer-icon[data-secondary] { display: none; }
      .viewer-body.comments-open,
      .viewer-body.versions-open { grid-template-columns: minmax(0,1fr); }
      .viewer-panel { position: absolute; z-index: 18; inset: 0 0 0 auto; width: min(92vw, 352px); box-shadow: -18px 0 50px rgba(0,0,0,.28); }
      .versions-panel { inset: 0 auto 0 0; box-shadow: 18px 0 50px rgba(0,0,0,.28); }
      .viewer-document { padding: 38px 22px 92px; }
      .document-title { font-size: clamp(44px, 15vw, 70px); }
      .document-process { grid-template-columns: 1fr; }
      .document-step { min-height: 126px; border-right: 0; border-bottom: 1px solid #cbc6bb; }
      .document-step:last-child { border-bottom: 0; }
      .document-step h3 { margin-top: 24px; }
    }
  </style>
</head>
<body>
  <header class="atlas-bar">
    <div class="atlas-id">
      <span class="atlas-mark" aria-hidden="true"></span>
      <strong>Artifact Server</strong>
      <span>UI atlas</span>
    </div>
    <nav class="atlas-modes" aria-label="Atlas sections">
      <button class="atlas-mode" data-mode="reference" data-active>Reference pages</button>
      <button class="atlas-mode" data-mode="directions">Layout directions</button>
    </nav>
    <nav class="atlas-page-nav" id="atlas-page-nav" aria-label="Reference pages"></nav>
    <span class="atlas-count" id="atlas-count">01 / 08</span>
  </header>

  <main class="atlas-stage" id="reference-stage"></main>
  <section class="atlas-stage direction-stage" id="directions-stage" hidden>
    <div id="stage"></div>
    <nav class="proto-picker" aria-label="Prototype variants">
      <span class="proto-picker-highlight" aria-hidden="true"></span>
      <button class="proto-picker-item" data-active aria-current="true">Clean view</button>
      <button class="proto-picker-item">Comments open</button>
      <button class="proto-picker-item">Browse + versions</button>
    </nav>
  </section>

  <div class="dialog-layer" id="dialog-layer" role="presentation">
    <section class="dialog" role="dialog" aria-modal="true" aria-labelledby="dialog-title" id="dialog-content"></section>
  </div>

  <script>
    const pages = [
      ["signin", "Sign in"],
      ["projects", "Projects"],
      ["artifacts", "Artifacts"],
      ["artifact", "Artifact detail"],
      ["review", "Version review"],
      ["public-links", "Public links"],
      ["members", "Members"],
      ["api-keys", "API keys"],
    ];

    const icon = (name) => {
      const paths = {
        projects: '<rect x="3" y="4" width="18" height="16" rx="1"/><path d="M3 9h18M8 4v5"/>',
        artifacts: '<path d="M7 3h8l4 4v14H7z"/><path d="M15 3v5h5M10 13h6M10 17h6"/>',
        links: '<path d="M10 13a5 5 0 0 0 7.1.1l2-2a5 5 0 0 0-7.1-7.1l-1.1 1.1"/><path d="M14 11a5 5 0 0 0-7.1-.1l-2 2A5 5 0 0 0 12 20l1.1-1.1"/>',
        people: '<path d="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M22 21v-2a4 4 0 0 0-3-3.9M16 3.1a4 4 0 0 1 0 7.8"/>',
        key: '<circle cx="7.5" cy="15.5" r="4.5"/><path d="m11 12 9-9M15 8l3 3M17 6l3 3"/>',
        search: '<circle cx="11" cy="11" r="7"/><path d="m20 20-4-4"/>',
        command: '<path d="M18 9a3 3 0 1 0-3-3v12a3 3 0 1 0 3-3H6a3 3 0 1 0 3 3V6a3 3 0 1 0-3 3z"/>',
        settings: '<circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.7 1.7 0 0 0 .3 1.9l.1.1-2.8 2.8-.1-.1a1.7 1.7 0 0 0-1.9-.3 1.7 1.7 0 0 0-1 1.6v.2h-4V21a1.7 1.7 0 0 0-1-1.6 1.7 1.7 0 0 0-1.9.3l-.1.1L4.2 17l.1-.1a1.7 1.7 0 0 0 .3-1.9A1.7 1.7 0 0 0 3 14H2.8v-4H3a1.7 1.7 0 0 0 1.6-1 1.7 1.7 0 0 0-.3-1.9L4.2 7 7 4.2l.1.1a1.7 1.7 0 0 0 1.9.3A1.7 1.7 0 0 0 10 3V2.8h4V3a1.7 1.7 0 0 0 1 1.6 1.7 1.7 0 0 0 1.9-.3l.1-.1L19.8 7l-.1.1a1.7 1.7 0 0 0-.3 1.9 1.7 1.7 0 0 0 1.6 1h.2v4H21a1.7 1.7 0 0 0-1.6 1z"/>',
        back: '<path d="m15 18-6-6 6-6"/>',
        comments: '<path d="M21 15a4 4 0 0 1-4 4H8l-5 3V7a4 4 0 0 1 4-4h10a4 4 0 0 1 4 4z"/>',
        history: '<path d="M3 12a9 9 0 1 0 3-6.7L3 8"/><path d="M3 3v5h5M12 7v5l3 2"/>',
        share: '<circle cx="18" cy="5" r="3"/><circle cx="6" cy="12" r="3"/><circle cx="18" cy="19" r="3"/><path d="m8.6 10.5 6.8-4M8.6 13.5l6.8 4"/>',
        more: '<circle cx="5" cy="12" r="1" fill="currentColor" stroke="none"/><circle cx="12" cy="12" r="1" fill="currentColor" stroke="none"/><circle cx="19" cy="12" r="1" fill="currentColor" stroke="none"/>',
        focus: '<path d="M8 3H3v5M16 3h5v5M8 21H3v-5M16 21h5v-5"/>',
        close: '<path d="m6 6 12 12M18 6 6 18"/>',
      };
      return `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">${paths[name] || paths.artifacts}</svg>`;
    };

    const badge = (text, tone = "") => `<span class="badge ${tone}">${text}</span>`;
    const button = (text, kind = "", action = "") => `<button class="btn ${kind}" ${action ? `data-action="${action}"` : ""}>${text}</button>`;
    const pageHeader = (eyebrow, title, description, actions = "") => `
      <header class="page-header">
        <div><p class="eyebrow">${eyebrow}</p><h1>${title}</h1><p class="lede">${description}</p></div>
        ${actions ? `<div class="header-actions">${actions}</div>` : ""}
      </header>`;

    function appShell(content, active = "artifacts") {
      return `<div class="product-shell">
        <header class="app-header">
          <div class="app-header-inner">
            <div class="app-brand-row">
              <a class="app-brand" href="#reference/artifacts" data-page="artifacts">Artifact Server</a>
              <span class="divider-v"></span>
              <select class="project-picker" aria-label="Selected project"><option>Default</option><option>Workspaces</option><option>Research notes</option></select>
            </div>
            <div class="app-user-row" style="gap:12px; min-width:0;">
              <nav class="app-nav" aria-label="Primary navigation">
                ${[["projects","Projects"],["public-links","Public links"],["members","Members"],["api-keys","API keys"]].map(([key,label]) => `<a class="nav-link ${active===key?"active":""}" href="#reference/${key}" data-page="${key}">${label}</a>`).join("")}
              </nav>
              <span class="divider-v"></span>
              <div class="user-meta"><div class="user-id">local-owner</div><div class="user-role">administrator</div></div>
              ${badge("human", "primary")}
              <button class="btn ghost sm" data-action="theme">Light theme</button>
            </div>
          </div>
        </header>
        <main class="main"><div class="stack">${content}</div></main>
      </div>`;
    }

    const artifactsRows = () => `
      <tr><td><a class="td-title" href="#reference/artifact" data-page="artifact">Workspaces launch review</a><div class="tag-row">${badge("prototype")}${badge("launch")}</div></td><td>${badge("Public link","primary")}</td><td><span class="mono tiny">ver_01JQF8…K2T</span></td><td class="muted small">Aug 23, 2026, 10:42 AM</td><td><div class="action-row">${button("Open","sm")}${button("Manage","sm","artifact")}</div></td></tr>
      <tr><td><a class="td-title" href="#reference/artifact" data-page="artifact">Artifact Server onboarding</a><div class="tag-row">${badge("docs")}${badge("team")}</div></td><td>${badge("Account required")}</td><td><span class="mono tiny">ver_01JQE7…4MC</span></td><td class="muted small">Aug 22, 2026, 4:18 PM</td><td><div class="action-row">${button("Open","sm")}${button("Manage","sm","artifact")}</div></td></tr>
      <tr><td><a class="td-title" href="#reference/artifact" data-page="artifact">Infrastructure decision map</a><div class="tag-row">${badge("architecture")}</div></td><td>${badge("Account required")}</td><td><span class="mono tiny">ver_01JQB3…9PL</span></td><td class="muted small">Aug 20, 2026, 9:07 AM</td><td><div class="action-row">${button("Open","sm")}${button("Manage","sm","artifact")}</div></td></tr>`;

    const artifactsTable = () => `<div class="table-wrap"><table><thead><tr><th>Artifact</th><th>Access</th><th>Current version</th><th>Created</th><th style="text-align:right">Actions</th></tr></thead><tbody>${artifactsRows()}</tbody></table></div>`;

    function renderSignIn() {
      return `<div class="signin"><section class="signin-card"><p class="eyebrow">Artifact Server</p><h1>Sign in required</h1><p class="lede">Sign in with this installation’s configured identity provider.</p>${button("Sign in","primary","signin")}</section></div>`;
    }

    function renderProjects() {
      const card = (name,id,state,git,copy) => `<article class="project-card"><div class="project-top"><div><h2>${name}</h2><p class="mono tiny muted">${id}</p></div>${badge(state,state==="Active"?"primary":"")}</div><p class="small muted" style="margin:18px 0 0">Created ${copy}</p><div class="git-block"><div class="git-head"><div><h3>Git history</h3><p class="tiny muted" style="margin:0">Optional Cloudflare mirror for this project.</p></div>${badge(git,git==="On"?"primary":"")}</div><div class="git-actions">${button(git==="On"?"Turn off":"Turn on","sm")}</div></div><div class="action-row" style="margin-top:20px; justify-content:flex-start">${button("Open project","sm","artifacts")}${button("Rename","ghost sm")}</div></article>`;
      const content = pageHeader("Installation","Projects","One installation contains one or more projects. Project names are labels; stable IDs select the project.",button("New project","primary","new-project")) + `<div class="projects-grid">${card("Default","prj_default","Active","On","Aug 17, 2026")}${card("Workspaces","prj_workspaces","Active","Off","Aug 19, 2026")}${card("Research notes","prj_research","Active","Off","Aug 20, 2026")}${card("Client archive","prj_client_archive","Archived","Off","Jul 02, 2026")}</div>`;
      return appShell(content,"projects");
    }

    function renderArtifacts() {
      const content = pageHeader("Project","Default","Browse active artifacts in this project. Publication stays in the CLI and Agent Skill.") + `<form class="filter-bar" onsubmit="return false"><label class="field grow"><span class="label">Exact tag</span><input class="input" placeholder="prototype"></label>${button("Filter")}</form>${artifactsTable()}`;
      return appShell(content,"artifacts");
    }

    const overviewPanel = () => `<div class="detail-grid"><section class="panel panel-pad"><div class="section-head"><h2>Current artifact</h2>${badge("Public link","primary")}</div><dl class="meta"><div class="meta-row"><dt>Current version</dt><dd>Version 7</dd></div><div class="meta-row"><dt>Saved</dt><dd>Aug 23, 2026, 10:42 AM</dd></div><div class="meta-row"><dt>Entry file</dt><dd class="mono tiny">index.html</dd></div><div class="meta-row"><dt>Routing</dt><dd>SPA</dd></div><div class="meta-row"><dt>Tags</dt><dd><div class="tag-row">${badge("launch")}${badge("prototype")}</div></dd></div><div class="meta-row"><dt>Linked file</dt><dd><span class="mono tiny">/Users/ramos/workspaces/launch/index.html</span> ${badge("Modified","warning")}</dd></div></dl><div class="notice" style="margin-top:18px"><div class="row" style="justify-content:space-between; gap:12px"><span class="small muted">The linked file has changed since version 7 was captured.</span>${button("Capture now","sm")}</div></div></section><aside class="panel panel-pad"><h2>Manage</h2><div class="manage-stack">${button("Edit tags")}${button("Require account")}${button("Tombstone artifact","danger")}</div></aside></div>`;

    const versionsPanel = () => `<div class="version-list">${[[7,"Current","Aug 23, 10:42 AM",2],[6,"","Aug 22, 6:13 PM",0],[5,"","Aug 21, 11:04 AM",1]].map(([n,current,time,threads])=>`<article class="version-row"><div><div class="row" style="gap:9px"><h2 style="margin:0">Version ${n}</h2>${current?badge(current,"primary"):""}${threads?badge(`${threads} open ${threads===1?"thread":"threads"}`,"warning"):""}</div><p class="mono tiny muted" style="margin:8px 0 0">ver_01JQ${n}F8C4WQ3Y9</p><p class="small muted" style="margin:8px 0 0">Saved ${time} · 14 files · 2.8 MB</p></div><div class="action-row">${button("Review","sm","review")}${button("Open","sm")}${!current?button("Restore","sm"):""}</div></article>`).join("")}</div>`;

    function renderArtifact() {
      const content = pageHeader("Artifact","Workspaces launch review","Project: Default",button("Open artifact","primary")+button("Reload")) + `<nav class="tabs" aria-label="Artifact sections"><button class="tab active" data-tab="overview">Overview</button><button class="tab" data-tab="versions">Versions</button><button class="tab" data-tab="compare">Compare</button><button class="tab" data-tab="comments">Comments</button><button class="tab" data-tab="actions">Action history</button></nav><div id="artifact-tab-content">${overviewPanel()}</div>`;
      return appShell(content,"artifacts");
    }

    function reviewCanvas() {
      return `<div class="review-canvas"><article class="artifact-preview"><div class="preview-top"><strong>WORKSPACES</strong><span>Product brief · 07</span></div><div class="preview-body"><p class="preview-kicker">A calmer place for agent work</p><div class="preview-title">Make the work visible while it is still moving.</div><p class="preview-copy">Workspaces turns drafts, decisions, and live artifacts into a review surface the whole team can understand.</p><div class="preview-grid"><div class="preview-card"><b>01</b><h3 style="margin-top:22px">Capture</h3><p class="small" style="color:#666">Keep the exact version worth discussing.</p></div><div class="preview-card"><b>02</b><h3 style="margin-top:22px">Review</h3><p class="small" style="color:#666">Comment directly on the work.</p></div><div class="preview-card"><b>03</b><h3 style="margin-top:22px">Resolve</h3><p class="small" style="color:#666">Send bounded feedback to an agent.</p></div></div></div></article><aside class="comment-rail"><header class="comment-head"><span class="eyebrow" style="margin:0">3 threads</span>${button("Send all open","primary sm")}</header><div class="comment-list"><article class="comment"><div class="comment-meta"><div class="row" style="gap:8px"><span class="avatar">ER</span><b class="small">Emily Ramos</b></div>${badge("Open","warning")}</div><p class="small">Can the headline say what becomes visible, rather than speaking abstractly about work?</p><p class="tiny muted" style="margin-top:12px">on “Make the work visible…” · 12 min ago</p></article><article class="comment"><div class="comment-meta"><div class="row" style="gap:8px"><span class="avatar">JR</span><b class="small">José Ramos</b></div>${badge("Open","warning")}</div><p class="small">The three-step framing is strong. “Resolve” may imply the agent closes the thread automatically.</p><p class="tiny muted" style="margin-top:12px">on the process grid · 8 min ago</p></article><article class="comment"><div class="comment-meta"><div class="row" style="gap:8px"><span class="avatar">AS</span><b class="small">Artifact Server</b></div>${badge("Resolved","success")}</div><p class="small">Updated the supporting copy and preserved the original thread attribution.</p></article></div></aside></div>`;
    }

    function renderReview() {
      const content = pageHeader("Version 7 · Current","Review Workspaces launch review","Click an element in the page to comment on it. Every comment is attached to this exact saved version.",button("Back to artifact","","artifact")) + `<div class="notice"><div class="row" style="justify-content:space-between; gap:16px"><span>${badge("Modified","warning")} <span class="small muted" style="margin-left:9px">The linked file has changed since this captured version.</span></span>${button("Open live view","sm")}</div></div>` + reviewCanvas();
      return appShell(content,"artifacts");
    }

    function renderPublicLinks() {
      const row = (project,name,version,url) => `<tr><td><input class="check" type="checkbox" aria-label="Select ${name}"></td><td><b>${project}</b></td><td><a class="td-title" href="#reference/artifact" data-page="artifact">${name}</a><div class="tiny muted">Created Aug 20, 2026</div></td><td><b>Version ${version}</b><div class="mono tiny muted" style="margin-top:5px">ver_01JQF8…</div></td><td><span class="mono tiny text-link secret-prefix">https://artifacts.local/a/${name.toLowerCase().replaceAll(" ","-")}</span></td><td><div class="action-row">${button("Open","sm")}${button("Make private","ghost sm")}</div></td></tr>`;
      const content = pageHeader("Administration","Public links","See every active artifact that currently allows public-link access, then make individual links or a bounded selection private.",button("Reload")) + `<section class="bulk-bar"><div class="row" style="gap:8px">${button("Select visible (3)","sm")}${button("Select all (3)","sm")}${button("Clear selection","ghost sm")}</div><div class="row" style="gap:12px"><span class="small muted">0 selected · maximum 100</span>${button("Make 0 private","primary sm")}</div></section><div class="table-wrap"><table><thead><tr><th></th><th>Project</th><th>Artifact</th><th>Current version</th><th>Public URL</th><th style="text-align:right">Actions</th></tr></thead><tbody>${row("Default","Workspaces launch review",7,"url")}${row("Default","Release readiness board",3,"url")}${row("Research notes","Agent interaction map",12,"url")}</tbody></table></div>`;
      return appShell(content,"public-links");
    }

    function renderMembers() {
      const row = (initials,name,email,role,status,date) => `<tr><td><div class="row" style="gap:11px"><span class="avatar">${initials}</span><div><b class="td-title">${name}</b><div class="tiny muted">${email}</div></div></div></td><td style="text-transform:capitalize">${role}</td><td>${badge(status,status==="active"?"primary":"")}</td><td class="small muted">${date}</td><td><div class="action-row">${status==="active"?button("Deactivate","ghost sm"):""}</div></td></tr>`;
      const content = pageHeader("Administration","Members","One installation has one closed member group. There is no public sign-up or project-specific membership.",button("Admit member","primary","admit-member")) + `<div class="table-wrap"><table><thead><tr><th>Member</th><th>Role</th><th>Status</th><th>Admitted</th><th style="text-align:right">Actions</th></tr></thead><tbody>${row("JR","José Ramos","jose@example.com","administrator","active","Aug 17, 2026")}${row("ER","Emily Ramos","emily@example.com","member","active","Aug 18, 2026")}${row("MC","Maya Chen","maya@example.com","member","active","Aug 21, 2026")}${row("AL","Alex Lee","alex@example.com","member","inactive","Jul 04, 2026")}</tbody></table></div>`;
      return appShell(content,"members");
    }

    function renderApiKeys() {
      const key = (name,prefix,expiry,caps,state="Active") => `<article class="version-row" style="grid-template-columns:260px 1fr auto"><div><div class="row" style="gap:9px"><h2 style="margin:0">${name}</h2>${badge(state,state==="Active"?"primary":"danger")}</div><p class="mono tiny muted" style="margin:9px 0 0">${prefix}</p><p class="tiny muted" style="margin:7px 0 0">Expires ${expiry}</p></div><div class="tag-row">${caps.map(cap=>badge(cap)).join("")}</div><div class="action-row">${state==="Active"?button("Rotate","sm")+button("Revoke","ghost sm"):""}</div></article>`;
      const content = pageHeader("Administration","API keys","Managed API keys have explicit capabilities, a required expiration, and revocation. Secrets are never shown again.",button("Issue API key","primary","issue-key")) + `<div class="version-list">${key("Codex local","as_k_8fd1…","Nov 30, 2026",["artifact:read","artifact:create","artifact:publish:any"])}${key("Release automation","as_k_2c41…","Dec 31, 2026",["artifact:read","artifact:publish:any","agent:connect"])}${key("Old preview bot","as_k_91aa…","Oct 01, 2026",["artifact:read"],"Revoked")}</div>`;
      return appShell(content,"api-keys");
    }

    const pageRenderers = { signin: renderSignIn, projects: renderProjects, artifacts: renderArtifacts, artifact: renderArtifact, review: renderReview, "public-links": renderPublicLinks, members: renderMembers, "api-keys": renderApiKeys };

    const viewerControl = (name, label, options = {}) => {
      const { active = false, count = "", attributes = "", secondary = false } = options;
      return `<button class="viewer-icon${active ? " active" : ""}" type="button" aria-label="${label}" title="${label}" ${secondary ? "data-secondary" : ""} ${attributes}>${icon(name)}${count ? `<span class="control-count">${count}</span>` : ""}</button>`;
    };

    function viewerToolbar(state) {
      return `<header class="viewer-toolbar">
        <div class="viewer-toolbar-left">
          ${viewerControl("back", "Back to artifact details", { attributes: 'data-page="artifact"' })}
          <button class="viewer-icon" type="button" aria-label="Browse artifacts and versions" title="Browse artifacts and versions" data-view-state="2">${icon("artifacts")}</button>
          <div class="viewer-title-block"><span class="viewer-title">Workspaces launch review</span><span class="viewer-project">Default · v7</span></div>
        </div>
        <div class="viewer-toolbar-center">
          <span class="viewer-version"><strong>Version 7</strong> · Current</span>
          <button class="viewer-drift" type="button" title="Linked source has changed" data-viewer-action="drift">Source modified</button>
        </div>
        <div class="viewer-toolbar-right">
          ${viewerControl("comments", "Comments — 3 threads", { active: state === 1, count: "3", attributes: 'data-view-state="1"' })}
          ${viewerControl("history", "Browse artifacts and versions", { active: state === 2, attributes: 'data-view-state="2"' })}
          ${viewerControl("share", "Share this version", { attributes: 'data-viewer-action="share"', secondary: true })}
          ${viewerControl("focus", "Focus mode — F", { attributes: 'data-viewer-action="focus"', secondary: true })}
        </div>
      </header>`;
    }

    function artifactDocument(showAnnotations = false) {
      return `<section class="viewer-surface" aria-label="Artifact canvas">
        <article class="viewer-document">
          <div class="document-masthead"><strong>Workspaces</strong><span>Product brief · 07</span></div>
          <p class="document-kicker">A calmer place for agent work</p>
          <h1 class="document-title">Make the work visible while it is still moving.</h1>
          <p class="document-intro">Workspaces turns drafts, decisions, and live artifacts into a review surface the whole team can understand—without asking the work to stop first.</p>
          <div class="document-process">
            <section class="document-step"><span>01</span><h3>Capture</h3><p>Keep the exact version worth discussing.</p></section>
            <section class="document-step"><span>02</span><h3>Review</h3><p>Comment directly on the work, in context.</p></section>
            <section class="document-step"><span>03</span><h3>Resolve</h3><p>Send bounded feedback back to the agent.</p></section>
          </div>
        </article>
        ${showAnnotations ? `<button class="annotation-pin one" type="button" aria-label="Open comment 1" data-view-state="1">1</button><button class="annotation-pin two" type="button" aria-label="Open comment 2" data-view-state="1">2</button><button class="annotation-pin three" type="button" aria-label="Open comment 3" data-view-state="1">3</button>` : ""}
      </section>`;
    }

    function commentsPanel() {
      const comment = (initials, name, copy, location, selected = false, resolved = false) => `<article class="viewer-comment${selected ? " selected" : ""}">
        <div class="row" style="justify-content:space-between;gap:8px"><span class="row" style="gap:8px"><span class="avatar">${initials}</span><b class="small">${name}</b></span>${badge(resolved ? "Resolved" : "Open", resolved ? "success" : "warning")}</div>
        <p>${copy}</p><div class="viewer-comment-location">${location}</div>
      </article>`;
      return `<aside class="viewer-panel comments-panel" aria-label="Comments">
        <header class="viewer-panel-header"><h2>Comments <span class="muted">3</span></h2>${viewerControl("close", "Close comments", { attributes: 'data-view-state="0"' })}</header>
        <div class="viewer-panel-scroll">
          ${comment("ER", "Emily Ramos", "Can the headline say what becomes visible, rather than speaking abstractly about work?", "Headline · 12 minutes ago", true)}
          ${comment("JR", "José Ramos", "The three-step framing is strong. “Resolve” may imply the agent closes the thread automatically.", "Process grid · 8 minutes ago")}
          ${comment("AS", "Artifact Server", "Updated the supporting copy and preserved the original thread attribution.", "Supporting copy · 2 minutes ago", false, true)}
        </div>
        <form class="viewer-compose" onsubmit="return false"><textarea aria-label="Reply to selected thread" placeholder="Reply to thread…"></textarea><div class="viewer-compose-actions">${button("Resolve", "ghost sm")}${button("Reply", "primary sm")}</div></form>
      </aside>`;
    }

    function viewerVersionsPanel() {
      const artifact = (name, meta, count, active = false) => `<button class="artifact-jump${active ? " active" : ""}" type="button"><span><span class="jump-name">${name}</span><span class="jump-meta">${meta}</span></span><span class="jump-count">${count}</span></button>`;
      const version = (number, meta, threads, active = false) => `<button class="version-jump${active ? " active" : ""}" type="button"><span><span class="jump-name">Version ${number}</span><span class="jump-meta">${meta}</span></span><span class="jump-count">${threads}</span></button>`;
      return `<aside class="viewer-panel versions-panel" aria-label="Browse artifacts and versions">
        <header class="viewer-panel-header"><h2>Browse</h2>${viewerControl("close", "Close browser", { attributes: 'data-view-state="0"' })}</header>
        <div style="padding:12px;border-bottom:1px solid var(--border)"><label class="field"><span class="label">Jump to artifact</span><input class="input" aria-label="Search artifacts" placeholder="Search…  ⌘ K"></label></div>
        <div class="viewer-panel-scroll">
          <div class="viewer-panel-section">Recent artifacts</div>
          ${artifact("Workspaces launch review", "Default · HTML", "v7", true)}
          ${artifact("Artifact Server onboarding", "Default · Markdown", "v4")}
          ${artifact("Infrastructure decision map", "Research · HTML", "v12")}
          <div class="viewer-panel-section">Version history</div>
          ${version(7, "Current · Aug 23, 10:42", "2 open", true)}
          ${version(6, "Aug 22, 18:13", "—")}
          ${version(5, "Aug 21, 11:04", "1 open")}
          ${version(4, "Aug 19, 16:38", "—")}
        </div>
      </aside>`;
    }

    function artifactStage(state = 0) {
      const panelClass = state === 1 ? "comments-open" : state === 2 ? "versions-open" : "";
      const panel = state === 1 ? commentsPanel() : state === 2 ? viewerVersionsPanel() : "";
      return `<div class="viewer-shell" data-viewer-shell>
        ${viewerToolbar(state)}
        <div class="viewer-body ${panelClass}">${state === 2 ? panel : ""}${artifactDocument(state === 1)}${state === 1 ? panel : ""}</div>
        <button class="focus-return" type="button" data-viewer-action="focus">Exit focus mode · Esc</button>
      </div>`;
    }

    const directionClean = () => artifactStage(0);
    const directionComments = () => artifactStage(1);
    const directionVersions = () => artifactStage(2);

    const referenceStage = document.getElementById("reference-stage");
    const directionsStage = document.getElementById("directions-stage");
    const atlasPageNav = document.getElementById("atlas-page-nav");
    const atlasCount = document.getElementById("atlas-count");
    let currentPage = "signin";
    let currentMode = "reference";

    atlasPageNav.innerHTML = pages.map(([key,label],i)=>`<button class="atlas-page" data-page="${key}">${String(i+1).padStart(2,"0")} ${label}</button>`).join("");

    function setMode(mode) {
      currentMode = mode;
      document.querySelectorAll(".atlas-mode").forEach(el => el.toggleAttribute("data-active", el.dataset.mode === mode));
      referenceStage.hidden = mode !== "reference";
      directionsStage.hidden = mode !== "directions";
      atlasPageNav.hidden = mode !== "reference";
      atlasCount.hidden = mode !== "reference";
      if (mode === "directions") requestAnimationFrame(moveHighlight);
      location.hash = mode === "directions" ? "directions" : `reference/${currentPage}`;
    }

    function setPage(key, updateHash = true) {
      if (!pageRenderers[key]) return;
      currentPage = key;
      referenceStage.innerHTML = pageRenderers[key]();
      const index = pages.findIndex(([page]) => page === key);
      atlasCount.textContent = `${String(index+1).padStart(2,"0")} / ${String(pages.length).padStart(2,"0")}`;
      document.querySelectorAll(".atlas-page").forEach(el => el.toggleAttribute("data-active", el.dataset.page === key));
      if (updateHash) location.hash = `reference/${key}`;
      window.scrollTo({top:0, behavior:"instant"});
    }

    function openDialog(kind) {
      const dialogs = {
        "new-project": ["New project","Projects organize artifacts inside this installation. Every admitted member can manage every project.",`<label class="field"><span class="label">Project name</span><input class="input" value="Launch research"></label>`,"Create project"],
        "admit-member": ["Admit member","Admit one person to this installation. Every active member can manage artifacts in every project.",`<label class="field"><span class="label">Display name</span><input class="input" value="Avery Stone"></label><label class="field"><span class="label">Email</span><input class="input" type="email" value="avery@example.com"></label><label class="field"><span class="label">Role</span><select class="input"><option>Member</option><option>Administrator</option></select></label>`,"Admit member"],
        "issue-key": ["Issue API key","The secret appears once. Give the key only the capabilities it needs and choose a future expiration.",`<label class="field"><span class="label">Name</span><input class="input" value="Preview automation"></label><label class="field"><span class="label">Expires at</span><input class="input" type="datetime-local" value="2026-12-31T17:00"></label><div class="field"><span class="label">Capabilities</span><label class="capability"><input class="check" type="checkbox" checked><span><b>Read artifacts</b><small class="muted" style="display:block;margin-top:4px">List and read artifact metadata.</small></span></label><label class="capability"><input class="check" type="checkbox" checked><span><b>Publish versions</b><small class="muted" style="display:block;margin-top:4px">Publish new immutable versions.</small></span></label></div>`,"Issue API key"],
        signin: ["Identity provider handoff","In a remote team deployment this continues to the configured provider. In local-owner mode the application establishes the owner session automatically.",`<div class="notice"><b>Mockup behavior</b><div class="small muted" style="margin-top:6px">No external sign-in is performed from this atlas.</div></div>`,"Done"],
        share: ["Share version 7","This link stays pinned to the exact immutable version currently on screen.",`<label class="field"><span class="label">Version URL</span><input class="input mono" readonly value="https://artifacts.local/a/workspaces-launch-review?v=7"></label><div class="capability"><input class="check" type="checkbox" checked><span><b>Require an account</b><small class="muted" style="display:block;margin-top:4px">Only admitted installation members can open this link.</small></span></div>`,"Copy link"],
        drift: ["Linked source changed","Version 7 remains immutable. The file linked from your workspace has changed since this version was captured.",`<div class="notice"><b>Current saved version is safe</b><div class="small muted" style="margin-top:6px">Open the live file to inspect the change, or capture it as a new version from the artifact details page.</div></div>`,"Done"],
      };
      const [title,description,form,confirm] = dialogs[kind] || ["Mock action","This control is represented for layout review only.","","Done"];
      document.getElementById("dialog-content").innerHTML = `<h2 id="dialog-title">${title}</h2><p>${description}</p><div class="dialog-form">${form}</div><footer class="dialog-footer">${button("Cancel","ghost","close-dialog")}${button(confirm,"primary","close-dialog")}</footer>`;
      document.getElementById("dialog-layer").classList.add("open");
    }

    document.addEventListener("click", event => {
      const pageTarget = event.target.closest("[data-page]");
      if (pageTarget) { event.preventDefault(); setMode("reference"); setPage(pageTarget.dataset.page); return; }
      const modeTarget = event.target.closest("[data-mode]");
      if (modeTarget) { setMode(modeTarget.dataset.mode); return; }
      const viewStateTarget = event.target.closest("[data-view-state]");
      if (viewStateTarget) { setActive(Number(viewStateTarget.dataset.viewState)); return; }
      const viewerActionTarget = event.target.closest("[data-viewer-action]");
      if (viewerActionTarget) {
        const action = viewerActionTarget.dataset.viewerAction;
        if (action === "focus") document.querySelector("[data-viewer-shell]")?.classList.toggle("focus");
        else openDialog(action);
        return;
      }
      const jumpTarget = event.target.closest(".artifact-jump, .version-jump");
      if (jumpTarget) {
        const selector = jumpTarget.classList.contains("artifact-jump") ? ".artifact-jump" : ".version-jump";
        jumpTarget.closest(".viewer-panel")?.querySelectorAll(selector).forEach(el => el.classList.toggle("active", el === jumpTarget));
        return;
      }
      const actionTarget = event.target.closest("[data-action]");
      if (actionTarget) {
        const action = actionTarget.dataset.action;
        if (action === "theme") {
          document.documentElement.classList.toggle("dark");
          document.querySelectorAll('[data-action="theme"]').forEach(el => el.textContent = document.documentElement.classList.contains("dark") ? "Light theme" : "Dark theme");
        } else if (["artifact","artifacts","review"].includes(action)) setPage(action);
        else if (action === "close-dialog") document.getElementById("dialog-layer").classList.remove("open");
        else openDialog(action);
      }
      const tab = event.target.closest("[data-tab]");
      if (tab) {
        document.querySelectorAll("[data-tab]").forEach(el=>el.classList.toggle("active",el===tab));
        const content = document.getElementById("artifact-tab-content");
        if (tab.dataset.tab === "overview") content.innerHTML = overviewPanel();
        else if (tab.dataset.tab === "versions") content.innerHTML = versionsPanel();
        else if (tab.dataset.tab === "compare") content.innerHTML = `<div class="panel panel-pad"><div class="section-head"><h2>Compare saved versions</h2>${badge("Version 6 → 7","primary")}</div><div class="projects-grid" style="margin-top:20px"><div class="project-card"><p class="eyebrow">Added · 3</p><span class="mono small">assets/diagram.svg</span></div><div class="project-card"><p class="eyebrow">Changed · 2</p><span class="mono small">index.html</span></div></div></div>`;
        else if (tab.dataset.tab === "comments") content.innerHTML = `<div class="panel panel-pad"><div class="section-head"><h2>Open comment threads</h2>${button("Send all open","primary sm")}</div><p class="muted">Three open threads are attached to versions 5 and 7. Open a version review to see anchored comments in place.</p>${button("Review current version","","review")}</div>`;
        else content.innerHTML = `<div class="version-list"><article class="version-row"><div><h2>Access changed</h2><p class="small muted">Made public by local-owner · Aug 23, 10:45 AM</p></div>${badge("Attributed","primary")}</article><article class="version-row"><div><h2>Version published</h2><p class="small muted">Version 7 published by Codex local · Aug 23, 10:42 AM</p></div>${badge("Immutable","success")}</article></div>`;
      }
    });

    document.getElementById("dialog-layer").addEventListener("click", event => {
      if (event.target.id === "dialog-layer") event.currentTarget.classList.remove("open");
    });

    const variants = [directionClean, directionComments, directionVersions];
    const stage = document.getElementById('stage');
    const picker = document.querySelector('.proto-picker');
    const highlight = picker.querySelector('.proto-picker-highlight');
    const items = [...picker.querySelectorAll('.proto-picker-item:not(.proto-picker-replay)')];
    const replay = picker.querySelector('.proto-picker-replay');
    let current = 0;

    function moveHighlight() {
      const el = items[current];
      highlight.style.width = el.offsetWidth + 'px';
      highlight.style.transform = `translateX(${el.offsetLeft}px)`;
    }

    function mount(i) {
      stage.innerHTML = '';
      requestAnimationFrame(() => { stage.innerHTML = variants[i](); });
    }

    function setActive(i) {
      if (i < 0 || i >= variants.length) return;
      current = i;
      items.forEach((el, j) => {
        el.toggleAttribute('data-active', j === i);
        if (j === i) el.setAttribute('aria-current', 'true');
        else el.removeAttribute('aria-current');
      });
      moveHighlight();
      const url = new URL(location);
      url.searchParams.set('v', i + 1);
      history.replaceState(null, '', url);
      mount(i);
    }

    items.forEach((el, i) => el.addEventListener('click', () => setActive(i)));
    replay?.addEventListener('click', () => mount(current));
    window.addEventListener('resize', moveHighlight);

    document.addEventListener('keydown', (e) => {
      if (/^(INPUT|TEXTAREA|SELECT)$/.test(e.target.tagName) || e.target.isContentEditable) return;
      if (currentMode !== "directions") return;
      if (e.key === 'Escape' && document.querySelector('[data-viewer-shell].focus')) {
        document.querySelector('[data-viewer-shell]')?.classList.remove('focus');
        return;
      }
      if (e.metaKey || e.ctrlKey || e.altKey) return;
      if (e.key === 'f' || e.key === 'F') {
        document.querySelector('[data-viewer-shell]')?.classList.toggle('focus');
        return;
      }
      const num = parseInt(e.key, 10);
      if (num >= 1 && num <= variants.length) setActive(num - 1);
      else if (e.key === 'ArrowRight') setActive((current + 1) % variants.length);
      else if (e.key === 'ArrowLeft') setActive((current - 1 + variants.length) % variants.length);
      else if (e.key === 'r' || e.key === 'R') mount(current);
    });

    setActive((parseInt(new URLSearchParams(location.search).get('v'), 10) || 1) - 1);
    requestAnimationFrame(() => requestAnimationFrame(() => picker.setAttribute('data-ready', '')));

    const initialHash = location.hash.replace(/^#/, "");
    if (initialHash === "directions") setMode("directions");
    else {
      const hashPage = initialHash.startsWith("reference/") ? initialHash.split("/")[1] : "signin";
      setPage(pageRenderers[hashPage] ? hashPage : "signin", false);
      setMode("reference");
    }
  </script>
</body>
</html>