/* endmin's only stylesheet. One hand-written file, no framework, no build
   step, no CDN. Everything a page can show is styled here. */

/* ------------------------------------------------------------- the palette
   Every colour in the app is one of these. The dark block below redefines the
   same names and nothing else, so no rule is ever written twice. */

:root {
  color-scheme: light dark;

  --bg: #f6f8fa;
  --surface: #ffffff;
  --surface-2: #f0f3f6;
  --surface-3: #eaeef2;
  --border: #d0d7de;
  --border-strong: #afb8c1;

  --text: #1f2328;
  --text-muted: #59636e;

  --accent: #0969da;
  --accent-hover: #0860ca;
  --accent-fg: #ffffff;
  --accent-soft: #ddf4ff;

  --success: #1a7f37;
  --danger: #cf222e;
  --danger-soft: #ffebe9;
  --warn: #9a6700;

  /* The rail is dark in both themes: it is chrome, not page. */
  --nav-bg: #24292f;
  --nav-fg: #ffffff;
  --nav-fg-muted: #b6bec6;

  /* The terminal's own colours. term-xterm.js reads these back out with
     getComputedStyle and hands them to xterm as its theme, so the terminal
     palette lives in css like every other colour in the app. */
  --term-bg: #0d1117;
  --term-fg: #d5dbe3;
  --term-cursor: #539bf5;
  --term-sel: rgba(83, 155, 245, 0.35);

  --ansi-black: #22272e;         --ansi-bright-black: #545d68;
  --ansi-red: #f47067;           --ansi-bright-red: #ff938a;
  --ansi-green: #57ab5a;         --ansi-bright-green: #6bc46d;
  --ansi-yellow: #c69026;        --ansi-bright-yellow: #daaa3f;
  --ansi-blue: #539bf5;          --ansi-bright-blue: #6cb6ff;
  --ansi-magenta: #b083f0;       --ansi-bright-magenta: #dcbdfb;
  --ansi-cyan: #39c5cf;          --ansi-bright-cyan: #56d4dd;
  --ansi-white: #adbac7;         --ansi-bright-white: #cdd9e5;

  /* ---- geometry. Tokens rather than magic numbers, because the terminal's
     height falls out of these and the two must never drift apart. */
  --rail-w: 200px;
  --tabbar-h: 56px;
  --termbar-h: 42px;
  --keybar-h: 46px;
  --safe-b: env(safe-area-inset-bottom, 0px);

  /* Published by viewport.js onto <html>. Declared here too, because a calc()
     against an undefined custom property makes the whole declaration invalid
     and the page would have no height at all before script runs. */
  --vvh: 100vh;
  --kb: 0px;

  --radius: 6px;
  --sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  --mono: ui-monospace, SFMono-Regular, Menlo, Consolas, "DejaVu Sans Mono", monospace;
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg: #0d1117;
    --surface: #151b23;
    --surface-2: #1b2028;
    --surface-3: #262c36;
    --border: #3d444d;
    --border-strong: #4d545e;
    --text: #d1d7e0;
    --text-muted: #9198a1;
    --accent: #4493f8;
    --accent-hover: #58a6ff;
    --accent-fg: #ffffff;
    --accent-soft: #121d2f;
    --danger: #f85149;
    --danger-soft: #2d1213;
    --nav-bg: #151b23;
    --nav-fg: #f0f6fc;
    --nav-fg-muted: #9198a1;
    --term-bg: #0b0f16;
  }
}

/* ------------------------------------------------------------------ reset */

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  /* No pull-to-refresh. A swipe up in the terminal must never reload the page
     and destroy the view of a running session. */
  overscroll-behavior: none;
}

body {
  font-family: var(--sans);
  font-size: 14px;
  line-height: 1.5;
  color: var(--text);
  background: var(--bg);
}

