diff --git a/angular.json b/angular.json index fd1f73a..fd5ca34 100644 --- a/angular.json +++ b/angular.json @@ -28,8 +28,13 @@ }, { "glob": "**/*", - "input": "arabian-chess", - "output": "/arabian-chess" + "input": "assets/arabian-chess", + "output": "/assets/arabian-chess" + }, + { + "glob": "**/*", + "input": "assets/ChessAssets", + "output": "/assets/ChessAssets" } ], "styles": [ @@ -99,8 +104,13 @@ }, { "glob": "**/*", - "input": "arabian-chess", - "output": "/arabian-chess" + "input": "assets/arabian-chess", + "output": "/assets/arabian-chess" + }, + { + "glob": "**/*", + "input": "assets/ChessAssets", + "output": "/assets/ChessAssets" } ], "styles": [ diff --git a/assets/ChessAssets/b_Bishop.png b/assets/ChessAssets/b_Bishop.png new file mode 100644 index 0000000..26458d8 Binary files /dev/null and b/assets/ChessAssets/b_Bishop.png differ diff --git a/assets/ChessAssets/b_King.png b/assets/ChessAssets/b_King.png new file mode 100644 index 0000000..9a7d13f Binary files /dev/null and b/assets/ChessAssets/b_King.png differ diff --git a/assets/ChessAssets/b_Knight.png b/assets/ChessAssets/b_Knight.png new file mode 100644 index 0000000..ec3b8ba Binary files /dev/null and b/assets/ChessAssets/b_Knight.png differ diff --git a/assets/ChessAssets/b_Pawn.png b/assets/ChessAssets/b_Pawn.png new file mode 100644 index 0000000..891e2d9 Binary files /dev/null and b/assets/ChessAssets/b_Pawn.png differ diff --git a/assets/ChessAssets/b_Queen.png b/assets/ChessAssets/b_Queen.png new file mode 100644 index 0000000..a87a5dc Binary files /dev/null and b/assets/ChessAssets/b_Queen.png differ diff --git a/assets/ChessAssets/b_Rook.png b/assets/ChessAssets/b_Rook.png new file mode 100644 index 0000000..afcca80 Binary files /dev/null and b/assets/ChessAssets/b_Rook.png differ diff --git a/assets/ChessAssets/w_Bishop.png b/assets/ChessAssets/w_Bishop.png new file mode 100644 index 0000000..473f5f4 Binary files /dev/null and b/assets/ChessAssets/w_Bishop.png differ diff --git a/assets/ChessAssets/w_King.png b/assets/ChessAssets/w_King.png new file mode 100644 index 0000000..b34a354 Binary files /dev/null and b/assets/ChessAssets/w_King.png differ diff --git a/assets/ChessAssets/w_Knight.png b/assets/ChessAssets/w_Knight.png new file mode 100644 index 0000000..f824639 Binary files /dev/null and b/assets/ChessAssets/w_Knight.png differ diff --git a/assets/ChessAssets/w_Pawn.png b/assets/ChessAssets/w_Pawn.png new file mode 100644 index 0000000..185ca0a Binary files /dev/null and b/assets/ChessAssets/w_Pawn.png differ diff --git a/assets/ChessAssets/w_Queen.png b/assets/ChessAssets/w_Queen.png new file mode 100644 index 0000000..735cad5 Binary files /dev/null and b/assets/ChessAssets/w_Queen.png differ diff --git a/assets/ChessAssets/w_Rook.png b/assets/ChessAssets/w_Rook.png new file mode 100644 index 0000000..217acde Binary files /dev/null and b/assets/ChessAssets/w_Rook.png differ diff --git a/arabian-chess/license.txt b/assets/arabian-chess/license.txt similarity index 100% rename from arabian-chess/license.txt rename to assets/arabian-chess/license.txt diff --git a/arabian-chess/plane.png b/assets/arabian-chess/plane.png similarity index 100% rename from arabian-chess/plane.png rename to assets/arabian-chess/plane.png diff --git a/arabian-chess/player-one.gif b/assets/arabian-chess/player-one.gif similarity index 100% rename from arabian-chess/player-one.gif rename to assets/arabian-chess/player-one.gif diff --git a/arabian-chess/player-two.gif b/assets/arabian-chess/player-two.gif similarity index 100% rename from arabian-chess/player-two.gif rename to assets/arabian-chess/player-two.gif diff --git a/arabian-chess/raf.gif b/assets/arabian-chess/raf.gif similarity index 100% rename from arabian-chess/raf.gif rename to assets/arabian-chess/raf.gif diff --git a/arabian-chess/ref/cover.png b/assets/arabian-chess/ref/cover.png similarity index 100% rename from arabian-chess/ref/cover.png rename to assets/arabian-chess/ref/cover.png diff --git a/arabian-chess/ref/full_art.png b/assets/arabian-chess/ref/full_art.png similarity index 100% rename from arabian-chess/ref/full_art.png rename to assets/arabian-chess/ref/full_art.png diff --git a/arabian-chess/ref/logo.png b/assets/arabian-chess/ref/logo.png similarity index 100% rename from arabian-chess/ref/logo.png rename to assets/arabian-chess/ref/logo.png diff --git a/arabian-chess/sheets/board.png b/assets/arabian-chess/sheets/board.png similarity index 100% rename from arabian-chess/sheets/board.png rename to assets/arabian-chess/sheets/board.png diff --git a/arabian-chess/sheets/board_centered.png b/assets/arabian-chess/sheets/board_centered.png similarity index 100% rename from arabian-chess/sheets/board_centered.png rename to assets/arabian-chess/sheets/board_centered.png diff --git a/arabian-chess/sheets/board_without_bottom.png b/assets/arabian-chess/sheets/board_without_bottom.png similarity index 100% rename from arabian-chess/sheets/board_without_bottom.png rename to assets/arabian-chess/sheets/board_without_bottom.png diff --git a/arabian-chess/sheets/nums & letters.png b/assets/arabian-chess/sheets/nums & letters.png similarity index 100% rename from arabian-chess/sheets/nums & letters.png rename to assets/arabian-chess/sheets/nums & letters.png diff --git a/arabian-chess/sheets/pieces.png b/assets/arabian-chess/sheets/pieces.png similarity index 100% rename from arabian-chess/sheets/pieces.png rename to assets/arabian-chess/sheets/pieces.png diff --git a/arabian-chess/sprites/board/board_bottom.png b/assets/arabian-chess/sprites/board/board_bottom.png similarity index 100% rename from arabian-chess/sprites/board/board_bottom.png rename to assets/arabian-chess/sprites/board/board_bottom.png diff --git a/arabian-chess/sprites/board/board_square_black.png b/assets/arabian-chess/sprites/board/board_square_black.png similarity index 100% rename from arabian-chess/sprites/board/board_square_black.png rename to assets/arabian-chess/sprites/board/board_square_black.png diff --git a/arabian-chess/sprites/board/board_square_white.png b/assets/arabian-chess/sprites/board/board_square_white.png similarity index 100% rename from arabian-chess/sprites/board/board_square_white.png rename to assets/arabian-chess/sprites/board/board_square_white.png diff --git a/arabian-chess/sprites/nums & letters/letter_a.png b/assets/arabian-chess/sprites/nums & letters/letter_a.png similarity index 100% rename from arabian-chess/sprites/nums & letters/letter_a.png rename to assets/arabian-chess/sprites/nums & letters/letter_a.png diff --git a/arabian-chess/sprites/nums & letters/letter_b.png b/assets/arabian-chess/sprites/nums & letters/letter_b.png similarity index 100% rename from arabian-chess/sprites/nums & letters/letter_b.png rename to assets/arabian-chess/sprites/nums & letters/letter_b.png diff --git a/arabian-chess/sprites/nums & letters/letter_c.png b/assets/arabian-chess/sprites/nums & letters/letter_c.png similarity index 100% rename from arabian-chess/sprites/nums & letters/letter_c.png rename to assets/arabian-chess/sprites/nums & letters/letter_c.png diff --git a/arabian-chess/sprites/nums & letters/letter_d.png b/assets/arabian-chess/sprites/nums & letters/letter_d.png similarity index 100% rename from arabian-chess/sprites/nums & letters/letter_d.png rename to assets/arabian-chess/sprites/nums & letters/letter_d.png diff --git a/arabian-chess/sprites/nums & letters/letter_e.png b/assets/arabian-chess/sprites/nums & letters/letter_e.png similarity index 100% rename from arabian-chess/sprites/nums & letters/letter_e.png rename to assets/arabian-chess/sprites/nums & letters/letter_e.png diff --git a/arabian-chess/sprites/nums & letters/letter_f.png b/assets/arabian-chess/sprites/nums & letters/letter_f.png similarity index 100% rename from arabian-chess/sprites/nums & letters/letter_f.png rename to assets/arabian-chess/sprites/nums & letters/letter_f.png diff --git a/arabian-chess/sprites/nums & letters/letter_g.png b/assets/arabian-chess/sprites/nums & letters/letter_g.png similarity index 100% rename from arabian-chess/sprites/nums & letters/letter_g.png rename to assets/arabian-chess/sprites/nums & letters/letter_g.png diff --git a/arabian-chess/sprites/nums & letters/letter_h.png b/assets/arabian-chess/sprites/nums & letters/letter_h.png similarity index 100% rename from arabian-chess/sprites/nums & letters/letter_h.png rename to assets/arabian-chess/sprites/nums & letters/letter_h.png diff --git a/arabian-chess/sprites/nums & letters/num_0.png b/assets/arabian-chess/sprites/nums & letters/num_0.png similarity index 100% rename from arabian-chess/sprites/nums & letters/num_0.png rename to assets/arabian-chess/sprites/nums & letters/num_0.png diff --git a/arabian-chess/sprites/nums & letters/num_1.png b/assets/arabian-chess/sprites/nums & letters/num_1.png similarity index 100% rename from arabian-chess/sprites/nums & letters/num_1.png rename to assets/arabian-chess/sprites/nums & letters/num_1.png diff --git a/arabian-chess/sprites/nums & letters/num_2.png b/assets/arabian-chess/sprites/nums & letters/num_2.png similarity index 100% rename from arabian-chess/sprites/nums & letters/num_2.png rename to assets/arabian-chess/sprites/nums & letters/num_2.png diff --git a/arabian-chess/sprites/nums & letters/num_3.png b/assets/arabian-chess/sprites/nums & letters/num_3.png similarity index 100% rename from arabian-chess/sprites/nums & letters/num_3.png rename to assets/arabian-chess/sprites/nums & letters/num_3.png diff --git a/arabian-chess/sprites/nums & letters/num_4.png b/assets/arabian-chess/sprites/nums & letters/num_4.png similarity index 100% rename from arabian-chess/sprites/nums & letters/num_4.png rename to assets/arabian-chess/sprites/nums & letters/num_4.png diff --git a/arabian-chess/sprites/nums & letters/num_5.png b/assets/arabian-chess/sprites/nums & letters/num_5.png similarity index 100% rename from arabian-chess/sprites/nums & letters/num_5.png rename to assets/arabian-chess/sprites/nums & letters/num_5.png diff --git a/arabian-chess/sprites/nums & letters/num_6.png b/assets/arabian-chess/sprites/nums & letters/num_6.png similarity index 100% rename from arabian-chess/sprites/nums & letters/num_6.png rename to assets/arabian-chess/sprites/nums & letters/num_6.png diff --git a/arabian-chess/sprites/nums & letters/num_7.png b/assets/arabian-chess/sprites/nums & letters/num_7.png similarity index 100% rename from arabian-chess/sprites/nums & letters/num_7.png rename to assets/arabian-chess/sprites/nums & letters/num_7.png diff --git a/arabian-chess/sprites/pieces/black_bishop.png b/assets/arabian-chess/sprites/pieces/black_bishop.png similarity index 100% rename from arabian-chess/sprites/pieces/black_bishop.png rename to assets/arabian-chess/sprites/pieces/black_bishop.png diff --git a/arabian-chess/sprites/pieces/black_king.png b/assets/arabian-chess/sprites/pieces/black_king.png similarity index 100% rename from arabian-chess/sprites/pieces/black_king.png rename to assets/arabian-chess/sprites/pieces/black_king.png diff --git a/arabian-chess/sprites/pieces/black_knight.png b/assets/arabian-chess/sprites/pieces/black_knight.png similarity index 100% rename from arabian-chess/sprites/pieces/black_knight.png rename to assets/arabian-chess/sprites/pieces/black_knight.png diff --git a/arabian-chess/sprites/pieces/black_pawn.png b/assets/arabian-chess/sprites/pieces/black_pawn.png similarity index 100% rename from arabian-chess/sprites/pieces/black_pawn.png rename to assets/arabian-chess/sprites/pieces/black_pawn.png diff --git a/arabian-chess/sprites/pieces/black_queen.png b/assets/arabian-chess/sprites/pieces/black_queen.png similarity index 100% rename from arabian-chess/sprites/pieces/black_queen.png rename to assets/arabian-chess/sprites/pieces/black_queen.png diff --git a/arabian-chess/sprites/pieces/black_rook.png b/assets/arabian-chess/sprites/pieces/black_rook.png similarity index 100% rename from arabian-chess/sprites/pieces/black_rook.png rename to assets/arabian-chess/sprites/pieces/black_rook.png diff --git a/arabian-chess/sprites/pieces/white_bishop.png b/assets/arabian-chess/sprites/pieces/white_bishop.png similarity index 100% rename from arabian-chess/sprites/pieces/white_bishop.png rename to assets/arabian-chess/sprites/pieces/white_bishop.png diff --git a/arabian-chess/sprites/pieces/white_king.png b/assets/arabian-chess/sprites/pieces/white_king.png similarity index 100% rename from arabian-chess/sprites/pieces/white_king.png rename to assets/arabian-chess/sprites/pieces/white_king.png diff --git a/arabian-chess/sprites/pieces/white_knight.png b/assets/arabian-chess/sprites/pieces/white_knight.png similarity index 100% rename from arabian-chess/sprites/pieces/white_knight.png rename to assets/arabian-chess/sprites/pieces/white_knight.png diff --git a/arabian-chess/sprites/pieces/white_pawn.png b/assets/arabian-chess/sprites/pieces/white_pawn.png similarity index 100% rename from arabian-chess/sprites/pieces/white_pawn.png rename to assets/arabian-chess/sprites/pieces/white_pawn.png diff --git a/arabian-chess/sprites/pieces/white_queen.png b/assets/arabian-chess/sprites/pieces/white_queen.png similarity index 100% rename from arabian-chess/sprites/pieces/white_queen.png rename to assets/arabian-chess/sprites/pieces/white_queen.png diff --git a/arabian-chess/sprites/pieces/white_rook.png b/assets/arabian-chess/sprites/pieces/white_rook.png similarity index 100% rename from arabian-chess/sprites/pieces/white_rook.png rename to assets/arabian-chess/sprites/pieces/white_rook.png diff --git a/arabian-chess/xav.png b/assets/arabian-chess/xav.png similarity index 100% rename from arabian-chess/xav.png rename to assets/arabian-chess/xav.png diff --git a/arabian-chess/zayne.png b/assets/arabian-chess/zayne.png similarity index 100% rename from arabian-chess/zayne.png rename to assets/arabian-chess/zayne.png diff --git a/src/app/components/chess-board/chess-board.component.css b/src/app/components/chess-board/chess-board.component.css index 4eec498..47b3421 100644 --- a/src/app/components/chess-board/chess-board.component.css +++ b/src/app/components/chess-board/chess-board.component.css @@ -42,11 +42,41 @@ } .square.light { - background-image: url('/arabian-chess/sprites/board/board_square_white.png'); + background-image: url('/assets/arabian-chess/sprites/board/board_square_white.png'); } .square.dark { - background-image: url('/arabian-chess/sprites/board/board_square_black.png'); + background-image: url('/assets/arabian-chess/sprites/board/board_square_black.png'); +} + +.board-grid--classic { + border-radius: var(--border-radius-md); +} + +.board-grid--classic .square { + background-image: none; + transition: filter 160ms ease; +} + +.board-grid--classic .square.light { + background-color: #f3c8a0; +} + +.board-grid--classic .square.dark { + background-color: #ba6d4b; +} + +.board-grid--classic .square.drag-over { + outline-color: #5a2c28; +} + +.board-grid--classic .square.selected { + outline-color: #5a2c28; +} + +.board-grid--classic .square.highlighted::after { + background: #b9dad1; + border-color: #5a2c28; } .square.highlighted::after { diff --git a/src/app/components/chess-board/chess-board.component.html b/src/app/components/chess-board/chess-board.component.html index 3644300..0704d39 100644 --- a/src/app/components/chess-board/chess-board.component.html +++ b/src/app/components/chess-board/chess-board.component.html @@ -1,5 +1,5 @@
-
+
@for (square of squares; track trackByCoordinate($index, square)) {
diff --git a/src/app/components/chess-board/chess-board.component.ts b/src/app/components/chess-board/chess-board.component.ts index dc38701..0a1a1a8 100644 --- a/src/app/components/chess-board/chess-board.component.ts +++ b/src/app/components/chess-board/chess-board.component.ts @@ -7,6 +7,8 @@ interface BoardSquare { pieceCode: string | null; } +type BoardTheme = 'arabian' | 'classic'; + @Component({ selector: 'app-chess-board', standalone: true, @@ -18,6 +20,7 @@ export class ChessBoardComponent implements OnChanges { @Input({ required: true }) fen = ''; @Input() selectedSquare: string | null = null; @Input() highlightedSquares: string[] = []; + @Input() boardTheme: BoardTheme = 'arabian'; @Output() squareSelected = new EventEmitter(); squares: BoardSquare[] = []; diff --git a/src/app/components/chess-piece/chess-piece.component.ts b/src/app/components/chess-piece/chess-piece.component.ts index bdfb755..6b3e125 100644 --- a/src/app/components/chess-piece/chess-piece.component.ts +++ b/src/app/components/chess-piece/chess-piece.component.ts @@ -1,5 +1,7 @@ import { Component, EventEmitter, Input, Output } from '@angular/core'; +type BoardTheme = 'arabian' | 'classic'; + @Component({ selector: 'app-chess-piece', standalone: true, @@ -8,6 +10,7 @@ import { Component, EventEmitter, Input, Output } from '@angular/core'; }) export class ChessPieceComponent { @Input({ required: true }) pieceCode: string | null = null; + @Input() boardTheme: BoardTheme = 'arabian'; @Input() draggable = false; @Output() pieceDragStart = new EventEmitter(); @Output() pieceDragEnd = new EventEmitter(); @@ -30,12 +33,21 @@ export class ChessPieceComponent { return ''; } - const color = this.pieceCode === this.pieceCode.toUpperCase() ? 'white' : 'black'; - const pieceName = this.getPieceName(this.pieceCode.toLowerCase()); - return `/arabian-chess/sprites/pieces/${color}_${pieceName}.png`; + const isWhite = this.pieceCode === this.pieceCode.toUpperCase(); + const pieceCode = this.pieceCode.toLowerCase(); + + if (this.boardTheme === 'classic') { + const colorPrefix = isWhite ? 'w' : 'b'; + const classicPieceName = this.getClassicPieceName(pieceCode); + return `/assets/ChessAssets/${colorPrefix}_${classicPieceName}.png`; + } + + const arabianColor = isWhite ? 'white' : 'black'; + const arabianPieceName = this.getArabianPieceName(pieceCode); + return `/assets/arabian-chess/sprites/pieces/${arabianColor}_${arabianPieceName}.png`; } - private getPieceName(piece: string): string { + private getArabianPieceName(piece: string): string { switch (piece) { case 'k': return 'king'; @@ -53,4 +65,23 @@ export class ChessPieceComponent { return 'pawn'; } } + + private getClassicPieceName(piece: string): string { + switch (piece) { + case 'k': + return 'King'; + case 'q': + return 'Queen'; + case 'r': + return 'Rook'; + case 'b': + return 'Bishop'; + case 'n': + return 'Knight'; + case 'p': + return 'Pawn'; + default: + return 'Pawn'; + } + } } diff --git a/src/app/pages/game/game.component.css b/src/app/pages/game/game.component.css index b9ca9ea..611d0b5 100644 --- a/src/app/pages/game/game.component.css +++ b/src/app/pages/game/game.component.css @@ -48,6 +48,39 @@ h2 { flex: 0 0 auto; } +.board-theme-card { + background: var(--color-bg-card); + border: var(--border-width) solid var(--color-border); + border-radius: var(--border-radius-md); + padding: var(--size-md-padding); + display: grid; + gap: var(--size-sm); +} + +.board-theme-card h3 { + margin: 0; + color: var(--color-text-primary); + font-size: 1rem; +} + +.board-theme-group { + display: flex; + gap: var(--size-md); + flex-wrap: wrap; +} + +.board-theme-option { + display: inline-flex; + align-items: center; + gap: var(--size-xs); + color: var(--color-text-primary); + font-weight: 600; +} + +.board-theme-option input { + accent-color: var(--color-primary); +} + .move-card { padding: var(--size-lg-padding); } diff --git a/src/app/pages/game/game.component.html b/src/app/pages/game/game.component.html index e0df059..9d54af4 100644 --- a/src/app/pages/game/game.component.html +++ b/src/app/pages/game/game.component.html @@ -48,11 +48,37 @@ [fen]="facade.state.fen" [selectedSquare]="facade.selectedSquare" [highlightedSquares]="facade.highlightedSquares" + [boardTheme]="boardTheme" (squareSelected)="facade.onBoardSquareSelected($event)" />
+
+

Board Design

+
+ + + +
+
+ { @@ -70,6 +74,11 @@ export class GameComponent implements OnInit, OnDestroy { this.syncExportValue(); } + setBoardTheme(theme: BoardTheme): void { + this.boardTheme = theme; + localStorage.setItem(GameComponent.BOARD_THEME_STORAGE_KEY, theme); + } + completeExport(): void { this.syncExportValue(); if (!this.exportValue.trim()) { @@ -220,4 +229,9 @@ export class GameComponent implements OnInit, OnDestroy { private getTimerStorageKey(gameId: string): string { return `nowchess.timer.${gameId}`; } + + private resolveStoredBoardTheme(): BoardTheme { + const stored = localStorage.getItem(GameComponent.BOARD_THEME_STORAGE_KEY); + return stored === 'classic' ? 'classic' : 'arabian'; + } } diff --git a/src/app/pages/welcome/welcome.component.css b/src/app/pages/welcome/welcome.component.css index e919f9b..74d99f7 100644 --- a/src/app/pages/welcome/welcome.component.css +++ b/src/app/pages/welcome/welcome.component.css @@ -1,22 +1,67 @@ .welcome-shell { - min-height: 100vh; + --city-sky-top: #dbefff; + --city-sky-mid: #bfd7eb; + --city-sky-bottom: #95b3ca; + --city-fog: rgba(168, 203, 226, 0.35); + --city-building-a: #8ba8be; + --city-building-b: #7696af; + --city-building-c: #6787a3; + --city-building-edge: rgba(230, 247, 255, 0.2); + --city-window: #bdeeff; + --city-window-soft: rgba(189, 238, 255, 0.25); + --city-billboard-bg: rgba(223, 246, 255, 0.92); + --city-billboard-border: rgba(111, 161, 195, 0.6); + --city-billboard-text: #21435a; + --city-panel-bg: rgba(235, 248, 255, 0.9); + --city-panel-border: rgba(122, 170, 201, 0.55); + --city-panel-input: rgba(255, 255, 255, 0.92); + + min-height: 100svh; display: flex; flex-direction: column; + justify-content: space-between; align-items: center; - justify-content: center; - padding: var(--size-xl); + padding: clamp(1rem, 2.3vw, 1.75rem); position: relative; + overflow: hidden; + background: linear-gradient(180deg, var(--city-sky-top) 0%, var(--city-sky-mid) 58%, var(--city-sky-bottom) 100%); +} + +:host-context([data-theme='dark']) .welcome-shell { + --city-sky-top: #010f1f; + --city-sky-mid: #051424; + --city-sky-bottom: #00626e; + --city-fog: rgba(0, 218, 243, 0.14); + --city-building-a: #122131; + --city-building-b: #1c2b3c; + --city-building-c: #273647; + --city-building-edge: rgba(255, 255, 255, 0.08); + --city-window: #00e5ff; + --city-window-soft: rgba(0, 229, 255, 0.22); + --city-billboard-bg: rgba(0, 218, 243, 0.16); + --city-billboard-border: rgba(0, 229, 255, 0.45); + --city-billboard-text: #d4e4fa; + --city-panel-bg: rgba(18, 33, 49, 0.88); + --city-panel-border: rgba(0, 218, 243, 0.35); + --city-panel-input: rgba(5, 20, 36, 0.88); +} + +.sky-vignette { + position: absolute; + inset: 0; + pointer-events: none; + background: linear-gradient(180deg, transparent 45%, var(--city-fog) 100%); + opacity: 0.9; } .clouds-container { display: flex; justify-content: center; align-items: flex-start; - gap: 60px; + gap: clamp(1.25rem, 4vw, 3.5rem); width: 100%; - max-width: 900px; - margin-bottom: var(--size-xl); - position: relative; + max-width: 980px; + margin-top: clamp(2.8rem, 6vh, 5.2rem); z-index: 1; } @@ -27,7 +72,7 @@ display: flex; align-items: center; justify-content: center; - filter: drop-shadow(0 4px 10px rgba(0, 0, 0, 0.12)); + filter: drop-shadow(0 8px 18px rgba(0, 0, 0, 0.18)); } .plane-body { @@ -54,7 +99,7 @@ display: flex; align-items: center; justify-content: center; - filter: drop-shadow(0 4px 10px rgba(0, 0, 0, 0.12)); + filter: drop-shadow(0 6px 12px rgba(0, 0, 0, 0.15)); } .cloud::before { @@ -85,91 +130,288 @@ height: 100px; object-fit: contain; z-index: 10; - filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.15)); position: relative; } -.gif-with-halo { +.welcome-intro { position: relative; - display: inline-block; -} - -.gif-with-halo::before { - content: ''; - position: absolute; - top: -10px; - left: 50%; - transform: translateX(-50%); - width: 75px; - height: 15px; - border: 2px solid rgba(255, 215, 0, 0.7); - border-radius: 50%; - box-shadow: 0 0 8px rgba(255, 215, 0, 0.5); - z-index: 5; -} - -.welcome-card { - width: min(900px, 100%); - border-radius: var(--border-radius-lg); - border: var(--border-width) solid var(--color-border); - background: var(--color-bg-main); - padding: var(--size-xl-padding); - box-shadow: var(--shadow-md); + z-index: 2; + margin-top: clamp(0.4rem, 1.1vh, 1rem); + text-align: center; } h1 { - margin: 0 0 var(--size-xs); - color: var(--color-text-primary); - font-size: var(--heading-h1); + margin: 0; + color: var(--city-billboard-text); + font-size: clamp(1.65rem, 3.6vw, 2.65rem); + letter-spacing: 0.04em; + text-transform: uppercase; } p { - margin: 0 0 var(--size-lg); + margin: 0; + color: var(--city-billboard-text); } -.mode-grid { +.welcome-intro p { + margin-top: 0.25rem; + opacity: 0.9; + font-size: clamp(0.88rem, 1.6vw, 1.02rem); +} + +.skyline-controls { + position: relative; + width: min(1200px, 100%); + min-height: clamp(280px, 43vh, 500px); display: grid; - grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); - gap: var(--size-xl-gap); + grid-template-columns: repeat(4, minmax(110px, 1fr)); + gap: clamp(0.6rem, 1.2vw, 1.2rem); + align-items: end; + z-index: 2; + padding-inline: clamp(0.2rem, 1.2vw, 0.9rem); + margin-top: auto; +} + +.tower { + --tower-height: clamp(210px, 38vh, 430px); + position: relative; + height: var(--tower-height); + border-radius: 14px 14px 0 0; + overflow: visible; + background: linear-gradient(180deg, var(--city-building-b) 0%, var(--city-building-a) 65%, var(--city-building-c) 100%); + border: 1px solid var(--city-building-edge); + box-shadow: inset 0 0 30px rgba(0, 0, 0, 0.2); +} + +.tower::before { + content: ''; + position: absolute; + inset: 0; + background: linear-gradient(90deg, transparent 0%, rgba(255, 255, 255, 0.08) 48%, transparent 52%); + opacity: 0.55; + pointer-events: none; +} + +.tower-windows { + position: absolute; + left: 18%; + right: 18%; + bottom: 22px; + display: grid; + gap: 14px; +} + +.tower-windows span { + height: 2px; + border-radius: 999px; + background: var(--city-window); + box-shadow: 0 0 5px var(--city-window); + opacity: 0.28; +} + +.tower-bot { + --tower-height: clamp(245px, 48vh, 520px); +} + +.tower-1v1 { + --tower-height: clamp(200px, 39vh, 430px); +} + +.tower-join { + --tower-height: clamp(225px, 44vh, 480px); +} + +.tower-import { + --tower-height: clamp(265px, 51vh, 560px); } .mode { - border: var(--border-width) solid var(--color-border); - border-radius: var(--border-radius-md); - padding: var(--size-lg-padding); + border-radius: 0.8rem; + border: 1px solid var(--city-billboard-border); + background: var(--city-billboard-bg); + color: var(--city-billboard-text); + backdrop-filter: blur(4px); text-align: left; display: grid; - gap: var(--size-xs); + gap: 0.2rem; + transition: transform 180ms ease, box-shadow 180ms ease, border-color 180ms ease; +} + +.mode-billboard { + position: absolute; + left: 12%; + right: 12%; + top: 0; + transform: translateY(-56%); + padding: 0.8rem 0.9rem; } .mode span { - font-size: 1.15rem; - color: var(--color-text-primary); + font-size: clamp(0.95rem, 1.4vw, 1.12rem); + font-weight: 700; + letter-spacing: 0.02em; } .mode small { - color: var(--color-text-primary); - opacity: 0.9; + color: var(--city-billboard-text); + opacity: 0.85; + font-size: 0.75rem; } .mode-active { - background: var(--color-secondary-mint); cursor: pointer; } .mode-active:hover:enabled { - background: var(--color-secondary-blue); + transform: translateY(-60%) scale(1.01); + box-shadow: 0 0 22px var(--city-window-soft); } -.mode-disabled { - background: var(--color-bg-card); - opacity: 0.75; +.mode-active:disabled { + opacity: 0.6; + cursor: not-allowed; +} + +.interaction-deck { + width: min(880px, 100%); + display: grid; + gap: 0.7rem; + margin-top: 0.45rem; + margin-bottom: clamp(0.5rem, 1.4vh, 0.95rem); + z-index: 3; +} + +.difficulty-selector, +.join-game-form, +.import-game-form { + background: var(--city-panel-bg); + border: 1px solid var(--city-panel-border); + border-radius: 12px; + padding: 0.8rem; + backdrop-filter: blur(6px); +} + +.difficulty-selector p, +.join-game-form p, +.import-game-form p { + margin: 0 0 0.65rem; + font-weight: 600; +} + +.difficulty-buttons { + display: flex; + gap: 0.55rem; + flex-wrap: wrap; +} + +.difficulty-btn { + flex: 1; + min-width: 78px; + padding: 0.45rem 0.65rem; + border: 1px solid var(--city-panel-border); + border-radius: 9px; + cursor: pointer; + font-weight: 600; + background: rgba(170, 226, 255, 0.68); + color: var(--city-billboard-text); +} + +.difficulty-btn:hover:enabled { + filter: brightness(0.96); +} + +.join-game-input-group { + display: flex; + gap: 0.5rem; + flex-wrap: wrap; +} + +.join-game-input, +.import-game-text { + width: 100%; + border: 1px solid var(--city-panel-border); + border-radius: 9px; + background: var(--city-panel-input); + color: var(--city-billboard-text); + font-family: inherit; +} + +.join-game-input { + flex: 1; + min-width: 155px; + padding: 0.58rem 0.72rem; + font-size: 0.95rem; +} + +.import-game-text { + margin-top: 0.55rem; + margin-bottom: 0.55rem; + min-height: 110px; + resize: vertical; + padding: 0.58rem 0.72rem; + font-size: 0.95rem; +} + +.join-game-input:focus, +.import-game-text:focus { + outline: none; + border-color: var(--city-window); + box-shadow: 0 0 0 2px var(--city-window-soft); +} + +.import-mode-group { + display: flex; + gap: 0.8rem; + margin-bottom: 0.5rem; +} + +.import-mode-option { + display: inline-flex; + align-items: center; + gap: 0.35rem; + font-size: 0.92rem; +} + +.join-game-btn { + padding: 0.52rem 0.72rem; + border-radius: 9px; + border: 1px solid var(--city-panel-border); + cursor: pointer; + font-weight: 600; + color: var(--city-billboard-text); +} + +.join-game-btn.join { + background: rgba(170, 226, 255, 0.68); +} + +.join-game-btn.join:hover:enabled { + filter: brightness(0.95); +} + +.join-game-btn.cancel { + background: rgba(238, 243, 252, 0.82); +} + +.join-game-btn.cancel:hover:enabled { + filter: brightness(0.96); +} + +.join-game-btn:disabled, +.difficulty-btn:disabled { + opacity: 0.56; + cursor: not-allowed; } .error { - color: var(--color-text-primary); - font-weight: 700; - margin-top: var(--size-xl); + margin-top: 0.05rem; + margin-bottom: 0; + color: #ffd0d0; + background: rgba(146, 0, 16, 0.45); + border: 1px solid rgba(255, 170, 170, 0.6); + border-radius: 9px; + padding: 0.5rem 0.65rem; + font-weight: 600; } .plane-left { @@ -187,281 +429,57 @@ p { } @keyframes float { - 0%, 100% { - transform: translateY(0px); + 0%, + 100% { + transform: translateY(0); } + 50% { - transform: translateY(-15px); + transform: translateY(-12px); } } -@media (max-width: 768px) { - .welcome-shell { - padding: var(--size-lg); - } - +@media (max-width: 900px) { .clouds-container { - gap: 30px; - margin-bottom: var(--size-lg); + gap: 1rem; } - .plane { - width: 240px; - height: 110px; + .skyline-controls { + grid-template-columns: repeat(2, minmax(130px, 1fr)); + min-height: clamp(350px, 53vh, 620px); } - .plane-gif { - width: 55px; - height: 55px; - transform: translateX(-20px) translateY(12px); + .tower { + --tower-height: clamp(170px, 25vh, 280px); + } +} + +@media (max-width: 560px) { + .welcome-shell { + padding: 0.75rem; } - .cloud { - width: 170px; - height: 75px; + .skyline-controls { + gap: 0.45rem; + min-height: clamp(360px, 57vh, 650px); } - .cloud::before { - width: 65px; - height: 65px; - box-shadow: 40px 0 0 7px #ffffff, 80px 0 0 3px #ffffff, 20px -13px 0 10px #ffffff, 60px -10px 0 8px #ffffff; - } - - .cloud::after { - width: 170px; - height: 38px; - } - - .cloud-gif { - width: 140px; - height: 140px; - } - - .gif-with-halo::before { - top: -8px; - width: 80px; - height: 12px; - border: 1.5px solid rgba(255, 215, 0, 0.7); - } - - .welcome-card { - padding: var(--size-xl); - } - - h1 { - font-size: var(--heading-h1-mobile); - } - - p { - font-size: 0.875rem; - margin: 0 0 var(--size-lg); - } - - .mode-grid { - grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); - gap: var(--size-md-gap); - } - - .mode { - padding: var(--size-md-padding); - gap: var(--size-xs-gap); + .mode-billboard { + left: 10%; + right: 10%; + padding: 0.72rem 0.72rem; } .mode span { - font-size: 1rem; + font-size: 0.9rem; } .mode small { font-size: 0.7rem; } - .error { - font-size: 0.75rem; + .interaction-deck { + margin-top: 0.3rem; + margin-bottom: 0.45rem; } } - -@media (max-width: 480px) { - .welcome-shell { - padding: var(--size-sm); - } - - .welcome-card { - padding: var(--size-lg-padding); - border-radius: var(--border-radius-md); - } - - h1 { - font-size: var(--heading-h1-small); - margin: 0 0 var(--size-xs); - } - - p { - font-size: 0.8rem; - margin: 0 0 var(--size-md); - } - - .mode-grid { - grid-template-columns: 1fr; - } - - .mode { - padding: var(--size-md-padding); - } - - .mode span { - font-size: 0.95rem; - } -} - -.difficulty-selector { - grid-column: 1 / -1; - background: var(--color-bg-card); - border: var(--border-width) solid var(--color-border); - border-radius: var(--border-radius-md); - padding: var(--size-lg-padding); - margin: var(--size-md) 0; -} - -.difficulty-selector p { - margin: 0 0 var(--size-md); - font-weight: 600; -} - -.difficulty-buttons { - display: flex; - gap: var(--size-md-gap); - flex-wrap: wrap; -} - -.difficulty-btn { - flex: 1; - min-width: 80px; - padding: var(--size-md-padding); - border: var(--border-width) solid var(--color-border); - border-radius: var(--border-radius-md); - cursor: pointer; - font-weight: 600; - transition: all 0.3s ease; -} - -.difficulty-btn.easy { - background: var(--color-success-light, #d4edda); - color: var(--color-text-primary); -} - -.difficulty-btn.easy:hover:enabled { - background: var(--color-success, #28a745); - color: white; -} - -.difficulty-btn.medium { - background: var(--color-warning-light, #fff3cd); - color: var(--color-text-primary); -} - -.difficulty-btn.medium:hover:enabled { - background: var(--color-warning, #ffc107); - color: var(--color-text-primary); -} - -.difficulty-btn.hard { - background: var(--color-danger-light, #f8d7da); - color: var(--color-text-primary); -} - -.difficulty-btn.hard:hover:enabled { - background: var(--color-danger, #dc3545); - color: white; -} - -.join-game-form { - grid-column: 1 / -1; - background: var(--color-bg-card); - border: var(--border-width) solid var(--color-border); - border-radius: var(--border-radius-md); - padding: var(--size-lg-padding); - margin: var(--size-md) 0; -} - -.join-game-form p { - margin: 0 0 var(--size-md); - font-weight: 600; -} - -.join-game-input-group { - display: flex; - gap: var(--size-md-gap); - flex-wrap: wrap; -} - -.join-game-input { - flex: 1; - min-width: 150px; - padding: var(--size-md-padding); - border: var(--border-width) solid var(--color-border); - border-radius: var(--border-radius-md); - background: var(--color-bg-input); - color: var(--color-text-primary); - font-family: inherit; - font-size: 1rem; - transition: border-color 0.3s ease; -} - -.join-game-input:focus { - outline: none; - border-color: var(--color-secondary-mint); - box-shadow: 0 0 0 3px rgba(185, 218, 209, 0.2); -} - -.join-game-input:disabled { - background: var(--color-bg-card); - opacity: 0.6; -} - -.join-game-btn { - padding: var(--size-md-padding) var(--size-lg); - border: var(--border-width) solid var(--color-border); - border-radius: var(--border-radius-md); - cursor: pointer; - font-weight: 600; - font-size: 0.95rem; - transition: all 0.3s ease; -} - -.join-game-btn.join { - background: var(--color-secondary-mint); - color: var(--color-text-primary); -} - -.join-game-btn.join:hover:enabled { - background: var(--color-secondary-blue); -} - -.join-game-btn.join:disabled { - opacity: 0.6; - cursor: not-allowed; -} - -.join-game-btn.cancel { - background: var(--color-bg-card); - color: var(--color-text-primary); -} - -.join-game-btn.cancel:hover:enabled { - background: var(--color-border); -} - -.join-game-btn.cancel:disabled { - opacity: 0.6; - cursor: not-allowed; -} - -.difficulty-btn.hard:hover:enabled { - background: var(--color-danger, #dc3545); - color: white; -} - -.difficulty-btn:disabled { - opacity: 0.6; - cursor: not-allowed; -} diff --git a/src/app/pages/welcome/welcome.component.html b/src/app/pages/welcome/welcome.component.html index 254d5c7..4d1d7ca 100644 --- a/src/app/pages/welcome/welcome.component.html +++ b/src/app/pages/welcome/welcome.component.html @@ -8,62 +8,88 @@
+ + +
- Player One + Player One
- Plane - Raf + Plane + Raf
- Player Two + Player Two
-
+ +

Welcome to NowChess

Pick a mode to begin.

+
-
- + + - @if (showDifficultySelector) { -
-

Select difficulty:

-
- - - -
-
- } - - + + - + + - -
+ + +
+ +
+ @if (showDifficultySelector) { +
+

Select difficulty:

+
+ + + +
+
+ } @if (showJoinGameForm) {
diff --git a/src/app/pages/welcome/welcome.component.ts b/src/app/pages/welcome/welcome.component.ts index a948317..0bb52c0 100644 --- a/src/app/pages/welcome/welcome.component.ts +++ b/src/app/pages/welcome/welcome.component.ts @@ -11,7 +11,7 @@ import { GameApiService } from '../../services/game-api.service'; standalone: true, imports: [CommonModule, FormsModule], templateUrl: './welcome.component.html', - styleUrl: './welcome.component.css' + styleUrls: ['./welcome.component.css'] }) export class WelcomeComponent { creating = false;