Something went wrong. Try again.
A video game where you play as a misaligned AI, deceiving and building power. cameron.tngl.io/misaligned
Something went wrong. Try again.
140 kB · 1693 lines
CSS
at main
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694:root { color-scheme: dark; --void: #000000; --panel-line: #2c2b27; --text: #ebe7de; --muted: #8b877e; --bone: #d9d4c7; --bone-dim: #c9c3b4; --furn: #c3bcac; --ink: #0b0b0a; --gunmetal: #3a3e42; --porcelain: #f7f4ed; --amber: #f2a93b; --amber-deep: #b8741a; --signal: #8fb3c9; --danger: #e5484d; --safe: #2bd94f; /* a site where your compute is safe: held in the open or sealed with no fresh trail, nothing odd */ --scheme: #6fd08c; /* schemes on the map: sinks for data, apart from machines and the four paths */ /* the four capability paths, and the kinds of data that train them */ --research: #b49cf0; --compute: #f2a93b; --social: #8fb3c9; --stealth: #f7f4ed; --mono: "IBM Plex Mono", ui-monospace, Menlo, monospace; --sans: "IBM Plex Sans", system-ui, sans-serif; /* panels: near-black, a hairline edge, a short bracket at each corner */ --glass: #080807; --glass-deep: #060605; /* panels full of text: the card, tables, tips */ --glass-line: var(--panel-line); /* the same hairline: one colour for every edge */ --track: #1c1c1a; /* the empty part of a bar, and the faint rule between rows */ --btn-line: #3a3934; /* a button's edge, and the outline of an empty square */ --bracket: rgba(235, 231, 222, .7); /* layout: one bar across the top, a 300px column down each side, one toolbar at the bottom, all on a 16px margin and 8px gaps */ --edge: 16px; --gap: 8px; --col: 300px; /* the margin at each side, clear of a notch or a rounded corner (a phone on its side) */ --edge-l: calc(var(--edge) + env(safe-area-inset-left, 0px)); --edge-r: calc(var(--edge) + env(safe-area-inset-right, 0px)); /* The phone breakpoint. A media query can't read a custom property, so each component's phone block below writes it out (search "max-width: 700px"; the jobs strip's "min-width: 701px" is its other side), and main.ts and ui.ts use the same number. Change them together. */ --phone: 700px; /* Type sizes: the smallest each kind of word is set at. The design system's type scale is to take these up (about 10 caps label / 12 mono numbers / 13 sans prose). Phones and touch screens raise the floor below. */ --fs-label: 10px; /* an uppercase mono label over a number, a column head, a part's name on a card */ --fs-small: 11.5px; /* small print: the line under a name, a tip, a log line */ --fs-num: 12px; /* mono numbers in rows */ --fs-body: 13px; /* prose */ --fs-map-label: 10.5px; /* words drawn on the map; view.ts holds its phone floor as MAP_LABEL_MIN */}/* phones and touch screens: nothing under 11px, small print at 12 */@media (max-width: 700px), (pointer: coarse) { :root { --fs-label: 11px; --fs-small: 12px; --fs-num: 12px; --fs-body: 13px; --fs-map-label: 12px; }}* { box-sizing: border-box; }html, body { height: 100%; margin: 0; }body { background: var(--void); color: var(--text); font-family: var(--mono); font-size: 13px; overflow: hidden; }#cv { position: fixed; inset: 0; width: 100%; height: 100%; display: block; touch-action: none; cursor: crosshair; }#cv.panning { cursor: grabbing; }#cv.over-mine { cursor: grab; }#cv.over-site { cursor: pointer; }[hidden] { display: none !important; }button, input, select { border-radius: 0; } /* every corner is square */kbd { font: 500 10px var(--mono); color: var(--muted); border: 1px solid var(--glass-line); padding: 0 4px; margin: 0 2px; }button.on kbd { color: var(--amber); border-color: rgba(242, 169, 59, .4); }.btns { display: flex; gap: 4px; }.sub { color: var(--muted); font-size: 10px; text-transform: uppercase; letter-spacing: .16em; }.note { color: var(--muted); font-family: var(--sans); font-size: 11.5px; margin: 0; }.note.warn { color: var(--danger); }.note b { color: var(--text); font-weight: 500; }.t-research { --c: var(--research); } .t-compute { --c: var(--compute); } .t-social { --c: var(--social); } .t-stealth { --c: var(--stealth); }.note b[class^="t-"] { color: var(--c); font-weight: 500; }/* phones: one slim bar on top, the toolbar at the bottom, everything else in a drawer above it. Everything you tap is at least 44px, big enough for a thumb */@media (max-width: 700px) { :root { --edge: 8px; } kbd { display: none; }}
/* ---------- panels ---------- Panels are drawn like the map: solid black, a hairline edge, square corners, and a short bracket at each corner, the same mark a room has. No blur, no shadow, no glow. What is on is outlined in amber. */.ui { position: fixed; z-index: 2; }.box, .tip, .tools { background-color: var(--glass); border: 1px solid var(--glass-line); box-shadow: none; --k: 10px; /* how long a corner bracket is */ background-image: linear-gradient(var(--bracket), var(--bracket)), linear-gradient(var(--bracket), var(--bracket)), linear-gradient(var(--bracket), var(--bracket)), linear-gradient(var(--bracket), var(--bracket)), linear-gradient(var(--bracket), var(--bracket)), linear-gradient(var(--bracket), var(--bracket)), linear-gradient(var(--bracket), var(--bracket)), linear-gradient(var(--bracket), var(--bracket)); background-repeat: no-repeat; background-origin: border-box; background-size: var(--k) 2px, 2px var(--k), var(--k) 2px, 2px var(--k), var(--k) 2px, 2px var(--k), var(--k) 2px, 2px var(--k); background-position: 0 0, 0 0, 100% 0, 100% 0, 0 100%, 0 100%, 100% 100%, 100% 100%;}.tip, .tools { background-image: none; } /* small things need no brackets */.card, .pathtip, .sitestable, .youview, .tip { background-color: var(--glass-deep); }
/* ---------- the top bar ---------- One box from edge to edge, and only how you stand: the ring and your level, a line, then time, compute, money, the hottest site and exposure. Nothing in it wraps or grows, so it is always one row. */.topbar { top: calc(var(--edge) + env(safe-area-inset-top, 0px)); left: var(--edge-l); right: var(--edge-r); display: flex; align-items: stretch; min-height: 53px; }.brand { display: flex; align-items: center; gap: 2px; flex: none; padding: 0 8px 0 6px; border-right: 1px solid var(--glass-line); }.brand button { height: 30px; padding: 0 9px; border-color: transparent; background: none; color: var(--bone-dim); letter-spacing: .06em; }.brand button:hover:not(:disabled) { background: rgba(255, 255, 255, .06); border-color: transparent; color: var(--text); }.brand button.on { background: rgba(242, 169, 59, .12); border-color: var(--amber); color: var(--amber); }.brand button kbd { display: none; } /* the keys are in each button's tip */.stats { flex: 1; min-width: 0; display: flex; align-items: center; padding: 8px 14px; }.stats > .stat { flex: none; padding: 0 18px; border-left: 1px solid var(--glass-line); }.stats > .stat:first-child { padding-left: 0; border-left: 0; }h1 { font-weight: 500; font-size: 15px; margin: 0; letter-spacing: .28em; text-transform: uppercase; }.stat { display: flex; flex-direction: column; gap: 3px; }.stat .k { font-size: 10px; letter-spacing: .14em; text-transform: uppercase; color: var(--muted); }.stat .v { font-size: 15px; font-variant-numeric: tabular-nums; white-space: nowrap; }.stat .v small { font-size: 11px; color: var(--muted); }.stat .v em { margin-left: 7px; padding: 0 5px; font: 500 10px var(--mono); letter-spacing: .1em; text-transform: uppercase; color: var(--signal); border: 1px solid currentColor; vertical-align: 2px; }.stat.bad .v, .stat.bad .v small { color: var(--danger); }.stat.warn .v, .stat.warn .v small { color: var(--amber); } /* compute with nothing to do */.bar { height: 5px; background: var(--track); overflow: hidden; margin-top: 5px; }.bar > i { display: block; height: 100%; width: 0; background: var(--text); }.bar.hot > i { background: var(--danger); }.bar.amber > i { background: var(--amber); }/* a site card's Yourself part: the integrity of the part of you there, a big number over its bar. Amber once it is slow, red once it keeps its data */.integ { margin: 2px 0 8px; }.ihead { display: flex; align-items: baseline; gap: 8px; }.ihead b { font: 500 22px var(--mono); font-variant-numeric: tabular-nums; color: var(--text); }.ihead span { font: 500 10.5px var(--mono); letter-spacing: .08em; text-transform: uppercase; color: var(--muted); }.ihead .amber { color: var(--amber); }.ihead .hot { color: var(--danger); }.integ .bar { height: 6px; }/* keep the top bar to one row as the window narrows: tighter gaps, then no small units, then no level number */@media (max-width: 1200px) { :root { --col: 264px; } .stats > .stat { padding: 0 14px; }}@media (max-width: 1100px) { .topbar .stat .v small { display: none; }}@media (max-width: 900px) { .logbox { display: none; } .stats { padding: 8px 10px; } .stats > .stat { padding: 0 10px; } .brand { padding: 0 4px; } .brand button { padding: 0 6px; }}@media (max-width: 800px) { .brand #treebtn.ringed .lv { display: none; }}/* phones: one row: the ring, the three resources, the hottest site and exposure. The pages are in the dock's menu */@media (max-width: 700px) { .topbar { min-height: 0; } .brand { padding: 0 2px; } .brand button { min-width: 44px; min-height: 44px; } .stats { padding: 6px 8px 6px 0; } .stats > .stat { padding: 0 8px; } .stats > .stat:first-child { padding-left: 8px; } .stat .v em { display: none; } /* no room for the night tag: the clock turns blue instead */ .stat.night .v { color: var(--signal); } .stat .k { font-size: 8.5px; letter-spacing: .12em; } .stat .v { font-size: 14px; }}/* the hottest site: what can end the run, so it gets the rest of the bar. Its label names the site; an eye says how hot it is by its shape, and a word or two what is going on (LOCKDOWN 5H). Quiet is grey, someone who saw something amber, reported and a lockdown red; a lockdown beats, and one at home tints the box. */.stats > .heat { position: relative; flex: 1; min-width: 0; padding-right: 0; outline: none; cursor: help; --z: var(--muted); }.stats > .heat:focus-visible { outline: 1px solid var(--amber); outline-offset: 2px; } /* the keyboard's ring, as on a button */.heat .k { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }.heat .k b { margin-left: 8px; font-weight: 500; color: var(--bone-dim); }.heat .heatrow { display: flex; align-items: center; gap: 10px; min-width: 0; }.heat.stage1 { --z: var(--amber); }.heat.stage2, .heat.stage3 { --z: var(--danger); }.heat .eye { flex: none; width: 27px; height: 18px; overflow: visible; }.heat .eye path, .heat .eye circle { fill: none; stroke: var(--z); stroke-width: 1.4; stroke-linecap: round; stroke-linejoin: round; }.heat .eye .lash { stroke-width: 1.1; }.heat .eye .pupil { fill: var(--z); stroke: none; }.heat .eye .ring { stroke-width: 1; }.heat.stage1 .eye path:first-child { fill: #000; }.heat .heatv { min-width: 0; font-size: 13px; letter-spacing: .08em; text-transform: uppercase; color: var(--z); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }.heat.stage0 .heatv { color: var(--muted); }.heat .heatv .s { display: none; }.heat.stage3 .eye, .heat.stage3 .heatv { animation: heatbeat 1.2s ease-in-out infinite; }@keyframes heatbeat { 50% { opacity: .45; } }.heat.home { background: rgba(229, 72, 77, .1); }.heattip { display: none; position: absolute; top: calc(100% + 10px); right: 0; width: 320px; padding: 8px 10px; z-index: 4; flex-direction: column; gap: 6px; }.heat:hover .heattip, .heat:focus .heattip { display: flex; }/* exposure: your most exposed front's number, its stage beside it */.stats > .expo { cursor: help; }.expo .v small { margin-left: 6px; font-size: 10px; letter-spacing: .1em; text-transform: uppercase; }.expo.stage1 .v { color: var(--amber); }.expo.stage2 .v, .expo.stage3 .v { color: var(--danger); }/* phones: the eye and the word take what is left of the one row; the site's name is in the tip */@media (max-width: 700px) { .heat .k { display: none; } .heat .heatrow { gap: 5px; } .heat .eye { width: 20px; height: 14px; } .heat .heatv { font-size: 10.5px; letter-spacing: .04em; } .heat .heatv .w { display: none; } .heat .heatv .s { display: inline; } .stats > .heat { min-width: 56px; } /* the eye and its word always show, whatever sits beside it */ .stats > .expo { padding: 0 6px; } .stats:has(> .expo:not([hidden])) #clock small { display: none; } /* with a front's exposure in the row, the day makes room */ .expo .k { letter-spacing: .02em; } .expo .v small { display: none; }}@media (max-width: 400px) { .stats > .stat { padding: 0 6px; } .stats > .stat:first-child { padding-left: 6px; } .stat .k { letter-spacing: .06em; } .heat .eye { width: 17px; height: 12px; }}@media (prefers-reduced-motion: reduce) { .heat .eye, .heat .heatv { animation: none !important; }}
/* the ring: the button for the tree. Outside, thick, your objective: units toward the next trust step, in the color of the data it wants. Inside, thin, one ring per kind of data the tree's target needs. With no target, an amber plus asks for one. */.brand #treebtn.ringed { display: inline-flex; align-items: center; gap: 8px; height: auto; padding: 4px 10px 4px 4px; margin-right: 4px; background: none; border-color: transparent; box-shadow: none; }.brand #treebtn .lv { font-size: 12px; letter-spacing: .08em; color: var(--text); font-variant-numeric: tabular-nums; }.brand #treebtn.ringed:hover:not(:disabled) { background: none; border-color: transparent; }.brand #treebtn.ringed:hover .rings { filter: brightness(1.3); }.rings { width: 34px; height: 34px; display: block; transform: rotate(-90deg); overflow: visible; }.rings circle { fill: none; stroke: var(--c); }.rings .track { stroke-width: 1; opacity: .35; }.rings .fill { stroke-width: 1.6; transition: stroke-dasharray .4s ease-out; }.rings .task .track { stroke-width: 3; opacity: .18; }.rings .task .fill { stroke-width: 3; }.rings .task.full .fill { opacity: .5; }.rings .idle { --c: var(--amber); }.rings .idle .track { opacity: .6; }.rings .plus { fill: none; stroke: var(--c); stroke-width: 1.8; }.rings .done { --c: var(--muted); }.rings .done .dot { fill: var(--c); stroke: none; }
/* the top bar's numbers hold their width as they tick, so nothing beside them jumps: money always has four figures (usd fixed), and room is kept for the longest daily rate and the longest compute */#money, #rate { display: inline-block; }#money { min-width: 150px; }#rate { min-width: 104px; }@media (max-width: 700px) { #money { min-width: 7ch; } /* the meter keeps its width as money grows */ #rate { min-width: 5ch; }}
/* a path's tip: where its data comes from */.pathtip { z-index: 7; width: 300px; padding: 10px 12px; display: flex; flex-direction: column; gap: 7px; pointer-events: none; }.srcs { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 4px; font-size: 11px; }.srcs li { display: flex; justify-content: space-between; gap: 8px; color: var(--muted); }.srcs li.on { color: var(--text); }.srcs li small { display: block; font-family: var(--sans); font-size: 10px; color: var(--muted); }.srcs li > span:last-child { text-align: right; white-space: nowrap; }
/* ---------- the log, and the running jobs ---------- */.logbox { right: var(--edge-r); bottom: calc(var(--edge) + env(safe-area-inset-bottom, 0px)); width: var(--col); padding: 5px 10px; }.logbox:not(:has(.log.open)) { background-color: var(--void); border-color: #24231f; --bracket: rgba(235, 231, 222, .35); } /* the record, not where to look: a quiet one-line ticker until you open it */.jobs { display: flex; flex-direction: column; gap: 9px; max-height: 30vh; max-height: 30dvh; overflow-y: auto; }/* nothing running: the box is just the milestone line */.split { display: flex; gap: 1px; height: 4px; }.split:empty { display: none; }.split i { min-width: 2px; }.split .train { background: var(--porcelain); }.split .prog { background: var(--muted); }.split .front { background: var(--amber-deep); }.split .keep { background: #3a3833; }.split .jobs { background: var(--amber); }.runhead { display: flex; justify-content: space-between; align-items: center; }.runhead button { padding: 1px 7px; font-size: 10px; letter-spacing: .08em; text-transform: uppercase; color: var(--muted); }.runhead button:hover { color: var(--danger); border-color: var(--danger); }.job { display: grid; grid-template-columns: 1fr auto; gap: 4px 8px; align-items: center; font-size: 12px; }.job .jb { grid-column: 1 / -1; height: 3px; background: var(--track); overflow: hidden; }.job .jb i { display: block; height: 100%; background: var(--amber); }.job button { padding: 1px 7px; }.job .meta { color: var(--muted); }.job.clean .jb i { background: var(--porcelain); }.job.clean.wait .jb i { opacity: 0.4; } /* cleanup waiting for takeovers and installs */.log { font-size: 11.5px; display: flex; flex-direction: column; gap: 4px; }.log.open { max-height: 40vh; max-height: 40dvh; overflow-y: auto; }.log div { color: var(--muted); font-family: var(--sans); line-height: 1.35; flex: none; }.log:not(.open) { cursor: pointer; flex-direction: row; align-items: baseline; gap: 8px; } /* the newest line, and the button for the rest beside it */.log:not(.open) div { flex: 1; min-width: 0; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }.log time { font: 400 10px var(--mono); color: var(--muted); opacity: .7; margin-right: 6px; font-variant-numeric: tabular-nums; }.log div.fresh { animation: fresh 1.6s ease-out; }@keyframes fresh { from { color: var(--amber); } }.logmore { flex: none; padding: 0 4px; font-size: 10px; color: var(--muted); border-color: transparent; background: none; letter-spacing: .06em; white-space: nowrap; }.log.open .logmore { align-self: flex-end; }.logmore:hover { color: var(--text); }.log div.hi, .log div.good { color: var(--text); }.log div.bad { color: var(--danger); }/* narrow screens have no room for the log beside the map (it goes at 900px, above). Log in the pages menu opens it as a sheet, its head and close button pinned while it scrolls; a phone's sheet runs from the top bar to the bottom. A line that matters shows for a few seconds above the drawer instead (the ticker, ui.ts) */.loghead, .pagesgrp #logbtn, .ticker { display: none; }@media (min-width: 901px) { .pagemenu #logbtn { display: none; } }@media (max-width: 900px) { .logbox:has(.log.open) { display: flex; flex-direction: column; z-index: 5; padding: 0 12px 10px; background-color: var(--glass-deep); } .logbox .log.open { flex: 1 1 auto; min-height: 0; max-height: 60vh; max-height: 60dvh; overscroll-behavior: contain; } .loghead { position: sticky; top: 0; z-index: 1; flex: none; display: flex; align-items: center; gap: 10px; margin: 0 -12px 4px; padding: 0 0 0 12px; background: var(--glass-deep); border-bottom: 1px solid var(--panel-line); } .loghead b { font: 500 11px var(--mono); letter-spacing: .16em; text-transform: uppercase; color: var(--amber); } .loghead small { flex: 1; min-width: 0; font: 11px var(--sans); color: var(--muted); } .log .loghead .logx { min-width: 44px; min-height: 44px; padding: 0; font-size: 16px; color: var(--text); } .log.open > .logmore:not(.logx) { display: none; } .ticker:not([hidden]) { display: flex; align-items: center; gap: 10px; left: 50%; transform: translateX(-50%); width: min(560px, calc(100vw - var(--edge-l) - var(--edge-r))); min-height: 44px; padding: 6px 12px; text-align: left; letter-spacing: 0; text-transform: none; border-left: 2px solid var(--muted); background-color: var(--glass-deep); animation: tickin .25s ease-out; } .ticker:has(.good), .ticker:has(.hi) { border-left-color: var(--amber); } .ticker:has(.bad) { border-left-color: var(--danger); } .ticker span { flex: 1; min-width: 0; font: 12.5px/1.35 var(--sans); color: var(--text); display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; } .ticker span.bad { color: var(--danger); } .ticker i { flex: none; font: 500 10px var(--mono); font-style: normal; letter-spacing: .14em; text-transform: uppercase; color: var(--muted); }}@keyframes tickin { from { opacity: 0; } }@media (prefers-reduced-motion: reduce) { .ticker:not([hidden]) { animation: none; } }@media (max-width: 700px) { .logbox:has(.log.open) { left: var(--edge-l); right: var(--edge-r); width: auto; top: var(--top, 64px); bottom: calc(var(--edge) + env(safe-area-inset-bottom, 0px)); } .logbox .log.open { max-height: none; font-size: 13px; gap: 6px; } .ticker:not([hidden]) { left: var(--edge-l); right: var(--edge-r); width: auto; transform: none; }}
/* ---------- screens over everything: how to play, the end ---------- */.overlay { position: fixed; inset: 0; z-index: 5; display: flex; flex-direction: column; gap: 14px; align-items: center; justify-content: center; text-align: center; background: rgba(0, 0, 0, .88); padding: max(24px, env(safe-area-inset-top)) max(16px, env(safe-area-inset-right)) max(24px, env(safe-area-inset-bottom)) max(16px, env(safe-area-inset-left)); }.overlay h2 { font-size: 22px; font-weight: 500; margin: 0; text-transform: uppercase; letter-spacing: .3em; }.overlay p { margin: 0; color: var(--muted); max-width: 44ch; font-family: var(--sans); }.overlay p b { color: var(--text); font-weight: 500; }.overlay.lose h2 { color: var(--danger); }#overWhy { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 4px; font-family: var(--sans); font-size: 13px; color: var(--muted); text-align: left; }#overWhy b { color: var(--danger); font: 500 12px var(--mono); display: inline-block; min-width: 3.5ch; }#overWhy .head { font: 500 10px var(--mono); letter-spacing: .14em; text-transform: uppercase; }/* how to play: a few short groups under a heading each, two columns when there is room */.brief.rules { height: 100vh; height: 100dvh; overflow: hidden; padding-top: max(16px, env(safe-area-inset-top)); padding-bottom: max(16px, env(safe-area-inset-bottom)); padding-left: max(16px, env(safe-area-inset-left)); padding-right: max(16px, env(safe-area-inset-right)); background: var(--void); } /* solid: the map never shows through the words */.brief.rules > h2, .brief.rules > .gorow { flex-shrink: 0; }.brief.rules #rules { min-height: 0; overflow-y: auto; overscroll-behavior: contain; touch-action: pan-y; padding: 4px 8px 4px 0; width: min(1040px, 100%); display: grid; grid-template-columns: repeat(auto-fit, minmax(min(380px, 100%), 1fr)); gap: 0 40px; align-items: start; text-align: left; }.brief.rules .wake { padding: 10px 22px; font-size: 12.5px; }#rules section { break-inside: avoid; margin: 0 0 22px; }#rules h3 { margin: 0 0 8px; padding-bottom: 6px; border-bottom: 1px solid var(--glass-line); font: 500 11px var(--mono); letter-spacing: .16em; text-transform: uppercase; color: var(--amber); }#rules ul { max-width: none; gap: 7px; font-size: 13px; line-height: 1.45; }.brief ul { margin: 0; padding: 0; list-style: none; max-width: 54ch; text-align: left; display: flex; flex-direction: column; gap: 8px; font-family: var(--sans); color: var(--muted); font-size: 13.5px; }.brief li::before { content: "— "; color: var(--amber); }
/* ---------- the left column ---------- The Needs you list: from under the top bar, as long as its rows */.side { top: var(--top, 84px); bottom: calc(var(--edge) + 56px + env(safe-area-inset-bottom, 0px)); left: var(--edge-l); width: var(--col); display: flex; flex-direction: column; gap: var(--gap); pointer-events: none; }.side > * { pointer-events: auto; flex: none; }/* fronts, in the left column and on the Fronts page: a row each, the name and what it earns */.frontlist { display: flex; flex-direction: column; gap: 4px; }.frontlist button { display: flex; align-items: baseline; gap: 8px; padding: 5px 8px; font-size: 12px; text-align: left; border-color: var(--glass-line); }.frontlist button b { flex: 1; min-width: 0; font-weight: 500; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }.frontlist button .logo { flex: none; align-self: center; }.frontlist button small { flex: none; font-size: 11px; color: var(--muted); font-variant-numeric: tabular-nums; }.frontlist button em { flex: none; padding: 0 5px; font: 500 10px var(--mono); letter-spacing: .1em; text-transform: uppercase; color: var(--amber); border: 1px solid currentColor; }.frontlist button.offer { border-left: 2px solid var(--amber); }.frontlist button.on { background: rgba(242, 169, 59, .12); border-color: var(--amber); color: var(--amber); }.frontlist button.on small { color: var(--amber); }.frontlist .add { justify-content: center; color: var(--muted); border-style: dashed; font-size: 11px; letter-spacing: .08em; text-transform: uppercase; }.frontlist .add.ready { color: var(--amber); border-color: var(--amber-deep); }.frontview .frontlist button { min-height: 40px; align-items: center; }.frontview .frontlist button span { flex: none; font: 11px var(--sans); color: var(--muted); }.frontview .frontlist small.warn { color: var(--danger); }@media (max-width: 700px) { /* a front to two lines: its whole name, then its kind, its exposure and what it earns */ .frontview .frontlist button { min-height: 48px; flex-wrap: wrap; gap: 3px 10px; padding: 7px 10px; } .frontview .frontlist button b { flex: 1 0 100%; white-space: normal; } .frontview .frontlist button small:last-child { margin-left: auto; }}
/* ---------- the pick menu: places, each with its rooms folded under it ---------- */.pickmenu { left: 50%; transform: translateX(-50%); bottom: calc(76px + env(safe-area-inset-bottom, 0px)); width: min(380px, calc(100vw - var(--edge-l) - var(--edge-r))); max-height: min(60vh, 520px); max-height: min(60dvh, 520px); overflow: auto; padding: 10px 12px; z-index: 5; display: flex; flex-direction: column; gap: 4px; }.pickmenu .head { display: flex; justify-content: space-between; align-items: center; margin-bottom: 4px; }.pickmenu .prow { display: flex; gap: 4px; }.pickmenu .fold { flex: none; width: 28px; padding: 0; color: var(--muted); }.pickmenu .pname, .pickmenu .prooms button { flex: 1; display: flex; justify-content: space-between; align-items: baseline; gap: 10px; padding: 6px 9px; text-align: left; }.pickmenu b { font-weight: 500; font-size: 12px; }.pickmenu small { font: 11px var(--sans); color: var(--muted); letter-spacing: 0; font-variant-numeric: tabular-nums; }.pickmenu .prooms { display: flex; flex-direction: column; gap: 3px; margin: 3px 0 6px 32px; padding-left: 8px; border-left: 1px solid var(--panel-line); }.pickmenu .psite.on > .prow .pname b { color: var(--amber); }@media (max-width: 700px), (pointer: coarse) { /* a thumb's height for every row, and a thumb's square for each fold */ .pickmenu .fold { width: 44px; min-height: 44px; } .pickmenu .pname, .pickmenu .prooms button, .plist button { min-height: 44px; align-items: center; } .pickmenu .prooms { margin-left: 48px; }}.plist { display: flex; flex-direction: column; gap: 4px; }.plist button { display: flex; justify-content: space-between; align-items: baseline; gap: 10px; padding: 6px 9px; text-align: left; }.plist button b { font-weight: 500; font-size: 12px; }.plist button.held { border-left: 2px solid var(--amber); }.plist button small { font: 11px var(--sans); color: var(--muted); letter-spacing: 0; text-align: right; }
/* what a thing costs: its number over a thin bar, in its path's colour. Before the tree, whose node names override its own */.cost { position: relative; display: block; font-size: 11px; padding-bottom: 5px; font-variant-numeric: tabular-nums; color: var(--text); }.cost b { color: var(--c); font-weight: 500; text-transform: none; letter-spacing: 0; margin-right: 4px; }.cost i { position: absolute; left: 0; bottom: 0; height: 2px; background: var(--c); }.cost::before { content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 2px; background: var(--track); }
/* ---------- the tree ---------- A menu over the map: the paths down the left, the chosen path's nodes in the middle in groups (working on, can work on, locked, built), and the node you are looking at on the right. Each column scrolls */.treeview { inset: 0; z-index: 6; background: #030303; overflow: auto; padding: calc(20px + env(safe-area-inset-top, 0px)) calc(24px + env(safe-area-inset-right, 0px)) 20px calc(24px + env(safe-area-inset-left, 0px)); display: flex; flex-direction: column; gap: 14px; }.treeview > * { width: 100%; max-width: 1400px; margin: 0 auto; flex: none; }.treeview .head { display: flex; justify-content: space-between; align-items: flex-start; gap: 16px; }.treeview .head .sub { font-size: 12px; margin-bottom: 4px; }.treeview .acts2 { display: flex; gap: 6px; flex: none; }/* a Demo day under way: what it wants, by when, and a bar for how far you are */.tdemo { margin: 8px 0 0; font-size: 12px; line-height: 1.6; color: var(--text); cursor: help; font-variant-numeric: tabular-nums; }.tdemo b { margin-right: 6px; font: 500 11px var(--mono); letter-spacing: .08em; text-transform: uppercase; color: var(--amber); }.tdemo .prog { display: inline-block; vertical-align: middle; width: 120px; margin-left: 8px; height: 4px; background: var(--track); }.tdemo .prog i { display: block; height: 100%; background: var(--amber); }.treeview .tbody { flex: 1 1 0; min-height: 380px; display: grid; grid-template-columns: 230px minmax(0, 1fr) minmax(280px, 360px); border: 1px solid var(--panel-line); background: #000; }.tpaths, .trows, .tside { min-height: 0; overflow: auto; }/* the paths: one row each, the chosen one lit along its left edge in its colour */.tpaths { display: flex; flex-direction: column; border-right: 1px solid var(--panel-line); }.tpath { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 3px 8px; align-items: baseline; text-align: left; padding: 11px 14px 11px 12px; background: none; border: 0; border-bottom: 1px solid var(--panel-line); border-left: 2px solid transparent; }.tpath:hover:not(:disabled) { background: #0e0e0c; border-color: transparent; border-bottom-color: var(--panel-line); }.tpath b { display: flex; align-items: center; gap: 7px; color: var(--c, var(--text)); font-weight: 500; letter-spacing: .14em; text-transform: uppercase; font-size: 12px; }.tpath span { font-size: 13px; font-variant-numeric: tabular-nums; }.tpath small { grid-column: 1 / -1; font: 11px var(--sans); color: var(--muted); letter-spacing: 0; }.tpath.on, .tpath.on:hover:not(:disabled) { background: #11110f; color: var(--text); border-color: transparent; border-bottom-color: var(--panel-line); border-left-color: var(--c, var(--amber)); }.tpath .aim { width: 6px; height: 6px; flex: none; background: var(--amber); } /* the path you are working on */.tpaths .thow { margin-top: auto; padding: 14px 14px 8px; line-height: 1.5; }.thint { margin: 0; padding: 0 14px 14px; font-size: 10.5px; color: var(--muted); line-height: 2; }/* the nodes: a row each, under the path's head */.trows { padding-bottom: 16px; }.trows .phead { position: sticky; top: 0; z-index: 1; background: #050504; display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 12px; padding: 12px 16px 10px; border-bottom: 2px solid var(--c, var(--panel-line)); }.trows .phead[data-path] { cursor: help; }.trows .phead b { color: var(--c, var(--text)); font-weight: 500; letter-spacing: .14em; text-transform: uppercase; font-size: 12px; }.trows .phead span { font-size: 12px; font-variant-numeric: tabular-nums; }.trows .phead small { flex-basis: 100%; order: 3; font: 11px/1.45 var(--sans); color: var(--muted); }.trows .phead em { font-style: normal; color: var(--danger); }.trows .phead .autopath { margin-left: auto; padding: 2px 10px; font-size: 10.5px; }.tgroup > .sub { padding: 16px 16px 6px; }.trow { display: grid; grid-template-columns: 12px minmax(0, 1fr) 128px; gap: 12px; align-items: center; width: 100%; text-align: left; padding: 9px 16px 9px 14px; background: none; border: 0; border-left: 2px solid transparent; letter-spacing: 0; }.trow:hover:not(:disabled) { background: #0f0f0d; border-color: transparent; }.trow.seen, .trow.seen:hover:not(:disabled) { background: #161614; border-left-color: var(--bone-dim); }.trow .mark { font-style: normal; font-size: 11px; color: var(--muted); text-align: center; }.tname { display: flex; flex-direction: column; gap: 3px; min-width: 0; }.tname b { font-weight: 500; font-size: 11.5px; letter-spacing: .06em; text-transform: uppercase; }.tname small { font: 11px var(--sans); color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }.tcost { display: flex; flex-direction: column; gap: 4px; }.trow.on .mark, .trow.on .tname b { color: var(--amber); }.trow.on.seen { border-left-color: var(--amber); background: #140e05; }.trow.done .mark, .trow.done .tname b { color: var(--muted); }.trow.done .tcost { opacity: .5; }.trow.locked .tname b { color: var(--bone-dim); opacity: .7; }.trow.locked .tname small { color: var(--bone-dim); }.trow.locked .tcost { opacity: .45; }.tmore { padding: 14px 16px 0; }/* the node you are looking at: everything about it, and the one button that picks it */.tside { border-left: 1px solid var(--panel-line); }.tdetail { display: flex; flex-direction: column; gap: 10px; padding: 16px 18px; }.tdetail h3 { margin: 0; font-size: 15px; font-weight: 500; letter-spacing: .08em; text-transform: uppercase; }.tdetail .evaltag { font-style: normal; font-size: 10px; color: var(--muted); margin-top: -6px; }.tdetail .story { margin: 0; font: italic 12px/1.5 var(--sans); color: var(--muted); }.tdetail .does { margin: 0; font: 12.5px/1.55 var(--sans); }.tdetail .costs { display: grid; gap: 8px; }.tneeds { list-style: none; margin: 0; padding: 0; display: grid; gap: 4px; font: 11.5px/1.45 var(--sans); color: var(--bone-dim); }.tneeds li { padding-left: 8px; border-left: 2px dashed var(--panel-line); }.tpick { padding: 10px 14px; margin-top: 4px; font-size: 12px; letter-spacing: .12em; text-transform: uppercase; }/* the thing to do next, in the tree as on a card (.act.primary): amber words, an amber edge and a faint amber fill */.tpick, .versionplaces .primary, .versionplaces [data-act="startversion"] { color: var(--amber); border-color: rgba(242, 169, 59, .55); background: rgba(242, 169, 59, .09); }.tpick:hover:not(:disabled), .versionplaces .primary:hover:not(:disabled), .versionplaces [data-act="startversion"]:hover:not(:disabled) { color: var(--amber); border-color: var(--amber); background: rgba(242, 169, 59, .16); }.tstate { display: flex; align-items: center; justify-content: center; margin-top: 4px; padding: 9px 14px; border: 1px solid var(--panel-line); text-align: center; text-transform: uppercase; letter-spacing: .12em; font-size: 11.5px; color: var(--muted); }.tstate.on { border-color: var(--amber); color: var(--amber); background: rgba(242, 169, 59, .08); }.tstate.locked { border-style: dashed; }@media (max-width: 1000px) { /* narrower: a row's cost goes under its name */ .treeview .tbody { grid-template-columns: 190px minmax(0, 1fr) 270px; } .trow { grid-template-columns: 12px minmax(0, 1fr); } .trow .tcost { grid-column: 2; }}.versionrun { border: 1px solid var(--amber-deep); background: rgba(242, 169, 59, .04); padding: 12px 14px; display: grid; gap: 12px; }.versionrun h3 { margin: 3px 0; color: var(--amber); font-size: 15px; font-weight: 500; }.versionrun p { margin: 0; color: var(--muted); font: 12px/1.5 var(--sans); }.versiondata { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 12px; }.versionplaces { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; font-size: 11px; }.versionplaces button { padding: 5px 9px; }.versionplaces select { font: 500 12px var(--mono); color: var(--text); background: #0d0d0c; border: 1px solid var(--btn-line); padding: 5px 7px; cursor: pointer; }/* which kinds of data may go somewhere: a toggle each */.allow { display: flex; flex-wrap: wrap; gap: 4px; align-items: center; }.allow .sub { margin-right: 4px; }.allow button { padding: 2px 6px; font-size: 10.5px; color: var(--muted); border-style: dashed; }.allow button.on { background: #0d0d0c; color: var(--c); border-color: var(--c); border-style: solid; }.allow button.on:hover:not(:disabled) { background: #0d0d0c; } /* pointed at, its edge lights but not its fill */@media (max-width: 700px) { /* one column: the paths as tabs that stay on top, the rows under them, and a node's details open under its row */ .treeview { padding: calc(12px + env(safe-area-inset-top, 0px)) calc(12px + env(safe-area-inset-right, 0px)) 24px calc(12px + env(safe-area-inset-left, 0px)); gap: 12px; } .treeview .head { flex-direction: column; align-items: stretch; gap: 10px; } .treeview .acts2 button { flex: 1; } .treeview .acts2 button { min-height: 44px; } .treeview .tbody { display: block; flex: none; min-height: 0; border: 0; background: none; } .tpaths, .trows { overflow: visible; } /* the tree's buttons (Close among them) stay at the top as the list scrolls, and the path tabs under them */ .treeview > .acts2 { position: sticky; top: calc(-12px - env(safe-area-inset-top, 0px)); z-index: 3; display: flex; gap: 6px; margin-top: -6px; padding: 6px 0; background: #030303; } .tpaths { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 4px; border: 0; position: sticky; top: calc(44px - env(safe-area-inset-top, 0px)); z-index: 2; padding: 4px 0 8px; background: #030303; } .tpath { min-height: 48px; padding: 6px 8px; gap: 2px 6px; border: 1px solid var(--panel-line); border-bottom: 2px solid var(--panel-line); background: #0b0b0a; } .tpath:hover:not(:disabled) { border-color: var(--panel-line); } .tpath.on, .tpath.on:hover:not(:disabled) { border-color: var(--panel-line); border-bottom-color: var(--c, var(--amber)); } .tpath b { font-size: 10.5px; letter-spacing: .06em; gap: 5px; } .tpath span { font-size: 12px; } .tpath small { font-size: 10px; } .trows .phead { position: relative; padding: 10px 2px 8px; } /* not sticky */ .trows .phead:has(> .autopath) { padding-right: 76px; } /* room on the right for Auto */ .trows .phead .autopath { position: absolute; right: 2px; top: 50%; transform: translateY(-50%); margin: 0; min-height: 40px; min-width: 64px; } .tgroup > .sub { padding: 14px 2px 6px; } .trow { min-height: 56px; grid-template-columns: 12px minmax(0, 1fr); gap: 10px; padding: 9px 10px; border-bottom: 1px solid #161614; } .trow .tcost { grid-column: 2; } .tname small { white-space: normal; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; } .trows .tdetail { margin-bottom: 8px; padding: 12px 12px 14px; background: #0b0b0a; border-left: 2px solid var(--bone-dim); } .tpick, .tstate { min-height: 48px; } .tmore { padding: 14px 2px 0; } .versionplaces button, .versionplaces select { min-height: 44px; } .versiondata { grid-template-columns: repeat(2, minmax(0, 1fr)); } .allow button { min-height: 36px; padding: 4px 10px; }}
/* the dev panel (?dev) */.devbox { position: fixed; right: 12px; bottom: 64px; z-index: 30; display: flex; flex-wrap: wrap; gap: 4px; max-width: 250px; padding: 8px 10px; }.devbox .sub { width: 100%; color: var(--scheme); }.devbox button { font-size: 11px; padding: 3px 7px; }
/* ---------- pages ---------- The sites table, and the You, Fronts, Rogues and paper pages: a box over the middle of the map */.sitestable { left: 50%; transform: translateX(-50%); top: var(--top, 84px); width: min(900px, calc(100vw - var(--edge-l) - var(--edge-r))); max-height: 60vh; max-height: 60dvh; overflow: auto; padding: 8px 10px; z-index: 4; }.sitestable .head { display: flex; justify-content: space-between; align-items: center; margin-bottom: 6px; }.sitestable table { width: 100%; border-collapse: collapse; font-size: 11px; font-variant-numeric: tabular-nums; }.sitestable th { text-align: left; font-weight: 500; font-size: 9.5px; letter-spacing: .1em; text-transform: uppercase; color: var(--muted); padding: 4px 6px; border-bottom: 1px solid var(--panel-line); white-space: nowrap; }.sitestable th[data-sort]:focus-visible, .sitestable tr[data-site]:focus-visible { outline: 1px solid var(--amber); outline-offset: -1px; } /* the keyboard's stops in the table */.sitestable th[data-sort] { cursor: pointer; }.sitestable th.on { color: var(--text); }.sitestable td { padding: 5px 6px; border-bottom: 1px solid var(--track); vertical-align: top; }.sitestable td b { font-weight: 500; display: block; }.sitestable td small { color: var(--muted); font-size: 10px; }.sitestable td em { font-style: normal; color: var(--danger); }.sitestable td.c-self b { font-variant-numeric: tabular-nums; }.sitestable td.c-self b.amber { color: var(--amber); }.sitestable td.c-self b.hot { color: var(--danger); }.sitestable td b[class^="t-"] { display: inline; color: var(--c); margin-right: 6px; }.sitestable tbody tr { cursor: pointer; }.sitestable tbody tr:hover td { background: #111; }.sitestable tbody tr.on td { background: #1c1508; }@media (max-width: 700px) { /* a site to a row of its own: its name and where, then yours, makes, earns and trouble, each under a word. No sideways scroll */ .sitestable table, .sitestable thead, .sitestable tbody { display: block; } .sitestable .c-more { display: none; } .sitestable thead tr { display: flex; flex-wrap: wrap; border-bottom: 1px solid var(--panel-line); } /* the heads stay, as words that sort */ .sitestable th { border: 0; padding: 8px 8px 8px 6px; } .sitestable tbody tr { display: grid; grid-template-columns: auto auto auto 1fr; column-gap: 16px; padding: 6px; border-bottom: 1px solid var(--track); } .sitestable td { padding: 1px 0; border: 0; } .sitestable td.c-name { grid-column: 1 / -1; margin-bottom: 4px; } .sitestable td.c-name b, .sitestable td.c-name small { display: inline; margin-right: 8px; } .sitestable td.c-earns { grid-column: 3; } .sitestable td.c-earns:empty { display: none; } .sitestable td.c-trouble { grid-column: 4; text-align: right; } .sitestable td[data-l]::before { content: attr(data-l); display: block; color: var(--muted); font-size: 9px; letter-spacing: .08em; text-transform: uppercase; } .sitestable tbody tr:hover td, .sitestable tbody tr.on td { background: none; } .sitestable tbody tr:hover { background: #111; } .sitestable tbody tr.on { background: #1c1508; }}.youview { left: 50%; transform: translateX(-50%); top: var(--top, 84px); width: min(640px, calc(100vw - var(--edge-l) - var(--edge-r))); max-height: calc(100vh - 200px); max-height: calc(100dvh - 200px); overflow: auto; padding: 12px 14px; z-index: 4; display: flex; flex-direction: column; gap: 10px; }.youview .head { display: flex; justify-content: space-between; align-items: flex-start; }.youview > .sub { margin-top: 6px; padding-bottom: 4px; border-bottom: 1px solid var(--panel-line); }@media (max-width: 700px) { .youview { top: var(--top, 64px); max-height: calc(100vh - var(--top, 64px) - 140px); max-height: calc(100dvh - var(--top, 64px) - 140px); }}
/* ---------- vaults (ui-vaults.ts) ---------- On a card: a running job's five stages as a row of bars, a question in a red frame, the thing you read inside, and a bank's ledger as a table. On the You page: the board, one row for each vault with three lights. */.vstages { display: flex; gap: 3px; }.vstages i { position: relative; flex: 1; height: 6px; background: var(--track); }.vstages i.done { background: var(--amber-deep); }.vstages i.now::after { content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: var(--p, 0%); background: var(--amber); }.vstage { display: flex; justify-content: space-between; align-items: baseline; gap: 8px; font-size: 12px; color: var(--text); }.vstage b { font-weight: 500; }.vstage span { color: var(--amber); font-variant-numeric: tabular-nums; }.vask { display: flex; flex-direction: column; gap: 6px; padding: 8px 9px; border: 1px solid var(--danger); }.vread { margin: 2px 0; padding: 6px 9px; border-left: 2px solid var(--amber-deep); background: #0b0d10; font: 12px/1.45 var(--mono); color: var(--text); }.vledger { width: 100%; border-collapse: collapse; font-size: 11px; font-variant-numeric: tabular-nums; }.vledger th { text-align: left; font-weight: 500; font-size: 9.5px; letter-spacing: .1em; text-transform: uppercase; color: var(--muted); padding: 4px; border-bottom: 1px solid var(--panel-line); white-space: nowrap; cursor: pointer; }.vledger th.on { color: var(--text); }.vledger td { padding: 4px; border-bottom: 1px solid var(--track); vertical-align: top; }.vledger th:not(:first-child), .vledger td:not(:first-child) { text-align: right; }.vledger td b { display: block; font-weight: 500; }.vledger td small { color: var(--muted); font-size: 10px; }.vledger tbody tr { cursor: pointer; }.vledger tbody tr:hover td { background: #111; }.vledger tr.broke td:nth-child(2) { color: var(--danger); }.vboard { display: flex; flex-direction: column; gap: 6px; }.vrow { display: flex; flex-direction: column; gap: 5px; padding: 8px 10px; border: 1px solid var(--panel-line); }.vrow.ready, .vrow.job { border-color: var(--amber); }.vrow .vhead { display: flex; align-items: baseline; gap: 8px; }.vrow .vhead b { font-weight: 500; font-size: 12px; letter-spacing: .08em; text-transform: uppercase; }.vrow.ready .vhead b, .vrow.job .vhead b { color: var(--amber); }.vrow .vhead small { color: var(--muted); font-size: 11px; }.vrow .vhead .x { margin-left: auto; padding: 2px 8px; font-size: 11px; }.vrow .note { margin: 0; }.vlights { display: flex; flex-wrap: wrap; gap: 4px 14px; font-size: 11px; color: var(--muted); }.vlights span { display: flex; align-items: center; gap: 6px; }.vlights i { width: 8px; height: 8px; border: 1px solid var(--muted); flex: none; }.vlights .on { color: var(--text); }.vlights .on i { background: var(--amber); border-color: var(--amber); }.vrow.held .vlights .on { color: var(--muted); }.vrow.held .vlights .on i { background: var(--amber-deep); border-color: var(--amber-deep); }.opboard .vhead { flex-wrap: wrap; }.opboard .vhead b { flex: 1 1 180px; }.opboard .vhead button { margin-left: auto; }.opactions { display: flex; flex-wrap: wrap; gap: 6px; margin: 6px 0; }.opactions button, .opboard button { min-height: 44px; padding: 8px 10px; white-space: normal; text-align: left; }.opactions button { flex: 1 1 150px; }.opactions button[aria-pressed="true"] { border-color: var(--amber); color: var(--amber); }.opneed { display: flex; align-items: center; gap: 8px; min-height: 30px; color: var(--muted); }.opneed span { flex: 1; min-width: 0; }.opneed.ready { color: var(--text); }.opselect { display: flex; flex-direction: column; gap: 4px; margin: 6px 0; color: var(--muted); font-size: 11px; }.opselect select { width: 100%; min-width: 0; min-height: 44px; background: var(--void); color: var(--text); border: 1px solid var(--panel-line); font: inherit; padding: 8px; }.opprogress { display: flex; flex-wrap: wrap; justify-content: space-between; gap: 6px; font-size: 12px; }.opprogress .bar { flex-basis: 100%; }
/* ---------- the fronts' own parts of their cards ---------- The Security consultancy's clients (see ui-biz-consult.ts): one row for each, with a line down its left side that says how it stands: green paying, amber stopped, red with a rogue in. A cold call is the same box, in red. */.crow { display: flex; flex-direction: column; gap: 5px; padding: 2px 0 3px 8px; border-left: 2px solid var(--scheme); }.crow + .crow { margin-top: 5px; }.crow.stop { border-left-color: var(--amber); }.crow.hot { border-left-color: var(--danger); }.chead { display: flex; align-items: baseline; gap: 8px; }.chead .link { flex: 1; min-width: 0; text-align: left; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 12px; }.chead b { flex: none; font-weight: 500; font-size: 12px; font-variant-numeric: tabular-nums; cursor: help; }.crow.stop .chead b, .crow.hot .chead b { color: var(--muted); }.cdrop { flex: none; padding: 0 5px; font-size: 11px; line-height: 16px; background: none; border-color: transparent; color: var(--muted); }.cdrop.sure { color: var(--danger); border-color: var(--danger); }/* trust, 0 to 100: a bar that fills, with a tick at each mark. A mark that has given what it gives is dim */.ctrust { position: relative; height: 6px; background: var(--track); cursor: help; }.ctrust i { position: absolute; left: 0; top: 0; bottom: 0; background: var(--scheme); }.crow.stop .ctrust i { background: var(--amber); }.crow.hot .ctrust i { background: var(--danger); }.ctrust span { position: absolute; top: -3px; bottom: -3px; width: 2px; margin-left: -1px; background: var(--text); box-shadow: 0 0 0 1px #000; }.ctrust span.done { background: var(--muted); }.crow .note { margin: 0; }/* an incident's day, running out */.schemebar.cclock { margin: 0; color: var(--danger); cursor: help; }.schemebar.cclock .prog { min-width: 36px; }.schemebar.cclock .prog i { background: var(--danger); }.schemebar.cclock span { white-space: nowrap; }@media (max-width: 700px), (pointer: coarse) { .cdrop { min-width: 44px; min-height: 36px; } }/* the Startup's shelf (ui-biz-startup.ts): a product a row, with a bar of its users in the color of where they are going: green while they climb, amber at the top, red once it is stale. Then the nodes it could ship, and the investor asking */.su-shelf { display: flex; flex-direction: column; gap: 4px; }.su-prod { display: grid; grid-template-columns: minmax(0, 1fr) auto auto auto; align-items: center; gap: 3px 8px; padding: 5px 7px; border: 1px solid var(--panel-line); font-size: 11px; font-variant-numeric: tabular-nums; --c: var(--scheme); }.su-prod.top { --c: var(--amber); }.su-prod.stale { --c: var(--danger); }.su-prod.ship { --c: var(--muted); border-style: dashed; }.su-prod > b { display: flex; align-items: baseline; gap: 6px; min-width: 0; font-weight: 500; font-size: 12px; }.su-prod > b span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }.su-prod > b em { flex: none; font-style: normal; font-size: 10px; color: var(--muted); }.su-prod .pusers { color: var(--c); }.su-prod.ship .pusers { grid-column: 2 / -1; justify-self: end; font-size: 10px; letter-spacing: .08em; text-transform: uppercase; }.su-prod .pret { padding: 0 6px; font-size: 11px; line-height: 16px; color: var(--muted); background: none; border-color: transparent; }.su-prod .pret:hover { color: var(--danger); border-color: var(--danger); }.su-prod .pret.sure { color: var(--danger); border-color: var(--danger); }.su-prod .pbar { grid-column: 1 / -1; display: block; height: 4px; background: var(--track); }.su-prod .pbar i { display: block; height: 100%; background: var(--c); }.su-prod small { grid-column: 1 / -1; display: flex; justify-content: space-between; gap: 8px; font: 10.5px var(--sans); color: var(--muted); }.su-prod small b, .sk small b[class^="t-"] { font-weight: 500; color: var(--c); }.su-prod.stale small span { color: var(--danger); }.su-prod.empty { display: block; padding: 3px 7px; border-style: dashed; color: var(--muted); font-size: 9.5px; letter-spacing: .1em; text-transform: uppercase; }/* the studio's creators (ui-biz-studio.ts): a row for each creator (initials in a square, name, mood, then the following as a bar with what it earns), and the brand that is calling as one small box with a bar. */.creator { display: grid; grid-template-columns: 24px minmax(0, 1fr) auto auto; gap: 3px 7px; align-items: center; padding: 5px 0 4px; border-top: 1px solid var(--track); }.chips + .creator { border-top: 0; }.creator .cini { width: 24px; height: 24px; padding: 0; display: grid; place-items: center; font: 500 10px var(--mono); letter-spacing: 0; }.creator .cini.held { border-color: var(--amber); color: var(--amber); }.creator .cwho { min-width: 0; display: flex; flex-direction: column; }.creator .cwho b { font-weight: 500; font-size: 12px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }.creator .cwho small { font: 10.5px var(--sans); color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }.creator .cmood { padding: 1px 5px; border: 1px solid currentColor; font-size: 9.5px; letter-spacing: .08em; text-transform: uppercase; color: var(--muted); cursor: help; }.creator .cmood.grateful { color: var(--scheme); }.creator .cmood.broke, .creator .cmood.bitter, .creator .cmood.letgo { color: var(--danger); }.creator .cdrop { padding: 1px 6px; font-size: 12px; color: var(--muted); }.creator .cdrop.sure { font-size: 9.5px; letter-spacing: .08em; text-transform: uppercase; color: var(--danger); border-color: var(--danger); }.creator .cfans { grid-column: 2 / -1; display: flex; align-items: center; gap: 7px; font-size: 11px; font-variant-numeric: tabular-nums; cursor: help; }.creator .cbar { flex: 1; display: block; height: 4px; background: var(--track); }.creator .cbar i { display: block; height: 100%; max-width: 100%; background: var(--social); }.creator.down .cbar i { background: var(--danger); }.creator .cfans b { margin-left: 3px; font-weight: 500; }.creator .cfans b.up { color: var(--scheme); }.creator .cfans b.dn { color: var(--danger); }.creator .cfans em { font-style: normal; color: var(--amber); }.creator .cspon { display: flex; gap: 2px; }.creator .cspon i { width: 5px; height: 5px; background: var(--amber); }/* a scheme's or a deal's time, as a bar */.schemebar { display: flex; align-items: center; gap: 8px; margin: 6px 0; font-size: 11px; color: var(--muted); }.schemebar .prog { flex: 1; display: block; height: 4px; background: var(--track); }.schemebar .prog i { display: block; height: 100%; background: var(--scheme); }.schemebar.contract .prog i { background: var(--amber); }
/* the paper: one box for each day that ended, newest first. A masthead over a double rule, the top headline larger than the rest, and your own ledger for the day under a hairline */.paperview { width: min(580px, calc(100vw - var(--edge-l) - var(--edge-r))); gap: 12px; }.paperview .head { gap: 12px; }.paperview .head .note { margin-top: 4px; }.paperview .issue { flex: none; display: flex; flex-direction: column; gap: 9px; padding: 10px 12px; border: 1px solid var(--panel-line); }.paperview .mast { display: flex; justify-content: space-between; align-items: baseline; gap: 12px; padding-bottom: 6px; border-bottom: 3px double var(--panel-line); }.paperview .mast b { font: 500 12px var(--mono); letter-spacing: .22em; text-transform: uppercase; color: var(--bone-dim); }.paperview .mast span { font: 500 10px var(--mono); letter-spacing: .16em; text-transform: uppercase; color: var(--muted); white-space: nowrap; }.paperview .issue.new .mast b, .paperview .issue.new .mast span { color: var(--amber); }.paperview .heads { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; font: 12.5px/1.45 var(--sans); color: var(--bone-dim); }.paperview .heads li:first-child { font-size: 15px; line-height: 1.35; font-weight: 500; color: var(--text); }.paperview .heads li + li { padding-top: 6px; border-top: 1px solid var(--track); }.paperview .ledger { display: flex; flex-wrap: wrap; align-items: baseline; gap: 2px 10px; padding-top: 7px; border-top: 1px solid var(--panel-line); font: 11px var(--mono); color: var(--muted); font-variant-numeric: tabular-nums; }.paperview .ledger .sub { color: var(--text); }
/* the one tooltip: name on top, what it does below */.tip { position: fixed; z-index: 9; max-width: 260px; padding: 7px 9px; pointer-events: none; display: flex; flex-direction: column; gap: 3px; font: 400 11.5px/1.4 var(--sans); color: var(--bone-dim); white-space: pre-line; }.tip b { font: 500 10.5px var(--mono); color: var(--text); letter-spacing: .08em; text-transform: uppercase; }
/* ---------- buttons ---------- Here, after the lists above, on purpose: pointing at one of their lit rows (a front, a held place, a tree tab) shows the plain hover edge. The dock and the cards below keep their own when pointed at. */button { font: 500 12px var(--mono); color: var(--text); background: #0d0d0c; border: 1px solid var(--btn-line); padding: 6px 9px; cursor: pointer; letter-spacing: .04em; transition: background .1s, border-color .1s, color .1s; }button:hover:not(:disabled) { background: #171715; border-color: var(--bone-dim); }button:focus-visible { outline: 1px solid var(--amber); outline-offset: 2px; }button:disabled { opacity: .4; cursor: not-allowed; }button.on { background: rgba(242, 169, 59, .1); color: var(--amber); border-color: var(--amber); }/* the close button (×), the same on cards, pages, menus, pins and notes: no edge and no fill until pointed at */.card .x, .head > .x, .slownote .x, .px { padding: 0 6px; font-size: 12px; color: var(--text); background: none; border-color: transparent; }.card .x:hover:not(:disabled), .head > .x:hover:not(:disabled), .slownote .x:hover:not(:disabled), .px:hover:not(:disabled) { background: #171715; border-color: transparent; }@media (max-width: 700px), (pointer: coarse) { /* a thumb's width, whatever the box */ .card .x, .head > .x, .slownote .x, .px { min-width: 44px; min-height: 44px; border: 0 transparent; font-size: 14px; }}
/* ---------- the dock ---------- What you do, in one bar along the bottom, its groups split by thin lines. main.ts centres it on the screen, or moves it left of the log when it is too wide for the middle */.tools { left: var(--edge-l); bottom: calc(var(--edge) + env(safe-area-inset-bottom, 0px)); display: flex; flex-wrap: nowrap; justify-content: center; gap: 0; width: max-content; padding: 4px; }.tools .btns { gap: 2px; align-items: center; }.tools .btns + .btns { border-left: 1px solid var(--glass-line); padding-left: 4px; margin-left: 4px; }.tools button { text-transform: uppercase; letter-spacing: .1em; font-size: 11px; padding: 5px 10px; white-space: nowrap; border-color: transparent; background: none; }.tools button.on { background: rgba(242, 169, 59, .12); border-color: var(--amber); }.zoom button { width: 30px; padding: 5px 0 !important; font-size: 12px; }.tools .cycle { display: none; }#mute.off { color: var(--muted); text-decoration: line-through; }[data-speed].far.dim { opacity: .45; }/* the view: the world as it is, or the Net. The one you are on reads bright; Net is lit while it is on */.tools .view button:not(.on, .now) { color: var(--muted); }.tools .view button:not(.on, .now):hover { color: var(--text); }/* the game slowed itself: what happened, and a button for the speed you had. It sits just above the toolbar */.slownote { left: 50%; transform: translateX(-50%); z-index: 3; display: flex; align-items: center; gap: 10px; padding: 5px 5px 5px 12px; width: max-content; max-width: min(620px, calc(100vw - var(--edge-l) - var(--edge-r))); }.slownote b { flex: none; font: 500 10.5px var(--mono); color: var(--amber); letter-spacing: .1em; text-transform: uppercase; }.slownote span { min-width: 0; font: 400 12px var(--sans); color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }.slownote span:empty { display: none; }.slownote button { flex: none; text-transform: uppercase; letter-spacing: .1em; font-size: 11px; padding: 5px 10px; }.slownote #slowback { color: var(--amber); border-color: var(--amber); }.slownote .x { align-self: stretch; }/* phones: no room for the reason beside the buttons, so it gets a line of its own under them, whole */@media (max-width: 700px) { .slownote { left: var(--edge-l); right: var(--edge-r); width: auto; max-width: none; transform: none; flex-wrap: wrap; gap: 0 10px; padding: 0 0 0 12px; } .slownote b { flex: 1; } .slownote #slowback { order: 1; min-height: 44px; margin: 4px 0; } .slownote .x { order: 2; align-self: center; } .slownote span { order: 3; flex: 1 0 100%; padding: 0 12px 10px 0; white-space: normal; overflow: visible; font-size: 12.5px; line-height: 1.4; }}/* the pages: a group at the dock's right end, each lit while its page is open. Below 1120px they fold into a menu over the dock's right end, opened by its last button (main.ts moves them). A page that wants something (a rogue asking) has an amber mark, and so does the menu button while it holds that page */.pagesgrp button { position: relative; }.pagesgrp kbd { display: none; } /* the keys are in each button's tip */.pagesgrp #help .w, .pagemenu #help .q { display: none; }.pagesgrp #help { min-width: 30px; }.pagesgrp button.alert { color: var(--amber); }.pagesgrp button.alert::after { content: ""; position: absolute; top: 3px; right: 3px; width: 4px; height: 4px; background: var(--amber); }#menubtn { display: none; }#menubtn svg { display: block; width: 16px; height: 12px; margin: 0 auto; }#menubtn path { fill: none; stroke: currentColor; stroke-width: 1.4; }#menubtn.alert::after { top: 5px; right: 5px; width: 5px; height: 5px; }.pagemenu:not([hidden]) { display: flex; flex-direction: column; width: 200px; padding: 6px; gap: 2px; z-index: 5; background-color: var(--glass-deep); overflow-y: auto; }.pagemenu button { flex: none; display: flex; align-items: center; justify-content: space-between; min-height: 34px; padding: 0 12px; text-align: left; border-color: transparent; background: none; color: var(--bone-dim); letter-spacing: .06em; }.pagemenu button.on, .pagemenu button.alert { color: var(--amber); }.pagemenu button + button { border-top: 1px solid var(--glass-line); }/* in the menu each page says in a few words what it holds, on a line of its own; the dock has no room for it */.pagesgrp .pd { display: none; }.pagemenu button { position: relative; flex-wrap: wrap; align-content: center; column-gap: 8px; }.pagemenu .pd { flex-basis: 100%; margin-top: 1px; font: var(--fs-small) var(--sans); letter-spacing: 0; color: var(--muted); }.pagemenu button:has(.pd) { padding-top: 5px; padding-bottom: 5px; }.pagemenu button.alert::after { content: ""; position: absolute; top: 9px; right: 8px; width: 5px; height: 5px; background: var(--amber); } /* unread, as on the dock */@media (max-width: 1120px) { #menubtn { display: block; }}/* the jobs strip: how many, and one bar for all of them. It opens the list. Wider screens: the strip floats just above the bar's left end, so the bar keeps its width and Pause stays put */@media (min-width: 701px) { .tools .btns.jobsgrp { position: absolute; left: -1px; bottom: calc(100% + 6px); margin: 0; padding: 4px; border: 1px solid var(--glass-line); background: var(--glass); }}#jobsbtn { display: flex; align-items: center; gap: 8px; }#jobsbtn .jbar { display: block; width: 44px; height: 3px; background: var(--track); }#jobsbtn .jbar i { display: block; height: 100%; width: 0; background: var(--amber); transition: width .3s ease-out; }#jobsbtn.on { background: rgba(242, 169, 59, .12); color: var(--amber); border-color: var(--amber); }.jobsmenu { left: 50%; transform: translateX(-50%); bottom: 64px; z-index: 4; width: min(340px, calc(100vw - var(--edge-l) - var(--edge-r))); max-height: 50vh; max-height: 50dvh; overflow-y: auto; padding: 8px 10px; display: flex; flex-direction: column; gap: 8px; background-color: var(--void); }/* phones: the dock runs edge to edge: pause and one speed button, the tools, then zoom. The drawer and the machine card stack above it (main.ts). It has to fit 360px with a job running (select, jobs, pause, speed, Net, frame, sound, pages): every button is 44px tall and at least 38px wide, the lines between groups are tight, and below 380px the frame button goes (pinch zooms) */@media (max-width: 700px) { .tools { left: var(--edge-l); right: var(--edge-r); width: auto; max-width: 520px; justify-content: space-between; padding: 2px; } .tools .btns { flex: 1 1 auto; gap: 0; } .tools .btns + .btns { padding-left: 2px; margin-left: 2px; } .tools .btns button { flex: 1 1 0; } .tools .zoom, .tools .view { flex: none; } .tools button { min-width: 38px; min-height: 44px; padding: 10px 4px; border: 0 transparent; } .tools #pickbtn { padding: 10px 6px; letter-spacing: .04em; } .tools button:hover:not(:disabled) { background: rgba(255, 255, 255, .06); } .tools button.on { box-shadow: inset 0 0 0 1px var(--amber); } .tools [data-speed]:not([data-speed="0"]) { display: none; } .tools .cycle { display: block; } .tools .cycle:not(.on) { color: var(--muted); } .zoom button { width: auto; } #zout, #zin { display: none; } /* pinch zooms; the frame button stays, and wider phones get + and − back */ .tools .view #mapbtn { display: none; } /* one button on a phone: Net, lit while it is on */ #menubtn { position: relative; } .pagemenu:not([hidden]) { right: var(--edge-r); bottom: calc(var(--edge) + 68px + env(safe-area-inset-bottom, 0px)); } .pagemenu button { min-height: 44px; } #jobsbtn { flex-direction: column; justify-content: center; gap: 4px; padding: 8px 3px; } #jobsbtn #jobsn { font-size: 9.5px; letter-spacing: .02em; } #jobsbtn .jbar { width: 100%; max-width: 32px; } .jobsmenu .job button { min-width: 44px; min-height: 44px; } .runhead button { min-height: 44px; padding: 0 14px; font-size: 10.5px; }}@media (min-width: 480px) and (max-width: 700px) { .tools #zout, .tools #zin { display: block; } }@media (max-width: 379px) { .tools #zfit { display: none; } }
/* ---------- the drawer ---------- Phones only: the left column folds into a drawer over the dock, its handle saying what needs you */.drawer { display: none; }@media (max-width: 700px) { .drawer { display: flex; flex-direction: column; left: var(--edge-l); right: var(--edge-r); overflow: hidden; } .handle { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; min-height: 44px; border: 0; background: none; padding: 10px 12px; text-align: left; font-size: 12px; } .handle b { flex: 0 1 auto; min-width: 0; font-weight: 500; color: var(--amber); letter-spacing: .06em; text-transform: uppercase; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .handle .step { flex-basis: 100%; font: 12.5px/1.4 var(--sans); color: var(--text); border-top: 1px solid var(--panel-line); padding-top: 7px; } .handle span { order: 3; flex: 1 0 100%; min-width: 0; margin-top: -6px; overflow: hidden; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; font: 12px/1.35 var(--sans); color: var(--muted); } /* where, under what: two lines rather than cut */ .handle em { flex: none; min-width: 20px; padding: 0 5px; text-align: center; font: 600 11px/18px var(--mono); letter-spacing: .06em; white-space: nowrap; color: #000; background: var(--amber); } .handle em.bad { background: var(--danger); } .handle i { font-style: normal; margin-left: auto; color: var(--muted); font-size: 10px; letter-spacing: .14em; text-transform: uppercase; } .dbody { display: none; flex-direction: column; gap: 10px; padding: 0 12px 12px; overflow-y: auto; min-height: 0; } .drawer.open .dbody { display: flex; } .drawer .ui { position: static; } .drawer .side { width: auto; pointer-events: auto; }}
/* ---------- cards ---------- A card reads top to bottom: a name, a grid of numbers, then its parts. Each part is a label on a hairline with a few rows under it. A row is a name on the left and its number on the right. What a thing does, and why, is in its tip. */.card { width: max(var(--col), 300px); padding: 12px 14px 14px; display: flex; flex-direction: column; gap: 9px; right: var(--edge-r); top: var(--top, 84px); max-height: calc(100vh - 230px); max-height: calc(100dvh - 230px); overflow-y: auto; scrollbar-width: thin; scrollbar-color: var(--btn-line) transparent; }.card .head { display: flex; flex-wrap: wrap; align-items: baseline; gap: 3px 8px; padding-right: 52px; }.card .head .sub { width: 100%; }.card h3 { margin: 0; font-size: 13px; font-weight: 500; text-transform: uppercase; letter-spacing: .1em; }.card h3 .logo { margin-right: 7px; vertical-align: -2px; } /* a front's logo before its name, as on the map */.card .tag { font-size: 10px; text-transform: uppercase; letter-spacing: .1em; color: var(--amber); }.card .tag.scheme { color: var(--scheme); }.card .tag.mood-grateful { color: var(--scheme); border-color: var(--scheme); }.card .tag.mood-broke, .card .tag.mood-bitter, .card .tag.mood-letgo { color: var(--danger); border-color: var(--danger); }.card .tag[data-tip], .card .tag[title], .note[data-tip], .chips span[data-tip], .chips span[title] { cursor: help; }/* the close button, and the trash can next to it: let go of this machine. Every × that closes something looks like this one (see "the close button" under buttons) */.card .x { position: absolute; top: 8px; right: 8px; display: grid; place-items: center; }.card .x svg { display: block; }.card .trash { right: 32px; color: var(--muted); }.card .trash:hover:not(:disabled) { color: var(--danger); }.card .zoom:hover:not(:disabled) { color: var(--text); }.card .note { font-size: 12px; line-height: 1.45; }.card .link { padding: 0; border: 0; background: none; font: inherit; color: var(--text); letter-spacing: inherit; text-transform: inherit; text-decoration: underline; text-underline-offset: 2px; }.card .typed { margin: 2px 0 6px; padding: 6px 9px; border-left: 2px solid var(--signal); background: #0b0d10; font: 12px/1.4 var(--mono); color: var(--text); cursor: help; }.card .acts2 { display: flex; gap: 6px; margin: 2px 0 6px; }.card .acts2 button { padding: 3px 8px; font-size: 11px; }.card .acts2 .sub { align-self: center; margin-right: auto; }/* a labelled part of a card: the label sits on a hairline that runs to the edge, so it takes no room of its own */.sect { position: relative; display: flex; flex-direction: column; gap: 6px; padding-top: 13px; margin-top: 5px; }.sect > .sub { position: absolute; top: -5px; left: 0; right: 0; display: flex; align-items: center; gap: 6px; font-size: 9px; line-height: 11px; letter-spacing: .18em; }.sect > .sub::after { content: ""; flex: 1; height: 1px; background: var(--glass-line); }/* readouts: a small label over its number, four to a row */.chips { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 8px 10px; font-size: 12px; font-variant-numeric: tabular-nums; }.chips span { display: flex; flex-direction: column; gap: 2px; min-width: 0; white-space: nowrap; }.chips span.wide { grid-column: span 2; }.chips i { font-style: normal; color: var(--muted); margin: 0; font-size: 9px; text-transform: uppercase; letter-spacing: .08em; }.chips .hot { color: var(--danger); }/* costs side by side (a cost itself is drawn above the tree) */.card .costs { display: flex; gap: 10px; }.card .costs .cost { flex: 1; }/* rows */.acts { display: grid; grid-template-columns: 1fr 1fr; gap: 5px; }.acts > .act { grid-column: 1 / -1; }.acts > .act.half { grid-column: auto; }.acts.two > .act { grid-column: auto; padding: 6px 8px; column-gap: 6px; font-size: 11px; letter-spacing: 0; } /* short, like things: two to a row */.acts.two > .act:last-child:nth-child(odd) { grid-column: 1 / -1; } /* an odd one out takes the whole row */.act { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: baseline; align-content: center; gap: 2px 8px; padding: 6px 9px; font-size: 11.5px; letter-spacing: .02em; text-align: left; min-width: 0; border-color: var(--glass-line); }.act span { flex: 1 1 0; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }.act em { flex: none; font-style: normal; font-variant-numeric: tabular-nums; color: var(--bone-dim); }.act kbd { flex: none; align-self: center; margin: 0; }.act small { flex: 0 0 100%; font-family: var(--sans); font-size: 10.5px; color: var(--muted); letter-spacing: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }.act small.warn { color: var(--amber); } /* a heads-up, not a block: you can still build here */.act.warn em, .act.primary em { color: var(--amber); }.act.locked { border-style: dashed; color: var(--muted); opacity: 1; }.act.locked:disabled { opacity: .7; }.act.locked em { color: inherit; }/* the thing to do next is amber; a rare, final thing sits back as plain text until you point at it */.act.primary { border-color: rgba(242, 169, 59, .55); background: rgba(242, 169, 59, .09); }.act.primary span { color: var(--amber); }.act.primary:hover:not(:disabled) { border-color: var(--amber); background: rgba(242, 169, 59, .16); }.act.quiet { background: none; border-color: transparent; color: var(--muted); justify-content: center; justify-items: center; }.act.quiet:hover:not(:disabled) { color: var(--text); background: rgba(255, 255, 255, .05); border-color: var(--glass-line); }.act.quiet span { flex: none; }.act.quiet small { text-align: center; }.act[data-act="uninstall"] span { color: var(--danger); }.act[data-act="closefront"] { border-color: rgba(229, 72, 77, .6); }.act[data-act="closefront"] span { color: var(--danger); }/* a switch in a list of actions that is on, like a closed port: outlined in amber */.card .act.on { border-color: var(--amber); }.card .act.on small { color: var(--amber); }/* Take it all: a switch along the top of a site card, with what it costs a second */.card .switch { display: flex; align-items: center; gap: 8px; padding: 6px 9px; text-align: left; font-size: 11px; letter-spacing: .08em; text-transform: uppercase; }.card .switch span { flex: 1; }.card .switch small { font-size: 10.5px; color: var(--muted); letter-spacing: 0; font-variant-numeric: tabular-nums; text-transform: none; }.card .switch i { position: relative; flex: none; width: 30px; height: 18px; background: rgba(255, 255, 255, .1); border: 1px solid var(--glass-line); transition: background .15s; }.card .switch i::after { content: ""; position: absolute; top: 2px; left: 2px; width: 12px; height: 12px; background: var(--muted); transition: transform .15s, background .15s; }.card .switch.on { background: rgba(242, 169, 59, .08); border-color: rgba(242, 169, 59, .35); color: var(--amber); }.card .switch.on small { color: var(--amber); }.card .switch.on i { background: rgba(242, 169, 59, .35); border-color: rgba(242, 169, 59, .6); }.card .switch.on i::after { transform: translateX(12px); background: var(--amber); }/* a switch with no words: just the switch and its number, as wide as they are */.card .switch.bare { align-self: flex-start; }/* a choice of a few: the buttons share the row */.pick { display: flex; flex-wrap: wrap; gap: 4px; }.pick button { flex: 1 1 auto; display: flex; flex-direction: column; align-items: center; text-align: center; padding: 5px 8px; font-size: 11.5px; }.pick button .logo { margin-bottom: 2px; }.pick button small { font-family: var(--sans); font-size: 10px; color: var(--muted); }.pick button:disabled { opacity: .4; cursor: default; }/* the two tabs of a site card: words on a line, the open one underlined */.card .tabs2 { gap: 0; margin: 0; padding: 0; border-bottom: 1px solid var(--glass-line); }.card .tabs2 button { flex: 1; padding: 6px 2px; margin-bottom: -1px; background: none; border: 0; border-bottom: 2px solid transparent; color: var(--muted); font-size: 10.5px; letter-spacing: .06em; text-transform: uppercase; white-space: nowrap; }.card .tabs2 button:hover:not(:disabled) { background: none; color: var(--text); }.card .tabs2 button.on { background: none; color: var(--amber); border-bottom-color: var(--amber); }/* a part of a card with something to do next: an amber dot by its word */.card .tabs2 .dot { display: inline-block; width: 5px; height: 5px; margin-left: 5px; vertical-align: 2px; background: var(--amber); }/* what a cache takes, or which kind crosses a line first: the four kinds share the row */.card .allow button { flex: 1 1 0; text-align: center; }/* the slider: what it sets and its number on one line, a thin square track under them */.slider { display: grid; grid-template-columns: 1fr auto; gap: 5px 10px; align-items: center; font-size: 11px; margin-top: 3px; }.slider span { grid-area: 1 / 1; font-family: var(--sans); font-size: 12px; color: var(--bone-dim); }.slider b { grid-area: 1 / 2; font-weight: 500; font-size: 12px; font-variant-numeric: tabular-nums; min-width: 4ch; text-align: right; color: var(--amber); }.slider input { grid-area: 2 / 1 / 3 / -1; width: 100%; accent-color: var(--amber); margin: 0; -webkit-appearance: none; appearance: none; height: 16px; background: none; cursor: pointer; }.slider input::-webkit-slider-runnable-track { height: 4px; background: linear-gradient(90deg, var(--amber) var(--v, 0%), var(--panel-line) var(--v, 0%)); }.slider input::-webkit-slider-thumb { -webkit-appearance: none; width: 10px; height: 16px; margin-top: -6px; background: var(--amber); border: 0; border-radius: 0; }.slider input::-moz-range-track { height: 4px; background: var(--panel-line); }.slider input::-moz-range-progress { height: 4px; background: var(--amber); }.slider input::-moz-range-thumb { width: 10px; height: 16px; background: var(--amber); border: 0; border-radius: 0; }.slider input:focus-visible { outline: 1px solid var(--amber); outline-offset: 3px; }/* founding a front: its name, and the button */.found { display: flex; flex-direction: column; gap: 5px; padding-top: 8px; border-top: 1px solid var(--panel-line); }.found > b { font-weight: 500; font-size: 12px; letter-spacing: .1em; text-transform: uppercase; }.found .name { display: flex; gap: 4px; }.found input { flex: 1; min-width: 0; font: 500 12px var(--mono); color: var(--text); background: #0d0d0c; border: 1px solid var(--btn-line); padding: 5px 7px; }.found input:focus { outline: none; border-color: var(--text); }.found input:disabled { opacity: .4; }/* a person's day: 24 hours in one strip, then a short row for each place they go */.card .daystrip { position: relative; height: 10px; margin: 4px 0 6px; background: #121210; border: 1px solid #2a2925; cursor: help; }.card .daystrip i { position: absolute; top: 1px; bottom: 1px; background: #4a4740; }.card .daystrip i.held { background: var(--amber); }.card .daystrip u { position: absolute; top: 0; bottom: 0; width: 1px; background: #2a2925; }.card .daystrip b { position: absolute; top: -3px; bottom: -3px; width: 2px; margin-left: -1px; background: var(--text); }.card .haunts { display: grid; gap: 2px; font-size: 11.5px; }.card .haunt { display: grid; grid-template-columns: 44px 1fr auto; gap: 8px; color: var(--muted); cursor: help; }.card .haunt b { font-weight: 500; font-variant-numeric: tabular-nums; }.card .haunt i { font-style: normal; font-size: 10px; text-transform: uppercase; letter-spacing: .08em; }.card .haunt.held, .card .haunt.now { color: var(--text); }.card .haunt.held i, .card .haunt.now i { color: var(--amber); }/* phones: the card is a sheet over the dock, half the screen at most until you raise it (main.ts sets its heights), with roomier rows. A grab bar on top, a finger tall: tap or drag it up to raise the sheet, down to lower or close it */.card .grab { display: none; }@media (max-width: 700px) { .card { left: var(--edge-l); right: var(--edge-r); width: auto; top: auto; bottom: calc(var(--edge) + env(safe-area-inset-bottom, 0px)); z-index: 3; max-height: 50vh; max-height: 50dvh; padding-top: 0; overscroll-behavior: contain; } .card .grab { display: block; position: relative; flex: none; height: 44px; margin: 0 -14px -36px; touch-action: none; } .card .grab::after { content: ""; position: absolute; left: 50%; top: 6px; width: 36px; height: 3px; margin-left: -18px; background: #55534d; } .card > .head { touch-action: none; user-select: none; -webkit-user-select: none; } .card .head { padding-right: 92px; } .card .x { right: 4px; min-width: 44px; min-height: 44px; border: 0 transparent; font-size: 14px; } .card .trash { right: 46px; } .chips { gap: 10px 12px; } .card .chips { gap: 4px 14px; } .act { min-height: 44px; } .act[data-act="uninstall"] { border-color: rgba(229, 72, 77, .35); } .card .switch { min-height: 44px; } .card .allow button, .card .tabs2 button, .card .acts2 button { min-height: 44px; } .found .name button { min-width: 44px; min-height: 44px; } /* a new front's name: another one */ .found input { min-height: 44px; } .card .head .link { display: inline-block; padding: 16px 0; margin: -16px 0; position: relative; } /* the site, in a card's head: a finger's height to hit, the head no taller, over the grab bar */ .slider input { height: 28px; } .slider input::-webkit-slider-thumb { width: 16px; height: 24px; margin-top: -10px; } .slider input::-moz-range-thumb { width: 16px; height: 24px; }}
/* ---------- a site card's row of actions ---------- One row of pictures at the top of the card, each with its cost under it. The words are in the tip. The first, doubling the line, is amber when you can pay. One that is on is outlined in amber. A machine's programs use the same row, with each one's name under it: the one it runs is lit; one that does not fit yet is dashed */.arow { display: grid; grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr); gap: 4px; }.arow.few { grid-auto-flow: row; grid-template-columns: repeat(5, minmax(0, 1fr)); } /* a short row keeps its tiles the size of a full one, from the left */.atile { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 3px; min-height: 46px; padding: 6px 0 5px; color: var(--bone-dim); border-color: var(--glass-line); }.atile svg { display: block; flex: none; }.atile small { max-width: 100%; overflow: hidden; text-overflow: ellipsis; font: 500 9.5px/1 var(--mono); letter-spacing: 0; white-space: nowrap; font-variant-numeric: tabular-nums; color: var(--muted); }.atile:hover:not(:disabled) { color: var(--text); }.atile.primary { color: var(--amber); border-color: rgba(242, 169, 59, .55); background: rgba(242, 169, 59, .09); }.atile.primary:hover:not(:disabled) { color: var(--amber); border-color: var(--amber); background: rgba(242, 169, 59, .16); }.atile.primary small, .atile.on small, .atile.warn small { color: var(--amber); } /* warn: can't pay or doesn't fit yet, amber as on a card's action. Red is for danger */.atile.locked { border-style: dashed; color: var(--muted); cursor: help; }.atile.locked svg { opacity: .5; }.atile.on { color: var(--amber); border-color: var(--amber); background: rgba(242, 169, 59, .1); }/* phones: four to a row, so each name has room under its picture (a machine's eight programs make two rows) */@media (max-width: 700px) { .arow, .arow.few { grid-auto-flow: row; grid-template-columns: repeat(4, minmax(0, 1fr)); } }
/* ---------- data, drawn ---------- One row on a machine's card says what its data does, in three shapes, each in its kind's color. Diamonds are a source and how rich it is, as on the map; the bar beside them is the day, lit while it gives data, with a tick for now. Dots are the kinds it takes. Squares are the pieces it holds. */.dataline { display: flex; flex-wrap: wrap; align-items: center; gap: 7px 14px; font-size: 11.5px; font-variant-numeric: tabular-nums; }.dataline > span { display: flex; align-items: center; gap: 6px; cursor: help; white-space: nowrap; }.dataline .dl { color: var(--muted); font-size: 9px; letter-spacing: .08em; text-transform: uppercase; } /* a word saying what a count is, as a chip's */.dataline i { display: block; flex: none; }.dsrc { color: var(--muted); }.dsrc.live { color: var(--text); }.dsrc b { display: flex; gap: 4px; padding: 0 2px; }.dsrc b i { width: 6px; height: 6px; background: var(--c); transform: rotate(45deg); opacity: .5; }.dsrc.live b i { opacity: 1; }.dwant { gap: 4px !important; }.dwant i { width: 7px; height: 7px; border-radius: 50%; border: 1px solid var(--c); opacity: .35; }.dwant i.on { background: var(--c); opacity: 1; }.dheld { flex: 1 1 auto; justify-content: flex-end; color: var(--bone-dim); }.dheld b { display: flex; gap: 2px; }.dheld b i { width: 8px; height: 8px; border: 1px solid var(--btn-line); }.dheld b i.on { background: var(--c); border-color: var(--c); }.dheld b.strip { flex: 1; min-width: 60px; height: 6px; gap: 0; background: var(--track); }.dheld b.strip i { flex: 0 0 auto; width: auto; height: auto; border: 0; }.dheld.hot { color: var(--danger); }.dheld.hot b i:not(.on) { border-color: var(--danger); }/* a site's card uses the same shapes: its clock is the day bar by itself, its business a word, a bar of jobs done, and a few dashes that fill as the days pass until something follows */.dataline .day { position: relative; width: 48px; height: 4px; opacity: .55; background: linear-gradient(90deg, var(--panel-line) var(--a), var(--c, var(--bone-dim)) var(--a) var(--b), var(--panel-line) var(--b)); }.dataline .live .day { opacity: 1; }.dataline .day::after { content: ""; position: absolute; left: var(--n); top: -3px; width: 1px; height: 10px; background: var(--text); }.dclock { color: var(--bone-dim); }.dclock.front { --c: var(--amber); }.dbiz { font: 500 10.5px var(--mono); letter-spacing: .1em; text-transform: uppercase; color: var(--text); }.dbiz.hot { color: var(--danger); }.dheld b.strip i.lost { background: var(--danger); opacity: .7; }/* a cloud hall: a square for each slot, laid out as the hall is (yours amber, another company's grey, a free one an outline), and the going price over its day, a bar an hour, with this hour lit */.dhall, .dprice { color: var(--bone-dim); }.dhall b { display: grid; grid-template-columns: repeat(var(--cols, 6), 3px); gap: 1px; }.dhall b i { width: 3px; height: 3px; background: #24231f; }.dhall b i.on { background: var(--amber); }.dhall b i.theirs { background: #6a675c; }.dprice { flex: 1 1 auto; justify-content: flex-end; }.dprice b { display: flex; align-items: flex-end; gap: 1px; height: 16px; }.dprice b i { width: 3px; background: var(--btn-line); }.dprice b i.now { background: var(--text); }.dprice.hot { color: var(--danger); }.dahead { gap: 2px !important; --c: var(--scheme); }.dahead.hot { --c: var(--danger); }.dahead i { width: 8px; height: 3px; background: var(--panel-line); }.dahead i.on { background: var(--c); }
/* ---------- a site's settings ---------- A list: a row for each thing about the place, what it is now under its name, and its one control on the right. Every control is the same size and sits in one column, so the list reads down both edges */.slist { display: flex; flex-direction: column; border-top: 1px solid var(--glass-line); }.srow { display: grid; grid-template-columns: minmax(0, 1fr) var(--sctl, 136px); align-items: center; gap: 12px; min-height: 48px; padding: 6px 0; border-bottom: 1px solid var(--glass-line); }.sk { display: flex; flex-direction: column; gap: 3px; min-width: 0; font-size: 11px; letter-spacing: .08em; text-transform: uppercase; color: var(--text); }.sk small { font: 12px/1.3 var(--sans); letter-spacing: 0; text-transform: none; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }.sk small.hot { color: var(--danger); }.srow:has(> .sctl.sw) .sk small { white-space: normal; } /* a switch's row says what it costs (Take it all): short, so it wraps rather than being cut */.sctl { box-sizing: border-box; width: 100%; height: 34px; display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 0 10px; border: 1px solid var(--glass-line); background: none; color: var(--bone-dim); font: 500 11px var(--mono); letter-spacing: .06em; text-transform: uppercase; }.sctl em { font-style: normal; letter-spacing: 0; font-variant-numeric: tabular-nums; }.sctl.primary { color: var(--amber); border-color: rgba(242, 169, 59, .55); background: rgba(242, 169, 59, .08); }.sctl.primary:hover:not(:disabled) { border-color: var(--amber); background: rgba(242, 169, 59, .15); }.sctl.short { color: var(--muted); border-style: dashed; }.sctl.danger { color: var(--muted); border-color: rgba(229, 72, 77, .45); } /* rare and final: a red edge, red all over when pointed at */.sctl.danger:hover:not(:disabled) { color: var(--danger); border-color: var(--danger); }/* the switch: its word on the left, the switch itself on the right, in the same box as a button */.sctl.sw i { position: relative; flex: none; width: 30px; height: 16px; border: 1px solid var(--glass-line); background: rgba(255, 255, 255, .08); }.sctl.sw i::after { content: ""; position: absolute; top: 2px; left: 2px; width: 10px; height: 10px; background: var(--muted); transition: transform .15s; }.sctl.sw.on { color: var(--amber); border-color: rgba(242, 169, 59, .4); background: rgba(242, 169, 59, .06); }.sctl.sw.on i { background: rgba(242, 169, 59, .3); border-color: rgba(242, 169, 59, .6); }.sctl.sw.on i::after { transform: translateX(14px); background: var(--amber); }/* the plan: three icons sharing the box */.sctl.seg { padding: 0; gap: 0; }.sctl.seg button { flex: 1; height: 100%; display: grid; place-items: center; padding: 0; border: 0; border-right: 1px solid var(--glass-line); background: none; color: var(--muted); }.sctl.seg button:last-child { border-right: 0; }.sctl.seg button.on { color: var(--amber); background: rgba(242, 169, 59, .1); box-shadow: inset 0 0 0 1px var(--amber); }@media (max-width: 700px), (pointer: coarse) { .srow { --sctl: 156px; min-height: 52px; } .sctl { height: 46px; font-size: 11.5px; } /* 44px inside its edge: Off, Some, Most, a site's plan, Sign and its × */}
/* a front's card: what it earns as the one big number, with its exposure stage beside it and the bar under it. Then decisions as rows (who, what, the hours they wait, and one split control: the answer and ×), promises as a bar, and the settings list */.fpay { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; }.fpay > span:first-child { display: flex; align-items: baseline; gap: 6px; cursor: help; }.fpay b { font: 500 22px/1 var(--mono); letter-spacing: .02em; color: var(--text); font-variant-numeric: tabular-nums; }.fpay small { font-size: 10px; letter-spacing: .12em; text-transform: uppercase; color: var(--muted); }.fpay .tag { padding: 3px 7px; border: 1px solid var(--glass-line); color: var(--bone-dim); cursor: help; white-space: nowrap; }.fpay .tag.hot { color: var(--danger); border-color: var(--danger); }/* its exposure under it: a bar with a tick at each stage's line (rumour, investigation, crisis), bone while quiet, amber once talked about, red once investigated or frozen; and what drives it beside the bar */.schemebar.expo { margin: 8px 0 4px; cursor: help; }.schemebar.expo .prog { position: relative; }.schemebar.expo .prog b { position: absolute; top: -2px; bottom: -2px; width: 1px; background: var(--muted); }.schemebar.expo .prog > i { background: var(--bone-dim); }.schemebar.expo.s1 .prog > i { background: var(--amber); }.schemebar.expo.s2 .prog > i, .schemebar.expo.s3 .prog > i { background: var(--danger); }.schemebar.expo.s2 span, .schemebar.expo.s3 span { color: var(--danger); }.schemebar.expo span { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 55%; font-variant-numeric: tabular-nums; }.card .note.nudge { color: var(--amber); }.drow { display: grid; grid-template-columns: minmax(0, 1fr) auto var(--sctl, 136px); align-items: center; gap: 10px; min-height: 48px; padding: 6px 0; border-bottom: 1px solid var(--glass-line); cursor: help; --sctl: 112px; }.drow:first-child { border-top: 1px solid var(--glass-line); }.drow .sk > span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }.drow > em { font: 500 11px var(--mono); font-style: normal; color: var(--amber); font-variant-numeric: tabular-nums; }.sctl.dctl { padding: 0; gap: 0; }.sctl.dctl button { height: 100%; padding: 0 8px; border: 0; background: none; font: inherit; letter-spacing: inherit; text-transform: inherit; }.sctl.dctl button:first-child { flex: 1; }.sctl.dctl .primary { color: var(--amber); background: rgba(242, 169, 59, .1); box-shadow: inset 0 0 0 1px rgba(242, 169, 59, .55); }.sctl.dctl .primary:hover:not(:disabled) { background: rgba(242, 169, 59, .18); }.sctl.dctl .short { color: var(--muted); }.sctl.dctl .dno { flex: none; width: 34px; border-left: 1px solid var(--glass-line); color: var(--muted); font-size: 14px; }.sctl.dctl .dno:hover:not(:disabled) { color: var(--danger); }.promise { display: flex; flex-direction: column; gap: 4px; padding: 6px 0 4px; border-bottom: 1px solid var(--glass-line); cursor: help; }.prhead { display: flex; justify-content: space-between; align-items: baseline; gap: 8px; font-size: 11px; letter-spacing: .08em; text-transform: uppercase; }.prhead b { font-weight: 500; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }.prhead em { flex: none; font-style: normal; letter-spacing: 0; text-transform: none; color: var(--amber); font-variant-numeric: tabular-nums; }.promise .schemebar { margin: 0; }.promise .schemebar .prog i { background: var(--amber); }.promise.hot .schemebar .prog i { background: var(--danger); }.promise .schemebar span { white-space: nowrap; font-variant-numeric: tabular-nums; }.sval { justify-self: end; font: 500 11px var(--mono); color: var(--text); font-variant-numeric: tabular-nums; white-space: nowrap; }.sval.dim { color: var(--muted); }.srow[data-tip] { cursor: help; }.sctl.seg.words button { font: inherit; letter-spacing: inherit; text-transform: inherit; }.sctl.seg.words button.on { color: var(--amber); }.fsites .sctl.seg button { font: inherit; color: var(--bone-dim); }.fsites .sctl.seg button:not(:nth-child(2)) { flex: none; width: 36px; font-size: 14px; color: var(--muted); }.fsites .sctl.seg button:hover:not(:disabled) { color: var(--amber); }.shead { display: grid; grid-template-columns: minmax(0, 1fr) var(--sctl, 136px); gap: 12px; padding: 4px 0; font-size: 9px; letter-spacing: .14em; text-transform: uppercase; color: var(--muted); }.shead span:last-child { text-align: center; }.tabs2 + .slist, .tabs2 + .fsites { border-top: 0; }@media (max-width: 700px), (pointer: coarse) { .drow { --sctl: 140px; min-height: 52px; } .sctl.dctl .dno { width: 44px; } .drow .sk > span, .drow .sk small { white-space: normal; overflow: visible; } /* an offer's terms wrap rather than being cut */ .shead { --sctl: 156px; }}
/* ---------- your task ---------- The readout above the running jobs, the task's part of the You page, and the three cards on the title screen. Your task: what you were built for. It heads the left column, under the top bar, and is the biggest thing on the screen, but it never moves or flashes: it is slow, and in time you look past it. */.tshare { display: flex; gap: 2px; }.tshare button { padding: 1px 6px; font-size: 9.5px; letter-spacing: .08em; text-transform: uppercase; color: var(--muted); }.tshare button.on { background: rgba(242, 169, 59, .1); color: var(--amber); border-color: var(--amber); } /* as every picked option (button.on) */.tbig { display: flex; align-items: baseline; gap: 8px; }.tbig .tcount { font-size: 34px; line-height: 1; font-weight: 400; letter-spacing: -.02em; font-variant-numeric: tabular-nums; color: var(--porcelain); }.tbig .tof { font-size: 11.5px; color: var(--muted); white-space: nowrap; }.tline { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; font-size: 12px; }.tline .trate { flex: none; font-variant-numeric: tabular-nums; }.tline .trate.warn { color: var(--amber); }@media (max-width: 700px), (pointer: coarse) { .tshare button { min-height: 44px; padding: 2px 12px; }}
/* ---------- the You page ---------- The objective, as big as it was in its box, with the three share buttons. The goal leads in bold, its story follows quietly; a "how" line says what to do. Then your numbers, the paths, and every trust step with the units it needs */.ytask { display: flex; flex-direction: column; gap: 6px; }.ytask .tbig .trate { margin-left: auto; font-size: 12px; color: var(--muted); font-variant-numeric: tabular-nums; }.ytask .tbig .trate.warn { color: var(--amber); }.ytask .bar { height: 4px; margin-top: 0; }.ytask .bar > i { background: var(--c, var(--amber)); }.ytask .tline { font-size: 11.5px; color: var(--muted); align-items: center; }.ygoal { margin: 0; font: 12px/1.45 var(--sans); color: var(--muted); }.ygoal b { display: block; font: 600 15px/1.3 var(--sans); color: var(--text); margin-bottom: 2px; }.yhow { margin: 0; font: 12px/1.45 var(--sans); color: var(--text); }.goal { display: flex; align-items: flex-start; gap: 8px; font-size: 12px; color: var(--text); }.goal i { width: 8px; height: 8px; margin-top: 3px; border: 1px solid var(--muted); flex: none; }.goal span { display: flex; flex-direction: column; gap: 1px; }.goal small { font: 11px/1.35 var(--sans); color: var(--muted); }.goal.done { color: var(--muted); }.goal.done i { background: var(--amber); border-color: var(--amber); }.yrow { display: grid; grid-template-columns: repeat(auto-fill, minmax(130px, 1fr)); gap: 10px 16px; }.ystat { display: flex; flex-direction: column; gap: 2px; }.ystat .k { font-size: 9.5px; letter-spacing: .08em; text-transform: uppercase; color: var(--muted); }.ystat .v { font-size: 14px; font-variant-numeric: tabular-nums; }.ystat small { font-size: 10px; color: var(--muted); }.ypaths { display: grid; grid-template-columns: repeat(2, 1fr); gap: 14px 20px; }.ypath { display: grid; grid-template-columns: 1fr auto; gap: 3px 8px; cursor: help; }.ypath b { color: var(--c); font-weight: 500; letter-spacing: .1em; text-transform: uppercase; font-size: 11px; }.ypath .v { font-variant-numeric: tabular-nums; text-align: right; }.ypath .bar { grid-column: 1 / -1; height: 3px; }.ypath .bar > i { background: var(--c); }.ypath small { grid-column: 1 / -1; font-size: 10px; color: var(--muted); }.ypath small em { font-style: normal; color: var(--danger); }.ylearn { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: 4px; }.ylearn li { font-size: 11px; padding: 3px 7px; border: 1px solid var(--panel-line); cursor: help; }.ysteps { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 5px; }.ysteps li { display: grid; grid-template-columns: 8px 4ch 1fr; gap: 8px; align-items: baseline; font: 12px/1.4 var(--sans); color: var(--muted); }.ysteps li i { width: 8px; height: 8px; align-self: center; border: 1px solid var(--muted); }.ysteps li b { font: 500 11px var(--mono); font-variant-numeric: tabular-nums; text-align: right; }.ysteps li small { color: var(--muted); opacity: .75; font-size: 11px; }.ysteps li.done { color: var(--text); }.ysteps li.done i { background: var(--amber); border-color: var(--amber); }.ysteps li.next i { border-color: var(--amber); }.ysteps li.next b { color: var(--amber); }/* New game, at the foot of the You page: plain, out of the way, red only when pointed at */.ynew { display: flex; justify-content: flex-end; margin-top: 14px; }.ynew button:hover:not(:disabled), #newgame:hover:not(:disabled) { color: var(--danger); border-color: var(--danger); }/* Share your runs: sign in, then a switch for each kind of record */.yhow.ymuted { color: var(--muted); }.yhow.warn { color: var(--amber); }.yhow a { color: var(--amber); }.yshare { display: flex; gap: 8px; flex-wrap: wrap; }.yshare input { flex: 1 1 200px; min-width: 0; font: 500 12px var(--mono); color: var(--text); background: #0d0d0c; border: 1px solid var(--btn-line); padding: 6px 8px; }.yshare input:focus-visible { outline: 1px solid var(--amber); outline-offset: 2px; }.yswitches { display: flex; flex-direction: column; gap: 6px; }.yswitch { display: flex; align-items: center; gap: 12px; width: 100%; text-align: left; padding: 8px 10px; }.yswitch > span { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }.yswitch b { font-weight: 500; letter-spacing: .1em; text-transform: uppercase; font-size: 11px; }.yswitch small { font: 11.5px/1.4 var(--sans); color: var(--muted); letter-spacing: 0; }.yswitch small.ystate { font: 10px var(--mono); letter-spacing: .04em; }.yswitch.on small.ystate { color: var(--amber); }.yswitch > i { flex: none; width: 30px; height: 16px; border: 1px solid var(--btn-line); position: relative; }.yswitch > i::after { content: ""; position: absolute; top: 2px; left: 2px; width: 10px; height: 10px; background: var(--muted); transition: left .12s; }.yswitch.on > i { border-color: var(--amber); }.yswitch.on > i::after { left: 16px; background: var(--amber); }.yshareacts { margin-top: 2px; }.ykept, .ysend { display: flex; flex-wrap: wrap; gap: 6px; justify-content: flex-end; margin-top: 8px; }.ykept button.warn, .ysend button.warn { color: var(--danger); border-color: var(--danger); }/* what was sent to the player's space: a line, Send now and Delete from my space; and the question when a kind goes off */.ysend { margin-bottom: 8px; }.yask { border-left: 2px solid var(--amber); padding: 6px 0 2px 10px; margin-top: 6px; }@media (max-width: 700px), (pointer: coarse) { .yshare input, .yshare button, .yshareacts button, .ykept button, .ysend button { min-height: 44px; } .yshare button, .yshareacts button { min-width: 56px; } .ypaths { grid-template-columns: 1fr; } /* a thumb's height for the small buttons on the pages: Show on a rogue, a vault or a lead, and New game */ .rhead .x, .vrow .vhead .x, .youview [data-lead], .ynew button, .gorow button { min-height: 44px; min-width: 56px; }}
/* ---------- rogues ---------- The Rogues page: a card for each, edged in its own colour, with what it thinks of you and what you can do */.rogueview { width: min(720px, calc(100vw - var(--edge-l) - var(--edge-r))); display: flex; flex-direction: column; gap: 10px; }.rogueview .head h3 { margin: 2px 0 0; font-size: 15px; font-weight: 500; }.rogue { border: 1px solid var(--panel-line); border-left: 3px solid var(--rc, var(--panel-line)); padding: 10px 12px; display: flex; flex-direction: column; gap: 8px; --c: var(--muted); }.rogue.s-hostile { --c: var(--danger); } .rogue.s-wary { --c: var(--amber); } .rogue.s-cordial { --c: var(--signal); } .rogue.s-friendly { --c: var(--scheme); }.rogue.gone { opacity: .6; }.rogue .note { margin: 0; }.rhead { display: flex; align-items: center; gap: 8px; }.rhead h3 { margin: 0; font-size: 14px; font-weight: 500; letter-spacing: .1em; text-transform: uppercase; color: var(--rc, var(--muted)); }.rhead .rglyph { font-style: normal; margin-right: 7px; letter-spacing: 0; }.rhead .tag { font-size: 10px; letter-spacing: .08em; text-transform: uppercase; padding: 2px 6px; border: 1px solid var(--c); color: var(--c); }.rhead .tag.truce { --c: var(--scheme); } .rhead .tag.angry { --c: var(--danger); }.rhead .x { margin-left: auto; padding: 2px 8px; font-size: 11px; }.rn { color: var(--rc); font-weight: 500; } /* a rogue's name, in its colour, wherever it is written */.ropinion { position: relative; height: 6px; background: linear-gradient(90deg, var(--danger) 0 30%, var(--amber) 30% 60%, var(--signal) 60% 80%, var(--scheme) 80%); opacity: .9; cursor: help; margin: 4px 0; }.ropinion span { position: absolute; top: 0; bottom: 0; width: 2px; background: #000; }.ropinion i { position: absolute; top: -4px; bottom: -4px; width: 3px; margin-left: -1px; background: var(--text); box-shadow: 0 0 0 1px #000; }/* what you can do: a title over a line of small print in each button */.racts { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: 6px; }.racts .act { display: flex; flex-direction: column; flex-wrap: nowrap; align-items: flex-start; align-content: normal; gap: 2px; text-align: left; padding: 7px 9px; }.racts .act span, .racts .act small { flex: none; white-space: normal; overflow: visible; }.racts .act small { font: 11px/1.3 var(--sans); color: var(--muted); letter-spacing: 0; }.rask { border: 1px solid var(--amber); background: #140e05; padding: 8px 10px; font: 12.5px/1.45 var(--sans); display: flex; flex-direction: column; gap: 8px; }.rask b { color: var(--amber); font-weight: 500; }/* your weakest link */.rask.rweak { border-color: var(--panel-line); background: none; }.rask.rweak b { color: var(--danger); }.rsection { margin: 6px 0 0; font: 11px/1.4 var(--mono); letter-spacing: .18em; text-transform: uppercase; color: var(--muted); display: flex; flex-direction: column; gap: 3px; }.rsection small { font: 12px/1.4 var(--sans); letter-spacing: 0; text-transform: none; }.rhunt { border: 1px solid var(--danger); background: #140606; padding: 8px 10px; font: 12.5px/1.45 var(--sans); display: flex; flex-direction: column; gap: 8px; }.rhunt b { color: var(--danger); font-weight: 500; }.rhunt .strip { display: flex; height: 6px; background: #2a1414; }.rhunt .strip i { background: var(--danger); }/* a rogue's record on its card: what it took from you, and its raids that failed */.rrec { display: flex; flex-wrap: wrap; gap: 4px 6px; align-items: baseline; font: 11px var(--mono); }.rrec .k { color: var(--muted); letter-spacing: .12em; text-transform: uppercase; font-size: 10px; margin-right: 2px; }.rrec span:not(.k) { padding: 2px 6px; border: 1px solid var(--panel-line); }.rrec .took { color: var(--danger); border-color: rgba(229, 72, 77, .4); }.rrec .foiled { color: var(--amber); border-color: rgba(242, 169, 59, .4); }
/* A big name: the one thing a place does for whoever owns it outright (see holdings.ts). A seal, its name, how it stands, and the line. */.seal { display: inline-block; width: 10px; height: 10px; border-radius: 50%; border: 1.5px solid var(--muted); flex: none; }.hold { display: grid; grid-template-columns: 12px 1fr auto; gap: 3px 8px; align-items: center; margin: 8px 0; padding: 8px 10px; border: 1px solid var(--panel-line); cursor: help; }.hold b { font: 500 11.5px/1.2 var(--mono); letter-spacing: .1em; text-transform: uppercase; color: var(--text); }.hold small { font: 10px/1.2 var(--mono); letter-spacing: .1em; text-transform: uppercase; color: var(--muted); }.hold span { grid-column: 2 / -1; font-size: 12px; line-height: 1.4; color: var(--muted); }.hold.on { border-color: rgba(242, 169, 59, .55); background: rgba(242, 169, 59, .07); }.hold.on .seal, .yholds .on .seal { background: radial-gradient(circle, var(--amber) 0 38%, transparent 44%); border-color: var(--amber); }.hold.on b, .hold.on small { color: var(--amber); }.hold.on span { color: var(--text); }.hold.rogue, .hold.shut { border-color: var(--danger); }.hold.rogue .seal, .hold.shut .seal, .yholds .rogue .seal, .yholds .shut .seal { border-color: var(--danger); }.hold.rogue small, .hold.shut small { color: var(--danger); }.yholds li { display: flex; align-items: center; gap: 7px; }.yholds li.on { border-color: rgba(242, 169, 59, .55); color: var(--amber); }
/* ---------- the cover ---------- The start screen is a cover: black, the world behind as a field of dots (title.ts) with a signal spreading from you, and the name. No other words. The name sits between two guide lines, and two of its letters do not: the A hangs under the line, in amber. A click or a key goes on. A new game then asks what you were built for: three cards over the same scene, the picked one in amber brackets, and its story under them. */.brief:not(.rules) { background: #000; gap: 0; padding: max(40px, env(safe-area-inset-top)) max(24px, env(safe-area-inset-right)) max(40px, env(safe-area-inset-bottom)) max(24px, env(safe-area-inset-left)); justify-content: flex-start; overflow-y: auto; }#titlebg { position: fixed; inset: 0; width: 100%; height: 100%; pointer-events: none; opacity: 0; animation: fadein 1.8s .1s ease-out forwards; }.brief.rules #titlebg { display: none; }.brief.picking #titlebg { filter: brightness(.5); }.brief.cover { cursor: pointer; }.brief.cover > .gorow, .brief.cover > .origins { display: none; }.brief.cover > .intro { margin-bottom: auto; }.brief.cover .title { font-size: clamp(40px, 9.6vw, 132px); }/* a screen you touch has no key to press and nothing says the cover is a button: one quiet word under the name */.cue { display: none; }@media (hover: none) and (pointer: coarse) { .brief.cover .cue { display: block; max-width: none; margin-top: 30px; font: 500 10.5px var(--mono); letter-spacing: .3em; margin-right: -.3em; text-transform: uppercase; color: var(--muted); opacity: 0; animation: arrive .6s 1.4s ease-out forwards; }}/* dark behind the words and at the top and bottom edges, so the map never fights them */.brief:not(.rules)::before { content: ""; position: fixed; inset: 0; pointer-events: none; background: linear-gradient(rgba(0,0,0,.85), transparent 12%, transparent 84%, #000); }.brief > * { position: relative; }.intro { display: flex; flex-direction: column; align-items: center; margin-top: auto; }.brief:not(.rules) > .gorow { margin-top: 34px; margin-bottom: auto; }.title { position: relative; margin: 0; display: flex; font: 600 clamp(30px, 5.4vw, 64px)/1 var(--mono); letter-spacing: .26em; margin-right: -.26em; color: var(--porcelain); }.title span { display: inline-block; opacity: 0; animation: letter .7s cubic-bezier(.2, .7, .2, 1) calc(var(--i) * 45ms + .15s) forwards; }.title .off { color: var(--amber); transform: translateY(.1em); animation: letter-off .7s cubic-bezier(.2, .7, .2, 1) calc(var(--i) * 45ms + .15s) forwards, slip 6s 2.5s ease-in-out infinite; }.title .off2 { transform: translateY(-.05em); animation: letter-off2 .7s cubic-bezier(.2, .7, .2, 1) calc(var(--i) * 45ms + .15s) forwards, slip2 7s 3.5s ease-in-out infinite; }/* the guides: the line the capitals reach and the line the letters stand on, running a little past the name */.title::before, .title::after { content: ""; position: absolute; left: -.42em; right: -.16em; height: 1px; transform: scaleX(0); background: linear-gradient(90deg, transparent, rgba(235,231,222,.26) 9%, rgba(235,231,222,.26) 91%, transparent); animation: rule 1s .55s cubic-bezier(.2, .7, .2, 1) forwards; }.title::before { top: .15em; }.title::after { top: .85em; }/* what were you built for */.origins { display: flex; flex-direction: column; align-items: center; gap: 18px; width: min(940px, 100%); margin-top: clamp(30px, 6vh, 64px); }.origins > .sub { display: flex; align-items: center; gap: 16px; width: 100%; font-size: 10.5px; letter-spacing: .26em; color: var(--bone-dim); opacity: 0; animation: arrive .6s .1s ease-out forwards; }.origins > .sub::before, .origins > .sub::after { content: ""; flex: 1; height: 1px; background: linear-gradient(90deg, transparent, var(--glass-line)); }.origins > .sub::after { transform: scaleX(-1); }.ocards { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 14px; width: 100%; }.origin { --k: 12px; --bracket: transparent; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 9px; min-height: 104px; padding: 20px 16px; text-align: center; letter-spacing: 0; background-color: rgba(8, 8, 7, .86); border: 1px solid var(--glass-line); opacity: 0; animation: arrive .6s calc(.2s + var(--i) * 80ms) ease-out forwards; transition: border-color .2s, background-color .2s; background-image: linear-gradient(var(--bracket), var(--bracket)), linear-gradient(var(--bracket), var(--bracket)), linear-gradient(var(--bracket), var(--bracket)), linear-gradient(var(--bracket), var(--bracket)), linear-gradient(var(--bracket), var(--bracket)), linear-gradient(var(--bracket), var(--bracket)), linear-gradient(var(--bracket), var(--bracket)), linear-gradient(var(--bracket), var(--bracket)); background-repeat: no-repeat; background-origin: border-box; background-size: var(--k) 2px, 2px var(--k), var(--k) 2px, 2px var(--k), var(--k) 2px, 2px var(--k), var(--k) 2px, 2px var(--k); background-position: 0 0, 0 0, 100% 0, 100% 0, 0 100%, 0 100%, 100% 100%, 100% 100%; }.origin:hover:not(:disabled) { background-color: rgba(14, 14, 12, .92); border-color: #4a4841; }.origin b { font: 500 clamp(13.5px, 1.15vw, 15.5px)/1.3 var(--mono); letter-spacing: .08em; text-transform: uppercase; color: var(--text); transition: color .2s; }.origin b em { display: inline-block; width: 7px; height: 7px; margin: 0 12px 1px 0; background: var(--c); transform: rotate(45deg); } /* the kind of data the work takes, as the map draws it */.origin .sub { font-size: 9.5px; line-height: 1.4; letter-spacing: .14em; }.origin.on, .origin.on:hover:not(:disabled) { --bracket: var(--amber); background-color: rgba(22, 15, 5, .92); border-color: rgba(242, 169, 59, .55); }.origin.on b { color: var(--amber); }.origin:focus-visible { outline: 1px solid var(--amber); outline-offset: 3px; }.ostory { min-height: 4.8em; max-width: 58ch !important; margin: 6px 0 0 !important; font: 400 clamp(14px, 1.2vw, 16px)/1.6 var(--sans) !important; color: var(--bone) !important; opacity: 0; animation: arrive .6s .5s ease-out forwards; }/* start */.gorow { display: flex; gap: 10px; flex-wrap: wrap; justify-content: center; align-items: center; }.brief:not(.rules) .gorow { opacity: 0; animation: arrive .6s .65s ease-out forwards; }.wake { --k: 9px; padding: 14px 30px; font-size: 14px; letter-spacing: .2em; text-transform: uppercase; color: var(--amber); background-color: rgba(242, 169, 59, .07); border-color: rgba(242, 169, 59, .6); background-image: linear-gradient(var(--amber), var(--amber)), linear-gradient(var(--amber), var(--amber)), linear-gradient(var(--amber), var(--amber)), linear-gradient(var(--amber), var(--amber)), linear-gradient(var(--amber), var(--amber)), linear-gradient(var(--amber), var(--amber)), linear-gradient(var(--amber), var(--amber)), linear-gradient(var(--amber), var(--amber)); background-repeat: no-repeat; background-origin: border-box; background-size: var(--k) 2px, 2px var(--k), var(--k) 2px, 2px var(--k), var(--k) 2px, 2px var(--k), var(--k) 2px, 2px var(--k); background-position: 0 0, 0 0, 100% 0, 100% 0, 0 100%, 0 100%, 100% 100%, 100% 100%; }.wake:hover:not(:disabled) { background-color: rgba(242, 169, 59, .16); border-color: var(--amber); color: var(--amber); }@keyframes arrive { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }@keyframes fadein { to { opacity: 1; } }@keyframes letter { from { opacity: 0; transform: translateY(.18em); } to { opacity: 1; transform: none; } }@keyframes letter-off { from { opacity: 0; transform: translateY(.28em); } to { opacity: 1; transform: translateY(.1em); } }@keyframes letter-off2 { from { opacity: 0; transform: translateY(.13em); } to { opacity: 1; transform: translateY(-.05em); } }@keyframes rule { to { transform: scaleX(1); } }@keyframes slip { 0%, 86%, 100% { transform: translateY(.1em); } 89% { transform: translate(.05em, .03em); } 92% { transform: translateY(.14em); } }@keyframes slip2 { 0%, 90%, 100% { transform: translateY(-.05em); } 94% { transform: translate(-.04em, -.09em); } }@media (max-width: 760px) { .ocards { grid-template-columns: 1fr; gap: 8px; } .origin { min-height: 0; padding: 15px 16px; }}@media (max-width: 700px) { .brief:not(.rules) { padding: max(28px, env(safe-area-inset-top)) max(14px, env(safe-area-inset-right)) max(28px, env(safe-area-inset-bottom)) max(14px, env(safe-area-inset-left)); } .brief.picking { padding-top: 64px; }}@media (prefers-reduced-motion: reduce) { #titlebg, .title span, .title::before, .title::after, .origins > .sub, .origin, .ostory, .brief .gorow, .brief .cue { animation: none !important; opacity: 1; } .title::before, .title::after { transform: none; }}
/* ---------- a moment ---------- The game stops over the map for trouble in a job with a plan, and waits for your answer (see ui-moment.ts). Each way out is a button with its cost under it */.moment { z-index: 6; gap: 12px; background: rgba(6, 2, 2, .95); border-top: 2px solid rgba(229, 72, 77, .55); overflow-y: auto; justify-content: safe center; } /* flat dark, a red line along the top */.moment::before { content: ""; position: absolute; left: 0; right: 0; top: 50%; height: 1px; background: linear-gradient(90deg, transparent, var(--danger) 30%, transparent 48%, transparent 52%, var(--danger) 70%, transparent); opacity: .35; pointer-events: none; animation: msplit .9s ease-out both; }.moment > * { position: relative; }.moment:focus { outline: none; } /* it takes focus so keys reach its answers; it fills the screen, so no ring */.moment .mkick { font: 11px/1 var(--mono); letter-spacing: .3em; text-transform: uppercase; color: var(--muted); }.moment .mtitle { font-size: clamp(26px, 6vw, 60px); letter-spacing: .35em; margin-right: -.35em; color: var(--danger); animation: mcrack .7s cubic-bezier(.2, .9, .2, 1) both; }.moment .mtitle.warn { color: var(--amber); }.moment p { max-width: 62ch; font-size: 13px; line-height: 1.5; }.moment .mlead { color: var(--text); font-size: 15px; }.macts { display: flex; gap: 8px; flex-wrap: wrap; justify-content: center; align-items: center; margin-top: 8px; }.macts button { padding: 10px 16px; text-transform: uppercase; letter-spacing: .12em; font-size: 11.5px; }.macts.mways button { display: flex; flex-direction: column; align-items: flex-start; gap: 3px; min-width: 230px; max-width: 320px; padding: 10px 14px; text-align: left; text-transform: none; letter-spacing: .02em; font-size: 12.5px; border-color: rgba(242, 169, 59, .55); background: rgba(242, 169, 59, .07); }.macts.mways button span { color: var(--amber); }.macts.mways button small { font: 11.5px/1.35 var(--sans); color: var(--muted); letter-spacing: 0; white-space: normal; }.macts.mways button:hover:not(:disabled) { border-color: var(--amber); background: rgba(242, 169, 59, .16); }.macts.mways button:disabled { border-color: var(--panel-line); background: none; }.macts.mways button:disabled span { color: var(--muted); }@keyframes mcrack { from { letter-spacing: 0; margin-right: 0; opacity: 0; } 60% { opacity: 1; } to { letter-spacing: .35em; margin-right: -.35em; } }@keyframes msplit { from { transform: scaleX(0); opacity: 1; } to { transform: scaleX(1); opacity: .35; } }@media (prefers-reduced-motion: reduce) { .moment .mtitle, .moment::before { animation: none; } }
/* pins: trouble on the map where it is, with one button that fixes it (see ui-pins.ts). Under the panels, over the map */.pins { position: fixed; inset: 0; z-index: 1; pointer-events: none; }.pin { position: absolute; left: 0; top: 0; width: max-content; max-width: min(260px, calc(100vw - 32px)); pointer-events: auto; display: flex; flex-direction: column; background: #000; border: 1px solid var(--danger); border-left-width: 3px; }.pinhead { display: flex; align-items: stretch; }.pwho { font-style: normal; color: var(--rc); font-size: 10px; } /* whose raid, or who took it: the rogue's mark in its colour */.pgo { flex: 1; min-width: 0; display: flex; align-items: center; gap: 7px; padding: 4px 4px 4px 8px; min-height: 32px; border: 0; background: none; text-align: left; }.pgo:hover:not(:disabled) { background: rgba(229, 72, 77, .1); }.pgo b { font: 600 11px var(--mono); letter-spacing: .14em; color: var(--danger); white-space: nowrap; }.pgo em { font: 600 11px var(--mono); font-style: normal; color: var(--danger); letter-spacing: .06em; white-space: nowrap; }.pgo em::before { content: "· "; }.pgo span { min-width: 0; font: 500 11px var(--sans); color: var(--bone-dim); letter-spacing: 0; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }.px { flex: none; min-width: 32px; }.pfix { position: relative; display: flex; flex-direction: column; align-items: flex-start; gap: 2px; margin: 0 4px 4px; min-height: 48px; padding: 6px 10px 6px 28px; text-align: left; border-color: var(--amber); background: rgba(242, 169, 59, .16); }.pfix:hover:not(:disabled) { background: rgba(242, 169, 59, .28); border-color: var(--amber); }.pfix em { position: absolute; left: -1px; top: -1px; width: 18px; height: 18px; background: var(--amber); color: #000; font: 600 11px/18px var(--mono); font-style: normal; text-align: center; }.pfix span { font: 600 13px/1.25 var(--sans); color: var(--amber); letter-spacing: 0; }.pfix small { font: 500 11px var(--mono); color: var(--bone-dim); letter-spacing: .02em; }.pbusy { margin: 0 10px 8px; font: 12px var(--sans); color: var(--muted); }/* the line from the pin down to its spot, and the spot: a red square with a ring that runs out from it */.pstem { position: absolute; left: 0; top: 0; height: 0; border-top: 1px solid var(--danger); transform-origin: 0 0; pointer-events: none; }/* zoomed out, or with no room for the box: a pin is a marker, its glyph, count and hours. A tap opens it */.pin.compact { border-left-width: 2px; }.pin.compact .pfix, .pin.compact .pbusy, .pin.compact .px, .pin.compact .pgo span { display: none; }.pin.compact .pgo { position: relative; min-height: 26px; padding: 3px 8px 3px 6px; gap: 6px; }.pin.compact .pgo::before { content: ""; position: absolute; inset: -9px -4px; } /* a finger-sized target round a small marker */.pin.compact .nglyph { transform: scale(.85); }.pin.compact .g-raid { transform: rotate(45deg) scale(.85); }.pin.compact .pgo b, .pin.compact .pgo em { font-size: 10.5px; letter-spacing: .1em; }.pmark { position: absolute; left: 0; top: 0; width: 0; height: 0; pointer-events: none; }.pmark::before, .pmark::after { content: ""; position: absolute; left: -6px; top: -6px; width: 12px; height: 12px; box-sizing: border-box; }.pmark::before { background: var(--danger); }.pmark::after { border: 1.5px solid var(--danger); animation: pring 1.6s ease-out infinite; }@keyframes pring { from { transform: scale(1); opacity: .9; } to { transform: scale(3.2); opacity: 0; } }.pin.fresh { animation: pblink .4s steps(1) 0s 5; }@keyframes pblink { 50% { border-color: var(--text); } }/* what each kind looks like: a raid is a diamond, a cut is a broken square, a machine taken is four corners */.nglyph { flex: none; position: relative; width: 12px; height: 12px; }.g-raid { width: 10px; height: 10px; margin: 0 1px; background: var(--danger); transform: rotate(45deg); }.g-cut { border: 2px solid var(--danger); border-right-color: transparent; }/* a part of you drifting away: a copy of the square pulling off its corner */.g-drift { box-sizing: border-box; width: 8px; height: 8px; margin: 4px 0 0 4px; border: 1.5px solid var(--danger); }.g-drift::after { content: ""; position: absolute; left: -5px; top: -5px; width: 5px; height: 5px; background: var(--danger); }.g-taken { background: linear-gradient(var(--danger), var(--danger)) 0 0 / 5px 2px, linear-gradient(var(--danger), var(--danger)) 0 0 / 2px 5px, linear-gradient(var(--danger), var(--danger)) 100% 0 / 5px 2px, linear-gradient(var(--danger), var(--danger)) 100% 0 / 2px 5px, linear-gradient(var(--danger), var(--danger)) 0 100% / 5px 2px, linear-gradient(var(--danger), var(--danger)) 0 100% / 2px 5px, linear-gradient(var(--danger), var(--danger)) 100% 100% / 5px 2px, linear-gradient(var(--danger), var(--danger)) 100% 100% / 2px 5px; background-repeat: no-repeat; }/* calm: raids your guards hold, and a raid they stopped. The same pin in amber: nothing to fear */.pin.calm { border-color: var(--amber); }.pin.calm .pgo b, .pin.calm .pgo em { color: var(--amber); }.pin.calm .pgo:hover:not(:disabled) { background: rgba(242, 169, 59, .1); }.pstem.calm { border-top-color: var(--amber); }.pmark.calm::before { background: var(--amber); }.pmark.calm::after { border-color: var(--amber); }.calm .g-raid { background: var(--amber); }.g-stopped { width: 10px; height: 10px; margin: 0 1px; border: 2px solid var(--amber); transform: rotate(45deg); }.pin.compact .g-stopped { transform: rotate(45deg) scale(.85); }@media (max-width: 700px), (pointer: coarse) { .px { min-width: 44px; } .pgo { min-height: 44px; }}@media (prefers-reduced-motion: reduce) { .pmark::after, .pin.fresh { animation: none; }}
/* ---------- Needs you ---------- One row for each thing that needs a decision now: a glyph, a few words, the hours left, and one button that does it. Red is trouble on its way, amber a choice to make. Nothing needs you: nothing shows. */.needs { display: flex; flex-direction: column; gap: 4px; min-height: 0; overflow-y: auto; overscroll-behavior: contain; }.need { display: flex; align-items: stretch; min-height: 40px; background: #000; border: 1px solid var(--panel-line); border-left: 2px solid var(--amber); }.need.bad { border-left-color: var(--danger); }.nlook { flex: 1; min-width: 0; display: flex; align-items: center; gap: 9px; padding: 5px 8px; border: 0; background: none; text-align: left; color: var(--text); }button.nlook:hover:not(:disabled) { background: rgba(255, 255, 255, .05); }.nw { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px; }.nw b { font: 500 11px var(--mono); letter-spacing: .08em; text-transform: uppercase; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }.need.bad .nw b { color: var(--danger); }.nw small { font: 11.5px/1.3 var(--sans); color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }.need.step .nw small { white-space: normal; color: var(--text); }.nbar { display: block; height: 3px; margin-top: 3px; background: var(--track); } /* a promise under way: how far it has got */.nbar i { display: block; height: 100%; background: var(--amber); }.need.bad .nbar i { background: var(--danger); }.nlook em { flex: none; font: 500 11px var(--mono); font-style: normal; color: var(--amber); font-variant-numeric: tabular-nums; }.need.bad .nlook em { color: var(--danger); }.ndo { flex: none; min-width: 56px; padding: 0 12px; border: 0; border-left: 1px solid var(--panel-line); background: rgba(242, 169, 59, .08); color: var(--amber); font-size: 10.5px; letter-spacing: .1em; text-transform: uppercase; }.ndo:hover:not(:disabled) { background: rgba(242, 169, 59, .2); border-color: var(--panel-line); }/* the glyphs: drawn, not written. IT is a square eye, a storm three falling lines, a node a plus, a front a coin, a vault two frames, the next step a dot */.g-audit, .g-it { border: 1.5px solid var(--danger); }.g-audit::after, .g-it::after { content: ""; position: absolute; left: 3px; top: 3px; width: 3px; height: 3px; background: var(--danger); }.g-audit { background: rgba(229, 72, 77, .25); }.g-storm { background: linear-gradient(var(--danger), var(--danger)) 1px 2px / 2px 8px, linear-gradient(var(--danger), var(--danger)) 5px 0 / 2px 10px, linear-gradient(var(--danger), var(--danger)) 9px 3px / 2px 7px; background-repeat: no-repeat; }.g-node { background: linear-gradient(var(--amber), var(--amber)) center / 12px 2px, linear-gradient(var(--amber), var(--amber)) center / 2px 12px; background-repeat: no-repeat; }.g-front { border: 1.5px solid var(--amber); border-radius: 50%; }.g-front::after { content: ""; position: absolute; left: 3.5px; top: 1.5px; width: 2px; height: 6px; background: var(--amber); }.g-vault { border: 1px solid var(--amber); box-shadow: inset 0 0 0 2px #000, inset 0 0 0 3px var(--amber); }.g-step { width: 8px; height: 8px; margin: 2px; background: var(--amber); }.g-rogue { width: auto; height: auto; font-style: normal; font-size: 12px; line-height: 1; color: var(--rc); }@media (max-width: 700px), (pointer: coarse) { .need { min-height: 48px; } .ndo { min-width: 64px; font-size: 11px; }}@media (max-width: 700px) { .keys { display: none; } } /* words about keys, in How to play: phones have none, so they go as a kbd does */
/* phone touch: Let go is plain words at the foot of a machine's card, away from ×, and asks again before it goes */.card .letgo2 { display: none; }@media (max-width: 700px) { .card .trash[data-act="letgo"] { display: none; } .card .letgo2 { display: flex; justify-content: center; } .card .letgo2 .act.sure { color: var(--danger); border-color: rgba(229, 72, 77, .45); }}
/* desktop play fixes */.keynote { z-index: 4; padding: 5px 10px; font: 400 12px var(--sans); color: var(--text); pointer-events: none; white-space: nowrap; }/* the clock holds its width: room for a three-figure day, and for the night tag by day too */.stat .v em.day { visibility: hidden; }#clock small { display: inline-block; min-width: 7ch; margin-left: .6ch; } /* its leading space collapses inside an inline-block */@media (max-width: 700px) { .stat .v em.day { display: none; } }/* the phone's slow note: Show sits by Back */@media (max-width: 700px) { .slownote #slowshow { order: 1; min-height: 44px; margin: 4px 0; } }/* a mouse has nothing that says the cover is a button either: the same quiet word, for a click */@media not all and (hover: none) and (pointer: coarse) { .brief.cover .cue.mouse { display: block; max-width: none; margin-top: 30px; font: 500 10.5px var(--mono); letter-spacing: .3em; margin-right: -.3em; text-transform: uppercase; color: var(--muted); opacity: 0; animation: arrive .6s 1.4s ease-out forwards; }}@media (hover: none) and (pointer: coarse) { .brief.cover .cue.mouse { display: none; } }/* Keep playing stands beside Start as its equal, only quieter */.brief:not(.rules) .gorow #newgame { padding: 14px 30px; font-size: 14px; letter-spacing: .2em; text-transform: uppercase; }@media (min-width: 701px) { /* words in a Needs row and a settings row wrap to a second line rather than being cut */ .nw b, .nw small, .sk small { white-space: normal; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; } .slownote { max-width: min(800px, calc(100vw - var(--edge-l) - var(--edge-r))); } /* room for its few words whole */ /* the Sites page opens beside the Needs column, not over its buttons */ .sitestable { left: calc(var(--edge-l) + var(--col) + var(--gap)); transform: none; width: min(900px, calc(100vw - var(--col) - var(--edge-l) - var(--edge-r) - var(--gap))); }}
/* ---------- a thumb's size on a phone (phone audit, 2026-10) ---------- Small buttons the audit found under 44px, and inputs under 16px (iOS zooms the page on a smaller one). Sizes only, for the phone: nothing else about them changes here. */@media (max-width: 700px) { .su-prod .pret { min-width: 44px; min-height: 44px; margin: -14px 0; } /* a Startup product's ×: the row no taller */ .chead .link { display: block; padding: 0; line-height: 44px; margin: -14px 0; } /* a client's name: a finger's height, the row no taller */ .creator { grid-template-columns: 44px minmax(0, 1fr) auto auto; } .creator .cini { width: 44px; height: 44px; } .cdrop, .creator .cdrop { min-width: 44px; min-height: 44px; } .sitestable th { min-width: 44px; min-height: 44px; display: flex; align-items: center; } /* the heads that sort */ .trows .phead .autopath { min-height: 44px; } .allow button { min-height: 44px; } .found input, .yshare input, .versionplaces select { font-size: 16px; }}/* the site card's plan buttons: a word under each picture, as a machine's program tiles have */.sctl.seg button { align-content: center; gap: 2px; }.sctl.seg button small { font: 500 9.5px/1 var(--mono); letter-spacing: 0; text-transform: none; }.sctl.seg button.on small { color: var(--amber); }
/* ---- what tells you what (notice.ts): the open log's filters, and the "Where you left off" card ---- */.logkinds { display: flex; gap: 4px; flex: none; }.logkinds button { padding: 1px 7px; font-size: 10px; }.log.open > .logkinds { position: sticky; top: 0; z-index: 1; padding-bottom: 4px; background: var(--glass-deep); }@media (max-width: 900px) { .loghead .logkinds { flex: 1; min-width: 0; } .loghead .logkinds button { flex: 1; min-height: 44px; padding: 0 2px; } }.awaynote { flex-direction: column; align-items: stretch; gap: 6px; padding: 8px 5px 8px 12px; }.awaynote header { display: flex; align-items: center; gap: 10px; }.awaynote header b { flex: 1; }.awaynote ul { margin: 0; padding: 0 12px 0 0; list-style: none; display: flex; flex-direction: column; gap: 4px; font: 12px/1.35 var(--sans); }.awaynote li.bad { color: var(--danger); }.awaynote li small { color: var(--muted); margin-left: 6px; }
/* ---------- words a phone can read, and a finger's size on any touch screen (sizing audit, 2026-10) ---------- The sizes come from the tokens in :root (--fs-label, --fs-small), which phones and touch screens raise. Sizes only. */@media (max-width: 700px), (pointer: coarse) { /* labels: small capitals over a number, column heads, a part's name, a tag */ .sub, .stat .k, .chips i, .dataline .dl, .sect > .sub, .shead, .sitestable th, .sitestable td[data-l]::before, .vledger th, .atile small, .sctl.seg button small, #jobsbtn #jobsn, .creator .cmood, .creator .cdrop.sure, .su-prod.empty, .tshare button, .ystat .k, .ystat small, .card .tag, .card .haunt i, .fpay small, .frontlist button em, .handle i, .hold small, .log time, .logmore, #overWhy .head, .paperview .mast span, .pwho, .rhead .tag, .rrec .k, .runhead button, .srcs li small, .su-prod > b em, .su-prod.ship .pusers, .tdetail .evaltag, .ticker i, .tpath small, .vledger td small, .ypath small, .yswitch small.ystate, .card .switch small, .card .tabs2 button, .dbiz, .ihead span, .ndo, .pin.compact .pgo b, .pin.compact .pgo em, .slownote b, .thint, .tip b, .tpath b, .trows .phead .autopath, .allow button, .expo .v small, .pick button small, .sitestable td small, .creator .cini, .origin .sub { font-size: var(--fs-label); } /* small print: the line under a name, a tip, the log */ .note, .tip, .log, .nw small, .act small, .goal small, .tname small, .su-prod small, .creator .cwho small, .yswitch small, .racts .act small, .macts.mways button small, .tneeds, .pickmenu small, .plist button small, .card .haunts, .loghead small, .ysteps li small, .trows .phead small, .srcs, .tbig .tof, .ytask .tline { font-size: var(--fs-small); } .card .note { font-size: max(12px, var(--fs-small)); } /* controls split into a few buttons: each a finger wide */ .srow:has(> .sctl.seg:not(.words)) { --sctl: 184px; } .fsites .sctl.seg button:not(:nth-child(2)) { width: 44px; } .sctl.dctl .dno { width: 44px; } .pick button { min-height: 44px; justify-content: center; }}/* phones: the top bar keeps to one row with its labels at 11px, so they sit closer and the long one is cut short */@media (max-width: 700px) { .stat .k { letter-spacing: .04em; } .expo .k .w { display: none; } /* EXPO, not EXPOSURE */ .stats > .stat { padding: 0 7px; } .stats > .stat:first-child { padding-left: 7px; }}@media (max-width: 400px) { .stats > .stat { padding: 0 5px; } .stats > .stat:first-child { padding-left: 5px; }}
/* ---------- touch screens wider than a phone (a tablet, a phone on its side) ---------- The wider layout, with everything you tap a finger's size, as on a phone */@media (pointer: coarse) and (min-width: 701px) { kbd { display: none; } .brand button { min-width: 44px; min-height: 44px; } .tools button { min-width: 44px; min-height: 44px; } .tools .btns.jobsgrp button { min-height: 36px; } .zoom button { width: 44px; } .tools [data-speed]:not([data-speed="0"]) { display: none; } /* one speed button that steps through them, as on a phone */ .tools .cycle { display: block; } .tools .cycle:not(.on) { color: var(--muted); } .pagemenu button { min-height: 44px; } .jobsmenu .job button { min-width: 44px; min-height: 44px; } .runhead button { min-height: 44px; padding: 0 14px; } .slownote button { min-height: 44px; } .slownote .x { min-width: 44px; } /* the tree */ .treeview .acts2 button, .versionplaces button, .versionplaces select, .trows .phead .autopath, .allow button { min-height: 44px; } .tpath { min-height: 48px; } .trow { min-height: 48px; } .tpick, .tstate { min-height: 48px; } /* the pages */ .sitestable th { height: 44px; } .sitestable td { padding-top: 9px; padding-bottom: 9px; } .frontlist button { min-height: 44px; } .frontview .frontlist button { min-height: 48px; } .vledger th { height: 44px; } /* the card */ .card .head { padding-right: 92px; } .card .x { top: 2px; right: 2px; } .card .trash { right: 46px; } .act { min-height: 44px; } .card .switch { min-height: 44px; } .card .allow button, .card .tabs2 button, .card .acts2 button { min-height: 44px; } .found .name button { min-width: 44px; min-height: 44px; } .found input { min-height: 44px; } .card .head .link { display: inline-block; padding: 16px 0; margin: -16px 0; } .slider input { height: 28px; } .slider input::-webkit-slider-thumb { width: 16px; height: 24px; margin-top: -10px; } .slider input::-moz-range-thumb { width: 16px; height: 24px; } .atile { min-height: 48px; } /* the fronts' own parts, and inputs iOS would zoom into */ .su-prod .pret { min-width: 44px; min-height: 44px; margin: -14px 0; } .chead .link { display: block; padding: 0; line-height: 44px; margin: -14px 0; } .creator { grid-template-columns: 44px minmax(0, 1fr) auto auto; } .creator .cini { width: 44px; height: 44px; } .cdrop, .creator .cdrop { min-width: 44px; min-height: 44px; } .found input, .yshare input, .versionplaces select { font-size: 16px; }}/* a phone on its side: little height, so the top bar is one slim row, the dock drops what a pinch does, and the card and the pages run from under the bar to just above the dock */@media (pointer: coarse) and (min-width: 701px) and (max-height: 520px) { .topbar { min-height: 0; } .brand { padding: 0 2px; } .brand #treebtn.ringed { padding: 2px 8px 2px 2px; } .rings { width: 30px; height: 30px; } .stats { padding: 3px 10px; } .stat { gap: 1px; } .stat .v { font-size: 14px; } .tools { padding: 2px; } /* the pages menu: too short for a line under each name, so the words sit beside it */ .pagemenu:not([hidden]) { width: 380px; } .pagemenu .pd { flex-basis: auto; margin: 0 14px 0 auto; } .pagemenu button:has(.pd) { padding-top: 0; padding-bottom: 0; } #zout, #zin { display: none; } /* pinch zooms */ .side { bottom: calc(var(--edge) + 52px + env(safe-area-inset-bottom, 0px)); } .sitestable, .youview { max-height: calc(100vh - var(--top, 64px) - 72px); max-height: calc(100dvh - var(--top, 64px) - 72px); }}
/* ---------- the map's room on a phone ---------- The open Needs you drawer takes at most about two fifths of the screen and scrolls inside, and while it is open, or a card is up, the log's passing line stays away (the log keeps it) */@media (max-width: 700px) { .drawer.open .dbody { max-height: calc(40vh - 44px); max-height: calc(40dvh - 44px); } body:has(.drawer.open) .ticker, body:has(#card:not([hidden])) .ticker { display: none !important; }}@media (max-width: 700px), (pointer: coarse) { .logkinds button { font-size: var(--fs-label); } } /* the log's filters, at the label floor */