a { color: var(--accent); text-decoration: none; }
a:hover { text-decoration: underline; }
h1, h2, h3 { margin: 0 0 8px; line-height: 1.25; }
p { margin: 0 0 10px; }
code, pre { font-family: var(--mono); font-size: 0.92em; }
pre {
  background: var(--surface-2); border: 1px solid var(--border);
  border-radius: var(--radius); padding: 10px 12px; overflow-x: auto;
}
.muted { color: var(--text-muted); }
.icon { width: 16px; height: 16px; flex: 0 0 auto; }
.visually-hidden {
  position: absolute; width: 1px; height: 1px; margin: -1px;
  padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* ----------------------------------------------------------------- controls */

.btn {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 6px 12px; font: inherit; font-size: 14px;
  border: 1px solid var(--border-strong); border-radius: var(--radius);
  background: var(--surface); color: var(--text); cursor: pointer;
  touch-action: manipulation;
}
.btn:hover { background: var(--surface-2); }
.btn-primary { background: var(--accent); border-color: var(--accent); color: var(--accent-fg); }
.btn-primary:hover { background: var(--accent-hover); }

.icon-button {
  display: inline-flex; align-items: center; justify-content: center;
  width: 30px; height: 30px; padding: 0;
  border: 1px solid transparent; border-radius: var(--radius);
  background: none; color: var(--text-muted); cursor: pointer;
  touch-action: manipulation;
}
.icon-button:hover { background: var(--surface-3); color: var(--text); }

.field { display: block; margin: 0 0 12px; }
.field > span { display: block; margin-bottom: 4px; color: var(--text-muted); }
.field input {
  width: 100%; padding: 8px 10px;
  /* 16px is the anti-zoom floor: iOS zooms the page whenever a focused field
     computes under it. */
  font: inherit; font-size: 16px;
  border: 1px solid var(--border-strong); border-radius: var(--radius);
  background: var(--surface); color: var(--text);
}

/* -------------------------------------------------------------- the shell */

.shell {
  display: grid;
  grid-template-columns: var(--rail-w) minmax(0, 1fr);
  /* dvh, not vh: on iOS vh is the tall-URL-bar height, so the bottom of the
     page sits underneath the browser toolbar. */
  height: 100dvh;
  overflow: hidden;
}

.rail {
  grid-column: 1;
  display: flex; flex-direction: column; gap: 2px;
  padding: 12px 8px;
  background: var(--nav-bg); color: var(--nav-fg);
  overflow-y: auto;
}
.rail-brand {
  padding: 6px 10px 14px; font-weight: 600; font-size: 15px;
  color: var(--nav-fg); letter-spacing: 0.2px;
}
.rail-brand:hover { text-decoration: none; }
.rail-items { display: flex; flex-direction: column; gap: 2px; }
.rail-item {
  display: flex; align-items: center; gap: 10px;
  padding: 7px 10px; border-radius: var(--radius);
  color: var(--nav-fg-muted);
}
.rail-item:hover { background: rgba(127,127,127,.22); color: var(--nav-fg); text-decoration: none; }
/* The accessibility attribute IS the state. There is no second source of
   truth to keep in sync. */
.rail-item[aria-current="page"] { background: rgba(127,127,127,.3); color: var(--nav-fg); }
.rail-spacer { flex: 1 1 auto; }

.rail-account { margin-top: auto; }
.rail-account > summary {
  display: flex; align-items: center; gap: 6px; justify-content: space-between;
  padding: 7px 10px; border-radius: var(--radius);
  color: var(--nav-fg-muted); cursor: pointer; list-style: none;
}
.rail-account > summary::-webkit-details-marker { display: none; }
.rail-account > summary:hover { background: rgba(127,127,127,.22); color: var(--nav-fg); }

.nav-menu { position: relative; }
.nav-menu-list {
  position: absolute; bottom: 100%; left: 0; min-width: 180px; z-index: 40;
  display: flex; flex-direction: column;
  padding: 4px; margin-bottom: 4px;
  background: var(--surface); color: var(--text);
  border: 1px solid var(--border); border-radius: var(--radius);
  box-shadow: 0 8px 24px rgba(0,0,0,.24);
}
.nav-menu-list a, .nav-menu-list button {
  display: block; width: 100%; text-align: left;
  padding: 7px 10px; font: inherit;
  border: 0; border-radius: var(--radius);
  background: none; color: var(--text); cursor: pointer;
}
.nav-menu-list a:hover, .nav-menu-list button:hover { background: var(--surface-2); text-decoration: none; }
.nav-menu-list a[aria-current="page"] { background: var(--accent-soft); }
.nav-menu-list .danger { color: var(--danger); }
.nav-menu-caret { width: 14px; height: 14px; opacity: .7; }

.main { grid-column: 2; min-width: 0; min-height: 0; overflow-y: auto; }
.main .pad { padding: 20px 16px 40px; max-width: 900px; }
/* A module that owns its whole box: no page padding, no page scroll. */
.main-flush { padding: 0; overflow: hidden; display: flex; }
.main-center {
  display: flex; align-items: center; justify-content: center;
  min-height: 100dvh; padding: 20px;
}

.tabs { display: none; }

/* ------------------------------------------------------------------- boxes */

.box {
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius); margin: 0 0 16px;
}
.box-head {
  display: flex; align-items: center; gap: 10px;
  padding: 10px 14px; border-bottom: 1px solid var(--border);
  background: var(--surface-2);
  border-radius: var(--radius) var(--radius) 0 0;
}
.box-title { margin: 0; font-size: 14px; font-weight: 600; }
.box-actions { margin-left: auto; }
.box-body { padding: 14px; }
.box-body > :last-child { margin-bottom: 0; }

