/* Dragondoku game layer — regions board, HUD, rules, pad.
   Loads AFTER theme.css. Palette tokens live in theme.css — this file only
   re-stamps them for html[data-theme] (the toggle marks <html>, theme.css
   only covers body[data-theme]) so the explicit toggle wins both directions. */

/* ---------- theme attribute on <html> beats the OS media query ---------- */
html[data-theme="light"] {
  --paper: #FDFBF7;
  --surface: #F5EEE3;
  --surface-2: #EFE6D6;
  --ink: #3D3229;
  --ink-soft: #8A7B6C;
  --accent: #E07A3F;
  --accent-deep: #C05F28;
  --accent-soft: #F6C9A4;
  --line: #E7DDCC;
  --line-strong: #B9A88E;
  --c-bad: #CF4B3E;
  --c-bad-bg: #F9DBD4;
  --ok: #5E8C4A;
  --shadow: 0 1px 2px rgba(61, 50, 41, 0.08), 0 4px 14px rgba(61, 50, 41, 0.07);
}

html[data-theme="dark"] {
  --paper: #221C17;
  --surface: #2B241D;
  --surface-2: #332B22;
  --ink: #F0E7DA;
  --ink-soft: #A2907C;
  --accent: #F0904D;
  --accent-deep: #F7A76B;
  --accent-soft: #6E4626;
  --line: #383026;
  --line-strong: #5C4D3B;
  --c-bad: #E56B5B;
  --c-bad-bg: #4A2A24;
  --ok: #93C47D;
  --shadow: 0 1px 2px rgba(0, 0, 0, 0.35), 0 4px 16px rgba(0, 0, 0, 0.3);
}

/* success token (new — not part of theme.css's palette) */
:root { --ok: #5E8C4A; }
@media (prefers-color-scheme: dark) { :root { --ok: #93C47D; } }

/* ---------- boot: hidden until JS is ready, fast fade on reveal ---------- */
.app {
  opacity: 1;
  transition: opacity 160ms ease-out;
}

body.booting .app { opacity: 0; }
body.booting .toast { display: none; }

/* slightly tighter gutters than theme's 12px — buys n=11 its 30px tap target */
.app {
  padding-left: calc(8px + env(safe-area-inset-left));
  padding-right: calc(8px + env(safe-area-inset-right));
}

/* ---------- HUD (topbar centre: Level / Time / Dragons) ---------- */
.hud {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  justify-content: center;
  align-items: center;
  gap: clamp(14px, 7vw, 34px);
  background: var(--surface);
  border-radius: 999px;
  padding: 5px 14px;
  box-shadow: var(--shadow);
}

.hud-stat {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1px;
  min-width: 0;
}

.hud-stat b {
  font-size: 1rem;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.01em;
  line-height: 1.1;
  color: var(--ink);
}

.hud-stat span {
  font-size: 0.55rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--ink-soft);
}

/* neutralise theme.css's old standalone #timer pill — it lives in the HUD now */
.hud #timer {
  margin: 0;
  padding: 0;
  background: none;
  border-radius: 0;
  font-size: 1rem;
  font-weight: 800;
  color: var(--ink);
}

/* ---------- rules pills ---------- */
.rules {
  display: flex;
  justify-content: center;
  flex-wrap: wrap;
  gap: 6px;
}

.rule {
  display: flex;
  align-items: center;
  gap: 6px;
  background: var(--surface);
  border-radius: 999px;
  padding: 6px 11px 6px 8px;
  font-size: clamp(0.62rem, 2.6vw, 0.72rem);
  font-weight: 600;
  color: var(--ink-soft);
  box-shadow: var(--shadow);
  white-space: nowrap;
}

.rule-ico {
  flex: 0 0 auto;
  width: 16px;
  height: 16px;
  border-radius: 5px;
  background: var(--surface-2);
}

/* four chalky quadrants = coloured regions */
.rule-ico[data-ico="region"] {
  background: conic-gradient(from 0deg at 50% 50%,
    #A9C7A0 0 25%, #E8BC82 0 50%, #9FB9D9 0 75%, #DBA3AB 0);
}

/* row + column cross */
.rule-ico[data-ico="line"] {
  background:
    linear-gradient(var(--accent), var(--accent)) 50% 0 / 3px 100% no-repeat,
    linear-gradient(var(--line-strong), var(--line-strong)) 0 50% / 100% 3px no-repeat,
    var(--surface-2);
}

/* two dragons sitting too close */
.rule-ico[data-ico="touch"] {
  background:
    radial-gradient(circle at 31% 31%, var(--accent) 0 3.4px, transparent 4.1px),
    radial-gradient(circle at 69% 69%, var(--ink-soft) 0 3.4px, transparent 4.1px),
    var(--surface-2);
}

/* ---------- board ---------- */
.board {
  display: grid;
  grid-template-columns: repeat(var(--n), 1fr);
  grid-template-rows: repeat(var(--n), 1fr);
}

#board.board {
  /* gap + heavy-edge width both scale down as n grows */
  --gap: max(1px, calc(12px / var(--n)));
  --bw: clamp(2px, calc(26px / var(--n)), 3.5px);
  --edge: var(--ink);
  --edge: color-mix(in srgb, var(--ink) 72%, transparent);
  width: min(100vw - 16px, calc(100vh - 20.5rem), 520px);
  width: min(100vw - 16px, calc(100dvh - 20.5rem), 520px);
  padding: var(--gap);
  gap: var(--gap);
  background: var(--surface);
  border: 1px solid var(--line);
}

/* ---------- cells ---------- */
.board .cell {
  position: relative;
  border: 0;                                /* kill theme.css sudoku hairlines */
  border-radius: 18%;
  background: var(--reg, var(--surface-2)); /* --reg set inline per tile by JS */
  color: var(--ink);
  min-width: 0;
  min-height: 0;
  user-select: none;
  -webkit-user-select: none;
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
  transition: transform var(--press) ease, box-shadow var(--snap) ease;
}

/* region boundaries: border drawn on an ::after box that reaches half the gap
   plus half the rule width past the tile — both neighbours' rules land on the
   exact same centred band, so shared borders never double up, and being
   absolutely positioned they never shift layout. */
.board .cell::after {
  content: "";
  position: absolute;
  inset: calc(-0.5 * (var(--gap) + var(--bw)));
  border: 0 solid var(--edge);
  border-radius: 1px;
  pointer-events: none;
  z-index: 2;
}

.board .cell.e-t::after { border-top-width: var(--bw); }
.board .cell.e-r::after { border-right-width: var(--bw); }
.board .cell.e-b::after { border-bottom-width: var(--bw); }
.board .cell.e-l::after { border-left-width: var(--bw); }

/* ---------- glyph ---------- */
.board .cell-glyph {
  width: 62%;
  height: 62%;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--ink);
  pointer-events: none;
  transition: opacity 140ms ease, transform 140ms ease;
}

