
:root{
  /* surfaces, darkest first */
  --ground:#0e1014;
  --surface:#161920;
  --surface-2:#1d212a;
  --surface-3:#242935;
  --line:#2a3040;
  --line-soft:#212632;

  /* text */
  --text:#e9ebf1;
  --text-dim:#aab3c5;
  --muted:#79839a;
  --faint:#5a6377;

  /* one accent, the gold of the insignia */
  --accent:#d4a850;
  --accent-hi:#f0c674;
  --accent-dim:#8a6f2e;
  --accent-bg:rgba(212,168,80,.13);
  --accent-line:rgba(212,168,80,.38);
  --on-accent:#1a1408;

  /* states */
  --ok:#54b880;--ok-bg:rgba(84,184,128,.13);--ok-line:rgba(84,184,128,.4);
  --warn:#e0ac4c;--warn-bg:rgba(224,172,76,.13);--warn-line:rgba(224,172,76,.4);
  --bad:#e2606a;--bad-bg:rgba(226,96,106,.13);--bad-line:rgba(226,96,106,.4);

  /* geometry
     Square corners and no shadow, on purpose. The artwork is pixel art with
     hard edges; a rounded, floating surface fights it, and a flat bordered
     panel is what the badges sit on in the game itself. The two variables stay
     rather than being deleted so the whole surface language is still one
     switch. */
  --step:4px;
  --radius:0;
  --radius-sm:0;
  --ctl:32px;
  --ctl-sm:27px;
  --shadow:none;
  --mono:ui-monospace,SFMono-Regular,Consolas,"Liberation Mono",monospace;
}

*{box-sizing:border-box}
html{-webkit-text-size-adjust:100%}
body{
  margin:0;
  background:var(--ground);
  color:var(--text);
  font:14px/1.55 -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;
  font-variant-numeric:tabular-nums;
  -webkit-font-smoothing:antialiased;
}
a{color:var(--accent);text-decoration:none}
a:hover{color:var(--accent-hi);text-decoration:underline;text-underline-offset:2px}
:focus-visible{outline:2px solid var(--accent);outline-offset:2px;border-radius:var(--radius-sm)}
img{border-style:none}
hr{border:0;border-top:1px solid var(--line);margin:20px 0}

/* ---- type scale ---- */
h1{margin:0 0 20px;font-size:22px;line-height:1.25;font-weight:650;letter-spacing:-.012em;
   display:flex;align-items:center;justify-content:center;text-align:center;gap:10px;flex-wrap:wrap}
h2{margin:26px 0 12px;font-size:15px;font-weight:650;letter-spacing:-.005em;
   padding-bottom:8px;border-bottom:1px solid var(--line)}
h3{margin:20px 0 8px;font-size:13px;font-weight:650;color:var(--text-dim)}
p{margin:0 0 14px}
p.sub{margin:-6px 0 18px;color:var(--muted);font-size:13px;line-height:1.6}
small,.small{font-size:12px}
.muted{color:var(--muted)}
.mono{font-family:var(--mono);font-size:12px}
.nowrap{white-space:nowrap}

/* ---- tables ----
   Separate borders, not collapsed: a collapsed table cannot keep a rounded
   corner, and every table here is a card. */
.scroll{overflow-x:auto;margin:0 0 18px;border-radius:var(--radius)}
.scroll>table{margin-bottom:0}
table{
  width:100%;margin:0 0 18px;font-size:13px;
  border-collapse:separate;border-spacing:0;
  background:var(--surface);
  border:1px solid var(--line);border-radius:var(--radius);
  box-shadow:var(--shadow);
  overflow:hidden;
}
/* A table's heading is a separate bar above it with a gap, not a <caption>
   welded to the header row: joined, the two read as one block and the table
   loses its own top edge. It is also a plain div, which sidesteps the caption
   trap - a caption made into a flex box leaves the table's box model and the
   browser renders it after the header row instead of above it. */
.tablehead{
  display:flex;align-items:center;gap:10px;margin:0 0 10px;padding:10px 14px;
  background:var(--surface-2);border:1px solid var(--line);
  font-size:13px;font-weight:650;color:var(--text);
}
.tablehead .more{margin-left:auto;font-weight:400;font-size:12px}

