/* Tablero: una parcela de campo vista desde arriba (césped segado, green, búnkeres, portales) */
#boardArea { position: relative; width: max-content; margin: 0 auto; }
#board { display: grid; gap: 3px; border-radius: 8px; padding: 3px; background: var(--grout); /* junta entre casillas */ }

/* capa de piezas móviles (pelotas y hoyo) sobre la cuadrícula */
#pieces { position: absolute; inset: 0; pointer-events: none; z-index: 5; }
.piece {
  position: absolute; top: 0; left: 0;
  width: var(--cell-w); height: var(--cell-h);
  display: flex; align-items: center; justify-content: center;
  will-change: transform;
}
.piece .cardOnCell { transition: transform .15s var(--ease-out); }
.hitFlash { box-shadow: 0 0 0 4px rgba(241,241,220,.95) !important; border-radius: 50%; }
.tilePop { animation: tilePop .3s var(--ease-out); }
@keyframes tilePop { from { transform: scale(.7); opacity: 0; } to { transform: scale(1); opacity: 1; } }

.cell {
  width: var(--cell-w); height: var(--cell-h);
  border-radius: 5px;
  /* casillas alternas en bandas diagonales de segado + grano */
  background-image: var(--grain); background-color: var(--grass-dark);
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  position: relative; user-select: none;
  box-shadow: inset 0 1px 0 rgba(255,255,255,.06);
  transition: background-color .2s var(--ease-out), box-shadow .2s;
}
/* columna de PAR: franja más clara, como marcas pintadas en el césped */
.cell.mowB { background-color: var(--grass-mid); }
.cell.par { background-color: var(--par-cell); }
.cell.cement { background-color: var(--cement-cell); }
.cell.sand { background-color: var(--sand-cell); }
.cell .parLabel {
  position: absolute; top: 5px; left: 0; right: 0; text-align: center;
  font-size: calc(var(--cell-w) * 0.16); font-weight: 500; letter-spacing: .12em;
  color: var(--on-grass);
}
/* casillas válidas: green claro */
.cell.selectable { background-color: var(--sel-cell); cursor: pointer; z-index: 2;
  box-shadow: inset 0 0 0 1.5px rgba(241,241,220,.55);
  animation: selPulse 1.8s ease-in-out infinite; }
@keyframes selPulse { 0%, 100% { background-color: var(--sel-cell); } 50% { background-color: var(--green-light); } }
.cell.selectable:hover { background-color: var(--green-light); animation: none; box-shadow: inset 0 0 0 2px var(--cream); }
.cell.selectable-out { cursor: pointer; z-index: 2;
  background-color: rgba(217,96,58,.22); box-shadow: inset 0 0 0 1.5px rgba(217,96,58,.7);
  background-image: repeating-linear-gradient(135deg, rgba(241,241,220,.18) 0 4px, transparent 4px 9px);
  animation: selOutPulse 1.8s ease-in-out infinite; }
@keyframes selOutPulse { 50% { box-shadow: inset 0 0 0 2px rgba(217,96,58,.95); } }
.cell.selectable-out:hover { background-color: rgba(217,96,58,.38); animation: none; }

/* salidas: tees crema con el anillo del color del jugador */
.spawnMark {
  position: absolute; left: 50%; top: 50%; transform: translate(-50%,-50%);
  width: 9px; height: 9px; border-radius: 50%;
  background: var(--cream); opacity: .85;
  box-shadow: 0 0 0 2px var(--pc, var(--cream-line)), 0 1.2px 3.6px 1px var(--shadow);
  z-index: 1;
}
.spawnMark.holeMark {
  width: 12px; height: 12px; background: transparent; opacity: .7;
  box-shadow: inset 0 0 0 2px rgba(241,241,220,.8);
}

