:root{
  --cream:#FBF8F2; --sand:#F4EEE0; --white:#FFFFFF;

  /* Surfaces, so the sidebar and terminal can be themed without every rule
     knowing which palette it is painting onto. */
  --side-bg:#12213D; --side-fg:#E3E8F0; --side-muted:#8C9AB6;
  --side-line:#29385A; --side-active:#1B2C4C; --side-title:#FFFFFF;
  --term-bg:#12213D; --term-fg:#E3E8F0; --term-muted:#8C9AB6;
  --term-line:#29385A; --term-bright:#FFFFFF; --term-accent:#7FBBAD;
  --page-bg:#FBF8F2; --surface:#FFFFFF; --field-bg:#FFFFFF;
  --ink:#12213D; --body:#3E4A63; --muted:#5B6478;
  --teal:#1F6F63; --teal-dark:#15544A; --teal-light:#7FBBAD; --teal-pale:#DCEEE9; --teal-line:#C7DED8;
  --line:#E3DDCE; --line-warm:#C7BFA8;
  --navy-card:#1B2C4C; --navy-line:#29385A;
  --on-navy:#E3E8F0; --on-navy-soft:#B8C2D6; --on-navy-mute:#8C9AB6;
  --amber:#D9A15B; --rust:#B0503F;
  --warn-bg:#FBF3E7; --warn-line:#E8D2A8; --warn-ink:#5B4426;
  --danger-bg:#FBEDEA; --danger-line:#E8C3BB; --danger-ink:#7A3325;
  --ok-bg:#E9F2F0; --ok-line:#9DC6BD; --ok-ink:#15544A;
  color-scheme:light;
  --serif:'Fraunces',Georgia,serif;
  --sans:'IBM Plex Sans',system-ui,-apple-system,sans-serif;
  --mono:'SFMono-Regular',Menlo,Consolas,'Liberation Mono',monospace;
}
html[data-theme="light"]{
  --cream:#FFFFFF; --sand:#F4F6F8; --page-bg:#FFFFFF; --surface:#FFFFFF;
  --line:#E2E6EB; --line-warm:#CBD2DA; --muted:#5A6572; --body:#38414E;
  --ink:#141A22; --field-bg:#FFFFFF;
  --side-bg:#F7F8FA; --side-fg:#38414E; --side-muted:#5E6773;
  --side-line:#E2E6EB; --side-active:#E9EDF2; --side-title:#141A22;
  --term-bg:#F7F8FA; --term-fg:#2B3440; --term-muted:#6B7480;
  --term-line:#E2E6EB; --term-bright:#141A22; --term-accent:#12695C;
  --teal:#12695C; --teal-dark:#0C4F45; --teal-light:#12695C; --teal-pale:#E6F1EF;
  /*
   * Restated for white, not inherited. The warm palette's tints and edges are
   * cream on cream; against white they wash out — a badge outline measured
   * 1.42:1, so it read as floating text rather than a chip. Borders clear 3:1
   * and text clears 4.5:1 against their own fill.
   */
  --warn-bg:#FFF3D4; --warn-line:#B0851C; --warn-ink:#6B4A0F;
  --danger-bg:#FDEAE6; --danger-line:#CF7A66; --danger-ink:#8C2F20;
  --ok-bg:#E4F1EE; --ok-line:#4E9C8D; --ok-ink:#0C4F45;
  --amber:#8A5A16; --rust:#A33A28;
}

*,*::before,*::after{box-sizing:border-box;}
body{margin:0;font-family:var(--sans);background:var(--page-bg);color:var(--ink);-webkit-font-smoothing:antialiased;}
a{color:var(--teal);text-decoration:none;}
a:hover{color:var(--teal-dark);}
a:focus-visible,button:focus-visible,input:focus-visible,select:focus-visible{outline:2px solid var(--teal);outline-offset:2px;}
h1,h2,h3{font-family:var(--serif);font-weight:600;margin:0;}
p{margin:0;}
.mono{font-family:var(--mono);}
.dim{color:var(--muted);}
.hidden{display:none !important;}

/* ---------- auth pages ---------- */
.auth{min-height:100vh;display:grid;grid-template-columns:1fr 1fr;}
.auth-aside{background:var(--ink);color:var(--white);padding:56px 48px;display:flex;flex-direction:column;justify-content:space-between;}
.auth-aside .brand{font-family:var(--serif);font-weight:700;font-size:22px;color:var(--white);}
.auth-aside h2{font-size:30px;line-height:1.2;color:var(--white);margin-top:auto;}
.auth-aside ul{list-style:none;padding:0;margin:22px 0 0;display:flex;flex-direction:column;gap:12px;}
.auth-aside li{font-size:15px;color:var(--on-navy-soft);display:flex;gap:10px;align-items:flex-start;}
.auth-aside li::before{content:"✓";color:var(--teal-light);font-weight:700;flex-shrink:0;}
.auth-aside .foot{font-size:13px;color:var(--on-navy-mute);margin-top:32px;}
.auth-main{display:flex;align-items:center;justify-content:center;padding:48px 24px;}
.auth-card{width:100%;max-width:440px;}
.auth-card h1{font-size:30px;line-height:1.2;}
.auth-card .sub{font-size:15px;color:var(--muted);margin-top:10px;}

/* ---------- forms ---------- */
.field{margin-top:20px;}
.field label{display:block;font-size:14px;font-weight:600;margin-bottom:6px;}
.field .hint{font-size:13px;color:var(--muted);margin-bottom:6px;}
.field input,.field select{width:100%;padding:11px 13px;font:inherit;font-size:15px;color:var(--ink);
  background:var(--field-bg);border:1px solid var(--line-warm);border-radius:8px;}