.board .cell-glyph svg { width: 100%; height: 100%; display: block; }

/* text fallbacks if the glyph pack fails */
.fallback-num {
  font-size: clamp(12px, 5.4vmin, 26px);
  color: var(--ink);
}

.fallback-x {
  font-weight: 800;
  font-size: clamp(12px, 5.4vmin, 26px);
  line-height: 1;
  color: var(--ink);
  pointer-events: none;
}

/* ---------- cell states ---------- */
/* settled dragon */
.cell.has-dragon .cell-glyph {
  transform: scale(1.05);
  filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.28));
}

/* the ✕ is scaffolding, not an answer — keep it quiet */
.cell.has-mark .cell-glyph {
  opacity: 0.4;
  transform: scale(0.82);
}

/* correctly-placed dragon: gentle warm glow (inset — board clips overflow) */
.cell.lit {
  box-shadow:
    inset 0 0 0 2px var(--accent),
    inset 0 0 10px rgba(224, 122, 63, 0.35);
}

/* rule-breaking dragon: warm-red ring (JS pairs it with .shake) */
.cell.bad {
  box-shadow: inset 0 0 0 2.5px var(--c-bad);
}

.cell.bad .cell-glyph { color: var(--c-bad); }

.cell.shake { animation: meow-shake 140ms ease; }

/* placement pop */
.cell.placed .cell-glyph {
  animation: drag-pop 180ms cubic-bezier(0.34, 1.45, 0.64, 1);
}

@keyframes drag-pop {
  0% { transform: scale(0.4); }
  62% { transform: scale(1.16); }
  100% { transform: scale(1); }
}

/* ---------- bottom pad: Undo / Auto-X / Hint / New ---------- */
.pad {
  display: flex;
  justify-content: center;
  gap: 8px;
  padding: 0 2px 2px;
}

