/* chess960puzzles.com
 *
 * DIRECTION — Japanese design principles, applied structurally rather than as
 * motifs. No washi texture, no vermilion dot, no brush script; those are
 * costume. The principles do the work:
 *
 *   MA (間)        Intervals are an active element. A chessboard is a grid of
 *                  intervals, so the page breathes at the same rhythm. Space
 *                  separates things; borders almost never do.
 *   KANSO (簡素)    Every rule, border and fill must earn its place. Cards,
 *                  shadows and pill nav are gone because none of them carried
 *                  information.
 *   FUKINSEI (不均整) Controlled asymmetry instead of a symmetric grid: the board
 *                  sits off-centre, the readout hangs beside it unaligned, and
 *                  headings hang left of the text measure.
 *   SHIBUI (渋い)   Colour withheld. Richness lives in detail and spacing, not
 *                  contrast, and reveals itself slowly.
 *   SEIJAKU (静寂)  Motion is slow and rare. Nothing bounces or shakes.
 *   SHIZEN (自然)   The wooden board is the one natural material and is left
 *                  unenhanced. Everything around it is ink on paper.
 *
 * Colour is aizome indigo rather than vermilion -- indigo is the deep Japanese
 * folk colour and avoids the Hinomaru-dot cliché. Vermilion appears in exactly
 * one place, the live turn marker, so that it reads as a seal.
 *
 * Token NAMES are stable; page-level <style> blocks depend on them.
 */
:root {
  --bg: #ffffff;
  --paper: #fbfbf9;          /* a half-tone, used sparingly for a resting field */
  --raise: transparent;      /* panels are defined by space, not by fill */
  --ink: #1d2226;            /* sumi: soft blue-black, never pure #000 */
  --soft: #5e625f;
  --faint: #9a9c96;          /* nezumi */
  --line: #ececea;
  --rule: #d9d9d4;
  --brand: #2a4256;          /* ai / aizome indigo */
  --brand-ink: #22384a;
  --brand-soft: #f2f4f6;
  --seal: #b0432e;           /* shu vermilion — the live marker, nowhere else */
  --good: #3f5f45;
  --bad: #a4503f;

  /* the one natural material */
  --sq-light: #f0d9b5;   /* lichess brown, the default everywhere */
  --sq-dark: #b58863;
  --sq-sel: #cfcb93;
  --sq-mark: #e6dda6;

  --shadow: none;
  --r: 0;                    /* nothing is rounded; edges are cut, not softened */
  --sans: system-ui, -apple-system, "Hiragino Sans", "Noto Sans JP", "Segoe UI", Roboto, sans-serif;
  --serif: var(--sans);      /* legacy alias — no serif in this direction */
  --mono: ui-monospace, "SF Mono", SFMono-Regular, Menlo, Consolas, monospace;

  --gap: clamp(2.5rem, 7vw, 6rem);   /* the interval: generous, and the same everywhere */
}
* { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; font-size: 100%; }
body {
  margin: 0; background: var(--bg); color: var(--ink);
  font-family: var(--sans); font-size: 1rem; line-height: 1.85;
  font-weight: 350; -webkit-font-smoothing: antialiased;
}
.wrap { width: 100%; max-width: 68rem; margin-inline: auto;
  padding-inline: clamp(1.25rem, 6vw, 4rem); }
.narrow { max-width: 46rem; }        /* the reading measure */

/* The prose was butting straight into the board. It is a separate movement of
   the page, so it gets the interval and a rule to start it -- and on a wide
   screen it is inset to the text column rather than starting hard against the
   left edge under a two-column board. */
/* separation lives on .stage itself, so it holds whatever follows the board */
/* An article page is nothing but this column, so it centres. The left offset is
   the deliberate asymmetry UNDER a board, and only there — applied everywhere it
   left an article stranded against the left edge of a much wider container. */
.narrow { margin-inline: 0; }

