diff --git a/AGENTS.md b/AGENTS.md index 78a286c..4013936 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -26,6 +26,17 @@ everything else (transport included) is hand-written. There is no linter, formatter, or CI. Do not invent commands beyond these. +### Visual changes + +- A change that alters what the player sees is reviewed by eye before it is + committed. Build a **minimal standalone HTML example** of the change first — + the isolated element and each of its states, not a whole mocked-up screen — + open it in a browser and show it to the user. Only commit once the user has + seen and approved the preview. +- Keep the examples small and self-contained: link the stylesheet and copy in + the few assets they need. A short gallery of one small example per visual + change is the right size. Do not add the examples to the repository. + ### Local testing mode - The server creates its game at startup; add `--testing` to diff --git a/client/css/style.css b/client/css/style.css index 675205c..998cb23 100644 --- a/client/css/style.css +++ b/client/css/style.css @@ -867,13 +867,8 @@ input:focus, select:focus { border-color: var(--accent); } padding: 12px 18px; } -/* Tile improvements, grouped under a category heading. */ -.tile-improvement-actions { - display: flex; - flex-direction: column; - gap: 8px; - margin-top: 8px; -} +/* Tile improvements, grouped under a category heading, in the management + panel. */ .improvement-group { display: flex; flex-direction: column; gap: 4px; } .improvement-category { font-size: 10px; @@ -885,30 +880,145 @@ input:focus, select:focus { border-color: var(--accent); } .improvement-btn { font-size: 12px; } .improvement-btn.current { opacity: 0.6; } .improvement-btn.remove { border-color: rgba(242, 114, 114, 0.6); } -/* Buildable improvements are square icons with the cost written beneath. */ -.improvement-icon-btn { - display: flex; - flex-direction: column; - align-items: center; - gap: 2px; - width: 64px; - padding: 5px 4px; -} -.improvement-icon { width: 40px; height: 40px; display: block; } -.improvement-cost { - display: flex; - flex-wrap: wrap; - justify-content: center; - align-items: center; - gap: 0 3px; - font-size: 10px; - color: var(--muted); - font-variant-numeric: tabular-nums; -} .cost-res { display: inline-flex; align-items: center; gap: 2px; } .cost-icon { width: 12px; height: 12px; vertical-align: middle; } .cost-money { color: var(--muted); } +/* The building and improvement card: icon, name and status up top, a + bottom-anchored action button carrying the estimated price and build time, + and a quiet remove control. What the work produces, consumes and costs is in + the hover tooltip so the card itself stays bare. Shared by the city + buildings tab and the HUD's tile improvement panel. */ +.building-scroller { overflow-x: auto; overflow-y: hidden; padding-bottom: 8px; } +.building-grid { + display: grid; + grid-template-rows: repeat(2, auto); + grid-auto-flow: column; + grid-auto-columns: 178px; + gap: 8px; + width: max-content; +} +.building-tile { + position: relative; + display: flex; + flex-direction: column; + gap: 4px; + width: 178px; + padding: 9px; + border-radius: 9px; + border: 1px solid rgba(150, 190, 240, 0.35); + background: linear-gradient(180deg, rgba(90, 130, 190, 0.3), rgba(35, 55, 90, 0.55)); +} +.building-tile:hover { filter: brightness(1.15); } +.building-tile.built { border-color: rgba(143, 227, 168, 0.6); } +.building-tile.locked { opacity: 0.6; filter: none; } +/* An unavailable work is hatched, so a locked card reads at a glance. */ +.building-tile.locked::after { + content: ""; + position: absolute; + inset: 0; + border-radius: inherit; + pointer-events: none; + background: repeating-linear-gradient( + 45deg, + rgba(255, 255, 255, 0.14) 0 2px, + transparent 2px 8px + ); +} +.bt-top { display: flex; align-items: center; gap: 8px; padding-right: 16px; } +.bt-top .building-icon { width: 34px; height: 34px; flex: 0 0 auto; opacity: 0.95; } +.bt-id { min-width: 0; } +.building-tile .bt-name { font-weight: 600; font-size: 12.5px; line-height: 1.15; } +.building-tile .bt-level { font-size: 10.5px; color: var(--muted); } +.building-tile .bt-level.built { color: #8fe3a8; } +.building-tile .bt-upgrade { + display: flex; + justify-content: space-between; + align-items: baseline; + gap: 6px; + width: 100%; + margin-top: auto; + padding: 4px 8px; + font-size: 11.5px; + text-align: left; +} +.building-tile .bt-up-label { font-weight: 600; } +.building-tile .bt-meta { + font-size: 10px; + font-weight: 400; + color: var(--muted); + font-variant-numeric: tabular-nums; + white-space: nowrap; +} +/* The money is an estimate, so it is italic and marked with a tilde. */ +.building-tile .bt-price { font-style: italic; } +.building-tile .bt-free { width: 100%; font-size: 10.5px; padding: 3px 6px; } +.building-tile .bt-downgrade { + position: absolute; + top: 5px; + right: 5px; + display: flex; + align-items: center; + justify-content: center; + width: 20px; + height: 20px; + padding: 0; + line-height: 1; + font-size: 11px; + border-radius: 6px; + background: transparent; + border: 1px solid transparent; + color: var(--muted); + opacity: 0.6; +} +.building-tile .bt-downgrade:hover:not(:disabled) { + opacity: 1; + color: #ff9a9a; + background: rgba(255, 255, 255, 0.06); + border-color: rgba(242, 114, 114, 0.5); +} +.building-tile .bt-downgrade:disabled { opacity: 0.2; } + +/* The card's hover tooltip. Fixed to the body so a scrolling card list never + clips it. */ +.card-tooltip { + position: fixed; + z-index: 1000; + pointer-events: none; + max-width: 300px; + padding: 8px 10px; + border-radius: 9px; + background: var(--panel-bg); + border: 1px solid var(--panel-border); + box-shadow: 0 16px 40px rgba(0, 0, 0, 0.7); + font-size: 11.5px; + color: var(--text); +} +.card-tooltip .tip-section + .tip-section { + margin-top: 6px; + border-top: 1px solid rgba(255, 255, 255, 0.08); + padding-top: 6px; +} +.card-tooltip .tip-head { + font-size: 9.5px; + letter-spacing: 0.08em; + text-transform: uppercase; + color: var(--muted); + margin-bottom: 2px; +} +.card-tooltip .tip-line { + display: flex; + align-items: center; + gap: 4px; + font-variant-numeric: tabular-nums; +} +.card-tooltip .tip-produce { color: #8fe3a8; } +.card-tooltip .tip-consume, +.card-tooltip .tip-cost { color: #e2c08a; } +.card-tooltip .tip-none { color: var(--muted); } +.card-tooltip .res { display: inline-flex; align-items: center; gap: 3px; } +.card-tooltip .res img { width: 13px; height: 13px; } + /* The tile panel leads with what the tile actually produces. */ #tile-production { margin: 4px 0 6px; display: flex; flex-direction: column; gap: 2px; } .tile-prod-row { @@ -1153,7 +1263,8 @@ input:focus, select:focus { border-color: var(--accent); } instead of covering it, so the approval figure stays in view while they are open. The 104px clears the summary's 12px offset plus its padded height. */ #modal-city, -#modal-nation { +#modal-nation, +#modal-tile { align-items: flex-start; padding: 104px 16px 16px; } @@ -1555,15 +1666,17 @@ input:focus, select:focus { border-color: var(--accent); } .training-queue .queue-row { padding: 8px 12px; } .training-queue .queue-row .actions .aero { min-width: 110px; } -/* The city modal keeps a fixed size whatever tab is open, so switching between - train, buildings, people and budget never resizes the card. The unit buttons - sit in a fixed-height box that scrolls when there are more units than fit; - the queue below is the flexible part and scrolls too, so adding units never - stretches the card or pushes the buttons out of reach. */ -#modal-city .modal-card { - width: 680px; - max-width: calc(100vw - 32px); - height: min(80vh, 740px); +/* The city and tile panels keep a fixed size whatever tab is open, so switching + between train, buildings, people and budget never resizes the card. They match + the nation panel so the three read as the same surface. The unit buttons sit in + a fixed-height box that scrolls when there are more units than fit; the queue + below is the flexible part and scrolls too, so adding units never stretches + the card or pushes the buttons out of reach. */ +#modal-city .modal-card, +#modal-tile .modal-card { + width: 90vw; + max-width: 1600px; + height: min(80vh, 900px); max-height: calc(100vh - 120px); } #modal-city #city-train-list { diff --git a/client/index.html b/client/index.html index d6ba568..c2e87dc 100644 --- a/client/index.html +++ b/client/index.html @@ -151,7 +151,9 @@
-
+
+ +
+ + +