/* ===========================================================================
   THE WORKSPACE SHELL — Josh's Tracker mockup, 2026-08-28.
   ---------------------------------------------------------------------------
   Every other page on this site is a DOCUMENT: you arrive, you read, you
   leave, and a 1200px column with generous air is right for that. The Tracker
   is a WORKSPACE: you come back to it, you move things around on it, and you
   expect it to be where you left it. Josh drew it as an application - a
   persistent left rail, a board you drag on, a detail panel that opens beside
   the work rather than navigating away from it - and a document shell wrapped
   around an application is most of the reason this board read as a list.

   WHAT STAYS, because it is the brand: the mark, Archivo set heavy and wide
   for the title, JetBrains Mono for coded labels, the navy ground, luminous
   green for what is live and steel blue for contracts.

   WHAT CHANGES, because the mockup needs it and the owner asked for it:
     - the page fills the window instead of sitting in a centred column
     - the ground is LIFTED two steps, so cards read as objects on a surface
       rather than as glass floating in space
     - each board column carries its own accent, which is how a kanban tells
       you where you are without reading the header
     - one new hue, a soft indigo, for the fourth summary card. Josh's mockup
       uses four distinct colours for the four counts and three of them already
       exist here; inventing the fourth is cheaper than collapsing two of his.

   The variables below are scoped to .ws so nothing here can leak into the
   fifteen document pages.
   =========================================================================== */

.ws {
  /* --ws-rail comes from :root in style.css now, so the rail is one width and
     one set of styles on all seventeen pages rather than two of each. */
  --ws-panel: 380px;
  /* THE LIFT. Two steps above --abyss, so a raised card has somewhere to be
     raised FROM. These stay as the OPAQUE fallbacks and as the border/tint
     reference; the surfaces themselves are now glass over the ground, the way
     every other panel on the site is built. */
  /* LIFTED AGAIN, and this is the second pass at it. The first kept the
     original near-black values and layered glass on top, and the result still
     read as grey boxes on a dark slab next to the home page's lit room. These
     carry more blue and sit two steps higher, so a card is a BLUE object on a
     navy ground rather than a lighter grey rectangle on a black one. */
  --ws-ground: #0A1728;
  --ws-surface: #112541;
  --ws-card: #16304F;
  --ws-card-hi: #1B3A5E;
  --ws-line: rgba(255,255,255,.10);
  --ws-line-2: rgba(255,255,255,.19);
  --ws-indigo: #8E8CF0;
  --ws-indigo-dim: rgba(142,140,240,.16);
  /* The ruled field is drawn brighter here than on the document pages. Those
     show it only inside a hero or a deep pool, where it sits under a headline;
     here it is the surface of the whole desk and at .05 it was invisible. */
  --rule-dark: rgba(255,255,255,.085);
  /* The two glass steps, in the workspace's own key. Same construction as
     --panel / --panel-2 in style.css: a translucent lift, never a flat fill. */
  --ws-glass:   linear-gradient(158deg, rgba(255,255,255,.085), rgba(255,255,255,.032));
  --ws-glass-2: linear-gradient(158deg, rgba(255,255,255,.125), rgba(255,255,255,.05));
  color: var(--on-navy);
  min-height: 100vh;
  margin: 0;
  /* ------------------------------------------------------------ THE ROOM
     SECOND PASS, and the first one did not go far enough. The workspace used
     to be `background: #0A1524` - one flat hex - and the first fix layered the
     site's construction over it at document-page strength: glows at .13 and
     .42 pushed to the far corners, the grid at .05 behind a mask that faded
     out by the middle of the screen. Put beside index.html the difference was
     obvious - home is a LIT ROOM with a readable plotting grid and a green
     pool you can actually see, and the workspace was still a dark slab with
     grey boxes on it.

     The reason the document values do not transfer: a document page pours its
     light into a 1220px measure with wide dark gutters either side, so a glow
     parked at 90% of the viewport lands in the gutter and reads as atmosphere.
     The workspace is full-bleed - the content runs to both edges - so the same
     glow lands off-screen and does nothing at all. These are aimed INTO the
     working area instead, and there are four of them rather than two:

       green   the working light, over the head and the cards
       blue    a cool counter-light high left, so the top is not one hue
       blue    the ambient floor pooling low left, the site's standing move
       base    a navy ramp that never reaches black - the old one hit #050C17
               by the foot of the page and took the grid down with it

     Fixed attachment, so scrolling moves the work through the light rather
     than dragging a backdrop along behind it. */
  background:
    radial-gradient(56% 46% at 74% -6%, rgba(121,185,40,.24), transparent 64%),
    radial-gradient(48% 38% at 16% 2%, rgba(39,82,126,.44), transparent 68%),
    radial-gradient(78% 56% at 6% 102%, rgba(39,82,126,.50), transparent 70%),
    linear-gradient(168deg, #0C1F38 0%, #0A1A2E 36%, #08172A 68%, #061020 100%);
  background-attachment: fixed;
}
/* THE RULED PLOTTING FIELD, and it has to be SEEN to be doing its job.
   Masked with a linear ramp rather than a radial one: a radial mask centred
   near the top means the grid is gone by the middle of a workspace, which on
   a page you scroll for a while is most of the page. This keeps it at full
   strength across the head and the cards and lets it fall away toward the
   foot, so the desk has a surface everywhere the work actually is. */
.ws::before {
  content: ""; position: fixed; inset: 0; z-index: 0; pointer-events: none;
  background-image:
    linear-gradient(var(--rule-dark) 1px, transparent 1px),
    linear-gradient(90deg, var(--rule-dark) 1px, transparent 1px);
  background-size: 72px 72px;
  -webkit-mask-image: linear-gradient(176deg, #000 0%, #000 40%,
                      rgba(0,0,0,.55) 72%, rgba(0,0,0,.18) 92%, transparent 100%);
  mask-image: linear-gradient(176deg, #000 0%, #000 40%,
              rgba(0,0,0,.55) 72%, rgba(0,0,0,.18) 92%, transparent 100%);
  animation: gridin 1.6s var(--ease-out) both;
}
/* Grain, at the threshold of visibility. It is what stops a large dark area
   from reading as a dead #hex swatch. */
.ws::after {
  content: ""; position: fixed; inset: 0; z-index: 0; pointer-events: none;
  background-image: var(--grain); background-size: 160px 160px;
  opacity: .05; mix-blend-mode: overlay;
}

.ws-shell { display: flex; min-height: 100vh; align-items: stretch;
  position: relative; z-index: 1; }

/* ---- the rail -------------------------------------------------------
   MOVED, ENTIRELY, to the bottom of assets/style.css on 2026-08-28. It was
   defined here, which meant only a page that loaded workspace.css could have
   a rail - which was the Tracker and the Ledger and nothing else. style.css
   is loaded by every page on the site, so that is where the one definition
   lives, and assets/ws-shell.js docks it onto the fifteen document pages that
   were never rebuilt. The only rule left on this side is which mode applies,
   and it is in style.css too (`.ws-shell > .ws-rail`).

   DO NOT RE-ADD RAIL RULES HERE. A second copy is exactly the drift that put
   plan.js and gate.ts out of step, and a rail that looks one way on Ledger
   and another way on Atlas is the visible version of the same fault. */

/* ---- the workspace column ------------------------------------------- */
.ws-main { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; }
/* STICKY, AND MADE OF GLASS. A workspace header that scrolls away takes the
   name of the thing you are looking at and the controls that change it off
   the screen, which on a board you scroll for a while is the wrong trade. It
   is the same blurred glass the site's top nav is made of, so the two read as
   the same material. */
.ws-head {
  position: sticky; top: 0; z-index: 40;
  display: flex; align-items: flex-start; justify-content: space-between;
  gap: 20px; flex-wrap: wrap; padding: 22px 26px 18px;
  border-bottom: 1px solid var(--ws-line);
  background:
    linear-gradient(100deg, rgba(255,255,255,.055), rgba(255,255,255,.015)),
    rgba(8,19,34,.82);
  -webkit-backdrop-filter: saturate(165%) blur(15px);
  backdrop-filter: saturate(165%) blur(15px);
  box-shadow: var(--edge-dark), 0 14px 34px -26px rgba(0,0,0,.9);
  animation: rise .55s var(--ease-out) both;
}
/* A LIT LOWER EDGE rather than a drawn line. The header is the boundary
   between the page's name and its work, and a flat 1px hairline is the one
   detail that most made this read as a generic admin template. */
.ws-head::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: -1px; height: 1px;
  background: linear-gradient(90deg, rgba(148,213,60,.55), rgba(143,182,224,.28) 38%,
              transparent 82%);
  pointer-events: none;
}
.ws-head { position: sticky; }
.ws-head h1 { position: relative; }
.ws-head h1 {
  margin: 0 0 4px; font-family: var(--f-display); font-weight: 800;
  font-stretch: 106%; letter-spacing: -.03em; font-size: clamp(24px, 2.6vw, 30px);
  color: #fff; text-transform: none;
}
.ws-head p { margin: 0; font-size: 14px; color: var(--on-navy-soft); }
.ws-head-r { display: flex; align-items: center; gap: 12px; }
.ws-seg { display: inline-flex; background: rgba(255,255,255,.045);
  border: 1px solid var(--ws-line); border-radius: 10px; padding: 3px;
  box-shadow: inset 0 1px 2px rgba(0,0,0,.28); }