#pad .pad-key {
  position: relative;
  flex: 1 1 0;
  max-width: 92px;
  width: auto;
  height: 54px;
  padding: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 3px;
  border-radius: 16px;
  background: var(--surface);
  box-shadow: var(--shadow);
  color: var(--ink);
  transition: transform var(--press) ease, background var(--snap) ease, color var(--snap) ease;
}

#pad .pad-key:active {
  transform: scale(0.93) translateY(1px);
  background: var(--surface-2);
}

#pad .k-ico {
  font-size: 1.15rem;
  line-height: 1;
  pointer-events: none;
}

#pad .k-lab {
  font-size: 0.58rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--ink-soft);
  pointer-events: none;
}

/* active pill state (Auto-X toggle etc.) */
button.on,
#pad .pad-key.on {
  background: var(--accent);
  color: #FFF6EC;
}

#pad .pad-key.on .k-lab { color: rgba(255, 246, 236, 0.85); }

/* hint badge */
#pad .pad-count {
  position: absolute;
  top: 5px;
  right: 7px;
  bottom: auto;
  left: auto;
  min-width: 16px;
  height: 16px;
  padding: 0 4px;
  border-radius: 999px;
  background: var(--accent);
  color: #FFF6EC;
  font-size: 0.6rem;
  font-weight: 800;
  line-height: 16px;
  text-align: center;
}

/* ---------- hint line ---------- */
.hint-line {
  text-align: center;
  font-size: 0.72rem;
  font-weight: 500;
  color: var(--ink-soft);
  padding-bottom: 2px;
}

.hint-line b { color: var(--ink); font-weight: 700; }

/* ---------- win overlay extras ---------- */
.win-dragon {
  width: 76px;
  height: 76px;
  margin: 0 auto 12px;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--accent);
}

.win-dragon svg { width: 100%; height: 100%; }

.win-dragon:not(:empty) { animation: drag-pop 180ms cubic-bezier(0.34, 1.45, 0.64, 1); }

#win-sub {
  color: var(--ink-soft);
  font-size: 0.9rem;
  margin-bottom: 16px;
}

.btn-primary {
  width: 100%;
  height: 48px;
  border-radius: 14px;
  background: var(--accent);
  color: #FFF6EC;
  font-size: 1rem;
  font-weight: 700;
  transition: transform var(--press) ease, background var(--snap) ease;
}

.btn-primary:active { transform: scale(0.96); background: var(--accent-deep); }

.btn-ghost {
  width: 100%;
  height: 42px;
  margin-top: 8px;
  border-radius: 14px;
  background: transparent;
  color: var(--ink-soft);
  font-size: 0.85rem;
  font-weight: 700;
  transition: transform var(--press) ease, color var(--snap) ease;
}

.btn-ghost:active { transform: scale(0.96); color: var(--ink); }

/* ---------- fatal (engine failed to boot) ---------- */
.fatal {
  margin: auto;
  max-width: 300px;
  padding: 20px 22px;
  background: var(--surface);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  color: var(--ink);
  font-size: 0.9rem;
  font-weight: 600;
  line-height: 1.5;
  text-align: center;
}

/* ---------- narrow phones ---------- */
@media (max-width: 400px) {
  #size-seg button, #diff-seg button {
    padding: 6px 8px;
    font-size: 0.74rem;
  }
  .hud { gap: clamp(10px, 5vw, 20px); padding: 4px 10px; }
  .hud-stat b, .hud #timer { font-size: 0.92rem; }
  .rule { padding: 5px 9px 5px 7px; gap: 5px; }
}

@media (max-width: 340px) {
  #size-seg button, #diff-seg button { padding: 5px 6px; font-size: 0.7rem; }
  .rule-ico { width: 14px; height: 14px; }
}

/* ================= interaction layer (highlight / settle / confirm / auto-x) ================= */

/* glyph and edge rules must ride above the ::before overlay */
.board .cell-glyph { position: relative; z-index: 3; }

/* ---------- 1. hover / press highlight ----------
   ::before is the overlay lane (edges own ::after). Opacity-only transitions —
   this fires on every pointer move, so it has to be cheap and calm. */
.board .cell::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  pointer-events: none;
  z-index: 1;
  opacity: 0;
  transition: opacity 120ms ease;
}

/* everything NOT highlighted recedes under a paper wash (reads as desaturation) */
.board.focused .cell:not(.hl):not(.hl-line):not(.hl-reg)::before {
  background: var(--paper);
  opacity: 0.38;
}