.field input:focus,.field select:focus{border-color:var(--teal);}
.field.bad input,.field.bad select{border-color:var(--rust);}
.field .err{font-size:13px;color:var(--rust);margin-top:6px;display:none;}
.field.bad .err{display:block;}
.row2{display:grid;grid-template-columns:1fr 1fr;gap:16px;}
button{font:inherit;cursor:pointer;border:0;border-radius:8px;font-weight:600;transition:background-color .15s ease;}
.btn{background:var(--teal);color:var(--cream);padding:12px 20px;font-size:15px;}
.btn:hover{background:var(--teal-dark);}
.btn:disabled{opacity:.6;cursor:not-allowed;}
.btn-block{display:block;width:100%;margin-top:26px;}
.btn-ghost{background:transparent;border:1px solid var(--line-warm);color:var(--ink);padding:10px 16px;font-size:14px;}
.btn-ghost:hover{border-color:var(--teal);color:var(--teal);background:transparent;}
.btn-ghost[aria-pressed="true"]{border-color:var(--teal);color:var(--teal);background:var(--teal-pale);}

/* On dark surfaces the ink-coloured label disappeared entirely. */
.side .btn-ghost,.term-head .btn-ghost{
  border-color:var(--side-line);color:var(--side-fg);
}
.side .btn-ghost:hover,.term-head .btn-ghost:hover{
  border-color:var(--term-accent);color:var(--term-accent);background:transparent;
}
.btn-sm{padding:8px 14px;font-size:14px;}
/* Small read-only tokens — the egress baseline, which is a list of facts
   rather than a set of controls. `.chips` carries the gap; without it the
   patterns render as one unreadable run of text. */
.chips{display:flex;flex-wrap:wrap;gap:8px;}
.chip{background:var(--sand);border:1px solid var(--line);border-radius:100px;
  font-size:13px;color:var(--body);padding:5px 12px;white-space:nowrap;}

.alert{margin-top:20px;padding:12px 14px;border-radius:8px;font-size:14px;line-height:1.55;display:none;}
.alert.show{display:block;}
.alert-error{background:var(--danger-bg);border:1px solid var(--danger-line);color:var(--danger-ink);}
.alert-info{background:var(--warn-bg);border:1px solid var(--warn-line);color:var(--warn-ink);}
.switch{margin-top:24px;font-size:14px;color:var(--muted);text-align:center;}

/* ---------- app shell ---------- */
/*
 * The sidebar collapses to a rail and slides out on hover, PUSHING the content
 * rather than covering it. It stays in the grid: the column itself animates, so
 * the main pane shrinks to match instead of sliding underneath.
 *
 * That does reflow the terminal, which xterm has to be told about — the width
 * it last measured is stale the moment this transition ends. `app.js` refits on
 * transitionend rather than on every animation frame, so the terminal reflows
 * once per hover instead of sixty times.
 */
.shell{
  display:grid;
  grid-template-columns:var(--side-w,240px) 1fr;
  min-height:100vh;
  transition:grid-template-columns .18s cubic-bezier(.4,0,.2,1);
}
html[data-rail="on"] .shell{grid-template-columns:62px 1fr;}
html[data-rail="on"][data-rail-open="true"] .shell{grid-template-columns:248px 1fr;}

.side{overflow:hidden;}
html[data-rail="on"] .side{
  position:relative;width:auto;z-index:20;
  transition:box-shadow .18s ease;
}
html[data-rail="on"][data-rail-open="true"] .side{
  box-shadow:6px 0 28px -14px rgba(18,33,61,.35);
}
@media (prefers-reduced-motion:reduce){
  .shell{transition:none;}
}
/* Labels are faded and pulled out of the layout so they cannot force a
   horizontal scrollbar while the rail is narrow. */
html[data-rail="on"] .side .label,
html[data-rail="on"] .side .ctx,
html[data-rail="on"] .side .theme-row,
html[data-rail="on"] .side #signout{
  opacity:0;pointer-events:none;transition:opacity .12s ease;white-space:nowrap;
}
html[data-rail="on"][data-rail-open="true"] .side .label,
html[data-rail="on"][data-rail-open="true"] .side .ctx,
html[data-rail="on"][data-rail-open="true"] .side .theme-row,
html[data-rail="on"][data-rail-open="true"] .side #signout{opacity:1;pointer-events:auto;}
html[data-rail="on"] .side .brand-mark{display:inline-flex;}
html[data-rail="on"][data-rail-open="true"] .side .brand-mark{display:none;}
/* The toggle is only reachable once the rail is open; collapsed, it just
   collided with the brand mark in 62px of space. Its width goes too, not only
   its opacity — a 29px invisible button still squeezes the 30px tile. It is
   not `display:none`, so it stays reachable by keyboard: focusing it opens the
   rail through :focus-within, which brings it back into view. */
html[data-rail="on"] .side .rail-toggle{
  opacity:0;pointer-events:none;width:0;padding:0;overflow:hidden;
  transition:opacity .12s ease;
}
html[data-rail="on"][data-rail-open="true"] .side .rail-toggle{
  opacity:1;pointer-events:auto;width:auto;padding:6px;
}
/* Collapsed, the rail leaves 30px of usable width — exactly one tile — so the
   row gives up its own padding and centres what is left. */
html[data-rail="on"] .side-top{padding-left:0;padding-right:0;justify-content:center;gap:0;}
html[data-rail="on"] .side .brand{padding:0;gap:0;}
/* Fading a label leaves its width behind, and the width is the problem: an
   icon centred together with a 70px invisible label is pushed out of a 30px
   rail and clipped away entirely. They are given no width until the rail
   opens. */