/* Safety net. Some pages put prose straight into .wrap with no .narrow, and
   .wrap is 68rem, which sets running text at roughly 180 characters a line.
   Anything that is a direct child of .wrap and is text gets the reading measure
   whether or not the page remembered to wrap it. */
main .wrap > h1, main .wrap > h2, main .wrap > h3,
main .wrap > p, main .wrap > ul, main .wrap > ol, main .wrap > dl,
main .wrap > figure, main .wrap > blockquote {
  max-width: 46rem;
  margin-inline: 0;
}
/* the board and its readout are the exception: they use the full width */
main .wrap > .stage, main .wrap > .grid3, main .wrap > .books { max-width: none; }
.narrow > h1:first-child { margin-top: 0; }
.narrow > h2:first-of-type { margin-top: 1.6rem; }

/* ---------- the quiet voice ----------
   Small, tracked, uppercase. Anything that names rather than speaks. */
.label, .eyebrow, nav a, .panel-label, .plylabel, .readout dt {
  font-family: var(--mono); font-size: .68rem; letter-spacing: .18em;
  text-transform: uppercase; font-weight: 400;
}

/* ---------- header ----------
   No bar, no fill, no border. It sits in space and is separated by space. */
header.site { background: var(--bg); position: sticky; top: 0; z-index: 20; }
header.site .inner {
  display: grid; align-items: center; column-gap: clamp(1.25rem, 4vw, 3rem);
  grid-template-columns: auto 1fr auto;
  grid-template-areas: "logo nav toggle";
  padding-block: 1.4rem .5rem;
}
.logo { grid-area: logo; }
header.site nav { grid-area: nav; }
.modeToggle { grid-area: toggle; justify-self: end; }
@media (max-width: 46rem) {
  header.site .inner {
    grid-template-columns: 1fr auto;
    grid-template-areas: "logo toggle" "nav nav";
    row-gap: .8rem;
  }
}
.logo { font-family: var(--mono); font-size: .74rem; font-weight: 500;
  letter-spacing: .22em; text-transform: uppercase; color: var(--ink);
  text-decoration: none; white-space: nowrap; }
.logo .mark { display: none; }       /* Kanso: the glyph said nothing the words did not */
nav { display: flex; align-items: center; gap: clamp(.35rem, 1.4vw, .8rem);
  flex-wrap: wrap; margin-left: -.6rem; }   /* cancels the link padding so the nav starts on the shared edge */
/* The toggle stays on the logo's row at every width: when the nav wraps to its
   own line it takes the full width and pushes past the toggle, which otherwise
   ends up stranded under the menu. */
nav a { color: var(--faint); text-decoration: none;
  padding: .38rem .6rem; border-radius: 2px; line-height: 1.2;
  transition: color .3s ease, background .3s ease; }
nav a:hover { color: var(--ink); }
nav a[aria-current="page"] { color: var(--ink); background: var(--brand-soft); }

/* ---------- type ---------- */
h1 { font-size: clamp(1.7rem, 1.15rem + 2.1vw, 2.5rem); line-height: 1.2;
  letter-spacing: 0; font-weight: 400; margin: 0 0 1rem; }
h2 { font-size: clamp(1.05rem, .98rem + .35vw, 1.2rem); line-height: 1.5;
  letter-spacing: .02em; font-weight: 500; margin: calc(var(--gap) * .62) 0 .6rem; }
