@import url('https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@500;600;700&family=Inter:wght@400;500;600&family=IBM+Plex+Mono:wght@400;500&display=swap');

/* The RocketX palette, unchanged from rocketx.app and the status panel. The
   three heat colours are the monitor's up/partial/down: a card waiting nine
   days should look like a site that is down, because it is the same feeling. */
:root{
  --void:#05080F; --navy:#0B1526; --panel:#0E1B33; --panel2:#101F3D;
  --blue:#2563EB; --sky:#60A5FA; --ice:#EDF2FB; --mist:#8FA1C4;
  --line:rgba(96,165,250,.14); --line-lit:rgba(96,165,250,.32);
  --display:'Space Grotesk',sans-serif; --body:'Inter',sans-serif;
  --mono:'IBM Plex Mono',ui-monospace,monospace;
  --calm:#34D399; --calm-bg:rgba(52,211,153,.12);
  --amber:#FBBF24; --amber-bg:rgba(251,191,36,.12);
  --red:#F87171;  --red-bg:rgba(248,113,113,.12);

  /* Everything a surface is made of, named rather than written out, because
     the light theme has to be able to replace all of it. A colour hard-coded
     further down is a thing that stays dark when somebody flips the switch,
     and it is always one nobody notices until it looks broken. */
  --sunken:rgba(5,8,15,.55);
  --glow:rgba(37,99,235,.18);
  --card-todo:#101F3D;
  --card-waiting:#1E1A10;
  --card-done:#0E1E1A;
  --wash-todo:rgba(96,165,250,.10);
  --wash-waiting:rgba(251,191,36,.09);
  --wash-done:rgba(52,211,153,.08);
  --chip:rgba(96,165,250,.10);
  --chip-strong:rgba(96,165,250,.18);
}

/* ------------------------------------------------------------------- light */
/* The same design in daylight: same blue, same faces, same shapes. Not an
   inversion - the greys are picked so text keeps its contrast and the three
   status colours stay apart from each other, which is what naive inverting
   breaks first. */
:root[data-theme="light"]{
  --void:#F4F7FC; --navy:#FFFFFF; --panel:#FFFFFF; --panel2:#FFFFFF;
  --blue:#2563EB; --sky:#1D4ED8; --ice:#0B1526; --mist:#5D6E8C;
  --line:rgba(11,21,38,.12); --line-lit:rgba(37,99,235,.42);
  --calm:#047857; --calm-bg:rgba(4,120,87,.10);
  --amber:#B45309; --amber-bg:rgba(180,83,9,.10);
  --red:#B91C1C;  --red-bg:rgba(185,28,28,.09);
  --sunken:rgba(11,21,38,.035);
  --glow:rgba(37,99,235,.10);
  --card-todo:#FFFFFF;
  --card-waiting:#FFFDF6;
  --card-done:#F6FCFA;
  --wash-todo:rgba(37,99,235,.06);
  --wash-waiting:rgba(180,83,9,.06);
  --wash-done:rgba(4,120,87,.05);
  --chip:rgba(11,21,38,.05);
  --chip-strong:rgba(37,99,235,.10);
}

*{box-sizing:border-box}
/* THE GLOW BELONGS TO THE WINDOW, NOT TO THE PAGE.
   It used to live on body alone. With no background on html, a body
   background is handed to the canvas and PAINTED ACROSS THE WHOLE OF IT,
   repeat and all — so on a short page, like the sign-in screen, the glow
   tiled down the window over and over. Giving html its own colour stops the
   hand-off; no-repeat and fixed keep one glow, anchored to the top of the
   window, however long the board gets. */
html{-webkit-text-size-adjust:100%;background:var(--void);color-scheme:dark}
html[data-theme="light"]{color-scheme:light}
body{
  margin:0;background-color:var(--void);color:var(--ice);
  font-family:var(--body);line-height:1.6;font-size:15px;
  padding:0 22px 90px;overflow-x:hidden;min-height:100vh;
  background-image:radial-gradient(900px 480px at 50% -8%,var(--glow),transparent 70%);
  background-repeat:no-repeat;
  background-attachment:fixed;
}
a{color:inherit;text-decoration:none}
button{font:inherit;cursor:pointer}