.session-list { list-style: none; margin: 0; padding: 0; }
.session-list li + li { border-top: 1px solid var(--border); }
.session-list a {
  display: flex; align-items: center; gap: 10px;
  padding: 10px 4px; color: var(--text);
}
.session-list a:hover { text-decoration: none; color: var(--accent); }
.session-name { font-weight: 500; }
.session-cwd { color: var(--text-muted); font-family: var(--mono); font-size: 12px; margin-left: auto; }
.dot { width: 8px; height: 8px; border-radius: 50%; background: var(--success); flex: 0 0 auto; }

/* ------------------------------------------------------------------ login */

.login {
  width: 100%; max-width: 320px;
  padding: 24px; background: var(--surface);
  border: 1px solid var(--border); border-radius: var(--radius);
}
.login-title { margin: 0 0 18px; font-size: 20px; text-align: center; }
.login-error {
  padding: 8px 10px; margin-bottom: 12px;
  color: var(--danger); background: var(--danger-soft);
  border: 1px solid var(--danger); border-radius: var(--radius);
}
.login .btn { width: 100%; justify-content: center; }

/* --------------------------------------------------------------- terminal */

.term {
  display: flex; flex-direction: column;
  flex: 1 1 auto;
  /* The flexbox rule everyone forgets. Without it the screen refuses to shrink
     and overflows the shell, which on a phone puts the key bar off screen. */
  min-height: 0;
  min-width: 0;
  background: var(--term-bg);
  position: relative;
}

.term-bar {
  display: flex; align-items: center; gap: 8px;
  flex: 0 0 auto; height: var(--termbar-h);
  padding: 0 8px;
  border-bottom: 1px solid var(--border);
  background: var(--surface);
}
.term-sessions > summary {
  display: flex; align-items: center; gap: 4px;
  padding: 5px 8px; border-radius: var(--radius);
  cursor: pointer; list-style: none; font-weight: 500;
  max-width: 40vw; overflow: hidden; white-space: nowrap; text-overflow: ellipsis;
}
.term-sessions > summary::-webkit-details-marker { display: none; }
.term-sessions > summary:hover { background: var(--surface-2); }
.term-sessions .nav-menu-list { top: 100%; bottom: auto; margin: 4px 0 0; }
.term-cwd {
  color: var(--text-muted); font-family: var(--mono); font-size: 12px;
  overflow: hidden; white-space: nowrap; text-overflow: ellipsis;
}

