valtech-components 4.0.455 → 4.0.457

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (28) hide show
  1. package/esm2022/lib/components/organisms/mini-games/bubble-blitz-game.component.mjs +9 -18
  2. package/esm2022/lib/components/organisms/mini-games/chessimals-engine.mjs +29 -107
  3. package/esm2022/lib/components/organisms/mini-games/chessimals-game.component.mjs +9 -18
  4. package/esm2022/lib/components/organisms/mini-games/memory-game.component.mjs +9 -18
  5. package/esm2022/lib/components/organisms/mini-games/mini-games.i18n.mjs +9 -159
  6. package/esm2022/lib/components/organisms/mini-games/simon-game.component.mjs +9 -18
  7. package/esm2022/lib/components/organisms/mini-games/types.mjs +1 -1
  8. package/esm2022/lib/version.mjs +2 -2
  9. package/esm2022/mini-games/public-api.mjs +2 -34
  10. package/esm2022/public-api.mjs +1 -3
  11. package/fesm2022/valtech-components-mini-games.mjs +2 -34
  12. package/fesm2022/valtech-components-mini-games.mjs.map +1 -1
  13. package/fesm2022/valtech-components.mjs +71 -2116
  14. package/fesm2022/valtech-components.mjs.map +1 -1
  15. package/lib/components/organisms/mini-games/bubble-blitz-game.component.d.ts +0 -2
  16. package/lib/components/organisms/mini-games/chessimals-game.component.d.ts +1 -3
  17. package/lib/components/organisms/mini-games/memory-game.component.d.ts +0 -2
  18. package/lib/components/organisms/mini-games/simon-game.component.d.ts +0 -2
  19. package/lib/components/organisms/mini-games/types.d.ts +1 -74
  20. package/lib/version.d.ts +1 -1
  21. package/mini-games/public-api.d.ts +0 -4
  22. package/package.json +1 -2
  23. package/public-api.d.ts +0 -2
  24. package/esm2022/lib/components/organisms/mini-games/christianity-game.component.mjs +0 -1731
  25. package/esm2022/lib/directives/light-ripple.directive.mjs +0 -57
  26. package/lib/components/organisms/mini-games/christianity-game.component.d.ts +0 -113
  27. package/lib/directives/light-ripple.directive.d.ts +0 -8
  28. package/src/lib/assets/games/christianity/card-symbol.svg +0 -51
@@ -1,5 +1,5 @@
1
1
  import * as i0 from '@angular/core';
2
- import { inject, InjectionToken, makeEnvironmentProviders, APP_INITIALIZER, ErrorHandler, Injectable, DestroyRef, Inject, signal, computed, PLATFORM_ID, isDevMode, Optional, runInInjectionContext, effect, Pipe, TemplateRef, ViewContainerRef, input, Directive, ElementRef, Renderer2, HostListener, EventEmitter, Component, Input, Output, ChangeDetectionStrategy, HostBinding, SecurityContext, NgZone, ViewChild, ChangeDetectorRef, output, ContentChild, model, ViewEncapsulation, untracked, viewChild, Injector, isSignal } from '@angular/core';
2
+ import { inject, InjectionToken, makeEnvironmentProviders, APP_INITIALIZER, ErrorHandler, Injectable, DestroyRef, Inject, signal, computed, PLATFORM_ID, isDevMode, Optional, runInInjectionContext, effect, Pipe, TemplateRef, ViewContainerRef, input, Directive, EventEmitter, Component, Input, Output, ChangeDetectionStrategy, HostBinding, HostListener, SecurityContext, NgZone, ViewChild, ElementRef, ChangeDetectorRef, output, ContentChild, model, ViewEncapsulation, untracked, viewChild, Injector, isSignal } from '@angular/core';
3
3
  import { BehaviorSubject, throwError, Subject, map, distinctUntilChanged, filter as filter$1, take as take$1, firstValueFrom, of, from, EMPTY, Observable, interval, defer, timer, merge, concat, debounceTime, switchMap as switchMap$1, catchError as catchError$1, takeUntil, isObservable, forkJoin, race, tap as tap$1, Subscription, shareReplay as shareReplay$1 } from 'rxjs';
4
4
  import { catchError, switchMap, finalize, filter, take, timeout, map as map$1, tap, shareReplay, distinctUntilChanged as distinctUntilChanged$1, retry, debounceTime as debounceTime$1, takeUntil as takeUntil$1 } from 'rxjs/operators';
5
5
  import * as i1$3 from '@angular/common/http';
@@ -49,7 +49,6 @@ import { Capacitor } from '@capacitor/core';
49
49
  import { ImageCropperComponent } from 'ngx-image-cropper';
50
50
  import Compressor from 'compressorjs';
51
51
  import { Calendar } from 'vanilla-calendar-pro';
52
- import { CdkDrag, CdkDropList } from '@angular/cdk/drag-drop';
53
52
  import 'prismjs/components/prism-scss';
54
53
  import 'prismjs/components/prism-json';
55
54
  import { BrowserMultiFormatReader } from '@zxing/browser';
@@ -59,7 +58,7 @@ import fixWebmDuration from 'fix-webm-duration';
59
58
  * Current version of valtech-components.
60
59
  * This is automatically updated during the publish process.
61
60
  */
62
- const VERSION = '4.0.455';
61
+ const VERSION = '4.0.457';
63
62
 
64
63
  // Control de estado de refresco (singleton a nivel de módulo)
65
64
  let isRefreshing = false;
@@ -10118,61 +10117,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
10118
10117
  }]
10119
10118
  }], ctorParameters: () => [] });
10120
10119
 