.ws-seg button {
  font: inherit; font-size: 13px; padding: 6px 13px; border-radius: 7px;
  border: 0; background: none; color: var(--on-navy-soft); cursor: pointer;
  transition: color var(--t-tint) var(--ease-out),
              background var(--t-tint) var(--ease-out);
}
.ws-seg button:hover:not(.is-on):not([disabled]) {
  color: #fff; background: rgba(255,255,255,.05); }
.ws-seg button.is-on {
  background: linear-gradient(168deg, #1E3A5E, #16294A);
  color: #fff; font-weight: 600;
  box-shadow: var(--shadow-xs), var(--edge-dark); }
.ws-seg button[disabled] { opacity: .45; cursor: not-allowed; }
.ws-acct { width: 32px; height: 32px; border-radius: 50%; flex: none;
  background: linear-gradient(150deg, var(--green-400), var(--green-500) 62%, #4E8A1C);
  color: #08172A; display: grid; place-items: center;
  font-family: var(--f-mono); font-size: 11px; font-weight: 700; text-decoration: none;
  box-shadow: 0 0 0 1px rgba(148,213,60,.34), 0 4px 16px -4px rgba(121,185,40,.55);
  transition: transform var(--t-quick) var(--ease-out),
              box-shadow var(--t-quick) var(--ease-out); }
.ws-acct:hover { transform: translateY(-1px) scale(1.05);
  box-shadow: 0 0 0 1px rgba(148,213,60,.5), 0 8px 22px -5px rgba(121,185,40,.7); }

.ws-body { padding: 20px 26px 40px; flex: 1 1 auto; position: relative; }
/* A pool of the working light over the top of the board, so the busiest part
   of the page sits IN the light rather than beside it. */
.ws-body::before {
  content: ""; position: absolute; inset: 0 0 auto; height: 340px; z-index: -1;
  pointer-events: none;
  background: radial-gradient(62% 100% at 22% 0%, rgba(39,82,126,.30), transparent 72%),
              radial-gradient(46% 90% at 88% 0%, rgba(121,185,40,.10), transparent 70%);
}
/* THE ENTRANCE IS ON THE CONTAINERS, NOT ON THE CARDS INSIDE THEM.
   Every one of these divs is in the page's markup and keeps its identity for
   the life of the visit; only its innerHTML is replaced. Putting the animation
   on the children instead would re-run it on every filter, every search
   keystroke and every drag - the board would flicker each time it answered. */
.tk-sums  { animation: rise .6s var(--ease-out) both; animation-delay: 60ms; }
.tk-board { animation: rise .6s var(--ease-out) both; animation-delay: 130ms; }
.tk-outcomes { animation: rise .6s var(--ease-out) both; animation-delay: 200ms; }

/* ---- the toolbar ---------------------------------------------------- */
.tk-bar { display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  margin: 0 0 18px; }
.tk-search { position: relative; flex: 1 1 200px; min-width: 150px; max-width: 340px; }
.tk-search input {
  width: 100%; font: inherit; font-size: 14px; padding: 9px 12px 9px 34px;
  border-radius: 10px; border: 1px solid var(--ws-line);
  background: rgba(6,15,28,.62); color: var(--on-navy);
  box-shadow: inset 0 1px 3px rgba(0,0,0,.34);
  transition: border-color var(--t-tint) var(--ease-out),
              box-shadow var(--t-tint) var(--ease-out),
              background var(--t-tint) var(--ease-out);
}
.tk-search input:hover { border-color: var(--ws-line-2); }
.tk-search input:focus { outline: none; background: rgba(6,15,28,.85);
  box-shadow: var(--ring), inset 0 1px 3px rgba(0,0,0,.34);
  border-color: rgba(148,213,60,.5); }
.tk-search svg { position: absolute; left: 11px; top: 50%; transform: translateY(-50%);
  width: 15px; height: 15px; color: var(--on-navy-mute); pointer-events: none; }
.tk-sel { position: relative; }
.tk-sel select {
  font: inherit; font-size: 13px; padding: 9px 28px 9px 11px; max-width: 148px; border-radius: 10px;
  border: 1px solid var(--ws-line); background: rgba(6,15,28,.62); color: var(--on-navy-soft);
  appearance: none; cursor: pointer;
  box-shadow: inset 0 1px 3px rgba(0,0,0,.3);
  transition: border-color var(--t-tint) var(--ease-out),
              color var(--t-tint) var(--ease-out);
}
.tk-sel select:hover { border-color: var(--ws-line-2); color: var(--on-navy); }
.tk-sel select:focus { outline: none; box-shadow: var(--ring); }
.tk-sel.is-on select { color: var(--green-400); border-color: rgba(148,213,60,.45);
  background: rgba(121,185,40,.1); }
.tk-sel::after { content: ""; position: absolute; right: 12px; top: 50%;
  width: 6px; height: 6px; border-right: 1.6px solid var(--on-navy-mute);
  border-bottom: 1.6px solid var(--on-navy-mute); transform: translateY(-70%) rotate(45deg);
  pointer-events: none; }
.tk-view { margin-left: auto; display: inline-flex; background: rgba(255,255,255,.05);
  border: 1px solid var(--ws-line); border-radius: 9px; padding: 3px; }
.tk-view button { font: inherit; font-size: 13px; padding: 6px 12px; border: 0;
  border-radius: 7px; background: none; color: var(--on-navy-soft); cursor: pointer;
  display: inline-flex; align-items: center; gap: 6px; }
.tk-view button.is-on { background: var(--ws-card-hi); color: #fff; font-weight: 600; }
.tk-view svg { width: 14px; height: 14px; }

/* ---- the four summary cards, which are filters ---------------------- */
.tk-sums { display: grid; gap: 11px; margin: 0 0 14px;
  grid-template-columns: repeat(4, minmax(0, 1fr)); }
@media (max-width: 860px) { .tk-sums { grid-template-columns: repeat(2, minmax(0,1fr)); } }
@media (max-width: 430px) { .tk-sums { grid-template-columns: minmax(0,1fr); } }
/* GLASS ON THE GROUND, NOT A FILL. Same construction as every raised panel
   on the site: a translucent step, a lit top edge, and a doubled shadow -
   tight contact plus wide ambient - so it reads as an object with a height
   above the desk rather than as a lighter rectangle painted on it. */
.tk-sum {
  position: relative; isolation: isolate; overflow: hidden;
  display: flex; align-items: flex-start; gap: 11px; padding: 13px 13px;
  border-radius: 14px; border: 1px solid var(--ws-line);
  background: var(--ws-glass), var(--ws-card);
  box-shadow: var(--shadow-sm), var(--edge-dark);
  font: inherit; color: inherit; text-align: left; cursor: pointer;
  transition: border-color var(--t-quick) var(--ease-out),
              transform var(--t-quick) var(--ease-out),
              box-shadow var(--t-quick) var(--ease-out);
}
/* Each card's own accent, pooled behind its figure. It is the accent already
   on the icon tile, lifted to the whole card at a tenth of the strength, so
   four cards in a row read as four different things at a glance. */
.tk-sum::before {
  content: ""; position: absolute; inset: 0; z-index: -1; opacity: 0;
  transition: opacity var(--t-quick) var(--ease-out);
}
.tk-sum.t-steel::before  { background: radial-gradient(118% 128% at 86% -28%, rgba(143,182,224,.30), transparent 68%); opacity: .85; }
.tk-sum.t-gold::before   { background: radial-gradient(118% 128% at 86% -28%, rgba(232,163,61,.30), transparent 68%);  opacity: .85; }
.tk-sum.t-green::before  { background: radial-gradient(118% 128% at 86% -28%, rgba(121,185,40,.32), transparent 68%);  opacity: .85; }
.tk-sum.t-indigo::before { background: radial-gradient(118% 128% at 86% -28%, rgba(142,140,240,.30), transparent 68%); opacity: .85; }
/* The lit top edge in the card's own hue. Without it the wash reads as a
   stain in the corner; with it the card reads as an object catching light. */
.tk-sum::after {
  content: ""; position: absolute; top: 0; left: 0; right: 0; height: 1px;
}
.tk-sum.t-steel::after  { background: linear-gradient(90deg, rgba(169,203,239,.8), transparent 74%); }
.tk-sum.t-gold::after   { background: linear-gradient(90deg, rgba(232,163,61,.8), transparent 74%); }
.tk-sum.t-green::after  { background: linear-gradient(90deg, rgba(148,213,60,.8), transparent 74%); }
.tk-sum.t-indigo::after { background: linear-gradient(90deg, rgba(142,140,240,.8), transparent 74%); }
.tk-sum.t-steel:hover  { border-color: rgba(143,182,224,.45); }
.tk-sum.t-gold:hover   { border-color: rgba(232,163,61,.45); }
.tk-sum.t-green:hover  { border-color: rgba(148,213,60,.45); }
.tk-sum.t-indigo:hover { border-color: rgba(142,140,240,.45); }
.tk-sum:hover { transform: translateY(-3px); border-color: var(--ws-line-2);
  box-shadow: var(--shadow-md), var(--edge-dark); }
.tk-sum:hover::before { opacity: 1; }
.tk-sum:active { transform: translateY(-1px); }
.tk-sum:focus-visible { outline: none; box-shadow: var(--ring); }
.tk-sum.is-on { border-color: rgba(148,213,60,.5);
  box-shadow: var(--shadow-glow), var(--edge-dark); }
.tk-sum-i { flex: none; width: 34px; height: 34px; border-radius: 11px;
  display: grid; place-items: center; box-shadow: var(--edge-dark);
  transition: transform var(--t-quick) var(--ease-out); }
.tk-sum:hover .tk-sum-i { transform: scale(1.07) rotate(-3deg); }
.tk-sum-i svg { width: 18px; height: 18px; }
.tk-sum.t-steel  .tk-sum-i { background: rgba(143,182,224,.20); color: var(--steel-400);
  box-shadow: 0 0 0 1px rgba(143,182,224,.28), 0 4px 14px -6px rgba(143,182,224,.6); }
.tk-sum.t-gold   .tk-sum-i { background: rgba(232,163,61,.20);  color: var(--gold-500);
  box-shadow: 0 0 0 1px rgba(232,163,61,.28), 0 4px 14px -6px rgba(232,163,61,.6); }
.tk-sum.t-green  .tk-sum-i { background: rgba(121,185,40,.20);   color: var(--green-400);
  box-shadow: 0 0 0 1px rgba(148,213,60,.28), 0 4px 14px -6px rgba(121,185,40,.6); }
.tk-sum.t-indigo .tk-sum-i { background: rgba(142,140,240,.20);   color: var(--ws-indigo);
  box-shadow: 0 0 0 1px rgba(142,140,240,.28), 0 4px 14px -6px rgba(142,140,240,.6); }
.tk-sum-b { min-width: 0; display: grid; gap: 1px; }
.tk-sum-l { font-size: 12px; color: var(--on-navy-soft); line-height: 1.3; }
.tk-sum-n { font-family: var(--f-display); font-weight: 800; font-stretch: 104%;
  font-size: 25px; line-height: 1.05; letter-spacing: -.03em; color: #fff;
  font-variant-numeric: tabular-nums; }
.tk-sum-d { font-size: 11px; color: var(--on-navy-mute); display: flex;
  align-items: center; gap: 4px; }
.tk-sum-d.up { color: var(--green-400); }
.tk-sum.is-on .tk-sum-n { color: var(--green-400); }

/* ---- the saved-search strip ----------------------------------------- */
.tk-saved { display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 11px 15px; border-radius: 12px; margin: 0 0 18px;
  background: linear-gradient(100deg, rgba(143,182,224,.13), rgba(143,182,224,.04));
  border: 1px solid rgba(143,182,224,.24);
  box-shadow: var(--edge-dark), 0 6px 20px -14px rgba(143,182,224,.5); }
.tk-saved:empty { display: none; }
.tk-saved svg { width: 15px; height: 15px; color: var(--steel-400); flex: none; }
.tk-saved b { color: var(--steel-400); font-weight: 600; font-size: 13.5px; }
.tk-saved span { font-size: 13.5px; color: var(--on-navy-soft); }
.tk-saved a { margin-left: auto; font-size: 13px; color: var(--steel-400);
  text-decoration: none; font-weight: 600; white-space: nowrap; }
.tk-saved a:hover { text-decoration: underline; }

/* ---- the board ------------------------------------------------------ */
/* A KANBAN IS A ROW, and dropping a column when the panel opens breaks it -
   "Submitted" wrapping to a second line is not a narrower board, it is a
   different one. So the columns keep their width and the board scrolls
   sideways, which is what every board of this kind does and what a subscriber
   already expects from one.

   The page itself must still never scroll sideways; the overflow is on this
   element and nowhere else. */
.tk-board { display: flex; gap: 12px; align-items: flex-start;
  overflow-x: auto; padding-bottom: 10px; scroll-snap-type: x proximity; }
.tk-board > .tk-col { flex: 1 0 262px; max-width: 420px; scroll-snap-align: start; }
@media (max-width: 560px) { .tk-board > .tk-col { flex: 1 0 84%; } }

/* A column is a surface the cards sit ON, so it is the quieter glass of the
   two steps, and it carries its stage's colour as a lit bar along the top
   edge - which is how a kanban tells you where you are without reading the
   header. */
.tk-col { position: relative; overflow: hidden;
  background: linear-gradient(180deg, rgba(255,255,255,.045), rgba(255,255,255,.012)),
              rgba(10,22,39,.72);
  border: 1px solid var(--ws-line);
  border-radius: 15px; padding: 12px 10px 11px; min-width: 0;
  display: flex; flex-direction: column; gap: 9px;
  box-shadow: var(--shadow-sm), var(--edge-dark);
  transition: border-color var(--t-quick) var(--ease-out),
              box-shadow var(--t-quick) var(--ease-out); }
.tk-col::before { content: ""; position: absolute; top: 0; left: 0; right: 0;
  height: 2px; opacity: .85;
  background: linear-gradient(90deg, rgba(255,255,255,.22), transparent 88%); }
.tk-col.c-w::before { background: linear-gradient(90deg, rgba(147,168,194,.6), transparent 88%); }
.tk-col.c-q::before { background: linear-gradient(90deg, var(--steel-400), transparent 88%); }
.tk-col.c-p::before { background: linear-gradient(90deg, var(--gold-500), transparent 88%); }
.tk-col.c-s::before { background: linear-gradient(90deg, var(--green-400), transparent 88%); }
/* THE DROP TARGET HAS TO BE UNMISTAKABLE. You are mid-drag with a card under
   the cursor; a one-shade border change is not an answer to "will it land
   here". */
.tk-col.is-over { border-color: rgba(148,213,60,.6);
  background: linear-gradient(180deg, rgba(121,185,40,.14), rgba(121,185,40,.03)),
              rgba(10,22,39,.72);
  box-shadow: var(--shadow-glow); }
.tk-col-h { display: flex; align-items: center; gap: 8px; padding: 1px 3px 2px; }
.tk-col-h svg { width: 16px; height: 16px; flex: none; }
.tk-col-h b { font-size: 14px; font-weight: 600; color: #fff; }
.tk-col-n { font-family: var(--f-mono); font-size: 11px; color: var(--on-navy-mute);
  background: rgba(255,255,255,.07); border-radius: 999px; padding: 2px 8px;
  box-shadow: var(--edge-dark); }
.tk-col.c-q .tk-col-n { color: var(--steel-400); background: rgba(143,182,224,.15); }
.tk-col.c-p .tk-col-n { color: var(--gold-500); background: rgba(232,163,61,.15); }
.tk-col.c-s .tk-col-n { color: var(--green-400); background: rgba(121,185,40,.16); }
.tk-col-more { margin-left: auto; background: none; border: 0; cursor: pointer;
  color: var(--on-navy-mute); font-size: 16px; line-height: 1; padding: 2px 5px;
  border-radius: 6px; }
.tk-col-more:hover { background: rgba(255,255,255,.07); color: #fff; }
.tk-col.c-w .tk-col-h svg { color: var(--on-navy-mute); }
.tk-col.c-q .tk-col-h svg { color: var(--steel-400); }
.tk-col.c-p .tk-col-h svg { color: var(--gold-500); }
.tk-col.c-s .tk-col-h svg { color: var(--green-400); }
.tk-col-empty { font-size: 12.5px; color: var(--on-navy-mute); line-height: 1.5;
  padding: 14px 4px; text-align: center; border: 1px dashed var(--ws-line);
  border-radius: 10px; }

/* ---- a card --------------------------------------------------------- */
.tk-card {
  background: var(--ws-glass), var(--ws-card);
  border: 1px solid var(--ws-line); position: relative;
  border-radius: 11px; padding: 11px 11px; cursor: pointer; display: grid;
  gap: 7px; text-align: left; font: inherit; color: inherit; width: 100%;
  box-shadow: var(--shadow-xs), var(--edge-dark);
  transition: border-color var(--t-tint) var(--ease-out),
              transform var(--t-tint) var(--ease-out),
              box-shadow var(--t-tint) var(--ease-out),
              background var(--t-tint) var(--ease-out);
}
.tk-card:hover { border-color: var(--ws-line-2); transform: translateY(-2px);
  background: var(--ws-glass-2), var(--ws-card);
  box-shadow: var(--shadow-md), var(--edge-dark); }
.tk-card:focus-visible { outline: none; box-shadow: var(--ring); }
.tk-card.is-open { border-color: rgba(148,213,60,.55);
  box-shadow: var(--shadow-glow), var(--edge-dark); }
.tk-card[draggable="true"] { cursor: grab; }
/* The card being dragged goes translucent and tips very slightly, so the one
   under the cursor is obviously the one in flight. */
.tk-card.is-drag { opacity: .4; transform: rotate(1.4deg) scale(.985); cursor: grabbing; }
.tk-card-t { display: flex; align-items: flex-start; gap: 8px; }
.tk-card-t h4 { margin: 0; font-size: 13px; line-height: 1.35; font-weight: 600;
  color: #fff; flex: 1 1 auto; min-width: 0; overflow-wrap: anywhere; }
.tk-star { flex: none; background: none; border: 0; cursor: pointer; padding: 0;
  color: var(--on-navy-mute); line-height: 0; }
.tk-star svg { width: 15px; height: 15px; }
.tk-star.is-on { color: var(--gold-500); }
.tk-card-ag { margin: 0; font-size: 11.5px; color: var(--on-navy-mute); line-height: 1.35;
  overflow-wrap: anywhere; }
.tk-card-m { display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  font-family: var(--f-mono); font-size: 11px; color: var(--on-navy-soft); }
.tk-card-m i { font-style: normal; display: inline-flex; align-items: center; gap: 4px; }
.tk-card-m svg { width: 12px; height: 12px; color: var(--on-navy-mute); }
.tk-tags { display: flex; align-items: center; gap: 7px; flex-wrap: wrap; }
.tk-stage { font-size: 11px; padding: 2px 9px; border-radius: 999px; font-weight: 600; }
.tk-stage.c-w { background: rgba(255,255,255,.07); color: var(--on-navy-soft); }
.tk-stage.c-q { background: rgba(143,182,224,.16); color: var(--steel-400); }
.tk-stage.c-p { background: rgba(232,163,61,.16); color: var(--gold-500); }
.tk-stage.c-s { background: rgba(121,185,40,.16); color: var(--green-400); }
.tk-pri { display: inline-flex; align-items: center; gap: 5px; font-size: 11.5px;
  color: var(--on-navy-soft); }
.tk-pri::before { content: ""; width: 7px; height: 7px; border-radius: 50%;
  background: currentColor; }
.tk-pri.p-h { color: var(--danger-300); }
.tk-pri.p-m { color: var(--gold-500); }
.tk-pri.p-l { color: var(--steel-400); }
/* THE CHANGE BANNER. One line, the highest unseen severity, and a count of the
   rest - section 20: "One highest severity unseen change badge per card.
   Additional changes appear as a count." */
.tk-chg { display: flex; align-items: center; gap: 7px; padding: 6px 9px;
  border-radius: 8px; font-size: 11.5px; line-height: 1.35; }
.tk-chg svg { width: 13px; height: 13px; flex: none; }
.tk-chg b { font-weight: 600; }
.tk-chg span { margin-left: auto; font-family: var(--f-mono); font-size: 10.5px;
  opacity: .8; flex: none; }
.tk-chg.s-critical { background: rgba(179,38,30,.16); color: var(--danger-300); }
.tk-chg.s-high { background: rgba(232,163,61,.14); color: var(--gold-300); }
.tk-chg.s-medium { background: rgba(232,163,61,.1); color: var(--gold-500); }
.tk-chg.s-low { background: rgba(143,182,224,.12); color: var(--steel-400); }

/* ---- the list view -------------------------------------------------- */
.tk-list { display: grid; gap: 1px; background: var(--ws-line);
  border: 1px solid var(--ws-line); border-radius: 12px; overflow: hidden; }
.tk-list .tk-row { display: grid; gap: 3px 14px; padding: 12px 15px;
  background: var(--ws-card); grid-template-columns: 1fr auto; align-items: center;
  cursor: pointer; text-align: left; font: inherit; color: inherit; border: 0; width: 100%; }
.tk-list .tk-row:hover { background: var(--ws-card-hi); }
.tk-row-t { font-size: 13.5px; font-weight: 600; color: #fff; min-width: 0;
  overflow-wrap: anywhere; }
.tk-row-s { grid-column: 1; font-size: 12px; color: var(--on-navy-mute); }
.tk-row-r { grid-row: 1 / span 2; display: flex; align-items: center; gap: 12px;
  flex-wrap: wrap; justify-content: flex-end; }

/* ---- outcomes ------------------------------------------------------- */
.tk-outcomes { display: grid; gap: 12px; margin: 20px 0 0;
  grid-template-columns: repeat(3, minmax(0, 1fr)); }
@media (max-width: 560px) { .tk-outcomes { grid-template-columns: minmax(0,1fr); } }
.tk-out { display: flex; align-items: center; gap: 11px; padding: 13px 15px;
  border-radius: 13px; border: 1px solid var(--ws-line);
  background: var(--ws-glass), rgba(10,22,39,.6);
  box-shadow: var(--shadow-xs), var(--edge-dark);
  font: inherit; color: inherit; cursor: pointer; text-align: left;
  transition: border-color var(--t-quick) var(--ease-out),
              transform var(--t-quick) var(--ease-out),
              box-shadow var(--t-quick) var(--ease-out); }
.tk-out:hover { border-color: var(--ws-line-2); transform: translateY(-2px);
  box-shadow: var(--shadow-sm), var(--edge-dark); }
.tk-out:focus-visible { outline: none; box-shadow: var(--ring); }
.tk-out.is-on { border-color: rgba(148,213,60,.5);
  box-shadow: var(--shadow-glow), var(--edge-dark); }
.tk-out svg { width: 17px; height: 17px; flex: none; color: var(--on-navy-mute); }
.tk-out.o-won svg { color: var(--green-400); }
.tk-out.o-lost svg { color: var(--danger-300); }
.tk-out b { font-size: 13.5px; font-weight: 600; color: var(--on-navy); }
.tk-out em { font-style: normal; margin-left: auto; font-family: var(--f-mono);
  font-size: 14px; color: #fff; }
.tk-out i { font-style: normal; color: var(--on-navy-mute); }

.tk-foot { margin: 26px 0 0; font-size: 12px; line-height: 1.6;
  color: var(--on-navy-mute); max-width: 78ch; }
.tk-foot a { color: var(--green-400); }

/* ---- the detail panel ----------------------------------------------- */
.ws-panel {
  width: var(--ws-panel); flex: none;
  background:
    radial-gradient(100% 34% at 100% 0%, rgba(121,185,40,.09), transparent 62%),
    linear-gradient(190deg, rgba(255,255,255,.05), rgba(255,255,255,.015)),
    rgba(9,20,36,.94);
  -webkit-backdrop-filter: saturate(150%) blur(12px);
  backdrop-filter: saturate(150%) blur(12px);
  border-left: 1px solid var(--ws-line); position: sticky; top: 0; height: 100vh;
  height: 100dvh;
  overflow-y: auto; padding: 20px 20px 40px;
  box-shadow: var(--edge-dark), -22px 0 54px -34px rgba(0,0,0,.9);
  animation: panelin .3s var(--ease-out) both;
}
/* The panel arrives FROM the side it lives on. A fade alone reads as a layer
   appearing on top of the work; a short slide reads as the work making room. */
@keyframes panelin {
  from { opacity: 0; transform: translateX(16px); }
  to   { opacity: 1; transform: none; }
}
.ws-scrim { display: none; }
.pn-top { display: flex; align-items: flex-start; gap: 10px; margin-bottom: 3px; }
.pn-top h2 { margin: 0; font-size: 16px; line-height: 1.35; font-weight: 700;
  color: #fff; flex: 1 1 auto; min-width: 0; overflow-wrap: anywhere;
  /* Not the page-title treatment: the global h2 is Archivo 900 uppercase and
     wide, which is right for "WHO WINS THE MONEY" and wrong for the name of
     one solicitation. */
  font-family: var(--f-sans); text-transform: none; letter-spacing: -.005em;
  font-stretch: normal; }
/* Every inline icon in this file is sized by its container; the panel's star
   has none, so it takes the width of the panel. */
.pn-top > svg { width: 17px; height: 17px; flex: none; margin-top: 3px;
  color: var(--gold-500); }
.pn-x { flex: none; background: none; border: 0; cursor: pointer; font-size: 20px;
  line-height: 1; color: var(--on-navy-mute); padding: 0 3px; border-radius: 6px; }
.pn-x:hover { color: #fff; background: rgba(255,255,255,.07); }
.pn-ag { margin: 0 0 11px; font-size: 12.5px; color: var(--on-navy-mute); }
.pn-tags { display: flex; align-items: center; gap: 9px; flex-wrap: wrap; margin-bottom: 11px; }
.pn-facts { display: flex; gap: 18px; flex-wrap: wrap; font-size: 12.5px;
  color: var(--on-navy-soft); padding-bottom: 14px; border-bottom: 1px solid var(--ws-line); }
.pn-sec { padding: 14px 0; border-bottom: 1px solid var(--ws-line); }
.pn-sec:last-child { border-bottom: 0; }
.pn-h { font-family: var(--f-mono); font-size: 9.5px; letter-spacing: .13em;
  text-transform: uppercase; color: var(--on-navy-mute); margin: 0 0 9px; font-weight: 600; }
.pn-k { font-size: 12px; color: var(--on-navy-mute); margin: 0 0 2px; }
.pn-v { font-size: 13.5px; color: var(--on-navy); margin: 0 0 10px; line-height: 1.5;
  overflow-wrap: anywhere; }
.pn-v a { color: var(--green-400); text-decoration: none; }
.pn-v a:hover { text-decoration: underline; }
.pn-row { display: grid; gap: 5px; margin-bottom: 12px; }
.pn-row > label { font-size: 12px; color: var(--on-navy-mute); }
.pn-row select, .pn-row input, .pn-row textarea {
  font: inherit; font-size: 13.5px; padding: 8px 10px; border-radius: 8px;
  border: 1px solid var(--ws-line); background: var(--ws-card); color: var(--on-navy);
  width: 100%;
}
.pn-row textarea { min-height: 74px; resize: vertical; line-height: 1.5; }
.pn-row select:focus, .pn-row input:focus, .pn-row textarea:focus {
  outline: none; box-shadow: var(--ring); border-color: rgba(148,213,60,.5); }
.pn-chg { display: flex; align-items: center; gap: 8px; padding: 8px 10px;
  border-radius: 8px; font-size: 12.5px; margin-bottom: 7px; }
.pn-chg span { margin-left: auto; font-family: var(--f-mono); font-size: 10.5px; opacity: .8; }
.pn-acts { display: grid; gap: 8px; margin-top: 4px; }
.pn-btn { display: flex; align-items: center; justify-content: center; gap: 8px;
  padding: 10px 14px; border-radius: 9px; font: inherit; font-size: 13.5px;
  font-weight: 600; cursor: pointer; text-decoration: none; border: 1px solid var(--ws-line);
  background: var(--ws-card); color: var(--on-navy); }
.pn-btn:hover { background: var(--ws-card-hi); }
.pn-btn.primary { background: var(--green-500); border-color: var(--green-500);
  color: #08172A; }
.pn-btn.primary:hover { background: var(--green-400); }
.pn-btn[disabled] { opacity: .45; cursor: not-allowed; }
.pn-note { font-size: 11.5px; line-height: 1.5; color: var(--on-navy-mute);
  margin: 8px 0 0; }

/* ---- the empty board ------------------------------------------------ */
/* The first-visit state fills the workspace rather than sitting in a box in
   the corner. Section 88: the first five minutes have to be useful before
   anything is saved, and a small empty rectangle in a large empty page reads
   as a broken board rather than a new one. */
.tk-none { padding: clamp(40px, 8vh, 90px) 24px; text-align: center;
  border-radius: 16px; border: 1px dashed var(--ws-line-2);
  background:
    radial-gradient(100% 80% at 50% -10%, rgba(121,185,40,.10), transparent 64%),
    var(--ws-glass), rgba(10,22,39,.6);
  box-shadow: var(--shadow-md), var(--edge-dark);
  max-width: 720px; margin: 6vh auto 0;
  animation: rise .7s var(--ease-out) both; }
/* An inline SVG with no width takes the whole column. Every icon in this file
   is sized by its container, so the empty state has to say so too. */
.tk-none > svg { width: 30px; height: 30px; color: var(--on-navy-mute);
  margin-bottom: 12px; }
.tk-none h3 { margin: 0 0 8px; font-size: 17px; color: #fff; }
.tk-none p { margin: 0 auto 16px; max-width: 52ch; font-size: 14px; line-height: 1.6;
  color: var(--on-navy-soft); }

/* ---- responsive ------------------------------------------------------
   The rail collapses to icons at 1100 and to a top strip on a phone; the
   panel becomes a full-screen sheet, which is section 61's requirement in as
   many words: "Side panels should become full screen sheets on narrow
   screens." */
@media (max-width: 1240px) {
  .ws { --ws-panel: 330px; }
}
/* The rail's own collapse to icons happens at 1180 and is defined in
   style.css, once, for both modes. Nothing about it belongs here. */
/* THE PANEL OVERLAYS RATHER THAN SQUEEZING, and 1180 is where that has to
   start. Below it, a 380px panel beside a 232px rail leaves under 570px of
   board, which is two columns of a four-column kanban - the panel would be
   taking the thing it is meant to explain off the screen. */
@media (max-width: 1439px) {
  .ws-panel { position: fixed; inset: 0 0 0 auto; width: min(420px, 100%);
    z-index: 60; box-shadow: var(--shadow-lg); }
  .ws-scrim { display: block; position: fixed; inset: 0; z-index: 55;
    background: rgba(5,12,23,.6); }
  .ws-scrim[hidden] { display: none; }
}
/* ON A PHONE THE RAIL LIES DOWN. The workspace pages have no other
   navigation - there is no top bar here to fall back on the way the document
   pages have - so it becomes a scrolling strip across the top rather than
   disappearing. The active row keeps its green pill; the indicator bar moves
   from the left edge to the bottom, because a vertical mark on a horizontal
   strip points at nothing. */
@media (max-width: 720px) {
  .ws-shell { flex-direction: column; }
  .ws-shell > .ws-rail { width: 100%; height: auto; position: sticky; top: 0;
    z-index: 60; flex-direction: row; align-items: center; overflow-x: auto;
    overflow-y: hidden; padding: 9px 12px;
    border-right: 0; border-bottom: 1px solid var(--ws-line);
    background:
      radial-gradient(60% 180% at 6% 0%, rgba(121,185,40,.15), transparent 66%),
      linear-gradient(180deg, #0B1B2F, #071322);
    -webkit-backdrop-filter: saturate(160%) blur(14px);
    backdrop-filter: saturate(160%) blur(14px); }
  .ws-shell > .ws-rail::before,
  .ws-shell > .ws-rail::after { display: none; }
  .ws-shell > .ws-rail .ws-brand { padding: 0 12px 0 0; }
  .ws-shell > .ws-rail .ws-nav { display: flex; gap: 2px; padding: 0; }
  .ws-shell > .ws-rail .ws-nav-foot { margin-top: 0; margin-left: 6px;
    padding-top: 0; padding-left: 8px; }
  .ws-shell > .ws-rail .ws-nav-foot::before { top: 12px; bottom: 12px;
    left: 0; right: auto; width: 1px; height: auto;
    background: linear-gradient(180deg, transparent, rgba(255,255,255,.18), transparent); }
  .ws-shell > .ws-rail .ws-nav a.is-here::after {
    left: 50%; top: auto; bottom: -7px; translate: -50% 0;
    width: 60%; height: 3px; border-radius: 3px 3px 0 0; animation: none; }
  /* THE FEDERAL GROUP IN A HORIZONTAL STRIP, 2026-09-01. The rail lies down
     here, and a group whose children are a vertical <ul> drops four icons out
     of the strip and down over the board. On a strip a group is not a
     container - it is four more stops along the row - so the <li>, its button
     and its children all lie down together, and the toggle is retired for the
     same reason it is retired on the icon-only rail: a control whose label is
     not on screen cannot be understood, and hiding four rooms behind it is
     worse than showing them. */
  .ws-shell > .ws-rail .ws-nav-grp { display: flex; align-items: center; gap: 2px; }
  .ws-shell > .ws-rail .ws-nav-sub {
    display: flex !important; gap: 2px; margin: 0 0 0 2px; padding: 0 0 0 6px;
    border-left: 1px solid rgba(255,255,255,.12); }
  .ws-shell > .ws-rail .ws-nav-b { pointer-events: none; }
  .ws-shell > .ws-rail .ws-nav-b .car { display: none; }
  /* A rule between groups on a horizontal strip is a vertical one. */
  .ws-shell > .ws-rail .ws-nav li.ws-nav-sep {
    width: 1px; height: 20px; margin: 0 7px; flex: none;
    background: linear-gradient(180deg, transparent, rgba(255,255,255,.2), transparent); }
  /* Nothing on the strip wraps: it scrolls sideways instead. */
  .ws-shell > .ws-rail .ws-nav a,
  .ws-shell > .ws-rail .ws-nav .ws-nav-dead { white-space: nowrap; flex: none; }
  .ws-head, .ws-body { padding-left: 16px; padding-right: 16px; }
  .tk-view { margin-left: 0; }
}

/* ===========================================================================
   THE FAMILY BACKDROP. Every board header carries a still from its family
   (assets/fam/, Higgsfield 2026-09-05, recoloured from one composition so the
   boards read as one product): federal money in the site green, Legislative
   in violet, the Calendar in amber, Foundations in rose. It sits under the
   glass at low opacity and fades out to the right so the controls stay on a
   plain ground. Below 900px it goes; the header is too short to carry it.
   =========================================================================== */
.ws-head { isolation: isolate; }
.ws-head::before {
  content: ""; position: absolute; inset: 0; z-index: -1; pointer-events: none;
  /* Positioned on the upper band of the still, where the points are; the
     composition's centre is deliberately empty and a header is only 130px tall. */
  background: url("fam/federal.jpg") 50% 12% / cover no-repeat; opacity: .85;
  mix-blend-mode: screen;
  -webkit-mask-image: linear-gradient(90deg, #000 18%, transparent 88%);
  mask-image: linear-gradient(90deg, #000 18%, transparent 88%);
}
body[data-page="legislative"] .ws-head::before { background-image: url("fam/legislative.jpg"); }
body[data-page="calendar"] .ws-head::before { background-image: url("fam/pipeline.jpg"); }
body[data-page="foundations"] .ws-head::before { background-image: url("fam/foundations.jpg"); }
@media (max-width: 899px) { .ws-head::before { display: none; } }
/* THE WORKSHOP. The Depot is a parts counter; its header sits on a drafting
   table (assets/fam/blueprint.jpg, texture only - every part line is typeset). */
body[data-page="depot"] .ws-head::before { background-image: url("fam/blueprint.jpg"); background-position: 50% 30%; opacity: .95; }
