:root{
  --bg:#05070a; --bg-2:#080c12;
  --panel:#0d131b; --panel-2:#121a24; --panel-3:#18222e;
  --line:#1d2836; --line-2:#2a3745;
  --ink:#e9eff7; --ink-2:#9aabbd; --ink-3:#61748a;
  --green:#35e07a; --green-2:#1f7f47; --green-glow:rgba(53,224,122,.30);
  --violet:#a06bff; --violet-2:#5b3b9e;
  --amber:#ffb454; --rose:#ff6b81; --cyan:#4fd6e0;
  /* Square, everywhere. The den is drawn in pixels and a rounded panel
     floating over it reads as a different application. Kept as tokens so
     there is still one place to answer the question. */
  --r:0; --r-sm:0; --r-xs:0;
  /* Depth is an offset, not a blur: the way a sprite casts a shadow. */
  --lift:4px 4px 0 rgba(0,0,0,.38); --lift-lg:8px 8px 0 rgba(0,0,0,.6);
  --fd:'Press Start 2P', ui-monospace, monospace;
  --fb:'Outfit', ui-sans-serif, system-ui, sans-serif;
  --fm:'DM Mono', ui-monospace, SFMono-Regular, monospace;
  --dock:64px;
}
*{box-sizing:border-box}
[hidden]{display:none !important}
html,body{margin:0;padding:0}
body{
  background:var(--bg); color:var(--ink);
  font-family:var(--fb); font-size:15px; line-height:1.5;
  -webkit-font-smoothing:antialiased;
  overflow:hidden;
}
button,input,textarea,select{font:inherit;color:inherit}
button{cursor:pointer;background:none;border:0}
:focus-visible{outline:2px solid var(--green);outline-offset:2px;border-radius:0}
::selection{background:var(--green-glow)}
canvas{display:block}
.pixel{image-rendering:pixelated;image-rendering:-moz-crisp-edges}
h1,h2,h3,h4{margin:0;text-wrap:balance;font-weight:600;letter-spacing:-.01em}
.num{font-family:var(--fm);font-variant-numeric:tabular-nums}
.eyebrow{font-family:var(--fd);font-size:9px;letter-spacing:.06em;color:var(--ink-3);text-transform:uppercase}

/* ---------- shell ---------- */
#stage{position:fixed;inset:0;display:flex;flex-direction:column;background:transparent}
#bgfx{position:fixed;inset:0;z-index:0;pointer-events:none}

