/* Design tokens and the minimal reset shared by every page.

   Kept separate from style.css so the marketing home page can pull in the
   palette without also pulling the ~97 KB application stylesheet, none of
   whose component rules it uses. style.css and home.css both build on this. */

:root{
  --bg:#12151a;  --bg2:#171b22;  --bg3:#1d222b;  --bg4:#252b36;
  --line:#2c333f; --line2:#39424f;
  --fg:#dde3ec;  --fg2:#95a1b3;  --fg3:#67728a;
  --accent:#4aa8ff; --accent2:#2b6fb5;
  --straight:#7fd4a8; --spiral:#ffc14d; --arc:#ff7a7a;
  --ground:#9c7a52; --rail:#4aa8ff; --cut:#e06a6a; --fill:#5aa9e6;
  --curv:#c58cff; --cantc:#ffc14d; --cdef:#ff7a7a;
  --err:#ff6b6b; --warn:#ffb648; --info:#5ab0ff; --ok:#5ed69a;
  --mono:"SFMono-Regular",ui-monospace,Menlo,Consolas,monospace;
  --ui:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;
}

*{box-sizing:border-box}
body{margin:0}

/* ── Primitives shared by the application and the marketing pages ──
   These live here rather than in style.css so index.html can style its
   buttons, form controls, canvases and progress flow without loading the
   ~81 KB of application chrome it never uses. */

.proj-name:focus,input:focus,select:focus,textarea:focus{outline:none; border-color:var(--accent2)}
input::placeholder,textarea::placeholder{color:var(--fg3); opacity:1}

/* Every text-bearing field, not only the two types that happened to exist when
   this rule was written — an email or password box that missed it fell through
   to the browser's white default and glared out of a dark dialog. */
input[type=text],input[type=number],input[type=email],input[type=password],
input[type=search],input[type=tel],input[type=url],select,textarea{
  background:var(--bg3); border:1px solid var(--line); color:var(--fg);
  border-radius:5px; padding:4px 7px; font:inherit;
}
textarea{width:100%; font-family:var(--mono); font-size:11px; resize:vertical}
select{padding-right:22px}

.btn{
  background:var(--bg3); border:1px solid var(--line2); color:var(--fg);
  border-radius:5px; padding:6px 11px; cursor:pointer; font:inherit; white-space:nowrap;
}
.btn:focus-visible, button:focus-visible, input:focus-visible, select:focus-visible, textarea:focus-visible{outline:2px solid var(--accent); outline-offset:1px}
.btn:hover{background:var(--bg4); border-color:var(--accent2)}
.btn:active{transform:translateY(1px)}
.btn.primary{background:var(--accent2); border-color:var(--accent); color:#fff}
.btn.primary:hover{background:var(--accent)}
.btn.wide{width:100%; text-align:left; margin-bottom:6px}
.btn:disabled{opacity:.4; cursor:default}

canvas{flex:1; display:block; width:100%; min-height:0; cursor:crosshair}
canvas.grabbing{cursor:grabbing}
canvas.grab{cursor:grab}
canvas.move{cursor:move}

/* scrollbars */
::-webkit-scrollbar{width:11px; height:11px}
::-webkit-scrollbar-track{background:var(--bg2)}
::-webkit-scrollbar-thumb{background:var(--line2); border-radius:6px; border:2px solid var(--bg2)}
::-webkit-scrollbar-thumb:hover{background:var(--fg3)}

/* ═══════════════ a process flow for work that blocks ═══════════════ */
.flow{padding:2px 0}
.flow-row{margin-bottom:2px}
.flow-step{
  display:flex; align-items:center; gap:9px; padding:6px 2px;
  font-size:12px; color:var(--fg3);
}
.flow-mark{
  flex:0 0 auto; width:15px; height:15px; border-radius:50%;
  border:1.5px solid var(--line2); position:relative;
  transition:border-color .2s ease, background .2s ease;
}
.flow-text{flex:1 1 auto; min-width:0}
.flow-bar{
  flex:0 0 auto; width:86px; height:4px; border-radius:2px;
  background:rgba(255,255,255,.06); overflow:hidden; opacity:0;
}
.flow-bar i{
  display:block; width:38%; height:100%; border-radius:2px; background:var(--accent);
  /* Animated by transform, which the browser runs on the compositor rather
     than the main thread — so it keeps moving through a synchronous search
     that stops every other pixel on the page from being redrawn. */
  transform:translateX(-100%);
  animation:flow-slide 1.15s cubic-bezier(.55,.1,.45,.9) infinite;
}
@keyframes flow-slide{
  from{transform:translateX(-100%)}
  to{transform:translateX(266%)}
}

/* waiting */
.flow-step.wait{opacity:.5}
/* running */
.flow-step.run{color:var(--fg)}
.flow-step.run .flow-mark{border-color:var(--accent)}
.flow-step.run .flow-bar{opacity:1}
/* done */
.flow-step.done{color:var(--fg2)}
.flow-step.done .flow-mark{border-color:var(--ok); background:var(--ok)}
.flow-step.done .flow-mark::after{
  content:''; position:absolute; left:4px; top:1px; width:4px; height:8px;
  border:solid #06210f; border-width:0 1.6px 1.6px 0; transform:rotate(42deg);
}
/* failed */
.flow-step.fail{color:var(--err)}
.flow-step.fail .flow-mark{border-color:var(--err); background:var(--err)}
.flow-step.fail .flow-mark::after{
  content:'!'; position:absolute; inset:0; color:#2a0808;
  font:700 10px/13px sans-serif; text-align:center;
}
.flow-note{
  font-size:11px; line-height:1.5; color:var(--fg3);
  padding:0 0 4px 24px; margin-top:-3px;
}
.flow-note.warn{color:var(--warn)}
@media (prefers-reduced-motion:reduce){
  /* The bar is the only thing that says "still working" while the main thread
     is blocked, so it is not removed — only slowed to something restful. */
  .flow-bar i{animation-duration:2.4s}
}