/* ----------------------------------------------------------------- masthead */
header{
  max-width:1180px;margin:0 auto;display:flex;align-items:center;
  justify-content:space-between;gap:18px;flex-wrap:wrap;padding:34px 0 26px;
}
.brand{
  font-family:var(--display);font-weight:700;font-size:19px;
  letter-spacing:-.01em;display:flex;align-items:center;gap:10px;
}
.brand img{display:block;border-radius:7px}
header nav{display:flex;align-items:center;gap:14px}
.who{
  font-family:var(--mono);font-size:12px;letter-spacing:.14em;
  text-transform:uppercase;color:var(--sky);
}
.link{
  background:none;border:0;color:var(--mist);font-family:var(--mono);
  font-size:12px;letter-spacing:.14em;text-transform:uppercase;padding:4px 0;
}
.link:hover{color:var(--ice)}
.link.danger{color:var(--red)}
main{max-width:1180px;margin:0 auto}

h2{
  font-family:var(--mono);font-size:12px;letter-spacing:.24em;
  text-transform:uppercase;color:var(--sky);font-weight:500;
  margin:0 0 14px;display:flex;align-items:center;gap:10px;
}
.count{
  font-size:11px;color:var(--mist);background:var(--chip);
  border-radius:999px;padding:1px 8px;letter-spacing:.06em;
}

/* -------------------------------------------------------------- chase today */
/* The only thing on the page allowed to shout. It is absent most days, which
   is what makes it worth reading on the days it is not. */
.chase{
  border:1px solid rgba(251,191,36,.34);background:var(--amber-bg);
  border-radius:14px;padding:18px 20px;margin:0 0 30px;
}
.chase h2{color:var(--amber);margin-bottom:10px}
.chase ul{list-style:none;margin:0;padding:0}
.chase li{
  display:flex;justify-content:space-between;gap:16px;align-items:baseline;
  padding:7px 0;border-top:1px solid rgba(251,191,36,.16);
}
.chase li:first-child{border-top:0}
.chase li a{font-weight:500}
.chase li a:hover{color:var(--amber)}
.chase .when{font-family:var(--mono);font-size:12px;color:var(--amber)}

/* ------------------------------------------------------------------- board */
.board{display:grid;grid-template-columns:repeat(3,1fr);gap:20px;align-items:start}
.col{
  background:linear-gradient(180deg,var(--panel),var(--navy));
  border:1px solid var(--line);border-radius:16px;padding:18px 16px 20px;
  min-height:180px;transition:border-color .18s,background .18s;
}
/* A COLOUR EACH, so a glance tells you which column you are looking at
   without reading the heading — and so a card dragged to the wrong place
   looks wrong. Kept to a tinted edge and a wash at the top rather than a
   filled panel: the cards have to stay the thing you see first, and the
   waiting column already carries amber age chips that a loud amber
   background would swallow. */
.col[data-col="todo"]{
  border-color:rgba(96,165,250,.20);
  background-image:linear-gradient(180deg,var(--wash-todo),transparent 42%);
}
.col[data-col="todo"] h2{color:var(--sky)}