/* ---------- top bar ---------- */
.topbar{
  position:relative;z-index:20;flex:0 0 auto;
  display:flex;align-items:center;gap:14px;
  padding:10px 14px;border-bottom:1px solid var(--line);
  background:linear-gradient(180deg,#0a0f16,#070b11);
}
.brand{display:flex;align-items:center;gap:10px;flex:0 0 auto}
.brand canvas{width:34px;height:34px}
.brand .wordmark{font-family:var(--fd);font-size:15px;letter-spacing:.02em;color:var(--ink);background:none;border:0;padding:0;cursor:pointer}
.brand .wordmark i{color:var(--green);font-style:normal}
/* A chip carries one short word and one number. The word goes pixel; the
   number stays in DM Mono, because digits are read, not scanned, and a pixel
   face makes a six-figure acorn count unreadable at this size. */
.chip{
  display:inline-flex;align-items:center;gap:7px;
  padding:6px 10px;border-radius:0;border:2px solid var(--line);
  background:var(--panel);font-size:12px;color:var(--ink-2);
  box-shadow:2px 2px 0 rgba(0,0,0,.35);
}
.chip b{color:var(--ink);font-family:var(--fm);font-variant-numeric:tabular-nums;font-weight:500}
.xpwrap{display:flex;align-items:center;gap:9px;min-width:0}
.lvl{font-family:var(--fd);font-size:9px;color:var(--violet)}
.xpbar{width:132px;height:8px;border-radius:0;background:#131c27;border:1px solid var(--line);overflow:hidden}
.xpbar i{display:block;height:100%;background:linear-gradient(90deg,var(--violet-2),var(--violet));width:0%}
.xptext{font-family:var(--fm);font-size:11px;color:var(--ink-3);white-space:nowrap}
.spacer{flex:1 1 auto}
.tbtn{
  display:inline-flex;align-items:center;gap:7px;padding:8px 12px;border-radius:0;
  white-space:nowrap;
  border:1px solid var(--line);background:var(--panel);color:var(--ink-2);font-size:13px;
  transition:border-color .15s,color .15s,background .15s;
}
/* A toolbar button holding one glyph instead of a word.

   .tbtn's padding is sized for a word. Give it a single 6px arrow and the
   content box comes out four pixels wide, the glyph overflows it, and what you
   aim at stops being the same shape as what takes the click -- you end up
   having to hit the arrow exactly. A square the height of its neighbours, with
   the glyph centred in it and large enough to be a target, is the whole fix. */
.tbtn.icon{
  justify-content:center;padding:0;min-width:38px;min-height:38px;
  font-size:18px;line-height:1;
}
.tbtn:hover{border-color:var(--line-2);color:var(--ink);background:var(--panel-2)}
.tbtn.on{border-color:var(--green-2);color:var(--ink);background:#0f1b16}
.who{font-size:13px;color:var(--ink-2)}
.who b{color:var(--ink);font-weight:500}

/* ---------- lobby ---------- */
.lobby{position:relative;z-index:10;flex:1 1 auto;display:flex;min-height:0}
.side{
  flex:0 0 268px;border-right:1px solid var(--line);
  padding:16px 14px;display:flex;flex-direction:column;gap:10px;
  background:linear-gradient(180deg,rgba(13,19,27,.92),rgba(7,11,17,.92));
  overflow-y:auto;transition:margin-left .25s ease;
}
.lobby.collapsed .side{margin-left:-269px}
.side h3{font-size:16px;font-weight:600}
/* Every text field, by element rather than by class.

   This is what the reskin missed: three fields were styled inline from
   JavaScript -- the display name, the journal box, a session row -- so the
   stylesheet never reached them and they kept their rounded corners while
   everything around them went square. A rule that only covers the classes
   someone remembered to add is a rule that loses to the next `el("input")`.
   Element selectors sit below class selectors, so .statusin, .inline,
   .relname and .tokenbox still win where they are used. */
input[type=text],input[type=email],input[type=password],input[type=search],
input[type=url],input[type=number],input:not([type]),textarea,select{
  box-sizing:border-box;padding:11px 12px;border-radius:0;
  border:2px solid var(--line);background:var(--panel-2);color:var(--ink);
  font-family:var(--fb);font-size:14px;
}
input::placeholder,textarea::placeholder{color:var(--ink-3)}

/* Dropdowns.

   The list a <select> drops is drawn by the operating system, not the page --
   on a Mac it is an NSMenu, and CSS on <option> has never reached it. The only
   ways out used to be living with it or hand-building a listbox, and a
   hand-built one means re-implementing arrow keys, type-ahead, aria-activedes-
   cendant and focus, which is where accessibility quietly goes to die.

   `appearance: base-select` is the third way: the popup becomes part of the
   page and takes CSS, while the element stays a real <select> and keeps its
   keyboard behaviour, its form semantics and, on a phone, the native wheel.
   Browsers that do not know it ignore these rules and show the system menu,
   which is exactly the fallback we would have written anyway. */
select, ::picker(select){ appearance:base-select; }

select{ cursor:pointer }
select:hover{ border-color:var(--line-2) }

/* Only where the opt-in took. A native <select> renders its own box and does
   not want to be a flex container -- these rules would fight its metrics in
   Safari and Firefox, which is the one place a fallback can still go wrong. */
@supports (appearance: base-select){
  select{
    display:flex;align-items:center;gap:8px;
    /* base-select drops the platform's own padding, so it comes from here. */
    padding:10px 12px;
  }
  select:open{ border-color:var(--green-2) }
}
/* The arrow, redrawn: a triangle of the same green as everything else. */
select::picker-icon{ content:"\25be";color:var(--green);font-size:11px;margin-left:auto;
  transition:transform .12s }
select:open::picker-icon{ transform:rotate(180deg) }

::picker(select){
  border:2px solid var(--line-2);border-radius:0;background:var(--panel);
  box-shadow:var(--lift-lg);padding:0;margin-top:2px;
}
option{
  padding:9px 12px;background:var(--panel);color:var(--ink-2);
  font-family:var(--fb);font-size:13px;border:0;
}
option:hover,option:focus{ background:var(--panel-3);color:var(--ink) }
option:checked{ color:var(--green) }
/* The tick the picker adds. Square, because everything here is. */
option::checkmark{ content:"\25aa";color:var(--green);margin-right:8px }
option:disabled{ color:var(--ink-3) }

/* Scrollbars.

   Styling ::-webkit-scrollbar at all makes the browser abandon the overlay
   scrollbar and lay out a real one, so this costs about twelve pixels of width
   wherever something scrolls. That is the trade: a scrollbar you can see and
   that belongs to the room, against a sliver of space.

   The grip is a repeating gradient rather than an image -- three notches, the
   way a sprite would draw a handle. Firefox cannot square its scrollbar, so it
   gets the colours and keeps its own shape; that is the whole of what
   scrollbar-color can say. */
/* Colour only. scrollbar-width is not just a Firefox hint any more -- Chrome
   honours it too, and `thin` there silently overrides the width set on
   ::-webkit-scrollbar below, which is why this bar stayed 11px while the rule
   said 14. Firefox keeps its own width and takes the colours. */
*{scrollbar-color:#2a9d5c #050a10}

::-webkit-scrollbar{width:14px;height:14px}
::-webkit-scrollbar-track{background:#050a10;border:2px solid var(--line);border-radius:0}
::-webkit-scrollbar-thumb{
  background:#2a9d5c;border:2px solid #0d4f2c;border-radius:0;
  /* Chunky enough to read at ten pixels across. Two-on, four-off stripes are
     a grip; the hairlines that were here first vanished at this size. */
  background-image:repeating-linear-gradient(180deg,
    rgba(255,255,255,.22) 0 2px, transparent 2px 6px);
}
::-webkit-scrollbar-thumb:horizontal{
  background-image:repeating-linear-gradient(90deg,
    rgba(255,255,255,.22) 0 2px, transparent 2px 6px);
}
::-webkit-scrollbar-thumb:hover{background:var(--green)}
::-webkit-scrollbar-thumb:active{background:#7bf3ac}
/* Where the two bars meet, so the gap is not a pale native square. */
::-webkit-scrollbar-corner{background:#050a10}

/* Sliders.

   The last round thing in the application, and the one no sweep of the DOM can
   find: a range thumb is a pseudo-element, so querySelectorAll never sees it
   and it kept its circle through the whole reskin. Styling it at all requires
   giving up the native control first, which then means drawing the track too,
   and doing it twice because WebKit and Gecko name the parts differently. */
input[type=range]{
  -webkit-appearance:none;appearance:none;
  width:100%;height:14px;background:transparent;cursor:pointer;padding:0;border:0;
}
input[type=range]::-webkit-slider-runnable-track{
  height:10px;background:#050a10;border:2px solid var(--line-2);border-radius:0;
}
input[type=range]::-webkit-slider-thumb{
  -webkit-appearance:none;appearance:none;
  width:12px;height:14px;border-radius:0;background:var(--green);
  border:2px solid #0d4f2c;margin-top:-4px;
}
input[type=range]:focus-visible::-webkit-slider-thumb{background:#7bf3ac}
input[type=range]::-moz-range-track{
  height:10px;background:#050a10;border:2px solid var(--line-2);border-radius:0;
}
input[type=range]::-moz-range-thumb{
  width:12px;height:14px;border-radius:0;background:var(--green);border:2px solid #0d4f2c;
}

.statusin{
  width:100%;padding:11px 12px;border-radius:0;
  background:var(--panel-2);border:1px solid var(--line);color:var(--ink);font-size:14px;
}
.statusin::placeholder{color:var(--ink-3)}
.big{
  width:100%;padding:14px;border-radius:0;text-align:center;
  /* Press Start 2P has no descender room and no lowercase rhythm, so it needs
     looser leading and a size of its own -- 10px here reads about the same as
     15px of Outfit did. Only ever on a few words. */
  font-family:var(--fd);font-size:10px;line-height:1.6;letter-spacing:.02em;
  border:2px solid transparent;
  transition:transform .1s,filter .15s,box-shadow .1s;
}
/* Pressed means pressed: the button moves onto its own shadow. */
.big:active{transform:translate(2px,2px)}
.big.go:active{box-shadow:2px 2px 0 #0d4f2c}
.big.go{background:var(--green);color:#04150b;border-color:#0d4f2c;box-shadow:4px 4px 0 #0d4f2c}
.big.go:hover{filter:brightness(1.07)}
.big.alt{background:var(--panel-2);border-color:var(--line-2);color:var(--ink);box-shadow:3px 3px 0 rgba(0,0,0,.4)}
.big.alt:active{box-shadow:1px 1px 0 rgba(0,0,0,.4)}
.big.alt:hover{background:var(--panel-3);border-color:var(--line-2)}
.statbox{margin-top:6px;border:2px solid var(--line);border-radius:0;background:var(--panel);overflow:hidden}
.statbox .hd{padding:10px 13px;border-bottom:1px solid var(--line)}
.statrow{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:9px 13px;font-size:14px}
.statrow+.statrow{border-top:1px solid rgba(29,40,54,.55)}
.statrow span{color:var(--ink-2)}
.statrow b{font-family:var(--fm);font-weight:500;font-variant-numeric:tabular-nums}
.rank{color:var(--violet);font-weight:600;font-family:var(--fb)}

.collapse{
  position:absolute;left:0;top:50%;transform:translateY(-50%);z-index:17;
  transition:left .25s ease;
  width:20px;height:52px;border:1px solid var(--line);border-left:0;
  border-radius:0;background:var(--panel-2);color:var(--ink-3);
}
.collapse:hover{color:var(--ink);background:var(--panel-3)}
.mobstart{display:none;position:absolute;left:12px;right:12px;bottom:12px;z-index:15;width:auto;box-shadow:var(--lift-lg)}

.main{flex:1 1 auto;min-width:0;display:flex;flex-direction:column;overflow:hidden}
.tabs{
  display:flex;gap:2px;padding:0 16px;border-bottom:1px solid var(--line);
  overflow-x:auto;scrollbar-width:none;flex:0 0 auto;
}
.tabs::-webkit-scrollbar{display:none}
.tab{
  padding:14px 14px 12px;font-size:14px;color:var(--ink-3);white-space:nowrap;
  border-bottom:2px solid transparent;transition:color .15s,border-color .15s;
}
.tab:hover{color:var(--ink-2)}
.tab.on{color:var(--ink);border-bottom-color:var(--green)}
.tab .dot{display:inline-block;width:5px;height:5px;border-radius:0;background:var(--violet);vertical-align:2px;margin-left:6px}
.pane{flex:1 1 auto;overflow-y:auto;padding:22px 24px 40px}
.panehd{display:flex;align-items:flex-end;justify-content:space-between;gap:16px;margin-bottom:18px;flex-wrap:wrap}
.panehd h2{font-size:21px}
.panehd .sub{font-size:13px;color:var(--ink-3);margin-top:3px}
.empty{max-width:520px;margin:56px auto;text-align:center}
.empty .ico{font-size:34px;margin-bottom:10px}
.empty h3{font-size:19px;margin-bottom:8px}
.empty p{color:var(--ink-2);font-size:14px;margin:0 0 18px}
.how{text-align:left;border:1px solid var(--line);background:var(--panel);border-radius:0;padding:14px 16px}
.modal .how+.how{margin-top:10px}
/* The acorn count is where the question gets asked, so it answers it. */
/* No `font:inherit` here. It is a shorthand, so it reset this chip's size and
   family back to whatever the topbar has -- which is why the acorn count came
   out at 15px beside a 12px hours chip. Buttons already inherit from the rule
   at the top of this sheet; saying it twice only undid .chip. */
.chiphelp{cursor:help}
.chiphelp:hover{border-color:var(--line-2)}
.how .eyebrow{display:block;margin-bottom:9px}
.how ul{margin:0;padding-left:18px;color:var(--ink-2);font-size:14px}
.how li+li{margin-top:5px}

/* ---------- cards / grid ---------- */
.card{border:2px solid var(--line);background:var(--panel);border-radius:0;padding:16px;
  box-shadow:var(--lift)}
/* A card's own title is short enough for the pixel face; its subtitle is a
   sentence, so that one stays in Outfit. This is the whole rule of the theme
   in two selectors. */
.card > h3{font-family:var(--fd);font-size:10px;line-height:1.7;margin-bottom:2px}
.card .sub{font-family:var(--fb)}
.grid{display:grid;gap:14px}
.tiles{grid-template-columns:repeat(auto-fit,minmax(168px,1fr))}
.tile .k{font-size:12px;color:var(--ink-3);letter-spacing:.03em;text-transform:uppercase}
.tile .v{font-family:var(--fm);font-size:29px;font-weight:500;font-variant-numeric:tabular-nums;margin-top:6px;line-height:1}
.tile .d{font-size:12px;color:var(--ink-3);margin-top:6px}
.tile .v.g{color:var(--green)} .tile .v.p{color:var(--violet)} .tile .v.a{color:var(--amber)}
.spark{margin-top:10px}
.tbar{display:flex;align-items:center;gap:12px}
.tbar .lb{flex:0 0 34%;min-width:0;font-size:13px;color:var(--ink-2);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.tbar .track{flex:1 1 auto;height:12px;border-radius:0;background:#111a24;border:1px solid var(--line);overflow:hidden}
.tbar .track i{display:block;height:100%;border-radius:0;background:var(--green-2)}
.tbar .vl{flex:0 0 54px;text-align:right;font-family:var(--fm);font-size:12px;font-variant-numeric:tabular-nums;color:var(--ink-2)}

/* ---------- kanban ---------- */
/* overflow-x:auto makes this a scroll container, and a scroll container clips
   both axes -- overflow-y computes to auto whether or not it is asked for. The
   focus ring is 2px at a 2px offset, so anything flush with an edge, like the
   name field for a new list, had its ring sliced off.

   The padding is the room the ring needs. The negative inline margin hands the
   width back: the lists already add up to exactly the width available, so
   padding alone bought the ring its four pixels at the cost of a horizontal
   scrollbar that had never been there. The pane's own 24px of padding absorbs
   the bleed, so nothing moves. */
.board{display:flex;gap:14px;align-items:flex-start;overflow-x:auto;
  padding:4px 4px 14px;margin-inline:-4px}
/* No overflow:hidden. It was here to clip the colour cap to the rounded top
   corners; with square corners it clips nothing but the focus ring of whatever
   sits against the edge. */
.list{flex:0 0 274px;border:2px solid var(--line);border-radius:0;background:var(--panel)}
.list .cap{height:3px;background:var(--violet)}
.list .lh{display:flex;align-items:center;gap:8px;padding:11px 12px}
.list .lh .bul{width:9px;height:9px;border-radius:0;background:var(--violet);flex:0 0 auto}
.list .lh .nm{font-weight:600;font-size:14px;flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.list .lh .ct{font-family:var(--fm);font-size:11px;color:var(--ink-3);background:var(--panel-3);border-radius:0;padding:2px 7px}
.drop{min-height:64px;padding:6px 10px 10px;display:flex;flex-direction:column;gap:8px}
.drop.over{background:rgba(160,107,255,.07)}
.drop .ph{border:1px dashed var(--line-2);border-radius:0;color:var(--ink-3);font-size:13px;text-align:center;padding:18px 8px}
.kc{
  border:1px solid var(--line);background:var(--panel-2);border-radius:0;
  padding:10px 11px;cursor:grab;display:flex;gap:9px;align-items:flex-start;
}
.kc:hover{border-color:var(--line-2)}
.kc.dragging{opacity:.4}
.kc .tx{flex:1 1 auto;font-size:14px;min-width:0;word-break:break-word}
.kc.done .tx{color:var(--ink-3);text-decoration:line-through}
.kc .box{
  width:16px;height:16px;flex:0 0 auto;margin-top:2px;border-radius:0;
  border:1.5px solid var(--line-2);
}
.kc.done .box{background:var(--green);border-color:var(--green);position:relative}
.kc.done .box::after{content:"";position:absolute;left:4px;top:1px;width:5px;height:9px;border:2px solid #04150b;border-top:0;border-left:0;transform:rotate(40deg)}
.kc .x{color:var(--ink-3);font-size:15px;line-height:1;padding:0 2px}
.kc .x:hover{color:var(--rose)}
.addrow{padding:0 10px 10px}
.addlink{color:var(--ink-3);font-size:13px;padding:6px 4px}
.addlink:hover{color:var(--green)}
.inline{
  width:100%;padding:9px 10px;border-radius:0;resize:vertical;
  background:var(--panel-3);border:1px solid var(--green-2);color:var(--ink);font-size:14px;
}
.inline::placeholder{color:var(--ink-3)}
textarea.inline{min-height:58px}
.popover{
  position:fixed;z-index:95;min-width:172px;padding:8px;border-radius:0;
  border:2px solid var(--line-2);background:var(--panel-2);box-shadow:var(--lift-lg);
  display:flex;flex-direction:column;gap:2px;
}
.popover .eyebrow{padding:2px 6px 6px}
.popover button{text-align:left;padding:8px 9px;border-radius:0;font-size:13px;color:var(--ink-2)}
.popover button:hover{background:var(--panel-3);color:var(--ink)}
.popover .none{padding:4px 6px;font-size:13px;color:var(--ink-3)}
.field{display:block;margin-bottom:12px}
.field span{display:block;margin-bottom:6px}
.field input,.field select{
  width:100%;padding:10px 12px;border-radius:0;
  background:var(--panel-2);border:1px solid var(--line);color:var(--ink);font-size:14px;
}
.newlist{flex:0 0 100%;border:1px dashed var(--line-2);border-radius:0;padding:15px;color:var(--ink-3);font-size:14px;text-align:left;background:rgba(18,26,36,.4)}
.newlist:hover{color:var(--ink);border-color:var(--green-2)}

/* ---------- tracker boards (Jira / GitLab) ---------- */
.srcbar{display:flex;align-items:center;gap:12px;margin-bottom:16px;flex-wrap:wrap}
.jql{
  display:flex;align-items:baseline;gap:10px;margin:-6px 0 16px;padding:9px 12px;
  border:1px solid var(--line);border-radius:0;background:var(--panel);overflow-x:auto;
}
.jql code{font-family:var(--fm);font-size:12px;color:var(--ink-2);white-space:nowrap}
.jerr{border:1px solid var(--line-2);border-left:3px solid var(--rose);border-radius:0;
  background:var(--panel);padding:13px 15px;margin-bottom:16px}
.jerr.warn{border-left-color:var(--amber)}
.jerr h3{font-size:15px;margin-bottom:5px}
.jerr p{margin:0;font-size:13px;color:var(--ink-2)}
.jc{border:1px solid var(--line);background:var(--panel-2);border-radius:0;padding:11px;display:flex;flex-direction:column;gap:7px}
.jc:hover{border-color:var(--line-2)}
.jtop{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.jkey{font-family:var(--fm);font-size:12px;color:var(--green);text-decoration:none;border-bottom:1px solid transparent}
.jkey:hover{border-bottom-color:var(--green)}
.jmeta{font-size:11px;color:var(--ink-3)}
.jsum{font-size:14px;line-height:1.35;word-break:break-word}
.jfoot{display:flex;gap:8px}
/* Two per row, always: 2 buttons make one row, 3 or 4 make two. A flex row
   instead squeezed four buttons into one line and each card ended up a
   different height. margin-top:auto drops the block to the bottom, so the
   buttons line up across a row of cards however tall their titles are. */
.jbtns{display:grid;grid-template-columns:1fr 1fr;gap:6px;margin-top:auto;padding-top:4px}
.jbtns .sbtn{width:100%;text-align:center}
/* An odd one out spans the row rather than sitting half-width next to a gap. */
.jbtns .sbtn:last-child:nth-child(odd){grid-column:1 / -1}
.jbadge{font-family:var(--fm);font-size:10px;color:var(--green);border:1px solid var(--green-2);
  border-radius:0;padding:1px 5px;text-decoration:none;flex:0 0 auto;align-self:flex-start;margin-top:2px}
.jbadge:hover{background:rgba(53,224,122,.1)}

/* ---------- calendar ---------- */
.calbar{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-bottom:14px}
.seg{display:flex;flex-wrap:wrap;border:1px solid var(--line);border-radius:0;overflow:hidden;background:var(--panel)}
.seg button{padding:7px 13px;font-size:13px;color:var(--ink-3)}
.seg button.on{background:var(--green);color:#04150b;font-weight:600}
.cal{border:1px solid var(--line);border-radius:0;overflow:hidden;background:var(--panel)}
.cal .dow{display:grid;grid-template-columns:repeat(7,minmax(0,1fr));border-bottom:1px solid var(--line)}
.cal .dow div{padding:8px 10px;font-size:11px;letter-spacing:.07em;color:var(--ink-3);text-transform:uppercase}
.cal .wk{display:grid;grid-template-columns:repeat(7,minmax(0,1fr))}
.cal .wk+.wk{border-top:1px solid var(--line)}
.cell{min-height:92px;padding:7px 8px;border-left:1px solid rgba(29,40,54,.6);display:flex;flex-direction:column;gap:5px;text-align:left;align-items:stretch}
.cell:first-child{border-left:0}
.cell:hover{background:var(--panel-2)}
.cell .dn{font-family:var(--fm);font-size:12px;color:var(--ink-2)}
.cell.out{background:#080c12}
.cell.out .dn{color:#3a4756}
.cell.today{box-shadow:inset 0 0 0 1.5px var(--green)}
.cell.today .dn{color:var(--green)}
.ev{font-size:11px;padding:2px 6px;border-radius:0;background:rgba(160,107,255,.16);color:#cbb0ff;border-left:2px solid var(--violet);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}
.ev.f{background:rgba(53,224,122,.14);color:#96f0bb;border-left-color:var(--green)}
.daylist{display:flex;flex-direction:column;gap:1px}
.dayrow{display:flex;gap:12px;padding:10px 14px;background:var(--panel);align-items:center}
.dayrow .t{font-family:var(--fm);font-size:12px;color:var(--ink-3);width:74px;flex:0 0 auto;white-space:nowrap}

/* ---------- habits ---------- */
.habit{display:flex;align-items:center;gap:12px;padding:12px 14px;border:1px solid var(--line);border-radius:0;background:var(--panel)}
.habit .nm{flex:1 1 auto;min-width:0;font-size:14px}
.habit .streak{font-family:var(--fm);font-size:12px;color:var(--amber)}
.hgrid{display:flex;gap:4px}
.hcell{width:17px;height:17px;border-radius:0;background:#131c27;border:1px solid var(--line);position:relative}
.hcell[data-l="1"]{background:#14442a;border-color:#1b5c38}
.hcell[data-l="2"]{background:#1c7247;border-color:#258b57}
.hcell[data-l="3"]{background:var(--green);border-color:var(--green)}
.hcell.today{box-shadow:0 0 0 2px rgba(53,224,122,.28)}
.inrow{display:flex;gap:9px;margin-bottom:14px}
.inrow input{flex:1 1 auto;padding:11px 13px;border-radius:0;background:var(--panel-2);border:1px solid var(--line)}
.inrow input::placeholder{color:var(--ink-3)}

/* ---------- friends / rooms / leaderboard ---------- */
.rowcard{display:flex;align-items:center;gap:13px;padding:12px 14px;border:1px solid var(--line);border-radius:0;background:var(--panel)}
.rowcard canvas{width:38px;height:38px;flex:0 0 auto;border-radius:0;background:var(--panel-3)}
.rowcard .nm{font-weight:600;font-size:14px}
.rowcard .st{font-size:12px;color:var(--ink-3)}
.rowcard .rt{margin-left:auto;text-align:right}
.rowcard .rt .xptext{margin-top:4px}
.pill{display:inline-flex;align-items:center;gap:5px;font-size:11px;padding:3px 8px;border-radius:0;border:1px solid var(--line-2);color:var(--ink-2)}
.pill.live{border-color:var(--green-2);color:var(--green);background:rgba(53,224,122,.08)}
.pill.idle{color:var(--ink-3)}
.rk{font-family:var(--fd);font-size:11px;color:var(--ink-3);width:26px;text-align:right;flex:0 0 auto}
.rk.g1{color:var(--amber)} .rk.g2{color:#cfd8e3} .rk.g3{color:#d18a5b}
.code{font-family:var(--fm);letter-spacing:.1em;background:var(--panel-3);border:1px solid var(--line);border-radius:0;padding:4px 9px;font-size:12px}

/* ---------- modal ---------- */
.veil{position:fixed;inset:0;z-index:60;background:rgba(3,5,8,.72);display:flex;align-items:center;justify-content:center;padding:24px}
.modal{
  width:100%;max-width:720px;max-height:86vh;display:flex;flex-direction:column;
  border:2px solid var(--line-2);border-radius:0;background:var(--panel);
  box-shadow:var(--lift-lg);overflow:hidden;
}
.modal .mh{display:flex;align-items:center;gap:12px;padding:15px 18px;border-bottom:1px solid var(--line)}
.modal .mh h3{font-family:var(--fd);font-size:11px;line-height:1.7;flex:1 1 auto}
.modal .mb{padding:16px 18px;overflow-y:auto}
.modal .mb .lede{margin:0 0 14px;color:var(--ink-2);font-size:14px}
.modal .mh .sub{color:var(--ink-3);font-size:12px}
.xbtn{width:30px;height:30px;border-radius:0;color:var(--ink-3);font-size:17px;line-height:1}
.xbtn:hover{background:var(--panel-3);color:var(--ink)}
.split{display:flex;gap:0;min-height:340px}
.catlist{flex:0 0 168px;border-right:1px solid var(--line);padding:12px;display:flex;flex-direction:column;gap:4px}
.catlist button{text-align:left;padding:9px 11px;border-radius:0;font-size:13px;color:var(--ink-2)}
.catlist button:hover{background:var(--panel-2);color:var(--ink)}
.catlist button.on{background:var(--green);color:#04150b;font-weight:600}
.items{flex:1 1 auto;padding:14px 16px;overflow-y:auto;display:flex;flex-direction:column;gap:9px}
.items .emptycat{color:var(--ink-2);font-size:14px;padding:10px 2px}
/* The room preview: as wide as the modal allows, and not a thumbnail. */
.roompv{display:block;width:100%;height:auto;border-radius:0;background:#0a1017;image-rendering:pixelated}
.roomtease{margin:12px 0 0;font-size:15px;color:var(--ink);line-height:1.45}
/* Its own line, not a second sentence of the one above it. */
.roomoff{display:block;margin-top:10px}
/* The thumbnail is the way into the room, so it has to look like a door. */
.item canvas.roomzoom{cursor:zoom-in;transition:outline-color .12s;outline:2px solid transparent;outline-offset:2px}
.item canvas.roomzoom:hover{outline-color:var(--green-2,#2f7d4f)}
.item{display:flex;align-items:center;gap:12px;padding:10px 11px;border:2px solid var(--line);border-radius:0;background:var(--panel-2)}
.item canvas{width:48px;height:60px;flex:0 0 auto;border-radius:0;background:#0a1017}
.item .thumb{flex:0 0 auto;display:flex;flex-direction:column;align-items:center;gap:7px}
/* The lit dot borrows .price's amber on purpose: in this shop that colour
   already means "yours", on the word owned right beside it. */
/* Every .dot in this sheet is scoped to its parent, so these are too — a bare
   .dot rule here reaches the tab badge and the tracker pips as well. */
.dots{display:flex;gap:5px;height:9px;align-items:center}
.dots .dot{width:9px;height:9px;padding:0;border-radius:0;border:1px solid var(--line-2);background:var(--panel-3)}
.dots .dot.on{background:var(--amber);border-color:var(--amber);box-shadow:0 0 5px rgba(255,180,84,.45);cursor:pointer}
.dots .dot.on:hover{box-shadow:none;opacity:.6}
/* Bought but switched off: the ring stays amber, so the row still reads as
   "these are yours" and the empty middle is the only thing saying it is idle. */
.dots .dot.off{border-color:var(--amber);background:rgba(255,180,84,.14);cursor:pointer}
.dots .dot.off:hover{background:rgba(255,180,84,.45)}
/* A level with no furniture written for it is not a slot you can fill, so it
   must not look like the merely-locked one next to it. A dashed 1px border on
   a 9px circle is invisible at this size; a smaller solid dot is not. */
.dots .dot.unbuilt{width:5px;height:5px;border:0;background:var(--line-2)}
.dots .dot:disabled{cursor:default}
.item .info{flex:1 1 auto;min-width:0}
.item .info .nm{font-size:14px;font-weight:600;display:flex;align-items:center;gap:7px}
.item .info .ds{font-size:12px;color:var(--ink-3)}
.item .buy{flex:0 0 auto;text-align:right;display:flex;flex-direction:column;gap:6px;align-items:flex-end}
.price{font-family:var(--fm);font-size:12px;color:var(--amber)}
.sbtn{padding:6px 12px;border-radius:0;font-size:12px;border:1px solid var(--line-2);background:var(--panel-3);color:var(--ink-2)}
.sbtn.own{border-color:var(--green-2);color:var(--green);background:rgba(53,224,122,.08)}
.sbtn.eq{background:var(--green);color:#04150b;border-color:var(--green);font-weight:600}
.sbtn:disabled{opacity:.45;cursor:not-allowed}
.tag{font-family:var(--fd);font-size:7px;padding:3px 5px;border-radius:0;background:var(--violet-2);color:#f0e6ff}
.tag.rare{background:#26456e;color:#cfe4ff}
.tag.epic{background:var(--violet-2);color:#f0e6ff}
.tag.legendary{background:linear-gradient(90deg,#b8862b,#ffd24a,#b8862b);background-size:200% 100%;color:#2a1a02;animation:legshine 2.4s linear infinite}
@keyframes legshine{to{background-position:-200% 0}}
.item.legendary{border-color:#6b5320;box-shadow:inset 0 0 0 1px rgba(255,210,74,.10)}
.item.locked canvas,.item.locked .info{opacity:.42}
.sbtn.lock{border-color:#5a4a22;color:#e8c778;background:rgba(255,210,74,.07)}
.sbtn.lock:disabled{opacity:1;cursor:not-allowed}
.node{display:flex;gap:13px;align-items:flex-start;padding:13px;border:1px solid var(--line);border-radius:0;background:var(--panel-2)}
.node .lock{width:34px;height:34px;border-radius:0;background:var(--panel-3);border:1px solid var(--line);display:grid;place-items:center;font-size:15px;flex:0 0 auto}
.node.open .lock{background:rgba(53,224,122,.12);border-color:var(--green-2)}
.node .nb{flex:1 1 auto;min-width:0}
.node .nt{display:flex;align-items:center;gap:8px;font-weight:600;font-size:14px}
.node .nd{font-size:13px;color:var(--ink-2);margin:3px 0 9px}
.mini{height:6px;border-radius:0;background:#131c27;border:1px solid var(--line);overflow:hidden}
.mini i{display:block;height:100%;background:linear-gradient(90deg,var(--violet-2),var(--violet))}
.lvtag{font-family:var(--fm);font-size:11px;color:var(--ink-3);border:1px solid var(--line);border-radius:0;padding:2px 7px;flex:0 0 auto}
.avwrap{display:grid;grid-template-columns:180px 1fr;gap:18px}
.avstage{border:1px solid var(--line);border-radius:0;background:linear-gradient(180deg,#101a22,#0a1016);display:grid;place-items:center;padding:14px}
.avstage canvas{width:132px;height:176px}
.swatches{display:flex;gap:7px;flex-wrap:wrap}
.sw{width:26px;height:26px;border-radius:0;border:2px solid transparent}
.sw.on{border-color:var(--ink)}
.fgroup{margin-bottom:15px}
.fgroup .eyebrow{display:block;margin-bottom:8px}
.intg{display:flex;flex-direction:column;gap:8px}
.intg .row{display:flex;align-items:center;gap:10px;padding:11px 12px;border:1px solid var(--line);border-radius:0;background:var(--panel-2)}
.intg .row .nm{font-weight:600}
.intg .row .st{font-size:12px;color:var(--ink-3)}
.intg .row .acts{margin-left:auto;display:flex;gap:6px}
.intg .row .acts button,.intg .tokenrow button{padding:6px 10px;border-radius:0;border:1px solid var(--line-2);color:var(--ink-2);font-size:12px}
.intg .row .acts button:hover,.intg .tokenrow button:hover{background:var(--panel-3);color:var(--ink)}
.intg .dot{width:8px;height:8px;border-radius:0;background:var(--ink-3);flex:0 0 auto}
.intg .dot.on{background:var(--green)}
.intg .tokenrow{display:flex;gap:8px}
.intg .tokenbox{width:100%;padding:11px 12px;border-radius:0;background:var(--panel-2);border:1px solid var(--line);color:var(--ink);font-family:var(--fm)}
.intg .tokenrow .tokenbox{flex:1;width:auto}

/* ---------- den ---------- */
.den{position:relative;z-index:10;flex:1 1 auto;min-height:0;overflow:hidden;background:#0a0710}
#room{position:absolute;inset:0;width:100%;height:100%}
.float{position:absolute;z-index:12}
.timer{
  left:22px;top:20px;width:262px;border:1px solid var(--line-2);border-radius:0;
  background:rgba(9,13,19,.9);padding:14px;
  box-shadow:var(--lift-lg);
}
.tmode{display:flex;gap:16px;border-bottom:1px solid var(--line);margin:-2px 0 12px}
.tmode button{padding:0 0 9px;font-size:14px;color:var(--ink-3);border-bottom:2px solid transparent}
.tmode button.on{color:var(--ink);border-bottom-color:var(--green)}
.tseg{display:flex;gap:5px;margin-bottom:14px}
.tseg button{padding:5px 11px;border-radius:0;font-size:12px;color:var(--ink-3);border:1px solid transparent}
.tseg button.on{background:var(--green);color:#04150b;font-weight:600}
.tseg button:not(.on):hover{border-color:var(--line-2);color:var(--ink-2)}
.taskpick{display:block;margin:-4px 0 12px}
.taskpick .eyebrow{display:block;margin-bottom:5px}
/* Only what makes this one different: it fills its column and sits tighter
   than a field in a form. Everything else -- the edge, the fill, the square
   corner -- comes from the shared rule, so a hairline border here no longer
   sits beside two-pixel ones everywhere else. */
.taskpick select{ width:100%;padding:8px 10px;font-size:13px }
.dial{width:172px;height:172px;margin:0 auto 6px;position:relative}
.dial svg{position:absolute;inset:0;transform:rotate(-90deg)}
.dial .lab{position:absolute;inset:0;display:grid;place-content:center;text-align:center}
.dial .lab .t{font-family:var(--fm);font-size:33px;font-weight:500;font-variant-numeric:tabular-nums;letter-spacing:.02em}
.dial .lab .m{font-size:12px;color:var(--ink-3);margin-top:2px}
.pips{display:flex;gap:6px;justify-content:center;margin:8px 0 10px}
.pip{width:6px;height:6px;border-radius:0;background:#1d2836}
.pip.on{background:var(--green)}
.sesline{text-align:center;font-size:12px;color:var(--ink-2);margin-bottom:12px}
.trow{display:flex;gap:9px}
.trow .big{flex:1 1 auto}
.iconbtn{
  flex:0 0 auto;width:44px;border-radius:0;border:1px solid var(--line);
  background:var(--panel-2);color:var(--ink-2);font-size:16px;
}
.iconbtn:hover{background:var(--panel-3);color:var(--ink)}
.todo{right:22px;top:20px;width:284px;border:2px solid var(--line-2);border-radius:0;background:rgba(9,13,19,.9);overflow:hidden;box-shadow:var(--lift-lg)}
.todo .th{display:flex;align-items:center;gap:8px;padding:11px 12px;border-bottom:1px solid var(--line)}
.todo .th .lb{font-weight:600;font-size:14px;flex:1 1 auto}
.todo .tb{padding:10px 12px;display:flex;flex-direction:column;gap:8px;max-height:230px;overflow-y:auto}
.todo .none{font-size:13px;color:var(--ink-3);padding:6px 2px}
.bubble{
  position:absolute;z-index:11;max-width:224px;padding:10px 13px;border-radius:0;
  background:#f4f7fb;color:#0e1620;font-size:13px;font-weight:500;
  box-shadow:var(--lift);
}
.bubble::after{content:"";position:absolute;left:26px;bottom:-8px;border:9px solid transparent;border-top-color:#f4f7fb;border-bottom:0}
.dockbar{
  position:absolute;left:0;right:0;bottom:0;z-index:13;height:var(--dock);
  display:flex;align-items:center;justify-content:center;gap:9px;flex-wrap:wrap;
  padding:0 14px;background:linear-gradient(0deg,rgba(5,7,10,.92),rgba(5,7,10,0));
}
/* The music list, sitting on the dock rather than in a modal: choosing a
   piece is a two-second decision and a dialog is too much ceremony for it. */
.mpick{
  position:absolute;left:50%;transform:translateX(-50%);bottom:calc(var(--dock) + 10px);z-index:20;
  min-width:232px;max-height:min(52vh,420px);overflow-y:auto;overscroll-behavior:contain;
  padding:10px;border:1px solid var(--line-2);border-radius:0;
  background:rgba(9,13,19,.94);box-shadow:var(--lift-lg);
  display:flex;flex-direction:column;gap:4px;
}
/* A room holds six songs and two arrangements, so the heading has to stay put
   while the rest of it scrolls. */
.mpick .eyebrow{position:sticky;top:-10px;background:rgba(9,13,19,.97);padding-top:8px;z-index:1}
.mpick .eyebrow{margin:0 4px 6px}
.mrow{display:block;width:100%;text-align:left;padding:7px 9px;border-radius:0;border:1px solid transparent;background:none;color:var(--ink-2)}
.mrow:hover{background:var(--panel-3)}
.mrow.on{border-color:var(--amber);background:rgba(255,180,84,.10);color:var(--ink)}
.mrow .mt{font-size:13px;font-weight:600}
.mrow .ms{font-size:11px;color:var(--ink-3);margin-top:1px}
/* Scoped under .mpick because .locked already means something on a shop card. */
.mpick .mrow .mt{display:flex;align-items:baseline;gap:8px;justify-content:space-between}
.mpick .mrow.locked .mt{color:var(--ink-3);font-weight:500}
.mpick .mrow.locked:hover{background:rgba(255,180,84,.08)}
.mpick .mrow .mprice{font-family:var(--fm);font-size:11px;color:var(--amber);white-space:nowrap;flex:0 0 auto}
.mpick .mrow .mprice.short{color:var(--ink-3)}
.mpick .mrow:disabled{opacity:.5;cursor:not-allowed}
.mpick .mrow:disabled:hover{background:none}
/* A locked row is a listen button beside a buy button, so it needs a container. */
.mpick .mrowwrap{display:flex;align-items:stretch;gap:4px}
.mpick .mrowwrap .mrow{flex:1 1 auto}
.mpick .mhear{
  flex:0 0 auto;width:30px;border-radius:0;border:1px solid var(--line-2);
  background:var(--panel-3);color:var(--ink-2);font-size:11px;
}
.mpick .mhear:hover{border-color:var(--amber);color:var(--amber)}
.mpick .mhear.on{background:var(--amber);border-color:var(--amber);color:#2a1a02}
/* Supporting text.

   Eight places wrote their own colour and size straight onto the element from
   JavaScript, which is how the display-name field kept its rounded corners
   through a whole reskin: an inline rule is a rule the stylesheet cannot
   reach. These are the same three or four kinds of text, named. */
.note{margin:4px 0 0;font-size:13px;line-height:1.5;color:var(--ink-3)}
.note.spaced{margin-top:16px}
.note.aside{margin-top:14px;font-style:italic}
/* A journal entry keeps its own line breaks; it is prose someone typed. */
.entry{margin:6px 0 0;font-size:14px;color:var(--ink-2);white-space:pre-wrap}
/* The caption under a progress bar: two ends of one line, in digits. */
.barfoot{display:flex;justify-content:space-between;margin-top:6px;
  font-family:var(--fm);font-size:11px;color:var(--ink-3)}
.modal .mh .aside{font-size:13px;color:var(--ink-2);text-align:right}
/* The title absorbs the slack so everything after it is pinned to the right
   and stops moving. "July 2026" is 85px wide and "September 2026" is 148px, so
   in a plain flex row the arrows jumped 63px between months -- you would press
   next and the button would walk out from under the pointer.

   flex-grow does the work; the min-width only matters once the pane is narrow
   enough that growing is not an option, and it is in em so it follows the font
   size rather than pinning it to one. tabular-nums keeps the year steady too:
   1 and 9 are not the same width in Outfit. */
.calbar h2{font-size:20px;margin-right:8px;flex:1 1 auto;min-width:7.6em;
  font-variant-numeric:tabular-nums}

.hint{position:absolute;left:16px;bottom:6px;z-index:13;font-size:11px;color:#4a5a6b}
.toasts{position:fixed;right:18px;bottom:18px;z-index:80;display:flex;flex-direction:column;gap:9px;align-items:flex-end}
.toast{
  display:flex;align-items:center;gap:10px;padding:11px 14px;border-radius:0;
  border:1px solid var(--line-2);background:var(--panel-2);font-size:14px;
  box-shadow:var(--lift-lg);animation:pop .22s ease both;
}
.toast b{font-family:var(--fm);font-weight:500}
.toast.xp{border-color:var(--violet-2)} .toast.coin{border-color:#7a5a1e} .toast.up{border-color:var(--green-2)}
.toast.leg{border-color:#ffd24a;box-shadow:0 0 22px -8px #ffd24a}
@keyframes pop{from{opacity:0;transform:translateY(8px) scale(.97)}to{opacity:1;transform:none}}
@keyframes flash{0%,100%{opacity:.35}50%{opacity:1}}
.livedot{width:7px;height:7px;border-radius:0;background:var(--green);animation:flash 1.6s infinite}

/* ---------- charts ---------- */
.chart{width:100%;overflow-x:auto;margin-top:12px}
.chart svg{display:block}
.axl{font-family:var(--fm);font-size:10px;fill:var(--ink-3)}
.gl{stroke:var(--line);stroke-width:1;opacity:.55}
.bar{fill:var(--green-2)}
.bar.hi{fill:var(--green)}
.tt{
  position:fixed;z-index:90;pointer-events:none;padding:7px 10px;border-radius:0;
  border:1px solid var(--line-2);background:#0c131b;font-size:12px;white-space:nowrap;
  box-shadow:0 14px 30px -14px #000;opacity:0;transition:opacity .1s;
}
.tt b{font-family:var(--fm);font-weight:500}
.legend{display:flex;gap:16px;flex-wrap:wrap;font-size:12px;color:var(--ink-2);margin-top:12px}
.legend i{display:inline-block;width:10px;height:10px;border-radius:0;margin-right:6px;vertical-align:-1px}
.legend i.no{background:#131c27;border:1px solid var(--line)}
.legend i.yes{background:var(--green)}

@media (max-width:900px){
  .lobby .side{position:absolute;z-index:16;height:100%;background:#080d13}
  .mobstart{display:block}
  .collapse{width:28px;height:64px;font-size:15px}
  .lobby.open .collapse{left:268px;border-radius:0}
  .pane{padding-bottom:86px}
  .lobby:not(.open) .side{margin-left:-269px}
  .avwrap{grid-template-columns:1fr}
  .pane{padding:16px 14px 32px}
  .panehd h2{font-size:19px}
  .timer{left:10px;right:10px;top:10px;width:auto;max-width:none}
  .dial{width:140px;height:140px}
  .dial .lab .t{font-size:28px}
  .todo{
    left:10px;right:10px;top:auto;bottom:calc(var(--dock) + 8px);
    width:auto;max-height:34vh;display:none;
  }
  .todo.open{display:block}
  .todo .tb{max-height:24vh}
  .hint{display:none}
  .dockbar{justify-content:flex-start;overflow-x:auto;flex-wrap:nowrap;scrollbar-width:none}
  .dockbar::-webkit-scrollbar{display:none}
  .list{flex:0 0 82vw}
  .split{flex-direction:column;min-height:0}
  .catlist{flex:0 0 auto;border-right:0;border-bottom:1px solid var(--line);flex-direction:row;overflow-x:auto}
  .catlist button{white-space:nowrap}
  .cell{min-height:64px}
  .modal{max-height:92vh}
}
@media (max-width:700px){
  .topbar{gap:9px;padding:9px 10px}
  .brand .wordmark{font-size:12px}
  .brand canvas{width:26px;height:26px}
  .xptext,.who,#btnJournal{display:none}
  .xpbar{width:74px}
  .chip{padding:4px 8px;font-size:12px}
}
@media (prefers-reduced-motion:reduce){
  *{animation-duration:.001ms !important;transition-duration:.001ms !important}
}

/* ---------- sign-in gate (web app only) ---------- */
.gate{
  position:fixed;inset:0;z-index:70;display:grid;place-items:center;padding:24px;
  /* Translucent, so the pixel field on #bgfx behind it keeps drifting. The
     gradient is still doing its job -- darkening the edges so the card is the
     brightest thing on screen -- it just no longer paints the animation out. */
  background:radial-gradient(120% 90% at 50% 0%, rgba(15,26,36,.38) 0%, rgba(5,7,10,.66) 62%);
}
/* The gate no longer paints the app out, so the app has to stand down while it
   is up -- otherwise the board reads straight through the backdrop. Keyed off
   the gate's own attribute rather than a class someone has to remember to
   toggle: `hidden` is set in four places and this follows all of them. */
#gate:not([hidden]) ~ #stage{visibility:hidden}

.gatecard{
  width:100%;max-width:440px;text-align:center;
  border:2px solid var(--line-2);border-radius:0;background:rgba(13,19,27,.86);
  padding:30px 28px 24px;box-shadow:0 40px 90px -40px #000;
}
.gatecard canvas{width:64px;height:64px;margin:0 auto 12px;display:block}
.gatecard h1{font-family:var(--fd);font-size:19px;letter-spacing:.02em;margin-bottom:12px}
.gatecard .lede{margin:0 0 20px;color:var(--ink-2);font-size:14px}
.gatecard .big{display:block;text-decoration:none;box-sizing:border-box}
.gatecard .fine{margin:12px 0 0;font-size:12px;color:var(--ink-3);line-height:1.5}
.gatecard form{display:flex;flex-direction:column;gap:10px;margin:0 0 4px}
.gatecard label{font-family:var(--fd);font-size:9px;letter-spacing:.06em;color:var(--ink-3);text-transform:uppercase;text-align:left}
.gatecard input[type=email],.gatecard input[type=password]{width:100%;padding:11px 12px;border-radius:0;background:var(--panel-2);border:1px solid var(--line);color:var(--ink)}
.gatecard .err{margin:0 0 10px;padding:9px 11px;border-radius:0;border:1px solid var(--rose);color:var(--rose);font-size:13px;text-align:left}
.gatecard .remember{display:flex;align-items:center;gap:8px;font-size:13px;color:var(--ink-2);text-transform:none;letter-spacing:0;font-family:var(--fb)}
.gatecard .orline{margin:14px 0 12px;font-size:12px;color:var(--ink-3)}
.linkish{
  margin-top:16px;color:var(--ink-2);font-size:13px;
  border-bottom:1px solid var(--line-2);padding-bottom:1px;
}
.linkish:hover{color:var(--ink);border-bottom-color:var(--green)}

/* ---------- sync indicator ---------- */
.syncdot{
  display:inline-block;width:7px;height:7px;border-radius:0;margin-right:6px;
  vertical-align:1px;background:var(--ink-3);
}
.syncdot.on{background:var(--green);box-shadow:0 0 6px rgba(53,224,122,.7)}
.syncdot.warn{background:var(--amber)}
.syncdot.off{background:var(--ink-3)}

/* ---------- popover hint line ---------- */
.popover .phint{display:block;font-size:11px;color:var(--ink-3);margin-top:2px}

/* ---------- tracker board reuse ---------- */
.board .list .drop{gap:8px}
/* One group that is a list, not a column: fill the width and let the cards
   flow, instead of stranding a 274px column beside empty space. */
.board.wide .list{flex:1 1 auto;min-width:0}
.board.wide .drop{display:grid;grid-template-columns:repeat(auto-fill,minmax(268px,1fr))}
.mrpipe{display:flex;align-items:center;gap:8px;font-size:13px}
.mrpipe .dot{width:9px;height:9px;border-radius:0;flex:0 0 auto}
.mrpipe a{color:var(--ink-2)}
.mrnote{border:1px solid var(--line);border-radius:0;background:var(--panel-2);padding:9px 11px;margin:0 0 8px}
.mrnote.done{opacity:.6}
.mrnote-h{display:flex;align-items:center;gap:8px;margin-bottom:5px;font-size:13px}
.mrnote-b{font-size:13px;color:var(--ink-2);white-space:pre-wrap;word-break:break-word}
.cmdlog{max-height:46vh;overflow-y:auto;border:1px solid var(--line);border-radius:0;background:var(--bg-2);padding:10px 12px;margin:0 0 10px}
.cmdline{display:flex;gap:8px;margin:0 0 7px;font-size:13px;line-height:1.5}
.cmdwho{font-family:var(--fd);font-size:8px;letter-spacing:.06em;text-transform:uppercase;color:var(--ink-3);padding-top:5px;flex:0 0 26px}
.cmdtext{white-space:pre-wrap;word-break:break-word;min-width:0}
.cmdline.say .cmdtext{color:var(--ink)}
.cmdline.you .cmdtext{color:var(--green)}
.cmdline.tool .cmdtext{font-family:var(--fm);font-size:12px;color:var(--ink-3)}
.cmdline.note .cmdtext{color:var(--ink-3);font-size:12px}
.cmdline.err .cmdtext{color:var(--rose)}
/* Is it still going? The transcript answers eventually; this answers now. */
.cmdstatus{display:flex;align-items:center;gap:7px;margin:0 0 9px;font-size:12px;color:var(--ink-3)}
.cmdstatus .dot{width:8px;height:8px;border-radius:0;background:var(--amber);flex:0 0 auto}
.cmdstatus.done .dot{background:var(--green)}
.cmdstatus.err .dot{background:var(--rose)}
.cmdinput{display:flex;gap:8px;align-items:center}
.cmdinput input{flex:1 1 auto;min-width:0;width:auto;padding:10px 12px;border-radius:0;background:var(--panel-2);border:1px solid var(--line);color:var(--ink)}
.cmdinput input:disabled{opacity:.5}
/* Not .big — that one is a full-width sidebar block and it crushes the field. */
.cmdbtn{flex:0 0 auto;width:auto;padding:10px 15px;border-radius:0;font-size:13px;border:1px solid var(--line-2);background:var(--panel-3);color:var(--ink)}
.cmdbtn:hover:not(:disabled){background:var(--panel-2)}
.cmdbtn.go{background:var(--green);border-color:var(--green);color:#04150b;font-weight:600}
.cmdbtn.go:hover:not(:disabled){filter:brightness(1.07)}
.cmdbtn:disabled{opacity:.4;cursor:not-allowed}

/* Releases: the operator's page, and the note players get when one lands. */
.relnew{display:flex;flex-direction:column;gap:6px;margin:8px 0 4px}
.relnewitem{background:var(--card-2,rgba(255,255,255,.04));border-radius:0;padding:8px 11px;font-size:14px}
.relbar{display:flex;gap:8px;align-items:center;flex-wrap:wrap;margin-bottom:12px}
.relbar .big{width:auto;padding:8px 14px;font-size:13px}
.relpick{flex:0 0 auto;min-width:170px}
.releditor .eyebrow{display:block;margin:14px 0 6px}
.relname,.relnotes{width:100%;box-sizing:border-box}
.relnotes{min-height:60px;resize:vertical}
.rellive{display:flex;gap:8px;align-items:center;margin-top:12px;font-size:14px;color:var(--ink-2)}
.relgrid{display:grid;grid-template-columns:repeat(auto-fill,minmax(160px,1fr));gap:4px 10px}
.relbox{display:flex;gap:7px;align-items:center;font-size:13px;color:var(--ink-2)}

/* The operator's price table. */
.pricetable{display:flex;flex-direction:column;gap:4px;margin-bottom:6px}
.pricerow{display:flex;align-items:center;gap:8px}
.pricename{flex:1 1 auto;font-size:13px;color:var(--ink-2);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.relprice{flex:0 0 auto;padding:5px 8px;font-size:12px;text-align:right}
/* A number the operator has taken over reads differently from one still shipped. */
.relprice.changed{border-color:var(--green-2,#2f7d4f);color:var(--green,#35e07a)}

/* Something ticked off the day's list. It stays on the calendar rather than
   disappearing: the server pays for it once and needs the record to know it
   already has, and seeing what you got through is worth more than a tidy grid. */
.dayrow.done span { opacity: .5; text-decoration: line-through; }
.ev.done { opacity: .5; text-decoration: line-through; }

/* Invitations, in the operator panel.

   The issued link is the one thing on this panel that has to survive being
   read aloud, pasted into a chat, or copied by hand, so it is framed as a
   ticket -- a hard-edged object with its own label -- rather than as another
   field. The label goes pixel because it is three words; the link stays in DM
   Mono because it is data, and a pixel face would make an o and a 0 the same
   shape in a token that only works if it is exact. */
.invout:empty{display:none}
.invout{margin-top:14px}
.invticket{border:2px solid var(--line-2);background:#070b10;padding:10px 11px;
  box-shadow:var(--lift)}
.invticket.sent{border-color:var(--green-2)}
.invhead{font-family:var(--fd);font-size:8px;line-height:1.7;color:var(--ink-2);
  display:flex;justify-content:space-between;gap:10px;margin-bottom:8px}
.invticket.sent .invhead{color:var(--green)}
.invnote{font-size:12px;color:var(--ink-3);margin:6px 0 0}
.invnote.warn{color:var(--amber)}
.invrow{display:flex;gap:8px;align-items:stretch}
/* .relname carries width:100%, and .big carries its own; inside a flex row
   both fight and the link box loses. Say which one stretches. */
.invrow .relname{flex:1 1 auto;min-width:0;width:auto;
  font-size:12px;font-family:var(--fm,ui-monospace,monospace)}
.invrow .big{flex:0 0 auto;width:auto;padding:0 13px;font-size:8px}
/* Labels between stacked fields need air above them, not only below. */
.invfield{margin-top:12px}
/* The roll is a list of records, so it is ruled like one. */
.invlist{border:2px solid var(--line);background:var(--panel-2)}
.invperson{display:flex;gap:10px;align-items:center;justify-content:space-between;
  font-size:13px;color:var(--ink-2);padding:8px 10px}
.invperson+.invperson{border-top:2px solid var(--line)}
.invwho{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.invlist .chip{font-family:var(--fd);font-size:7px;box-shadow:none;flex:0 0 auto}
.chip.wait{background:#3a3418;color:#e2c85a;border-color:#5a4a1c}
.chip.stale{background:#3d2626;color:#e08a8a;border-color:#5a2a2a}

/* An item another version introduced. Not disabled any more -- ticking it here
   records that this version improved it -- so it needs to look different from
   both an unticked new item and a ticked one. */
.relbox.improving{color:var(--amber)}
.relbox.improving span::after{content:" ↑";opacity:.7}