/* row/column — faint lift */
.board.focused .cell.hl-line::before {
  background: rgba(255, 255, 255, 0.13);
  opacity: 1;
}

/* same region — stronger lift + soft inner ring */
.board.focused .cell.hl-reg::before {
  background: rgba(255, 255, 255, 0.2);
  box-shadow: inset 0 0 0 1.5px rgba(255, 255, 255, 0.4);
  opacity: 1;
}

/* the focused tile itself — strongest */
.board.focused .cell.hl::before {
  background: rgba(255, 255, 255, 0.28);
  box-shadow: inset 0 0 0 2px var(--accent);
  opacity: 1;
}

/* ---------- 2. spring settle on dragon placement ---------- */
@keyframes drag-settle {
  0%   { transform: scale(0.55); opacity: 0.35; }
  55%  { transform: scale(1.12); opacity: 1; }
  78%  { transform: scale(0.96); }
  100% { transform: scale(1); }
}

.cell.settling .cell-glyph {
  animation: drag-settle 220ms cubic-bezier(0.3, 1.2, 0.5, 1) both;
}

/* ---------- 3. confirm states ----------
   background-image overlay lane — ::before (highlight) and ::after (edges) stay free. */

/* row AND column satisfied — whisper of settling */
.cell.line-done {
  background-image: linear-gradient(
    color-mix(in srgb, var(--paper) 20%, transparent),
    color-mix(in srgb, var(--paper) 20%, transparent));
}

/* whole colour region satisfied — creamy settled wash, blob recedes */
.cell.reg-done {
  background-image: linear-gradient(
    color-mix(in srgb, var(--paper) 40%, transparent),
    color-mix(in srgb, var(--paper) 40%, transparent));
}

/* the dragon that satisfies region + row + column: glow + tick badge */
.cell.confirmed {
  box-shadow:
    inset 0 0 0 2px color-mix(in srgb, var(--ok) 75%, transparent),
    inset 0 0 9px color-mix(in srgb, var(--ok) 28%, transparent);
}

.cell.confirmed .cell-glyph::after {
  content: "\2713";
  position: absolute;
  top: -10%;
  right: -12%;
  width: 40%;
  height: 40%;
  min-width: 11px;
  min-height: 11px;
  border-radius: 999px;
  background: var(--ok);
  color: #FFFDF7;
  font-size: clamp(7px, 1.9vmin, 12px);
  font-weight: 800;
  line-height: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.28);
  animation: drag-pop 180ms cubic-bezier(0.34, 1.45, 0.64, 1);
}

/* error ALWAYS wins the eye — re-asserted after every confirm state */
.board .cell.bad {
  box-shadow: inset 0 0 0 2.5px var(--c-bad);
  background-image: none;
}

.board .cell.bad .cell-glyph { color: var(--c-bad); }

.board .cell.bad .cell-glyph::after { content: none; }

/* dragons-placed counter mood */
#placed.all-good { color: var(--ok); }
#placed.has-bad { color: var(--c-bad); }

/* ---------- 4. auto-mark mode button ---------- */
/* equal flex-basis keeps every key the same width whatever the label says */
#pad .pad-key { min-width: 0; }
#pad .k-lab { white-space: nowrap; }

#pad #btn-autox[data-mode="off"] .k-ico { opacity: 0.55; }

#pad #btn-autox[data-mode="straight"] {
  background: var(--accent);
  color: #FFF6EC;
}

#pad #btn-autox[data-mode="straight"] .k-lab { color: rgba(255, 246, 236, 0.85); }

/* extended = a visible step up from straight, not the same pill */
#pad #btn-autox[data-mode="extended"] {
  background: var(--accent-deep);
  color: #FFF6EC;
  box-shadow: var(--shadow), inset 0 0 0 2px rgba(255, 246, 236, 0.55);
}

#pad #btn-autox[data-mode="extended"] .k-lab { color: #FFF6EC; }

/* ---------- reduced motion (theme.css has the global kill; belt+braces) ---------- */
@media (prefers-reduced-motion: reduce) {
  .app, .board .cell, .board .cell::before, .board .cell-glyph,
  .cell.settling .cell-glyph, .cell.confirmed .cell-glyph::after,
  #pad .pad-key, .btn-primary, .btn-ghost, .win-dragon {
    transition: none !important;
    animation: none !important;
  }
}