10121
- class LightRippleDirective {
10122
- constructor() {
10123
- this.host = inject(ElementRef);
10124
- this.renderer = inject(Renderer2);
10125
- }
10126
- createRipple(event) {
10127
- const element = this.host.nativeElement;
10128
- const rect = element.getBoundingClientRect();
10129
- const size = Math.max(rect.width, rect.height) * 1.55;
10130
- const ripple = this.renderer.createElement('span');
10131
- const x = event.clientX - rect.left - size / 2;
10132
- const y = event.clientY - rect.top - size / 2;
10133
- if (getComputedStyle(element).position === 'static') {
10134
- this.renderer.setStyle(element, 'position', 'relative');
10135
- }
10136
- this.renderer.setStyle(element, 'overflow', 'hidden');
10137
- this.renderer.setStyle(element, 'isolation', 'isolate');
10138
- this.renderer.setStyle(element, 'touch-action', 'manipulation');
10139
- this.renderer.setStyle(ripple, 'position', 'absolute');
10140
- this.renderer.setStyle(ripple, 'left', `${x}px`);
10141
- this.renderer.setStyle(ripple, 'top', `${y}px`);
10142
- this.renderer.setStyle(ripple, 'width', `${size}px`);
10143
- this.renderer.setStyle(ripple, 'height', `${size}px`);
10144
- this.renderer.setStyle(ripple, 'border-radius', '999px');
10145
- this.renderer.setStyle(ripple, 'pointer-events', 'none');
10146
- this.renderer.setStyle(ripple, 'z-index', '1');
10147
- this.renderer.setStyle(ripple, 'background', 'radial-gradient(circle, rgba(255,255,255,0.98) 0 0.16rem, rgba(191,219,254,0.9) 0.18rem 0.34rem, rgba(96,165,250,0.46) 0.36rem 23%, rgba(96,165,250,0.18) 38%, transparent 70%)');
10148
- this.renderer.setStyle(ripple, 'box-shadow', '0 0 0.75rem rgba(255,255,255,0.85), 0 0 1.8rem rgba(96,165,250,0.52)');
10149
- this.renderer.appendChild(element, ripple);
10150
- ripple
10151
- .animate([
10152
- { opacity: 0.88, transform: 'scale(0.08)' },
10153
- { opacity: 0.48, transform: 'scale(0.48)' },
10154
- { opacity: 0, transform: 'scale(1)' },
10155
- ], { duration: 680, easing: 'cubic-bezier(0.16, 0.84, 0.24, 1)' })
10156
- .finished.finally(() => {
10157
- if (ripple.parentNode === element) {
10158
- this.renderer.removeChild(element, ripple);
10159
- }
10160
- });
10161
- }
10162
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: LightRippleDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
10163
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.2.14", type: LightRippleDirective, isStandalone: true, selector: "[valLightRipple]", host: { listeners: { "pointerdown": "createRipple($event)" } }, ngImport: i0 }); }
10164
- }
10165
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: LightRippleDirective, decorators: [{
10166
- type: Directive,
10167
- args: [{
10168
- selector: '[valLightRipple]',
10169
- standalone: true,
10170
- }]
10171
- }], propDecorators: { createRipple: [{
10172
- type: HostListener,
10173
- args: ['pointerdown', ['$event']]
10174
- }] } });
10175
-
10176
10120
  /**
10177
10121
  * Presets de botón por defecto provistos por la librería.
10178
10122
  *
@@ -61087,66 +61031,18 @@ const CHESSIMALS_BOT_PROFILES = [
61087
61031
  labelKey: 'chessimalsBotSentinel',
61088
61032
  descriptionKey: 'chessimalsBotSentinelBody',
61089
61033
  },
61090
- {
61091
- id: 'oracle',
61092
- difficulty: 'hard',
61093
- avatar: '🔮',
61094
- labelKey: 'chessimalsBotOracle',
61095
- descriptionKey: 'chessimalsBotOracleBody',
61096
- },
61097
- {
61098
- id: 'ambusher',
61099
- difficulty: 'hard',
61100
- avatar: '🪤',
61101
- labelKey: 'chessimalsBotAmbusher',
61102
- descriptionKey: 'chessimalsBotAmbusherBody',
61103
- },
61104
- {
61105
- id: 'locksmith',
61106
- difficulty: 'hard',
61107
- avatar: '🔐',
61108
- labelKey: 'chessimalsBotLocksmith',
61109
- descriptionKey: 'chessimalsBotLocksmithBody',
61110
- },
61111
- {
61112
- id: 'storm',
61113
- difficulty: 'hard',
61114
- avatar: '🌩️',
61115
- labelKey: 'chessimalsBotStorm',
61116
- descriptionKey: 'chessimalsBotStormBody',
61117
- },
61118
- {
61119
- id: 'matriarch',
61120
- difficulty: 'hard',
61121
- avatar: '👑',
61122
- labelKey: 'chessimalsBotMatriarch',
61123
- descriptionKey: 'chessimalsBotMatriarchBody',
61124
- },
61125
- {
61126
- id: 'endgame',
61127
- difficulty: 'hard',
61128
- avatar: '⌛',
61129
- labelKey: 'chessimalsBotEndgame',
61130
- descriptionKey: 'chessimalsBotEndgameBody',
61131
- },
61132
61034
  ];
61133
61035
  const BOT_STYLES = {
61134
- explorer: { advancement: 1.05, capture: 0.82, safety: 0.62, power: 0.8, center: 1.15, unlock: 1.05, reply: 0.7, randomness: 260, spread: 0.68, mobility: 0.75, trap: 0.5, endgame: 0.55 },
61135
- impulsive: { advancement: 0.9, capture: 1.45, safety: 0.48, power: 1.15, center: 0.8, unlock: 0.9, reply: 0.55, randomness: 290, spread: 0.62, mobility: 0.85, trap: 0.62, endgame: 0.5 },
61136
- runner: { advancement: 1.55, capture: 0.78, safety: 0.5, power: 0.95, center: 0.7, unlock: 1.1, reply: 0.55, randomness: 250, spread: 0.6, mobility: 0.72, trap: 0.45, endgame: 1.1 },
61137
- hunter: { advancement: 0.95, capture: 1.45, safety: 0.9, power: 1.05, center: 0.95, unlock: 0.95, reply: 1, randomness: 90, spread: 0.3, mobility: 0.95, trap: 0.82, endgame: 0.76 },
61138
- guardian: { advancement: 0.88, capture: 1, safety: 1.45, power: 0.85, center: 1.05, unlock: 1, reply: 1.15, randomness: 70, spread: 0.26, mobility: 0.82, trap: 0.72, endgame: 0.72 },
61139
- jumper: { advancement: 1.12, capture: 1, safety: 0.92, power: 1.42, center: 1.18, unlock: 1.08, reply: 0.95, randomness: 95, spread: 0.32, mobility: 1.15, trap: 0.9, endgame: 0.82 },
61140
- strategist: { advancement: 1.05, capture: 1.08, safety: 1.22, power: 1.08, center: 1.16, unlock: 1.1, reply: 1.25, randomness: 22, spread: 0.14, mobility: 1.08, trap: 1.06, endgame: 1 },
61141
- predator: { advancement: 0.98, capture: 1.68, safety: 1.02, power: 1.34, center: 1, unlock: 1, reply: 1.12, randomness: 28, spread: 0.16, mobility: 1.02, trap: 1.18, endgame: 0.82 },
61142
- sprinter: { advancement: 1.72, capture: 0.9, safety: 0.95, power: 1.08, center: 0.86, unlock: 1.18, reply: 1, randomness: 26, spread: 0.15, mobility: 0.95, trap: 0.78, endgame: 1.42 },
61143
- sentinel: { advancement: 0.9, capture: 1.12, safety: 1.72, power: 0.95, center: 1.28, unlock: 1.05, reply: 1.38, randomness: 18, spread: 0.12, mobility: 0.86, trap: 1.04, endgame: 0.84 },
61144
- oracle: { advancement: 1, capture: 1.12, safety: 1.42, power: 1.1, center: 1.18, unlock: 1.08, reply: 1.8, randomness: 8, spread: 0.08, mobility: 1.06, trap: 1.22, endgame: 1.08 },
61145
- ambusher: { advancement: 0.9, capture: 1.48, safety: 1.08, power: 1.46, center: 1.05, unlock: 1.02, reply: 1.32, randomness: 14, spread: 0.1, mobility: 1.12, trap: 1.72, endgame: 0.92 },
61146
- locksmith: { advancement: 0.88, capture: 1.04, safety: 1.55, power: 1.02, center: 1.48, unlock: 1.12, reply: 1.52, randomness: 12, spread: 0.1, mobility: 1.58, trap: 1.24, endgame: 0.86 },
61147
- storm: { advancement: 1.18, capture: 1.38, safety: 0.98, power: 1.62, center: 1.08, unlock: 1.18, reply: 1.22, randomness: 18, spread: 0.13, mobility: 1.36, trap: 1.28, endgame: 1.02 },
61148
- matriarch: { advancement: 0.96, capture: 1.18, safety: 1.64, power: 1.18, center: 1.22, unlock: 1.08, reply: 1.66, randomness: 10, spread: 0.08, mobility: 1.02, trap: 1.36, endgame: 1 },
61149
- endgame: { advancement: 1.46, capture: 1, safety: 1.28, power: 1.04, center: 0.94, unlock: 1.08, reply: 1.44, randomness: 10, spread: 0.09, mobility: 0.98, trap: 1.02, endgame: 1.86 },
61036
+ explorer: { advancement: 1.05, capture: 0.82, safety: 0.62, power: 0.8, center: 1.15, unlock: 1.05, reply: 0.7, randomness: 260, spread: 0.68 },
61037
+ impulsive: { advancement: 0.9, capture: 1.45, safety: 0.48, power: 1.15, center: 0.8, unlock: 0.9, reply: 0.55, randomness: 290, spread: 0.62 },
61038
+ runner: { advancement: 1.55, capture: 0.78, safety: 0.5, power: 0.95, center: 0.7, unlock: 1.1, reply: 0.55, randomness: 250, spread: 0.6 },
61039
+ hunter: { advancement: 0.95, capture: 1.45, safety: 0.9, power: 1.05, center: 0.95, unlock: 0.95, reply: 1, randomness: 90, spread: 0.3 },
61040
+ guardian: { advancement: 0.88, capture: 1, safety: 1.45, power: 0.85, center: 1.05, unlock: 1, reply: 1.15, randomness: 70, spread: 0.26 },
61041
+ jumper: { advancement: 1.12, capture: 1, safety: 0.92, power: 1.42, center: 1.18, unlock: 1.08, reply: 0.95, randomness: 95, spread: 0.32 },
61042
+ strategist: { advancement: 1.05, capture: 1.08, safety: 1.22, power: 1.08, center: 1.16, unlock: 1.1, reply: 1.25, randomness: 22, spread: 0.14 },
61043
+ predator: { advancement: 0.98, capture: 1.68, safety: 1.02, power: 1.34, center: 1, unlock: 1, reply: 1.12, randomness: 28, spread: 0.16 },
61044
+ sprinter: { advancement: 1.72, capture: 0.9, safety: 0.95, power: 1.08, center: 0.86, unlock: 1.18, reply: 1, randomness: 26, spread: 0.15 },
61045
+ sentinel: { advancement: 0.9, capture: 1.12, safety: 1.72, power: 0.95, center: 1.28, unlock: 1.05, reply: 1.38, randomness: 18, spread: 0.12 },
61150
61046
  };
61151
61047
  const DEFAULT_BOT_PROFILE_BY_DIFFICULTY = {
61152
61048
  easy: 'explorer',
@@ -61232,17 +61128,8 @@ function chooseChessimalsBotMove(state, difficulty = 'normal', profileId = DEFAU
61232
61128
  if (moves.length === 0)
61233
61129
  return undefined;
61234
61130
  const style = BOT_STYLES[profileId] ?? BOT_STYLES[DEFAULT_BOT_PROFILE_BY_DIFFICULTY[difficulty]];
61235
- const quickScored = moves
61236
- .map((move) => ({ move, score: scoreBotMove(state, move, difficulty, style) }))
61237
- .sort((a, b) => b.score - a.score);
61238
- const lookaheadLimit = difficulty === 'hard' ? 32 : difficulty === 'normal' ? 24 : 0;
61239
- const scored = quickScored
61240
- .map((item, index) => ({
61241
- move: item.move,
61242
- score: index < lookaheadLimit
61243
- ? scoreBotMoveWithLookahead(state, item.move, difficulty, style)
61244
- : item.score,
61245
- }))
61131
+ const scored = moves
61132
+ .map((move) => ({ move, score: scoreBotMoveWithLookahead(state, move, difficulty, style) }))
61246
61133
  .sort((a, b) => b.score - a.score);
61247
61134
  if (difficulty === 'easy') {
61248
61135
  const playable = scored.filter((item) => item.score > -3000);
@@ -61260,6 +61147,9 @@ function chooseChessimalsBotMove(state, difficulty = 'normal', profileId = DEFAU
61260
61147
  if (blockingMove)
61261
61148
  return blockingMove.move;
61262
61149
  }
61150
+ const conservativeCapture = chooseConservativeHardCapture(state, scored);
61151
+ if (conservativeCapture)
61152
+ return conservativeCapture;
61263
61153
  return scored[0]?.move;
61264
61154
  }
61265
61155
  function applyChessimalsMove(state, candidate) {
@@ -61440,7 +61330,7 @@ function getPowerMoves(state, piece, animal) {
61440
61330
  const directions = getPowerDirections(animal);
61441
61331
  const moves = [];
61442
61332
  for (const direction of directions) {
61443
- for (let distance = 1; distance < state.boardSize; distance += 1) {
61333
+ for (let distance = 1; distance <= 3; distance += 1) {
61444
61334
  const target = {
61445
61335
  row: piece.position.row + direction.row * distance,
61446
61336
  col: piece.position.col + direction.col * distance,
@@ -61501,7 +61391,7 @@ function getKangarooMoves(state, piece) {
61501
61391
  }
61502
61392
  return moves;
61503
61393
  }
61504
- function scoreBotMove(state, move, difficulty, style, includeTacticalPressure = true) {
61394
+ function scoreBotMove(state, move, difficulty, style) {
61505
61395
  const color = state.currentTurn;
61506
61396
  const targetPiece = move.capturesPieceId
61507
61397
  ? activePieces(state).find((piece) => piece.id === move.capturesPieceId)
@@ -61527,14 +61417,6 @@ function scoreBotMove(state, move, difficulty, style, includeTacticalPressure =
61527
61417
  score += 14 * style.power;
61528
61418
  if (wouldUnlockPower(state, color, move.to))
61529
61419
  score += 90 * style.unlock;
61530
- if (includeTacticalPressure && state.boardSize <= 6) {
61531
- score += countPowerReachAfterMove(state, move, color) * (difficulty === 'hard' ? 8 : 4) * style.mobility;
61532
- score += countProtectedThreatsAfterMove(state, move, color) * (difficulty === 'hard' ? 36 : 18) * style.trap;
61533
- score += scoreEndgamePressure(state, move, color) * style.endgame;
61534
- }
61535
- else {
61536
- score += scoreEndgamePressure(state, move, color) * style.endgame;
61537
- }
61538
61420
  if (difficulty === 'hard' && isSquareVulnerableAfterMove(state, move)) {
61539
61421
  score -= (targetPiece ? 80 : 140) * style.safety;
61540
61422
  }
@@ -61565,7 +61447,7 @@ function scoreBotMoveWithLookahead(state, move, difficulty, style) {
61565
61447
  score += centerControl * (difficulty === 'hard' ? 18 : 10) * style.center;
61566
61448
  }
61567
61449
  const opponentBestReply = opponentMoves
61568
- .map((opponentMove) => scoreBotMove(afterMove, opponentMove, difficulty, style, false))
61450
+ .map((opponentMove) => scoreBotMove(afterMove, opponentMove, difficulty, style))
61569
61451
  .sort((a, b) => b - a)[0];
61570
61452
  if (opponentBestReply) {
61571
61453
  const replyWeight = difficulty === 'easy' ? 0.12 : difficulty === 'normal' ? 0.32 : 0.48;
@@ -61577,33 +61459,17 @@ function scoreBotMoveWithLookahead(state, move, difficulty, style) {
61577
61459
  }
61578
61460
  return score;
61579
61461
  }
61580
- function countPowerReachAfterMove(state, move, color) {
61581
- try {
61582
- const afterMove = applyChessimalsMove(state, move);
61583
- const evaluationState = { ...afterMove, currentTurn: color };
61584
- return getChessimalsAllLegalMoves(evaluationState, color).filter((nextMove) => nextMove.kind === 'power').length;
61585
- }
61586
- catch {
61587
- return 0;
61588
- }
61589
- }
61590
- function countProtectedThreatsAfterMove(state, move, color) {
61591
- try {
61592
- const afterMove = applyChessimalsMove(state, move);
61593
- const evaluationState = { ...afterMove, currentTurn: color };
61594
- const ourMoves = getChessimalsAllLegalMoves(evaluationState, color);
61595
- const enemyPieces = activePieces(afterMove).filter((piece) => piece.color !== color && !piece.captured);
61596
- return enemyPieces.filter((piece) => ourMoves.some((nextMove) => nextMove.capturesPieceId === piece.id)).length;
61597
- }
61598
- catch {
61599
- return 0;
61462
+ function chooseConservativeHardCapture(state, scored) {
61463
+ if (state.boardSize !== 8)
61464
+ return undefined;
61465
+ const best = scored[0];
61466
+ if (!best || best.move.kind !== 'power' || !best.move.capturesPieceId || best.score >= 10000) {
61467
+ return undefined;
61600
61468
  }
61601
- }
61602
- function scoreEndgamePressure(state, move, color) {
61603
- const remainingEnemyPieces = activePieces(state).filter((piece) => piece.color !== color && !piece.captured).length;
61604
- const urgency = remainingEnemyPieces <= Math.max(2, Math.floor(state.boardSize / 2)) ? 1.6 : 1;
61605
- const distanceToPromotion = color === 'white' ? move.to.row : state.boardSize - 1 - move.to.row;
61606
- return Math.max(0, state.boardSize - distanceToPromotion) * 14 * urgency;
61469
+ const bestBasicCapture = scored.find((item) => item.move.kind === 'basic' && item.move.capturesPieceId);
61470
+ if (!bestBasicCapture)
61471
+ return undefined;
61472
+ return best.score - bestBasicCapture.score <= 650 ? bestBasicCapture.move : undefined;
61607
61473
  }
61608
61474
  function pickNoisyBotMove(scored, spread) {
61609
61475
  if (scored.length === 0)
@@ -62694,63 +62560,6 @@ const MINI_GAMES_I18N = {
62694
62560
  bubbleDescription: 'Revienta grupos de burbujas, encadena combos y sube tu puntaje.',
62695
62561
  chessimalsTitle: 'Chessimals',
62696
62562
  chessimalsDescription: 'Una carrera de peones con cartas de animales y poderes tácticos.',
62697
- christianityTitle: 'Christianity',
62698
- christianityDescription: 'Un juego de cartas familiar con líderes, ofrendas y decisiones tácticas.',
62699
- christianityEyebrow: 'MVP de mesa',
62700
- christianityTable: 'Mesa de Christianity',
62701
- christianityTurn: 'Turno',
62702
- christianityOfferings: 'Ofrendas',
62703
- christianityHand: 'Mano',
62704
- christianityOpponentBattle: 'Zona de batalla rival',
62705
- christianityYourBattle: 'Tu zona de batalla',
62706
- christianityOpponentHand: 'Mano rival',
62707
- christianitySharedZone: 'Zona compartida',
62708
- christianityMatch: 'Match',
62709
- christianityMatchScore: 'Marcador de match',
62710
- christianityHistory: 'Historia',
62711
- christianityDeck: 'Mazo',
62712
- christianityPlace: 'Lugar',
62713
- christianityEmpty: 'Vacío',
62714
- christianityYourHand: 'Tu mano',
62715
- christianityCost: 'Coste',
62716
- christianityOfferingCard: 'Ofrenda',
62717
- christianityCharacterCard: 'Personaje',
62718
- christianityLeaderCard: 'Líder',
62719
- christianityHiddenCard: 'Carta oculta',
62720
- christianityPreviewCard: 'Ver carta',
62721
- christianityEndTurn: 'Terminar turno',
62722
- christianityPlayCard: 'Jugar carta',
62723
- christianityPlayOffering: 'Jugar ofrenda',
62724
- christianityPlayHere: 'Jugar aquí',
62725
- christianityReset: 'Reiniciar mock',
62726
- christianityWaitTurn: 'Espera el turno rival.',
62727
- christianityChooseTarget: 'Elige un objetivo para atacar.',
62728
- christianityChooseCharacterTarget: 'El rival tiene personajes: debes atacarlos antes que al líder.',
62729
- christianityReadyToPlay: 'Puedes jugar esta carta.',
62730
- christianityChooseSlot: 'Elige una casilla disponible para jugar esta carta.',
62731
- christianityPlaceOffering: 'Puedes jugar esta ofrenda con el botón de acción.',
62732
- christianityNeedOfferings: 'Necesitas más ofrendas para jugar esa carta.',
62733
- christianityChooseCard: 'Elige una carta o un personaje listo para actuar.',
62734
- christianityLeaderProtected: 'No puedes atacar directamente al líder mientras tenga personajes en batalla.',
62735
- christianityLeaderBody: 'Si su vida llega a 0, la partida termina.',
62736
- christianityOfferingReady: 'Lista',
62737
- christianityOfferingExhausted: 'Agotada',
62738
- christianityOfferingBody: 'Se agota para pagar costes y vuelve a estar lista al comenzar tu turno.',
62739
- christianityOfferingNoAbility: 'Esta ofrenda no tiene habilidad activable.',
62740
- christianityUseAbility: 'Usar',
62741
- christianityCloseOfferings: 'Cerrar ofrendas',
62742
- christianityCharacterBody: 'Entra a batalla y debe esperar un turno para atacar.',
62743
- christianityCharacterReady: 'Listo para atacar.',
62744
- christianityCharacterExhausted: 'No puede atacar todavía.',
62745
- christianityCardRemaining: 'carta restante',
62746
- christianityCardsRemaining: 'cartas restantes',
62747
- christianityDeckBody: 'El mazo es una pila compartida. Ambos jugadores roban desde aquí, por eso importa adaptarse a lo que aparece y cuidar el ritmo de la partida.',
62748
- christianityDeckRuleShared: 'Todas las cartas jugables viven en este mazo compartido, incluyendo personajes y ofrendas.',
62749
- christianityDeckRuleDraw: 'Al comenzar cada turno, el jugador activo roba la primera carta disponible.',
62750
- christianityDeckRuleEmpty: 'Si el mazo se queda sin cartas, se revisa la condición de victoria por vida al final del turno.',
62751
- christianityClosePreview: 'Cerrar previsualizacion de carta',
62752
- christianityCloseHistory: 'Cerrar historia',
62753
- christianityHistoryEmpty: 'Todavía no hay cartas en historia.',
62754
62563
  soonTitle: 'Próximamente',
62755
62564
  openGame: 'Jugar',
62756
62565
  close: 'Cerrar',
@@ -62875,10 +62684,10 @@ const MINI_GAMES_I18N = {
62875
62684
  chessimalsRulePowersTitle: 'Cuándo se activan los poderes',
62876
62685
  chessimalsRulePowersBody: 'Tus cartas se desbloquean cuando uno de tus peones cruza la línea central o cuando un peón rival entra en tu mitad del tablero.',
62877
62686
  chessimalsRuleCardsTitle: 'Cartas de animales',
62878
- chessimalsRuleEagle: 'Águila: se mueve en diagonal por todo el tablero, hacia adelante o atrás, sin entrar a la última fila.',
62879
- chessimalsRuleBull: 'Toro: se mueve en línea recta por todo el tablero, incluso hacia los lados, sin entrar a la última fila.',
62687
+ chessimalsRuleEagle: 'Águila: se mueve hasta 3 casillas en diagonal, hacia adelante o atrás.',
62688
+ chessimalsRuleBull: 'Toro: se mueve hasta 3 casillas en línea recta, incluso hacia los lados.',
62880
62689
  chessimalsRuleKangaroo: 'Canguro: salta en L, como el caballo del ajedrez. Puede saltar por encima de piezas y caer libre o capturar una pieza rival.',
62881
- chessimalsRuleLion: 'León: se mueve en cualquier dirección por todo el tablero, sin entrar a la última fila.',
62690
+ chessimalsRuleLion: 'León: se mueve hasta 3 casillas en cualquier dirección.',
62882
62691
  chessimalsRuleLimitsTitle: 'Reglas de equilibrio',
62883
62692
  chessimalsRuleLimitsBody: 'Cada carta se usa una sola vez por partida. Ningún poder puede entrar directamente a la última fila: el paso final para ganar siempre debe ser un avance normal.',
62884
62693
  chessimalsBoardSize: 'Tamaño del tablero',
@@ -62991,18 +62800,6 @@ const MINI_GAMES_I18N = {
62991
62800
  chessimalsBotSprinterBody: 'Optimiza rutas de promoción.',
62992
62801
  chessimalsBotSentinel: 'Centinela',
62993
62802
  chessimalsBotSentinelBody: 'Defiende sólido y castiga errores.',
62994
- chessimalsBotOracle: 'Oráculo',
62995
- chessimalsBotOracleBody: 'Lee respuestas y evita trampas profundas.',
62996
- chessimalsBotAmbusher: 'Emboscador',
62997
- chessimalsBotAmbusherBody: 'Prepara capturas dobles con poderes largos.',
62998
- chessimalsBotLocksmith: 'Cerrajero',
62999
- chessimalsBotLocksmithBody: 'Cierra el centro y reduce tus rutas.',
63000
- chessimalsBotStorm: 'Tormenta',
63001
- chessimalsBotStormBody: 'Usa poderes largos para presionar todo el tablero.',
63002
- chessimalsBotMatriarch: 'Matriarca',
63003
- chessimalsBotMatriarchBody: 'Protege su estructura y gana por desgaste.',
63004
- chessimalsBotEndgame: 'Finalista',
63005
- chessimalsBotEndgameBody: 'Convierte ventajas pequeñas en promoción.',
63006
62803
  chessimalsBotExplorerTendency: 'Tiende a variar rutas, probar el centro y cometer errores suaves.',
63007
62804
  chessimalsBotImpulsiveTendency: 'Tiende a capturar rápido, incluso cuando puede quedar expuesto.',
63008
62805
  chessimalsBotRunnerTendency: 'Tiende a avanzar hacia la promoción antes que defender.',
@@ -63013,12 +62810,6 @@ const MINI_GAMES_I18N = {
63013
62810
  chessimalsBotPredatorTendency: 'Tiende a forzar capturas y usar poderes agresivos.',
63014
62811
  chessimalsBotSprinterTendency: 'Tiende a encontrar caminos rápidos de promoción.',
63015
62812
  chessimalsBotSentinelTendency: 'Tiende a defender sólido y castigar errores.',
63016
- chessimalsBotOracleTendency: 'Tiende a anticipar respuestas y elegir jugadas difíciles de refutar.',
63017
- chessimalsBotAmbusherTendency: 'Tiende a dejar piezas bajo amenaza múltiple antes de capturar.',
63018
- chessimalsBotLocksmithTendency: 'Tiende a cortar rutas por el centro y dejarte sin buenas casillas.',
63019
- chessimalsBotStormTendency: 'Tiende a convertir poderes largos en presión desde varios ángulos.',
63020
- chessimalsBotMatriarchTendency: 'Tiende a conservar piezas y cambiar solo cuando queda mejor.',
63021
- chessimalsBotEndgameTendency: 'Tiende a simplificar y correr hacia la promoción cuando ve ventaja.',
63022
62813
  chessimalsBotReportTitle: 'Reporte del bot',
63023
62814
  chessimalsBotReportVs: 'Contra {bot}',
63024
62815
  chessimalsBotReportBody: '{outcome}. Hizo {captures} capturas y usó {powers} poderes. {style}',
@@ -63113,7 +62904,7 @@ const MINI_GAMES_I18N = {
63113
62904
  chessimalsTutorialStep4Title: 'Devuelve el turno',
63114
62905
  chessimalsTutorialStep4Body: 'Mueve el peón negro de la columna F una casilla hacia abajo para continuar.',
63115
62906
  chessimalsTutorialStep5Title: 'Usa el poder Canguro',
63116
- chessimalsTutorialStep5Body: 'Selecciona la carta Canguro y salta en L para capturar el peón negro. Las otras cartas pueden cruzar todo el tablero, pero ningún poder puede entrar a la última fila.',
62907
+ chessimalsTutorialStep5Body: 'Selecciona la carta Canguro y salta en L para capturar el peón negro.',
63117
62908
  chessimalsTutorialStep6Title: 'Prepara la llegada',
63118
62909
  chessimalsTutorialStep6Body: 'Mueve el último peón negro hacia abajo. Después tendrás camino para ganar.',
63119
62910
  chessimalsTutorialStep7Title: 'Llega a la última fila',
@@ -63177,63 +62968,6 @@ const MINI_GAMES_I18N = {
63177
62968
  bubbleDescription: 'Pop bubble groups, chain combos, and push your score higher.',
63178
62969
  chessimalsTitle: 'Chessimals',
63179
62970
  chessimalsDescription: 'A pawn race with animal cards and tactical powers.',
63180
- christianityTitle: 'Christianity',
63181
- christianityDescription: 'A family card game with leaders, offerings, and tactical choices.',
63182
- christianityEyebrow: 'Table MVP',
63183
- christianityTable: 'Christianity table',
63184
- christianityTurn: 'Turn',
63185
- christianityOfferings: 'Offerings',
63186
- christianityHand: 'Hand',
63187
- christianityOpponentBattle: 'Opponent battle zone',
63188
- christianityYourBattle: 'Your battle zone',
63189
- christianityOpponentHand: 'Opponent hand',
63190
- christianitySharedZone: 'Shared zone',
63191
- christianityMatch: 'Match',
63192
- christianityMatchScore: 'Match score',
63193
- christianityHistory: 'History',
63194
- christianityDeck: 'Deck',
63195
- christianityPlace: 'Place',
63196
- christianityEmpty: 'Empty',
63197
- christianityYourHand: 'Your hand',
63198
- christianityCost: 'Cost',
63199
- christianityOfferingCard: 'Offering',
63200
- christianityCharacterCard: 'Character',
63201
- christianityLeaderCard: 'Leader',
63202
- christianityHiddenCard: 'Hidden card',
63203
- christianityPreviewCard: 'Preview card',
63204
- christianityEndTurn: 'End turn',
63205
- christianityPlayCard: 'Play card',
63206
- christianityPlayOffering: 'Play offering',
63207
- christianityPlayHere: 'Play here',
63208
- christianityReset: 'Reset mock',
63209
- christianityWaitTurn: 'Wait for the opponent turn.',
63210
- christianityChooseTarget: 'Choose a target to attack.',
63211
- christianityChooseCharacterTarget: 'The opponent has characters: attack them before the leader.',
63212
- christianityReadyToPlay: 'You can play this card.',
63213
- christianityChooseSlot: 'Choose an available slot to play this card.',
63214
- christianityPlaceOffering: 'You can play this offering with the action button.',
63215
- christianityNeedOfferings: 'You need more offerings to play that card.',
63216
- christianityChooseCard: 'Choose a card or a ready character.',
63217
- christianityLeaderProtected: 'You cannot attack the leader directly while they have characters in battle.',
63218
- christianityLeaderBody: 'If this leader reaches 0 life, the game ends.',
63219
- christianityOfferingReady: 'Ready',
63220
- christianityOfferingExhausted: 'Exhausted',
63221
- christianityOfferingBody: 'Exhaust it to pay costs. It readies again at the start of your turn.',
63222
- christianityOfferingNoAbility: 'This offering has no active ability.',
63223
- christianityUseAbility: 'Use',
63224
- christianityCloseOfferings: 'Close offerings',
63225
- christianityCharacterBody: 'Enters battle and must wait one turn before attacking.',
63226
- christianityCharacterReady: 'Ready to attack.',
63227
- christianityCharacterExhausted: 'Cannot attack yet.',
63228
- christianityCardRemaining: 'card remaining',
63229
- christianityCardsRemaining: 'cards remaining',
63230
- christianityDeckBody: 'The deck is a shared pile. Both players draw from it, so the match rewards adapting to what appears and managing the pace.',
63231
- christianityDeckRuleShared: 'All playable cards live in this shared deck, including characters and offerings.',
63232
- christianityDeckRuleDraw: 'At the start of each turn, the active player draws the first available card.',
63233
- christianityDeckRuleEmpty: 'If the deck runs out, the leader life victory condition is checked at the end of the turn.',
63234
- christianityClosePreview: 'Close card preview',
63235
- christianityCloseHistory: 'Close history',
63236
- christianityHistoryEmpty: 'There are no cards in history yet.',
63237
62971
  soonTitle: 'Coming soon',
63238
62972
  openGame: 'Play',
63239
62973
  close: 'Close',
@@ -63358,10 +63092,10 @@ const MINI_GAMES_I18N = {
63358
63092
  chessimalsRulePowersTitle: 'When powers unlock',
63359
63093
  chessimalsRulePowersBody: 'Your cards unlock when one of your pawns crosses the center line, or when a rival pawn enters your half of the board.',
63360
63094
  chessimalsRuleCardsTitle: 'Animal cards',
63361
- chessimalsRuleEagle: 'Eagle: moves diagonally across the whole board, forward or backward, without entering the final row.',
63362
- chessimalsRuleBull: 'Bull: moves in a straight line across the whole board, including sideways, without entering the final row.',
63095
+ chessimalsRuleEagle: 'Eagle: moves up to 3 squares diagonally, forward or backward.',
63096
+ chessimalsRuleBull: 'Bull: moves up to 3 squares in a straight line, including sideways.',
63363
63097
  chessimalsRuleKangaroo: 'Kangaroo: jumps in an L shape, like a chess knight. It can jump over pieces and land on an empty square or capture a rival piece.',
63364
- chessimalsRuleLion: 'Lion: moves in any direction across the whole board, without entering the final row.',
63098
+ chessimalsRuleLion: 'Lion: moves up to 3 squares in any direction.',
63365
63099
  chessimalsRuleLimitsTitle: 'Balance rules',
63366
63100
  chessimalsRuleLimitsBody: 'Each card can be used once per game. No power can land directly on the final row: the winning step must always be a normal forward move.',
63367
63101
  chessimalsBoardSize: 'Board size',
@@ -63474,18 +63208,6 @@ const MINI_GAMES_I18N = {
63474
63208
  chessimalsBotSprinterBody: 'Optimizes promotion routes.',
63475
63209
  chessimalsBotSentinel: 'Sentinel',
63476
63210
  chessimalsBotSentinelBody: 'Defends solidly and punishes mistakes.',
63477
- chessimalsBotOracle: 'Oracle',
63478
- chessimalsBotOracleBody: 'Reads replies and avoids deep traps.',
63479
- chessimalsBotAmbusher: 'Ambusher',
63480
- chessimalsBotAmbusherBody: 'Sets up double captures with long powers.',
63481
- chessimalsBotLocksmith: 'Locksmith',
63482
- chessimalsBotLocksmithBody: 'Closes the center and reduces your routes.',
63483
- chessimalsBotStorm: 'Storm',
63484
- chessimalsBotStormBody: 'Uses long powers to pressure the whole board.',
63485
- chessimalsBotMatriarch: 'Matriarch',
63486
- chessimalsBotMatriarchBody: 'Protects structure and wins by attrition.',
63487
- chessimalsBotEndgame: 'Endgame',
63488
- chessimalsBotEndgameBody: 'Turns small edges into promotion.',
63489
63211
  chessimalsBotExplorerTendency: 'Tends to vary routes, test the center, and make soft mistakes.',
63490
63212
  chessimalsBotImpulsiveTendency: 'Tends to capture quickly, even when it can become exposed.',
63491
63213
  chessimalsBotRunnerTendency: 'Tends to push toward promotion before defending.',
@@ -63496,12 +63218,6 @@ const MINI_GAMES_I18N = {
63496
63218
  chessimalsBotPredatorTendency: 'Tends to force captures and use aggressive powers.',
63497
63219
  chessimalsBotSprinterTendency: 'Tends to find fast promotion paths.',
63498
63220
  chessimalsBotSentinelTendency: 'Tends to defend solidly and punish mistakes.',
63499
- chessimalsBotOracleTendency: 'Tends to anticipate replies and choose hard-to-refute moves.',
63500
- chessimalsBotAmbusherTendency: 'Tends to leave pieces under multiple threats before capturing.',
63501
- chessimalsBotLocksmithTendency: 'Tends to close central routes and leave you without good squares.',
63502
- chessimalsBotStormTendency: 'Tends to turn long powers into pressure from several angles.',
63503
- chessimalsBotMatriarchTendency: 'Tends to preserve pieces and trade only when it improves.',
63504
- chessimalsBotEndgameTendency: 'Tends to simplify and race toward promotion when ahead.',
63505
63221
  chessimalsBotReportTitle: 'Bot report',
63506
63222
  chessimalsBotReportVs: 'Against {bot}',
63507
63223
  chessimalsBotReportBody: '{outcome}. It made {captures} captures and used {powers} powers. {style}',
@@ -63596,7 +63312,7 @@ const MINI_GAMES_I18N = {
63596
63312
  chessimalsTutorialStep4Title: 'Return the turn',
63597
63313
  chessimalsTutorialStep4Body: 'Move the black pawn on file F one square downward to continue.',
63598
63314
  chessimalsTutorialStep5Title: 'Use the Kangaroo power',
63599
- chessimalsTutorialStep5Body: 'Select the Kangaroo card and jump in an L shape to capture the black pawn. The other cards can cross the whole board, but no power can enter the final row.',
63315
+ chessimalsTutorialStep5Body: 'Select the Kangaroo card and jump in an L shape to capture the black pawn.',
63600
63316
  chessimalsTutorialStep6Title: 'Prepare the finish',
63601
63317
  chessimalsTutorialStep6Body: 'Move the last black pawn downward. Then your path to win is open.',
63602
63318
  chessimalsTutorialStep7Title: 'Reach the last row',
@@ -64779,7 +64495,6 @@ class ChessimalsGameComponent {
64779
64495
  });
64780
64496
  this.botThinking = signal(false);
64781
64497
  this.confirmAction = signal(undefined);
64782
- this.confirmedAction = signal(undefined);
64783
64498
  this.onlineJoinCode = signal('');
64784
64499
  this.onlineLoading = signal(false);
64785
64500
  this.onlineAction = signal(undefined);
@@ -65758,12 +65473,13 @@ class ChessimalsGameComponent {
65758
65473
  closeConfirmModal() {
65759
65474
  this.confirmAction.set(undefined);
65760
65475
  }
65761
- handleConfirmModalDismissed() {
65762
- this.confirmAction.set(undefined);
65763
- const action = this.confirmedAction();
65764
- this.confirmedAction.set(undefined);
65765
- if (!action)
65476
+ confirmPendingAction(token) {
65477
+ if (token !== 'confirm') {
65478
+ this.closeConfirmModal();
65766
65479
  return;
65480
+ }
65481
+ const action = this.confirmAction();
65482
+ this.confirmAction.set(undefined);
65767
65483
  if (action === 'restart') {
65768
65484
  this.restartGame();
65769
65485
  return;
@@ -65785,15 +65501,6 @@ class ChessimalsGameComponent {
65785
65501
  this.createNewChallengeRun();
65786
65502
  }
65787
65503
  }
65788
- confirmPendingAction(token) {
65789
- if (token !== 'confirm') {
65790
- this.closeConfirmModal();
65791
- return;
65792
- }
65793
- const action = this.confirmAction();
65794
- this.confirmedAction.set(action);
65795
- this.confirmAction.set(undefined);
65796
- }
65797
65504
  resignGame() {
65798
65505
  const game = this.game();
65799
65506
  if (game.status === 'finished')
@@ -67885,7 +67592,7 @@ class ChessimalsGameComponent {
67885
67592
  <ion-modal
67886
67593
  [isOpen]="!!confirmAction()"
67887
67594
  cssClass="val-modal-adaptive"
67888
- (didDismiss)="handleConfirmModalDismissed()"
67595
+ (didDismiss)="closeConfirmModal()"
67889
67596
  >
67890
67597
  <ng-template>
67891
67598
  <val-modal-layout
@@ -68846,7 +68553,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
68846
68553
  <ion-modal
68847
68554
  [isOpen]="!!confirmAction()"
68848
68555
  cssClass="val-modal-adaptive"
68849
- (didDismiss)="handleConfirmModalDismissed()"
68556
+ (didDismiss)="closeConfirmModal()"
68850
68557
  >
68851
68558
  <ng-template>
68852
68559
  <val-modal-layout
@@ -68872,1731 +68579,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
68872
68579
  type: Input
68873
68580
  }] } });
68874
68581
 
68875
- const STARTER_CARDS = {
68876
- o_simple: {
68877
- id: 'o_simple',
68878
- name: 'Ofrenda simple',
68879
- type: 'offering',
68880
- cost: 0,
68881
- attack: 0,
68882
- life: 1,
68883
- verseText: 'Una ofrenda sencilla queda lista para sostener tus siguientes jugadas.',
68884
- scripture: 'Genesis 4:4',
68885
- edition: 'GEN',
68886
- collectorNumber: '001/020',
68887
- year: '2026',
68888
- author: 'MVP',
68889
- rarity: 'normal',
68890
- },
68891
- o_forbidden: {
68892
- id: 'o_forbidden',
68893
- name: 'El fruto prohibido',
68894
- type: 'offering',
68895
- cost: 0,
68896
- attack: 0,
68897
- life: 2,
68898
- abilityName: 'Conocimiento del bien y del mal',
68899
- abilityText: 'Al usarla, disminuye en 1 los puntos de vida de tu Líder.',
68900
- abilityCost: 0,
68901
- verseText: 'Dios el Señor puso al hombre en el jardín de Edén para que lo labrara y lo cuidara.',
68902
- scripture: 'Genesis 2:17 NBV',
68903
- edition: 'GEN',
68904
- collectorNumber: '012/180',
68905
- year: '2026',
68906
- author: 'MVP',
68907
- rarity: 'uncommon',
68908
- },
68909
- p_scout: {
68910
- id: 'p_scout',
68911
- name: 'Scout',
68912
- type: 'character',
68913
- cost: 1,
68914
- attack: 1,
68915
- life: 1,
68916
- verseText: 'Un explorador humilde abre camino antes de que llegue la batalla.',
68917
- scripture: 'Genesis 13:17',
68918
- edition: 'GEN',
68919
- collectorNumber: '002/020',
68920
- year: '2026',
68921
- author: 'MVP',
68922
- rarity: 'normal',
68923
- },
68924
- p_guard: { id: 'p_guard', name: 'Guard', type: 'character', cost: 2, attack: 1, life: 3, edition: 'GEN', collectorNumber: '003/020', year: '2026', author: 'MVP', rarity: 'normal' },
68925
- p_warrior: { id: 'p_warrior', name: 'Warrior', type: 'character', cost: 2, attack: 2, life: 2, edition: 'GEN', collectorNumber: '004/020', year: '2026', author: 'MVP', rarity: 'normal' },
68926
- p_elder: { id: 'p_elder', name: 'Elder', type: 'character', cost: 3, attack: 2, life: 4, edition: 'GEN', collectorNumber: '005/020', year: '2026', author: 'MVP', rarity: 'uncommon' },
68927
- p_champion: { id: 'p_champion', name: 'Champion', type: 'character', cost: 4, attack: 4, life: 4, edition: 'GEN', collectorNumber: '006/020', year: '2026', author: 'MVP', rarity: 'rare' },
68928
- };
68929
- const STARTING_SHARED_DECK = [
68930
- 'o_simple',
68931
- 'p_scout',
68932
- 'o_forbidden',
68933
- 'o_simple',
68934
- 'p_guard',
68935
- 'p_warrior',
68936
- 'o_simple',
68937
- 'p_elder',
68938
- 'p_scout',
68939
- 'o_simple',
68940
- 'p_champion',
68941
- 'p_guard',
68942
- 'o_simple',
68943
- 'p_warrior',
68944
- 'p_scout',
68945
- 'o_simple',
68946
- 'p_elder',
68947
- 'p_guard',
68948
- 'o_simple',
68949
- ];
68950
- const STARTING_GAME = {
68951
- gameId: 'mock-christianity',
68952
- status: 'in_progress',
68953
- mode: 'local_pass',
68954
- turnOwner: 'P1',
68955
- revision: 0,
68956
- turnCount: 1,
68957
- matchScore: { P1: 1, P2: 0 },
68958
- sharedDeck: STARTING_SHARED_DECK,
68959
- historyZone: [],
68960
- players: {
68961
- P1: {
68962
- seat: 'P1',
68963
- displayName: 'Jugador',
68964
- avatar: 'J',
68965
- avatarColor: '#2563eb',
68966
- leaderName: 'Adam',
68967
- leaderHp: 15,
68968
- leaderMaxHp: 15,
68969
- offerings: [
68970
- { instanceId: 'p1_offering_001', cardId: 'o_simple', name: 'Ofrenda simple', owner: 'P1', ready: true, value: 1 },
68971
- {
68972
- instanceId: 'p1_offering_002',
68973
- cardId: 'o_forbidden',
68974
- name: 'El fruto prohibido',
68975
- owner: 'P1',
68976
- ready: true,
68977
- value: 2,
68978
- abilityName: 'Conocimiento del bien y del mal',
68979
- abilityText: 'Al usarla, disminuye en 1 los puntos de vida de tu Lider.',
68980
- abilityCost: 0,
68981
- },
68982
- ],
68983
- offeringPlayedThisTurn: false,
68984
- hand: ['o_simple', 'p_scout', 'p_warrior', 'p_guard'],
68985
- battleZone: [],
68986
- },
68987
- P2: {
68988
- seat: 'P2',
68989
- displayName: 'Rival',
68990
- avatar: 'R',
68991
- avatarColor: '#b45309',
68992
- leaderName: 'Noah',
68993
- leaderHp: 15,
68994
- leaderMaxHp: 15,
68995
- offerings: [{ instanceId: 'p2_offering_001', cardId: 'o_simple', name: 'Ofrenda simple', owner: 'P2', ready: true, value: 1 }],
68996
- offeringPlayedThisTurn: false,
68997
- handCount: 4,
68998
- battleZone: [
68999
- {
69000
- instanceId: 'opp_001',
69001
- cardId: 'p_scout',
69002
- name: 'Scout',
69003
- owner: 'P2',
69004
- controller: 'P2',
69005
- attack: 1,
69006
- currentHp: 1,
69007
- maxHp: 1,
69008
- canAttack: false,
69009
- },
69010
- ],
69011
- },
69012
- },
69013
- log: ['Partida iniciada.'],
69014
- };
69015
- class ChristianityGameComponent {
69016
- constructor() {
69017
- this.i18n = inject(I18nService);
69018
- this.game = signal(structuredClone(STARTING_GAME));
69019
- this.selectedHandCard = signal(null);
69020
- this.selectedAttacker = signal(null);
69021
- this.selectedPreview = signal(null);
69022
- this.selectedInfo = signal(null);
69023
- this.previewTilt = signal({ rotateX: 5, rotateY: -5, shiftX: 0, shiftY: 0 });
69024
- this.hoveredHandIndex = signal(null);
69025
- this.draggingCardId = signal(null);
69026
- this.showHistory = signal(false);
69027
- this.offeringsSeat = signal(null);
69028
- this.canDropOnBattleSlot = (drag) => {
69029
- const card = this.cardDefinition(drag.data);
69030
- return card.type === 'character' && this.canPlay(card);
69031
- };
69032
- this.canDropOnOfferings = (drag) => {
69033
- const card = this.cardDefinition(drag.data);
69034
- return card.type === 'offering' && this.canPlay(card);
69035
- };
69036
- this.player = computed(() => this.game().players.P1);
69037
- this.opponent = computed(() => this.game().players.P2);
69038
- this.currentPlayer = computed(() => this.game().players[this.game().turnOwner]);
69039
- this.isOwnTurn = computed(() => this.game().turnOwner === 'P1');
69040
- this.hasOpponentGuards = computed(() => this.opponent().battleZone.length > 0);
69041
- this.opponentHandCount = computed(() => this.opponent().handCount ?? this.opponent().hand?.length ?? 0);
69042
- this.selectedCardDefinition = computed(() => {
69043
- const selected = this.selectedHandCard();
69044
- return selected ? this.cardDefinition(selected) : null;
69045
- });
69046
- this.selectedPreviewCard = computed(() => {
69047
- const cardId = this.selectedPreview()?.cardId;
69048
- return cardId ? this.cardDefinition(cardId) : null;
69049
- });
69050
- this.statusText = computed(() => {
69051
- const attacker = this.selectedAttacker();
69052
- const handCard = this.selectedCardDefinition();
69053
- if (!this.isOwnTurn()) {
69054
- return this.t('christianityWaitTurn');
69055
- }
69056
- if (attacker) {
69057
- return this.hasOpponentGuards() ? this.t('christianityChooseCharacterTarget') : this.t('christianityChooseTarget');
69058
- }
69059
- if (handCard) {
69060
- if (!this.canPlay(handCard)) {
69061
- return this.t('christianityNeedOfferings');
69062
- }
69063
- return handCard.type === 'offering' ? this.t('christianityPlaceOffering') : this.t('christianityChooseSlot');
69064
- }
69065
- return this.t('christianityChooseCard');
69066
- });
69067
- this.i18n.registerDefaults('MiniGames', MINI_GAMES_I18N);
69068
- }
69069
- t(key) {
69070
- this.i18n.lang();
69071
- return this.i18n.t(key, 'MiniGames');
69072
- }
69073
- cardDefinition(cardId) {
69074
- return STARTER_CARDS[cardId] ?? STARTER_CARDS['p_scout'];
69075
- }
69076
- cardTypeLabel(card) {
69077
- return card.type === 'offering' ? this.t('christianityOfferingCard') : this.t('christianityCharacterCard');
69078
- }
69079
- battleSlots(seat) {
69080
- const cards = this.game().players[seat].battleZone;
69081
- return Array.from({ length: 4 }, (_, index) => ({
69082
- trackId: cards[index]?.instanceId ?? `${seat}-empty-${index}`,
69083
- card: cards[index],
69084
- }));
69085
- }
69086
- battleSlotDropId(index) {
69087
- return `christianity-battle-slot-${index}`;
69088
- }
69089
- dropTargetIds() {
69090
- return ['christianity-offerings-drop', ...this.battleSlots('P1').map((_, index) => this.battleSlotDropId(index))];
69091
- }
69092
- hiddenHandCards(count) {
69093
- return Array.from({ length: count });
69094
- }
69095
- fanTransform(index, total, opponent) {
69096
- if (total <= 1)
69097
- return 'none';
69098
- const center = (total - 1) / 2;
69099
- const offset = index - center;
69100
- const rotate = offset * (opponent ? 8 : 5);
69101
- const lift = Math.abs(offset) * 0.25;
69102
- const hoverLift = opponent ? 0 : this.handWaveLift(index);
69103
- const scale = opponent ? 1 : this.handWaveScale(index);
69104
- const fanLift = opponent ? Math.abs(offset) * 0.34 : lift + hoverLift;
69105
- const fanSpread = opponent ? offset * 0.08 : 0;
69106
- return `translate(${fanSpread}rem, ${fanLift}rem) rotate(${rotate}deg) scale(${scale})`;
69107
- }
69108
- handCardZIndex(index) {
69109
- const hovered = this.hoveredHandIndex();
69110
- if (hovered === null)
69111
- return 2;
69112
- const distance = Math.abs(index - hovered);
69113
- return Math.max(2, 8 - distance);
69114
- }
69115
- setHoveredHandIndex(index) {
69116
- this.hoveredHandIndex.set(index);
69117
- }
69118
- clearHoveredHandIndex() {
69119
- this.hoveredHandIndex.set(null);
69120
- }
69121
- releaseHoveredHand(event) {
69122
- if (event.pointerType !== 'mouse') {
69123
- window.setTimeout(() => this.clearHoveredHandIndex(), 180);
69124
- }
69125
- }
69126
- handWaveLift(index) {
69127
- const hovered = this.hoveredHandIndex();
69128
- if (hovered === null)
69129
- return 0;
69130
- const distance = Math.abs(index - hovered);
69131
- if (distance === 0)
69132
- return -1.15;
69133
- if (distance === 1)
69134
- return -0.58;
69135
- if (distance === 2)
69136
- return -0.22;
69137
- return 0;
69138
- }
69139
- handWaveScale(index) {
69140
- const hovered = this.hoveredHandIndex();
69141
- if (hovered === null)
69142
- return 1;
69143
- const distance = Math.abs(index - hovered);
69144
- if (distance === 0)
69145
- return 1.06;
69146
- if (distance === 1)
69147
- return 1.03;
69148
- return 1;
69149
- }
69150
- readyOfferings(player) {
69151
- return player.offerings.reduce((total, offering) => total + (offering.ready ? offering.value : 0), 0);
69152
- }
69153
- totalOfferings(player) {
69154
- return player.offerings.reduce((total, offering) => total + offering.value, 0);
69155
- }
69156
- canPlay(card) {
69157
- if (!this.isOwnTurn())
69158
- return false;
69159
- if (card.type === 'offering')
69160
- return !this.player().offeringPlayedThisTurn;
69161
- return this.readyOfferings(this.player()) >= card.cost && this.player().battleZone.length < 4;
69162
- }
69163
- canPlaySelected() {
69164
- const selected = this.selectedHandCard();
69165
- return !!selected && this.canPlay(this.cardDefinition(selected));
69166
- }
69167
- selectedActionLabel() {
69168
- const selected = this.selectedCardDefinition();
69169
- if (!selected)
69170
- return this.t('christianityPlayCard');
69171
- return selected.type === 'offering' ? this.t('christianityPlayOffering') : this.t('christianityPlayCard');
69172
- }
69173
- selectedActionDisabled() {
69174
- const selected = this.selectedCardDefinition();
69175
- if (!selected || !this.canPlay(selected))
69176
- return true;
69177
- return selected.type === 'character';
69178
- }
69179
- previewActionDisabled() {
69180
- const preview = this.selectedPreview();
69181
- if (preview?.source !== 'hand' || !preview.cardId)
69182
- return true;
69183
- return !this.canPlay(this.cardDefinition(preview.cardId));
69184
- }
69185
- canPlaceSelectedCharacter() {
69186
- const selected = this.selectedCardDefinition();
69187
- return !!selected && selected.type === 'character' && this.canPlay(selected);
69188
- }
69189
- canPlaceSelectedOffering() {
69190
- const selected = this.selectedCardDefinition();
69191
- return !!selected && selected.type === 'offering' && this.canPlay(selected);
69192
- }
69193
- isDraggingCharacter() {
69194
- const cardId = this.draggingCardId();
69195
- if (!cardId)
69196
- return false;
69197
- const card = this.cardDefinition(cardId);
69198
- return card.type === 'character' && this.canPlay(card);
69199
- }
69200
- isDraggingOffering() {
69201
- const cardId = this.draggingCardId();
69202
- if (!cardId)
69203
- return false;
69204
- const card = this.cardDefinition(cardId);
69205
- return card.type === 'offering' && this.canPlay(card);
69206
- }
69207
- startDraggingCard(cardId) {
69208
- this.selectedAttacker.set(null);
69209
- this.selectedHandCard.set(cardId);
69210
- this.draggingCardId.set(cardId);
69211
- this.closePreview();
69212
- }
69213
- endDraggingCard() {
69214
- this.draggingCardId.set(null);
69215
- }
69216
- dropOnBattleSlot(event, slotIndex) {
69217
- const card = this.cardDefinition(event.item.data);
69218
- if (card.type !== 'character')
69219
- return;
69220
- this.playCardFromHand(event.item.data, slotIndex);
69221
- }
69222
- dropOnOfferings(event) {
69223
- const card = this.cardDefinition(event.item.data);
69224
- if (card.type !== 'offering')
69225
- return;
69226
- this.playCardFromHand(event.item.data);
69227
- }
69228
- selectHandCard(cardId) {
69229
- const wasSelected = this.selectedHandCard() === cardId;
69230
- this.selectedAttacker.set(null);
69231
- this.selectedHandCard.set(wasSelected ? null : cardId);
69232
- this.closePreview();
69233
- }
69234
- playSelectedCard(slotIndex) {
69235
- const cardId = this.selectedHandCard();
69236
- if (!cardId)
69237
- return;
69238
- this.playCardFromHand(cardId, slotIndex);
69239
- }
69240
- playCardFromHand(cardId, slotIndex) {
69241
- const card = this.cardDefinition(cardId);
69242
- if (!this.canPlay(card))
69243
- return;
69244
- this.game.update(game => {
69245
- const next = structuredClone(game);
69246
- const player = next.players.P1;
69247
- const handIndex = player.hand?.indexOf(cardId) ?? -1;
69248
- if (handIndex < 0 || !player.hand)
69249
- return game;
69250
- player.hand.splice(handIndex, 1);
69251
- if (card.type === 'offering') {
69252
- player.offerings.push({
69253
- instanceId: `p1_offering_${next.revision + 1}`,
69254
- cardId: card.id,
69255
- name: card.name,
69256
- owner: 'P1',
69257
- ready: true,
69258
- value: card.life,
69259
- abilityName: card.abilityName,
69260
- abilityText: card.abilityText,
69261
- abilityCost: card.abilityCost,
69262
- });
69263
- player.offeringPlayedThisTurn = true;
69264
- }
69265
- else {
69266
- this.spendOfferings(player, card.cost);
69267
- const insertIndex = Math.min(slotIndex ?? player.battleZone.length, player.battleZone.length);
69268
- player.battleZone.splice(insertIndex, 0, {
69269
- instanceId: `p1_${next.revision + 1}_${player.battleZone.length}`,
69270
- cardId: card.id,
69271
- name: card.name,
69272
- owner: 'P1',
69273
- controller: 'P1',
69274
- attack: card.attack,
69275
- currentHp: card.life,
69276
- maxHp: card.life,
69277
- canAttack: false,
69278
- });
69279
- }
69280
- next.revision++;
69281
- next.log = [
69282
- card.type === 'offering' ? `${card.name} queda lista como ofrenda.` : `${card.name} entra en batalla.`,
69283
- ...next.log,
69284
- ].slice(0, 4);
69285
- return next;
69286
- });
69287
- this.selectedHandCard.set(null);
69288
- this.draggingCardId.set(null);
69289
- this.closePreview();
69290
- }
69291
- playPreviewCard() {
69292
- const preview = this.selectedPreview();
69293
- if (preview?.source !== 'hand' || !preview.cardId)
69294
- return;
69295
- const card = this.cardDefinition(preview.cardId);
69296
- if (!this.canPlay(card))
69297
- return;
69298
- this.selectedHandCard.set(preview.cardId);
69299
- if (card.type === 'character') {
69300
- this.closePreview();
69301
- return;
69302
- }
69303
- this.playSelectedCard();
69304
- }
69305
- handleOfferingPile(seat) {
69306
- this.openOfferings(seat);
69307
- }
69308
- selectAttacker(card) {
69309
- this.selectedHandCard.set(null);
69310
- this.inspectCharacter(card);
69311
- if (!this.isOwnTurn() || !card.canAttack)
69312
- return;
69313
- this.selectedAttacker.set(this.selectedAttacker()?.instanceId === card.instanceId ? null : card);
69314
- }
69315
- handleOpponentCharacter(card) {
69316
- this.inspectCharacter(card);
69317
- if (this.selectedAttacker()) {
69318
- this.attackCharacter(card);
69319
- }
69320
- }
69321
- handleOpponentLeader() {
69322
- this.inspectLeader('P2');
69323
- if (this.selectedAttacker() && !this.hasOpponentGuards()) {
69324
- this.attackLeader();
69325
- }
69326
- }
69327
- attackLeader() {
69328
- const attacker = this.selectedAttacker();
69329
- if (!attacker)
69330
- return;
69331
- if (this.hasOpponentGuards()) {
69332
- this.selectedPreview.set({
69333
- title: this.opponent().leaderName,
69334
- eyebrow: this.t('christianityLeaderCard'),
69335
- meta: `${this.opponent().leaderHp}/${this.opponent().leaderMaxHp}`,
69336
- body: this.t('christianityLeaderProtected'),
69337
- });
69338
- return;
69339
- }
69340
- this.game.update(game => {
69341
- const next = structuredClone(game);
69342
- const liveAttacker = next.players.P1.battleZone.find(card => card.instanceId === attacker.instanceId);
69343
- if (!liveAttacker || !liveAttacker.canAttack)
69344
- return game;
69345
- next.players.P2.leaderHp = Math.max(0, next.players.P2.leaderHp - liveAttacker.attack);
69346
- liveAttacker.canAttack = false;
69347
- next.revision++;
69348
- next.log = [`${liveAttacker.name} ataca al lider rival.`, ...next.log].slice(0, 4);
69349
- return next;
69350
- });
69351
- this.selectedAttacker.set(null);
69352
- }
69353
- attackCharacter(target) {
69354
- const attacker = this.selectedAttacker();
69355
- if (!attacker)
69356
- return;
69357
- this.game.update(game => {
69358
- const next = structuredClone(game);
69359
- const liveAttacker = next.players.P1.battleZone.find(card => card.instanceId === attacker.instanceId);
69360
- const liveTarget = next.players.P2.battleZone.find(card => card.instanceId === target.instanceId);
69361
- if (!liveAttacker || !liveTarget || !liveAttacker.canAttack)
69362
- return game;
69363
- liveTarget.currentHp -= liveAttacker.attack;
69364
- liveAttacker.currentHp -= liveTarget.attack;
69365
- liveAttacker.canAttack = false;
69366
- this.cleanupDestroyed(next.players.P1, next);
69367
- this.cleanupDestroyed(next.players.P2, next);
69368
- next.revision++;
69369
- next.log = [`${liveAttacker.name} combate contra ${liveTarget.name}.`, ...next.log].slice(0, 4);
69370
- return next;
69371
- });
69372
- this.selectedAttacker.set(null);
69373
- }
69374
- endTurn() {
69375
- this.selectedHandCard.set(null);
69376
- this.selectedAttacker.set(null);
69377
- this.selectedPreview.set(null);
69378
- this.selectedInfo.set(null);
69379
- this.game.update(game => {
69380
- const next = structuredClone(game);
69381
- next.turnOwner = next.turnOwner === 'P1' ? 'P2' : 'P1';
69382
- next.turnCount++;
69383
- const current = next.players[next.turnOwner];
69384
- current.offeringPlayedThisTurn = false;
69385
- current.offerings = current.offerings.map(offering => ({ ...offering, ready: true }));
69386
- current.battleZone = current.battleZone.map(card => ({ ...card, canAttack: true }));
69387
- const drawnCard = next.sharedDeck.shift();
69388
- if (drawnCard) {
69389
- if (current.hand) {
69390
- current.hand.push(drawnCard);
69391
- }
69392
- else {
69393
- current.handCount = (current.handCount ?? 0) + 1;
69394
- }
69395
- }
69396
- next.revision++;
69397
- next.log = [
69398
- drawnCard ? `${current.displayName} roba una carta.` : `El mazo esta vacio.`,
69399
- `Turno de ${current.displayName}.`,
69400
- ...next.log,
69401
- ].slice(0, 4);
69402
- return next;
69403
- });
69404
- }
69405
- resetMock() {
69406
- this.game.set(structuredClone(STARTING_GAME));
69407
- this.selectedHandCard.set(null);
69408
- this.selectedAttacker.set(null);
69409
- this.selectedPreview.set(null);
69410
- this.selectedInfo.set(null);
69411
- this.showHistory.set(false);
69412
- this.offeringsSeat.set(null);
69413
- }
69414
- closePreview() {
69415
- this.selectedPreview.set(null);
69416
- this.resetPreviewTilt();
69417
- }
69418
- closeInfo() {
69419
- this.selectedInfo.set(null);
69420
- }
69421
- openOfferings(seat) {
69422
- this.selectedPreview.set(null);
69423
- this.selectedInfo.set(null);
69424
- this.showHistory.set(false);
69425
- this.offeringsSeat.set(seat);
69426
- }
69427
- openHistory() {
69428
- this.selectedPreview.set(null);
69429
- this.selectedInfo.set(null);
69430
- this.offeringsSeat.set(null);
69431
- this.showHistory.set(true);
69432
- }
69433
- closeOfferings() {
69434
- this.offeringsSeat.set(null);
69435
- }
69436
- tiltPreview(event) {
69437
- const bounds = event.currentTarget.getBoundingClientRect();
69438
- const x = (event.clientX - bounds.left) / bounds.width - 0.5;
69439
- const y = (event.clientY - bounds.top) / bounds.height - 0.5;
69440
- this.previewTilt.set({
69441
- rotateX: 5 - y * 18,
69442
- rotateY: -5 + x * 18,
69443
- shiftX: x * 10,
69444
- shiftY: y * 10,
69445
- });
69446
- }
69447
- resetPreviewTilt() {
69448
- this.previewTilt.set({ rotateX: 5, rotateY: -5, shiftX: 0, shiftY: 0 });
69449
- }
69450
- cleanupDestroyed(player, game) {
69451
- const destroyed = player.battleZone.filter(card => card.currentHp <= 0);
69452
- if (!destroyed.length)
69453
- return;
69454
- game.historyZone.push(...destroyed.map(card => card.cardId));
69455
- player.battleZone = player.battleZone.filter(card => card.currentHp > 0);
69456
- }
69457
- inspectLeader(seat) {
69458
- this.selectedInfo.set(null);
69459
- const player = this.game().players[seat];
69460
- this.selectedPreview.set({
69461
- title: player.leaderName,
69462
- eyebrow: this.t('christianityLeaderCard'),
69463
- meta: `${player.leaderHp}/${player.leaderMaxHp}`,
69464
- body: seat === 'P2' && this.hasOpponentGuards() ? this.t('christianityLeaderProtected') : this.t('christianityLeaderBody'),
69465
- });
69466
- }
69467
- inspectOffering(offering) {
69468
- this.selectedInfo.set(null);
69469
- this.selectedPreview.set({
69470
- title: offering.name,
69471
- eyebrow: this.t('christianityOfferingCard'),
69472
- meta: offering.ready ? this.t('christianityOfferingReady') : this.t('christianityOfferingExhausted'),
69473
- body: offering.abilityText || this.t('christianityOfferingBody'),
69474
- });
69475
- }
69476
- canUseOfferingAbility(offering, seat) {
69477
- if (seat !== 'P1' || !this.isOwnTurn())
69478
- return false;
69479
- if (!offering.ready || !offering.abilityName)
69480
- return false;
69481
- return this.readyOfferings(this.game().players[seat]) >= (offering.abilityCost ?? 0);
69482
- }
69483
- useOfferingAbility(offering, seat) {
69484
- if (!this.canUseOfferingAbility(offering, seat))
69485
- return;
69486
- this.game.update(game => {
69487
- const next = structuredClone(game);
69488
- const player = next.players[seat];
69489
- const liveOffering = player.offerings.find(card => card.instanceId === offering.instanceId);
69490
- if (!liveOffering || !liveOffering.ready)
69491
- return game;
69492
- const offeringId = liveOffering.instanceId;
69493
- this.spendOfferings(player, liveOffering.abilityCost ?? 0);
69494
- player.offerings = player.offerings.map(card => (card.instanceId === offeringId ? { ...card, ready: false } : card));
69495
- player.leaderHp = Math.max(0, player.leaderHp - 1);
69496
- next.revision++;
69497
- next.log = [`${liveOffering.name}: ${liveOffering.abilityName}.`, ...next.log].slice(0, 4);
69498
- return next;
69499
- });
69500
- }
69501
- inspectDeck() {
69502
- const remainingCards = this.game().sharedDeck.length;
69503
- this.selectedPreview.set(null);
69504
- this.selectedInfo.set({
69505
- title: this.t('christianityDeck'),
69506
- eyebrow: this.t('christianitySharedZone'),
69507
- meta: `${remainingCards} ${remainingCards === 1 ? this.t('christianityCardRemaining') : this.t('christianityCardsRemaining')}`,
69508
- body: this.t('christianityDeckBody'),
69509
- facts: [
69510
- this.t('christianityDeckRuleShared'),
69511
- this.t('christianityDeckRuleDraw'),
69512
- this.t('christianityDeckRuleEmpty'),
69513
- ],
69514
- });
69515
- }
69516
- inspectHandCard(cardId, fromHand = false) {
69517
- this.selectedInfo.set(null);
69518
- const card = this.cardDefinition(cardId);
69519
- if (fromHand) {
69520
- this.selectedAttacker.set(null);
69521
- this.selectedHandCard.set(cardId);
69522
- }
69523
- this.selectedPreview.set({
69524
- title: card.name,
69525
- eyebrow: card.type === 'offering' ? this.t('christianityOfferingCard') : this.t('christianityCharacterCard'),
69526
- meta: card.type === 'offering' ? `+${card.life}` : `${this.t('christianityCost')} ${card.cost} · ${card.attack}/${card.life}`,
69527
- body: card.type === 'offering' ? this.t('christianityOfferingBody') : this.t('christianityCharacterBody'),
69528
- cardId,
69529
- source: fromHand ? 'hand' : 'pile',
69530
- });
69531
- }
69532
- inspectHistoryCard(cardId) {
69533
- this.showHistory.set(false);
69534
- this.inspectHandCard(cardId);
69535
- }
69536
- inspectCharacter(card) {
69537
- this.selectedInfo.set(null);
69538
- this.selectedPreview.set({
69539
- title: card.name,
69540
- eyebrow: this.t('christianityCharacterCard'),
69541
- meta: `${card.attack}/${card.currentHp}`,
69542
- body: card.canAttack ? this.t('christianityCharacterReady') : this.t('christianityCharacterExhausted'),
69543
- });
69544
- }
69545
- spendOfferings(player, cost) {
69546
- let remaining = cost;
69547
- player.offerings = player.offerings.map(offering => {
69548
- if (remaining <= 0 || !offering.ready)
69549
- return offering;
69550
- remaining -= offering.value;
69551
- return { ...offering, ready: false };
69552
- });
69553
- }
69554
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ChristianityGameComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
69555
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: ChristianityGameComponent, isStandalone: true, selector: "val-christianity-game", ngImport: i0, template: `
69556
- <main class="christianity-shell">
69557
- <section class="christianity-header">
69558
- <div>
69559
- <p>{{ t('christianityEyebrow') }}</p>
69560
- <h1>{{ t('christianityTitle') }}</h1>
69561
- </div>
69562
- <div class="christianity-turn" [class.is-own-turn]="isOwnTurn()">
69563
- <span>{{ t('christianityTurn') }}</span>
69564
- <strong>{{ currentPlayer().displayName }}</strong>
69565
- </div>
69566
- </section>
69567
-
69568
- <section class="christianity-match-strip" [attr.aria-label]="t('christianityMatchScore')">
69569
- <article class="christianity-match-player">
69570
- <span class="christianity-avatar" [style.background]="player().avatarColor">{{ player().avatar }}</span>
69571
- <div>
69572
- <strong>{{ player().displayName }}</strong>
69573
- <small>{{ player().leaderName }} · {{ player().leaderHp }}/{{ player().leaderMaxHp }}</small>
69574
- </div>
69575
- </article>
69576
- <div class="christianity-scoreboard">
69577
- <span>{{ t('christianityMatch') }}</span>
69578
- <strong>{{ game().matchScore.P1 }}-{{ game().matchScore.P2 }}</strong>
69579
- </div>
69580
- <article class="christianity-match-player christianity-match-player--opponent">
69581
- <span class="christianity-avatar" [style.background]="opponent().avatarColor">{{ opponent().avatar }}</span>
69582
- <div>
69583
- <strong>{{ opponent().displayName }}</strong>
69584
- <small>{{ opponent().leaderName }} · {{ opponent().leaderHp }}/{{ opponent().leaderMaxHp }}</small>
69585
- </div>
69586
- </article>
69587
- </section>
69588
-
69589
- <section class="christianity-hand-shelf christianity-hand-shelf--opponent">
69590
- <div class="christianity-hand-meter christianity-hand-meter--opponent">
69591
- <span>{{ t('christianityHand') }}</span>
69592
- <strong>{{ opponentHandCount() }}</strong>
69593
- </div>
69594
- <section class="christianity-hand-fan christianity-hand-fan--opponent" [attr.aria-label]="t('christianityOpponentHand')">
69595
- @for (_ of hiddenHandCards(opponentHandCount()); track $index) {
69596
- <button
69597
- type="button"
69598
- class="christianity-card-preview-card christianity-card-frame christianity-card-frame--back"
69599
- valLightRipple
69600
- [style.transform]="fanTransform($index, opponentHandCount(), true)"
69601
- [attr.aria-label]="t('christianityHiddenCard')"
69602
- ></button>
69603
- }
69604
- </section>
69605
- </section>
69606
-
69607
- <section class="christianity-table" [attr.aria-label]="t('christianityTable')">
69608
- <section class="christianity-player-side christianity-player-side--opponent">
69609
- <section class="christianity-player-rack christianity-player-rack--opponent">
69610
- <div class="christianity-offerings-zone">
69611
- <button type="button" class="christianity-offering-pile" valLightRipple (click)="openOfferings('P2')">
69612
- <i aria-hidden="true"></i>
69613
- <i aria-hidden="true"></i>
69614
- <i aria-hidden="true"></i>
69615
- <span>{{ t('christianityOfferings') }}</span>
69616
- <strong>{{ readyOfferings(opponent()) }}/{{ totalOfferings(opponent()) }}</strong>
69617
- </button>
69618
- </div>
69619
- <button type="button" class="christianity-leader-card christianity-card-frame christianity-card-frame--leader" valLightRipple [class.is-target]="selectedAttacker() && !hasOpponentGuards()" (click)="handleOpponentLeader()">
69620
- <header class="christianity-card-frame-header">
69621
- <small>{{ t('christianityLeaderCard') }}</small>
69622
- <strong>{{ opponent().leaderName }}</strong>
69623
- <span>{{ opponent().leaderHp }}</span>
69624
- </header>
69625
- <section class="christianity-card-frame-art">
69626
- <span>{{ opponent().leaderName }}</span>
69627
- <small>{{ t('christianityLeaderCard') }}</small>
69628
- </section>
69629
- <section class="christianity-card-frame-effect">
69630
- <strong>{{ opponent().leaderHp }}/{{ opponent().leaderMaxHp }}</strong>
69631
- </section>
69632
- </button>
69633
- <span class="christianity-rack-spacer" aria-hidden="true"></span>
69634
- </section>
69635
-
69636
- <section class="christianity-battle-zone christianity-battle-zone--opponent" [attr.aria-label]="t('christianityOpponentBattle')">
69637
- @for (slot of battleSlots('P2'); track slot.trackId) {
69638
- @if (slot.card) {
69639
- <button
69640
- type="button"
69641
- class="christianity-card-preview-card christianity-card-preview-card--battle christianity-card-frame christianity-card-frame--battle"
69642
- valLightRipple
69643
- [class.is-target]="selectedAttacker()"
69644
- (click)="handleOpponentCharacter(slot.card)"
69645
- >
69646
- <header class="christianity-card-frame-header">
69647
- <small>{{ t('christianityCost') }} {{ cardDefinition(slot.card.cardId).cost }}</small>
69648
- <strong>{{ slot.card.name }}</strong>
69649
- <span>{{ cardDefinition(slot.card.cardId).cost }}</span>
69650
- </header>
69651
- <section class="christianity-card-frame-art">
69652
- <span>{{ slot.card.name }}</span>
69653
- <small>{{ t('christianityCharacterCard') }}</small>
69654
- </section>
69655
- <section class="christianity-card-frame-effect">
69656
- <strong>{{ slot.card.attack }} / {{ slot.card.currentHp }}</strong>
69657
- </section>
69658
- </button>
69659
- } @else {
69660
- <span class="christianity-slot"></span>
69661
- }
69662
- }
69663
- </section>
69664
- </section>
69665
-
69666
- <section class="christianity-shared-zone" [attr.aria-label]="t('christianitySharedZone')">
69667
- <button type="button" class="christianity-zone-pile christianity-zone-pile--history" valLightRipple (click)="openHistory()">
69668
- <i aria-hidden="true"></i>
69669
- <i aria-hidden="true"></i>
69670
- <i aria-hidden="true"></i>
69671
- <span>{{ t('christianityHistory') }}</span>
69672
- <strong>{{ game().historyZone.length }}</strong>
69673
- </button>
69674
- <button type="button" class="christianity-zone-pile christianity-zone-pile--deck" valLightRipple aria-live="polite" (click)="inspectDeck()">
69675
- <i aria-hidden="true"></i>
69676
- <i aria-hidden="true"></i>
69677
- <i aria-hidden="true"></i>
69678
- <span>{{ t('christianityDeck') }}</span>
69679
- <strong>{{ game().sharedDeck.length }}</strong>
69680
- </button>
69681
- <div class="christianity-zone-card">
69682
- <span>{{ t('christianityPlace') }}</span>
69683
- <strong>{{ t('christianityEmpty') }}</strong>
69684
- </div>
69685
- </section>
69686
-
69687
- <section class="christianity-player-side">
69688
- <section class="christianity-battle-zone" [class.is-placing-card]="canPlaceSelectedCharacter() || isDraggingCharacter()" [attr.aria-label]="t('christianityYourBattle')">
69689
- @for (slot of battleSlots('P1'); track slot.trackId) {
69690
- @if (slot.card) {
69691
- <button
69692
- type="button"
69693
- class="christianity-card-preview-card christianity-card-preview-card--battle christianity-card-frame christianity-card-frame--battle"
69694
- valLightRipple
69695
- [class.is-selected]="selectedAttacker()?.instanceId === slot.card.instanceId"
69696
- [class.is-exhausted]="!slot.card.canAttack"
69697
- (click)="selectAttacker(slot.card)"
69698
- >
69699
- <header class="christianity-card-frame-header">
69700
- <small>{{ t('christianityCost') }} {{ cardDefinition(slot.card.cardId).cost }}</small>
69701
- <strong>{{ slot.card.name }}</strong>
69702
- <span>{{ cardDefinition(slot.card.cardId).cost }}</span>
69703
- </header>
69704
- <section class="christianity-card-frame-art">
69705
- <span>{{ slot.card.name }}</span>
69706
- <small>{{ t('christianityCharacterCard') }}</small>
69707
- </section>
69708
- <section class="christianity-card-frame-effect">
69709
- <strong>{{ slot.card.attack }} / {{ slot.card.currentHp }}</strong>
69710
- </section>
69711
- </button>
69712
- } @else {
69713
- <button
69714
- type="button"
69715
- class="christianity-slot"
69716
- cdkDropList
69717
- [id]="battleSlotDropId($index)"
69718
- [cdkDropListData]="$index"
69719
- [cdkDropListConnectedTo]="['christianity-hand-source']"
69720
- [cdkDropListEnterPredicate]="canDropOnBattleSlot"
69721
- [class.christianity-slot--play-target]="canPlaceSelectedCharacter() || isDraggingCharacter()"
69722
- valLightRipple
69723
- (cdkDropListDropped)="dropOnBattleSlot($event, $index)"
69724
- (click)="playSelectedCard($index)"
69725
- >
69726
- @if (canPlaceSelectedCharacter() || isDraggingCharacter()) {
69727
- <span>{{ t('christianityPlayHere') }}</span>
69728
- }
69729
- </button>
69730
- }
69731
- }
69732
- </section>
69733
-
69734
- <section class="christianity-player-rack">
69735
- <div class="christianity-offerings-zone">
69736
- <button
69737
- type="button"
69738
- class="christianity-offering-pile"
69739
- cdkDropList
69740
- id="christianity-offerings-drop"
69741
- valLightRipple
69742
- [cdkDropListConnectedTo]="['christianity-hand-source']"
69743
- [class.is-play-target]="canPlaceSelectedOffering() || isDraggingOffering()"
69744
- [cdkDropListEnterPredicate]="canDropOnOfferings"
69745
- (cdkDropListDropped)="dropOnOfferings($event)"
69746
- (click)="handleOfferingPile('P1')"
69747
- >
69748
- <i aria-hidden="true"></i>
69749
- <i aria-hidden="true"></i>
69750
- <i aria-hidden="true"></i>
69751
- <span>{{ t('christianityOfferings') }}</span>
69752
- <strong>{{ readyOfferings(player()) }}/{{ totalOfferings(player()) }}</strong>
69753
- </button>
69754
- </div>
69755
- <button type="button" class="christianity-leader-card christianity-card-frame christianity-card-frame--leader" valLightRipple (click)="inspectLeader('P1')">
69756
- <header class="christianity-card-frame-header">
69757
- <small>{{ t('christianityLeaderCard') }}</small>
69758
- <strong>{{ player().leaderName }}</strong>
69759
- <span>{{ player().leaderHp }}</span>
69760
- </header>
69761
- <section class="christianity-card-frame-art">
69762
- <span>{{ player().leaderName }}</span>
69763
- <small>{{ t('christianityLeaderCard') }}</small>
69764
- </section>
69765
- <section class="christianity-card-frame-effect">
69766
- <strong>{{ player().leaderHp }}/{{ player().leaderMaxHp }}</strong>
69767
- </section>
69768
- </button>
69769
- <div class="christianity-player-command">
69770
- <div class="christianity-player-badge">
69771
- <span class="christianity-avatar" [style.background]="player().avatarColor">{{ player().avatar }}</span>
69772
- <strong>{{ player().displayName }}</strong>
69773
- </div>
69774
- <button
69775
- type="button"
69776
- class="christianity-end-turn"
69777
- (click)="endTurn()"
69778
- >
69779
- {{ t('christianityEndTurn') }}
69780
- </button>
69781
- </div>
69782
- </section>
69783
- </section>
69784
- </section>
69785
-
69786
- <section class="christianity-hand-shelf">
69787
- <div class="christianity-hand-meter">
69788
- <span>{{ t('christianityHand') }}</span>
69789
- <strong>{{ player().hand?.length ?? 0 }}</strong>
69790
- </div>
69791
- <section
69792
- class="christianity-hand-fan"
69793
- cdkDropList
69794
- id="christianity-hand-source"
69795
- [cdkDropListConnectedTo]="dropTargetIds()"
69796
- [attr.aria-label]="t('christianityYourHand')"
69797
- (pointerleave)="clearHoveredHandIndex()"
69798
- >
69799
- @for (cardId of player().hand ?? []; track cardId + $index) {
69800
- @let card = cardDefinition(cardId);
69801
- <div
69802
- class="christianity-hand-card-wrap"
69803
- [class.is-selected]="selectedHandCard() === cardId"
69804
- [class.is-dragging]="draggingCardId() === cardId"
69805
- [style.z-index]="handCardZIndex($index)"
69806
- [style.transform]="fanTransform($index, player().hand?.length ?? 0, false)"
69807
- (pointerenter)="setHoveredHandIndex($index)"
69808
- (pointerdown)="setHoveredHandIndex($index)"
69809
- (pointerup)="releaseHoveredHand($event)"
69810
- >
69811
- <button
69812
- type="button"
69813
- class="christianity-card-preview-card christianity-card-preview-card--hand christianity-card-frame"
69814
- cdkDrag
69815
- valLightRipple
69816
- [cdkDragData]="cardId"
69817
- [cdkDragDisabled]="!canPlay(card)"
69818
- [class.is-selected]="selectedHandCard() === cardId"
69819
- [class.is-disabled]="!canPlay(card)"
69820
- (cdkDragStarted)="startDraggingCard(cardId)"
69821
- (cdkDragEnded)="endDraggingCard()"
69822
- (click)="selectHandCard(cardId)"
69823
- >
69824
- <header class="christianity-card-frame-header">
69825
- <small>{{ card.type === 'offering' ? t('christianityOfferingCard') : t('christianityCost') + ' ' + card.cost }}</small>
69826
- <strong>{{ card.name }}</strong>
69827
- <span>{{ card.type === 'offering' ? '+' + card.life : card.cost }}</span>
69828
- </header>
69829
- <section class="christianity-card-frame-art">
69830
- <span>{{ card.name }}</span>
69831
- <small>{{ cardTypeLabel(card) }}</small>
69832
- </section>
69833
- <section class="christianity-card-frame-effect">
69834
- <strong>
69835
- @if (card.type === 'offering') {
69836
- +{{ card.life }}
69837
- } @else {
69838
- {{ card.attack }} / {{ card.life }}
69839
- }
69840
- </strong>
69841
- </section>
69842
- <footer class="christianity-card-frame-footer">
69843
- <span>{{ card.edition ?? 'MVP' }}</span>
69844
- <span>{{ card.collectorNumber ?? card.id }}</span>
69845
- </footer>
69846
- </button>
69847
- <button
69848
- type="button"
69849
- class="christianity-card-eye"
69850
- [attr.aria-label]="t('christianityPreviewCard')"
69851
- (click)="inspectHandCard(cardId, true); $event.stopPropagation()"
69852
- ></button>
69853
- </div>
69854
- }
69855
- </section>
69856
- </section>
69857
-
69858
- @if (selectedPreview()) {
69859
- <button type="button" class="christianity-preview-backdrop" [attr.aria-label]="t('christianityClosePreview')" (click)="closePreview()"></button>
69860
- <aside
69861
- class="christianity-floating-card-shell"
69862
- aria-live="polite"
69863
- >
69864
- <button type="button" class="christianity-floating-card-close" (click)="closePreview()">
69865
- {{ t('close') }}
69866
- </button>
69867
- <div
69868
- class="christianity-floating-card"
69869
- [style.--preview-rotate-x]="previewTilt().rotateX + 'deg'"
69870
- [style.--preview-rotate-y]="previewTilt().rotateY + 'deg'"
69871
- [style.--preview-shift-x]="previewTilt().shiftX + 'px'"
69872
- [style.--preview-shift-y]="previewTilt().shiftY + 'px'"
69873
- (pointermove)="tiltPreview($event)"
69874
- (pointerleave)="resetPreviewTilt()"
69875
- >
69876
- @if (selectedPreviewCard(); as previewCard) {
69877
- <header class="christianity-full-card-header">
69878
- <span class="christianity-full-card-type-icon" aria-hidden="true"></span>
69879
- <strong>{{ previewCard.name }}</strong>
69880
- <span class="christianity-full-card-cost">{{ previewCard.type === 'offering' ? '+' + previewCard.life : previewCard.cost }}</span>
69881
- </header>
69882
- <section class="christianity-full-card-art" [class.has-image]="previewCard.imageUrl">
69883
- @if (previewCard.imageUrl) {
69884
- <img [src]="previewCard.imageUrl" [alt]="previewCard.name" />
69885
- } @else {
69886
- <span>{{ previewCard.name }}</span>
69887
- }
69888
- <small>{{ cardTypeLabel(previewCard) }}</small>
69889
- </section>
69890
- <section class="christianity-full-card-verse">
69891
- <p>{{ previewCard.verseText ?? selectedPreview()?.body }}</p>
69892
- @if (previewCard.scripture) {
69893
- <strong>{{ previewCard.scripture }}</strong>
69894
- }
69895
- </section>
69896
- <section class="christianity-full-card-effect">
69897
- <div class="christianity-full-card-stats">
69898
- @if (previewCard.type === 'character') {
69899
- <strong>{{ previewCard.attack }}</strong>
69900
- <strong>{{ previewCard.life }}</strong>
69901
- } @else {
69902
- <strong>+{{ previewCard.life }}</strong>
69903
- }
69904
- </div>
69905
- <div>
69906
- @if (previewCard.abilityName) {
69907
- <strong>{{ previewCard.abilityName }}</strong>
69908
- }
69909
- <p>{{ previewCard.abilityText ?? selectedPreview()?.body }}</p>
69910
- </div>
69911
- <span
69912
- class="christianity-full-card-rarity"
69913
- [class.is-normal]="!previewCard.rarity || previewCard.rarity === 'normal'"
69914
- [class.is-uncommon]="previewCard.rarity === 'uncommon'"
69915
- [class.is-rare]="previewCard.rarity === 'rare'"
69916
- [class.is-legendary]="previewCard.rarity === 'legendary'"
69917
- aria-hidden="true"
69918
- ></span>
69919
- </section>
69920
- <footer class="christianity-full-card-footer">
69921
- <span>{{ previewCard.edition ?? 'MVP' }}</span>
69922
- <span>{{ previewCard.collectorNumber ?? previewCard.id }}</span>
69923
- <span>{{ previewCard.year ?? '2026' }} CHRISTIANITY</span>
69924
- <span>{{ previewCard.author ?? 'MVP' }}</span>
69925
- </footer>
69926
- } @else {
69927
- <small>{{ selectedPreview()?.eyebrow }}</small>
69928
- <strong>{{ selectedPreview()?.title }}</strong>
69929
- <span>{{ selectedPreview()?.meta }}</span>
69930
- <p>{{ selectedPreview()?.body }}</p>
69931
- }
69932
- </div>
69933
- @if (selectedPreview()?.source === 'hand') {
69934
- <div class="christianity-floating-card-actions">
69935
- <button type="button" [disabled]="previewActionDisabled()" (click)="playPreviewCard()">
69936
- {{ selectedActionLabel() }}
69937
- </button>
69938
- </div>
69939
- }
69940
- </aside>
69941
- }
69942
-
69943
- @if (selectedInfo(); as info) {
69944
- <button type="button" class="christianity-info-backdrop" [attr.aria-label]="t('close')" (click)="closeInfo()"></button>
69945
- <aside class="christianity-info-panel" aria-live="polite">
69946
- <button type="button" class="christianity-dialog-close christianity-info-close" (click)="closeInfo()">
69947
- {{ t('close') }}
69948
- </button>
69949
- <div class="christianity-rule-note">
69950
- <span class="christianity-rule-note-icon" aria-hidden="true">i</span>
69951
- <div>
69952
- <small>{{ info.eyebrow }}</small>
69953
- <h2>{{ info.title }}</h2>
69954
- <strong>{{ info.meta }}</strong>
69955
- <p>{{ info.body }}</p>
69956
- <ul>
69957
- @for (fact of info.facts; track fact) {
69958
- <li>{{ fact }}</li>
69959
- }
69960
- </ul>
69961
- </div>
69962
- </div>
69963
- </aside>
69964
- }
69965
-
69966
- <section class="christianity-actions" aria-live="polite">
69967
- <p>{{ statusText() }}</p>
69968
- <div>
69969
- <button type="button" [disabled]="selectedActionDisabled()" (click)="playSelectedCard()">
69970
- {{ selectedActionLabel() }}
69971
- </button>
69972
- <button type="button" (click)="resetMock()">
69973
- {{ t('christianityReset') }}
69974
- </button>
69975
- </div>
69976
- </section>
69977
-
69978
- @if (showHistory()) {
69979
- <button type="button" class="christianity-history-backdrop" [attr.aria-label]="t('christianityCloseHistory')" (click)="showHistory.set(false)"></button>
69980
- <section class="christianity-history-drawer">
69981
- <header>
69982
- <h2>{{ t('christianityHistory') }}</h2>
69983
- <div class="christianity-dialog-actions">
69984
- <span>{{ game().historyZone.length }}</span>
69985
- <button type="button" class="christianity-dialog-close" (click)="showHistory.set(false)">
69986
- {{ t('close') }}
69987
- </button>
69988
- </div>
69989
- </header>
69990
- @if (game().historyZone.length) {
69991
- <div class="christianity-history-grid">
69992
- @for (cardId of game().historyZone; track cardId + $index) {
69993
- @let card = cardDefinition(cardId);
69994
- <button type="button" class="christianity-card-preview-card christianity-card-frame christianity-card-frame--list" valLightRipple (click)="inspectHistoryCard(cardId)">
69995
- <header class="christianity-card-frame-header">
69996
- <small>{{ card.type === 'offering' ? t('christianityOfferingCard') : t('christianityCost') + ' ' + card.cost }}</small>
69997
- <strong>{{ card.name }}</strong>
69998
- <span>{{ card.type === 'offering' ? '+' + card.life : card.cost }}</span>
69999
- </header>
70000
- <section class="christianity-card-frame-art">
70001
- <span>{{ card.name }}</span>
70002
- <small>{{ cardTypeLabel(card) }}</small>
70003
- </section>
70004
- <section class="christianity-card-frame-effect">
70005
- <strong>
70006
- @if (card.type === 'offering') {
70007
- +{{ card.life }}
70008
- } @else {
70009
- {{ card.attack }} / {{ card.life }}
70010
- }
70011
- </strong>
70012
- </section>
70013
- </button>
70014
- }
70015
- </div>
70016
- } @else {
70017
- <p>{{ t('christianityHistoryEmpty') }}</p>
70018
- }
70019
- </section>
70020
- }
70021
-
70022
- @if (offeringsSeat()) {
70023
- @let offeringPlayer = game().players[offeringsSeat()!];
70024
- <button type="button" class="christianity-history-backdrop" [attr.aria-label]="t('christianityCloseOfferings')" (click)="closeOfferings()"></button>
70025
- <section class="christianity-history-drawer christianity-offerings-drawer">
70026
- <header>
70027
- <h2>{{ t('christianityOfferings') }}</h2>
70028
- <div class="christianity-dialog-actions">
70029
- <span>{{ readyOfferings(offeringPlayer) }}/{{ totalOfferings(offeringPlayer) }}</span>
70030
- <button type="button" class="christianity-dialog-close" (click)="closeOfferings()">
70031
- {{ t('close') }}
70032
- </button>
70033
- </div>
70034
- </header>
70035
- <div class="christianity-offering-list">
70036
- @for (offering of offeringPlayer.offerings; track offering.instanceId) {
70037
- <article class="christianity-offering-row" [class.is-exhausted]="!offering.ready">
70038
- <button type="button" class="christianity-offering-card christianity-card-frame christianity-card-frame--list" valLightRipple (click)="inspectOffering(offering)">
70039
- <header class="christianity-card-frame-header">
70040
- <small>{{ t('christianityOfferingCard') }}</small>
70041
- <strong>{{ offering.name }}</strong>
70042
- <span>+{{ offering.value }}</span>
70043
- </header>
70044
- <section class="christianity-card-frame-art">
70045
- <span>{{ offering.name }}</span>
70046
- <small>{{ t('christianityOfferingCard') }}</small>
70047
- </section>
70048
- <section class="christianity-card-frame-effect">
70049
- <strong>+{{ offering.value }}</strong>
70050
- @if (offering.abilityName) {
70051
- <p>{{ offering.abilityName }}</p>
70052
- }
70053
- </section>
70054
- </button>
70055
- <div>
70056
- <strong>{{ offering.ready ? t('christianityOfferingReady') : t('christianityOfferingExhausted') }}</strong>
70057
- <p>{{ offering.abilityText || t('christianityOfferingNoAbility') }}</p>
70058
- @if (offering.abilityName) {
70059
- <button
70060
- type="button"
70061
- [disabled]="!canUseOfferingAbility(offering, offeringsSeat()!)"
70062
- (click)="useOfferingAbility(offering, offeringsSeat()!)"
70063
- >
70064
- {{ t('christianityUseAbility') }}
70065
- </button>
70066
- }
70067
- </div>
70068
- </article>
70069
- }
70070
- </div>
70071
- </section>
70072
- }
70073
- </main>
70074
- `, isInline: true, styles: [":host{--christianity-theme-ink: var(--val-text-color, #1f2933);--christianity-theme-surface: #ffffff;--christianity-theme-parchment: #fffaf0;--christianity-theme-olive: #5f6f2a;--christianity-theme-gold: #d6a21d;--christianity-theme-gold-soft: rgba(214, 162, 29, .18);--christianity-theme-gold-ring: rgba(214, 162, 29, .48);--christianity-theme-glow: rgba(245, 199, 85, .32);--christianity-theme-focus: #2563eb;--christianity-theme-shadow: rgba(82, 64, 28, .18);--christianity-theme-shadow-strong: rgba(82, 64, 28, .3);--christianity-card-aspect: 5 / 7.45;display:block;max-width:100%;min-width:0;overflow-x:clip;color:var(--christianity-theme-ink)}.christianity-shell{box-sizing:border-box;display:grid;gap:.65rem;width:100%;max-width:100%;min-width:0;padding:.75rem .25rem;border:1px solid rgba(36,48,68,.12);border-radius:.75rem;background:#f6f8fb;overflow-x:clip;overflow-y:visible}.christianity-header,.christianity-match-strip,.christianity-player__summary,.christianity-shared-zone,.christianity-actions{display:flex;align-items:center;justify-content:space-between;gap:.75rem}.christianity-header h1,.christianity-header p,.christianity-match-player strong,.christianity-match-player small,.christianity-scoreboard span,.christianity-history h2,.christianity-actions p{margin:0}.christianity-header h1{font-size:1.35rem;line-height:1.1}.christianity-header p,.christianity-turn span,.christianity-offerings span,.christianity-hidden-hand span,.christianity-deck span,.christianity-place span,.christianity-pile span,.christianity-leader span{color:#1f2933a3;font-size:.75rem}.christianity-turn,.christianity-leader,.christianity-offerings,.christianity-hidden-hand,.christianity-pile,.christianity-deck,.christianity-place{display:grid;gap:.15rem;min-width:5.25rem;padding:.55rem .65rem;border:1px solid rgba(36,48,68,.12);border-radius:.5rem;background:#fff}.christianity-turn.is-own-turn{border-color:#12806c59;background:#ecfdf5}.christianity-match-strip{display:grid;grid-template-columns:minmax(0,1fr) auto minmax(0,1fr);padding:.45rem;border:1px solid rgba(36,48,68,.1);border-radius:.75rem;background:#fff}.christianity-match-player{display:grid;grid-template-columns:auto minmax(0,1fr);gap:.5rem;align-items:center;min-width:0}.christianity-match-player--opponent{direction:rtl}.christianity-match-player--opponent div{direction:ltr;text-align:right}.christianity-match-player div{display:grid;min-width:0}.christianity-match-player strong,.christianity-match-player small{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.christianity-match-player small,.christianity-scoreboard span{color:#1f293394;font-size:.72rem}.christianity-scoreboard{display:grid;justify-items:center;min-width:4.2rem;padding:0 .55rem;border-right:1px solid rgba(36,48,68,.1);border-left:1px solid rgba(36,48,68,.1)}.christianity-scoreboard strong{font-size:1.2rem;line-height:1}.christianity-table{box-sizing:border-box;display:grid;gap:.45rem;width:100%;max-width:100%;min-width:0;padding:.45rem .35rem;border-radius:.75rem;background:#dceafb;overflow-x:clip;overflow-y:visible}.christianity-player-side{box-sizing:border-box;display:grid;gap:.35rem;width:100%;max-width:100%;min-width:0;padding:.35rem .3rem;border-radius:.7rem;background:#ffffff57;grid-template-rows:minmax(7rem,1fr) auto;min-height:13.75rem}.christianity-player-side--opponent{grid-template-rows:auto minmax(7rem,1fr)}.christianity-player{display:grid;gap:.65rem}.christianity-battle-zone{--christianity-battle-card-width: clamp(4.8rem, 15vw, 6.6rem);box-sizing:border-box;display:grid;grid-template-columns:repeat(4,var(--christianity-battle-card-width));gap:.5rem;align-items:center;justify-content:center;width:100%;max-width:100%;min-width:0;min-height:clamp(9.1rem,29vw,11rem);padding:.55rem .4rem;border-radius:.75rem;background:#ffffffc2;transition:background .16s ease,box-shadow .16s ease}.christianity-battle-zone.is-placing-card{background:linear-gradient(180deg,#fffaf0f5,#ffffffd6),#ffffffc2;box-shadow:inset 0 0 0 .14rem var(--christianity-theme-gold-soft),0 .8rem 1.7rem #5f6f2a1f}.christianity-shared-zone{padding:.55rem .4rem;border-radius:.75rem;background:#ffffffe6}.christianity-card,.christianity-end-turn,.christianity-actions button,.christianity-pile,.christianity-leader--target{border:1px solid rgba(36,48,68,.16);border-radius:.5rem;background:#fff;color:inherit;font:inherit}.christianity-card{display:grid;align-content:space-between;min-height:5.8rem;padding:.5rem;text-align:left;box-shadow:0 .5rem 1.25rem #24304414}.christianity-card span{font-weight:700}.christianity-card strong{justify-self:end;padding:.15rem .35rem;border-radius:999px;background:#edf2f7;font-size:.8rem}.christianity-card.is-selected{border-color:var(--christianity-theme-gold);box-shadow:0 0 0 .18rem var(--christianity-theme-gold-soft),0 .85rem 1.4rem var(--christianity-theme-shadow)}.christianity-card.is-disabled,.christianity-card.is-exhausted{opacity:.55}.christianity-card.is-target{border-color:#dc2626}.christianity-offering-cards{display:grid;grid-auto-flow:column;grid-auto-columns:.7rem;gap:.16rem;align-items:end;min-height:1.05rem}.christianity-offering-cards i{display:block;width:.65rem;height:.95rem;border:1px solid rgba(16,42,67,.22);border-radius:.18rem;background:#f8fafc}.christianity-offering-cards i.is-used{background:#cbd5e1;transform:rotate(90deg);transform-origin:center}.christianity-slot{display:grid;place-items:center;justify-self:center;width:var(--christianity-battle-card-width);height:auto;min-height:0;aspect-ratio:var(--christianity-card-aspect);border:1px dashed rgba(36,48,68,.22);border-radius:.5rem;background:#ffffff73;color:inherit;font:inherit}.christianity-slot--play-target{position:relative;border-color:var(--christianity-theme-gold-ring);background:linear-gradient(180deg,#fffaf0eb,#f8fafcd1),#ffffffb3;color:#5d4305;font-weight:800;overflow:hidden;box-shadow:inset 0 0 0 .12rem #d6a21d33,0 .7rem 1.25rem var(--christianity-theme-shadow);animation:christianity-target-pulse 1.45s ease-in-out infinite}.christianity-slot--play-target:before{content:\"\";position:absolute;inset:.35rem;border:1px solid rgba(214,162,29,.22);border-radius:.4rem;background:linear-gradient(135deg,rgba(214,162,29,.1),transparent 46%),radial-gradient(circle at 50% 42%,var(--christianity-theme-glow),transparent 58%)}.christianity-slot--play-target span{position:relative;z-index:2;padding:.16rem .44rem;border-radius:999px;background:#ffffffc7;font-size:.78rem}@keyframes christianity-target-pulse{0%,to{box-shadow:inset 0 0 0 .12rem #d6a21d33,0 .7rem 1.25rem var(--christianity-theme-shadow)}50%{box-shadow:inset 0 0 0 .16rem #d6a21d57,0 .9rem 1.65rem var(--christianity-theme-shadow-strong)}}.christianity-hand{display:grid;grid-auto-columns:minmax(6rem,8rem);grid-auto-flow:column;gap:.55rem;overflow-x:auto;padding-bottom:.25rem}.christianity-actions{align-items:flex-start;padding:.75rem;border-radius:.75rem;background:#fff}.christianity-actions div{display:flex;flex-wrap:wrap;gap:.5rem;justify-content:flex-end}.christianity-actions button,.christianity-end-turn{min-height:2.4rem;padding:0 .75rem;font-weight:700}.christianity-actions button:not(:disabled),.christianity-end-turn{background:#102a43;color:#fff}.christianity-history{padding:.75rem;border-radius:.75rem;background:#fff}.christianity-hand-fan{position:relative;display:flex;justify-content:center;min-height:10.8rem;padding:.25rem .25rem 2.1rem;isolation:isolate;overflow:visible}.christianity-hand-shelf{position:relative;display:grid;z-index:12;min-height:12rem;margin-top:-1.15rem;padding:1.45rem .25rem 1rem;overflow:visible}.christianity-hand-shelf--opponent{z-index:8;min-height:6.85rem;margin-top:0;margin-bottom:0;padding:.45rem .25rem .85rem}.christianity-hand-fan--opponent{min-height:5.9rem;padding-bottom:.75rem;align-items:start}.christianity-card-preview-card,.christianity-card-mini,.christianity-offering-pile,.christianity-offering-card,.christianity-leader-card,.christianity-zone-card,.christianity-zone-pile,.christianity-end-turn{border:1px solid rgba(36,48,68,.16);border-radius:.5rem;background:#fff;color:inherit;font:inherit}.christianity-card-preview-card{display:grid;grid-template-rows:auto minmax(0,1fr) auto auto;gap:.28rem;align-content:stretch;width:clamp(4.9rem,17vw,7.1rem);height:auto;min-height:0;aspect-ratio:var(--christianity-card-aspect);padding:.48rem;text-align:left;transform-origin:50% 115%;transition:transform .16s ease,box-shadow .16s ease,border-color .16s ease;box-shadow:0 .5rem 1.25rem #2430441a}.christianity-card-frame{position:relative;display:grid;grid-template-rows:auto minmax(0,1fr) auto auto;gap:.28rem;align-content:stretch;overflow:hidden;padding:.48rem;text-align:left;background:linear-gradient(180deg,#fffffffa,#f8fafcfa),radial-gradient(circle at 15% 0%,rgba(214,162,29,.12),transparent 44%);box-shadow:0 .5rem 1.25rem #2430441a,inset 0 0 0 .18rem #ffffff9e}.christianity-card-frame-header{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:.16rem;align-items:start;min-width:0}.christianity-card-frame-header small{grid-column:1;min-width:0;overflow:hidden;color:#1f2933a3;font-size:clamp(.52rem,1.5vw,.68rem);line-height:1;text-overflow:ellipsis;white-space:nowrap}.christianity-card-frame-header strong{grid-column:1;justify-self:start;align-self:start;min-width:0;padding:0;overflow:hidden;border-radius:0;background:transparent;font-size:clamp(.82rem,2.5vw,1.05rem);line-height:1.02;text-overflow:ellipsis;white-space:nowrap}.christianity-card-frame-header span{grid-column:2;grid-row:1 / span 2;display:grid;place-items:center;min-width:1.3rem;height:1.3rem;padding:0 .22rem;border-radius:999px;background:#ffd91a;color:#243044;font-size:.8rem;font-weight:900;line-height:1;box-shadow:inset 0 -.08rem #52401c2e}.christianity-card-frame-art{position:relative;display:grid;place-items:center;min-height:0;overflow:hidden;border-radius:.36rem;background:linear-gradient(135deg,#5f6f2a2e,#d6a21d24),radial-gradient(circle at 50% 18%,rgba(255,255,255,.72),transparent 48%),#dbe7ef;box-shadow:inset 0 0 0 1px #24304414}.christianity-card-frame-art>span{max-width:78%;overflow:hidden;color:#2430447a;font-size:clamp(.82rem,2.2vw,1.05rem);font-weight:900;line-height:1.02;text-align:center;text-overflow:ellipsis}.christianity-card-frame-art small{position:absolute;right:0;bottom:.28rem;max-width:78%;padding:.1rem .34rem;overflow:hidden;border-radius:999px 0 0 999px;background:#ffffffe6;color:#1f2933a8;font-size:.48rem;font-style:italic;font-weight:900;line-height:1;text-overflow:ellipsis;text-transform:uppercase;white-space:nowrap}.christianity-card-frame-effect{display:grid;align-content:center;gap:.1rem;min-height:1.45rem;padding:.24rem;overflow:hidden;border-radius:.34rem;background:radial-gradient(circle at 50% 70%,rgba(36,48,68,.06),transparent 44%),#ffffffdb}.christianity-card-frame-effect strong{justify-self:end;align-self:end;padding:.12rem .32rem;border-radius:999px;background:#edf2f7;font-size:clamp(.66rem,2vw,.82rem);line-height:1.05}.christianity-card-frame-effect p{margin:0;overflow:hidden;color:#1f2933b8;font-size:.58rem;line-height:1.1;text-overflow:ellipsis;white-space:nowrap}.christianity-card-frame-footer{display:flex;justify-content:space-between;gap:.22rem;color:#1f293385;font-size:.46rem;font-weight:800;line-height:1}.christianity-card-frame--battle{gap:.22rem;padding:.42rem}.christianity-card-frame--battle .christianity-card-frame-art{min-height:2.6rem}.christianity-card-frame--leader .christianity-card-frame-art{background:linear-gradient(135deg,#2563eb24,#d6a21d29),radial-gradient(circle at 50% 18%,rgba(255,255,255,.78),transparent 48%),#e7eef8}.christianity-card-frame--list{width:clamp(4.4rem,22vw,5.8rem);padding:.38rem}.christianity-card-frame--list .christianity-card-frame-art{min-height:2.5rem}.christianity-hand-card-wrap{position:relative;display:grid;justify-items:center;flex:0 0 auto;margin-inline:-.42rem;padding-bottom:2rem;transform-origin:50% 115%;transition:transform .16s ease,filter .16s ease}.christianity-hand-card-wrap:hover,.christianity-hand-card-wrap.is-selected,.christianity-hand-card-wrap.is-dragging{z-index:3}.christianity-hand-card-wrap:hover .christianity-card-preview-card--hand,.christianity-hand-card-wrap.is-selected .christianity-card-preview-card--hand,.christianity-hand-card-wrap.is-dragging .christianity-card-preview-card--hand{border-color:var(--christianity-theme-gold);box-shadow:0 0 0 .12rem var(--christianity-theme-gold-soft),0 1rem 2rem var(--christianity-theme-shadow)}.christianity-card-preview-card--hand{touch-action:none}.christianity-card-preview-card--hand.cdk-drag-disabled{cursor:not-allowed}.christianity-card-preview-card.cdk-drag-preview{width:clamp(4.9rem,17vw,7.1rem);height:auto;min-height:0;aspect-ratio:var(--christianity-card-aspect);border:1px solid var(--christianity-theme-gold-ring);box-shadow:0 0 0 .16rem #fff4c2ad,0 1.5rem 3rem var(--christianity-theme-shadow-strong);transform:rotate(2deg) scale(1.03)}.christianity-card-preview-card.cdk-drag-placeholder{width:clamp(4.9rem,17vw,7.1rem);height:auto;min-height:0;aspect-ratio:var(--christianity-card-aspect);opacity:.22}.christianity-slot.cdk-drop-list-dragging,.christianity-offering-pile.cdk-drop-list-dragging{border-color:var(--christianity-theme-gold-ring)}.christianity-slot.cdk-drop-list-receiving,.christianity-offering-pile.cdk-drop-list-receiving{box-shadow:inset 0 0 0 .18rem #d6a21d57,0 1rem 1.9rem var(--christianity-theme-shadow-strong)}.christianity-card-eye{position:absolute;right:50%;bottom:.38rem;width:2.15rem;height:1.55rem;border:1px solid color-mix(in srgb,var(--christianity-theme-focus) 52%,transparent);border-radius:999px;background:#fffffff0;box-shadow:0 .55rem 1.1rem #102a4324;opacity:0;transform:translate(50%,-.2rem) scale(.92);transition:opacity .14s ease,transform .14s ease,border-color .14s ease}.christianity-card-eye:before{content:\"\";position:absolute;top:50%;left:50%;width:1.1rem;height:1.1rem;border:.12rem solid var(--christianity-theme-focus);border-radius:82% 0;background:#fffffff0;transform:translate(-50%,-50%) rotate(45deg)}.christianity-card-eye:after{content:\"\";position:absolute;top:50%;left:50%;width:.42rem;height:.42rem;border:.09rem solid rgba(255,255,255,.95);border-radius:999px;background:radial-gradient(circle at 35% 32%,#ffffff 0 .06rem,transparent .07rem),var(--christianity-theme-focus);transform:translate(-50%,-50%)}.christianity-hand-card-wrap:hover .christianity-card-eye,.christianity-hand-card-wrap.is-selected .christianity-card-eye,.christianity-card-eye:focus-visible{opacity:1;transform:translate(50%) scale(1)}.christianity-offering-pile.is-play-target{border-color:var(--christianity-theme-gold-ring);background:linear-gradient(180deg,#fffaf0f5,#fffffff0),radial-gradient(circle at 82% 14%,rgba(250,204,21,.28) 0 .7rem,transparent .72rem);box-shadow:inset 0 0 0 .12rem #d6a21d3d,0 .8rem 1.55rem var(--christianity-theme-shadow);animation:christianity-target-pulse 1.45s ease-in-out infinite}.christianity-card-preview-card--back{width:clamp(4rem,14vw,5.7rem);min-height:0;aspect-ratio:var(--christianity-card-aspect);place-items:center;padding:.55rem;box-shadow:0 .8rem 1.55rem #24304424;transform-origin:50% -18%;background:linear-gradient(135deg,#102a431f,#102a4305),repeating-linear-gradient(45deg,#dbeafe 0 .33rem,#fff .33rem .66rem)}.christianity-card-preview-card--battle{justify-self:center;width:var(--christianity-battle-card-width);min-width:0;height:auto;min-height:0;aspect-ratio:var(--christianity-card-aspect);margin-inline:0}.christianity-card-preview-card>span,.christianity-card-mini>span,.christianity-offering-pile>span,.christianity-offering-card>span,.christianity-leader-card>span,.christianity-zone-card>span,.christianity-zone-pile>span{position:relative;z-index:2;align-self:start;font-weight:700;line-height:1.05}.christianity-card-preview-card>strong,.christianity-card-mini>strong,.christianity-offering-pile>strong,.christianity-offering-card>strong,.christianity-leader-card>strong,.christianity-zone-card>strong,.christianity-zone-pile>strong{position:relative;z-index:3;justify-self:end;align-self:end;padding:.15rem .35rem;border-radius:999px;background:#edf2f7;font-size:.8rem}.christianity-player-rack{box-sizing:border-box;display:grid;grid-template-columns:minmax(5.9rem,7rem) minmax(5rem,1fr) minmax(4.2rem,7rem);gap:.45rem;align-items:end;justify-items:stretch;width:100%;max-width:100%;min-width:0}.christianity-player-rack--opponent{align-items:start}.christianity-hand-meter{position:absolute;top:0;right:.35rem;z-index:4;display:inline-grid;grid-auto-flow:column;gap:.25rem;align-items:center;min-height:1.7rem;padding:.18rem .46rem;border:1px solid rgba(36,48,68,.12);border-radius:999px;background:#ffffffe6;box-shadow:0 .35rem .8rem #102a4314}.christianity-hand-meter--opponent{top:.15rem}.christianity-hand-meter span{color:#1f293394;font-size:.68rem}.christianity-hand-meter strong{font-size:.86rem}.christianity-player-badge,.christianity-player-command{display:grid;gap:.35rem;justify-items:center;min-width:0}.christianity-player-badge{align-content:start;color:#1f2933c2;font-size:.74rem}.christianity-player-badge--opponent{justify-self:center;grid-auto-flow:column;align-items:center;justify-content:center}.christianity-player-badge strong{max-width:6.5rem;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.christianity-avatar{display:grid;place-items:center;width:1.85rem;height:1.85rem;border-radius:999px;color:#fff;font-size:.76rem;font-weight:800;box-shadow:0 .35rem .9rem #102a4329}.christianity-offerings-zone{display:flex;flex-wrap:wrap;gap:.25rem;justify-content:flex-start;justify-self:start;width:100%}.christianity-card-mini,.christianity-offering-pile,.christianity-offering-card,.christianity-leader-card,.christianity-zone-card,.christianity-zone-pile{display:grid;align-content:space-between;min-height:4.9rem;padding:.48rem;text-align:left}.christianity-card-frame{display:grid;grid-template-rows:auto minmax(0,1fr) auto auto;align-content:stretch}.christianity-offering-pile,.christianity-zone-card,.christianity-zone-pile{grid-template-rows:auto minmax(2.6rem,1fr) auto;align-content:stretch;gap:.32rem}.christianity-card-mini{width:3.5rem}.christianity-offering-pile{position:relative;isolation:isolate;overflow:hidden;justify-self:start;width:min(100%,5.9rem);min-height:7.1rem;padding:.95rem .52rem .6rem;background:linear-gradient(180deg,#fff,#f8fafc),linear-gradient(135deg,rgba(250,204,21,.18),transparent 42%)}.christianity-offering-pile i{position:absolute;top:2.45rem;left:.72rem;z-index:-1;width:2.55rem;height:3.55rem;border:1px solid rgba(16,42,67,.18);border-radius:.35rem;background:linear-gradient(180deg,#ffffffeb,#f1f5f9eb),radial-gradient(circle at 78% 18%,#facc15 0 .38rem,transparent .4rem);box-shadow:0 .35rem .85rem #102a431a;transform:rotate(-5deg)}.christianity-offering-pile i:nth-child(2){transform:translate(.28rem,.08rem) rotate(3deg)}.christianity-offering-pile i:nth-child(3){transform:translate(.55rem,.18rem) rotate(-1deg)}.christianity-leader-card{align-self:center;justify-self:center;width:clamp(4.75rem,17vw,6rem);min-height:0;aspect-ratio:var(--christianity-card-aspect)}.christianity-rack-spacer{display:block;min-height:1px}.christianity-battle-zone{grid-template-columns:repeat(4,var(--christianity-battle-card-width))}.christianity-shared-zone{box-sizing:border-box;display:grid;grid-template-columns:repeat(3,minmax(4.3rem,1fr));align-items:stretch;width:100%;max-width:100%;min-width:0}.christianity-zone-card,.christianity-zone-pile{min-height:6.45rem;padding:.7rem .52rem .55rem}.christianity-zone-pile{position:relative;isolation:isolate;overflow:hidden;box-shadow:inset 0 0 0 999px #ffffff1f}.christianity-zone-pile i{position:absolute;top:2.2rem;right:.72rem;z-index:-1;width:2.7rem;height:3.7rem;border:1px solid rgba(16,42,67,.18);border-radius:.35rem;background:#f8fafc;box-shadow:0 .35rem .85rem #102a431c;transform:rotate(4deg)}.christianity-zone-pile i:nth-child(2){transform:translate(-.28rem,.12rem) rotate(-3deg)}.christianity-zone-pile i:nth-child(3){background:linear-gradient(135deg,#102a4329,#102a4308),repeating-linear-gradient(45deg,#dbeafe 0 .33rem,#fff .33rem .66rem);transform:translate(-.54rem,.24rem) rotate(2deg)}.christianity-floating-card-shell{position:fixed;top:50%;left:50%;z-index:80;display:grid;gap:.55rem;width:min(26rem,calc(100vw - 1.25rem));padding-top:2.35rem;transform:translate(-50%,-50%)}.christianity-floating-card{position:relative;z-index:1;display:grid;grid-template-rows:auto minmax(9rem,1.25fr) auto minmax(7rem,.9fr) auto;gap:.58rem;width:100%;min-height:min(29rem,calc(100vh - 3.5rem));padding:.72rem;border:1px solid rgba(36,48,68,.18);border-radius:.75rem;background:linear-gradient(180deg,#fffffff5,#f8fafcf5),radial-gradient(circle at 20% 0%,var(--christianity-theme-gold-soft),transparent 45%);box-shadow:0 0 0 .18rem #fff4c294,0 0 2.2rem var(--christianity-theme-glow),0 2.4rem 5rem #102a4357,inset 0 0 0 .35rem #ffffff8c;touch-action:none;transform:translate(var(--preview-shift-x, 0px),var(--preview-shift-y, 0px)) perspective(48rem) rotateX(var(--preview-rotate-x, 5deg)) rotateY(var(--preview-rotate-y, -5deg));transition:transform 90ms ease-out}.christianity-full-card-header{display:grid;grid-template-columns:auto minmax(0,1fr) auto;gap:.42rem;align-items:center}.christianity-full-card-header strong{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:clamp(1.25rem,5vw,1.85rem);line-height:1.04}.christianity-full-card-type-icon,.christianity-full-card-cost{display:grid;place-items:center;border-radius:999px}.christianity-full-card-type-icon{width:1.6rem;height:1.6rem;background:radial-gradient(circle at 50% 50%,rgba(95,111,42,.72) 0 .22rem,transparent .24rem),#2430441a}.christianity-full-card-cost{width:2.1rem;height:2.1rem;background:#ffd91a;color:#243044;font-size:1.35rem;font-weight:900;box-shadow:inset 0 -.12rem #52401c2e}.christianity-full-card-art{position:relative;display:grid;place-items:center;min-height:9rem;overflow:hidden;border-radius:.48rem;background:linear-gradient(135deg,#5f6f2a33,#d6a21d29),radial-gradient(circle at 50% 25%,rgba(255,255,255,.76),transparent 42%),#dbe7ef;box-shadow:inset 0 0 0 1px #24304414}.christianity-full-card-art img{width:100%;height:100%;object-fit:cover}.christianity-full-card-art>span{max-width:80%;color:#24304494;font-size:clamp(1.1rem,5vw,1.8rem);font-weight:900;line-height:1.05;text-align:center}.christianity-full-card-art small{position:absolute;right:0;bottom:.55rem;min-width:5rem;padding:.16rem .48rem;border-radius:999px 0 0 999px;background:#ffffffe6;box-shadow:0 .3rem .8rem #102a431f;color:#1f2933bd;font-size:.68rem;font-style:italic;font-weight:900;text-align:center;text-transform:uppercase}.christianity-full-card-verse,.christianity-full-card-effect{display:grid;gap:.32rem}.christianity-full-card-verse p,.christianity-full-card-effect p{margin:0;line-height:1.25}.christianity-full-card-verse{color:#171923;font-family:Georgia,Times New Roman,serif;font-size:clamp(.72rem,2.7vw,.86rem)}.christianity-full-card-verse strong{font-family:inherit;font-size:.78rem;font-weight:900}.christianity-full-card-effect{position:relative;align-content:start;min-height:7rem;padding:.6rem .7rem;overflow:hidden;border-radius:.45rem;background:radial-gradient(circle at 50% 72%,rgba(36,48,68,.07),transparent 34%),#ffffffdb}.christianity-full-card-stats{display:flex;gap:1rem;min-height:1.35rem}.christianity-full-card-stats strong{font-size:1rem;line-height:1}.christianity-full-card-effect>div:last-of-type{display:grid;gap:.12rem}.christianity-full-card-effect>div:last-of-type strong{font-size:.82rem}.christianity-full-card-effect p{font-size:clamp(.78rem,2.9vw,.92rem)}.christianity-full-card-rarity{position:absolute;top:.62rem;right:.62rem;width:.46rem;height:.46rem;border-radius:.12rem;transform:rotate(45deg)}.christianity-full-card-rarity.is-normal{background:#d1d5db}.christianity-full-card-rarity.is-uncommon{background:#22c55e}.christianity-full-card-rarity.is-rare{background:#3b82f6}.christianity-full-card-rarity.is-legendary{background:#eab308}.christianity-full-card-footer{display:grid;grid-template-columns:auto auto minmax(0,1fr) auto;gap:.34rem;align-items:center;color:#1f2933ad;font-size:.58rem;line-height:1;text-transform:uppercase}.christianity-full-card-footer span{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.christianity-floating-card-close{position:absolute;top:0;right:.15rem;z-index:4;min-height:2rem;padding:0 .6rem;border:1px solid rgba(36,48,68,.14);border-radius:999px;background:#ffffffe6;color:#1f2933c7;font:inherit;font-size:.76rem;font-weight:800;box-shadow:0 .45rem 1rem #102a431a}.christianity-preview-backdrop,.christianity-history-backdrop,.christianity-info-backdrop{position:fixed;inset:0;border:0;border-radius:0;background:#0f172a75}.christianity-preview-backdrop{z-index:79}.christianity-info-backdrop{z-index:50}.christianity-info-panel{position:fixed;top:50%;left:50%;z-index:51;width:min(31rem,calc(100vw - 1.25rem));max-height:min(34rem,calc(100vh - 2rem));padding-top:2.35rem;transform:translate(-50%,-50%)}.christianity-info-close{position:absolute;top:0;right:.15rem;z-index:2}.christianity-rule-note{display:grid;grid-template-columns:auto minmax(0,1fr);gap:.85rem;max-height:inherit;padding:1rem;overflow-y:auto;border:1px solid rgba(36,48,68,.14);border-radius:.9rem;background:linear-gradient(180deg,#fffffff7,#f8fafcf7),radial-gradient(circle at 8% 0%,rgba(37,99,235,.1),transparent 38%);box-shadow:0 1.2rem 2.6rem #102a433d,inset 0 0 0 .25rem #ffffff85}.christianity-rule-note-icon{display:grid;place-items:center;width:2.1rem;height:2.1rem;border-radius:999px;background:color-mix(in srgb,var(--christianity-theme-focus) 12%,#ffffff);color:var(--christianity-theme-focus);font-size:1rem;font-weight:900;box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--christianity-theme-focus) 24%,transparent)}.christianity-rule-note small,.christianity-rule-note strong,.christianity-rule-note p,.christianity-rule-note h2{margin:0}.christianity-rule-note small{color:#1f29339e;font-size:.78rem;font-weight:800;text-transform:uppercase}.christianity-rule-note h2{margin-top:.18rem;font-size:clamp(1.5rem,7vw,2.2rem);line-height:1.05}.christianity-rule-note strong{display:inline-flex;width:fit-content;margin-top:.55rem;padding:.22rem .55rem;border-radius:999px;background:#edf2f7;font-size:.92rem}.christianity-rule-note p{margin-top:.75rem;color:#1f2933c7;line-height:1.45}.christianity-rule-note ul{display:grid;gap:.45rem;margin:.8rem 0 0;padding-left:1.05rem;color:#1f2933c7;line-height:1.35}.christianity-floating-card>small,.christianity-floating-card>span{color:#1f2933a3}.christianity-floating-card>strong{font-size:clamp(1.55rem,8vw,2.35rem);line-height:1.05}.christianity-floating-card>p{margin:0;align-self:end;font-size:.95rem;line-height:1.35}.christianity-floating-card-actions{position:relative;z-index:4;display:flex;justify-content:center;padding:0 .35rem;transform:translateZ(0)}.christianity-floating-card-actions button{min-height:2.35rem;padding:0 1rem;border:0;border-radius:999px;background:#102a43;color:#fff;font:inherit;font-size:.9rem;font-weight:800;box-shadow:0 .65rem 1.3rem #102a432e}.christianity-floating-card-actions button:disabled{cursor:not-allowed;opacity:.45}@media (min-width: 52rem){.christianity-floating-card-shell{width:min(29rem,calc(100vw - 3rem))}.christianity-floating-card{min-height:min(35rem,calc(100vh - 4rem));padding:1.35rem}}.christianity-history-backdrop{z-index:40}.christianity-history-drawer{position:fixed;right:auto;bottom:max(.5rem,env(safe-area-inset-bottom));left:50%;z-index:41;display:grid;grid-template-rows:auto minmax(0,1fr);gap:.75rem;width:min(calc(100vw - 1rem),44rem);min-height:min(18rem,calc(100dvh - 1rem));max-height:min(32rem,calc(100dvh - 2rem));padding:.8rem;border:1px solid rgba(36,48,68,.16);border-radius:.75rem;background:#fffffffa;box-shadow:0 1.5rem 4rem #102a4347;transform:translate(-50%)}.christianity-history-drawer header{display:flex;align-items:center;justify-content:space-between;gap:.75rem}.christianity-history-drawer h2,.christianity-history-drawer p{margin:0}.christianity-history-drawer header span{display:grid;place-items:center;min-width:1.85rem;height:1.85rem;border-radius:999px;background:#edf2f7;font-weight:800}.christianity-dialog-actions{display:flex;align-items:center;gap:.45rem}.christianity-dialog-close{min-height:1.85rem;padding:0 .62rem;border:1px solid rgba(36,48,68,.14);border-radius:999px;background:#fff;color:#1f2933c7;font:inherit;font-size:.76rem;font-weight:800;box-shadow:0 .35rem .8rem #102a4314}.christianity-history-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(5.4rem,1fr));gap:.55rem;min-height:0;overflow-y:scroll;scrollbar-color:rgba(36,48,68,.32) rgba(226,232,240,.72);scrollbar-gutter:stable;padding:.1rem .1rem .25rem}.christianity-history-grid::-webkit-scrollbar,.christianity-offering-list::-webkit-scrollbar{width:.65rem}.christianity-history-grid::-webkit-scrollbar-track,.christianity-offering-list::-webkit-scrollbar-track{border-radius:999px;background:#e2e8f0b8}.christianity-history-grid::-webkit-scrollbar-thumb,.christianity-offering-list::-webkit-scrollbar-thumb{border:.14rem solid rgba(226,232,240,.72);border-radius:999px;background:#24304452}.christianity-offerings-drawer{width:min(calc(100vw - 1rem),48rem);min-height:min(20rem,calc(100dvh - 1rem));max-height:min(34rem,calc(100dvh - 2rem))}.christianity-offering-list{display:grid;gap:.6rem;min-height:0;overflow-y:scroll;scrollbar-color:rgba(36,48,68,.32) rgba(226,232,240,.72);scrollbar-gutter:stable;padding:.1rem}.christianity-offering-row{display:grid;grid-template-columns:minmax(4.9rem,6.2rem) minmax(0,1fr);gap:.65rem;align-items:stretch;padding:.45rem;border:1px solid rgba(36,48,68,.12);border-radius:.65rem;background:#fff}.christianity-offering-row.is-exhausted{opacity:.68}.christianity-offering-card{min-height:7.4rem;background:linear-gradient(180deg,#fffffff5,#f8fafcf5),radial-gradient(circle at 82% 14%,#facc15 0 .48rem,transparent .5rem);box-shadow:0 .45rem 1rem #102a431a}.christianity-offering-card.christianity-card-frame{min-height:0;aspect-ratio:var(--christianity-card-aspect)}.christianity-offering-card small{color:#1f293394;font-size:.66rem;text-transform:uppercase}.christianity-offering-card p,.christianity-offering-row p{margin:0}.christianity-offering-card p{align-self:end;color:#1f2933a3;font-size:.72rem;line-height:1.2}.christianity-offering-row>div{display:grid;gap:.35rem;align-content:center;min-width:0}.christianity-offering-row>div p{color:#1f2933b8;font-size:.85rem;line-height:1.3}.christianity-offering-row>div button{justify-self:start;min-height:2.2rem;padding:0 .7rem;border:1px solid rgba(16,42,67,.16);border-radius:.5rem;background:#102a43;color:#fff;font:inherit;font-weight:800}.christianity-offering-row>div button:disabled{background:#e2e8f0;color:#1f293394}button{cursor:pointer}button:disabled{cursor:not-allowed;opacity:.55}button:focus-visible{outline:.1875rem solid color-mix(in srgb,var(--christianity-theme-focus) 24%,transparent);outline-offset:.125rem}@media (max-width: 720px){.christianity-shell{padding:.55rem 0;border-right:0;border-left:0;border-radius:0}.christianity-header,.christianity-player__summary,.christianity-shared-zone,.christianity-actions{align-items:stretch;flex-direction:column}.christianity-match-strip{grid-template-columns:minmax(0,1fr) auto minmax(0,1fr);gap:.35rem;padding:.35rem}.christianity-match-player{gap:.35rem}.christianity-match-player small{display:none}.christianity-scoreboard{min-width:3.65rem;padding:0 .35rem}.christianity-scoreboard strong{font-size:1.05rem}.christianity-table{gap:.35rem;padding-right:.25rem;padding-left:.25rem}.christianity-player-side{padding:.3rem .25rem}.christianity-battle-zone{--christianity-battle-card-width: min(5.2rem, calc((100vw - 4.25rem)/4) );grid-template-columns:repeat(4,var(--christianity-battle-card-width));justify-content:center;min-height:8.75rem;overflow-x:clip}.christianity-hand-fan{min-height:11.45rem;padding-bottom:2rem;overflow:visible}.christianity-hand-shelf{min-height:12.65rem;margin-top:-1rem;padding-top:1.35rem;padding-bottom:.9rem}.christianity-hand-shelf--opponent{min-height:6.65rem;margin-top:0;margin-bottom:0;padding-top:.4rem;padding-bottom:.85rem}.christianity-player-rack{grid-template-columns:minmax(4.5rem,5.7rem) minmax(4.4rem,1fr) minmax(3.5rem,4.8rem)}.christianity-shared-zone{gap:.45rem;grid-template-columns:repeat(3,minmax(0,1fr))}.christianity-zone-card,.christianity-zone-pile{min-height:6.15rem;padding:.58rem .46rem .5rem;gap:.24rem}.christianity-zone-pile i{top:2rem;right:.52rem;width:2.35rem;height:3.25rem}.christianity-offering-pile{min-height:6.85rem;padding:.88rem .46rem .55rem;gap:.24rem}.christianity-offering-pile i{top:2.25rem;left:.56rem;width:2.35rem;height:3.25rem}.christianity-card-preview-card{width:clamp(4.2rem,20vw,5.7rem);height:auto;min-height:0}.christianity-leader-card{width:clamp(4.55rem,20vw,5.7rem);min-height:0}.christianity-offering-row{grid-template-columns:minmax(4.5rem,5.5rem) minmax(0,1fr);gap:.5rem}.christianity-hand-fan--opponent{min-height:5.75rem;padding-bottom:.7rem}}\n"], dependencies: [{ kind: "directive", type: CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "directive", type: CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep", "cdkDropListElementContainer"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "directive", type: LightRippleDirective, selector: "[valLightRipple]" }] }); }
70075
- }
70076
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ChristianityGameComponent, decorators: [{
70077
- type: Component,
70078
- args: [{ selector: 'val-christianity-game', standalone: true, imports: [CdkDrag, CdkDropList, LightRippleDirective], template: `
70079
- <main class="christianity-shell">
70080
- <section class="christianity-header">
70081
- <div>
70082
- <p>{{ t('christianityEyebrow') }}</p>
70083
- <h1>{{ t('christianityTitle') }}</h1>
70084
- </div>
70085
- <div class="christianity-turn" [class.is-own-turn]="isOwnTurn()">
70086
- <span>{{ t('christianityTurn') }}</span>
70087
- <strong>{{ currentPlayer().displayName }}</strong>
70088
- </div>
70089
- </section>
70090
-
70091
- <section class="christianity-match-strip" [attr.aria-label]="t('christianityMatchScore')">
70092
- <article class="christianity-match-player">
70093
- <span class="christianity-avatar" [style.background]="player().avatarColor">{{ player().avatar }}</span>
70094
- <div>
70095
- <strong>{{ player().displayName }}</strong>
70096
- <small>{{ player().leaderName }} · {{ player().leaderHp }}/{{ player().leaderMaxHp }}</small>
70097
- </div>
70098
- </article>
70099
- <div class="christianity-scoreboard">
70100
- <span>{{ t('christianityMatch') }}</span>
70101
- <strong>{{ game().matchScore.P1 }}-{{ game().matchScore.P2 }}</strong>
70102
- </div>
70103
- <article class="christianity-match-player christianity-match-player--opponent">
70104
- <span class="christianity-avatar" [style.background]="opponent().avatarColor">{{ opponent().avatar }}</span>
70105
- <div>
70106
- <strong>{{ opponent().displayName }}</strong>
70107
- <small>{{ opponent().leaderName }} · {{ opponent().leaderHp }}/{{ opponent().leaderMaxHp }}</small>
70108
- </div>
70109
- </article>
70110
- </section>
70111
-
70112
- <section class="christianity-hand-shelf christianity-hand-shelf--opponent">
70113
- <div class="christianity-hand-meter christianity-hand-meter--opponent">
70114
- <span>{{ t('christianityHand') }}</span>
70115
- <strong>{{ opponentHandCount() }}</strong>
70116
- </div>
70117
- <section class="christianity-hand-fan christianity-hand-fan--opponent" [attr.aria-label]="t('christianityOpponentHand')">
70118
- @for (_ of hiddenHandCards(opponentHandCount()); track $index) {
70119
- <button
70120
- type="button"
70121
- class="christianity-card-preview-card christianity-card-frame christianity-card-frame--back"
70122
- valLightRipple
70123
- [style.transform]="fanTransform($index, opponentHandCount(), true)"
70124
- [attr.aria-label]="t('christianityHiddenCard')"
70125
- ></button>
70126
- }
70127
- </section>
70128
- </section>
70129
-
70130
- <section class="christianity-table" [attr.aria-label]="t('christianityTable')">
70131
- <section class="christianity-player-side christianity-player-side--opponent">
70132
- <section class="christianity-player-rack christianity-player-rack--opponent">
70133
- <div class="christianity-offerings-zone">
70134
- <button type="button" class="christianity-offering-pile" valLightRipple (click)="openOfferings('P2')">
70135
- <i aria-hidden="true"></i>
70136
- <i aria-hidden="true"></i>
70137
- <i aria-hidden="true"></i>
70138
- <span>{{ t('christianityOfferings') }}</span>
70139
- <strong>{{ readyOfferings(opponent()) }}/{{ totalOfferings(opponent()) }}</strong>
70140
- </button>
70141
- </div>
70142
- <button type="button" class="christianity-leader-card christianity-card-frame christianity-card-frame--leader" valLightRipple [class.is-target]="selectedAttacker() && !hasOpponentGuards()" (click)="handleOpponentLeader()">
70143
- <header class="christianity-card-frame-header">
70144
- <small>{{ t('christianityLeaderCard') }}</small>
70145
- <strong>{{ opponent().leaderName }}</strong>
70146
- <span>{{ opponent().leaderHp }}</span>
70147
- </header>
70148
- <section class="christianity-card-frame-art">
70149
- <span>{{ opponent().leaderName }}</span>
70150
- <small>{{ t('christianityLeaderCard') }}</small>
70151
- </section>
70152
- <section class="christianity-card-frame-effect">
70153
- <strong>{{ opponent().leaderHp }}/{{ opponent().leaderMaxHp }}</strong>
70154
- </section>
70155
- </button>
70156
- <span class="christianity-rack-spacer" aria-hidden="true"></span>
70157
- </section>
70158
-
70159
- <section class="christianity-battle-zone christianity-battle-zone--opponent" [attr.aria-label]="t('christianityOpponentBattle')">
70160
- @for (slot of battleSlots('P2'); track slot.trackId) {
70161
- @if (slot.card) {
70162
- <button
70163
- type="button"
70164
- class="christianity-card-preview-card christianity-card-preview-card--battle christianity-card-frame christianity-card-frame--battle"
70165
- valLightRipple
70166
- [class.is-target]="selectedAttacker()"
70167
- (click)="handleOpponentCharacter(slot.card)"
70168
- >
70169
- <header class="christianity-card-frame-header">
70170
- <small>{{ t('christianityCost') }} {{ cardDefinition(slot.card.cardId).cost }}</small>
70171
- <strong>{{ slot.card.name }}</strong>
70172
- <span>{{ cardDefinition(slot.card.cardId).cost }}</span>
70173
- </header>
70174
- <section class="christianity-card-frame-art">
70175
- <span>{{ slot.card.name }}</span>
70176
- <small>{{ t('christianityCharacterCard') }}</small>
70177
- </section>
70178
- <section class="christianity-card-frame-effect">
70179
- <strong>{{ slot.card.attack }} / {{ slot.card.currentHp }}</strong>
70180
- </section>
70181
- </button>
70182
- } @else {
70183
- <span class="christianity-slot"></span>
70184
- }
70185
- }
70186
- </section>
70187
- </section>
70188
-
70189
- <section class="christianity-shared-zone" [attr.aria-label]="t('christianitySharedZone')">
70190
- <button type="button" class="christianity-zone-pile christianity-zone-pile--history" valLightRipple (click)="openHistory()">
70191
- <i aria-hidden="true"></i>
70192
- <i aria-hidden="true"></i>
70193
- <i aria-hidden="true"></i>
70194
- <span>{{ t('christianityHistory') }}</span>
70195
- <strong>{{ game().historyZone.length }}</strong>
70196
- </button>
70197
- <button type="button" class="christianity-zone-pile christianity-zone-pile--deck" valLightRipple aria-live="polite" (click)="inspectDeck()">
70198
- <i aria-hidden="true"></i>
70199
- <i aria-hidden="true"></i>
70200
- <i aria-hidden="true"></i>
70201
- <span>{{ t('christianityDeck') }}</span>
70202
- <strong>{{ game().sharedDeck.length }}</strong>
70203
- </button>
70204
- <div class="christianity-zone-card">
70205
- <span>{{ t('christianityPlace') }}</span>
70206
- <strong>{{ t('christianityEmpty') }}</strong>
70207
- </div>
70208
- </section>
70209
-
70210
- <section class="christianity-player-side">
70211
- <section class="christianity-battle-zone" [class.is-placing-card]="canPlaceSelectedCharacter() || isDraggingCharacter()" [attr.aria-label]="t('christianityYourBattle')">
70212
- @for (slot of battleSlots('P1'); track slot.trackId) {
70213
- @if (slot.card) {
70214
- <button
70215
- type="button"
70216
- class="christianity-card-preview-card christianity-card-preview-card--battle christianity-card-frame christianity-card-frame--battle"
70217
- valLightRipple
70218
- [class.is-selected]="selectedAttacker()?.instanceId === slot.card.instanceId"
70219
- [class.is-exhausted]="!slot.card.canAttack"
70220
- (click)="selectAttacker(slot.card)"
70221
- >
70222
- <header class="christianity-card-frame-header">
70223
- <small>{{ t('christianityCost') }} {{ cardDefinition(slot.card.cardId).cost }}</small>
70224
- <strong>{{ slot.card.name }}</strong>
70225
- <span>{{ cardDefinition(slot.card.cardId).cost }}</span>
70226
- </header>
70227
- <section class="christianity-card-frame-art">
70228
- <span>{{ slot.card.name }}</span>
70229
- <small>{{ t('christianityCharacterCard') }}</small>
70230
- </section>
70231
- <section class="christianity-card-frame-effect">
70232
- <strong>{{ slot.card.attack }} / {{ slot.card.currentHp }}</strong>
70233
- </section>
70234
- </button>
70235
- } @else {
70236
- <button
70237
- type="button"
70238
- class="christianity-slot"
70239
- cdkDropList
70240
- [id]="battleSlotDropId($index)"
70241
- [cdkDropListData]="$index"
70242
- [cdkDropListConnectedTo]="['christianity-hand-source']"
70243
- [cdkDropListEnterPredicate]="canDropOnBattleSlot"
70244
- [class.christianity-slot--play-target]="canPlaceSelectedCharacter() || isDraggingCharacter()"
70245
- valLightRipple
70246
- (cdkDropListDropped)="dropOnBattleSlot($event, $index)"
70247
- (click)="playSelectedCard($index)"
70248
- >
70249
- @if (canPlaceSelectedCharacter() || isDraggingCharacter()) {
70250
- <span>{{ t('christianityPlayHere') }}</span>
70251
- }
70252
- </button>
70253
- }
70254
- }
70255
- </section>
70256
-
70257
- <section class="christianity-player-rack">
70258
- <div class="christianity-offerings-zone">
70259
- <button
70260
- type="button"
70261
- class="christianity-offering-pile"
70262
- cdkDropList
70263
- id="christianity-offerings-drop"
70264
- valLightRipple
70265
- [cdkDropListConnectedTo]="['christianity-hand-source']"
70266
- [class.is-play-target]="canPlaceSelectedOffering() || isDraggingOffering()"
70267
- [cdkDropListEnterPredicate]="canDropOnOfferings"
70268
- (cdkDropListDropped)="dropOnOfferings($event)"
70269
- (click)="handleOfferingPile('P1')"
70270
- >
70271
- <i aria-hidden="true"></i>
70272
- <i aria-hidden="true"></i>
70273
- <i aria-hidden="true"></i>
70274
- <span>{{ t('christianityOfferings') }}</span>
70275
- <strong>{{ readyOfferings(player()) }}/{{ totalOfferings(player()) }}</strong>
70276
- </button>
70277
- </div>
70278
- <button type="button" class="christianity-leader-card christianity-card-frame christianity-card-frame--leader" valLightRipple (click)="inspectLeader('P1')">
70279
- <header class="christianity-card-frame-header">
70280
- <small>{{ t('christianityLeaderCard') }}</small>
70281
- <strong>{{ player().leaderName }}</strong>
70282
- <span>{{ player().leaderHp }}</span>
70283
- </header>
70284
- <section class="christianity-card-frame-art">
70285
- <span>{{ player().leaderName }}</span>
70286
- <small>{{ t('christianityLeaderCard') }}</small>
70287
- </section>
70288
- <section class="christianity-card-frame-effect">
70289
- <strong>{{ player().leaderHp }}/{{ player().leaderMaxHp }}</strong>
70290
- </section>
70291
- </button>
70292
- <div class="christianity-player-command">
70293
- <div class="christianity-player-badge">
70294
- <span class="christianity-avatar" [style.background]="player().avatarColor">{{ player().avatar }}</span>
70295
- <strong>{{ player().displayName }}</strong>
70296
- </div>
70297
- <button
70298
- type="button"
70299
- class="christianity-end-turn"
70300
- (click)="endTurn()"
70301
- >
70302
- {{ t('christianityEndTurn') }}
70303
- </button>
70304
- </div>
70305
- </section>
70306
- </section>
70307
- </section>
70308
-
70309
- <section class="christianity-hand-shelf">
70310
- <div class="christianity-hand-meter">
70311
- <span>{{ t('christianityHand') }}</span>
70312
- <strong>{{ player().hand?.length ?? 0 }}</strong>
70313
- </div>
70314
- <section
70315
- class="christianity-hand-fan"
70316
- cdkDropList
70317
- id="christianity-hand-source"
70318
- [cdkDropListConnectedTo]="dropTargetIds()"
70319
- [attr.aria-label]="t('christianityYourHand')"
70320
- (pointerleave)="clearHoveredHandIndex()"
70321
- >
70322
- @for (cardId of player().hand ?? []; track cardId + $index) {
70323
- @let card = cardDefinition(cardId);
70324
- <div
70325
- class="christianity-hand-card-wrap"
70326
- [class.is-selected]="selectedHandCard() === cardId"
70327
- [class.is-dragging]="draggingCardId() === cardId"
70328
- [style.z-index]="handCardZIndex($index)"
70329
- [style.transform]="fanTransform($index, player().hand?.length ?? 0, false)"
70330
- (pointerenter)="setHoveredHandIndex($index)"
70331
- (pointerdown)="setHoveredHandIndex($index)"
70332
- (pointerup)="releaseHoveredHand($event)"
70333
- >
70334
- <button
70335
- type="button"
70336
- class="christianity-card-preview-card christianity-card-preview-card--hand christianity-card-frame"
70337
- cdkDrag
70338
- valLightRipple
70339
- [cdkDragData]="cardId"
70340
- [cdkDragDisabled]="!canPlay(card)"
70341
- [class.is-selected]="selectedHandCard() === cardId"
70342
- [class.is-disabled]="!canPlay(card)"
70343
- (cdkDragStarted)="startDraggingCard(cardId)"
70344
- (cdkDragEnded)="endDraggingCard()"
70345
- (click)="selectHandCard(cardId)"
70346
- >
70347
- <header class="christianity-card-frame-header">
70348
- <small>{{ card.type === 'offering' ? t('christianityOfferingCard') : t('christianityCost') + ' ' + card.cost }}</small>
70349
- <strong>{{ card.name }}</strong>
70350
- <span>{{ card.type === 'offering' ? '+' + card.life : card.cost }}</span>
70351
- </header>
70352
- <section class="christianity-card-frame-art">
70353
- <span>{{ card.name }}</span>
70354
- <small>{{ cardTypeLabel(card) }}</small>
70355
- </section>
70356
- <section class="christianity-card-frame-effect">
70357
- <strong>
70358
- @if (card.type === 'offering') {
70359
- +{{ card.life }}
70360
- } @else {
70361
- {{ card.attack }} / {{ card.life }}
70362
- }
70363
- </strong>
70364
- </section>
70365
- <footer class="christianity-card-frame-footer">
70366
- <span>{{ card.edition ?? 'MVP' }}</span>
70367
- <span>{{ card.collectorNumber ?? card.id }}</span>
70368
- </footer>
70369
- </button>
70370
- <button
70371
- type="button"
70372
- class="christianity-card-eye"
70373
- [attr.aria-label]="t('christianityPreviewCard')"
70374
- (click)="inspectHandCard(cardId, true); $event.stopPropagation()"
70375
- ></button>
70376
- </div>
70377
- }
70378
- </section>
70379
- </section>
70380
-
70381
- @if (selectedPreview()) {
70382
- <button type="button" class="christianity-preview-backdrop" [attr.aria-label]="t('christianityClosePreview')" (click)="closePreview()"></button>
70383
- <aside
70384
- class="christianity-floating-card-shell"
70385
- aria-live="polite"
70386
- >
70387
- <button type="button" class="christianity-floating-card-close" (click)="closePreview()">
70388
- {{ t('close') }}
70389
- </button>
70390
- <div
70391
- class="christianity-floating-card"
70392
- [style.--preview-rotate-x]="previewTilt().rotateX + 'deg'"
70393
- [style.--preview-rotate-y]="previewTilt().rotateY + 'deg'"
70394
- [style.--preview-shift-x]="previewTilt().shiftX + 'px'"
70395
- [style.--preview-shift-y]="previewTilt().shiftY + 'px'"
70396
- (pointermove)="tiltPreview($event)"
70397
- (pointerleave)="resetPreviewTilt()"
70398
- >
70399
- @if (selectedPreviewCard(); as previewCard) {
70400
- <header class="christianity-full-card-header">
70401
- <span class="christianity-full-card-type-icon" aria-hidden="true"></span>
70402
- <strong>{{ previewCard.name }}</strong>
70403
- <span class="christianity-full-card-cost">{{ previewCard.type === 'offering' ? '+' + previewCard.life : previewCard.cost }}</span>
70404
- </header>
70405
- <section class="christianity-full-card-art" [class.has-image]="previewCard.imageUrl">
70406
- @if (previewCard.imageUrl) {
70407
- <img [src]="previewCard.imageUrl" [alt]="previewCard.name" />
70408
- } @else {
70409
- <span>{{ previewCard.name }}</span>
70410
- }
70411
- <small>{{ cardTypeLabel(previewCard) }}</small>
70412
- </section>
70413
- <section class="christianity-full-card-verse">
70414
- <p>{{ previewCard.verseText ?? selectedPreview()?.body }}</p>
70415
- @if (previewCard.scripture) {
70416
- <strong>{{ previewCard.scripture }}</strong>
70417
- }
70418
- </section>
70419
- <section class="christianity-full-card-effect">
70420
- <div class="christianity-full-card-stats">
70421
- @if (previewCard.type === 'character') {
70422
- <strong>{{ previewCard.attack }}</strong>
70423
- <strong>{{ previewCard.life }}</strong>
70424
- } @else {
70425
- <strong>+{{ previewCard.life }}</strong>
70426
- }
70427
- </div>
70428
- <div>
70429
- @if (previewCard.abilityName) {
70430
- <strong>{{ previewCard.abilityName }}</strong>
70431
- }
70432
- <p>{{ previewCard.abilityText ?? selectedPreview()?.body }}</p>
70433
- </div>
70434
- <span
70435
- class="christianity-full-card-rarity"
70436
- [class.is-normal]="!previewCard.rarity || previewCard.rarity === 'normal'"
70437
- [class.is-uncommon]="previewCard.rarity === 'uncommon'"
70438
- [class.is-rare]="previewCard.rarity === 'rare'"
70439
- [class.is-legendary]="previewCard.rarity === 'legendary'"
70440
- aria-hidden="true"
70441
- ></span>
70442
- </section>
70443
- <footer class="christianity-full-card-footer">
70444
- <span>{{ previewCard.edition ?? 'MVP' }}</span>
70445
- <span>{{ previewCard.collectorNumber ?? previewCard.id }}</span>
70446
- <span>{{ previewCard.year ?? '2026' }} CHRISTIANITY</span>
70447
- <span>{{ previewCard.author ?? 'MVP' }}</span>
70448
- </footer>
70449
- } @else {
70450
- <small>{{ selectedPreview()?.eyebrow }}</small>
70451
- <strong>{{ selectedPreview()?.title }}</strong>
70452
- <span>{{ selectedPreview()?.meta }}</span>
70453
- <p>{{ selectedPreview()?.body }}</p>
70454
- }
70455
- </div>
70456
- @if (selectedPreview()?.source === 'hand') {
70457
- <div class="christianity-floating-card-actions">
70458
- <button type="button" [disabled]="previewActionDisabled()" (click)="playPreviewCard()">
70459
- {{ selectedActionLabel() }}
70460
- </button>
70461
- </div>
70462
- }
70463
- </aside>
70464
- }
70465
-
70466
- @if (selectedInfo(); as info) {
70467
- <button type="button" class="christianity-info-backdrop" [attr.aria-label]="t('close')" (click)="closeInfo()"></button>
70468
- <aside class="christianity-info-panel" aria-live="polite">
70469
- <button type="button" class="christianity-dialog-close christianity-info-close" (click)="closeInfo()">
70470
- {{ t('close') }}
70471
- </button>
70472
- <div class="christianity-rule-note">
70473
- <span class="christianity-rule-note-icon" aria-hidden="true">i</span>
70474
- <div>
70475
- <small>{{ info.eyebrow }}</small>
70476
- <h2>{{ info.title }}</h2>
70477
- <strong>{{ info.meta }}</strong>
70478
- <p>{{ info.body }}</p>
70479
- <ul>
70480
- @for (fact of info.facts; track fact) {
70481
- <li>{{ fact }}</li>
70482
- }
70483
- </ul>
70484
- </div>
70485
- </div>
70486
- </aside>
70487
- }
70488
-
70489
- <section class="christianity-actions" aria-live="polite">
70490
- <p>{{ statusText() }}</p>
70491
- <div>
70492
- <button type="button" [disabled]="selectedActionDisabled()" (click)="playSelectedCard()">
70493
- {{ selectedActionLabel() }}
70494
- </button>
70495
- <button type="button" (click)="resetMock()">
70496
- {{ t('christianityReset') }}
70497
- </button>
70498
- </div>
70499
- </section>
70500
-
70501
- @if (showHistory()) {
70502
- <button type="button" class="christianity-history-backdrop" [attr.aria-label]="t('christianityCloseHistory')" (click)="showHistory.set(false)"></button>
70503
- <section class="christianity-history-drawer">
70504
- <header>
70505
- <h2>{{ t('christianityHistory') }}</h2>
70506
- <div class="christianity-dialog-actions">
70507
- <span>{{ game().historyZone.length }}</span>
70508
- <button type="button" class="christianity-dialog-close" (click)="showHistory.set(false)">
70509
- {{ t('close') }}
70510
- </button>
70511
- </div>
70512
- </header>
70513
- @if (game().historyZone.length) {
70514
- <div class="christianity-history-grid">
70515
- @for (cardId of game().historyZone; track cardId + $index) {
70516
- @let card = cardDefinition(cardId);
70517
- <button type="button" class="christianity-card-preview-card christianity-card-frame christianity-card-frame--list" valLightRipple (click)="inspectHistoryCard(cardId)">
70518
- <header class="christianity-card-frame-header">
70519
- <small>{{ card.type === 'offering' ? t('christianityOfferingCard') : t('christianityCost') + ' ' + card.cost }}</small>
70520
- <strong>{{ card.name }}</strong>
70521
- <span>{{ card.type === 'offering' ? '+' + card.life : card.cost }}</span>
70522
- </header>
70523
- <section class="christianity-card-frame-art">
70524
- <span>{{ card.name }}</span>
70525
- <small>{{ cardTypeLabel(card) }}</small>
70526
- </section>
70527
- <section class="christianity-card-frame-effect">
70528
- <strong>
70529
- @if (card.type === 'offering') {
70530
- +{{ card.life }}
70531
- } @else {
70532
- {{ card.attack }} / {{ card.life }}
70533
- }
70534
- </strong>
70535
- </section>
70536
- </button>
70537
- }
70538
- </div>
70539
- } @else {
70540
- <p>{{ t('christianityHistoryEmpty') }}</p>
70541
- }
70542
- </section>
70543
- }
70544
-
70545
- @if (offeringsSeat()) {
70546
- @let offeringPlayer = game().players[offeringsSeat()!];
70547
- <button type="button" class="christianity-history-backdrop" [attr.aria-label]="t('christianityCloseOfferings')" (click)="closeOfferings()"></button>
70548
- <section class="christianity-history-drawer christianity-offerings-drawer">
70549
- <header>
70550
- <h2>{{ t('christianityOfferings') }}</h2>
70551
- <div class="christianity-dialog-actions">
70552
- <span>{{ readyOfferings(offeringPlayer) }}/{{ totalOfferings(offeringPlayer) }}</span>
70553
- <button type="button" class="christianity-dialog-close" (click)="closeOfferings()">
70554
- {{ t('close') }}
70555
- </button>
70556
- </div>
70557
- </header>
70558
- <div class="christianity-offering-list">
70559
- @for (offering of offeringPlayer.offerings; track offering.instanceId) {
70560
- <article class="christianity-offering-row" [class.is-exhausted]="!offering.ready">
70561
- <button type="button" class="christianity-offering-card christianity-card-frame christianity-card-frame--list" valLightRipple (click)="inspectOffering(offering)">
70562
- <header class="christianity-card-frame-header">
70563
- <small>{{ t('christianityOfferingCard') }}</small>
70564
- <strong>{{ offering.name }}</strong>
70565
- <span>+{{ offering.value }}</span>
70566
- </header>
70567
- <section class="christianity-card-frame-art">
70568
- <span>{{ offering.name }}</span>
70569
- <small>{{ t('christianityOfferingCard') }}</small>
70570
- </section>
70571
- <section class="christianity-card-frame-effect">
70572
- <strong>+{{ offering.value }}</strong>
70573
- @if (offering.abilityName) {
70574
- <p>{{ offering.abilityName }}</p>
70575
- }
70576
- </section>
70577
- </button>
70578
- <div>
70579
- <strong>{{ offering.ready ? t('christianityOfferingReady') : t('christianityOfferingExhausted') }}</strong>
70580
- <p>{{ offering.abilityText || t('christianityOfferingNoAbility') }}</p>
70581
- @if (offering.abilityName) {
70582
- <button
70583
- type="button"
70584
- [disabled]="!canUseOfferingAbility(offering, offeringsSeat()!)"
70585
- (click)="useOfferingAbility(offering, offeringsSeat()!)"
70586
- >
70587
- {{ t('christianityUseAbility') }}
70588
- </button>
70589
- }
70590
- </div>
70591
- </article>
70592
- }
70593
- </div>
70594
- </section>
70595
- }
70596
- </main>
70597
- `, styles: [":host{--christianity-theme-ink: var(--val-text-color, #1f2933);--christianity-theme-surface: #ffffff;--christianity-theme-parchment: #fffaf0;--christianity-theme-olive: #5f6f2a;--christianity-theme-gold: #d6a21d;--christianity-theme-gold-soft: rgba(214, 162, 29, .18);--christianity-theme-gold-ring: rgba(214, 162, 29, .48);--christianity-theme-glow: rgba(245, 199, 85, .32);--christianity-theme-focus: #2563eb;--christianity-theme-shadow: rgba(82, 64, 28, .18);--christianity-theme-shadow-strong: rgba(82, 64, 28, .3);--christianity-card-aspect: 5 / 7.45;display:block;max-width:100%;min-width:0;overflow-x:clip;color:var(--christianity-theme-ink)}.christianity-shell{box-sizing:border-box;display:grid;gap:.65rem;width:100%;max-width:100%;min-width:0;padding:.75rem .25rem;border:1px solid rgba(36,48,68,.12);border-radius:.75rem;background:#f6f8fb;overflow-x:clip;overflow-y:visible}.christianity-header,.christianity-match-strip,.christianity-player__summary,.christianity-shared-zone,.christianity-actions{display:flex;align-items:center;justify-content:space-between;gap:.75rem}.christianity-header h1,.christianity-header p,.christianity-match-player strong,.christianity-match-player small,.christianity-scoreboard span,.christianity-history h2,.christianity-actions p{margin:0}.christianity-header h1{font-size:1.35rem;line-height:1.1}.christianity-header p,.christianity-turn span,.christianity-offerings span,.christianity-hidden-hand span,.christianity-deck span,.christianity-place span,.christianity-pile span,.christianity-leader span{color:#1f2933a3;font-size:.75rem}.christianity-turn,.christianity-leader,.christianity-offerings,.christianity-hidden-hand,.christianity-pile,.christianity-deck,.christianity-place{display:grid;gap:.15rem;min-width:5.25rem;padding:.55rem .65rem;border:1px solid rgba(36,48,68,.12);border-radius:.5rem;background:#fff}.christianity-turn.is-own-turn{border-color:#12806c59;background:#ecfdf5}.christianity-match-strip{display:grid;grid-template-columns:minmax(0,1fr) auto minmax(0,1fr);padding:.45rem;border:1px solid rgba(36,48,68,.1);border-radius:.75rem;background:#fff}.christianity-match-player{display:grid;grid-template-columns:auto minmax(0,1fr);gap:.5rem;align-items:center;min-width:0}.christianity-match-player--opponent{direction:rtl}.christianity-match-player--opponent div{direction:ltr;text-align:right}.christianity-match-player div{display:grid;min-width:0}.christianity-match-player strong,.christianity-match-player small{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.christianity-match-player small,.christianity-scoreboard span{color:#1f293394;font-size:.72rem}.christianity-scoreboard{display:grid;justify-items:center;min-width:4.2rem;padding:0 .55rem;border-right:1px solid rgba(36,48,68,.1);border-left:1px solid rgba(36,48,68,.1)}.christianity-scoreboard strong{font-size:1.2rem;line-height:1}.christianity-table{box-sizing:border-box;display:grid;gap:.45rem;width:100%;max-width:100%;min-width:0;padding:.45rem .35rem;border-radius:.75rem;background:#dceafb;overflow-x:clip;overflow-y:visible}.christianity-player-side{box-sizing:border-box;display:grid;gap:.35rem;width:100%;max-width:100%;min-width:0;padding:.35rem .3rem;border-radius:.7rem;background:#ffffff57;grid-template-rows:minmax(7rem,1fr) auto;min-height:13.75rem}.christianity-player-side--opponent{grid-template-rows:auto minmax(7rem,1fr)}.christianity-player{display:grid;gap:.65rem}.christianity-battle-zone{--christianity-battle-card-width: clamp(4.8rem, 15vw, 6.6rem);box-sizing:border-box;display:grid;grid-template-columns:repeat(4,var(--christianity-battle-card-width));gap:.5rem;align-items:center;justify-content:center;width:100%;max-width:100%;min-width:0;min-height:clamp(9.1rem,29vw,11rem);padding:.55rem .4rem;border-radius:.75rem;background:#ffffffc2;transition:background .16s ease,box-shadow .16s ease}.christianity-battle-zone.is-placing-card{background:linear-gradient(180deg,#fffaf0f5,#ffffffd6),#ffffffc2;box-shadow:inset 0 0 0 .14rem var(--christianity-theme-gold-soft),0 .8rem 1.7rem #5f6f2a1f}.christianity-shared-zone{padding:.55rem .4rem;border-radius:.75rem;background:#ffffffe6}.christianity-card,.christianity-end-turn,.christianity-actions button,.christianity-pile,.christianity-leader--target{border:1px solid rgba(36,48,68,.16);border-radius:.5rem;background:#fff;color:inherit;font:inherit}.christianity-card{display:grid;align-content:space-between;min-height:5.8rem;padding:.5rem;text-align:left;box-shadow:0 .5rem 1.25rem #24304414}.christianity-card span{font-weight:700}.christianity-card strong{justify-self:end;padding:.15rem .35rem;border-radius:999px;background:#edf2f7;font-size:.8rem}.christianity-card.is-selected{border-color:var(--christianity-theme-gold);box-shadow:0 0 0 .18rem var(--christianity-theme-gold-soft),0 .85rem 1.4rem var(--christianity-theme-shadow)}.christianity-card.is-disabled,.christianity-card.is-exhausted{opacity:.55}.christianity-card.is-target{border-color:#dc2626}.christianity-offering-cards{display:grid;grid-auto-flow:column;grid-auto-columns:.7rem;gap:.16rem;align-items:end;min-height:1.05rem}.christianity-offering-cards i{display:block;width:.65rem;height:.95rem;border:1px solid rgba(16,42,67,.22);border-radius:.18rem;background:#f8fafc}.christianity-offering-cards i.is-used{background:#cbd5e1;transform:rotate(90deg);transform-origin:center}.christianity-slot{display:grid;place-items:center;justify-self:center;width:var(--christianity-battle-card-width);height:auto;min-height:0;aspect-ratio:var(--christianity-card-aspect);border:1px dashed rgba(36,48,68,.22);border-radius:.5rem;background:#ffffff73;color:inherit;font:inherit}.christianity-slot--play-target{position:relative;border-color:var(--christianity-theme-gold-ring);background:linear-gradient(180deg,#fffaf0eb,#f8fafcd1),#ffffffb3;color:#5d4305;font-weight:800;overflow:hidden;box-shadow:inset 0 0 0 .12rem #d6a21d33,0 .7rem 1.25rem var(--christianity-theme-shadow);animation:christianity-target-pulse 1.45s ease-in-out infinite}.christianity-slot--play-target:before{content:\"\";position:absolute;inset:.35rem;border:1px solid rgba(214,162,29,.22);border-radius:.4rem;background:linear-gradient(135deg,rgba(214,162,29,.1),transparent 46%),radial-gradient(circle at 50% 42%,var(--christianity-theme-glow),transparent 58%)}.christianity-slot--play-target span{position:relative;z-index:2;padding:.16rem .44rem;border-radius:999px;background:#ffffffc7;font-size:.78rem}@keyframes christianity-target-pulse{0%,to{box-shadow:inset 0 0 0 .12rem #d6a21d33,0 .7rem 1.25rem var(--christianity-theme-shadow)}50%{box-shadow:inset 0 0 0 .16rem #d6a21d57,0 .9rem 1.65rem var(--christianity-theme-shadow-strong)}}.christianity-hand{display:grid;grid-auto-columns:minmax(6rem,8rem);grid-auto-flow:column;gap:.55rem;overflow-x:auto;padding-bottom:.25rem}.christianity-actions{align-items:flex-start;padding:.75rem;border-radius:.75rem;background:#fff}.christianity-actions div{display:flex;flex-wrap:wrap;gap:.5rem;justify-content:flex-end}.christianity-actions button,.christianity-end-turn{min-height:2.4rem;padding:0 .75rem;font-weight:700}.christianity-actions button:not(:disabled),.christianity-end-turn{background:#102a43;color:#fff}.christianity-history{padding:.75rem;border-radius:.75rem;background:#fff}.christianity-hand-fan{position:relative;display:flex;justify-content:center;min-height:10.8rem;padding:.25rem .25rem 2.1rem;isolation:isolate;overflow:visible}.christianity-hand-shelf{position:relative;display:grid;z-index:12;min-height:12rem;margin-top:-1.15rem;padding:1.45rem .25rem 1rem;overflow:visible}.christianity-hand-shelf--opponent{z-index:8;min-height:6.85rem;margin-top:0;margin-bottom:0;padding:.45rem .25rem .85rem}.christianity-hand-fan--opponent{min-height:5.9rem;padding-bottom:.75rem;align-items:start}.christianity-card-preview-card,.christianity-card-mini,.christianity-offering-pile,.christianity-offering-card,.christianity-leader-card,.christianity-zone-card,.christianity-zone-pile,.christianity-end-turn{border:1px solid rgba(36,48,68,.16);border-radius:.5rem;background:#fff;color:inherit;font:inherit}.christianity-card-preview-card{display:grid;grid-template-rows:auto minmax(0,1fr) auto auto;gap:.28rem;align-content:stretch;width:clamp(4.9rem,17vw,7.1rem);height:auto;min-height:0;aspect-ratio:var(--christianity-card-aspect);padding:.48rem;text-align:left;transform-origin:50% 115%;transition:transform .16s ease,box-shadow .16s ease,border-color .16s ease;box-shadow:0 .5rem 1.25rem #2430441a}.christianity-card-frame{position:relative;display:grid;grid-template-rows:auto minmax(0,1fr) auto auto;gap:.28rem;align-content:stretch;overflow:hidden;padding:.48rem;text-align:left;background:linear-gradient(180deg,#fffffffa,#f8fafcfa),radial-gradient(circle at 15% 0%,rgba(214,162,29,.12),transparent 44%);box-shadow:0 .5rem 1.25rem #2430441a,inset 0 0 0 .18rem #ffffff9e}.christianity-card-frame-header{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:.16rem;align-items:start;min-width:0}.christianity-card-frame-header small{grid-column:1;min-width:0;overflow:hidden;color:#1f2933a3;font-size:clamp(.52rem,1.5vw,.68rem);line-height:1;text-overflow:ellipsis;white-space:nowrap}.christianity-card-frame-header strong{grid-column:1;justify-self:start;align-self:start;min-width:0;padding:0;overflow:hidden;border-radius:0;background:transparent;font-size:clamp(.82rem,2.5vw,1.05rem);line-height:1.02;text-overflow:ellipsis;white-space:nowrap}.christianity-card-frame-header span{grid-column:2;grid-row:1 / span 2;display:grid;place-items:center;min-width:1.3rem;height:1.3rem;padding:0 .22rem;border-radius:999px;background:#ffd91a;color:#243044;font-size:.8rem;font-weight:900;line-height:1;box-shadow:inset 0 -.08rem #52401c2e}.christianity-card-frame-art{position:relative;display:grid;place-items:center;min-height:0;overflow:hidden;border-radius:.36rem;background:linear-gradient(135deg,#5f6f2a2e,#d6a21d24),radial-gradient(circle at 50% 18%,rgba(255,255,255,.72),transparent 48%),#dbe7ef;box-shadow:inset 0 0 0 1px #24304414}.christianity-card-frame-art>span{max-width:78%;overflow:hidden;color:#2430447a;font-size:clamp(.82rem,2.2vw,1.05rem);font-weight:900;line-height:1.02;text-align:center;text-overflow:ellipsis}.christianity-card-frame-art small{position:absolute;right:0;bottom:.28rem;max-width:78%;padding:.1rem .34rem;overflow:hidden;border-radius:999px 0 0 999px;background:#ffffffe6;color:#1f2933a8;font-size:.48rem;font-style:italic;font-weight:900;line-height:1;text-overflow:ellipsis;text-transform:uppercase;white-space:nowrap}.christianity-card-frame-effect{display:grid;align-content:center;gap:.1rem;min-height:1.45rem;padding:.24rem;overflow:hidden;border-radius:.34rem;background:radial-gradient(circle at 50% 70%,rgba(36,48,68,.06),transparent 44%),#ffffffdb}.christianity-card-frame-effect strong{justify-self:end;align-self:end;padding:.12rem .32rem;border-radius:999px;background:#edf2f7;font-size:clamp(.66rem,2vw,.82rem);line-height:1.05}.christianity-card-frame-effect p{margin:0;overflow:hidden;color:#1f2933b8;font-size:.58rem;line-height:1.1;text-overflow:ellipsis;white-space:nowrap}.christianity-card-frame-footer{display:flex;justify-content:space-between;gap:.22rem;color:#1f293385;font-size:.46rem;font-weight:800;line-height:1}.christianity-card-frame--battle{gap:.22rem;padding:.42rem}.christianity-card-frame--battle .christianity-card-frame-art{min-height:2.6rem}.christianity-card-frame--leader .christianity-card-frame-art{background:linear-gradient(135deg,#2563eb24,#d6a21d29),radial-gradient(circle at 50% 18%,rgba(255,255,255,.78),transparent 48%),#e7eef8}.christianity-card-frame--list{width:clamp(4.4rem,22vw,5.8rem);padding:.38rem}.christianity-card-frame--list .christianity-card-frame-art{min-height:2.5rem}.christianity-hand-card-wrap{position:relative;display:grid;justify-items:center;flex:0 0 auto;margin-inline:-.42rem;padding-bottom:2rem;transform-origin:50% 115%;transition:transform .16s ease,filter .16s ease}.christianity-hand-card-wrap:hover,.christianity-hand-card-wrap.is-selected,.christianity-hand-card-wrap.is-dragging{z-index:3}.christianity-hand-card-wrap:hover .christianity-card-preview-card--hand,.christianity-hand-card-wrap.is-selected .christianity-card-preview-card--hand,.christianity-hand-card-wrap.is-dragging .christianity-card-preview-card--hand{border-color:var(--christianity-theme-gold);box-shadow:0 0 0 .12rem var(--christianity-theme-gold-soft),0 1rem 2rem var(--christianity-theme-shadow)}.christianity-card-preview-card--hand{touch-action:none}.christianity-card-preview-card--hand.cdk-drag-disabled{cursor:not-allowed}.christianity-card-preview-card.cdk-drag-preview{width:clamp(4.9rem,17vw,7.1rem);height:auto;min-height:0;aspect-ratio:var(--christianity-card-aspect);border:1px solid var(--christianity-theme-gold-ring);box-shadow:0 0 0 .16rem #fff4c2ad,0 1.5rem 3rem var(--christianity-theme-shadow-strong);transform:rotate(2deg) scale(1.03)}.christianity-card-preview-card.cdk-drag-placeholder{width:clamp(4.9rem,17vw,7.1rem);height:auto;min-height:0;aspect-ratio:var(--christianity-card-aspect);opacity:.22}.christianity-slot.cdk-drop-list-dragging,.christianity-offering-pile.cdk-drop-list-dragging{border-color:var(--christianity-theme-gold-ring)}.christianity-slot.cdk-drop-list-receiving,.christianity-offering-pile.cdk-drop-list-receiving{box-shadow:inset 0 0 0 .18rem #d6a21d57,0 1rem 1.9rem var(--christianity-theme-shadow-strong)}.christianity-card-eye{position:absolute;right:50%;bottom:.38rem;width:2.15rem;height:1.55rem;border:1px solid color-mix(in srgb,var(--christianity-theme-focus) 52%,transparent);border-radius:999px;background:#fffffff0;box-shadow:0 .55rem 1.1rem #102a4324;opacity:0;transform:translate(50%,-.2rem) scale(.92);transition:opacity .14s ease,transform .14s ease,border-color .14s ease}.christianity-card-eye:before{content:\"\";position:absolute;top:50%;left:50%;width:1.1rem;height:1.1rem;border:.12rem solid var(--christianity-theme-focus);border-radius:82% 0;background:#fffffff0;transform:translate(-50%,-50%) rotate(45deg)}.christianity-card-eye:after{content:\"\";position:absolute;top:50%;left:50%;width:.42rem;height:.42rem;border:.09rem solid rgba(255,255,255,.95);border-radius:999px;background:radial-gradient(circle at 35% 32%,#ffffff 0 .06rem,transparent .07rem),var(--christianity-theme-focus);transform:translate(-50%,-50%)}.christianity-hand-card-wrap:hover .christianity-card-eye,.christianity-hand-card-wrap.is-selected .christianity-card-eye,.christianity-card-eye:focus-visible{opacity:1;transform:translate(50%) scale(1)}.christianity-offering-pile.is-play-target{border-color:var(--christianity-theme-gold-ring);background:linear-gradient(180deg,#fffaf0f5,#fffffff0),radial-gradient(circle at 82% 14%,rgba(250,204,21,.28) 0 .7rem,transparent .72rem);box-shadow:inset 0 0 0 .12rem #d6a21d3d,0 .8rem 1.55rem var(--christianity-theme-shadow);animation:christianity-target-pulse 1.45s ease-in-out infinite}.christianity-card-preview-card--back{width:clamp(4rem,14vw,5.7rem);min-height:0;aspect-ratio:var(--christianity-card-aspect);place-items:center;padding:.55rem;box-shadow:0 .8rem 1.55rem #24304424;transform-origin:50% -18%;background:linear-gradient(135deg,#102a431f,#102a4305),repeating-linear-gradient(45deg,#dbeafe 0 .33rem,#fff .33rem .66rem)}.christianity-card-preview-card--battle{justify-self:center;width:var(--christianity-battle-card-width);min-width:0;height:auto;min-height:0;aspect-ratio:var(--christianity-card-aspect);margin-inline:0}.christianity-card-preview-card>span,.christianity-card-mini>span,.christianity-offering-pile>span,.christianity-offering-card>span,.christianity-leader-card>span,.christianity-zone-card>span,.christianity-zone-pile>span{position:relative;z-index:2;align-self:start;font-weight:700;line-height:1.05}.christianity-card-preview-card>strong,.christianity-card-mini>strong,.christianity-offering-pile>strong,.christianity-offering-card>strong,.christianity-leader-card>strong,.christianity-zone-card>strong,.christianity-zone-pile>strong{position:relative;z-index:3;justify-self:end;align-self:end;padding:.15rem .35rem;border-radius:999px;background:#edf2f7;font-size:.8rem}.christianity-player-rack{box-sizing:border-box;display:grid;grid-template-columns:minmax(5.9rem,7rem) minmax(5rem,1fr) minmax(4.2rem,7rem);gap:.45rem;align-items:end;justify-items:stretch;width:100%;max-width:100%;min-width:0}.christianity-player-rack--opponent{align-items:start}.christianity-hand-meter{position:absolute;top:0;right:.35rem;z-index:4;display:inline-grid;grid-auto-flow:column;gap:.25rem;align-items:center;min-height:1.7rem;padding:.18rem .46rem;border:1px solid rgba(36,48,68,.12);border-radius:999px;background:#ffffffe6;box-shadow:0 .35rem .8rem #102a4314}.christianity-hand-meter--opponent{top:.15rem}.christianity-hand-meter span{color:#1f293394;font-size:.68rem}.christianity-hand-meter strong{font-size:.86rem}.christianity-player-badge,.christianity-player-command{display:grid;gap:.35rem;justify-items:center;min-width:0}.christianity-player-badge{align-content:start;color:#1f2933c2;font-size:.74rem}.christianity-player-badge--opponent{justify-self:center;grid-auto-flow:column;align-items:center;justify-content:center}.christianity-player-badge strong{max-width:6.5rem;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.christianity-avatar{display:grid;place-items:center;width:1.85rem;height:1.85rem;border-radius:999px;color:#fff;font-size:.76rem;font-weight:800;box-shadow:0 .35rem .9rem #102a4329}.christianity-offerings-zone{display:flex;flex-wrap:wrap;gap:.25rem;justify-content:flex-start;justify-self:start;width:100%}.christianity-card-mini,.christianity-offering-pile,.christianity-offering-card,.christianity-leader-card,.christianity-zone-card,.christianity-zone-pile{display:grid;align-content:space-between;min-height:4.9rem;padding:.48rem;text-align:left}.christianity-card-frame{display:grid;grid-template-rows:auto minmax(0,1fr) auto auto;align-content:stretch}.christianity-offering-pile,.christianity-zone-card,.christianity-zone-pile{grid-template-rows:auto minmax(2.6rem,1fr) auto;align-content:stretch;gap:.32rem}.christianity-card-mini{width:3.5rem}.christianity-offering-pile{position:relative;isolation:isolate;overflow:hidden;justify-self:start;width:min(100%,5.9rem);min-height:7.1rem;padding:.95rem .52rem .6rem;background:linear-gradient(180deg,#fff,#f8fafc),linear-gradient(135deg,rgba(250,204,21,.18),transparent 42%)}.christianity-offering-pile i{position:absolute;top:2.45rem;left:.72rem;z-index:-1;width:2.55rem;height:3.55rem;border:1px solid rgba(16,42,67,.18);border-radius:.35rem;background:linear-gradient(180deg,#ffffffeb,#f1f5f9eb),radial-gradient(circle at 78% 18%,#facc15 0 .38rem,transparent .4rem);box-shadow:0 .35rem .85rem #102a431a;transform:rotate(-5deg)}.christianity-offering-pile i:nth-child(2){transform:translate(.28rem,.08rem) rotate(3deg)}.christianity-offering-pile i:nth-child(3){transform:translate(.55rem,.18rem) rotate(-1deg)}.christianity-leader-card{align-self:center;justify-self:center;width:clamp(4.75rem,17vw,6rem);min-height:0;aspect-ratio:var(--christianity-card-aspect)}.christianity-rack-spacer{display:block;min-height:1px}.christianity-battle-zone{grid-template-columns:repeat(4,var(--christianity-battle-card-width))}.christianity-shared-zone{box-sizing:border-box;display:grid;grid-template-columns:repeat(3,minmax(4.3rem,1fr));align-items:stretch;width:100%;max-width:100%;min-width:0}.christianity-zone-card,.christianity-zone-pile{min-height:6.45rem;padding:.7rem .52rem .55rem}.christianity-zone-pile{position:relative;isolation:isolate;overflow:hidden;box-shadow:inset 0 0 0 999px #ffffff1f}.christianity-zone-pile i{position:absolute;top:2.2rem;right:.72rem;z-index:-1;width:2.7rem;height:3.7rem;border:1px solid rgba(16,42,67,.18);border-radius:.35rem;background:#f8fafc;box-shadow:0 .35rem .85rem #102a431c;transform:rotate(4deg)}.christianity-zone-pile i:nth-child(2){transform:translate(-.28rem,.12rem) rotate(-3deg)}.christianity-zone-pile i:nth-child(3){background:linear-gradient(135deg,#102a4329,#102a4308),repeating-linear-gradient(45deg,#dbeafe 0 .33rem,#fff .33rem .66rem);transform:translate(-.54rem,.24rem) rotate(2deg)}.christianity-floating-card-shell{position:fixed;top:50%;left:50%;z-index:80;display:grid;gap:.55rem;width:min(26rem,calc(100vw - 1.25rem));padding-top:2.35rem;transform:translate(-50%,-50%)}.christianity-floating-card{position:relative;z-index:1;display:grid;grid-template-rows:auto minmax(9rem,1.25fr) auto minmax(7rem,.9fr) auto;gap:.58rem;width:100%;min-height:min(29rem,calc(100vh - 3.5rem));padding:.72rem;border:1px solid rgba(36,48,68,.18);border-radius:.75rem;background:linear-gradient(180deg,#fffffff5,#f8fafcf5),radial-gradient(circle at 20% 0%,var(--christianity-theme-gold-soft),transparent 45%);box-shadow:0 0 0 .18rem #fff4c294,0 0 2.2rem var(--christianity-theme-glow),0 2.4rem 5rem #102a4357,inset 0 0 0 .35rem #ffffff8c;touch-action:none;transform:translate(var(--preview-shift-x, 0px),var(--preview-shift-y, 0px)) perspective(48rem) rotateX(var(--preview-rotate-x, 5deg)) rotateY(var(--preview-rotate-y, -5deg));transition:transform 90ms ease-out}.christianity-full-card-header{display:grid;grid-template-columns:auto minmax(0,1fr) auto;gap:.42rem;align-items:center}.christianity-full-card-header strong{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:clamp(1.25rem,5vw,1.85rem);line-height:1.04}.christianity-full-card-type-icon,.christianity-full-card-cost{display:grid;place-items:center;border-radius:999px}.christianity-full-card-type-icon{width:1.6rem;height:1.6rem;background:radial-gradient(circle at 50% 50%,rgba(95,111,42,.72) 0 .22rem,transparent .24rem),#2430441a}.christianity-full-card-cost{width:2.1rem;height:2.1rem;background:#ffd91a;color:#243044;font-size:1.35rem;font-weight:900;box-shadow:inset 0 -.12rem #52401c2e}.christianity-full-card-art{position:relative;display:grid;place-items:center;min-height:9rem;overflow:hidden;border-radius:.48rem;background:linear-gradient(135deg,#5f6f2a33,#d6a21d29),radial-gradient(circle at 50% 25%,rgba(255,255,255,.76),transparent 42%),#dbe7ef;box-shadow:inset 0 0 0 1px #24304414}.christianity-full-card-art img{width:100%;height:100%;object-fit:cover}.christianity-full-card-art>span{max-width:80%;color:#24304494;font-size:clamp(1.1rem,5vw,1.8rem);font-weight:900;line-height:1.05;text-align:center}.christianity-full-card-art small{position:absolute;right:0;bottom:.55rem;min-width:5rem;padding:.16rem .48rem;border-radius:999px 0 0 999px;background:#ffffffe6;box-shadow:0 .3rem .8rem #102a431f;color:#1f2933bd;font-size:.68rem;font-style:italic;font-weight:900;text-align:center;text-transform:uppercase}.christianity-full-card-verse,.christianity-full-card-effect{display:grid;gap:.32rem}.christianity-full-card-verse p,.christianity-full-card-effect p{margin:0;line-height:1.25}.christianity-full-card-verse{color:#171923;font-family:Georgia,Times New Roman,serif;font-size:clamp(.72rem,2.7vw,.86rem)}.christianity-full-card-verse strong{font-family:inherit;font-size:.78rem;font-weight:900}.christianity-full-card-effect{position:relative;align-content:start;min-height:7rem;padding:.6rem .7rem;overflow:hidden;border-radius:.45rem;background:radial-gradient(circle at 50% 72%,rgba(36,48,68,.07),transparent 34%),#ffffffdb}.christianity-full-card-stats{display:flex;gap:1rem;min-height:1.35rem}.christianity-full-card-stats strong{font-size:1rem;line-height:1}.christianity-full-card-effect>div:last-of-type{display:grid;gap:.12rem}.christianity-full-card-effect>div:last-of-type strong{font-size:.82rem}.christianity-full-card-effect p{font-size:clamp(.78rem,2.9vw,.92rem)}.christianity-full-card-rarity{position:absolute;top:.62rem;right:.62rem;width:.46rem;height:.46rem;border-radius:.12rem;transform:rotate(45deg)}.christianity-full-card-rarity.is-normal{background:#d1d5db}.christianity-full-card-rarity.is-uncommon{background:#22c55e}.christianity-full-card-rarity.is-rare{background:#3b82f6}.christianity-full-card-rarity.is-legendary{background:#eab308}.christianity-full-card-footer{display:grid;grid-template-columns:auto auto minmax(0,1fr) auto;gap:.34rem;align-items:center;color:#1f2933ad;font-size:.58rem;line-height:1;text-transform:uppercase}.christianity-full-card-footer span{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.christianity-floating-card-close{position:absolute;top:0;right:.15rem;z-index:4;min-height:2rem;padding:0 .6rem;border:1px solid rgba(36,48,68,.14);border-radius:999px;background:#ffffffe6;color:#1f2933c7;font:inherit;font-size:.76rem;font-weight:800;box-shadow:0 .45rem 1rem #102a431a}.christianity-preview-backdrop,.christianity-history-backdrop,.christianity-info-backdrop{position:fixed;inset:0;border:0;border-radius:0;background:#0f172a75}.christianity-preview-backdrop{z-index:79}.christianity-info-backdrop{z-index:50}.christianity-info-panel{position:fixed;top:50%;left:50%;z-index:51;width:min(31rem,calc(100vw - 1.25rem));max-height:min(34rem,calc(100vh - 2rem));padding-top:2.35rem;transform:translate(-50%,-50%)}.christianity-info-close{position:absolute;top:0;right:.15rem;z-index:2}.christianity-rule-note{display:grid;grid-template-columns:auto minmax(0,1fr);gap:.85rem;max-height:inherit;padding:1rem;overflow-y:auto;border:1px solid rgba(36,48,68,.14);border-radius:.9rem;background:linear-gradient(180deg,#fffffff7,#f8fafcf7),radial-gradient(circle at 8% 0%,rgba(37,99,235,.1),transparent 38%);box-shadow:0 1.2rem 2.6rem #102a433d,inset 0 0 0 .25rem #ffffff85}.christianity-rule-note-icon{display:grid;place-items:center;width:2.1rem;height:2.1rem;border-radius:999px;background:color-mix(in srgb,var(--christianity-theme-focus) 12%,#ffffff);color:var(--christianity-theme-focus);font-size:1rem;font-weight:900;box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--christianity-theme-focus) 24%,transparent)}.christianity-rule-note small,.christianity-rule-note strong,.christianity-rule-note p,.christianity-rule-note h2{margin:0}.christianity-rule-note small{color:#1f29339e;font-size:.78rem;font-weight:800;text-transform:uppercase}.christianity-rule-note h2{margin-top:.18rem;font-size:clamp(1.5rem,7vw,2.2rem);line-height:1.05}.christianity-rule-note strong{display:inline-flex;width:fit-content;margin-top:.55rem;padding:.22rem .55rem;border-radius:999px;background:#edf2f7;font-size:.92rem}.christianity-rule-note p{margin-top:.75rem;color:#1f2933c7;line-height:1.45}.christianity-rule-note ul{display:grid;gap:.45rem;margin:.8rem 0 0;padding-left:1.05rem;color:#1f2933c7;line-height:1.35}.christianity-floating-card>small,.christianity-floating-card>span{color:#1f2933a3}.christianity-floating-card>strong{font-size:clamp(1.55rem,8vw,2.35rem);line-height:1.05}.christianity-floating-card>p{margin:0;align-self:end;font-size:.95rem;line-height:1.35}.christianity-floating-card-actions{position:relative;z-index:4;display:flex;justify-content:center;padding:0 .35rem;transform:translateZ(0)}.christianity-floating-card-actions button{min-height:2.35rem;padding:0 1rem;border:0;border-radius:999px;background:#102a43;color:#fff;font:inherit;font-size:.9rem;font-weight:800;box-shadow:0 .65rem 1.3rem #102a432e}.christianity-floating-card-actions button:disabled{cursor:not-allowed;opacity:.45}@media (min-width: 52rem){.christianity-floating-card-shell{width:min(29rem,calc(100vw - 3rem))}.christianity-floating-card{min-height:min(35rem,calc(100vh - 4rem));padding:1.35rem}}.christianity-history-backdrop{z-index:40}.christianity-history-drawer{position:fixed;right:auto;bottom:max(.5rem,env(safe-area-inset-bottom));left:50%;z-index:41;display:grid;grid-template-rows:auto minmax(0,1fr);gap:.75rem;width:min(calc(100vw - 1rem),44rem);min-height:min(18rem,calc(100dvh - 1rem));max-height:min(32rem,calc(100dvh - 2rem));padding:.8rem;border:1px solid rgba(36,48,68,.16);border-radius:.75rem;background:#fffffffa;box-shadow:0 1.5rem 4rem #102a4347;transform:translate(-50%)}.christianity-history-drawer header{display:flex;align-items:center;justify-content:space-between;gap:.75rem}.christianity-history-drawer h2,.christianity-history-drawer p{margin:0}.christianity-history-drawer header span{display:grid;place-items:center;min-width:1.85rem;height:1.85rem;border-radius:999px;background:#edf2f7;font-weight:800}.christianity-dialog-actions{display:flex;align-items:center;gap:.45rem}.christianity-dialog-close{min-height:1.85rem;padding:0 .62rem;border:1px solid rgba(36,48,68,.14);border-radius:999px;background:#fff;color:#1f2933c7;font:inherit;font-size:.76rem;font-weight:800;box-shadow:0 .35rem .8rem #102a4314}.christianity-history-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(5.4rem,1fr));gap:.55rem;min-height:0;overflow-y:scroll;scrollbar-color:rgba(36,48,68,.32) rgba(226,232,240,.72);scrollbar-gutter:stable;padding:.1rem .1rem .25rem}.christianity-history-grid::-webkit-scrollbar,.christianity-offering-list::-webkit-scrollbar{width:.65rem}.christianity-history-grid::-webkit-scrollbar-track,.christianity-offering-list::-webkit-scrollbar-track{border-radius:999px;background:#e2e8f0b8}.christianity-history-grid::-webkit-scrollbar-thumb,.christianity-offering-list::-webkit-scrollbar-thumb{border:.14rem solid rgba(226,232,240,.72);border-radius:999px;background:#24304452}.christianity-offerings-drawer{width:min(calc(100vw - 1rem),48rem);min-height:min(20rem,calc(100dvh - 1rem));max-height:min(34rem,calc(100dvh - 2rem))}.christianity-offering-list{display:grid;gap:.6rem;min-height:0;overflow-y:scroll;scrollbar-color:rgba(36,48,68,.32) rgba(226,232,240,.72);scrollbar-gutter:stable;padding:.1rem}.christianity-offering-row{display:grid;grid-template-columns:minmax(4.9rem,6.2rem) minmax(0,1fr);gap:.65rem;align-items:stretch;padding:.45rem;border:1px solid rgba(36,48,68,.12);border-radius:.65rem;background:#fff}.christianity-offering-row.is-exhausted{opacity:.68}.christianity-offering-card{min-height:7.4rem;background:linear-gradient(180deg,#fffffff5,#f8fafcf5),radial-gradient(circle at 82% 14%,#facc15 0 .48rem,transparent .5rem);box-shadow:0 .45rem 1rem #102a431a}.christianity-offering-card.christianity-card-frame{min-height:0;aspect-ratio:var(--christianity-card-aspect)}.christianity-offering-card small{color:#1f293394;font-size:.66rem;text-transform:uppercase}.christianity-offering-card p,.christianity-offering-row p{margin:0}.christianity-offering-card p{align-self:end;color:#1f2933a3;font-size:.72rem;line-height:1.2}.christianity-offering-row>div{display:grid;gap:.35rem;align-content:center;min-width:0}.christianity-offering-row>div p{color:#1f2933b8;font-size:.85rem;line-height:1.3}.christianity-offering-row>div button{justify-self:start;min-height:2.2rem;padding:0 .7rem;border:1px solid rgba(16,42,67,.16);border-radius:.5rem;background:#102a43;color:#fff;font:inherit;font-weight:800}.christianity-offering-row>div button:disabled{background:#e2e8f0;color:#1f293394}button{cursor:pointer}button:disabled{cursor:not-allowed;opacity:.55}button:focus-visible{outline:.1875rem solid color-mix(in srgb,var(--christianity-theme-focus) 24%,transparent);outline-offset:.125rem}@media (max-width: 720px){.christianity-shell{padding:.55rem 0;border-right:0;border-left:0;border-radius:0}.christianity-header,.christianity-player__summary,.christianity-shared-zone,.christianity-actions{align-items:stretch;flex-direction:column}.christianity-match-strip{grid-template-columns:minmax(0,1fr) auto minmax(0,1fr);gap:.35rem;padding:.35rem}.christianity-match-player{gap:.35rem}.christianity-match-player small{display:none}.christianity-scoreboard{min-width:3.65rem;padding:0 .35rem}.christianity-scoreboard strong{font-size:1.05rem}.christianity-table{gap:.35rem;padding-right:.25rem;padding-left:.25rem}.christianity-player-side{padding:.3rem .25rem}.christianity-battle-zone{--christianity-battle-card-width: min(5.2rem, calc((100vw - 4.25rem)/4) );grid-template-columns:repeat(4,var(--christianity-battle-card-width));justify-content:center;min-height:8.75rem;overflow-x:clip}.christianity-hand-fan{min-height:11.45rem;padding-bottom:2rem;overflow:visible}.christianity-hand-shelf{min-height:12.65rem;margin-top:-1rem;padding-top:1.35rem;padding-bottom:.9rem}.christianity-hand-shelf--opponent{min-height:6.65rem;margin-top:0;margin-bottom:0;padding-top:.4rem;padding-bottom:.85rem}.christianity-player-rack{grid-template-columns:minmax(4.5rem,5.7rem) minmax(4.4rem,1fr) minmax(3.5rem,4.8rem)}.christianity-shared-zone{gap:.45rem;grid-template-columns:repeat(3,minmax(0,1fr))}.christianity-zone-card,.christianity-zone-pile{min-height:6.15rem;padding:.58rem .46rem .5rem;gap:.24rem}.christianity-zone-pile i{top:2rem;right:.52rem;width:2.35rem;height:3.25rem}.christianity-offering-pile{min-height:6.85rem;padding:.88rem .46rem .55rem;gap:.24rem}.christianity-offering-pile i{top:2.25rem;left:.56rem;width:2.35rem;height:3.25rem}.christianity-card-preview-card{width:clamp(4.2rem,20vw,5.7rem);height:auto;min-height:0}.christianity-leader-card{width:clamp(4.55rem,20vw,5.7rem);min-height:0}.christianity-offering-row{grid-template-columns:minmax(4.5rem,5.5rem) minmax(0,1fr);gap:.5rem}.christianity-hand-fan--opponent{min-height:5.75rem;padding-bottom:.7rem}}\n"] }]
70598
- }], ctorParameters: () => [] });
70599
-
70600
68582
  addIcons({ refreshOutline, sparklesOutline, trophyOutline });
70601
68583
  const BUBBLE_COLORS = {
70602
68584
  rose: '#ff4f9f',
@@ -70653,7 +68635,6 @@ class BubbleBlitzGameComponent {
70653
68635
  this.animating = signal(false);
70654
68636
  this.leaderboard = signal(this.readLeaderboard());
70655
68637
  this.confirmAction = signal(undefined);
70656
- this.confirmedAction = signal(undefined);
70657
68638
  this.config = computed(() => MODE_CONFIG[this.mode()]);
70658
68639
  this.feverReady = computed(() => this.fever() >= this.config().feverTarget);
70659
68640
  this.feverProgress = computed(() => Math.min(100, Math.round((this.fever() / this.config().feverTarget) * 100)));
@@ -70833,12 +68814,13 @@ class BubbleBlitzGameComponent {
70833
68814
  closeConfirmModal() {
70834
68815
  this.confirmAction.set(undefined);
70835
68816
  }
70836
- handleConfirmModalDismissed() {
70837
- this.confirmAction.set(undefined);
70838
- const action = this.confirmedAction();
70839
- this.confirmedAction.set(undefined);
70840
- if (!action)
68817
+ confirmPendingAction(token) {
68818
+ if (token !== 'confirm') {
68819
+ this.closeConfirmModal();
70841
68820
  return;
68821
+ }
68822
+ const action = this.confirmAction();
68823
+ this.confirmAction.set(undefined);
70842
68824
  if (action === 'restart') {
70843
68825
  this.start();
70844
68826
  return;
@@ -70851,15 +68833,6 @@ class BubbleBlitzGameComponent {
70851
68833
  this.resetToGamesMenu();
70852
68834
  }
70853
68835
  }
70854
- confirmPendingAction(token) {
70855
- if (token !== 'confirm') {
70856
- this.closeConfirmModal();
70857
- return;
70858
- }
70859
- const action = this.confirmAction();
70860
- this.confirmedAction.set(action);
70861
- this.confirmAction.set(undefined);
70862
- }
70863
68836
  startTimer() {
70864
68837
  this.stopTimer();
70865
68838
  this.timer = window.setInterval(() => {
@@ -71163,7 +69136,7 @@ class BubbleBlitzGameComponent {
71163
69136
  <ion-modal
71164
69137
  [isOpen]="!!confirmAction()"
71165
69138
  cssClass="val-modal-adaptive"
71166
- (didDismiss)="handleConfirmModalDismissed()"
69139
+ (didDismiss)="closeConfirmModal()"
71167
69140
  >
71168
69141
  <ng-template>
71169
69142
  <val-modal-layout
@@ -71313,7 +69286,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
71313
69286
  <ion-modal
71314
69287
  [isOpen]="!!confirmAction()"
71315
69288
  cssClass="val-modal-adaptive"
71316
- (didDismiss)="handleConfirmModalDismissed()"
69289
+ (didDismiss)="closeConfirmModal()"
71317
69290
  >
71318
69291
  <ng-template>
71319
69292
  <val-modal-layout
@@ -71377,7 +69350,6 @@ class MemoryGameComponent {
71377
69350
  this.lockBoard = signal(false);
71378
69351
  this.leaderboard = signal(this.readLeaderboard());
71379
69352
  this.confirmAction = signal(undefined);
71380
- this.confirmedAction = signal(undefined);
71381
69353
  this.profileConfig = computed(() => PROFILE_CONFIG[this.profile()]);
71382
69354
  this.pairCount = computed(() => this.profileConfig().pairs);
71383
69355
  this.boardClass = computed(() => `memory-board ${this.profileConfig().boardClass}`);
@@ -71515,12 +69487,13 @@ class MemoryGameComponent {
71515
69487
  closeConfirmModal() {
71516
69488
  this.confirmAction.set(undefined);
71517
69489
  }
71518
- handleConfirmModalDismissed() {
71519
- this.confirmAction.set(undefined);
71520
- const action = this.confirmedAction();
71521
- this.confirmedAction.set(undefined);
71522
- if (!action)
69490
+ confirmPendingAction(token) {
69491
+ if (token !== 'confirm') {
69492
+ this.closeConfirmModal();
71523
69493
  return;
69494
+ }
69495
+ const action = this.confirmAction();
69496
+ this.confirmAction.set(undefined);
71524
69497
  if (action === 'restart') {
71525
69498
  this.start();
71526
69499
  return;
@@ -71533,15 +69506,6 @@ class MemoryGameComponent {
71533
69506
  this.resetToGamesMenu();
71534
69507
  }
71535
69508
  }
71536
- confirmPendingAction(token) {
71537
- if (token !== 'confirm') {
71538
- this.closeConfirmModal();
71539
- return;
71540
- }
71541
- const action = this.confirmAction();
71542
- this.confirmedAction.set(action);
71543
- this.confirmAction.set(undefined);
71544
- }
71545
69509
  flip(card) {
71546
69510
  if (this.lockBoard() || card.flipped || card.matched || this.won() || this.failed())
71547
69511
  return;
@@ -71856,7 +69820,7 @@ class MemoryGameComponent {
71856
69820
  <ion-modal
71857
69821
  [isOpen]="!!confirmAction()"
71858
69822
  cssClass="val-modal-adaptive"
71859
- (didDismiss)="handleConfirmModalDismissed()"
69823
+ (didDismiss)="closeConfirmModal()"
71860
69824
  >
71861
69825
  <ng-template>
71862
69826
  <val-modal-layout
@@ -72014,7 +69978,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
72014
69978
  <ion-modal
72015
69979
  [isOpen]="!!confirmAction()"
72016
69980
  cssClass="val-modal-adaptive"
72017
- (didDismiss)="handleConfirmModalDismissed()"
69981
+ (didDismiss)="closeConfirmModal()"
72018
69982
  >
72019
69983
  <ng-template>
72020
69984
  <val-modal-layout
@@ -72360,7 +70324,6 @@ class SimonGameComponent {
72360
70324
  this.activePad = signal(undefined);
72361
70325
  this.leaderboard = signal(this.readLeaderboard());
72362
70326
  this.confirmAction = signal(undefined);
72363
- this.confirmedAction = signal(undefined);
72364
70327
  this.modeConfig = computed(() => SIMON_MODES[this.mode()]);
72365
70328
  this.bestRound = computed(() => this.modeLeaderboard()[0]?.round ?? 0);
72366
70329
  this.modeLeaderboard = computed(() => this.leaderboard()
@@ -72460,12 +70423,13 @@ class SimonGameComponent {
72460
70423
  closeConfirmModal() {
72461
70424
  this.confirmAction.set(undefined);
72462
70425
  }
72463
- handleConfirmModalDismissed() {
72464
- this.confirmAction.set(undefined);
72465
- const action = this.confirmedAction();
72466
- this.confirmedAction.set(undefined);
72467
- if (!action)
70426
+ confirmPendingAction(token) {
70427
+ if (token !== 'confirm') {
70428
+ this.closeConfirmModal();
72468
70429
  return;
70430
+ }
70431
+ const action = this.confirmAction();
70432
+ this.confirmAction.set(undefined);
72469
70433
  if (action === 'restart') {
72470
70434
  this.start();
72471
70435
  return;
@@ -72478,15 +70442,6 @@ class SimonGameComponent {
72478
70442
  this.resetToGamesMenu();
72479
70443
  }
72480
70444
  }
72481
- confirmPendingAction(token) {
72482
- if (token !== 'confirm') {
72483
- this.closeConfirmModal();
72484
- return;
72485
- }
72486
- const action = this.confirmAction();
72487
- this.confirmedAction.set(action);
72488
- this.confirmAction.set(undefined);
72489
- }
72490
70445
  tap(pad) {
72491
70446
  if (this.phase() !== 'waiting' || !this.acceptingInput)
72492
70447
  return;
@@ -72730,7 +70685,7 @@ class SimonGameComponent {
72730
70685
  <ion-modal
72731
70686
  [isOpen]="!!confirmAction()"
72732
70687
  cssClass="val-modal-adaptive"
72733
- (didDismiss)="handleConfirmModalDismissed()"
70688
+ (didDismiss)="closeConfirmModal()"
72734
70689
  >
72735
70690
  <ng-template>
72736
70691
  <val-modal-layout
@@ -72860,7 +70815,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
72860
70815
  <ion-modal
72861
70816
  [isOpen]="!!confirmAction()"
72862
70817
  cssClass="val-modal-adaptive"
72863
- (didDismiss)="handleConfirmModalDismissed()"
70818
+ (didDismiss)="closeConfirmModal()"
72864
70819
  >
72865
70820
  <ng-template>
72866
70821
  <val-modal-layout
@@ -88176,5 +86131,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
88176
86131
  * Generated bundle index. Do not edit.
88177
86132
  */
