/* ============================================================================
   game-starlock.css — visual layer owned exclusively by starlock.
   Loaded only on starlock pages, after site.css / themes.css / games.css, so rules
   here win without touching any shared stylesheet.

   Direction: a lacquered wooden puzzle box that lights up like a slot machine
   when a row locks in. states are calm, events are loud.
   ========================================================================== */

/* board hosts absolutely-positioned SVG overlays (conflict links, constellation) */
#board.grid{position:relative}

/* ============================================================================
   0. THE PUZZLE BOX
   The grid used to float on the page. It now sits INSIDE a lacquered wooden
   case: a stained frame with long grain and cathedral figure, a mitred bevel,
   a recessed well, and a soft inner shadow over the tiles so they read as
   sunk below the rim rather than printed on it.

   Every colour is mixed from the existing tokens (--surface-2, --bg-deep,
   --gold, --line), so arm B (neon) re-stains the wood hot and arm C (paper)
   re-stains it as pale birch — nothing here assumes dark mode.
   ========================================================================== */
body[data-game=starlock] #stage{
  --wood:color-mix(in oklch, var(--surface-2), var(--gold) 15%);
  --wood-lt:color-mix(in oklch, var(--wood), white 18%);
  --wood-dk:color-mix(in oklch, var(--bg-deep), var(--gold) 7%);
  position:relative;
  overflow:hidden;                       /* keeps the sheen sweep inside the case */
  padding:clamp(1rem,3.4vw,1.9rem);
  background:
    /* lacquer highlight, top-left */
    radial-gradient(130% 85% at 20% -14%, color-mix(in oklch,white,transparent 86%), transparent 58%),
    /* long grain */
    repeating-linear-gradient(93deg,
      color-mix(in oklch,var(--wood-dk),transparent 74%) 0 2px,
      transparent 2px 7px,
      color-mix(in oklch,var(--wood-lt),transparent 82%) 7px 8px,
      transparent 8px 18px),
    /* cathedral figure rising from the base */
    radial-gradient(180% 62% at 50% 122%, color-mix(in oklch,var(--wood-dk),transparent 42%), transparent 64%),
    linear-gradient(163deg, var(--wood-lt), var(--wood) 38%, var(--wood-dk));
  box-shadow:
    var(--sh-3),
    inset 0 1px 0 color-mix(in oklch,white,transparent 80%),
    inset 0 -2px 0 color-mix(in oklch,black,transparent 72%),
    inset 0 0 0 1px color-mix(in oklch,black,transparent 78%);
}
/* the well the grid drops into — spread rings only, so nothing reflows */
:root body[data-game=starlock] #board.grid{
  box-shadow:
    0 0 0 1px color-mix(in oklch,black,transparent 52%),
    0 0 0 5px color-mix(in oklch,var(--wood-dk),transparent 14%),
    0 0 0 6px color-mix(in oklch,var(--wood-lt),transparent 58%),
    0 10px 26px -8px rgb(0 0 0/.55);
}
/* inner shadow ON TOP of the tiles (an inset shadow on #board would sit under
   them) — this is what makes the grid look contained rather than pasted on */
body[data-game=starlock] #board.grid::after{
  content:'';position:absolute;inset:0;z-index:4;pointer-events:none;
  border-radius:inherit;
  box-shadow:
    inset 0 0 0 1px rgb(0 0 0/.34),
    inset 0 3px 12px rgb(0 0 0/.50),
    inset 0 -7px 20px rgb(0 0 0/.26);
}
/* slow lacquer sheen crossing the case — opacity + transform only */
body[data-game=starlock] #stage::after{
  content:'';position:absolute;inset:-10%;z-index:0;pointer-events:none;opacity:0;
  background:linear-gradient(104deg,
    transparent 33%,
    color-mix(in oklch,white,transparent 91%) 47%,
    transparent 61%);
}
@media (prefers-reduced-motion: no-preference){
  body[data-game=starlock]:not([data-fx=off]) #stage::after{
    animation:sl-lacquer 13s ease-in-out infinite;
  }
}
@keyframes sl-lacquer{
  0%,100%{opacity:0;transform:translateX(-9%)}
  50%{opacity:.6;transform:translateX(9%)}
}

/* ---------- 1. tile-ified cells ----------
   Each cell gets an inner rounded lacquered tile: lighter top, 1px dark inner
   keyline, ~4px radius — layered over the region colour (--gl/--gh) which stays
   on the cell itself. Walls (box-shadow on the cell) are untouched. */
#board.grid .cell::before{
  content:'';position:absolute;inset:2px;border-radius:4px;pointer-events:none;
  background:linear-gradient(180deg,rgb(255 255 255/.12),rgb(255 255 255/.03) 42%,rgb(0 0 0/.14));
  box-shadow:
    inset 0 0 0 1px rgb(0 0 0/.38),
    inset 0 1px 0 rgb(255 255 255/.10);
  transition:box-shadow 260ms var(--ease-out);
}

/* ---------- 2. star glyph (inline SVG, injected from JS) ---------- */
#board.grid .glyph{position:relative;z-index:2}
#board.grid .glyph svg{display:block;width:clamp(1.1rem,4.6vw,2rem);height:auto;overflow:visible}
#board.grid .cell[data-v="2"] .glyph{
  filter:drop-shadow(0 1px 2px rgb(0 0 0/.5)) drop-shadow(0 0 10px oklch(0.9 0.18 95/.7));
}
/* retarget the pop-in from the span to the svg */
@media(prefers-reduced-motion:no-preference){
  #board.grid .cell[data-v="2"] .glyph{animation:none}
  #board.grid .cell[data-v="2"] .glyph svg{animation:starIn 320ms var(--ease-pop)}
}