th,td{padding:9px 14px;text-align:left;vertical-align:middle;border-bottom:1px solid var(--line-soft)}
thead th{
  background:var(--surface-2);color:var(--muted);
  font-size:11px;font-weight:650;letter-spacing:.06em;text-transform:uppercase;
  white-space:nowrap;border-bottom:1px solid var(--line);
}
tbody th{
  color:var(--text-dim);font-weight:400;background:var(--surface-2);
  white-space:nowrap;width:220px;
}
tbody tr:last-child>*{border-bottom:0}
tbody tr:hover>td{background:var(--surface-3)}
tfoot td{background:var(--surface-2);font-weight:650;border-bottom:0;border-top:1px solid var(--line)}

/* Numeric columns line up only when the header follows the cell. */
.num,td.n,th.n{text-align:right;font-variant-numeric:tabular-nums;white-space:nowrap}
th.num{text-align:right}
td.act,th.act{text-align:right;white-space:nowrap;width:1%}
td.act>*{vertical-align:middle}
td.act form{display:inline}
td.act form+form,td.act form+button,td.act button+button,td.act a+form,td.act a+a{margin-left:8px}
/* A table with many columns scrolls rather than squeezing its text; without a
   min-width, width:100% wins and every cell wraps to one character. */
table.wide{min-width:1080px}
td.empty,tbody td[colspan]{color:var(--muted)}

/* ---- badges: rank insignia and clan emblems ----
   The artwork is 32px and 64px pixel art. Scaling it smoothly turns a crisp
   insignia into a smudge, so every one of them is nearest-neighbour. */
.badge{
  display:inline-block;vertical-align:middle;flex:none;
  image-rendering:pixelated;border-radius:var(--radius-sm);
  background:var(--surface-3);
}
.badge.sm{width:24px;height:24px}
.badge.md{width:32px;height:32px}
.badge.lg{width:48px;height:48px}
.badge.xl{width:64px;height:64px}
.emblem{border:1px solid var(--line)}
/* A name with its badge: one flex row so the two never drift apart. */
.who-cell{display:flex;align-items:center;gap:9px;white-space:nowrap}

/* ---- tags ---- */
.tag{
  display:inline-block;padding:1px 9px;
  border:1px solid var(--line);background:var(--surface-3);color:var(--text-dim);
  font-size:11px;line-height:18px;font-weight:650;white-space:nowrap;
}
.tag+.tag{margin-left:4px}
.tag.on{border-color:var(--ok-line);background:var(--ok-bg);color:var(--ok)}
.tag.off{border-color:var(--line);background:var(--surface-2);color:var(--muted)}
.tag.edit,.tag.warn{border-color:var(--warn-line);background:var(--warn-bg);color:var(--warn)}
.tag.bad{border-color:var(--bad-line);background:var(--bad-bg);color:var(--bad)}
.tag.gold{border-color:var(--accent-line);background:var(--accent-bg);color:var(--accent)}

/* ---- controls ---- */
input,select,textarea,button{font:inherit;font-size:13px;color:var(--text);
  background:var(--surface-3);border:1px solid var(--line);border-radius:var(--radius-sm)}
input,select,button{height:var(--ctl);padding:0 10px}
select{padding-right:6px}
input:hover,select:hover,textarea:hover{border-color:var(--faint)}
input:focus,select:focus,textarea:focus{outline:none;border-color:var(--accent-dim);
  box-shadow:0 0 0 3px var(--accent-bg)}
textarea{width:100%;padding:8px 10px;resize:vertical;font-family:var(--mono);font-size:12px;line-height:1.6}
input[type=number],input.n{text-align:right;font-family:var(--mono);width:120px}
input[type=checkbox],input[type=radio]{height:auto;width:15px;margin:0;vertical-align:middle;accent-color:var(--accent)}
input.wide{width:100%;min-width:220px}
input.narrow{width:76px}
input[readonly]{background:var(--surface-2);color:var(--muted)}
input[disabled],select[disabled],button[disabled]{opacity:.5;cursor:not-allowed}
::placeholder{color:var(--faint)}
td input,td select,td button,.bar input,.bar select,.bar button{height:var(--ctl-sm)}