.term-state {
  font-size: 12px; padding: 3px 8px; border-radius: 999px;
  background: var(--surface-3); color: var(--text-muted); white-space: nowrap;
}
.term-state[data-state="open"] { background: var(--accent-soft); color: var(--accent); }
.term-state[data-state="offline"],
.term-state[data-state="error"] { background: var(--danger-soft); color: var(--danger); }
.term-state[data-state="exited"] { background: var(--surface-3); color: var(--warn); }
.term-state[data-state="stopped"] {
  background: var(--danger-soft); color: var(--danger); cursor: pointer;
}
.term-state[data-state="stopped"]:hover { text-decoration: underline; }

.term-screen {
  flex: 1 1 auto; min-height: 0;
  padding: 4px 2px 4px 6px;
  /* A swipe that reaches the top of the scrollback must not turn into a
     pull-to-refresh on the page behind it. */
  overscroll-behavior: contain;
}
.term-screen .xterm { height: 100%; }
.term-screen .xterm-viewport { background-color: transparent !important; }

/* Input is visibly dead while the socket is down, and it is obvious why:
   keystrokes are dropped rather than queued, because replaying them into a
   Claude Code prompt that has moved on could approve a tool call nobody read. */
.term[data-conn="offline"] .term-screen,
.term[data-conn="stopped"] .term-screen,
.term[data-conn="reconnecting"] .term-screen { opacity: .55; pointer-events: none; }

.term-search { flex: 0 0 auto; padding: 6px 8px; background: var(--surface-2); border-bottom: 1px solid var(--border); }
.term-search input {
  width: 100%; padding: 6px 10px; font: inherit; font-size: 16px;
  border: 1px solid var(--border-strong); border-radius: var(--radius);
  background: var(--surface); color: var(--text);
}

.term-drop {
  position: absolute; inset: 0; z-index: 20;
  display: none; align-items: center; justify-content: center;
  background: rgba(9, 105, 218, .18);
  border: 2px dashed var(--accent);
  color: var(--accent-fg); font-weight: 600; pointer-events: none;
}
.term[data-drop="over"] .term-drop { display: flex; }
.term-drop span { padding: 8px 16px; background: var(--accent); border-radius: var(--radius); }

/* ------------------------------------------------------------- the key bar
   Shown by capability, not by width: a tablet at 1400px with a touchscreen
   wants it, a 700px desktop window does not. */

.term-keys { display: none; }

@media (pointer: coarse) {
  .term-keys[data-role="keybar"]:not([hidden]) {
    display: flex; flex: 0 0 auto; gap: 4px;
    height: calc(var(--keybar-h) + var(--safe-b));
    padding: 4px 6px calc(4px + var(--safe-b));
    overflow-x: auto; overflow-y: hidden;
    scrollbar-width: none;
    background: var(--surface-2);
    border-top: 1px solid var(--border);
    /* One horizontal swipe lane. Without this a drag along the bar scrolls the
       page and the button never fires. */
    touch-action: pan-x;
    overscroll-behavior-x: contain;
    -webkit-overflow-scrolling: touch;
  }
}
.term-keys::-webkit-scrollbar { display: none; }

.tkey {
  flex: 0 0 auto; min-width: 42px; height: 36px; padding: 0 9px;
  font-family: var(--mono); font-size: 15px;
  border: 1px solid var(--border-strong); border-radius: var(--radius);
  background: var(--surface); color: var(--text);
  /* Kills the 300ms tap delay and double-tap-to-zoom on the bar. */
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
  user-select: none; cursor: pointer;
}
.tkey:active { background: var(--surface-3); }
.tkey[aria-pressed="true"] { background: var(--accent); border-color: var(--accent); color: var(--accent-fg); }
/* Locked by a double tap: same colour, plus a ring to say it stays on. */
.tkey[data-lock="on"] { box-shadow: 0 0 0 2px var(--accent-soft); }