/* ---------- 3. mark = small round dark dot (✕ is reserved for traps) ---------- */
#board.grid .cell[data-v="1"] .glyph{opacity:.85;font-size:inherit}
#board.grid .glyph .dot{
  display:block;width:8px;height:8px;border-radius:50%;
  background:oklch(0.22 0.01 260);
  box-shadow:inset 0 1px 1.5px rgb(0 0 0/.65),0 1px 0 rgb(255 255 255/.14);
}

/* ---------- 4. completion lighting ----------
   .shine is a per-cell overlay the JS pulses down a satisfied line (18ms stagger);
   [data-done="1"] settles the tile with a 1px gold inner edge via the ::before
   transition above. */
#board.grid .cell .shine{
  position:absolute;inset:2px;border-radius:4px;pointer-events:none;opacity:0;z-index:1;
  background:linear-gradient(180deg,rgb(255 255 255/.8),rgb(255 255 255/.28));
}
@media(prefers-reduced-motion:no-preference){
  #board.grid .cell.sweep .shine{animation:sl-shine 200ms var(--ease-out)}
  @keyframes sl-shine{0%{opacity:0}35%{opacity:.55}100%{opacity:0}}
}
#board.grid .cell[data-done="1"]::before{
  box-shadow:
    inset 0 0 0 1px color-mix(in oklch,var(--gold),transparent 28%),
    inset 0 1px 0 rgb(255 255 255/.10);
}

/* ---------- 5. conflict connector + 7. constellation overlays ---------- */
#board.grid .sl-overlay{
  position:absolute;inset:0;width:100%;height:100%;pointer-events:none;z-index:5;overflow:visible;
}
#board.grid .sl-overlay .clink{
  fill:none;stroke:color-mix(in oklch,var(--gold),var(--hazard) 55%);
  stroke-width:2;stroke-dasharray:6 5;stroke-linecap:round;
  transition:opacity 300ms var(--ease-out);
}
#board.grid .sl-overlay .lockline{
  fill:none;stroke:var(--gold);stroke-width:3;stroke-linecap:round;stroke-linejoin:round;
  filter:drop-shadow(0 0 8px oklch(0.85 0.16 90/.8));
}

/* ---------- 5b. keyboard focus must beat the case overlay ----------
   `#board.grid::after` is a full-board inner-shadow overlay at z-index 4 that
   paints ON TOP of every tile — that is what makes the grid look contained.
   It also painted on top of the focus ring, so tabbing across an 8×8 Starlock
   grid produced a ring that was drawn and then covered: a keyboard player
   could not see which cell they were on. Lifting the focused cell (and only
   the focused cell) above the overlay fixes it without changing the case.
   Audited 2026-08-04 — nothing in this file removes an outline. */
#board.grid .cell:focus-visible{
  position:relative;
  z-index:5;
}

/* ---------- 6. cell press feel ---------- */
@media(prefers-reduced-motion:no-preference){
  #board.grid .cell{
    transition:background var(--t-fast) var(--ease-out),transform 240ms var(--ease-pop);
  }
  #board.grid .cell:active{transform:scale(.92);transition-duration:var(--t-fast),60ms}
}

/* ---------- 7. LOCKED stamp (chrome poster type, springs in, gone ≤700ms) ---------- */
#board.grid .lockstamp{
  position:absolute;inset:0;display:grid;place-items:center;z-index:6;pointer-events:none;
}
#board.grid .lockstamp span{font-size:2.8rem}
@media(prefers-reduced-motion:no-preference){
  #board.grid .lockstamp span{animation:sl-lock 700ms var(--ease-pop) both}
  @keyframes sl-lock{
    0%{transform:scale(.3) skewX(-6deg);opacity:0}
    45%{transform:scale(1.1) skewX(-6deg);opacity:1}
    72%{transform:scale(1) skewX(-6deg);opacity:1}
    100%{transform:scale(1) skewX(-6deg);opacity:0}
  }
}

/* ---------- fx-off kill switch: everything decorative goes still ---------- */
body[data-fx=off] #board.grid .cell,
body[data-fx=off] #board.grid .cell::before,
body[data-fx=off] #board.grid .glyph svg,
body[data-fx=off] #board.grid .cell .shine,
body[data-fx=off] #board.grid .lockstamp span,
body[data-fx=off] #board.grid .sl-overlay .clink{
  animation:none!important;transition:none!important;
}

/* ---------- difficulty + par strip (shown before the clock starts) ---------- */
.sl-diffbar{
  display:flex;align-items:center;justify-content:center;gap:.5rem;
  font-family:var(--mono);font-size:.68rem;font-weight:600;
  letter-spacing:.16em;text-transform:uppercase;color:var(--muted);
  margin:0 0 .55rem;user-select:none;min-height:1em;
}
.sl-diff-stars{color:var(--gold);letter-spacing:.06em}
.sheet .sl-diff,.sheet .sl-pace{margin:.5rem 0 0;line-height:1.45}
.sheet .sl-pace b{font-family:var(--mono);letter-spacing:.12em}
#undo[disabled]{opacity:.38;pointer-events:none}

/* placeholder while a large grid is being proved unique (9×9 and 10×10 only) */
.sl-building{
  display:grid;place-items:center;min-height:min(560px,72svh);
  color:var(--muted);font-family:var(--mono);font-size:.86rem;text-align:center;padding:1rem;
}