button{cursor:pointer;padding:0 14px;font-weight:650;color:var(--text-dim);white-space:nowrap}
button:hover{background:var(--surface-2);border-color:var(--faint);color:var(--text)}
button.go{background:var(--accent);border-color:var(--accent);color:var(--on-accent)}
button.go:hover{background:var(--accent-hi);border-color:var(--accent-hi);color:var(--on-accent)}
button.danger{color:var(--bad);border-color:var(--bad-line)}
button.danger:hover{background:var(--bad);border-color:var(--bad);color:#fff}
button.quiet{background:none;border-color:transparent;color:var(--muted)}
button.quiet:hover{background:var(--surface-3);border-color:var(--line);color:var(--text)}
form.inline{display:inline}

/* ---- forms: a labelled stack, one rhythm everywhere ---- */
.card{
  background:var(--surface);border:1px solid var(--line);border-radius:var(--radius);
  box-shadow:var(--shadow);padding:20px;margin:0 0 18px;
}
.field{display:block;margin:0 0 14px}
.field:last-of-type{margin-bottom:18px}
.field>span,.card label{display:block;margin:0 0 6px;
  font-size:11px;font-weight:650;letter-spacing:.06em;text-transform:uppercase;color:var(--muted)}
.field input,.field select{width:100%}
.field .hint{margin:6px 0 0;font-size:12px;font-weight:400;letter-spacing:0;text-transform:none;color:var(--muted)}
/* A button is as wide as its label. A full-bleed button in a narrow card reads
   as a banner, not as a control. */
.card button{min-width:132px}

/* ---- messages ---- */
.msg,.err,.warn,.ok{
  padding:11px 14px;margin:0 0 18px;border-radius:var(--radius);
  border:1px solid var(--line);font-size:13px;background:var(--surface);
}
.msg,.ok{border-color:var(--ok-line);background:var(--ok-bg);color:var(--ok)}
.err{border-color:var(--bad-line);background:var(--bad-bg);color:var(--bad)}
.warn{border-color:var(--warn-line);background:var(--warn-bg);color:var(--warn)}

/* ---- filter strip ---- */
.bar{
  display:flex;flex-wrap:wrap;align-items:center;gap:10px;margin:0 0 18px;
  padding:11px 14px;border:1px solid var(--line);border-radius:var(--radius);
  background:var(--surface);box-shadow:var(--shadow);
}
.bar form{display:flex;flex-wrap:wrap;align-items:center;gap:10px;margin:0}
.bar label{display:inline-flex;align-items:center;gap:7px;font-size:12px;color:var(--muted)}
.bar .grow{flex:1 1 auto}

/* ---- fact list ---- */
dl.facts{
  display:grid;grid-template-columns:220px 1fr;margin:0 0 18px;background:var(--surface);
  border:1px solid var(--line);border-radius:var(--radius);overflow:hidden;box-shadow:var(--shadow);
}
dl.facts dt{padding:9px 14px;border-bottom:1px solid var(--line-soft);background:var(--surface-2);
  font-size:12px;color:var(--muted)}
dl.facts dd{margin:0;padding:9px 14px;border-bottom:1px solid var(--line-soft);
  font-size:13px;word-break:break-word}
dl.facts dd.mono{font-family:var(--mono);font-size:12px;word-break:break-all}
dl.facts dt:last-of-type,dl.facts dd:last-of-type{border-bottom:0}

/* ---- containers ---- */
fieldset{border:1px solid var(--line);border-radius:var(--radius);margin:0 0 18px;padding:16px 18px 6px;
  background:var(--surface);box-shadow:var(--shadow)}
fieldset .bar,fieldset table,fieldset .card{box-shadow:none}
legend{font-size:11px;font-weight:650;letter-spacing:.08em;text-transform:uppercase;color:var(--muted);padding:0 8px}
details{margin:0 0 18px;padding:12px 16px;background:var(--surface);border:1px solid var(--line);border-radius:var(--radius)}
details[open]{box-shadow:var(--shadow)}
summary{cursor:pointer;font-size:12px;font-weight:650;color:var(--text-dim)}
summary:hover{color:var(--accent)}
details>*:not(summary){margin-top:14px}
pre{margin:0 0 18px;padding:12px 14px;border:1px solid var(--line);border-radius:var(--radius);
  background:var(--surface);font-size:12px;overflow-x:auto;white-space:pre-wrap;font-family:var(--mono);color:var(--text-dim)}
code{font-family:var(--mono);font-size:12px;color:var(--text-dim)}

/* ---- pager ---- */
.pager,.pages{display:flex;align-items:center;gap:16px;margin:0 0 22px;font-size:13px}
.pager span,.pages span{color:var(--muted)}
.pager .muted,.pages .range{margin-left:auto;color:var(--faint);font-size:12px}
.pages .range{margin-left:0;font-family:var(--mono)}
.pages .off,.pager .off{color:var(--faint)}

/* ---- progress bar ----
   The width is a class, not an inline style: style-src 'self' forbids the
   latter, and a twenty-step ladder is enough resolution for a bar. */
.meter{display:block;height:6px;background:var(--surface-3);overflow:hidden;min-width:120px}
.meter>i{display:block;height:100%;background:var(--accent)}
td.barcell{width:180px}
.bar-fill{display:block;height:8px;background:var(--accent);min-width:2px}
.w0{width:0%}.w5{width:5%}.w10{width:10%}.w15{width:15%}.w20{width:20%}
.w25{width:25%}.w30{width:30%}.w35{width:35%}.w40{width:40%}.w45{width:45%}
.w50{width:50%}.w55{width:55%}.w60{width:60%}.w65{width:65%}.w70{width:70%}
.w75{width:75%}.w80{width:80%}.w85{width:85%}.w90{width:90%}.w95{width:95%}.w100{width:100%}

/* ---- centred column ----
   A page that is one form or one action is a column in the middle of the
   viewport, not a card pinned to the left margin of a 1200px grid. */
.narrowpage{max-width:420px;margin:0 auto}
.midpage{max-width:960px;margin:0 auto}
.narrowpage .card,.narrowpage form.card{max-width:none;width:100%}
.narrowpage p,.narrowpage .sub{text-align:center}
/* A centred card wants its submit centred too; left-aligned under a centred
   form it reads as a stray control. */
.narrowpage .card button{display:block;margin-left:auto;margin-right:auto}

/* ---- action row ---- */
.actions{display:flex;flex-wrap:wrap;align-items:center;gap:8px;margin:0 0 18px}
.actions form{display:inline}

/* ---- layout ---- */
.wrap{display:flex;align-items:stretch;min-height:100vh}
aside{width:250px;flex:0 0 250px;background:var(--surface);border-right:1px solid var(--line);
  padding-bottom:32px;display:flex;flex-direction:column}
main{flex:1 1 auto;min-width:0;padding:24px 28px 64px;background:var(--ground)}

/* ---- side menu ----
   Two levels: a rail of sections, then the open section's groups. A leaf lives
   in exactly one section, which is what mechanically prevents the same data
   being reachable from two menus. */
aside .brand{
  display:flex;align-items:center;gap:9px;padding:16px 18px;
  color:var(--accent);font-weight:750;letter-spacing:.11em;font-size:13px;
  border-bottom:1px solid var(--line);
}
aside .brand:hover{color:var(--accent-hi);text-decoration:none;background:var(--surface-2)}
.rail{display:flex;flex-direction:column;padding:8px 0;border-bottom:1px solid var(--line)}
.rail a{
  padding:8px 18px;color:var(--text-dim);border-left:3px solid transparent;
  font-weight:650;font-size:13px;
}
.rail a:hover{background:var(--surface-2);color:var(--text);text-decoration:none}
.rail a.on{border-left-color:var(--accent);background:var(--accent-bg);color:var(--accent)}
aside h3{margin:0;padding:16px 18px 5px;font-size:10px;letter-spacing:.13em;
  text-transform:uppercase;color:var(--faint);font-weight:650;border-bottom:0}
aside ul{list-style:none;margin:0;padding:0}
aside li a{display:block;padding:6px 18px 6px 21px;color:var(--muted);
  border-left:3px solid transparent;font-size:13px}
aside li a:hover{background:var(--surface-2);color:var(--text);text-decoration:none}
aside li a.on{border-left-color:var(--accent);background:var(--accent-bg);color:var(--accent);font-weight:650}
.who{display:flex;align-items:center;gap:9px;margin-top:auto;padding:14px 18px 0;
  border-top:1px solid var(--line)}
.who span{flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;
  white-space:nowrap;color:var(--muted);font-size:12px}
.who form{margin:0}

/* ---- page head ----
   The title and the actions that belong to the page as a whole share one row,
   so a page-level control is never mistaken for a row-level one. */
.head{display:flex;align-items:flex-start;gap:16px;flex-wrap:wrap;margin:0 0 18px}
.head .tools{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
main>h1{margin:8px 0 20px}
/* A page title inside the .head row keeps its left edge: a page-level action
   sits beside it there, and a centred title would push the two apart. */
.head h1{margin:0;flex:1 1 auto;min-width:0;justify-content:flex-start;text-align:left}

/* ---- crumbs ---- */
.crumbs{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin:-6px 0 16px;
  font-size:12px;color:var(--muted)}
.crumbs a{color:var(--text-dim)}
.crumbs a:hover{color:var(--accent)}

/* ---- overview cards ----
   The numbers an operator opens the panel to see, before any table. */
.cards{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:12px;margin:0 0 22px}
.cardlet{display:block;padding:14px 16px;background:var(--surface);border:1px solid var(--line);
  border-radius:var(--radius);box-shadow:var(--shadow)}
a.cardlet:hover{border-color:var(--accent-line);text-decoration:none}
.cardlet .k{display:block;font-size:11px;font-weight:650;letter-spacing:.07em;
  text-transform:uppercase;color:var(--muted);margin:0 0 6px}
.cardlet .v{display:block;font-size:22px;font-weight:650;line-height:1.1;
  letter-spacing:-.01em;color:var(--text)}
.cardlet .note{display:block;margin-top:5px;font-size:12px;color:var(--muted)}

/* ---- identity strip on a detail page ---- */
.ident{display:flex;align-items:center;gap:16px;padding:16px 18px;margin:8px 0 18px;flex-wrap:wrap;
  background:var(--surface);border:1px solid var(--line);border-radius:var(--radius);box-shadow:var(--shadow)}
.ident .grow{flex:1 1 auto;min-width:0}
.ident .name{font-size:19px;font-weight:650;letter-spacing:-.01em;line-height:1.25}
.ident .meta{margin-top:3px;color:var(--muted);font-size:12.5px}
.ident .meta a{color:var(--text-dim)}
.ident .meta a:hover{color:var(--accent)}

/* ---- permission grid ----
   One checkbox per menu leaf. The host-root ones are tinted rather than merely
   labelled: the difference between "can edit coupons" and "has a shell on the
   server" should be visible before the click, not after. */
.grants{display:grid;grid-template-columns:repeat(auto-fit,minmax(250px,1fr));
  gap:4px 16px;margin:0 0 16px}
.grant{display:flex;align-items:center;gap:8px;padding:6px 8px;
  border:1px solid transparent;font-size:12.5px}
.grant.danger{border-color:var(--warn-line);background:var(--warn-bg)}
.grant input{margin:0;flex:0 0 auto}
.grant span{min-width:0}

/* ---- login ----
   The one page without the shell. It centres on both axes so the form sits in
   the middle of the viewport rather than in the top-left corner. */
.login{display:flex;align-items:center;justify-content:center;min-height:100vh;padding:24px}
.login form{width:340px;max-width:100%;padding:26px;background:var(--surface);
  border:1px solid var(--line);border-radius:var(--radius);box-shadow:var(--shadow)}
.login h1{margin:0 0 20px;padding-bottom:14px;border-bottom:1px solid var(--line);
  justify-content:center;letter-spacing:.11em;font-size:16px;color:var(--accent)}
.login p{margin:0 0 14px}
.login p:last-child{margin-bottom:0}
.login label{display:block;font-size:11px;font-weight:650;letter-spacing:.06em;
  text-transform:uppercase;color:var(--muted)}
.login input{width:100%;margin-top:6px}
.login button{width:100%}

@media(max-width:900px){
  .wrap{display:block}
  aside{width:auto;border-right:0;border-bottom:1px solid var(--line);display:block}
  .rail{flex-direction:row;flex-wrap:wrap}
  .rail a{border-left:0;border-bottom:3px solid transparent}
  .rail a.on{border-left:0;border-bottom-color:var(--accent)}
  .who{margin-top:14px}
  dl.facts{grid-template-columns:1fr}
  main{padding:18px 16px 48px}
}

/* ---- item picker ---- */
.pick{position:relative;display:inline-block}
.pick input[type=search]{width:260px;height:var(--ctl)}
td .pick input[type=search]{width:210px}
.pick .hits{position:absolute;z-index:5;top:calc(100% + 3px);left:0;width:340px;max-height:260px;
  overflow:auto;border:1px solid var(--line);border-radius:var(--radius);
  background:var(--surface-2);box-shadow:var(--shadow)}
.pick .hits[hidden]{display:none}
.pick .hits button{display:block;width:100%;height:auto;text-align:left;border:0;
  border-bottom:1px solid var(--line-soft);border-radius:0;padding:7px 11px;
  background:var(--surface-2);font-weight:400;color:var(--text)}
.pick .hits button:hover,.pick .hits button.on{background:var(--accent-bg);color:var(--accent)}
.pick .hits button code{float:right;color:var(--muted);font-family:var(--mono);font-size:11px}
.pick .hits button small{color:var(--muted);margin-left:6px}
.pick .hits p{margin:0;padding:8px 11px;color:var(--muted);font-size:12px}