.key-sheet {
  border: 1px solid var(--border); border-radius: var(--radius);
  background: var(--surface); color: var(--text); padding: 14px;
  max-width: min(420px, 92vw);
}
.key-sheet::backdrop { background: rgba(0,0,0,.5); }
.key-sheet-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(56px, 1fr));
  gap: 6px; margin-bottom: 12px;
}

/* THE anti-zoom rule. iOS zooms whenever a focused field computes under 16px,
   and xterm's helper textarea inherits the terminal's font size — 13px on a
   phone. It is 0x0 and transparent, so this size is never seen; it exists only
   to stop the zoom. */
.xterm-helper-textarea { font-size: 16px !important; }

/* --------------------------------------------------------------- dialogs */

.modal {
  border: 1px solid var(--border); border-radius: var(--radius);
  background: var(--surface); color: var(--text);
  padding: 18px; width: min(460px, 92vw);
}
.modal::backdrop { background: rgba(0,0,0,.5); }
.modal textarea {
  width: 100%; font: inherit; font-size: 16px; padding: 8px;
  border: 1px solid var(--border-strong); border-radius: var(--radius);
  background: var(--surface); color: var(--text);
}
.modal-actions { display: flex; gap: 8px; justify-content: flex-end; margin-top: 14px; }
.modal-error { color: var(--danger); }
.picker-roots { display: flex; gap: 6px; flex-wrap: wrap; }
.chip {
  padding: 4px 10px; font: inherit; font-size: 13px;
  border: 1px solid var(--border-strong); border-radius: 999px;
  background: var(--surface); color: var(--text); cursor: pointer;
}
.picker-path { font-family: var(--mono); font-size: 12px; color: var(--text-muted); margin: 8px 0 4px; }
.picker-list {
  max-height: 220px; overflow-y: auto;
  border: 1px solid var(--border); border-radius: var(--radius);
}
.picker-item {
  display: block; width: 100%; text-align: left;
  padding: 6px 10px; font: inherit; font-family: var(--mono); font-size: 13px;
  border: 0; background: none; color: var(--text); cursor: pointer;
}
.picker-item:hover { background: var(--surface-2); }

/* ----------------------------------------------------------------- phone */

@media (max-width: 820px) {
  .shell {
    grid-template-columns: minmax(0, 1fr);
    /* The visual viewport, not the layout viewport. When the iOS keyboard
       opens innerHeight does not change but visualViewport.height does, and
       this is the number that keeps the last terminal line above it. */
    height: var(--vvh);
  }

  .rail { display: none; }

  .tabs {
    display: flex; align-items: stretch;
    position: fixed; left: 0; right: 0; bottom: 0; z-index: 30;
    height: calc(var(--tabbar-h) + var(--safe-b));
    padding-bottom: var(--safe-b);
    background: var(--nav-bg);
    /* Rides up with the keyboard, exactly like the key bar. */
    transform: translateY(calc(-1 * var(--kb)));
  }
  .tabs .rail-item {
    flex: 1 1 0; flex-direction: column; gap: 2px; justify-content: center;
    font-size: 11px; border-radius: 0;
  }

  /* With the keyboard up the tab bar is noise and the key bar needs the room.
     This is state, not size, which is why it is an attribute and not a query. */
  body[data-kb="open"] .tabs { display: none; }

  .main { padding-bottom: calc(var(--tabbar-h) + var(--safe-b)); }
  .main-flush { padding-bottom: 0; }
  body[data-kb="open"] .main { padding-bottom: 0; }

  .term-cwd { display: none; }
  .term-sessions > summary { max-width: 45vw; }
  .main .pad { padding: 16px 12px 32px; }
}

@media (prefers-reduced-motion: reduce) {
  * { animation-duration: .01ms !important; transition-duration: .01ms !important; }
}