h3 { font-size: .95rem; font-weight: 500; letter-spacing: .02em; margin: 1.8rem 0 .3rem; }
p, li { color: #3a3f3c; font-weight: 350; }
.lede { font-size: 1.05rem; color: var(--soft); max-width: 52ch; line-height: 1.8; }
a { color: var(--brand-ink); text-decoration-thickness: 1px; text-underline-offset: .25em; }
main { padding-bottom: calc(var(--gap) * 1.4); }
ul, ol { padding-left: 1.1rem; }
li { margin-bottom: .35rem; }
strong { font-weight: 500; }
em { font-style: normal; color: var(--brand-ink); }
.skip { position: absolute; left: -9999px; }
.skip:focus { left: 1rem; top: 1rem; background: var(--bg); padding: .7rem 1rem;
  z-index: 99; border: 1px solid var(--ink); }
:focus-visible { outline: 1px solid var(--brand); outline-offset: 3px; }

/* ---------- SIGNATURE: the back-rank string ----------
   The one thing unique to Chess960 — which of the 960 arrangements this is.
   Set wide, because the interval BETWEEN the letters is the point. */
.specimen { margin: 1.5rem 0 0; display: flex; align-items: baseline;
  gap: clamp(1rem, 4vw, 2.5rem); flex-wrap: wrap; }
.specimen .code { font-family: var(--mono); font-size: clamp(.95rem, .8rem + .6vw, 1.3rem);
  letter-spacing: .55em; color: var(--ink); font-weight: 300; overflow-wrap: anywhere; }
.specimen .sp { font-family: var(--mono); font-size: .68rem; letter-spacing: .18em;
  text-transform: uppercase; color: var(--faint); }

/* ---------- layout: Fukinsei ----------
   Not a symmetric split. The board takes the larger share and the readout hangs
   beside it, top-aligned to the board rather than to its own box. */
.stage { display: grid; gap: clamp(1.5rem, 5vw, 3.5rem); align-items: start;
  margin: clamp(1.5rem, 4vw, 3rem) 0 var(--gap);
  padding-bottom: var(--gap);
  border-bottom: 1px solid var(--line);
  grid-template-columns: minmax(0, 1.55fr) minmax(13rem, .85fr); }
@media (max-width: 56rem) { .stage { grid-template-columns: 1fr; } }
.board-col { width: 100%; max-width: min(34rem, 92vw); }

/* the readout: no box, no fill, no border — only rhythm */
.side { background: var(--raise); border: 0; border-radius: 0; padding: 0;
  position: sticky; top: 5.5rem; }
@media (max-width: 56rem) { .side { position: static; } }
.side .panel-label { display: block; color: var(--faint); margin-bottom: .6rem; }
.turn { font-size: 1rem; font-weight: 400; margin: 0; letter-spacing: .02em; }
/* the seal: the only vermilion on the site, and only while it is your move */
.turn[data-live="1"]::before { content: ""; display: inline-block; width: .4rem;
  height: .4rem; background: var(--seal); margin-right: .55rem; vertical-align: .08em; }
.meta { color: var(--faint); font-size: .78rem; margin: .5rem 0 0; line-height: 1.7; }
.status { min-height: 3.2em; margin: 1.2rem 0 0; font-size: .9rem; color: var(--soft); line-height: 1.7; }
.status.good { color: var(--good); }
.status.bad { color: var(--bad); }
hr.sep { border: 0; border-top: 1px solid var(--line); margin: 1.2rem 0; }
.readout { display: grid; grid-template-columns: auto 1fr; gap: .5rem 1.5rem;
  font-family: var(--mono); font-size: .78rem; margin-top: 1.2rem; }
.readout dt { color: var(--faint); }
.readout dd { margin: 0; color: var(--ink); text-align: right; font-variant-numeric: tabular-nums; }

/* ---------- controls ----------
   Three weights, so what is pressable is never in doubt. The earlier pass set
   every control as text with a rule under it: quiet, and unreadable as a button.
   Type stays mono and tracked -- that is the identity; only the box is new. */
.btn { display: inline-block; font-family: var(--mono); font-size: .68rem;
  letter-spacing: .16em; text-transform: uppercase; font-weight: 500; cursor: pointer;
  padding: .72rem 1.1rem; border-radius: 0; text-decoration: none; text-align: center;
  background: var(--ink); color: var(--bg); border: 1px solid var(--ink);
  transition: background .2s ease, border-color .2s ease, color .2s ease; }
.btn:hover { background: var(--brand); border-color: var(--brand); color: #fff; }

/* secondary: outlined, same shape, clearly still a control */
.btn.ghost { background: transparent; color: var(--ink); border-color: var(--rule); }
.btn.ghost:hover { background: transparent; border-color: var(--ink); color: var(--brand-ink); }

/* tertiary: genuinely a link that happens to sit among buttons */
.btn.quiet { background: transparent; border-color: transparent; color: var(--faint);
  padding-inline: 0; }
.btn.quiet:hover { background: transparent; color: var(--ink); border-color: transparent; }

.btn:disabled { background: transparent; color: #b9bcb6; border-color: var(--line);
  cursor: default; }
.btn.block { display: block; width: 100%; }
.controls { display: flex; flex-direction: column; gap: .5rem; margin-top: 1.2rem; }

label.rng { display: block; margin-top: 1.6rem; font-family: var(--mono); font-size: .68rem;
  letter-spacing: .18em; text-transform: uppercase; color: var(--faint); }
label.rng strong { color: var(--ink); font-weight: 500; letter-spacing: .06em; }
input[type=range] { width: 100%; margin-top: .7rem; accent-color: var(--brand); }
input[type=text], input[type=number] { width: 100%; font-family: var(--mono); font-size: .78rem;
  padding: .55rem .6rem; border: 1px solid var(--rule); border-radius: 0;
  background: var(--bg); color: var(--ink); }
input[type=text]:focus, input[type=number]:focus { border-color: var(--ink); outline: none; }
select { font-family: var(--mono); font-size: .74rem; padding: .55rem .6rem; width: 100%;
  border: 1px solid var(--rule); border-radius: 0; background: var(--bg); color: var(--ink); }
.score { display: flex; justify-content: space-between; align-items: baseline;
  font-family: var(--mono); font-size: .68rem; letter-spacing: .18em;
  text-transform: uppercase; color: var(--faint); margin-top: 1.6rem; }
.score b { color: var(--ink); font-weight: 500; letter-spacing: .06em; }
.nav { display: flex; align-items: center; justify-content: space-between;
  gap: .6rem; margin-top: 1.2rem; }
.btn.step { padding: .5rem .8rem; font-size: .85rem; letter-spacing: 0; }
.plylabel { color: var(--soft); text-align: center; flex: 1; }

/* ---------- passages ----------
   No cards. Sections are separated by the interval and a single hairline. */
.grid3, .books { display: grid; gap: var(--gap); margin: var(--gap) 0 0;
  background: transparent; border: 0; border-radius: 0; overflow: visible;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 14rem), 1fr)); }
