Files
Commonwealth-Online-Public/ui/views/CommonwealthOnline/pause-menu/styles.css
T
andrew c3f5afe7f6 Consolidate shared UI assets
Move common logo and controller glyphs into `ui/views/CommonwealthOnline/shared/` and update the pause menu, main menu, and browser glyph loader to use the shared paths. Also add a sync script and update deploy/staging scripts to copy controller icons once into the shared folder.
2026-07-05 22:46:38 +12:00

650 lines
16 KiB
CSS
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* Commonwealth Online — pause menu concept (1920×1080 baseline) */
@font-face {
font-family: "Futura PT Demibold";
src: url("../../fonts/futura-pt-demibold.otf") format("opentype");
font-weight: 600;
font-display: swap;
}
:root {
/*
* --co-ui-scale is set by JavaScript (script.js) to a numeric value
* because nested calc()/min()/clamp() in custom properties doesn't
* resolve to a number in all browsers — it stays as a formula string,
* which breaks calc(Npx * var(--co-ui-scale)). The JS computes the
* scale on load and on resize, ensuring it's always a real number.
*/
--co-ui-scale: 1;
--co-black: #0a0c0a;
--co-panel-bg: rgba(8, 14, 10, 0.72);
--co-panel-fade: rgba(8, 14, 10, 0);
--co-green: #3ecf4a;
--co-green-dim: rgba(62, 207, 74, 0.35);
--co-amber: #c9a84a;
--co-amber-muted: rgba(201, 168, 74, 0.55);
--co-text-pale: #d8ddd0;
--co-text-muted: #9aa898;
--co-select-yellow: #c4a84b;
--co-select-yellow-bright: #d4bc62;
--co-select-text: #1a1c18;
--co-border: rgba(201, 168, 74, 0.45);
--co-font: "Futura PT Demibold", "Roboto Condensed", "Bahnschrift", "Arial Narrow", Arial, sans-serif;
--co-transition: 120ms ease-out;
--co-panel-width: 28%;
--co-menu-size: calc(26px * var(--co-ui-scale));
--co-menu-gap: calc(6px * var(--co-ui-scale));
}
*,
*::before,
*::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
html,
body {
width: 100vw;
height: 100vh;
overflow: hidden;
font-family: var(--co-font);
font-weight: 600;
color: var(--co-text-pale);
background: var(--co-black);
user-select: none;
-webkit-font-smoothing: antialiased;
}
/* ── Root layout ─────────────────────────────────────────────── */
.pause-screen {
position: relative;
width: 100vw;
height: 100vh;
overflow: hidden;
}
/* ── Map world (map art + markers, one shared blur/pan/zoom) ── */
.map-world {
position: absolute;
inset: 0;
z-index: 1;
filter: brightness(0.74) contrast(1.04) saturate(0.55);
transform: translate(var(--map-pan-x, 0px), var(--map-pan-y, 0px))
scale(var(--map-zoom, 1));
transform-origin: center center;
/* Transform is driven by JS (smooth zoom / drag pan); only filter animates. */
transition: filter 200ms ease-out;
cursor: grab;
pointer-events: none;
}
.map-world.is-interactive {
pointer-events: auto;
}
.map-world.is-blurred {
filter: brightness(0.74) contrast(1.04) saturate(0.55) blur(12px);
}
.pause-screen.is-panning .map-world {
transition: none;
cursor: grabbing;
}
.map-layer {
position: absolute;
inset: 0;
/*
* "contain" keeps the whole regional map visible (Fallout 76-style full
* overview) instead of "cover" cropping it down to a tight, zoomed-in
* strip. background-color fills the letterboxed edges so they blend
* into the dark UI instead of showing hard bars.
*/
background:
url("assets/map.png") center center / contain no-repeat;
background-color: #0b100c;
}
.map-overlay {
position: absolute;
inset: 0;
z-index: 2;
pointer-events: none;
background:
linear-gradient(
90deg,
rgba(6, 10, 8, 0.75) 0%,
rgba(6, 10, 8, 0.32) 24%,
rgba(6, 10, 8, 0.1) 55%,
rgba(6, 10, 8, 0.18) 100%
),
rgba(4, 8, 6, 0.18);
}
/* ── Map markers ───────────────────────────────────────────── */
/* Inside .map-world so they share the same filter and transform as the map. */
.map-markers {
position: absolute;
inset: 0;
pointer-events: none;
}
.marker {
position: absolute;
transform: translate(-50%, -50%);
}
.marker--player {
width: calc(14px * var(--co-ui-scale));
height: calc(14px * var(--co-ui-scale));
background: var(--co-green);
clip-path: polygon(50% 0%, 0% 100%, 100% 100%);
filter: drop-shadow(0 0 4px rgba(62, 207, 74, 0.6));
opacity: 0.85;
}
.marker--ally {
width: calc(7px * var(--co-ui-scale));
height: calc(7px * var(--co-ui-scale));
border-radius: 50%;
background: var(--co-amber-muted);
box-shadow: 0 0 6px rgba(201, 168, 74, 0.35);
opacity: 0.7;
}
/* ── Screen effects: vignette, scanlines, HUD grid ─────────── */
.screen-effects {
position: absolute;
inset: 0;
z-index: 4;
pointer-events: none;
}
.screen-effects::before {
content: "";
position: absolute;
inset: 0;
background:
radial-gradient(
ellipse at center,
transparent 40%,
rgba(0, 0, 0, 0.55) 100%
);
opacity: 0.9;
}
.screen-effects::after {
content: "";
position: absolute;
inset: 0;
background:
/* horizontal scanlines */
repeating-linear-gradient(
0deg,
transparent,
transparent 2px,
rgba(0, 0, 0, 0.12) 2px,
rgba(0, 0, 0, 0.12) 3px
),
/* subtle grid */
repeating-linear-gradient(
90deg,
transparent,
transparent 79px,
rgba(62, 207, 74, 0.03) 79px,
rgba(62, 207, 74, 0.03) 80px
),
repeating-linear-gradient(
0deg,
transparent,
transparent 79px,
rgba(62, 207, 74, 0.03) 79px,
rgba(62, 207, 74, 0.03) 80px
);
opacity: 0.65;
mix-blend-mode: overlay;
}
/* scratch/grime texture via extra box-shadow on root */
.pause-screen::after {
content: "";
position: absolute;
inset: 0;
z-index: 20;
pointer-events: none;
background:
url("data:image/svg+xml,%3Csvg viewBox='0 0 200 200' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='0.08'/%3E%3C/svg%3E");
opacity: 0.35;
}
/* ── Left panel ──────────────────────────────────────────────── */
.left-panel {
position: absolute;
top: 0;
left: 0;
bottom: 0;
z-index: 10;
width: var(--co-panel-width);
min-width: calc(280px * var(--co-ui-scale));
max-width: 36%;
display: flex;
flex-direction: column;
padding:
calc(28px * var(--co-ui-scale))
calc(32px * var(--co-ui-scale))
calc(72px * var(--co-ui-scale))
calc(28px * var(--co-ui-scale));
background:
linear-gradient(
90deg,
var(--co-panel-bg) 0%,
rgba(8, 14, 10, 0.55) 70%,
var(--co-panel-fade) 100%
);
transition: opacity 200ms ease-out, visibility 200ms ease-out;
}
.left-panel.is-hidden {
opacity: 0;
visibility: hidden;
}
.brand-logo {
width: calc(200px * var(--co-ui-scale));
height: auto;
margin-bottom: calc(36px * var(--co-ui-scale));
opacity: 0.88;
filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.5));
}
/* ── Menu list ───────────────────────────────────────────────── */
.menu {
display: flex;
flex-direction: column;
gap: var(--co-menu-gap);
flex: 1;
}
.menu-item {
position: relative;
display: flex;
align-items: center;
gap: calc(14px * var(--co-ui-scale));
width: 100%;
padding:
calc(10px * var(--co-ui-scale))
calc(12px * var(--co-ui-scale));
border: none;
background: transparent;
color: var(--co-text-muted);
font-family: inherit;
font-size: var(--co-menu-size);
font-weight: 700;
letter-spacing: 0.14em;
text-align: left;
cursor: pointer;
transition:
color var(--co-transition),
transform var(--co-transition);
outline: none;
}
.menu-item__label {
position: relative;
z-index: 2;
}
/* Yellow selection bar with chevron right edge */
.menu-item__bar {
position: absolute;
left: calc(-28px * var(--co-ui-scale));
top: 50%;
transform: translateY(-50%) scaleX(0);
transform-origin: left center;
width: calc(100% + 80px * var(--co-ui-scale));
height: calc(100% + 4px);
background: linear-gradient(
90deg,
var(--co-select-yellow) 0%,
var(--co-select-yellow-bright) 85%,
#e0cc6e 100%
);
clip-path: polygon(
0 0,
calc(100% - 18px) 0,
100% 50%,
calc(100% - 18px) 100%,
0 100%
);
opacity: 0;
transition:
opacity var(--co-transition),
transform var(--co-transition);
z-index: 1;
box-shadow: 0 0 12px rgba(196, 168, 75, 0.25);
}
.menu-item:hover {
color: var(--co-text-pale);
}
.menu-item:hover .menu-item__bar {
opacity: 1;
transform: translateY(-50%) scaleX(1);
}
.menu-item:focus-visible {
color: var(--co-text-pale);
outline: 1px solid var(--co-green-dim);
outline-offset: 2px;
}
.menu-item.is-selected {
color: var(--co-select-text);
}
.menu-item.is-selected .menu-item__bar {
opacity: 1;
transform: translateY(-50%) scaleX(1);
}
/* ── Server panel ────────────────────────────────────────────── */
.server-panel {
position: absolute;
top: calc(28px * var(--co-ui-scale));
right: calc(32px * var(--co-ui-scale));
z-index: 10;
min-width: calc(240px * var(--co-ui-scale));
padding:
calc(14px * var(--co-ui-scale))
calc(18px * var(--co-ui-scale));
background: rgba(6, 12, 8, 0.78);
border: 1px solid var(--co-border);
box-shadow:
inset 0 0 20px rgba(0, 0, 0, 0.4),
0 2px 8px rgba(0, 0, 0, 0.35);
transition: opacity 220ms ease-out, visibility 220ms ease-out;
}
.server-panel__heading {
font-size: calc(10px * var(--co-ui-scale));
font-weight: 700;
letter-spacing: 0.18em;
color: var(--co-amber);
margin-bottom: calc(4px * var(--co-ui-scale));
}
.server-panel__heading + .server-panel__heading {
margin-top: calc(14px * var(--co-ui-scale));
}
.server-panel__row {
display: flex;
align-items: center;
gap: calc(10px * var(--co-ui-scale));
}
.server-panel__name,
.server-panel__players {
font-size: calc(15px * var(--co-ui-scale));
font-weight: 600;
letter-spacing: 0.04em;
color: var(--co-text-pale);
}
.signal-bars {
display: flex;
align-items: flex-end;
gap: 2px;
height: calc(14px * var(--co-ui-scale));
flex-shrink: 0;
}
.signal-bars span {
display: block;
width: calc(3px * var(--co-ui-scale));
background: var(--co-green);
opacity: 0.85;
}
.signal-bars span:nth-child(1) { height: 35%; }
.signal-bars span:nth-child(2) { height: 55%; }
.signal-bars span:nth-child(3) { height: 75%; }
.signal-bars span:nth-child(4) { height: 100%; }
/* ── Bottom prompt bar ───────────────────────────────────────── */
.prompt-bar {
position: absolute;
left: 0;
right: 0;
bottom: 0;
z-index: 10;
display: flex;
align-items: center;
justify-content: center;
gap: calc(40px * var(--co-ui-scale));
padding:
calc(10px * var(--co-ui-scale))
calc(24px * var(--co-ui-scale));
background: linear-gradient(
180deg,
transparent 0%,
rgba(6, 10, 8, 0.75) 30%,
rgba(6, 10, 8, 0.88) 100%
);
border-top: 1px solid rgba(201, 168, 74, 0.15);
transition: opacity 200ms ease-out, visibility 200ms ease-out;
}
.prompt-bar[hidden] {
opacity: 0;
visibility: hidden;
}
.prompt-bar--map-mode {
justify-content: center;
}
.prompt {
display: flex;
align-items: center;
gap: calc(8px * var(--co-ui-scale));
}
.prompt__glyph {
display: inline-flex;
align-items: center;
justify-content: center;
min-width: calc(22px * var(--co-ui-scale));
height: calc(22px * var(--co-ui-scale));
font-size: calc(11px * var(--co-ui-scale));
font-weight: 700;
color: var(--co-amber);
border: 1px solid var(--co-amber-muted);
border-radius: 50%;
background: rgba(0, 0, 0, 0.35);
line-height: 1;
}
/* Xbox PNG glyphs (from shared/icons); white pixels are tinted amber in script.js */
.prompt__glyph--icon {
border: none;
border-radius: 0;
background: transparent;
min-width: calc(28px * var(--co-ui-scale));
width: calc(28px * var(--co-ui-scale));
height: calc(28px * var(--co-ui-scale));
padding: 0;
}
/* Stick glyphs have more detail (arrows/rings) and read better slightly larger */
.prompt__glyph--icon-stick {
min-width: calc(34px * var(--co-ui-scale));
width: calc(34px * var(--co-ui-scale));
height: calc(34px * var(--co-ui-scale));
}
.prompt__glyph-img {
width: 100%;
height: 100%;
display: block;
pointer-events: none;
user-select: none;
}
.prompt__label {
font-size: calc(11px * var(--co-ui-scale));
font-weight: 600;
letter-spacing: 0.16em;
color: var(--co-text-pale);
opacity: 0.85;
}
/* ── Map mode PC back button ─────────────────────────────────── */
/*
* Fades in after the left panel (logo) finishes hiding (200ms), and
* fades out immediately on exit so it never sits on top of the logo.
*/
.map-pc-back {
position: absolute;
top: calc(28px * var(--co-ui-scale));
left: calc(28px * var(--co-ui-scale));
z-index: 12;
display: flex;
align-items: center;
gap: calc(12px * var(--co-ui-scale));
padding:
calc(10px * var(--co-ui-scale))
calc(16px * var(--co-ui-scale));
border: 1px solid var(--co-border);
background: rgba(6, 12, 8, 0.82);
box-shadow:
inset 0 0 16px rgba(0, 0, 0, 0.35),
0 2px 8px rgba(0, 0, 0, 0.35);
color: var(--co-text-pale);
font-family: inherit;
font-size: calc(14px * var(--co-ui-scale));
font-weight: 700;
letter-spacing: 0.16em;
cursor: pointer;
outline: none;
opacity: 0;
visibility: hidden;
pointer-events: none;
transition:
color var(--co-transition),
border-color var(--co-transition),
background var(--co-transition),
opacity 150ms ease-out,
visibility 0ms linear 150ms;
}
.map-pc-back.is-visible {
opacity: 1;
visibility: visible;
pointer-events: auto;
transition:
color var(--co-transition),
border-color var(--co-transition),
background var(--co-transition),
opacity 200ms ease-out 200ms,
visibility 0ms linear 200ms;
}
.map-pc-back__key {
display: inline-flex;
align-items: center;
justify-content: center;
min-width: calc(36px * var(--co-ui-scale));
padding:
calc(3px * var(--co-ui-scale))
calc(8px * var(--co-ui-scale));
border: 1px solid var(--co-amber-muted);
border-radius: 2px;
background: rgba(0, 0, 0, 0.4);
color: var(--co-amber);
font-size: calc(11px * var(--co-ui-scale));
font-weight: 700;
letter-spacing: 0.08em;
line-height: 1.2;
}
.map-pc-back__label {
line-height: 1;
}
.map-pc-back:hover {
color: var(--co-green);
border-color: var(--co-green-dim);
background: rgba(8, 18, 10, 0.9);
}
.map-pc-back:hover .map-pc-back__key {
color: var(--co-green);
border-color: var(--co-green-dim);
}
.map-pc-back:focus-visible {
outline: 1px solid var(--co-green-dim);
outline-offset: 2px;
}
/* Settings mode: keep pause nav, dim map more, hide server panel */
/* (Settings panel styles live in ../settings/settings.css) */
.pause-screen.is-settings-mode .left-panel {
overflow: hidden;
background:
linear-gradient(
90deg,
rgba(8, 14, 10, 0.9) 0%,
rgba(8, 14, 10, 0.78) 65%,
rgba(8, 14, 10, 0.15) 100%
);
}
.pause-screen.is-settings-mode .menu-item__bar {
width: calc(100% + 28px * var(--co-ui-scale));
}
.pause-screen.is-settings-mode .server-panel {
opacity: 0;
visibility: hidden;
pointer-events: none;
}
.pause-screen.is-settings-mode .map-overlay {
background:
linear-gradient(
90deg,
rgba(6, 10, 8, 0.88) 0%,
rgba(6, 10, 8, 0.55) 24%,
rgba(6, 10, 8, 0.4) 55%,
rgba(6, 10, 8, 0.48) 100%
),
rgba(4, 8, 6, 0.32);
}
/* ── Responsive tweaks ───────────────────────────────────────── */
/*
* Sizing is already fluid via --co-ui-scale (see :root), which now scales
* down for windows smaller than 1920x1080 instead of only scaling up.
* No breakpoint overrides needed on top of that for panel width or bar
* width; keeping both in sync with one scale avoids them drifting apart
* at arbitrary window sizes.
*/