88178
86133
 
88179
- export { ACTION_CARD_DEFAULTS, AD_SIZE_MAP, API_TABLE_COLUMN_LABELS, APP_VERSION_PLATFORM_PLUGIN, APP_VERSION_REMOTE_PLUGIN, ARTICLE_CARD_DEFAULTS, ARTICLE_SPACING, ARTICLE_STRIP_DEFAULTS, AUTH_CTA_DEFAULTS, AVATAR_UPLOAD_DEFAULTS, AboutViewComponent, AccordionComponent, AccountViewComponent, ActionCardComponent, ActionHeaderComponent, ActionType, AdSlotComponent, AdsLoaderService, AdsService, AlertBoxComponent, AnalyticsErrorHandler, AnalyticsRouterTracker, AnalyticsService, AnimatedTerminalComponent, ApiKeyCreateModalComponent, ApiKeyService, ApiKeysModalComponent, ApiKeysViewComponent, AppConfigService, AppVersionService, ArticleBuilder, ArticleCardComponent, ArticleComponent, ArticleStripComponent, AttachmentUploaderComponent, AuthBackgroundComponent, AuthCtaComponent, AuthService, AuthStateService, AuthStorageService, AuthSyncService, AvatarComponent, AvatarUploadComponent, BOTTOM_NAV_DEFAULTS, BannerComponent, BlogPostBuilder, BottomNavComponent, BoxComponent, BreadcrumbComponent, BubbleBlitzGameComponent, ButtonComponent, ButtonGroupComponent, CALLOUT_LABELS, CHESSIMALS_BOT_PROFILES, CHEV_KEYS, CIRCLE_KEYS, COMMON_COUNTRY_CODES, COMMON_CURRENCIES, CORNER_KEYS, CTA_CARD_DEFAULTS, CURRENCY_INFO, CardComponent, CardSection, CardType, CardsCarouselComponent, ChangeEmailModalComponent, ChangePasswordModalComponent, ChatComposerComponent, ChatInputComponent, ChatWindowComponent, CheckInputComponent, CheckboxRadioInputComponent, ChessimalsGameComponent, ChessimalsOnlineService, ChipGroupComponent, ChristianityGameComponent, CodeDisplayComponent, CommandDisplayComponent, CommentComponent, CommentInputComponent, CommentSectionComponent, CompanyFooterComponent, ComponentStates, ConfirmationDialogService, ContainerComponent, ContentLoaderComponent, ContentReactionComponent, ContentReactionModalComponent, ContentService, ContentTransformer, ConversationListItemComponent, ConversationService, CookieBannerComponent, CookieSettingsComponent, CountdownComponent, CreateOrgModalComponent, CtaCardComponent, CurrencyInputComponent, DEFAULT_ADS_CONFIG, DEFAULT_APP_CONFIG_SERVICE_CONFIG, DEFAULT_APP_VERSION_SERVICE_CONFIG, DEFAULT_AUTH_CONFIG, DEFAULT_BACK_HEADER, DEFAULT_BUTTON_PRESETS, DEFAULT_CANCEL_BUTTON, DEFAULT_CHECK_INTERVAL_MS, DEFAULT_CONFIRM_BUTTON, DEFAULT_COUNTDOWN_LABELS, DEFAULT_COUNTDOWN_LABELS_EN, DEFAULT_DEBUG_CONSOLE_CONFIG, DEFAULT_DONATION_CONFIG, DEFAULT_EMPTY_STATE, DEFAULT_EMULATOR_CONFIG, DEFAULT_FEEDBACK_CONFIG, DEFAULT_FEEDBACK_TYPE_OPTIONS, DEFAULT_HOME_HEADER, DEFAULT_INFINITE_LIST_METADATA, DEFAULT_LOGIN_LOGO, DEFAULT_MODAL_CANCEL_BUTTON, DEFAULT_MODAL_CONFIRM_BUTTON, DEFAULT_PAGE_SIZE_OPTIONS, DEFAULT_PLATFORMS, DEFAULT_POST_UPDATE_GRACE_MS, DEFAULT_PRESETS, DEFAULT_REFRESHER_METADATA, DEFAULT_SKELETON_CONFIG, DEFAULT_SPLASH_SCREEN_CONFIG, DataTableComponent, DatasetPaginationService, DateInputComponent, DatePickerComponent, DateRangeInputComponent, DebugConsoleComponent, DeleteAccountModalComponent, DetailSkeletonComponent, DeviceService, DisplayComponent, DividerComponent, DocsApiTableComponent, DocsBreadcrumbComponent, DocsBuilder, DocsCalloutComponent, DocsCodeExampleComponent, DocsLayoutComponent, DocsNavLinksComponent, DocsNavigationService, DocsPageComponent, DocsSearchComponent, DocsSectionComponent, DocsShellComponent, DocsSidebarComponent, DocsTocComponent, DonationService, DownloadService, EditOrgModalComponent, EmptyStateComponent, EntityCardComponent, EntityFeedService, ExpandableTextComponent, ExternalBrowserService, FEATURES_LIST_DEFAULTS, FUN_MODAL_DEFAULTS, FabComponent, FaqComponent, FeaturesListComponent, FeedbackFormComponent, FeedbackService, FieldListComponent, FileInputComponent, FirebaseService, FirestoreCollectionFactory, FirestoreService, FontSizeOption, FontSizeSelectorComponent, FontSizeService, FooterComponent, FooterLinksComponent, FormComponent, FormFieldComponent, FormSchemaBuilderService, FormSkeletonComponent, FunHeaderComponent, FunModalComponent, GlassComponent, GlowCardComponent, GlowComponent, GridSkeletonComponent, HANDOFF_ROUTE_PARAM, HANDOFF_TOKEN_PARAM, HandoffService, HapticsService, HasPermissionDirective, HeaderActionsService, HeaderComponent, HintComponent, HorizontalScrollComponent, HrefComponent, HtmlViewerModalComponent, I18nService, IMAGE_DEFAULTS, INITIAL_AUTH_STATE, INITIAL_MFA_STATE, INVITATION_CARD_DEFAULTS, IONIC_COLORS$5 as IONIC_COLORS, Icon, IconComponent, IconService, ImageComponent, ImageCropComponent, ImageService, InAppBrowserService, InfiniteListComponent, InfoComponent, InputI18nHelper, InputType, InvitationCardComponent, InviteMemberModalComponent, ItemListComponent, KNOWN_ROUTES, LANG_STORAGE_KEY$1 as LANG_STORAGE_KEY, LEGAL_CONTENT_CONFIG, LOGGED_IN_HINT_COOKIE, LOGIN_DEFAULTS, LandingSplitComponent, LandingStepsComponent, LanguageSelectorComponent, LanguageSelectorV2Component, LayeredCardComponent, LegalContentService, LegalLinkService, LightRippleDirective, LinkComponent, LinkProcessorService, LinkedProvidersComponent, LinksAccordionComponent, LinksCakeComponent, ListSkeletonComponent, LiveReadFallbackService, LoadMoreComponent, LoadingDirective, LocalStorageService, LocaleService, LoginAttemptModalComponent, LoginComponent, MEDIA_OBJECT_DEFAULTS, MEMBER_CARD_DEFAULTS, META_SCHEMA_VERSION, METRIC_CARD_DEFAULTS, MINI_GAME_PLAYER_AVATARS, MINI_GAME_PLAYER_COLORS, MODAL_SIZES, MOTIF_KEYS, MOTION, MaintenancePageComponent, MarkdownArticleParserService, MediaObjectComponent, MediaViewerModalComponent, MemberCardComponent, MemberDetailModalComponent, MemberImportModalComponent, MemoryGameComponent, MenuComponent, MessageBubbleComponent, MessagingService, MetaService, MetricCardComponent, MfaModalComponent, MiniGamePlayerProfileService, MiniGamesMenuComponent, ModalLayoutComponent, ModalService, ModalShellComponent, MultiSelectSearchComponent, NUM_KEYS, NavigationService, NetworkBannerComponent, NetworkStatusService, NewsBuilder, NoContentComponent, NotesBoxComponent, NotificationActionService, NotificationPreferencesViewComponent, NotificationsService, NotificationsViewComponent, NumberFromToComponent, NumberStepperComponent, OAUTH_PROVIDERS_INFO, OAuthCallbackComponent, OAuthService, OperationReferenceComponent, OptionCardsComponent, OrgInfoSheetComponent, OrgService, OrgSwitchService, OrganizationViewComponent, PATTERN_MOTIFS, PATTERN_PALETTES, PATTERN_STYLE_CONFIGS, PLATFORM_CONFIGS, POST_UPDATE_TS_KEY, PageContentComponent, PageLinksComponent, PageRefreshService, PageTemplateComponent, PageWavesComponent, PageWrapperComponent, PaginationComponent, PaginationService, PasswordInputComponent, PatternComponent, PdfService, PermissionCatalogService, PermissionSelectorComponent, PermissionsModalComponent, PermissionsViewComponent, PhoneDisplayComponent, PhoneFormatService, PhoneInputComponent, PickerV2Component, PillComponent, PinInputComponent, PlainCodeBoxComponent, PopoverSelectorComponent, PreferencesService, PreferencesViewComponent, PresetService, PriceTagComponent, PricingTableComponent, ProcessLinksPipe, ProfileContentComponent, ProfileModalComponent, ProfileSkeletonComponent, ProfileViewComponent, ProgressBarComponent, ProgressRingComponent, ProgressStatusComponent, PrompterComponent, QR_PRESETS, QrCodeComponent, QrGeneratorService, QrScannerComponent, QueryBuilder, QuoteBoxComponent, REQUEST_STATUSES, RadioInputComponent, RangeInputComponent, RatingComponent, ReactionBarComponent, ReactionsService, RefresherComponent, RequestFirestoreService, RequestFormBuilderService, RequestFormComponent, RequestModalComponent, RequestService, RetroAudioService, RightsFooterComponent, RotatingTextComponent, SEARCH_HEADER_DEFAULTS, SETTINGS_SECTIONS_CATALOG, SHAPE_KEYS, SHARE_PROFILE_MODAL_DEFAULTS, SKELETON_LAYOUT_DEFAULT_ROWS, SKELETON_PRESETS, SOLID_KEYS, STATS_BAR_DEFAULTS, STROKE_KEYS, SearchHeaderComponent, SearchSelectorComponent, SearchbarComponent, SectionHeaderComponent, SecurityViewComponent, SegmentControlComponent, SelectSearchComponent, SessionListModalComponent, SessionService, SessionTransitionOverlayComponent, SettingsHubComponent, ShareButtonsComponent, ShareProfileModalComponent, SimonGameComponent, SimpleComponent, SkeletonComponent, SkeletonLayoutComponent, SkeletonService, SplashComponent, SplashScreenService, StatsBarComponent, StatsCardComponent, StepperComponent, StorageService, SwipeCarouselComponent, SwitchOrgModalComponent, TRI_KEYS, TabbedContentComponent, TableSkeletonComponent, TabsComponent, Terminal404Component, TestimonialCardComponent, TestimonialCarouselComponent, TextComponent, TextInputComponent, TextareaInputComponent, ThemeOption, ThemeService, ThreadPanelComponent, TicketCardComponent, TicketCardImageService, TimelineComponent, TitleBlockComponent, TitleComponent, ToastService, ToggleInputComponent, TokenService, ToolbarActionType, ToolbarComponent, TransferOwnershipModalComponent, TranslatePipe, TypedCollection, TypingIndicatorComponent, UPDATE_BANNER_DEFAULT_CONTENT, UPDATE_BANNER_I18N_NAMESPACE, UpdateBannerComponent, UsageMetersComponent, UsageService, UserAvatarComponent, UsernameInputComponent, VALTECH_ADS_CONFIG, VALTECH_APP_CONFIG, VALTECH_APP_VERSION, VALTECH_AUTH_CONFIG, VALTECH_CHAT_CONFIG, VALTECH_COMPANY_LINKS, VALTECH_CONTENT_CONFIG, VALTECH_DEBUG_CONSOLE, VALTECH_DEFAULT_CONTENT, VALTECH_DONATION_CONFIG, VALTECH_FEEDBACK_CONFIG, VALTECH_FIREBASE_CONFIG, VALTECH_FOOTER_I18N, VALTECH_FOOTER_LOGO, VALTECH_LANGUAGE_SELECTOR, VALTECH_LEGAL_CONFIG, VALTECH_NETWORK_ERROR_KEY, VALTECH_REACTIONS_CONFIG, VALTECH_SETTINGS_MENU_LINKS, VALTECH_SITE_PATHS, VALTECH_SOCIAL_LINKS, VALTECH_SPLASH_SCREEN, VALTECH_WEB_BASE_URLS, VALTECH_WHATSAPP_CONFIG, VERSION, ValtechErrorService, VerifyViewComponent, WhatsappFabComponent, WhatsappService, WizardComponent, WizardFooterComponent, WorkflowService, applyChessimalsMove, applyDefaultValueToControl, authGuard, authInterceptor, authPasswordValidator, beautifyLegalArticle, blogPost, buildCompanyFooterProps, buildFooterLinks, buildLegalLinkResolver, buildPath, buildSettingsCards, button, canSubmitRequestType, chooseChessimalsBotMove, collections, connectPageRefresh, createChessimalsGame, createChessimalsReviewState, createErrorStateProps, createFirebaseConfig, createGlowCardProps, createInitialDatasetState, createInitialPaginationState, createNumberFromToField, createPageState, createPermissionLabeler, createRefreshableStream, createTitleProps, datasetPageFromLegacyCursor, docs, errorLoggingInterceptor, extractPathParams, formatClockTime, formatDateSeparator, formatRelativeTime, generatePatternTiles, generateRandomTile, getAppInfo, getAppVersion, getChessimalsAllLegalMoves, getChessimalsLegalMoves, getChessimalsPieceAt, getCollectionPath, getDocumentId, getTimeOfDayKey, goToTop, groupPermissionsByScope, guestGuard, hasEmulators, iconButton, interpretError, isAtEnd, isCollectionPath, isDocumentPath, isEmulatorMode, isIonicColor, isKnownRoute, isValidPath, joinPath, maxLength, mulberry32, news, parseMarkdownArticle, permissionGuard, permissionGuardFromRoute, positionKey, provideLegalContent, provideSplashScreen, provideValtechAboutRoutes, provideValtechAccountRoutes, provideValtechAds, provideValtechApiKeysRoutes, provideValtechAppConfig, provideValtechAppVersion, provideValtechAppVersionHttp, provideValtechAuth, provideValtechAuthInterceptor, provideValtechChat, provideValtechContent, provideValtechDebugConsole, provideValtechDonations, provideValtechErrorHandling, provideValtechFeedback, provideValtechFirebase, provideValtechI18n, provideValtechLegal, provideValtechNotificationClickActions, provideValtechNotificationPreferencesRoutes, provideValtechNotificationsRoutes, provideValtechOrganizationRoutes, provideValtechPermissionsRoutes, provideValtechPreferencesRoutes, provideValtechPresets, provideValtechProfileRoutes, provideValtechReactions, provideValtechSecurityRoutes, provideValtechSettingsRoutes, provideValtechSite, provideValtechSkeleton, provideValtechWhatsapp, query, rbacGuard, renderPatternSvgInner, replaceSpecialChars, requestSubmitMode, resignChessimalsGame, resolveColor, resolveInputDefaultValue, resolveIonicColor, resolveWebBaseUrl, roleGuard, selectableRequestTypes, storagePaths, superAdminGuard, toArticle, validateRoutes };
86134
+ export { ACTION_CARD_DEFAULTS, AD_SIZE_MAP, API_TABLE_COLUMN_LABELS, APP_VERSION_PLATFORM_PLUGIN, APP_VERSION_REMOTE_PLUGIN, ARTICLE_CARD_DEFAULTS, ARTICLE_SPACING, ARTICLE_STRIP_DEFAULTS, AUTH_CTA_DEFAULTS, AVATAR_UPLOAD_DEFAULTS, AboutViewComponent, AccordionComponent, AccountViewComponent, ActionCardComponent, ActionHeaderComponent, ActionType, AdSlotComponent, AdsLoaderService, AdsService, AlertBoxComponent, AnalyticsErrorHandler, AnalyticsRouterTracker, AnalyticsService, AnimatedTerminalComponent, ApiKeyCreateModalComponent, ApiKeyService, ApiKeysModalComponent, ApiKeysViewComponent, AppConfigService, AppVersionService, ArticleBuilder, ArticleCardComponent, ArticleComponent, ArticleStripComponent, AttachmentUploaderComponent, AuthBackgroundComponent, AuthCtaComponent, AuthService, AuthStateService, AuthStorageService, AuthSyncService, AvatarComponent, AvatarUploadComponent, BOTTOM_NAV_DEFAULTS, BannerComponent, BlogPostBuilder, BottomNavComponent, BoxComponent, BreadcrumbComponent, BubbleBlitzGameComponent, ButtonComponent, ButtonGroupComponent, CALLOUT_LABELS, CHESSIMALS_BOT_PROFILES, CHEV_KEYS, CIRCLE_KEYS, COMMON_COUNTRY_CODES, COMMON_CURRENCIES, CORNER_KEYS, CTA_CARD_DEFAULTS, CURRENCY_INFO, CardComponent, CardSection, CardType, CardsCarouselComponent, ChangeEmailModalComponent, ChangePasswordModalComponent, ChatComposerComponent, ChatInputComponent, ChatWindowComponent, CheckInputComponent, CheckboxRadioInputComponent, ChessimalsGameComponent, ChessimalsOnlineService, ChipGroupComponent, CodeDisplayComponent, CommandDisplayComponent, CommentComponent, CommentInputComponent, CommentSectionComponent, CompanyFooterComponent, ComponentStates, ConfirmationDialogService, ContainerComponent, ContentLoaderComponent, ContentReactionComponent, ContentReactionModalComponent, ContentService, ContentTransformer, ConversationListItemComponent, ConversationService, CookieBannerComponent, CookieSettingsComponent, CountdownComponent, CreateOrgModalComponent, CtaCardComponent, CurrencyInputComponent, DEFAULT_ADS_CONFIG, DEFAULT_APP_CONFIG_SERVICE_CONFIG, DEFAULT_APP_VERSION_SERVICE_CONFIG, DEFAULT_AUTH_CONFIG, DEFAULT_BACK_HEADER, DEFAULT_BUTTON_PRESETS, DEFAULT_CANCEL_BUTTON, DEFAULT_CHECK_INTERVAL_MS, DEFAULT_CONFIRM_BUTTON, DEFAULT_COUNTDOWN_LABELS, DEFAULT_COUNTDOWN_LABELS_EN, DEFAULT_DEBUG_CONSOLE_CONFIG, DEFAULT_DONATION_CONFIG, DEFAULT_EMPTY_STATE, DEFAULT_EMULATOR_CONFIG, DEFAULT_FEEDBACK_CONFIG, DEFAULT_FEEDBACK_TYPE_OPTIONS, DEFAULT_HOME_HEADER, DEFAULT_INFINITE_LIST_METADATA, DEFAULT_LOGIN_LOGO, DEFAULT_MODAL_CANCEL_BUTTON, DEFAULT_MODAL_CONFIRM_BUTTON, DEFAULT_PAGE_SIZE_OPTIONS, DEFAULT_PLATFORMS, DEFAULT_POST_UPDATE_GRACE_MS, DEFAULT_PRESETS, DEFAULT_REFRESHER_METADATA, DEFAULT_SKELETON_CONFIG, DEFAULT_SPLASH_SCREEN_CONFIG, DataTableComponent, DatasetPaginationService, DateInputComponent, DatePickerComponent, DateRangeInputComponent, DebugConsoleComponent, DeleteAccountModalComponent, DetailSkeletonComponent, DeviceService, DisplayComponent, DividerComponent, DocsApiTableComponent, DocsBreadcrumbComponent, DocsBuilder, DocsCalloutComponent, DocsCodeExampleComponent, DocsLayoutComponent, DocsNavLinksComponent, DocsNavigationService, DocsPageComponent, DocsSearchComponent, DocsSectionComponent, DocsShellComponent, DocsSidebarComponent, DocsTocComponent, DonationService, DownloadService, EditOrgModalComponent, EmptyStateComponent, EntityCardComponent, EntityFeedService, ExpandableTextComponent, ExternalBrowserService, FEATURES_LIST_DEFAULTS, FUN_MODAL_DEFAULTS, FabComponent, FaqComponent, FeaturesListComponent, FeedbackFormComponent, FeedbackService, FieldListComponent, FileInputComponent, FirebaseService, FirestoreCollectionFactory, FirestoreService, FontSizeOption, FontSizeSelectorComponent, FontSizeService, FooterComponent, FooterLinksComponent, FormComponent, FormFieldComponent, FormSchemaBuilderService, FormSkeletonComponent, FunHeaderComponent, FunModalComponent, GlassComponent, GlowCardComponent, GlowComponent, GridSkeletonComponent, HANDOFF_ROUTE_PARAM, HANDOFF_TOKEN_PARAM, HandoffService, HapticsService, HasPermissionDirective, HeaderActionsService, HeaderComponent, HintComponent, HorizontalScrollComponent, HrefComponent, HtmlViewerModalComponent, I18nService, IMAGE_DEFAULTS, INITIAL_AUTH_STATE, INITIAL_MFA_STATE, INVITATION_CARD_DEFAULTS, IONIC_COLORS$5 as IONIC_COLORS, Icon, IconComponent, IconService, ImageComponent, ImageCropComponent, ImageService, InAppBrowserService, InfiniteListComponent, InfoComponent, InputI18nHelper, InputType, InvitationCardComponent, InviteMemberModalComponent, ItemListComponent, KNOWN_ROUTES, LANG_STORAGE_KEY$1 as LANG_STORAGE_KEY, LEGAL_CONTENT_CONFIG, LOGGED_IN_HINT_COOKIE, LOGIN_DEFAULTS, LandingSplitComponent, LandingStepsComponent, LanguageSelectorComponent, LanguageSelectorV2Component, LayeredCardComponent, LegalContentService, LegalLinkService, LinkComponent, LinkProcessorService, LinkedProvidersComponent, LinksAccordionComponent, LinksCakeComponent, ListSkeletonComponent, LiveReadFallbackService, LoadMoreComponent, LoadingDirective, LocalStorageService, LocaleService, LoginAttemptModalComponent, LoginComponent, MEDIA_OBJECT_DEFAULTS, MEMBER_CARD_DEFAULTS, META_SCHEMA_VERSION, METRIC_CARD_DEFAULTS, MINI_GAME_PLAYER_AVATARS, MINI_GAME_PLAYER_COLORS, MODAL_SIZES, MOTIF_KEYS, MOTION, MaintenancePageComponent, MarkdownArticleParserService, MediaObjectComponent, MediaViewerModalComponent, MemberCardComponent, MemberDetailModalComponent, MemberImportModalComponent, MemoryGameComponent, MenuComponent, MessageBubbleComponent, MessagingService, MetaService, MetricCardComponent, MfaModalComponent, MiniGamePlayerProfileService, MiniGamesMenuComponent, ModalLayoutComponent, ModalService, ModalShellComponent, MultiSelectSearchComponent, NUM_KEYS, NavigationService, NetworkBannerComponent, NetworkStatusService, NewsBuilder, NoContentComponent, NotesBoxComponent, NotificationActionService, NotificationPreferencesViewComponent, NotificationsService, NotificationsViewComponent, NumberFromToComponent, NumberStepperComponent, OAUTH_PROVIDERS_INFO, OAuthCallbackComponent, OAuthService, OperationReferenceComponent, OptionCardsComponent, OrgInfoSheetComponent, OrgService, OrgSwitchService, OrganizationViewComponent, PATTERN_MOTIFS, PATTERN_PALETTES, PATTERN_STYLE_CONFIGS, PLATFORM_CONFIGS, POST_UPDATE_TS_KEY, PageContentComponent, PageLinksComponent, PageRefreshService, PageTemplateComponent, PageWavesComponent, PageWrapperComponent, PaginationComponent, PaginationService, PasswordInputComponent, PatternComponent, PdfService, PermissionCatalogService, PermissionSelectorComponent, PermissionsModalComponent, PermissionsViewComponent, PhoneDisplayComponent, PhoneFormatService, PhoneInputComponent, PickerV2Component, PillComponent, PinInputComponent, PlainCodeBoxComponent, PopoverSelectorComponent, PreferencesService, PreferencesViewComponent, PresetService, PriceTagComponent, PricingTableComponent, ProcessLinksPipe, ProfileContentComponent, ProfileModalComponent, ProfileSkeletonComponent, ProfileViewComponent, ProgressBarComponent, ProgressRingComponent, ProgressStatusComponent, PrompterComponent, QR_PRESETS, QrCodeComponent, QrGeneratorService, QrScannerComponent, QueryBuilder, QuoteBoxComponent, REQUEST_STATUSES, RadioInputComponent, RangeInputComponent, RatingComponent, ReactionBarComponent, ReactionsService, RefresherComponent, RequestFirestoreService, RequestFormBuilderService, RequestFormComponent, RequestModalComponent, RequestService, RetroAudioService, RightsFooterComponent, RotatingTextComponent, SEARCH_HEADER_DEFAULTS, SETTINGS_SECTIONS_CATALOG, SHAPE_KEYS, SHARE_PROFILE_MODAL_DEFAULTS, SKELETON_LAYOUT_DEFAULT_ROWS, SKELETON_PRESETS, SOLID_KEYS, STATS_BAR_DEFAULTS, STROKE_KEYS, SearchHeaderComponent, SearchSelectorComponent, SearchbarComponent, SectionHeaderComponent, SecurityViewComponent, SegmentControlComponent, SelectSearchComponent, SessionListModalComponent, SessionService, SessionTransitionOverlayComponent, SettingsHubComponent, ShareButtonsComponent, ShareProfileModalComponent, SimonGameComponent, SimpleComponent, SkeletonComponent, SkeletonLayoutComponent, SkeletonService, SplashComponent, SplashScreenService, StatsBarComponent, StatsCardComponent, StepperComponent, StorageService, SwipeCarouselComponent, SwitchOrgModalComponent, TRI_KEYS, TabbedContentComponent, TableSkeletonComponent, TabsComponent, Terminal404Component, TestimonialCardComponent, TestimonialCarouselComponent, TextComponent, TextInputComponent, TextareaInputComponent, ThemeOption, ThemeService, ThreadPanelComponent, TicketCardComponent, TicketCardImageService, TimelineComponent, TitleBlockComponent, TitleComponent, ToastService, ToggleInputComponent, TokenService, ToolbarActionType, ToolbarComponent, TransferOwnershipModalComponent, TranslatePipe, TypedCollection, TypingIndicatorComponent, UPDATE_BANNER_DEFAULT_CONTENT, UPDATE_BANNER_I18N_NAMESPACE, UpdateBannerComponent, UsageMetersComponent, UsageService, UserAvatarComponent, UsernameInputComponent, VALTECH_ADS_CONFIG, VALTECH_APP_CONFIG, VALTECH_APP_VERSION, VALTECH_AUTH_CONFIG, VALTECH_CHAT_CONFIG, VALTECH_COMPANY_LINKS, VALTECH_CONTENT_CONFIG, VALTECH_DEBUG_CONSOLE, VALTECH_DEFAULT_CONTENT, VALTECH_DONATION_CONFIG, VALTECH_FEEDBACK_CONFIG, VALTECH_FIREBASE_CONFIG, VALTECH_FOOTER_I18N, VALTECH_FOOTER_LOGO, VALTECH_LANGUAGE_SELECTOR, VALTECH_LEGAL_CONFIG, VALTECH_NETWORK_ERROR_KEY, VALTECH_REACTIONS_CONFIG, VALTECH_SETTINGS_MENU_LINKS, VALTECH_SITE_PATHS, VALTECH_SOCIAL_LINKS, VALTECH_SPLASH_SCREEN, VALTECH_WEB_BASE_URLS, VALTECH_WHATSAPP_CONFIG, VERSION, ValtechErrorService, VerifyViewComponent, WhatsappFabComponent, WhatsappService, WizardComponent, WizardFooterComponent, WorkflowService, applyChessimalsMove, applyDefaultValueToControl, authGuard, authInterceptor, authPasswordValidator, beautifyLegalArticle, blogPost, buildCompanyFooterProps, buildFooterLinks, buildLegalLinkResolver, buildPath, buildSettingsCards, button, canSubmitRequestType, chooseChessimalsBotMove, collections, connectPageRefresh, createChessimalsGame, createChessimalsReviewState, createErrorStateProps, createFirebaseConfig, createGlowCardProps, createInitialDatasetState, createInitialPaginationState, createNumberFromToField, createPageState, createPermissionLabeler, createRefreshableStream, createTitleProps, datasetPageFromLegacyCursor, docs, errorLoggingInterceptor, extractPathParams, formatClockTime, formatDateSeparator, formatRelativeTime, generatePatternTiles, generateRandomTile, getAppInfo, getAppVersion, getChessimalsAllLegalMoves, getChessimalsLegalMoves, getChessimalsPieceAt, getCollectionPath, getDocumentId, getTimeOfDayKey, goToTop, groupPermissionsByScope, guestGuard, hasEmulators, iconButton, interpretError, isAtEnd, isCollectionPath, isDocumentPath, isEmulatorMode, isIonicColor, isKnownRoute, isValidPath, joinPath, maxLength, mulberry32, news, parseMarkdownArticle, permissionGuard, permissionGuardFromRoute, positionKey, provideLegalContent, provideSplashScreen, provideValtechAboutRoutes, provideValtechAccountRoutes, provideValtechAds, provideValtechApiKeysRoutes, provideValtechAppConfig, provideValtechAppVersion, provideValtechAppVersionHttp, provideValtechAuth, provideValtechAuthInterceptor, provideValtechChat, provideValtechContent, provideValtechDebugConsole, provideValtechDonations, provideValtechErrorHandling, provideValtechFeedback, provideValtechFirebase, provideValtechI18n, provideValtechLegal, provideValtechNotificationClickActions, provideValtechNotificationPreferencesRoutes, provideValtechNotificationsRoutes, provideValtechOrganizationRoutes, provideValtechPermissionsRoutes, provideValtechPreferencesRoutes, provideValtechPresets, provideValtechProfileRoutes, provideValtechReactions, provideValtechSecurityRoutes, provideValtechSettingsRoutes, provideValtechSite, provideValtechSkeleton, provideValtechWhatsapp, query, rbacGuard, renderPatternSvgInner, replaceSpecialChars, requestSubmitMode, resignChessimalsGame, resolveColor, resolveInputDefaultValue, resolveIonicColor, resolveWebBaseUrl, roleGuard, selectableRequestTypes, storagePaths, superAdminGuard, toArticle, validateRoutes };
88180
86135
  //# sourceMappingURL=valtech-components.mjs.map