.card, .book { background: transparent; border: 0; border-top: 1px solid var(--ink);
  border-radius: 0; padding: 1rem 0 0; box-shadow: none;
  display: flex; flex-direction: column; }
.card h3, .book h3 { margin-top: 0; }
.card p, .book p.desc { font-size: .88rem; color: var(--soft); line-height: 1.8; }
.card a, .book a.btn { font-family: var(--mono); font-size: .68rem; letter-spacing: .18em;
  text-transform: uppercase; text-decoration: none; }
.card a:hover { text-decoration: underline; text-underline-offset: .3em; }
.book .price { font-family: var(--mono); font-weight: 400; font-size: .9rem; margin: 0;
  letter-spacing: .06em; }
.book .ku { font-family: var(--mono); color: var(--good); font-size: .64rem;
  letter-spacing: .16em; text-transform: uppercase; margin: .4rem 0 .9rem; }
code { font-family: var(--mono); font-size: .76rem; background: var(--paper);
  padding: .1rem .3rem; overflow-wrap: anywhere; }

/* Draw the squares ourselves. chessground's bundled themes paint the board with
   a background IMAGE, which cannot be recoloured, so a picker would be
   impossible with them.

   The selector must be .cg-wrap cg-board, not bare cg-board: chessground's
   base.css loads AFTER this file and sets `cg-board { background-size: cover }`,
   which stretched the checker into one giant tile. This needs the extra
   specificity to win.

   conic-gradient, not the 45deg linear-gradient trick -- the linear version
   makes diamonds, not squares. One tile is 2x2 squares, so 25% of an 8x8 board. */