html[data-rail="on"] .side .label{width:0;overflow:hidden;}
html[data-rail="on"][data-rail-open="true"] .side .label{width:auto;overflow:visible;}
html[data-rail="on"][data-rail-open="true"] .side-top{
  padding-left:6px;padding-right:6px;justify-content:space-between;gap:6px;
}
html[data-rail="on"][data-rail-open="true"] .side .brand{padding:0 4px;gap:8px;}
/* Same arithmetic for the nav: 18px icon plus 22px of padding does not fit in
   30px, so the icons are centred instead of left-aligned while collapsed. */
html[data-rail="on"] .side nav button{justify-content:center;padding-left:0;padding-right:0;gap:0;}
html[data-rail="on"][data-rail-open="true"] .side nav button{
  justify-content:flex-start;padding-left:11px;padding-right:11px;gap:11px;
}
@media (prefers-reduced-motion:reduce){
  html[data-rail="on"] .side{transition:none;}
}
.side{background:var(--side-bg);color:var(--side-fg);border-right:1px solid var(--side-line);padding:20px 16px;display:flex;flex-direction:column;gap:6px;}
.side-top{display:flex;align-items:center;justify-content:space-between;gap:6px;padding:4px 6px 14px;}
.side .brand{font-family:var(--serif);font-weight:700;font-size:19px;color:var(--side-title);
  display:flex;align-items:center;gap:8px;padding:0 4px;min-width:0;}
.brand-mark{display:none;width:30px;height:30px;border-radius:8px;background:var(--side-active);
  color:var(--side-title);align-items:center;justify-content:center;font-size:13px;letter-spacing:.02em;flex-shrink:0;}
.rail-toggle{background:transparent;border:0;color:var(--side-muted);padding:6px;border-radius:7px;
  display:flex;align-items:center;flex-shrink:0;}
.rail-toggle:hover{background:var(--side-active);color:var(--side-title);}
.rail-toggle svg{width:17px;height:17px;}
.side nav{display:flex;flex-direction:column;gap:2px;}
.side nav button{background:transparent;color:var(--side-fg);text-align:left;padding:9px 11px;
  border-radius:7px;font-size:14px;font-weight:500;display:flex;align-items:center;gap:11px;
  white-space:nowrap;overflow:hidden;}
.side nav button svg{width:18px;height:18px;flex-shrink:0;}
.side nav button:hover{background:var(--side-active);color:var(--side-title);}
.side nav button[aria-current="true"]{background:var(--side-active);color:var(--side-title);font-weight:600;}
.side .ctx{margin-top:auto;border-top:1px solid var(--side-line);padding-top:14px;font-size:12px;line-height:1.7;}
.side .ctx .k{color:var(--side-muted);text-transform:uppercase;letter-spacing:.06em;font-size:10px;}
.side .ctx .v{color:var(--side-title);font-weight:500;}
.main{display:flex;flex-direction:column;min-width:0;overflow-x:hidden;}
.content{min-width:0;}
.topbar{border-bottom:1px solid var(--line);padding:14px 28px;display:flex;align-items:center;justify-content:space-between;gap:16px;background:var(--page-bg);}
.topbar h1{font-size:20px;}
.content{padding:28px;flex:1;min-width:0;}
.panel{display:none;}
.panel.on{display:block;}

/* ---------- lists & cards ---------- */
.card{background:var(--surface);border:1px solid var(--line);border-radius:12px;padding:20px;}
.stack{display:flex;flex-direction:column;gap:12px;}
.list{background:var(--surface);border:1px solid var(--line);border-radius:12px;overflow:hidden;}
.list-item{display:flex;align-items:center;justify-content:space-between;gap:16px;padding:14px 18px;border-bottom:1px solid var(--line);}
.list-item:last-child{border-bottom:0;}
.list-item .name{font-weight:600;font-size:15px;}
.list-item .meta{font-size:13px;color:var(--muted);}
.list-item button{background:transparent;color:var(--teal);font-size:14px;padding:6px 10px;}
.empty{padding:36px;text-align:center;color:var(--muted);font-size:15px;}
.toolbar{display:flex;align-items:center;justify-content:space-between;gap:16px;margin-bottom:18px;flex-wrap:wrap;}
.tag{display:inline-block;background:var(--sand);border:1px solid var(--line);border-radius:100px;font-size:12px;color:var(--body);padding:3px 10px;}