/* piezas y losetas sobre la casilla */
.cardOnCell {
  width: calc(var(--cell-w) - 6px); height: calc(var(--cell-h) - 6px);
  border-radius: 8px;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  font-size: calc(var(--cell-w) * 0.38);
  position: relative;
}
.cardOnCell .sub {
  position: absolute; bottom: 5%; left: 0; right: 0; text-align: center;
  font-size: calc(var(--cell-w) * 0.13); font-weight: 500; letter-spacing: .12em; color: rgba(36,36,36,.55);
}
.tilePic, .holeSvg { width: 100%; height: 100%; display: block; overflow: visible; }
/* hoyo: green circular con agujero y bandera (SVG en art.js) */
.tile-hole { width: var(--cell-w); height: var(--cell-h); background: transparent; }
.tile-bunker { background: transparent; }
.tile-bunker .tilePic { transform: scale(1.28) translateY(-3%); }
.tile-portal { background: transparent; }
.tile-portal .sub { color: rgba(241,241,220,.75); }
/* pelotas: círculos planos de su color con sombra corta diagonal */
.tile-ball { background: transparent; }
/* pelotas de golf de verdad en el color de cada jugador: hoyuelos, brillo, sombreado esférico
   y sello "J1" impreso en el centro */
.tile-ball .circ {
  --pc: #888;
  width: 64%; aspect-ratio: 1; border-radius: 50%; position: relative;
  display: flex; align-items: center; justify-content: center;
  background-color: var(--pc);
  /* todo liso: brillo como círculo plano, hoyuelos como puntos planos, sombra de volumen como media luna dura */
  background-image:
    radial-gradient(circle at 31% 27%, rgba(255,255,255,.5) 0 12%, transparent 12.5%),
    radial-gradient(circle, rgba(0,0,0,.12) 0 .7px, transparent .8px);
  background-size: 100% 100%, 3.6px 3.6px;
  box-shadow: 0 2.4px 7.2px var(--shadow), inset -3px -3px 0 rgba(0,0,0,.14);
}
.ballStamp {
  display: flex; align-items: center; justify-content: center;
  min-width: 58%; height: 38%; padding: 0 3px; border-radius: 999px;
  background: rgba(255,255,255,.92); color: color-mix(in srgb, var(--pc) 70%, #1a1a1a);
  font-weight: 700; font-size: calc(var(--cell-w) * 0.15); letter-spacing: .01em; line-height: 1;
  box-shadow: inset 0 -1px 0 rgba(0,0,0,.12);
}
/* pelota de obstáculo: blanca grisácea (--pc, pColor) y sin etiqueta de jugador ni forma */
.piece.decoyBall .ballStamp, .piece.decoyBall .shp { display: none; }
.badge {
  position: absolute; bottom: 3px; right: 3px; z-index: 6;
  width: 18px; height: 18px; border-radius: 50%; display: flex; align-items: center; justify-content: center;
  background: var(--sand); color: var(--ink); font-size: 11px;
}

/* ---- arte bitmap (assets/art/*.png); si no existe el PNG se usa el fallback SVG ---- */
.card .cardArt { width: 62%; height: auto; }
.artCard { padding: 0; overflow: hidden; position: relative; }
.artCard img.fill { width: 100%; height: 100%; object-fit: cover; border-radius: inherit; display: block; }
.ballTag {
  position: absolute; bottom: 3px; right: 3px; z-index: 2;
  font-size: calc(var(--cell-w) * 0.17); font-weight: 600; color: #fff;
  border-radius: 6px; padding: 0 4px;
}

/* portal: anillos concéntricos que nacen en el centro y crecen hasta el borde, desvaneciéndose
   (escala <= 1: nunca se salen de la esfera; el trazo no engorda al crecer) */
.portalRing { transform-origin: 50px 70px; transform-box: view-box; vector-effect: non-scaling-stroke; opacity: 0;
  animation: portalRing 3s cubic-bezier(.25,.6,.4,1) infinite; }
.cardSvg .portalRing { transform-origin: 50px 54px; }
.portalRing:nth-child(2) { animation-delay: -1s; }
.portalRing:nth-child(3) { animation-delay: -2s; }
@keyframes portalRing { 0% { transform: scale(.08); opacity: 0; } 18% { opacity: .95; } 100% { transform: scale(1); opacity: 0; } }
.portalCore { transform-origin: 50px 70px; transform-box: view-box; animation: portalCore 3s ease-in-out infinite; }
.cardSvg .portalCore { transform-origin: 50px 54px; }
@keyframes portalCore { 50% { transform: scale(1.25); } }
@media (prefers-reduced-motion: reduce) {
  .portalRing, .portalCore { animation: none; }
  .portalRing { opacity: .5; } .portalRing:nth-child(1) { transform: scale(.35); } .portalRing:nth-child(2) { transform: scale(.68); }
}

/* ---------- agua (baraja de agua) ----------
   río: agua clara que baja (chevrones en movimiento); lago: agua profunda y quieta con reflejos
   y nenúfar. Las casillas vecinas del mismo tipo se unen por encima de la junta (wN/wS/wW/wE). */
.cell.water { overflow: visible; }
.cell.river { background-color: #5BB6D6; background-image: linear-gradient(90deg, rgba(20,80,110,.25), transparent 22%, transparent 78%, rgba(20,80,110,.25));
  box-shadow: inset 0 0 0 2px rgba(255,255,255,.18); }
.cell.lake { background-color: #2E7E8C; background-image: radial-gradient(ellipse at 35% 30%, rgba(255,255,255,.14), transparent 60%);
  box-shadow: inset 0 0 0 3px rgba(18,70,80,.35), inset 0 0 14px rgba(10,40,50,.35); border-radius: 12px; }
.cell.water::before, .cell.water::after { content: ''; position: absolute; pointer-events: none; background: inherit; z-index: 0; }
.cell.water.wS::after { left: 0; right: 0; bottom: -6px; height: 10px; background-color: inherit; }
.cell.water.wE::before { top: 0; bottom: 0; right: -6px; width: 10px; background-color: inherit; }
.cell.lake.wS::after, .cell.lake.wE::before { background-image: none; }
.cell.river.wN { border-top-left-radius: 0; border-top-right-radius: 0; }
.cell.river.wS { border-bottom-left-radius: 0; border-bottom-right-radius: 0; }
.cell.lake.wN { border-top-left-radius: 0; border-top-right-radius: 0; } .cell.lake.wS { border-bottom-left-radius: 0; border-bottom-right-radius: 0; }
.cell.lake.wW { border-top-left-radius: 0; border-bottom-left-radius: 0; } .cell.lake.wE { border-top-right-radius: 0; border-bottom-right-radius: 0; }
/* nacimiento (manantial) y desembocadura (espuma) del río */
.cell.river.rSrc { background-image: radial-gradient(ellipse 60% 30% at 50% 0, rgba(255,255,255,.45), transparent 70%), linear-gradient(90deg, rgba(20,80,110,.25), transparent 22%, transparent 78%, rgba(20,80,110,.25)); }
.cell.river.rEnd { background-image: radial-gradient(ellipse 70% 26% at 50% 100%, rgba(255,255,255,.55), transparent 70%), linear-gradient(90deg, rgba(20,80,110,.25), transparent 22%, transparent 78%, rgba(20,80,110,.25)); }
.cell.water > * { position: relative; z-index: 1; }
.tile-river, .tile-lake { background: transparent; width: 100%; height: 100%; }
.tile-river .sub, .tile-lake .sub { color: rgba(241,251,255,.8); }
.riverPic { overflow: hidden; }
.riverFlow { animation: riverFlow 1.4s linear infinite; }
@keyframes riverFlow { from { transform: translateY(0); } to { transform: translateY(46px); } }
.lakeShine { transform-box: fill-box; transform-origin: center; animation: lakeShine 4.5s ease-in-out infinite; }
.lakeShine.b { animation-delay: -2.2s; }
@keyframes lakeShine { 50% { transform: scaleX(1.25); opacity: .45; } }
@media (prefers-reduced-motion: reduce) { .riverFlow, .lakeShine { animation: none; } }
html.reduceMotion .riverFlow, html.reduceMotion .lakeShine { animation: none; }
.cardSvg .riverFlow { animation-name: riverFlowCard; }
@keyframes riverFlowCard { from { transform: translateY(0); } to { transform: translateY(30px); } }
/* (colores del agua en una variable: la casilla y sus puentes sobre la junta usan el mismo) */
.cell.river { --wc: #5BB6D6; } .cell.lake { --wc: #2E7E8C; }
.cell.river.selectable { --wc: #6FC3E0; } .cell.lake.selectable { --wc: #3A93A2; }
:is(#board, #edBoard) .cell.water { background-color: var(--wc); }
:is(#board, #edBoard) .cell.water.wS::after { background: var(--wc); left: 0; right: 0; bottom: -7px; height: 12px; }
:is(#board, #edBoard) .cell.water.wE::before { background: var(--wc); top: 0; bottom: 0; right: -7px; width: 12px; }
:is(#board, #edBoard) .cell.river.wS::after { left: 0; right: 0; }
.tile-river .sub, .tile-lake .sub { display: none; }
:is(#board, #edBoard) .cell.river { box-shadow: none; }
:is(#board, #edBoard) .cell.river.wS::after { background-image: linear-gradient(90deg, rgba(20,80,110,.25), transparent 22%, transparent 78%, rgba(20,80,110,.25)); }
:is(#board, #edBoard) .cell.lake { box-shadow: none; background-image: radial-gradient(ellipse at 35% 30%, rgba(255,255,255,.12), transparent 60%); }
:is(#board, #edBoard) .cell.lake:not(.wN):not(.wS):not(.wW):not(.wE) { box-shadow: inset 0 0 0 3px rgba(18,70,80,.3); }
.cell.lake:not(.lPad) .lakePic g { display: none; }
.cardSvg:has(.riverFlow) { overflow: hidden; border-radius: 6px; }

/* corriente del río: chevrones finos en un patrón continuo en coordenadas del tablero (cada casilla
   lo desplaza por su fila), así los tramos seguidos, y los puentes sobre la junta, encajan sin cortes.
   El reloj (--flow) se anima en cada casilla de río, no en todo el tablero: animar una variable heredada en
   #board obligaba a recalcular las 247 casillas de Ultimate en cada fotograma (la partida iba a tirones).
   Avanza a saltos de 1 px (igual de fluido) y todas van en fase: cada casilla nueva empieza con un retraso
   negativo según el reloj de la página (--wd, board.js), así un tramo puesto más tarde encaja con los demás */
@property --flow { syntax: '<length>'; inherits: true; initial-value: 0px; }
:is(#board, #edBoard) .cell.river { animation: riverClock 1.6s steps(28) infinite; animation-delay: var(--wd, 0s); }
@keyframes riverClock { to { --flow: 28px; } }
:is(#board, #edBoard) .cell.river {
  --step: calc(var(--cell-h) + 3px); --off: calc(var(--row) * var(--step) * -1 + var(--flow));
  background-image:
    url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='20' height='28'><path d='M5 10l5 4 5-4' fill='none' stroke='white' stroke-opacity='.5' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/></svg>"),
    linear-gradient(90deg, rgba(20,80,110,.22), transparent 24%, transparent 76%, rgba(20,80,110,.22));
  background-size: 20px 28px, 100% 100%;
  background-repeat: repeat-y, no-repeat;
  background-position: center var(--off), 0 0;
}
:is(#board, #edBoard) .cell.river.wS::after {
  background-image: inherit; background-size: 20px 28px, 100% 100%; background-repeat: repeat-y, no-repeat;
  background-position: center calc(var(--off) - var(--cell-h) + 5px), 0 0;
}
/* nacimiento y desembocadura: un velo de espuma encima (sin tapar la corriente) */
:is(#board, #edBoard) .cell.river.rSrc > .tile-river { background: radial-gradient(ellipse 60% 26% at 50% 0, rgba(255,255,255,.4), transparent 70%); }
:is(#board, #edBoard) .cell.river.rEnd > .tile-river { background: radial-gradient(ellipse 70% 24% at 50% 100%, rgba(255,255,255,.5), transparent 70%); }
:is(#board, #edBoard) .cell.river.rSrc.rEnd > .tile-river { background: radial-gradient(ellipse 60% 26% at 50% 0, rgba(255,255,255,.4), transparent 70%), radial-gradient(ellipse 70% 24% at 50% 100%, rgba(255,255,255,.5), transparent 70%); }
:is(#board, #edBoard) .cell.river > .tile-river { position: absolute; inset: 0; width: auto; height: auto; border-radius: inherit; }
@media (prefers-reduced-motion: reduce) { :is(#board, #edBoard) .cell.river { animation: none; } }
html.reduceMotion :is(#board, #edBoard) .cell.river { animation: none; }

/* ---------- lago continuo ----------
   El agua es un solo patrón en coordenadas del tablero (--col/--row): reflejos suaves y ondas que
   derivan despacio con un reloj común (--lflow). Borde oscuro solo en la orilla exterior (lados sin
   vecina de lago) y los bloques 2×2 rellenan también la esquina de la junta (wSE). */
@property --lflow { syntax: '<length>'; inherits: true; initial-value: 0px; }
:is(#board, #edBoard) .cell.lake { animation: lakeClock 36s steps(90) infinite; animation-delay: var(--wd, 0s); } /* (en cada casilla: ver el río) */
@keyframes lakeClock { to { --lflow: 180px; } }
:is(#board, #edBoard) .cell.lake {
  --stepX: calc(var(--cell-w) + 3px); --stepY: calc(var(--cell-h) + 3px);
  --ox: calc(var(--col) * var(--stepX) * -1 + var(--lflow)); --oy: calc(var(--row) * var(--stepY) * -1);
  --lakeTex: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='180' height='150'><g fill='white'><ellipse cx='30' cy='26' rx='20' ry='3.2' fill-opacity='.16'/><ellipse cx='112' cy='18' rx='12' ry='2.2' fill-opacity='.11'/><ellipse cx='146' cy='82' rx='22' ry='3.4' fill-opacity='.14'/><ellipse cx='64' cy='104' rx='15' ry='2.6' fill-opacity='.12'/><ellipse cx='16' cy='132' rx='10' ry='2' fill-opacity='.1'/></g><g fill='none' stroke='white' stroke-opacity='.08' stroke-width='1.4'><path d='M78 58q14-6 28 0'/><path d='M120 134q12-5 24 0'/><path d='M8 76q10-4 20 0'/></g></svg>");
  /* segunda capa: destellos finos que van al revés y más despacio (el agua parece moverse en dos planos) */
  --lakeGlint: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='140' height='120'><g fill='white'><ellipse cx='22' cy='64' rx='9' ry='1.4' fill-opacity='.2'/><ellipse cx='96' cy='30' rx='6' ry='1.1' fill-opacity='.18'/><ellipse cx='118' cy='98' rx='8' ry='1.3' fill-opacity='.16'/><ellipse cx='58' cy='12' rx='5' ry='1' fill-opacity='.14'/></g></svg>");
  --gx: calc(var(--col) * var(--stepX) * -1 - var(--lflow) * .55 + 40px); --gy: calc(var(--oy) + 30px);
  background-image: var(--lakeTex), var(--lakeGlint); background-size: 180px 150px, 140px 120px; background-repeat: repeat;
  background-position: var(--ox) var(--oy), var(--gx) var(--gy);
  --eN: 3px; --eS: 3px; --eW: 3px; --eE: 3px;
  box-shadow: inset 0 var(--eN) 0 rgba(18,62,72,.45), inset 0 calc(var(--eS) * -1) 0 rgba(18,62,72,.45),
    inset var(--eW) 0 0 rgba(18,62,72,.45), inset calc(var(--eE) * -1) 0 0 rgba(18,62,72,.45) !important;
}
:is(#board, #edBoard) .cell.lake.wN { --eN: 0px; } :is(#board, #edBoard) .cell.lake.wS { --eS: 0px; } :is(#board, #edBoard) .cell.lake.wW { --eW: 0px; } :is(#board, #edBoard) .cell.lake.wE { --eE: 0px; }
:is(#board, #edBoard) .cell.lake.wS::after {
  background-color: var(--wc); background-image: var(--lakeTex), var(--lakeGlint); background-size: 180px 150px, 140px 120px;
  background-position: var(--ox) calc(var(--oy) - var(--cell-h) + 5px), var(--gx) calc(var(--gy) - var(--cell-h) + 5px);
  /* orilla en los lados del puente que dan al césped */
  box-shadow: inset 3px 0 0 rgba(18,62,72,.45), inset -3px 0 0 rgba(18,62,72,.45);
}
:is(#board, #edBoard) .cell.lake.wS.wW::after { box-shadow: inset -3px 0 0 rgba(18,62,72,.45); }
:is(#board, #edBoard) .cell.lake.wS.wE::after { box-shadow: inset 3px 0 0 rgba(18,62,72,.45); }
:is(#board, #edBoard) .cell.lake.wS.wW.wE::after { box-shadow: none; }
:is(#board, #edBoard) .cell.lake.wSE::after { right: -7px; box-shadow: none; } /* bloque 2×2: rellena también la esquina */
:is(#board, #edBoard) .cell.lake.wE::before {
  background-color: var(--wc); background-image: var(--lakeTex), var(--lakeGlint); background-size: 180px 150px, 140px 120px;
  background-position: calc(var(--ox) - var(--cell-w) + 5px) var(--oy), calc(var(--gx) - var(--cell-w) + 5px) var(--gy);
  box-shadow: inset 0 3px 0 rgba(18,62,72,.45), inset 0 -3px 0 rgba(18,62,72,.45);
}
:is(#board, #edBoard) .cell.lake.wE.wN::before { box-shadow: inset 0 -3px 0 rgba(18,62,72,.45); }
:is(#board, #edBoard) .cell.lake.wE.wS::before { box-shadow: inset 0 3px 0 rgba(18,62,72,.45); }
:is(#board, #edBoard) .cell.lake.wE.wN.wS::before { box-shadow: none; }
/* el nenúfar se mece despacio (cada uno a su ritmo, según su casilla) */
.cell.lake .padBob { transform-box: fill-box; transform-origin: 30% 60%; animation: padBob 7s ease-in-out infinite; animation-delay: calc(var(--col) * -1.3s - var(--row) * .7s); }
@keyframes padBob { 0%, 100% { transform: rotate(-4deg) translate(0, 0); } 50% { transform: rotate(5deg) translate(1.5px, -1px); } }
@media (prefers-reduced-motion: reduce) { :is(#board, #edBoard) .cell.lake { animation: none; } .cell.lake .padBob { animation: none; } }
html.reduceMotion .cell.lake .padBob { animation: none; }
html.reduceMotion :is(#board, #edBoard) .cell.lake { animation: none; }

/* ---------- piezas de madera (baraja de minigolf) ---------- */
.cell.wood { overflow: visible; }
.tile-block, .tile-corner, .tile-tunnel, .tile-launcher { background: transparent; width: 100%; height: 100%; }
.tile-block .sub, .tile-corner .sub, .tile-tunnel .sub, .tile-launcher .sub { display: none; }
.woodPic { overflow: visible; }
.lArrow { transform-box: view-box; transform-origin: 50px 66px; transform: rotate(var(--r)); animation: lSpin .5s cubic-bezier(.3,1.4,.5,1); }
@keyframes lSpin { from { transform: rotate(calc(var(--r) - 90deg)); } }
@media (prefers-reduced-motion: reduce) { .lArrow { animation: none; } }
html.reduceMotion .lArrow { animation: none; }
/* fantasma de la loseta a colocar (con su giro) */
.ghostTile { position: absolute; inset: 3px; opacity: 0; pointer-events: none; transition: opacity .15s; z-index: 2; }
.ghostTile .tilePic { width: 100%; height: 100%; }
.cell.selectable:hover .ghostTile, .cell.selectable:focus-visible .ghostTile { opacity: .7; }
.rotBtn { gap: 5px; } .rotBtn .i { width: 14px; height: 14px; }
/* pieza puesta de prueba: se ve fija, con un marco que late, hasta confirmarla */
.cell.staged .ghostTile, .ghostTile.on { opacity: .95 !important; }
.cell.staged { box-shadow: inset 0 0 0 2.5px #F1F1DC, 0 0 0 3px rgba(232,135,58,.8) !important; animation: stagedPulse 1.2s ease-in-out infinite !important; z-index: 3; }
@keyframes stagedPulse { 50% { box-shadow: inset 0 0 0 2.5px #F1F1DC, 0 0 0 5px rgba(232,135,58,.45); } }