.cg-wrap cg-board {
  background-color: var(--sq-light);
  background-image: conic-gradient(
    var(--sq-dark) 0 25%, var(--sq-light) 0 50%,
    var(--sq-dark) 0 75%, var(--sq-light) 0);
  background-size: 25% 25%;
  background-position: 0 0;
  background-repeat: repeat;
}

/* ---------- board colour picker ---------- */
#themePicker { margin-top: 1.4rem; }
.swatches { display: flex; gap: .5rem; flex-wrap: wrap; margin-top: .5rem; }
.swatch { width: 1.7rem; height: 1.7rem; padding: 0; cursor: pointer;
  border: 1px solid var(--rule); border-radius: 0;
  background-color: var(--a);
  background-image: conic-gradient(var(--b) 0 25%, var(--a) 0 50%, var(--b) 0 75%, var(--a) 0);
  background-size: 50% 50%;
  outline: 2px solid transparent; outline-offset: 2px;
  transition: outline-color .2s ease; }
.swatch[aria-pressed="true"] { outline-color: var(--ink); }
.swatch:hover { border-color: var(--ink); }

/* ---------- chessground ----------
   chessground's own .cg-wrap is `position:relative; display:block` with NO
   dimensions, and its cg-container child is height:100% -- of a box that is
   zero tall. So putting aspect-ratio on an OUTER div does nothing: chessground
   inserts .cg-wrap inside it and the square never reaches the board, which
   collapses to nothing. The square has to be set on .cg-wrap itself.
   This rule is global on purpose, so it holds whatever wrapper a page uses. */
.cg-wrap { width: 100%; aspect-ratio: 1 / 1; height: auto; }
.cg-wrap-outer { width: 100%; max-width: min(34rem, 92vw); }
.cg-square { position: relative; width: 100%; }

/* Coordinates ship at a fixed px size, which is illegible on a small board and
   clumsy on a large one. Scale them with the board instead. */
.cg-wrap coords { font-family: var(--mono); font-size: clamp(.42rem, 1.4vw, .62rem);
  letter-spacing: .04em; font-weight: 400; opacity: .75; }

/* Seijaku: a rejected move settles rather than shakes. */
.board-col.shake, .cg-square.shake { animation: settle .5s cubic-bezier(.22,.61,.36,1); }
@keyframes settle {
  0% { opacity: 1; }
  30% { opacity: .55; }
  100% { opacity: 1; }
}
@media (prefers-reduced-motion: reduce) {
  .shake { animation: none; }
  * { transition-duration: .01ms !important; }
}

/* ---------- footer ---------- */
footer.site { border-top: 1px solid var(--rule); color: var(--faint);
  font-size: .78rem; padding: 1.6rem 0 calc(var(--gap) * .8); margin-top: var(--gap); }
footer.site a { color: var(--faint); text-decoration: none; }
footer.site a:hover { color: var(--ink); }
footer.site .row { display: flex; gap: clamp(1rem, 3vw, 2rem); flex-wrap: wrap;
  margin-bottom: 1.2rem; font-family: var(--mono); font-size: .68rem;
  letter-spacing: .18em; text-transform: uppercase; }
footer.site p { margin: .3rem 0; font-size: .76rem; line-height: 1.8; }

/* ---------- dark ----------
   Lichess's own dark palette: a warm charcoal page (#161512), grey type, and a
   blue accent — not a cool slate. Opt-in only, never from the OS; an earlier
   build followed prefers-color-scheme and served a dark page to someone who had
   asked for white. The toggle sets data-theme on <html>; nothing else does. */