/* ---------- terminal ---------- */
.term-wrap{background:var(--term-bg);border:1px solid var(--term-line);border-radius:12px;overflow:hidden;display:flex;flex-direction:column;height:calc(100vh - 150px);min-height:420px;}
.term-head{padding:12px 18px;border-bottom:1px solid var(--term-line);display:flex;gap:22px;flex-wrap:wrap;font-size:11px;}
.term-head .k{color:var(--term-muted);text-transform:uppercase;letter-spacing:.07em;}
.term-head .v{color:var(--term-bright);font-weight:600;margin-left:6px;}
.term-out{flex:1;overflow-y:auto;padding:16px 18px;font-family:var(--mono);font-size:13px;line-height:1.65;}
.term-out .l{white-space:pre-wrap;word-break:break-word;color:var(--term-fg);}
.term-out .l.dim{color:var(--term-muted);}
.term-out .l.ok{color:var(--term-accent);}
.term-out .l.warn{color:var(--amber);}
.term-out .l.error{color:#E39B7F;}
.term-out .l.head{color:var(--term-bright);font-weight:700;}
.term-out .l.echo{color:var(--term-accent);}
.term-out .l.kv{display:flex;gap:14px;}
.term-out .l.kv .lab{color:var(--term-muted);min-width:190px;flex-shrink:0;}
.term-out .l.kv .val{color:var(--term-bright);}
.term-out hr{border:0;border-top:1px solid var(--term-line);margin:8px 0;}
.term-in{display:flex;align-items:center;gap:10px;border-top:1px solid var(--term-line);padding:12px 18px;}
.term-in span{color:var(--term-accent);font-family:var(--mono);font-size:13px;}
.term-in input{flex:1;background:transparent;border:0;outline:0;color:var(--term-bright);font-family:var(--mono);font-size:13px;}

/* ---------- drop zone ---------- */
.drop{border:2px dashed var(--line-warm);border-radius:12px;padding:32px;text-align:center;background:var(--white);transition:border-color .15s ease,background-color .15s ease;}
.drop.over{border-color:var(--teal);background:var(--teal-pale);}
.drop p{font-size:15px;color:var(--muted);}
.drop strong{color:var(--ink);}

@media (max-width:820px){
  .auth{grid-template-columns:1fr;}
  .auth-aside{display:none;}
  /* Two rows, the bar sized by its content. Without the explicit rows the
     grid stretches both to fill `min-height:100vh` and the bar becomes a
     third of the screen. */
  .shell{grid-template-columns:1fr;grid-template-rows:auto 1fr;}
  .side{flex-direction:row;align-items:center;gap:10px;overflow-x:auto;padding:12px;}
  /* The rail is a desktop affordance. Here the sidebar is a bar across the
     top, so everything the collapsed rail does — taking it out of the flow,
     narrowing it, and giving its labels no width — is undone. */
  html[data-rail="on"] .side,
  html[data-rail="on"][data-rail-open="true"] .side{position:static;width:auto;box-shadow:none;}
  html[data-rail="on"] .shell,
  html[data-rail="on"][data-rail-open="true"] .shell{
    grid-template-columns:1fr;grid-template-rows:auto 1fr;
  }
  html[data-rail="on"] .main{grid-column:auto;}
  html[data-rail="on"] .side .label,
  html[data-rail="on"] .side .ctx,
  html[data-rail="on"] .side .theme-row,
  html[data-rail="on"] .side #signout{opacity:1;pointer-events:auto;}
  html[data-rail="on"] .side .label{width:auto;overflow:visible;}
  html[data-rail="on"] .side-top{padding:0;justify-content:flex-start;gap:6px;}
  html[data-rail="on"] .side .brand{gap:8px;}
  html[data-rail="on"] .side nav button{
    justify-content:flex-start;padding-left:11px;padding-right:11px;gap:11px;
  }
  html[data-rail="on"] .side .brand-mark{display:none;}
  /* Nothing to collapse when the sidebar is a bar, and an invisible focusable
     control is worse than an absent one. */
  html[data-rail="on"] .rail-toggle,
  .rail-toggle{display:none;}
  .side .brand{padding:0 8px 0 4px;}
  .side nav{flex-direction:row;}
  .side .ctx{display:none;}
  .row2{grid-template-columns:1fr;}
  .content{padding:18px;}
}

/* Theme switch, in the sidebar footer. */
.theme-row{display:flex;gap:6px;margin-top:12px;}
.theme-row button{
  flex:1;background:transparent;border:1px solid var(--side-line);color:var(--side-muted);
  padding:6px 8px;font-size:12px;font-weight:600;border-radius:7px;
}
.theme-row button:hover{color:var(--side-title);border-color:var(--term-accent);}
.theme-row button[aria-pressed="true"]{
  background:var(--side-active);color:var(--side-title);border-color:var(--term-accent);
}

/* First-run sign-in dialog. */
.modal{position:fixed;inset:0;z-index:60;display:flex;align-items:center;justify-content:center;
  padding:24px;background:rgba(18,33,61,.55);backdrop-filter:blur(3px);}
.modal[hidden]{display:none;}
.modal-card{background:var(--surface);border:1px solid var(--line);border-radius:14px;
  padding:28px;max-width:520px;width:100%;box-shadow:0 24px 60px -24px rgba(18,33,61,.45);}
.modal-card h2{font-size:21px;line-height:1.25;}
.modal-card .modal-body{font-size:15px;line-height:1.65;color:var(--body);margin-top:12px;}
.modal-card .field{margin-top:0;}

/* Context-change notice, above the terminal and outside its stream. */
#agent-notice{
  margin:0 10px 6px;padding:7px 12px;border-radius:7px;font-size:13px;
  background:var(--side-active);color:var(--term-bright);
  border:1px solid var(--term-accent);
}

/* Linking progress.
   Named stages, because the operator is waiting on an OAuth round trip and a
   write they cannot see. The active one animates so a slow step still reads as
   moving; a finished one is ticked and stops. */
.prog{list-style:none;margin:16px 0 0;padding:0;display:flex;flex-direction:column;gap:2px;}
.prog-step{position:relative;padding:7px 0 7px 28px;font-size:14px;color:var(--muted);
  transition:color .2s ease;}
.prog-step::before{content:"";position:absolute;left:4px;top:50%;width:9px;height:9px;
  margin-top:-4.5px;border-radius:50%;border:1.5px solid var(--line-warm);box-sizing:border-box;}
.prog-step[data-state="active"]{color:var(--ink);font-weight:600;}
.prog-step[data-state="active"]::before{border-color:var(--teal);background:var(--teal);
  animation:prog-pulse 1.25s ease-in-out infinite;}
.prog-step[data-state="done"]{color:var(--body);}
.prog-step[data-state="done"]::before{border-color:var(--teal);background:var(--teal);}
.prog-step[data-state="done"]::after{content:"";position:absolute;left:6.5px;top:50%;width:3px;height:6px;
  margin-top:-4px;border:solid var(--surface);border-width:0 1.5px 1.5px 0;transform:rotate(45deg);}