.col[data-col="waiting"]{
  border-color:rgba(251,191,36,.24);
  background-image:linear-gradient(180deg,var(--wash-waiting),transparent 42%);
}
.col[data-col="waiting"] h2{color:var(--amber)}
.col[data-col="waiting"] .add button{background:#B45309}
.col[data-col="waiting"] .add button:hover{background:var(--amber);color:var(--void)}

.col[data-col="done"]{
  border-color:rgba(52,211,153,.20);
  background-image:linear-gradient(180deg,var(--wash-done),transparent 42%);
}
.col[data-col="done"] h2{color:var(--calm)}
.col[data-col="done"] .add button{background:#047857}
.col[data-col="done"] .add button:hover{background:var(--calm);color:var(--void)}
/* a finished card should recede, not compete */
.col[data-col="done"] .card .title{color:var(--mist)}

/* AND THE CARDS TAKE THE COLUMN'S COLOUR WITH THEM. A card that moves is the
   main thing that happens on this board, and it should be visible from across
   the room that it landed somewhere new. Kept dark and low-saturation so the
   title stays the brightest thing on the card and the amber and red age chips
   still read against the waiting column's own amber. */
.col[data-col="todo"] .card{background:var(--card-todo);border-color:rgba(96,165,250,.20)}
.col[data-col="todo"] .card:hover{border-color:rgba(96,165,250,.42)}

.col[data-col="waiting"] .card{background:var(--card-waiting);border-color:rgba(251,191,36,.20)}
.col[data-col="waiting"] .card:hover{border-color:rgba(251,191,36,.44)}
.col[data-col="waiting"] .card .title:hover{color:var(--amber)}
.col[data-col="waiting"] .moves button{border-color:rgba(251,191,36,.20)}

.col[data-col="done"] .card{background:var(--card-done);border-color:rgba(52,211,153,.18)}
.col[data-col="done"] .card:hover{border-color:rgba(52,211,153,.40)}
.col[data-col="done"] .card .title:hover{color:var(--calm)}
.col[data-col="done"] .moves button{border-color:rgba(52,211,153,.18)}

.col.over{border-color:var(--line-lit);background:var(--panel2)}
.cards{display:flex;flex-direction:column;gap:10px;min-height:20px}

/* the add box: one field, because a task you have to fill in a form for is a
   task you do not write down */
.add{display:flex;gap:8px;margin:0 0 14px}
.add input{
  flex:1;min-width:0;background:var(--sunken);border:1px solid var(--line);
  border-radius:10px;padding:9px 12px;color:var(--ice);font:inherit;font-size:14px;
}
.add input::placeholder{color:var(--mist)}
.add input:focus{outline:none;border-color:var(--line-lit)}
.add button{
  background:var(--blue);border:0;border-radius:10px;color:#fff;
  width:38px;font-size:18px;line-height:1;
}
.add button:hover{background:var(--sky);color:var(--void)}

/* ------------------------------------------------------------------- cards */
.card{
  background:var(--card-todo);border:1px solid var(--line);border-radius:12px;
  padding:12px 13px 10px;cursor:grab;
  transition:border-color .18s,transform .18s;
}
.card:hover{border-color:var(--line-lit)}
.card.dragging{opacity:.45;cursor:grabbing}
.card .title{display:block;font-weight:500;line-height:1.4}
.card .title:hover{color:var(--sky)}
.meta{
  display:flex;flex-wrap:wrap;gap:6px;margin-top:9px;
  font-family:var(--mono);font-size:11px;letter-spacing:.04em;
}
.meta span{border-radius:999px;padding:2px 8px;background:var(--chip);color:var(--mist)}
.meta .on{color:var(--ice);background:var(--chip-strong)}
.meta .owner{background:none;padding:2px 0;color:var(--mist)}
.age.calm {color:var(--calm); background:var(--calm-bg)}
.age.amber{color:var(--amber);background:var(--amber-bg)}
.age.red  {color:var(--red);  background:var(--red-bg)}
.nudge{color:var(--sky);background:rgba(96,165,250,.12)}
.nudge.due{color:var(--amber);background:var(--amber-bg)}
/* when it was written down: context, not a signal. No pill, no colour — it
   must not compete with the waiting clock, which is the number that matters. */
.made{background:none;padding:2px 0;color:var(--mist);opacity:.7}

.moves{display:flex;gap:6px;margin-top:9px;align-items:center;flex-wrap:wrap}
.moves form{margin:0}
.moves button{
  background:var(--sunken);border:1px solid var(--line);border-radius:8px;
  color:var(--mist);width:30px;height:26px;line-height:1;font-size:13px;
}
.moves button:hover{border-color:var(--line-lit);color:var(--ice)}
/* The thing you press most often on this board, so it is wider than the
   arrows and says what it does in words. Amber because it belongs to the
   waiting column and to the clock it resets — and quiet until hovered,
   because it sits on every waiting card and three shouting buttons in a
   column is a column you stop reading. */
.chased{margin-left:auto}
.chased button{
  /* inline-flex and nowrap, not a fixed height with wrapping text: the label
     is two words and it wrapped inside a 26px box, so it hung out of its own
     border top and bottom. The height comes from the padding now, and the
     words are not allowed to break. */
  display:inline-flex;align-items:center;justify-content:center;
  white-space:nowrap;
  background:rgba(251,191,36,.08);border:1px solid rgba(251,191,36,.26);
  /* width:auto BEATS THE 30px IT INHERITS. This button lives inside .moves,
     whose buttons are 30px squares for the arrows, and nothing here was
     overriding that - so the box stayed arrow-sized while the words ran out
     the side of it. That, not the wrapping, was the overlap. */
  width:auto;height:auto;
  border-radius:8px;color:var(--mist);min-height:26px;padding:5px 10px;
  font-family:var(--mono);font-size:10px;letter-spacing:.08em;
  text-transform:uppercase;line-height:1.1;
  transition:border-color .18s,color .18s,background .18s;
}
.chased button:hover{
  background:rgba(251,191,36,.16);border-color:rgba(251,191,36,.6);
  color:var(--amber);
}
/* THE SAME 30px TRAP, A SECOND TIME. ".list .go button" is (0,2,1) and beats
   ".chased button" at (0,1,1), so the list view squeezed this back into an
   arrow-sized box and the words ran out of the side again — exactly the bug
   that was fixed on the board, in the one place nobody re-checked. Anything
   that restyles a button inside .go has to say what happens to this one. */
.list .go .chased{display:inline-block;margin:0 6px 0 0;vertical-align:middle}
.list .go .chased button{
  width:auto;height:auto;min-height:26px;padding:5px 10px;
  white-space:nowrap;font-size:10px;letter-spacing:.08em;line-height:1.1;
  background:rgba(251,191,36,.08);border-color:rgba(251,191,36,.26);
}
.list .go .chased button:hover{
  background:rgba(251,191,36,.16);border-color:rgba(251,191,36,.6);
  color:var(--amber);
}
.actions .chased{margin-left:0}
.actions .chased button{min-height:0;padding:11px 18px;font-size:11px}

/* ------------------------------------------------------------- task & login */
.back{
  font-family:var(--mono);font-size:12px;letter-spacing:.14em;
  text-transform:uppercase;color:var(--mist);display:inline-block;margin-bottom:20px;
}
.back:hover{color:var(--sky)}
.edit,.login{
  display:flex;flex-direction:column;gap:16px;max-width:640px;
  background:linear-gradient(180deg,var(--panel),var(--navy));
  border:1px solid var(--line);border-radius:16px;padding:24px;
}
.login{max-width:380px;margin:60px auto 0}
.edit label,.login label{
  display:flex;flex-direction:column;gap:6px;font-family:var(--mono);
  font-size:11px;letter-spacing:.2em;text-transform:uppercase;color:var(--sky);
}
.edit .row{display:flex;gap:16px;flex-wrap:wrap}
.edit .row label{flex:1;min-width:180px}
input,select,textarea{
  background:var(--sunken);border:1px solid var(--line);border-radius:10px;
  padding:10px 12px;color:var(--ice);font-family:var(--body);font-size:15px;
  letter-spacing:normal;text-transform:none;
}
textarea{resize:vertical;line-height:1.6}
input:focus,select:focus,textarea:focus{outline:none;border-color:var(--line-lit)}
.primary{
  background:var(--blue);border:0;border-radius:10px;color:#fff;
  padding:11px 26px;font-weight:500;align-self:flex-start;
}
.primary:hover{background:var(--sky);color:var(--void)}
.actions{display:flex;gap:12px}
.waited{margin:0;font-family:var(--mono);font-size:12px;color:var(--mist)}
.danger{border:0;background:none;padding:0;margin:18px 0 0}
.bad{
  color:var(--red);background:var(--red-bg);border:1px solid rgba(248,113,113,.3);
  border-radius:10px;padding:10px 14px;margin:0 0 18px;font-size:14px;
}

/* ----------------------------------------------------------------- search */
.find input{
  background:var(--sunken);border:1px solid var(--line);border-radius:9px;
  padding:6px 11px;color:var(--ice);font-family:var(--body);font-size:13px;
  width:150px;transition:border-color .18s,width .18s;
}
.find input::placeholder{color:var(--mist)}
.find input:focus{outline:none;border-color:var(--line-lit);width:210px}
.find.big{margin:0 0 24px}
.find.big input{width:100%;max-width:520px;font-size:16px;padding:12px 15px}
.find.big input:focus{width:100%}
/* where a result lives, including the archive - the whole reason to search */
.tags .where{font-weight:500}
.tags .where.todo{color:var(--sky);background:var(--chip-strong)}
.tags .where.waiting{color:var(--amber);background:var(--amber-bg)}
.tags .where.done{color:var(--calm);background:var(--calm-bg)}
main > h2 .count{text-transform:none;letter-spacing:0;font-size:12px}

/* ---------------------------------------------------------------- archive */
/* At the foot of Done, always. Built out of the pieces already on the board -
   the same border, radius and muted mono as the move buttons and the add
   field - so it reads as one more control rather than a new kind of object.
   The first version was a dashed green box, which was the only dashed thing
   on the page and looked like somewhere to drop a card. */
.archive-btn{
  display:flex;align-items:center;gap:10px;
  margin-top:12px;padding:10px 13px;border-radius:10px;
  border:1px solid var(--line);background:var(--sunken);
  font-family:var(--mono);font-size:11px;letter-spacing:.12em;
  text-transform:uppercase;color:var(--mist);
  transition:border-color .18s,color .18s;
}
.archive-btn::after{content:"\2192";margin-left:auto;font-size:13px;opacity:.55}
.archive-btn:hover{border-color:rgba(52,211,153,.42);color:var(--calm)}
.archive-btn:hover::after{opacity:1}
.archive-btn .count{background:rgba(52,211,153,.14);color:var(--calm)}
.archived{
  display:block;margin-top:14px;font-family:var(--mono);font-size:11px;
  letter-spacing:.14em;text-transform:uppercase;color:var(--mist);
}
.archived:hover{color:var(--calm)}
.list + .archived{margin-top:22px}
.quiet{color:var(--mist);font-size:14px;max-width:46rem;margin:0 0 22px}
main > h2{margin-top:6px}

/* -------------------------------------------------------------- list view */
.views{display:flex;gap:2px;border:1px solid var(--line);border-radius:9px;
  padding:2px;margin-right:4px}
.view{
  font-family:var(--mono);font-size:11px;letter-spacing:.14em;
  text-transform:uppercase;color:var(--mist);padding:4px 10px;border-radius:7px;
}
.view:hover{color:var(--ice)}
.view.on{background:var(--chip-strong);color:var(--sky)}
/* The day/night switch. Same size and border as the view toggle beside it,
   so the masthead reads as one row of controls rather than three ideas. */
.theme button{
  background:none;border:1px solid var(--line);border-radius:9px;
  color:var(--mist);width:34px;height:30px;line-height:1;font-size:14px;
  transition:border-color .18s,color .18s;
}
.theme button:hover{border-color:var(--line-lit);color:var(--ice)}

.list{width:100%;border-collapse:collapse}
.list tr.head th{
  text-align:left;padding:26px 0 8px;font-family:var(--mono);font-weight:500;
  font-size:12px;letter-spacing:.24em;text-transform:uppercase;
}
.list tr.head.todo    th{color:var(--sky)}
.list tr.head.waiting th{color:var(--amber)}
.list tr.head.done    th{color:var(--calm)}
.list tr.head .count{margin-left:10px}
.list tr.empty td{
  padding:8px 0 4px;color:var(--mist);font-size:14px;opacity:.6;
  border-bottom:1px solid var(--line);
}
.list tbody tr:not(.head):not(.empty){border-bottom:1px solid var(--line)}
.list tbody tr:not(.head):not(.empty):hover{background:rgba(96,165,250,.05)}
.list td{padding:11px 14px 11px 0;vertical-align:middle}
.list td:last-child{padding-right:0}
.list .what{width:46%}
.list .what a{font-weight:500}
.list .what a:hover{color:var(--sky)}
.list tr.done .what a{color:var(--mist)}
.list .tags{display:flex;flex-wrap:wrap;gap:6px;padding-top:13px;
  font-family:var(--mono);font-size:11px;letter-spacing:.04em}
.list .tags span{border-radius:999px;padding:2px 8px;
  background:var(--chip);color:var(--mist)}
.list .tags .on{color:var(--ice);background:var(--chip-strong)}
/* THE HEAT HAS TO SURVIVE THE CHANGE OF VIEW. ".list .tags span" outranks
   ".age.red" on specificity, so without these the list quietly painted every
   age chip the same grey — and a nine-day wait looking exactly like a
   one-day wait is the one thing this board must never do. */
.list .tags .age.calm {color:var(--calm); background:var(--calm-bg)}
.list .tags .age.amber{color:var(--amber);background:var(--amber-bg)}
.list .tags .age.red  {color:var(--red);  background:var(--red-bg)}
.list .tags .nudge{color:var(--sky);background:rgba(96,165,250,.12)}
.list .tags .nudge.due{color:var(--amber);background:var(--amber-bg)}
.list .whose{
  font-family:var(--mono);font-size:11px;color:var(--mist);white-space:nowrap;
}
.list .whose .made{display:block;opacity:.6;background:none;padding:0}
.list .go{white-space:nowrap;text-align:right}
.list .go form{display:inline-block;margin-left:6px}
.list .go button{
  background:var(--sunken);border:1px solid var(--line);border-radius:8px;
  color:var(--mist);width:30px;height:26px;line-height:1;font-size:13px;
}
.list .go button:hover{border-color:var(--line-lit);color:var(--ice)}
@media (max-width:820px){
  .list .whose{display:none}
  .list .what{width:60%}
}

/* ------------------------------------------------------------------ notes */
.notes-on{
  max-width:640px;margin:22px 0 0;
  background:linear-gradient(180deg,var(--panel),var(--navy));
  border:1px solid var(--line);border-radius:16px;padding:22px 24px 24px;
}
.thread{list-style:none;margin:0 0 18px;padding:0;display:flex;
  flex-direction:column;gap:12px}
.thread li{
  background:var(--sunken);border:1px solid var(--line);
  border-radius:12px;padding:11px 13px 9px;
}
.said{line-height:1.55;white-space:pre-wrap;overflow-wrap:anywhere}
.by{
  display:flex;align-items:center;gap:10px;margin-top:7px;
  font-family:var(--mono);font-size:11px;letter-spacing:.06em;color:var(--mist);
}
.by span:first-child{color:var(--sky)}
.by form{margin-left:auto}
.by .link{font-size:15px;letter-spacing:0;padding:0 2px;line-height:1}
.say{display:flex;flex-direction:column;gap:12px}
.say textarea{width:100%}
.say .primary{align-self:flex-start}
/* how many notes a card carries, quiet like the date beside it */
.notes{color:var(--mist);background:rgba(96,165,250,.10)}

/* ------------------------------------------------------------------- phone */
@media (max-width:820px){
  body{padding:0 14px 60px}
  .board{grid-template-columns:1fr;gap:14px}
  .col{min-height:0}
  header{padding:22px 0 18px}
}
@media (prefers-reduced-motion:reduce){
  *{transition:none!important;animation:none!important}
}