:root[data-theme="dark"] {
  --bg: #161512;
  --paper: #262421;
  --ink: #bababa;
  --soft: #a0a0a0;
  --faint: #7d7d7d;
  --line: #2b2925;
  --rule: #404040;
  --brand: #3692e7;
  --brand-ink: #63aef0;
  --brand-soft: #1d1f22;
  --seal: #d85c3d;
  --good: #629924;
  --bad: #cc5b47;
}
:root[data-theme="dark"] p,
:root[data-theme="dark"] li { color: #b0b0b0; }
/* In dark mode --ink IS grey (#bababa), so the light-mode trick of painting
   --ink on --bg gives grey on charcoal with no contrast, and the earlier
   override put grey text back on top of it. The primary fill becomes the blue
   accent instead, which is the one colour with contrast against the page. */
:root[data-theme="dark"] .btn {
  background: var(--brand); border-color: var(--brand); color: #fff; }
:root[data-theme="dark"] .btn:hover {
  background: var(--brand-ink); border-color: var(--brand-ink); color: #fff; }
:root[data-theme="dark"] .btn.ghost {
  background: transparent; color: var(--ink); border-color: var(--rule); }
:root[data-theme="dark"] .btn.ghost:hover {
  background: transparent; color: #fff; border-color: var(--ink); }
:root[data-theme="dark"] .btn:disabled {
  background: transparent; color: #5c5c5c; border-color: var(--line); }
:root[data-theme="dark"] .btn.quiet {
  background: transparent; border-color: transparent; color: var(--faint); }
:root[data-theme="dark"] .book .cover img { border-color: var(--rule); }

/* ---------- light / dark toggle ---------- */
.modeToggle { display: inline-flex; align-items: center;
  justify-content: center; width: 2rem; height: 2rem; padding: 0;
  color: var(--faint); background: transparent; border: 0; cursor: pointer;
  transition: color .3s ease; }
.modeToggle:hover { color: var(--ink); }
@media (max-width: 34rem) { .modeToggle { margin-left: 0; } }

/* Square highlights. These lived in chessground.brown.css, which also hardcoded
   the board image; dropping that file for a recolourable board took the move
   dots, selection and check glow with it. Lichess's own values, restored. */
.cg-wrap cg-board square.move-dest {
  background: radial-gradient(rgba(20,85,30,.5) 22%, #208530 0, rgba(0,0,0,.3) 0, rgba(0,0,0,0) 0);
}
.cg-wrap cg-board square.oc.move-dest {
  background: radial-gradient(transparent 0%, transparent 80%, rgba(20,85,0,.3) 80%);
}
.cg-wrap cg-board square.move-dest:hover { background: rgba(20,85,30,.3); }
.cg-wrap cg-board square.last-move { background-color: rgba(155,199,0,.41); }
.cg-wrap cg-board square.selected   { background-color: rgba(20,85,30,.5); }
.cg-wrap cg-board square.check {
  background: radial-gradient(ellipse at center, rgba(255,0,0,1) 0%, rgba(231,0,0,1) 25%,
    rgba(169,0,0,0) 89%, rgba(158,0,0,0) 100%);
}

/* Books is where the site is trying to send people, so the nav says so. Quiet
   about it: a rule under the word, not a coloured pill. */
nav a[href="/books"] { color: var(--bg); background: var(--ink); font-weight: 500; }
nav a[href="/books"]:hover { background: var(--brand); color: #fff; }
nav a[href="/books"][aria-current="page"] { background: var(--brand); color: #fff; }

/* In dark mode --ink is grey, so an ink fill would read as a washed-out block.
   The blue accent is the only fill with contrast against #161512, same as the
   primary button. */
:root[data-theme="dark"] nav a[href="/books"] { background: var(--brand); color: #fff; }
:root[data-theme="dark"] nav a[href="/books"]:hover { background: var(--brand-ink); color: #fff; }