.prog-step[data-state="failed"]{color:var(--ink);font-weight:600;}
.prog-step[data-state="failed"]::before{border-color:#B0503F;background:#B0503F;}
@keyframes prog-pulse{0%,100%{box-shadow:0 0 0 0 rgba(31,111,99,.45);}50%{box-shadow:0 0 0 5px rgba(31,111,99,0);}}

/* The card arrives, and on success minimises away toward the terminal rather
   than vanishing between frames. */
.modal:not([hidden]){animation:modal-in .18s ease-out;}
.modal:not([hidden]) .modal-card{animation:card-in .26s cubic-bezier(.2,.8,.3,1);}
.modal[data-closing="true"]{animation:modal-in .38s ease-in reverse forwards;pointer-events:none;}
.modal[data-closing="true"] .modal-card{animation:card-out .38s cubic-bezier(.4,0,.2,1) forwards;}
@keyframes modal-in{from{opacity:0;}to{opacity:1;}}
@keyframes card-in{from{opacity:0;transform:translateY(8px) scale(.97);}to{opacity:1;transform:none;}}
@keyframes card-out{to{opacity:0;transform:translateY(40px) scale(.82);}}

/* Collapses the code form out of the way as the progress list takes its place. */
.fold-out{animation:fold-out .2s ease-in forwards;overflow:hidden;}
@keyframes fold-out{to{opacity:0;transform:translateY(-6px);}}

@media (prefers-reduced-motion:reduce){
  .modal:not([hidden]),.modal:not([hidden]) .modal-card,
  .modal[data-closing="true"],.modal[data-closing="true"] .modal-card,
  .prog-step[data-state="active"]::before,.fold-out{animation:none !important;}
  .modal[data-closing="true"]{opacity:0;}
}

/* ---------- document browser ---------- */
.fs-bar{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin-bottom:14px;}
.fs-areas{display:flex;gap:4px;background:var(--sand);border:1px solid var(--line);
  border-radius:9px;padding:3px;flex-wrap:wrap;}
.fs-areas button{background:transparent;color:var(--muted);padding:6px 11px;font-size:13px;
  font-weight:600;border-radius:6px;}
.fs-areas button:hover{color:var(--ink);}
.fs-areas button[aria-pressed="true"]{background:var(--surface);color:var(--ink);
  box-shadow:0 1px 2px rgba(18,33,61,.09);}
.fs-search{flex:1;min-width:190px;}
.fs-search input{width:100%;padding:8px 12px;font:inherit;font-size:14px;color:var(--ink);
  background:var(--field-bg);border:1px solid var(--line-warm);border-radius:8px;}
.fs-search input:focus{border-color:var(--teal);outline:none;}
.crumbs{display:flex;align-items:center;gap:5px;flex-wrap:wrap;font-size:14px;margin-bottom:12px;}
.crumbs button{background:transparent;color:var(--teal);padding:3px 5px;font-size:14px;
  font-weight:600;border-radius:5px;}
.crumbs button:hover{background:var(--sand);}
.crumbs span{color:var(--muted);}
.crumbs .here{color:var(--ink);font-weight:600;padding:3px 5px;}

.fs{background:var(--surface);border:1px solid var(--line);border-radius:12px;overflow:hidden;
  position:relative;min-height:320px;}
.fs.drop-active{border-color:var(--teal);box-shadow:inset 0 0 0 2px var(--teal-pale);}
.fs-head,.fs-row{display:grid;grid-template-columns:1fr 110px 170px 88px;gap:12px;align-items:center;
  padding:10px 16px;}
.fs-head{border-bottom:1px solid var(--line);background:var(--sand);}
.fs-head button{background:transparent;color:var(--body);font-size:12px;font-weight:700;
  letter-spacing:.05em;text-transform:uppercase;text-align:left;padding:2px 0;display:flex;
  align-items:center;gap:5px;}
.fs-head button:hover{color:var(--ink);}
.fs-head .arrow{opacity:0;font-size:10px;}
.fs-head button[data-active="true"] .arrow{opacity:1;}
.fs-row{border-bottom:1px solid var(--line);font-size:14px;cursor:default;}
.fs-row .fs-name button{color:var(--ink);}
.fs-row:last-child{border-bottom:0;}
.fs-row:hover{background:var(--sand);}
.fs-row.drag-over{background:var(--teal-pale);box-shadow:inset 0 0 0 2px var(--teal);}
.fs-row.dragging{opacity:.45;}
.fs-name{display:flex;align-items:center;gap:10px;min-width:0;}
.fs-name svg{width:17px;height:17px;flex-shrink:0;color:var(--muted);}
.fs-row[data-kind="folder"] .fs-name svg{color:var(--teal);}
.fs-name button{background:transparent;color:inherit;font-size:14px;padding:0;text-align:left;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-weight:500;}
.fs-name button:hover{color:var(--teal);text-decoration:underline;}
.fs-meta{color:var(--muted);font-size:13px;white-space:nowrap;}
.fs-actions{display:flex;gap:4px;justify-content:flex-end;}
.fs-actions button,.fs-actions a{background:transparent;color:var(--teal);padding:4px 8px;
  border-radius:6px;font-size:12px;font-weight:600;text-decoration:none;}
.fs-actions button:hover,.fs-actions a:hover{background:var(--sand);color:var(--teal);}
.fs-empty{padding:52px 24px;text-align:center;color:var(--muted);font-size:15px;}
.fs-drop-hint{position:absolute;inset:0;display:none;align-items:center;justify-content:center;
  background:var(--teal-pale);color:var(--teal-dark);font-weight:600;font-size:16px;
  border-radius:12px;pointer-events:none;z-index:5;}
.fs.drop-active .fs-drop-hint{display:flex;}
.fs-status{font-size:13px;color:var(--muted);margin-top:12px;min-height:18px;}
.readonly-note{background:var(--warn-bg);border:1px solid var(--warn-line);color:var(--warn-ink);
  /* A left rule gives the banner an edge that survives on white, where a
     1px cream outline did not read as a boundary at all. */
  border-left-width:4px;
  border-radius:8px;padding:9px 13px;font-size:13px;margin-bottom:12px;}

/* preview */
.viewer{position:fixed;inset:0;z-index:70;display:flex;flex-direction:column;
  background:rgba(18,33,61,.72);backdrop-filter:blur(3px);padding:28px;}
.viewer[hidden]{display:none;}
.viewer-bar{display:flex;align-items:center;justify-content:space-between;gap:16px;
  color:#fff;padding-bottom:14px;flex-wrap:wrap;}
.viewer-bar .name{font-weight:600;font-size:15px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
.viewer-bar .sub{font-size:12px;color:#B8C2D6;font-family:var(--mono);}
.viewer-bar .acts{display:flex;gap:8px;flex-shrink:0;}
.viewer-bar a,.viewer-bar button{background:rgba(255,255,255,.12);color:#fff;border:0;
  padding:7px 13px;border-radius:7px;font-size:13px;font-weight:600;text-decoration:none;}
.viewer-bar a:hover,.viewer-bar button:hover{background:rgba(255,255,255,.22);color:#fff;}
.viewer-body{flex:1;background:var(--surface);border-radius:12px;overflow:auto;min-height:0;}
.viewer-body iframe,.viewer-body img{display:block;width:100%;height:100%;border:0;}
.viewer-body img{object-fit:contain;background:var(--sand);}
.viewer-body pre{margin:0;padding:22px;font-family:var(--mono);font-size:13px;line-height:1.6;
  white-space:pre-wrap;word-break:break-word;color:var(--ink);}
.viewer-body .unsupported{padding:56px;text-align:center;color:var(--muted);}

/* Retrieval results, which are passages rather than rows. */
.hit{border-bottom:1px solid var(--line);padding:14px 16px;}
.hit:last-child{border-bottom:0;}
.hit-head{display:flex;align-items:baseline;gap:10px;flex-wrap:wrap;margin-bottom:6px;}
.hit-head button{background:transparent;color:var(--teal);font-weight:600;font-size:14px;padding:0;}
.hit-head button:hover{text-decoration:underline;}
.hit-meta{font-size:12px;color:var(--muted);}
.hit-text{font-size:13px;line-height:1.65;color:var(--body);white-space:pre-wrap;
  max-height:5.2em;overflow:hidden;}
.hit mark{background:var(--teal-pale);color:var(--teal-dark);padding:0 2px;border-radius:3px;}
.badge{display:inline-block;font-size:11px;font-weight:700;letter-spacing:.02em;padding:3px 9px;
  border-radius:100px;background:var(--ok-bg);color:var(--ok-ink);border:1px solid var(--ok-line);
  white-space:nowrap;vertical-align:middle;}
.badge.pending{background:var(--warn-bg);border-color:var(--warn-line);color:var(--warn-ink);}
.badge.review{background:var(--danger-bg);border-color:var(--danger-line);color:var(--danger-ink);}

/* ---------- command palette ----------
   Sits between the scrollback and the prompt, inside the terminal panel, so
   the list grows upward from where you are typing rather than covering what
   you have just read. It uses the terminal's own surface tokens, which is why
   it stays legible in both themes without a second set of colours. */
.palette{
  border-top:1px solid var(--term-line);
  background:var(--term-bg);
  max-height:46vh;
  overflow-y:auto;
}
.palette-list{display:flex;flex-direction:column;}
.palette-row{
  display:grid;
  grid-template-columns:minmax(12ch,28ch) 1fr auto;
  gap:14px;
  align-items:baseline;
  width:100%;
  padding:7px 18px;
  border:0;
  border-left:2px solid transparent;
  background:none;
  font-family:var(--mono);
  font-size:13px;
  line-height:1.6;
  text-align:left;
  color:var(--term-fg);
  cursor:pointer;
}
.palette-row.on{background:var(--term-line);border-left-color:var(--term-accent);}
.palette-row:disabled{cursor:default;opacity:.55;}
.palette-name{color:var(--term-bright);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
.palette-summary{color:var(--term-muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
.palette-tag{
  font-family:var(--sans);
  font-size:10px;
  letter-spacing:.07em;
  text-transform:uppercase;
  padding:1px 8px;
  border-radius:999px;
  border:1px solid var(--term-line);
  color:var(--term-muted);
  white-space:nowrap;
}
/* Only the class that stops and asks is coloured. Tinting all three would make
   the one that matters into just another badge. */
.palette-tag.t-execute{color:var(--warn-ink);border-color:var(--warn-line);background:var(--warn-bg);}
.palette-why{grid-column:2 / -1;font-family:var(--sans);font-size:12px;color:var(--term-muted);}
.palette-foot{
  padding:6px 18px;
  border-top:1px solid var(--term-line);
  font-family:var(--sans);
  font-size:11px;
  color:var(--term-muted);
}
@media (max-width:720px){
  .palette-row{grid-template-columns:1fr auto;}
  .palette-summary{grid-column:1 / -1;white-space:normal;}
}

/* ---------------------------------------------------------------------------
   Terminal 2 — the task bar and the skills list.

   The task bar sits between the header and the terminal because that is where
   its subject sits: what the agent is working on is neither session metadata
   nor terminal output. It wraps rather than scrolls at narrow widths — a task
   the user cannot read is a task they will not set.
   --------------------------------------------------------------------------- */
.task-bar{display:flex;align-items:center;gap:10px;flex-wrap:wrap;
  padding:10px 18px;border-bottom:1px solid var(--term-line);font-size:12px;}
.task-bar .k{color:var(--term-muted);text-transform:uppercase;letter-spacing:.07em;}
.task-bar .v{color:var(--term-bright);font-weight:600;flex:1 1 220px;min-width:0;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
.task-bar input{flex:2 1 280px;min-width:0;background:transparent;color:var(--term-fg);
  border:1px solid var(--term-line);border-radius:8px;padding:6px 10px;font-size:12px;
  font-family:inherit;}
.task-bar input::placeholder{color:var(--term-muted);}
.task-bar input:focus{outline:none;border-color:var(--term-accent);}

.skill-row{display:flex;align-items:flex-start;justify-content:space-between;gap:14px;
  padding:10px 0;border-bottom:1px solid var(--line);}
.skill-row:last-child{border-bottom:0;}
.skill-name{font-weight:600;font-size:14px;}

/* ---------- terminal: native-parity chrome ----------
   The tab strip, the find bar, the context menu and the drop target. All of
   it sits inside .term-wrap so the terminal keeps one border and reads as one
   object rather than a stack of widgets. */

.term-tabbar{display:flex;align-items:stretch;gap:6px;padding:6px 8px 0;border-bottom:1px solid var(--term-line);background:color-mix(in srgb,var(--term-bg) 88%,#000 12%);}
.term-tabs{display:flex;align-items:stretch;gap:4px;flex:1;min-width:0;overflow-x:auto;scrollbar-width:none;}
.term-tabs::-webkit-scrollbar{display:none;}

/* Wider than it was: the label now carries client, ABN and financial year,
   and at 220px a name like Joe-Blog-51824753556-FY2026 lost the year to the
   ellipsis — which is the part that tells two tabs on one client apart. */
.term-tab{display:flex;align-items:center;gap:7px;padding:6px 8px 6px 10px;max-width:270px;min-width:96px;
  border:1px solid transparent;border-bottom:0;border-radius:8px 8px 0 0;background:transparent;
  color:var(--term-muted);font:inherit;font-size:12px;cursor:pointer;white-space:nowrap;
  transition:background-color .12s ease,color .12s ease;}
.term-tab:hover{background:color-mix(in srgb,var(--term-bg) 70%,#fff 8%);color:var(--term-fg);}
.term-tab.is-active{background:var(--term-bg);border-color:var(--term-line);color:var(--term-bright);font-weight:600;}
.term-tab-label{overflow:hidden;text-overflow:ellipsis;flex:1;min-width:0;text-align:left;}
.term-tab-dot{width:7px;height:7px;border-radius:50%;flex-shrink:0;background:var(--term-muted);}
.term-tab-dot[data-state="on"]{background:var(--term-accent);}
.term-tab-dot[data-state="wait"]{background:var(--amber);animation:term-pulse 1.4s ease-in-out infinite;}
.term-tab-dot[data-state="off"]{background:#E39B7F;}
@keyframes term-pulse{0%,100%{opacity:1}50%{opacity:.35}}
.term-tab-close{flex-shrink:0;width:16px;height:16px;line-height:15px;text-align:center;border-radius:4px;
  font-size:14px;opacity:0;transition:opacity .12s ease,background-color .12s ease;}
.term-tab:hover .term-tab-close,.term-tab.is-active .term-tab-close{opacity:.6;}
.term-tab-close:hover{opacity:1;background:color-mix(in srgb,var(--term-bg) 50%,#fff 20%);}

.term-tab-add,.term-tabbar-btn{align-self:center;width:26px;height:26px;margin-bottom:5px;border:1px solid transparent;
  border-radius:7px;background:transparent;color:var(--term-muted);font-size:15px;line-height:1;cursor:pointer;
  transition:background-color .12s ease,color .12s ease;}
.term-tab-add:hover:not(:disabled),.term-tabbar-btn:hover{background:color-mix(in srgb,var(--term-bg) 70%,#fff 10%);color:var(--term-bright);}
.term-tab-add:disabled{opacity:.3;cursor:not-allowed;}
.term-tabbar-btn{font-size:13px;}

.term-shortcuts{padding:12px 16px;border-bottom:1px solid var(--term-line);background:color-mix(in srgb,var(--term-bg) 92%,#000 8%);}
.term-shortcuts-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(230px,1fr));gap:6px 20px;}
.term-shortcuts-grid div{display:flex;align-items:baseline;gap:10px;font-size:12px;color:var(--term-muted);}
.term-shortcuts-grid kbd{font-family:var(--mono);font-size:11px;color:var(--term-bright);
  background:color-mix(in srgb,var(--term-bg) 60%,#fff 12%);border:1px solid var(--term-line);
  border-radius:5px;padding:2px 6px;white-space:nowrap;flex-shrink:0;min-width:104px;text-align:center;}

/* The host holds one pane per open terminal; only the active one is laid out.
   `display:none` rather than visibility, because a hidden-but-laid-out xterm
   still measures and still costs a reflow on every resize. */
.term-host{position:relative;}
.term-pane{position:absolute;inset:0;display:none;padding:8px 10px;}
.term-pane.is-active{display:block;}
.term-pane.term-bell{animation:term-bell-flash .15s ease;}
@keyframes term-bell-flash{from{background:color-mix(in srgb,var(--term-bg) 70%,#fff 18%)}to{background:transparent}}

/* `hidden` is a UA-stylesheet rule (`[hidden]{display:none}`) and ANY class
   rule that sets `display` outranks it on specificity. A component that is
   shown and hidden by the attribute and also sets its own display therefore
   needs this explicitly, or it is permanently visible — which is exactly how
   the drop overlay ended up covering the terminal it was meant to sit over.
   `tests/terminal-ux` fails if a new one is added without it. */
.term-find[hidden],.term-drop[hidden],.term-menu[hidden],.term-shortcuts[hidden]{display:none;}

.term-find{position:absolute;top:8px;right:14px;z-index:6;display:flex;align-items:center;gap:6px;
  padding:5px 6px;border:1px solid var(--term-line);border-radius:9px;
  background:color-mix(in srgb,var(--term-bg) 82%,#000 18%);box-shadow:0 6px 20px rgba(0,0,0,.28);}
.term-find-input{width:180px;background:transparent;border:0;outline:0;color:var(--term-bright);
  font-family:var(--mono);font-size:12px;padding:2px 4px;}
.term-find-count{color:var(--term-muted);font-family:var(--mono);font-size:11px;min-width:42px;text-align:right;}
.term-find-btn{width:22px;height:22px;border:0;border-radius:5px;background:transparent;color:var(--term-muted);
  font-size:13px;line-height:1;cursor:pointer;}
.term-find-btn:hover{background:color-mix(in srgb,var(--term-bg) 60%,#fff 14%);color:var(--term-bright);}

.term-menu{position:absolute;z-index:8;min-width:210px;padding:5px;border:1px solid var(--term-line);
  border-radius:10px;background:color-mix(in srgb,var(--term-bg) 84%,#000 16%);
  box-shadow:0 10px 30px rgba(0,0,0,.35);}
.term-menu-item{display:flex;align-items:center;justify-content:space-between;gap:20px;width:100%;
  padding:6px 9px;border:0;border-radius:6px;background:transparent;color:var(--term-fg);
  font:inherit;font-size:12.5px;text-align:left;cursor:pointer;}
.term-menu-item:hover:not(:disabled){background:color-mix(in srgb,var(--term-bg) 55%,#fff 16%);color:var(--term-bright);}
.term-menu-item:disabled{opacity:.38;cursor:default;}
.term-menu-item kbd{font-family:var(--mono);font-size:11px;color:var(--term-muted);}
.term-menu-sep{height:1px;margin:4px 6px;background:var(--term-line);}

.term-drop{position:absolute;inset:0;z-index:7;display:grid;place-items:center;
  background:color-mix(in srgb,var(--term-bg) 72%,#000 28%);border:2px dashed var(--term-accent);
  border-radius:10px;pointer-events:none;}
.term-drop-inner{text-align:center;display:grid;gap:5px;}
.term-drop-inner strong{color:var(--term-bright);font-size:15px;}
.term-drop-inner span{color:var(--term-muted);font-size:12.5px;}

/* Below this the tab strip scrolls rather than wrapping, and the shortcut
   sheet goes to one column — a hover-and-keyboard sheet on a phone is only
   ever in the way. */
@media (max-width:820px){
  .term-tab{min-width:78px;max-width:150px;}
  .term-shortcuts-grid{grid-template-columns:1fr;}
  .term-find-input{width:120px;}
}

/* Hermes has one terminal rather than tabs, so its host IS the pane. It still
   needs to be a containing block: the find bar, the context menu and the drop
   overlay are positioned inside it. */
.term-solo{position:relative;}
.term-tab-rename{flex:1;min-width:0;background:transparent;border:0;outline:0;color:var(--term-bright);
  font:inherit;font-size:12px;font-weight:600;padding:0;}

/* A drop the terminal cannot honour says so while the file is still in the
   air, rather than after it has been let go. */
.term-drop[data-ready="no"]{border-color:var(--amber);}
.term-drop[data-ready="no"] .term-drop-inner strong{color:var(--amber);}

/* ---------- terminal header actions ----------
   Pushed to the right of the context strip. `margin-left:auto` on a flex-wrap
   container puts them on their own line once the strip wraps, which is the
   behaviour wanted on a narrow screen: the context reads first. */
.term-head-actions{margin-left:auto;display:flex;gap:6px;align-items:center;}
.term-head-btn{padding:3px 10px;font-size:12px;white-space:nowrap;}
/* The one that loses work is marked, quietly. A red button next to two grey
   ones is read before the label is, which is the point. */
.term-head-btn.is-destructive{color:var(--danger-ink);border-color:var(--danger-line);background:var(--danger-bg);}
.term-head-btn:disabled{opacity:.55;cursor:default;}

/* ---------- dictation ----------
   A microphone beside the terminal tabs. The ring is driven by the live
   signal level, because the commonest microphone failure is silent: the
   wrong input device is selected, permission is granted, the recorder runs,
   and the transcript comes back empty. A ring that does not move is the only
   way to see that before speaking a paragraph. */

.term-mic{--level:0;align-self:center;display:grid;place-items:center;width:26px;height:26px;
  margin-bottom:5px;border:1px solid transparent;border-radius:7px;background:transparent;
  color:var(--term-muted);cursor:pointer;position:relative;
  transition:background-color .12s ease,color .12s ease;}
.term-mic:hover{background:color-mix(in srgb,var(--term-bg) 70%,#fff 10%);color:var(--term-bright);}
.term-mic[hidden]{display:none;}

.term-mic[data-state="recording"]{color:#E39B7F;background:color-mix(in srgb,var(--term-bg) 60%,#E39B7F 14%);}
/* Scaled by the measured level rather than animated on a timer: a pulse on a
   timer looks identical whether or not anything is being heard. */
.term-mic[data-state="recording"]::after{content:'';position:absolute;inset:-3px;border-radius:9px;
  border:2px solid #E39B7F;opacity:calc(.25 + var(--level) * .75);
  transform:scale(calc(1 + var(--level) * .18));transition:transform .06s linear,opacity .06s linear;}

.term-mic[data-state="working"]{color:var(--amber);}
.term-mic[data-state="working"]::after{content:'';position:absolute;inset:-3px;border-radius:9px;
  border:2px solid var(--amber);border-top-color:transparent;animation:term-mic-spin .7s linear infinite;}
@keyframes term-mic-spin{to{transform:rotate(360deg)}}

@media (prefers-reduced-motion:reduce){
  .term-mic[data-state="recording"]::after{transform:none;transition:opacity .12s linear;}
  .term-mic[data-state="working"]::after{animation-duration:2s;}
}
