/* REM: the modern UI's design (docs/rem/ui-modern.md, "Design") -- shared by every window. RmlUi has no CSS variables: the tokens are written out, keep them in step with the table. space #070b12 page ground behind full-screen pages glass #0d1622 window fill (slightly see-through: #0d1622eb) glass2 #122033 rows, fields, cards line #24405c quiet lines (FL wire blue) linehi #3d6d96 window and button frames text #dbe6f0 muted #8197ad amber #f2b13c active / selected cyan #5cc8f0 hover, focus good #5fd08a warn #f2b13c bad #ef6a5b Fonts: Saira SemiCondensed (headings, buttons, tabs), Barlow (text), IBM Plex Mono (numbers). */ /* RmlUi has no browser defaults: the block elements are set here */ div, p, h1, h2, h3, h4, section, header, footer, ul, li, form { display: block; } strong, b { font-weight: bold; } .btn, .close, .chip, .state, .key { display: inline-block; } em, i { font-style: italic; } body { font-family: Barlow; font-weight: 500; /* Barlow Medium: the regular cut reads thin at high resolutions */ font-size: 15dp; color: #dbe6f0; } /* ---------------------------------------------------------------- window frame */ body.window { position: absolute; left: 9%; top: 7%; width: 82%; height: 86%; max-width: 1680dp; /* the flight HUD's frame: cut corners, one bright edge (hudframes, at the end of this file) */ decorator: ninepatch(fw, fw-i); display: flex; flex-direction: column; } /* a window opens with a short fade and lift (the host sets .rem-in for one frame) */ /* the transform only while the window moves in (.rem-anim); a transformed window's scrolled content is clipped through the clip mask's rectangle (rem_ui_render.cpp RenderToClipMask) */ body.window { opacity: 1; transition: opacity transform 0.22s cubic-out; } body.window.rem-anim { transform: translateY(0dp) scale(1); } body.window.rem-in { opacity: 0; transform: translateY(14dp) scale(0.985); } /* after a bar icon flew to the middle: the window grows out of it */ body.window.rem-in.rem-zoom { opacity: 0; transform: translateY(0dp) scale(0.3); } /* a smaller window (player, contracts, waypoints) */ body.window.medium { left: 18%; top: 12%; width: 64%; height: 76%; max-width: 1300dp; } body.window.small { left: 28%; top: 18%; width: 44%; height: 64%; max-width: 900dp; } .win-head { display: flex; flex-direction: row; align-items: center; padding: 12dp 18dp 12dp 28dp; /* clear of the cut corner */ border-bottom: 1dp #2b6f9e; drag: drag; /* the grip: a window moves by its head (rem_ui_host.cpp, rem.ini win_) */ cursor: move; } .win-head .title { font-family: "Saira SemiCondensed"; font-weight: 600; font-size: 20dp; letter-spacing: 2dp; color: #e8f4ff; margin-right: 16dp; } /* three slashes after a window's title, as the HUD's panel titles */ .win-head .sl { font-family: "Saira SemiCondensed"; font-weight: 600; font-size: 20dp; letter-spacing: -1dp; color: #5cc8f0; margin: 0 16dp 0 -6dp; } .win-head .loc { color: #8197ad; font-size: 15dp; } .win-head .spacer { flex: 1; } .chip { font-family: "Saira SemiCondensed"; font-size: 14dp; letter-spacing: 0.6dp; color: #8197ad; padding: 2dp 4dp; margin-left: 14dp; } .chip .v { font-family: "IBM Plex Mono"; color: #dbe6f0; } .close { width: 28dp; height: 28dp; line-height: 26dp; text-align: center; margin-left: 14dp; color: #8197ad; font-size: 20dp; } .close:hover { color: #5cc8f0; } .win-main { flex: 1; display: flex; flex-direction: row; min-height: 0; } .nav { width: 200dp; border-right: 1dp #2b6f9e; padding: 10dp 0; display: flex; flex-direction: column; } .nav .item { font-family: "Saira SemiCondensed"; font-size: 16dp; letter-spacing: 1.1dp; text-transform: uppercase; color: #8197ad; padding: 9dp 18dp; border-left: 2dp #00000000; display: flex; flex-direction: row; align-items: center; } .nav .item .badge { margin-left: auto; font-family: "IBM Plex Mono"; font-size: 11dp; color: #dbe6f0; background-color: #24405c; border-radius: 3dp; padding: 0 5dp; } .nav .item:hover { color: #5cc8f0; background-color: #5cc8f01a; } .nav .item img.ico { width: 20dp; height: 20dp; margin-right: 10dp; opacity: 0.7; } .nav .item:hover img.ico, .nav .item.active img.ico { opacity: 1; } .win-head img.head-ico { width: 26dp; height: 26dp; margin-right: 10dp; image-color: #f2b13c; } .nav .item.active { color: #f2b13c; border-left-color: #f2b13c; background-color: #f2b13c14; } .nav .sep { height: 1dp; background-color: #24405c; margin: 8dp 18dp; } .content { flex: 1; padding: 18dp; min-width: 0; display: flex; flex-direction: column; } .win-foot { display: flex; flex-direction: row; align-items: center; border-top: 1dp #2b6f9e; padding: 8dp 28dp 10dp 18dp; /* clear of the cut corner */ font-size: 13dp; color: #8197ad; } .win-foot .key { font-family: "IBM Plex Mono"; font-size: 11dp; color: #dbe6f0; background-color: #24405c; padding: 0 5dp; margin-right: 5dp; } .win-foot .hint { margin-right: 18dp; } .win-foot .status { margin-left: auto; color: #dbe6f0; } /* ---------------------------------------------------------------- headings, text */ h3, .label { font-family: "Saira SemiCondensed"; font-size: 14dp; letter-spacing: 1.2dp; text-transform: uppercase; color: #8197ad; } .muted { color: #8197ad; } .hint { font-size: 13dp; color: #8197ad; } .num { font-family: "IBM Plex Mono"; } .big { font-family: "Saira SemiCondensed"; font-weight: 600; font-size: 27dp; } .kind { font-family: "Saira SemiCondensed"; letter-spacing: 1dp; text-transform: uppercase; color: #8197ad; } /* ---------------------------------------------------------------- state chips, bars */ .state { font-family: "Saira SemiCondensed"; font-size: 12dp; letter-spacing: 0.8dp; text-transform: uppercase; padding: 1dp 7dp; border-width: 1dp; border-radius: 2dp; } .st-good { color: #5fd08a; border-color: #5fd08a; } .st-warn { color: #f2b13c; border-color: #f2b13c; } .st-bad { color: #ef6a5b; border-color: #ef6a5b; } .st-idle { color: #8197ad; border-color: #8197ad; } .bar { height: 4dp; background-color: #00000066; border-radius: 2dp; } .bar .fill { height: 4dp; border-radius: 2dp; background-color: #5fd08a; } .bar .fill.warn { background-color: #f2b13c; } .bar .fill.bad { background-color: #ef6a5b; } /* ---------------------------------------------------------------- buttons */ .btn { font-family: "Saira SemiCondensed"; font-size: 14dp; letter-spacing: 1.1dp; text-transform: uppercase; color: #dbe6f0; decorator: ninepatch(fs, fs-i); /* a small cut-corner frame */ padding: 7dp 16dp; margin-right: 8dp; margin-bottom: 8dp; position: relative; transition: color border-color 0.12s; } .btn:hover { color: #5cc8f0; } .btn:active { color: #ffffff; } .btn.primary { color: #f2b13c; decorator: ninepatch(fsa, fsa-i); } .btn.primary:hover { color: #ffd07a; } .btn.danger { color: #ef6a5b; decorator: ninepatch(fsd, fsd-i); } .btn.armed { color: #160604; decorator: none; background-color: #ef6a5b; } .btn.disabled { color: #8197ad66; opacity: 0.6; } .btn .small { font-family: "IBM Plex Mono"; font-size: 11dp; color: #8197ad; text-transform: none; letter-spacing: 0; margin-left: 6dp; } /* a tooltip: a .tip child, shown while the button is hovered */ .tip { display: none; position: absolute; left: 0; top: 100%; margin-top: 8dp; width: 260dp; z-index: 10; font-family: Barlow; font-size: 13dp; text-transform: none; letter-spacing: 0; color: #dbe6f0; decorator: ninepatch(fw, fw-i); padding: 7dp 12dp; } /* shown by the tool tip window over every window (rem_ui_tooltip.cpp), not here: inside its own document another window could cover it */ .actions { display: flex; flex-direction: row; flex-wrap: wrap; } /* ---------------------------------------------------------------- tabs inside a page */ .subtabs { display: flex; flex-direction: row; border-bottom: 1dp #24405c; margin-bottom: 12dp; } .subtabs .tab { font-family: "Saira SemiCondensed"; font-size: 14dp; letter-spacing: 1.2dp; text-transform: uppercase; color: #8197ad; padding: 7dp 14dp; border-bottom: 2dp #00000000; } .subtabs .tab:hover { color: #5cc8f0; } .subtabs .tab.active { color: #f2b13c; border-bottom-color: #f2b13c; } /* ---------------------------------------------------------------- lists and tables */ .scroll { overflow-y: auto; } scrollbarvertical { width: 8dp; margin-left: 4dp; } scrollbarvertical slidertrack { background-color: #0d1622; border-radius: 4dp; } scrollbarvertical sliderbar { background-color: #3d6d96; border-radius: 4dp; min-height: 24dp; } scrollbarvertical sliderbar:hover { background-color: #5cc8f0; } scrollbarvertical sliderarrowdec, scrollbarvertical sliderarrowinc { height: 0; } input.text { box-sizing: border-box; width: 100%; padding: 7dp 10dp; border-bottom: 1dp #3d6d96; background-color: #12203399; color: #dbe6f0; font-size: 14dp; cursor: text; } input.text:focus { border-bottom-color: #5cc8f0; } input.text .placeholder, input.text:placeholder { color: #8197ad; } .table { display: flex; flex-direction: column; min-height: 0; } .table .head, .table .row { display: flex; flex-direction: row; padding: 6dp 10dp; } .table .head { font-family: "Saira SemiCondensed"; font-size: 12dp; letter-spacing: 1.2dp; text-transform: uppercase; color: #8fb3d0; border-bottom: 1dp #2b6f9e; } .table .body { flex: 1; overflow-y: auto; } .table .row { font-size: 14dp; border-bottom: 1dp #24405c66; border-left: 3dp #00000000; } .table .row:hover { background-color: #5cc8f01a; } .table .row.selected { background-color: #f2b13c24; border-left-color: #f2b13c; } .table .row.current .c1 { color: #f2b13c; } .table .c1 { flex: 1; } .table .c2 { width: 30%; } .table .c3 { width: 70dp; text-align: right; font-family: "IBM Plex Mono"; } .table .c4 { width: 120dp; text-align: right; font-family: "IBM Plex Mono"; margin-right: 16dp; } .table .head .c3, .table .head .c4 { font-family: "Saira SemiCondensed"; } /* the amount slider (as Freelancer's quantity slider at the dealers) */ input.range { flex: 1; height: 18dp; } input.range slidertrack { height: 4dp; margin-top: 7dp; background-color: #24405c; border-radius: 2dp; } input.range sliderbar { width: 14dp; height: 18dp; background-color: #f2b13c; border-radius: 3dp; } input.range sliderbar:hover { background-color: #5cc8f0; } input.range sliderarrowdec, input.range sliderarrowinc { width: 0; height: 0; } /* the dealers' amount: a wide bar clicked or dragged anywhere (data-scrub, its scale too) -- the fill and the knob at the amount, a scale 1 / quarters / the most under it */ .abar { flex: 1; position: relative; padding-top: 6dp; } .abar.off { opacity: 0.4; } .abar .arail { position: relative; height: 12dp; border: 1dp #2b6f9e; background-color: #0a1424; } .abar .afill { position: absolute; left: 0; top: 0; bottom: 0; background-color: #f2b13c55; } .abar .tk { position: absolute; top: 0; bottom: 0; width: 1dp; background-color: #2b6f9e; } .abar .aknob { position: absolute; top: -6dp; width: 12dp; height: 22dp; margin-left: -6dp; background-color: #f2b13c; border-radius: 2dp; } .abar:hover .aknob { background-color: #ffd27a; } .abar .aticks { position: relative; height: 14dp; margin-top: 7dp; font-family: "IBM Plex Mono"; font-size: 11dp; color: #8197ad; } .abar .aticks span { position: absolute; top: 0; width: 60dp; margin-left: -30dp; text-align: center; } .abar .aticks .lo { margin-left: 0; text-align: left; } .abar .aticks .hi { left: auto; right: 0; margin-left: 0; text-align: right; } .table .empty { padding: 12dp 10dp; color: #8197ad; } /* ---------------------------------------------------------------- cards, stats */ .stats { display: flex; flex-direction: row; border-top: 1dp #2b6f9e; border-bottom: 1dp #2b6f9e; margin-bottom: 12dp; } .stats .cell { flex: 1; padding: 8dp 12dp; border-right: 1dp #24405c; } .stats .cell.last { border-right-width: 0; } .stats .k { font-family: "Saira SemiCondensed"; font-size: 12dp; letter-spacing: 1.1dp; text-transform: uppercase; color: #8197ad; } .stats .v { font-family: "IBM Plex Mono"; font-size: 16dp; } .cards { display: flex; flex-direction: row; margin-bottom: 12dp; } .card { flex: 1; border-left: 3dp #2b6f9e; /* an accent at the left, no box in the window's box */ background-color: #5cc8f00a; padding: 12dp; margin-right: 10dp; } .card.last { margin-right: 0; } .card .t { font-family: "Saira SemiCondensed"; font-size: 16dp; letter-spacing: 1dp; text-transform: uppercase; } .card .p { font-family: "IBM Plex Mono"; color: #f2b13c; margin: 4dp 0; } .card .d { font-size: 13dp; color: #8197ad; margin-bottom: 10dp; } .blocked { flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; color: #8197ad; } .blocked .t { font-family: "Saira SemiCondensed"; font-size: 22dp; color: #dbe6f0; margin-bottom: 6dp; } /* the windows' calm animation (rem_ui_host.cpp adds .runner with six lights .p1 .. .p6 to every body.window, the HUD's side panels have their own in hud.rml; the document has its theme's class: theme1 fire, theme2 ice, else the scan line). Over the window, taking no clicks. */ @keyframes win-glow { from { opacity: 0.35; } to { opacity: 1; } } @keyframes win-scan { 0% { top: -120dp; opacity: 0; } 8% { opacity: 1; } 55% { opacity: 1; } 60% { top: 100%; opacity: 0; } 100% { top: 100%; opacity: 0; } } @keyframes win-ember { 0% { top: 100%; margin-left: 0dp; opacity: 0; } 10% { opacity: 1; } 50% { margin-left: 14dp; } 85% { opacity: 0.7; } 100% { top: 15%; margin-left: -6dp; opacity: 0; } } @keyframes win-sheen { 0% { left: -40%; } 45% { left: 110%; } 100% { left: 110%; } } @keyframes win-twinkle { 0% { opacity: 0; transform: scale(0.3); } 6% { opacity: 1; transform: scale(1); } 14% { opacity: 0; transform: scale(0.3); } 100% { opacity: 0; transform: scale(0.3); } } .runner { position: absolute; left: 6dp; right: 6dp; top: 3dp; bottom: 3dp; overflow: hidden; pointer-events: none; } .runner div { position: absolute; display: none; pointer-events: none; } /* (two-colour gradients only: the renderer has no shaders for linear- / radial-gradient) */ /* standard: a faint line glides down, every 16 s */ .runner .p1 { display: block; left: 0; right: 0; height: 120dp; top: -120dp; border-bottom: 1dp #dcf6ff38; decorator: vertical-gradient(#5cc8f000 #5cc8f014); animation: 16s linear infinite win-scan; } .runner .p2 { display: block; left: 0; right: 0; top: 50%; bottom: 0; decorator: vertical-gradient(#5cc8f000 #5cc8f030); animation: 6s sine-in-out infinite alternate win-glow; } /* fire: a red glow from below, five embers rising and drifting */ .theme1 .runner div { display: block; width: 7dp; height: 7dp; top: 100%; opacity: 0; border-radius: 4dp; background-color: #ffb040; border: 1dp #fff0c0; decorator: none; } .theme1 .runner .p1 { left: 12%; right: auto; height: 7dp; border-bottom: 1dp #fff0c0; animation: 9s 0s sine-in-out infinite win-ember; } .theme1 .runner .p2 { left: 0; right: 0; top: 40%; bottom: 0; width: auto; height: auto; opacity: 1; border-radius: 0; border: 0; background-color: transparent; decorator: vertical-gradient(#ff3a0000 #ff5a1a50); animation: 6s sine-in-out infinite alternate win-glow; } .theme1 .runner .p3 { left: 52%; animation: 10s 6s sine-in-out infinite win-ember; } .theme1 .runner .p4 { left: 70%; width: 5dp; height: 5dp; animation: 13s 1.5s sine-in-out infinite win-ember; } .theme1 .runner .p5 { left: 86%; animation: 11s 4.5s sine-in-out infinite win-ember; } .theme1 .runner .p6 { left: 33%; width: 5dp; height: 5dp; animation: 12s 3s sine-in-out infinite win-ember; } /* ice: a cold light from below, a light edge crossing the window every 10 s, sparkles */ .theme2 .runner div { display: block; width: 6dp; height: 6dp; opacity: 0; border-radius: 3dp; background-color: #ffffff; border: 2dp #d6f4ff80; decorator: none; } .theme2 .runner .p1 { top: 0; bottom: 0; height: auto; left: -40%; right: auto; width: 22%; opacity: 1; border-radius: 0; border: 0; border-right: 2dp #ffffff50; background-color: transparent; decorator: horizontal-gradient(#ffffff00 #ffffff22); animation: 10s 1s sine-in-out infinite win-sheen; } .theme2 .runner .p2 { left: 18%; top: 22%; animation: 7s 0.5s linear infinite win-twinkle; } .theme2 .runner .p3 { left: 64%; top: 12%; animation: 9s 2.5s linear infinite win-twinkle; } .theme2 .runner .p4 { left: 82%; top: 58%; animation: 8s 4s linear infinite win-twinkle; } .theme2 .runner .p5 { left: 38%; top: 74%; animation: 10s 6s linear infinite win-twinkle; } .theme2 .runner .p6 { left: 0; right: 0; top: 50%; bottom: 0; width: auto; height: auto; opacity: 1; border-radius: 0; border: 0; background-color: transparent; decorator: vertical-gradient(#cfefff00 #cfefff28); animation: 6s sine-in-out infinite alternate win-glow; } /* a hovered bar icon turning (nnbar, rembar) */ @keyframes nb-spin { from { transform: perspective(240dp) rotateY(0deg) scale(1.12); } to { transform: perspective(240dp) rotateY(360deg) scale(1.12); } } /* the flight HUD's frames (every window, the HUD, the bars): panels with cut corners and one bright edge, as ninepatch sprites -- img/hud_frames.png, drawn by tools/rem/make_hud_frames.py (2x: 1 dp = 2 px). fa: top left + bottom right cut, fb: all four, fs: all four (small), fed: the HUD editor's, fw: as fa but nearly opaque, for windows and tips; fsa / fsd: the primary / danger button; fo / fh / fbr: a window with a clear hole (navmap.rml): the edge alone, the head's fill (top left cut), the side's fill (bottom right cut); fts: a tab hanging from a bar, open at the top; fht / fbl / fbrt: a panel's head as a tab on its body (the head open at the bottom, the body uncut under it, head at the left / right) */ @spritesheet hudframes { src: img/hud_frames.png; resolution: 2x; fa: 0px 0px 96px 96px; fa-i: 32px 32px 32px 32px; fb: 96px 0px 96px 96px; fb-i: 128px 32px 32px 32px; fs: 192px 0px 96px 96px; fs-i: 224px 32px 32px 32px; fed: 288px 0px 96px 96px; fed-i: 320px 32px 32px 32px; fw: 384px 0px 96px 96px; fw-i: 416px 32px 32px 32px; fsa: 480px 0px 96px 96px; fsa-i: 512px 32px 32px 32px; fsd: 576px 0px 96px 96px; fsd-i: 608px 32px 32px 32px; fo: 672px 0px 96px 96px; fo-i: 704px 32px 32px 32px; fh: 768px 0px 96px 96px; fh-i: 800px 32px 32px 32px; fbr: 864px 0px 96px 96px; fbr-i: 896px 32px 32px 32px; fts: 960px 0px 96px 96px; fts-i: 992px 32px 32px 32px; fht: 1056px 0px 96px 96px; fht-i: 1088px 32px 32px 32px; fbl: 1152px 0px 96px 96px; fbl-i: 1184px 32px 32px 32px; fbrt: 1248px 0px 96px 96px; fbrt-i: 1280px 32px 32px 32px; } /* a dealer's hold and credits, large (the tabs' row of the equipment dealer, the commodity trader's row): the hold a bar that fills with the load, amber from 3/4, red full */ .dstat { display: flex; flex-direction: row; align-items: center; align-self: center; margin-left: 24dp; } .dstat .sk { margin-right: 10dp; font-family: "Saira SemiCondensed"; font-weight: 600; font-size: 12dp; letter-spacing: 2dp; color: #8197ad; } .dstat .sv { font-family: "IBM Plex Mono"; font-size: 20dp; color: #f2b13c; } .hbar { position: relative; width: 200dp; height: 24dp; border: 1dp #2b6f9e; background-color: #00000066; } .hbar .hf { position: absolute; left: 0; top: 0; bottom: 0; background-color: #3a8fc899; } .hbar .hf.warn { background-color: #f2b13c99; } .hbar .hf.bad { background-color: #ef6a5bcc; } .hbar .ht { position: relative; display: block; line-height: 24dp; text-align: center; font-family: "IBM Plex Mono"; font-size: 15dp; color: #e8f4ff; }