/* =====================================================================
   Post-page component styles (the SSR /feed/<slug>/ pages link this plus the
   brand base injected by the server). Relies on the brand CSS variables.
   ===================================================================== */
/* Daily Wise Word Finder styles (shared with feed.css — must stay an @import) */
@import url("/feed/word-find.css");
article.post{ padding:42px 0 0 }
.post .kicker{ font-family:var(--ui); font-size:11px; font-weight:600; letter-spacing:.14em; text-transform:uppercase; color:var(--crimson) }
.post h1{ font-family:var(--display); font-weight:500; font-size:clamp(34px,6.5vw,56px); line-height:1.05; margin:10px 0 8px; letter-spacing:-.01em; }
.post .byline{ color:var(--ink-soft); font-size:15px; margin:0 0 4px }
.post .byline .pd{ color:var(--gold); font-style:italic; font-family:var(--display); font-size:16px }

/* vote widget */
.post-vote{ display:inline-flex; align-items:center; gap:10px; margin:22px 0 6px;
  border:1px solid var(--line); border-radius:999px; padding:6px 8px; }
.post-vote button{ font:inherit; line-height:1; background:none; border:0; cursor:pointer; color:var(--ink-soft);
  font-size:16px; padding:4px 8px; border-radius:999px; transition:.12s ease }
.post-vote button:hover{ background:var(--paper-2) }
.post-vote button:active{ transform:scale(.82) }
.post-vote button.up:hover{ color:#3b6ea5 }
.post-vote button.down:hover{ color:var(--crimson) }
.post-vote button.up[aria-pressed="true"]{ color:#3b6ea5 }        /* up = blue */
.post-vote button.down[aria-pressed="true"]{ color:var(--crimson) }  /* down = red */
.post-vote .count{ font-family:var(--display); font-weight:600; font-size:18px; min-width:2ch; text-align:center }
.post-vote .vlabel{ font-size:11px; letter-spacing:.08em; text-transform:uppercase; color:var(--ink-soft); padding-right:6px }

.post-media{ max-width:100%; border-radius:12px; border:1px solid var(--line); margin:6px 0 18px; display:block }

/* user-attached external link (create-post "link to a site") — a clear, framed
   exit button below the body. align-items:flex-start (not center) so a long host
   that wraps to two lines keeps the 🔗 icon, "Visit", and the ↗ on the first line
   instead of floating them to the vertical middle of the wrapped block. */
.post-extlink{ display:inline-flex; align-items:flex-start; gap:8px; margin:18px 0 0; text-decoration:none;
  font-family:var(--ui); font-size:14px; font-weight:600; line-height:1.4; color:var(--ink);
  background:var(--tile); border:1px solid var(--line); border-left:3px solid var(--crimson);
  border-radius:10px; padding:11px 16px; transition:.15s ease; overflow-wrap:anywhere }
.post-extlink:hover{ border-color:var(--crimson); color:var(--crimson) }
.post-extlink b{ font-weight:700 }
/* the leading "🔗 Visit" and the trailing arrow are single-line affordances — keep
   them whole so only the (possibly long) host wraps, never the label or glyph. */
.post-extlink-lead{ flex:none; white-space:nowrap }
.post-extlink-arr{ color:var(--ink-soft); flex:none }

/* user-uploaded image gallery (create-post attachments, /media/ paths only) */
.post-gallery{ display:grid; gap:8px; margin:18px 0 0; grid-template-columns:repeat(2, 1fr) }
.post-gallery.n1{ grid-template-columns:1fr }
/* Multi-image tiles share a fixed 4:3 box so the grid reads as tidy, equal rows
   — without it an odd count (e.g. 3) leaves the lone tile stranded beside a
   taller neighbour with a large empty gap, which looks broken. cover crops to
   fill the uniform box. */
.post-gallery-img{ width:100%; aspect-ratio:4/3; border-radius:10px; border:1px solid var(--line); display:block; object-fit:cover }
/* A single image keeps its real shape (contain) but inside a capped, centered
   box so a tall portrait can't balloon into a giant pillarboxed column. */
.post-gallery.n1 .post-gallery-img{ aspect-ratio:auto; width:auto; max-width:100%;
  max-height:520px; margin-inline:auto; object-fit:contain; background:var(--paper-2) }

/* "In short" SEO takeaways (post.seoSummary) — a quiet, skimmable summary card
   above the body. Gold left-rule + tile fill so it reads as a helpful aside, not
   part of the prose. */
.post-takeaways{ margin:6px 0 22px; padding:14px 18px; background:var(--tile);
  border:1px solid var(--line); border-left:3px solid var(--gold); border-radius:12px }
.post-takeaways-h{ font-family:var(--ui); font-size:11px; font-weight:700; letter-spacing:.1em;
  text-transform:uppercase; color:var(--gold); margin:0 0 8px }
.post-takeaways ul{ margin:0; padding:0 0 0 18px; display:flex; flex-direction:column; gap:5px }
.post-takeaways li{ font-size:14.5px; line-height:1.5; color:var(--ink) }

/* poems read as verse; prose posts read as paragraphs */
.poem{ font-family:var(--display); font-size:clamp(18px,2.6vw,21px); line-height:1.85; color:var(--ink); }
.poem p{ margin:0 0 1.5em } .poem p:last-child{ margin-bottom:0 }
.prose{ font-size:17px; line-height:1.7; color:var(--ink); }
.prose p{ margin:0 0 1.1em } .prose p:last-child{ margin-bottom:0 }

.post .source{ margin-top:30px; font-size:13px; color:var(--ink-soft); overflow-wrap:anywhere }
.post .source a{ color:var(--ink); text-decoration:none; border-bottom:1px solid var(--crimson); padding-bottom:1px }
.post .source a:hover{ color:var(--crimson) }

/* ---- comments ---- */
.comments{ margin:44px 0 0 }
.comments .rule{ display:flex; align-items:center; gap:14px; margin:0 0 18px; color:var(--gold) }
.comments .rule::before,.comments .rule::after{ content:""; height:1px; background:var(--line); flex:1 }
.comments .rule span{ font-family:var(--display); font-size:18px; letter-spacing:.3em }
.comments-h{ font-family:var(--display); font-weight:500; font-size:24px; margin:0 0 16px; letter-spacing:-.01em }

.comment-form{ display:flex; flex-direction:column; gap:9px; margin:0 0 24px }
.comment-input{ font:inherit; font-size:15px; color:var(--ink); background:var(--tile); resize:vertical;
  border:1px solid var(--line); border-radius:12px; padding:12px 14px; width:100%; line-height:1.5;
  transition:border-color .15s ease }
.comment-input:focus{ outline:none; border-color:var(--crimson) }
.comment-actions{ display:flex; align-items:center; justify-content:flex-end; gap:12px }
.comment-err{ margin-right:auto; color:var(--crimson); font-size:13px; min-width:0 }   /* min-width:0 so the err shrinks before the submit wraps */
.comment-submit{ font:inherit; font-size:14px; font-weight:600; color:#fff; cursor:pointer; white-space:nowrap;
  background:var(--crimson); border:0; border-radius:999px; padding:9px 18px; transition:.15s ease }
.comment-submit:hover{ filter:brightness(1.08); transform:translateY(-1px) }
.comment-submit:disabled{ opacity:.55; cursor:default; transform:none }
.comment-gate{ color:var(--ink-soft); font-size:14px; margin:0 0 24px;
  background:var(--tile); border:1px solid var(--line); border-radius:12px; padding:13px 15px }
.comment-gate a{ color:var(--ink); text-decoration:none; border-bottom:1px solid var(--crimson); padding-bottom:1px }
.comment-gate a:hover{ color:var(--crimson) }

.comment-list{ list-style:none; margin:0; padding:0; display:flex; flex-direction:column; gap:12px }
.comment{ background:var(--tile); border:1px solid var(--line-2, var(--line)); border-radius:12px; padding:12px 15px }
.comment-head{ display:flex; align-items:baseline; gap:10px; margin:0 0 5px }
.comment-name{ font-weight:600; font-size:14.5px; color:var(--ink) }
.comment-time{ font-size:12px; color:var(--ink-soft) }
.comment-text{ margin:0; font-size:15px; line-height:1.55; color:var(--ink); white-space:pre-wrap; overflow-wrap:anywhere }
.comment-empty{ color:var(--ink-soft); font-style:italic; padding:6px 2px }
/* a comment's attached image (our own /media/ paths only) */
.comment-img{ display:inline-block; margin:7px 0 0 }
.comment-img img{ max-width:240px; max-height:240px; border-radius:8px; border:1px solid var(--line); display:block }

/* awaiting-approval state: the author (and moderators) see their pending comment
   dimmed with a badge; the public never sees it at all (filtered client-side). */
/* dim the pending COPY only (the text + vote), not the badge or the moderator
   actions — a faded Approve/Remove read as disabled when they're fully live. */
.comment.is-pending .comment-text, .comment.is-pending .cvote{ opacity:.66 }
.comment-pending{ font-size:10.5px; font-weight:600; letter-spacing:.06em; text-transform:uppercase;
  color:var(--gold); border:1px solid currentColor; border-radius:999px; padding:2px 8px; margin-left:2px;
  white-space:nowrap }
/* moderator tools on a comment (approve a pending one / remove any) */
/* wrap so the trailing Share button drops to its own line (instead of squeezing /
   wrapping its label) when Approve+Remove+Share don't fit the narrow post column. */
.comment-mod{ display:flex; flex-wrap:wrap; gap:8px; margin:10px 0 0 }
.comment-mod button{ font:inherit; font-size:12.5px; font-weight:600; cursor:pointer; border-radius:8px;
  padding:6px 13px; border:1px solid var(--line); background:var(--paper-2); color:var(--ink-soft);
  transition:.15s ease; -webkit-tap-highlight-color:transparent }
.comment-mod button:focus-visible{ outline:2px solid var(--crimson); outline-offset:2px }
.comment-mod .c-approve{ border-color:var(--gold); color:var(--gold) }
.comment-mod .c-approve:hover{ background:var(--gold); color:#1a1407 }
.comment-mod .c-remove:hover{ border-color:var(--crimson); color:var(--crimson) }
/* author's own share: push to the trailing edge; never let the two-word label wrap
   to a second line (it read as a broken button beside the single-line mod buttons). */
.comment-mod .c-bsky{ margin-left:auto; white-space:nowrap }
.comment-mod .c-bsky:hover{ border-color:#1185fe; color:#1185fe }   /* Bluesky blue */
.comment-mod .c-bsky:focus-visible{ outline-color:#1185fe }
.comment-err.ok{ color:var(--gold) }

/* per-comment up/down vote (up = blue, down = red, matching post votes) */
.cvote{ display:inline-flex; align-items:center; gap:6px; margin:9px 0 0; user-select:none }
.cvote button{ font:inherit; line-height:1; background:none; border:0; cursor:pointer; color:var(--ink-soft);
  font-size:13px; padding:2px 6px; border-radius:6px; transition:.12s ease }
.cvote button:hover{ background:var(--paper-2) }
.cvote button:active{ transform:scale(.82) }
.cvote button.up:hover{ color:#3b6ea5 }
.cvote button.down:hover{ color:var(--crimson) }
.cvote button.up[aria-pressed="true"]{ color:#3b6ea5 }
.cvote button.down[aria-pressed="true"]{ color:var(--crimson) }
.cvote .ccount{ font-weight:600; font-size:13px; color:var(--ink); min-width:1.5ch; text-align:center; font-variant-numeric:tabular-nums }

/* ---- Daily Logic Puzzle (Morning Mystery) on the post page: a teaser with a
   big Play button to the same-domain subpage where it actually plays. ---- */
.dm-post{ text-align:center; margin:0 0 8px }
.dm-post-play{ display:inline-flex; align-items:center; gap:8px; margin:6px auto 2px;
  font-family:var(--ui); font-weight:600; font-size:15px; color:#fff; background:var(--crimson);
  border-radius:999px; padding:12px 26px; text-decoration:none; box-shadow:0 12px 26px -14px var(--shadow);
  transition:transform .15s ease, background .15s ease }
.dm-post-play:hover{ transform:translateY(-1px); background:color-mix(in srgb, var(--crimson) 82%, #000) }
.dm-post-play:active{ transform:translateY(0) scale(.98) }
@media (prefers-reduced-motion: reduce){ .dm-post-play:hover, .dm-post-play:active{ transform:none } }

/* ---- chess puzzle on the post page (board + prompt; answer in the comments) ---- */
.cp-board-wrap{ text-align:center; margin:0 0 8px }
.cp-prompt-lg{ font-family:var(--display); font-weight:600; font-size:clamp(18px,3vw,23px); margin:0 0 12px }
.cp-answer-note{ font-size:14px; color:var(--ink-soft); margin:12px 0 0 }
/* the "Browse past …" archive link rendered user-agent blue — brand it like
   every other in-post link (ink + crimson underline, crimson on hover). */
.cp-answer-note a{ color:var(--ink); text-decoration:none; border-bottom:1px solid var(--crimson); padding-bottom:1px }
.cp-answer-note a:hover{ color:var(--crimson) }
/* ---- the board: a PERFECT SQUARE (aspect-ratio:1/1) of 8×8 square cells.
   Larger cap than the feed card for the detail page. Piece art = CPB PNGs as a
   centered, contained background image (.cp-*), not Unicode glyphs. ---- */
/* width:100% (capped) so the board always fits its container, never the viewport —
   90vw overflowed the padded card on mobile and clipped the h-file/right edge. */
.chessb{ display:grid; grid-template-columns:repeat(8,1fr); width:100%; max-width:440px; aspect-ratio:1/1; margin:0 auto;
  position:relative; border:3px solid #6b4a2f; border-radius:8px; overflow:hidden;
  box-shadow:0 12px 32px -16px rgba(0,0,0,.5); }
.chessb .sq{ position:relative; aspect-ratio:1/1; width:100%; user-select:none }
/* background-COLOR only (not the shorthand) so it never resets the piece PNG. */
.chessb .sq.l{ background-color:#efe2c4 } .chessb .sq.d{ background-color:#b07a4f }
.chessb .sq.cp{ background-repeat:no-repeat; background-position:center; background-size:88%; }
/* Set only background-COLOR — the `background` shorthand would reset background-image
   to none and wipe the piece PNG (it out-specifies the .cp-* rules). See feed.css. */
.chessb .sq.cp.l{ background-color:#efe2c4 }
.chessb .sq.cp.d{ background-color:#b07a4f }
.cp-wp{ background-image:url(/images/chess/wp.png) } .cp-bp{ background-image:url(/images/chess/bp.png) }
.cp-wn{ background-image:url(/images/chess/wn.png) } .cp-bn{ background-image:url(/images/chess/bn.png) }
.cp-wb{ background-image:url(/images/chess/wb.png) } .cp-bb{ background-image:url(/images/chess/bb.png) }
.cp-wr{ background-image:url(/images/chess/wr.png) } .cp-br{ background-image:url(/images/chess/br.png) }
.cp-wq{ background-image:url(/images/chess/wq.png) } .cp-bq{ background-image:url(/images/chess/bq.png) }
.cp-wk{ background-image:url(/images/chess/wk.png) } .cp-bk{ background-image:url(/images/chess/bk.png) }
/* coordinate labels (files a–h, ranks 1–8) — flip with the board. */
.chessb .sq[data-file]::after{ content:attr(data-file); position:absolute; left:3px; bottom:1px;
  font:600 10px var(--ui); line-height:1; opacity:.62; pointer-events:none }
.chessb .sq[data-rank]::before{ content:attr(data-rank); position:absolute; right:3px; top:1px;
  font:600 10px var(--ui); line-height:1; opacity:.62; pointer-events:none }
.chessb .sq.l[data-file]::after,.chessb .sq.l[data-rank]::before{ color:#7a5230 }
.chessb .sq.d[data-file]::after,.chessb .sq.d[data-rank]::before{ color:#efe2c4 }

/* ===== Daily Chess Puzzle — INTERACTIVE board on the POST page (chess-play.js).
   Same component classes as the feed card; sized a touch larger for the detail
   page. Brand parchment/crimson, dark-mode + reduced-motion aware. ===== */
/* MINIMIZED SPAWN → EXPAND ON PLAY (task 1): the post card spawns compact —
   .dc-prelude.dc-min holds a SMALL board preview (~220px on the roomier detail
   page) + the Play button. On Play the interactive shell swaps in and the wrapper
   gets .dc-expanded, growing the board small→full (440px cap here) and fading in the
   bar/actions/status. Animating max-width keeps the grow cheap; the minimized state
   reserves its own small size in plain CSS so it hydrates jank-free. */
.dc-board-area{ width:100%; max-width:440px; aspect-ratio:1/1; margin:0 auto;
  display:flex; align-items:center; justify-content:center;
  transition:max-width .3s cubic-bezier(.2,.7,.2,1); will-change:max-width }
.dc-board-area > .chessb, .dc-board-area .dc-mount, .dc-board-area .dc-mount > .chessb{ margin:0 }
.dc-board-area .dc-mount{ width:100%; display:flex; align-items:center; justify-content:center }
.dc-post .dc-prelude{ display:flex; flex-direction:column; align-items:center; gap:0 }
.dc-post .dc-prelude .dc-play{ margin:14px auto 0 }
/* MINIMIZED preview (~220px on the roomier detail page) above the Play button. */
.dc-post .dc-prelude.dc-min .dc-board-area{ max-width:220px }
.dc-post .dc-prelude.dc-min .dc-play{ margin:12px auto 0 }
/* EXPANDED: chess-play.js adds .dc-expanded to the .closest(".post.daily-chess") —
   the OUTER post article — when Play is pressed. So we key the grow/fade off it.
   The interactive shell mounts a fresh .dc-board-area (no .dc-min wrapper); until
   the post gets .dc-expanded it must START small so the grow animates small→full. */
.post.daily-chess:not(.dc-expanded) .dc-board-area{ max-width:220px }
.post.daily-chess.dc-expanded .dc-board-area{ max-width:440px }
.post.daily-chess .dc-bar, .post.daily-chess .dc-actions, .post.daily-chess .dc-status{
  transition:opacity .28s ease .06s, transform .28s ease .06s }
.post.daily-chess:not(.dc-expanded) .dc-bar,
.post.daily-chess:not(.dc-expanded) .dc-actions,
.post.daily-chess:not(.dc-expanded) .dc-status{ opacity:0; transform:translateY(6px) }
.post.daily-chess.dc-expanded .dc-bar,
.post.daily-chess.dc-expanded .dc-actions,
.post.daily-chess.dc-expanded .dc-status{ opacity:1; transform:none }
/* "Share your solve" — appears under the win status (chess-play addShareButton) */
.dc-share{ font:inherit; font-family:var(--ui); font-size:12.5px; font-weight:600; cursor:pointer;
  margin:8px auto 0; display:inline-block; padding:6px 16px; border-radius:999px;
  border:1px solid var(--crimson); color:var(--crimson); background:transparent }
.dc-share:hover{ background:var(--crimson); color:#fff }
.dc-share:focus-visible{ outline:2px solid var(--crimson); outline-offset:2px }
.dc-play{ font:inherit; font-family:var(--ui); font-weight:600; font-size:14px; color:#fff;
  background:var(--crimson); border:1px solid color-mix(in srgb, var(--crimson) 70%, #000);
  border-radius:999px; padding:10px 22px; cursor:pointer; transition:.16s ease;
  /* touch-action:manipulation kills the ~300ms tap delay so the FIRST tap registers. */
  touch-action:manipulation; -webkit-tap-highlight-color:transparent;
  box-shadow:0 8px 20px -10px color-mix(in srgb, var(--crimson) 80%, #000) }
.dc-post .dc-hint,.dc-post .dc-reset{ touch-action:manipulation; -webkit-tap-highlight-color:transparent }
.dc-play:hover{ transform:translateY(-1px); filter:brightness(1.06) }
.dc-play:disabled{ opacity:.6; cursor:default; transform:none }
.dc-bar{ display:flex; align-items:center; justify-content:center; gap:12px; flex-wrap:wrap; margin:0 0 10px }
.dc-timer{ font-variant-numeric:tabular-nums; font-weight:700; font-size:22px; color:var(--ink); min-width:5ch }
.dc-goal{ font-size:11px; font-weight:600; letter-spacing:.1em; text-transform:uppercase; color:var(--crimson) }
.dc-flash{ font-size:13px; font-weight:600; padding:2px 8px; border-radius:999px }
.dc-flash.pen{ color:#fff; background:var(--crimson); animation:dc-pop .35s ease }
.dc-flash.bad{ color:var(--crimson); background:color-mix(in srgb, var(--crimson) 14%, transparent) }
@keyframes dc-pop{ 0%{ transform:scale(.7); opacity:0 } 60%{ transform:scale(1.12) } 100%{ transform:scale(1); opacity:1 } }
/* touch-action:none so DRAG (task 2) doesn't scroll the page; grab/grabbing cursors. */
.dc-board{ touch-action:none }
.dc-board .sq{ cursor:pointer }
.dc-board .sq.cp{ cursor:grab }
.dc-board.dc-drag-active, .dc-board.dc-drag-active .sq{ cursor:grabbing }
/* SELECTED SOURCE — HIGH CONTRAST (task 3): a double inset ring (bright gold core +
   dark outer ring) + a stronger gold wash so the picked-up piece pops against both
   wood square colors AND in dark mode. The dark outer ring is the key contrast add
   the old single 3px gold ring lacked. Legal dots/.cap rings stay distinct. */
.dc-board .sq.sel{
  box-shadow:inset 0 0 0 3px var(--gold), inset 0 0 0 5px rgba(0,0,0,.55), inset 0 0 12px rgba(255,200,40,.55);
  background-color:color-mix(in srgb, var(--gold) 62%, transparent) }
.dc-board .sq.last{ background-color:rgba(205,210,80,.55) }
/* last-move tint on a piece cell: override only the COLOR so the PNG survives. */
.dc-board .sq.last.cp.l{ background-color:rgba(205,210,80,.55) }
.dc-board .sq.last.cp.d{ background-color:rgba(180,185,70,.62) }
.dc-board .sq.dot::after{ content:""; position:absolute; inset:0; margin:auto; width:30%; height:30%;
  border-radius:50%; background:rgba(0,0,0,.16) }
.dc-board .sq.cap{ box-shadow:inset 0 0 0 4px rgba(0,0,0,.16) }
/* ENEMY KING IN CHECK (.chk): soft pulsing red GLOW (the king under fire), kept
   visually OPPOSITE to the wrong-move hard ring below so the two red meanings never
   collide. Brand crimson, not raw iOS red. Mirrors feed.css. */
.dc-board .sq.chk{ box-shadow:inset 0 0 14px 2px color-mix(in srgb, var(--crimson) 78%, transparent);
  background-color:color-mix(in srgb, var(--crimson) 30%, transparent); animation:dc-check .9s ease-in-out infinite }
@keyframes dc-check{ 0%,100%{ box-shadow:inset 0 0 10px 1px color-mix(in srgb, var(--crimson) 55%, transparent) }
  50%{ box-shadow:inset 0 0 16px 3px color-mix(in srgb, var(--crimson) 90%, transparent) } }
/* WRONG-move red flash (hard ring = "you erred"; slide-back animation lives in chess-play.js). */
.dc-board .sq.dc-wrong{ box-shadow:inset 0 0 0 4px #ff3b30; animation:dc-wrong .36s ease }
.dc-board .sq.dc-wrong::before{ content:""; position:absolute; inset:0; background:rgba(255,59,48,.5); z-index:1 }
@keyframes dc-wrong{ 0%{ filter:brightness(1) } 50%{ filter:brightness(1.25) } 100%{ filter:brightness(1) } }
/* CHECKMATE marker (owner ask 2026-06-12): mated king's square → celebratory green
   + a small green ✓ badge = "puzzle complete". Mirrors feed.css. */
.dc-board .sq.dc-mated{ box-shadow:inset 0 0 0 4px #1f9d57 !important;
  background-color:color-mix(in srgb, #2fae67 52%, transparent) !important; animation:none !important }
.dc-board .sq.dc-mated .dc-mate-badge{ position:absolute; z-index:6; top:5%; right:5%;
  width:42%; height:42%; max-width:24px; max-height:24px; border-radius:50%; display:grid; place-items:center;
  background:#1f9d57; color:#fff; font-weight:800; line-height:1; font-size:clamp(10px,3.2vw,14px);
  box-shadow:0 1px 5px rgba(0,0,0,.4); border:1.5px solid #fff; animation:dc-mate-pop .42s cubic-bezier(.2,1.6,.3,1) }
@keyframes dc-mate-pop{ 0%{ transform:scale(0); opacity:0 } 60%{ transform:scale(1.25) } 100%{ transform:scale(1); opacity:1 } }
@media (prefers-reduced-motion:reduce){ .dc-board .sq.dc-mated .dc-mate-badge{ animation:none } }
/* hidden source piece during a slide + the floating slide piece itself. */
.dc-board .sq.dc-hidden-piece{ background-image:none !important }
.dc-board .sq.dc-hidden-piece.l{ background:#efe2c4 } .dc-board .sq.dc-hidden-piece.d{ background:#b07a4f }
.dc-board .dc-float{ position:absolute; z-index:5; pointer-events:none;
  background-repeat:no-repeat; background-position:center; background-size:88%; will-change:transform }
/* DRAG float (task 2/7): enlarged + soft shadow while carried under the pointer. */
.dc-board .dc-float.dc-dragging{ z-index:8; transform:scale(1.18);
  filter:drop-shadow(0 6px 10px rgba(0,0,0,.45)); transition:none; cursor:grabbing }
/* ENEMY-KING WIGGLE (task 4): the king being mated wiggles once on Play — KING
   PIECE ONLY (a floating overlay .dc-king-float over the king's square; the tile
   stays still and the real piece is hidden via .dc-hidden-piece for the duration). */
/* Quick ~0.3s shake (was 1.4s — felt like a screen lock after Play). */
.dc-board .dc-float.dc-king-float{ z-index:6; pointer-events:none;
  animation:dc-king-wiggle .3s ease-in-out; transform-origin:50% 60% }
@keyframes dc-king-wiggle{
  0%{ transform:rotate(0) } 25%{ transform:rotate(-9deg) }
  55%{ transform:rotate(7deg) } 80%{ transform:rotate(-4deg) } 100%{ transform:rotate(0) }
}
.dc-board.dc-shake{ animation:dc-shake .3s ease }
@keyframes dc-shake{ 0%,100%{ transform:translateX(0) } 20%,60%{ transform:translateX(-5px) } 40%,80%{ transform:translateX(5px) } }
.dc-actions{ display:flex; gap:10px; justify-content:center; margin:12px 0 4px }
/* secondary actions — ~40px tap height to stay thumb-friendly on touch. */
.dc-hint,.dc-reset{ font:inherit; font-size:13px; font-weight:500; color:var(--ink-soft);
  background:var(--tile); border:1px solid var(--line); border-radius:999px; padding:9px 18px; cursor:pointer; transition:.15s ease }
.dc-hint:hover,.dc-reset:hover{ color:var(--crimson); border-color:var(--crimson); transform:translateY(-1px) }
.dc-hint-cost{ opacity:.7; font-size:11px }
/* HINT-USED / disabled states (task 2 / task 6): dimmed, no hover lift, not clickable. */
.dc-hint:disabled,.dc-reset:disabled,.dc-hint.dc-hint-used{ opacity:.5; cursor:default }
.dc-hint:disabled:hover,.dc-reset:disabled:hover,.dc-hint.dc-hint-used:hover{
  color:var(--ink-soft); border-color:var(--line); transform:none }
.dc-status{ font-size:14px; color:var(--ink-soft); margin:8px 0 0; min-height:1.2em }
.dc-status.win{ color:var(--gold); font-weight:600 } .dc-status.warn{ color:var(--crimson) }
.dc-board-lb{ margin:16px auto 0; max-width:360px; text-align:left }
.dc-lb-head{ font-size:11px; font-weight:600; letter-spacing:.1em; text-transform:uppercase;
  color:var(--crimson); text-align:center; margin:0 0 8px }
.dcl-status{ font-size:13px; color:var(--ink-soft); text-align:center; padding:10px 0 }
.dcl-status.dcl-err{ color:var(--crimson) }
/* day-average line under the board leaderboard (daily-chess/word-leaderboard.js
   render it on post pages too — it was styled in feed.css only, so here it fell
   back to 16px body prose). Mirrors feed.css, scaled to this page's lb type. */
.dcl-avg{ margin:7px 0 0; font-family:var(--ui); font-size:12px; color:var(--ink-soft);
  text-align:center; font-variant-numeric:tabular-nums }
.dcl-list{ list-style:none; margin:0; padding:0; display:flex; flex-direction:column; gap:2px }
.dcl-row{ display:grid; grid-template-columns:2ch 1fr auto auto; align-items:center; gap:8px;
  padding:7px 11px; border-radius:8px; font-size:14px; background:color-mix(in srgb, var(--ink) 3%, transparent) }
.dcl-row.me{ background:color-mix(in srgb, var(--gold) 18%, transparent); font-weight:600 }
.dcl-rank{ color:var(--ink-soft); font-variant-numeric:tabular-nums }
.dcl-name{ overflow:hidden; text-overflow:ellipsis; white-space:nowrap }
.dcl-pen{ font-size:11px; color:var(--crimson) }
.dcl-time{ font-variant-numeric:tabular-nums; font-weight:600 }
@media (prefers-reduced-motion: reduce){
  /* keep the wrong-move red overlay visible (no pulse); JS snaps slides too.
     King-wiggle fully suppressed (JS also early-returns under reduce — no float). */
  .dc-flash.pen,.dc-board .sq.chk,.dc-board .sq.dc-wrong,.dc-board.dc-shake,
  .dc-board .dc-float.dc-king-float{ animation:none; transform:none }
  .dc-board .dc-float.dc-dragging{ filter:none }
  .dc-play:hover,.dc-hint:hover,.dc-reset:hover{ transform:none }
  /* EXPAND still happens (task 1) but snaps — no animated grow/fade, no bounce. */
  .dc-board-area{ transition:none }
  .post.daily-chess .dc-bar, .post.daily-chess .dc-actions, .post.daily-chess .dc-status{ transition:none }
  .post.daily-chess:not(.dc-expanded) .dc-bar,
  .post.daily-chess:not(.dc-expanded) .dc-actions,
  .post.daily-chess:not(.dc-expanded) .dc-status{ opacity:1; transform:none }
}

/* ---- SERIES NAV (novella chapters — prev / all chapters / next) ---- */
.series-nav{ display:flex; align-items:center; justify-content:space-between; gap:12px; flex-wrap:wrap;
  margin:34px 0 0; padding:14px 2px 0; border-top:1px solid var(--line); font-family:var(--ui); font-size:14px }
.series-nav a{ color:var(--ink); text-decoration:none; border-bottom:1px solid var(--crimson); padding-bottom:1px }
.series-nav a:hover{ color:var(--crimson) }
.series-nav .series-all{ font-size:12.5px; color:var(--ink-soft); border-bottom-color:var(--line-2) }
.series-nav .series-soon{ font-size:12.5px; color:var(--ink-soft); font-style:italic }

/* ===== SERIES READING EXPERIENCE (chapters — nav, ToC, reader prefs) ===== */
.series-nav--top{ margin:18px 0 6px; padding:10px 2px; border-top:0; border-bottom:1px solid var(--line);
  position:relative; font-size:13.5px }
/* reading prefs come from CSS vars reader.js sets on article.post */
article.post .prose{ font-size:var(--reader-size, 17px); line-height:var(--reader-lh, 1.7) }
article.post.reader-sans .prose{ font-family:var(--ui) }
article.post:not(.reader-sans) .prose{ font-family:var(--display); font-size:calc(var(--reader-size, 17px) + 1px) }
article.post.reader-narrow .prose{ max-width:56ch; margin-left:auto; margin-right:auto }
/* reading mode: just the story (reader.js toggles body.fb-reading) */
body.fb-reading header.site, body.fb-reading #fbXpBar, body.fb-reading .comments,
body.fb-reading .post-vote, body.fb-reading .series-toc, body.fb-reading footer{ display:none !important }
body.fb-reading{ padding-top:0 !important }   /* the reserved EXP-bar slot collapses when the bar is hidden */
body.fb-reading article.post{ padding-top:16px }
/* theme overrides (Auto follows system; these force) */
body.reader-theme-parchment{ --paper:#f3ead6; --paper-2:#ece0c4; --tile:#f7f0df; --ink:#211c17; --ink-soft:#6a6253 }
body.reader-theme-sepia{ --paper:#efe2c8; --paper-2:#e6d6b4; --tile:#ece0c2; --ink:#3a2f1f; --ink-soft:#74634a }
body.reader-theme-dark{ --paper:#16120e; --paper-2:#1f1812; --tile:#211a13; --ink:#efe6d0; --ink-soft:#a99c84 }
/* reader controls (📖 + Aa) sit at the right edge of the top nav */
.rdr-controls{ display:inline-flex; gap:6px; align-items:center; position:relative }
.rdr-btn{ font:inherit; font-size:13px; font-weight:600; cursor:pointer; border-radius:8px; padding:4px 10px;
  border:1px solid var(--line); color:var(--ink); background:var(--tile) }
.rdr-btn:hover, .rdr-btn[aria-pressed="true"], .rdr-btn[aria-expanded="true"]{ border-color:var(--crimson); color:var(--crimson) }
.rdr-panel{ position:absolute; right:0; top:calc(100% + 8px); z-index:50; min-width:240px;
  background:var(--tile); border:1px solid var(--line); border-radius:12px; padding:12px;
  box-shadow:0 14px 34px -16px var(--shadow, rgba(0,0,0,.4)); display:flex; flex-direction:column; gap:8px }
.rdr-row{ display:flex; align-items:center; gap:6px; flex-wrap:wrap }
.rdr-lbl{ font-size:11px; letter-spacing:.06em; text-transform:uppercase; color:var(--ink-soft); width:54px }
.rdr-opt{ font:inherit; font-size:12px; cursor:pointer; border-radius:999px; padding:3px 10px;
  border:1px solid var(--line); color:var(--ink); background:transparent }
.rdr-opt.on{ border-color:var(--crimson); color:var(--crimson); font-weight:600 }
/* tap-catching backdrop (transparent on desktop, dims on mobile) — the reliable
   cross-device dismiss for the Aa panel */
.rdr-backdrop{ position:fixed; inset:0; z-index:49; background:transparent; -webkit-tap-highlight-color:transparent }
.rdr-head{ display:flex; align-items:center; justify-content:space-between; gap:10px }
.rdr-title{ font-size:11px; letter-spacing:.06em; text-transform:uppercase; color:var(--ink-soft); font-weight:600 }
.rdr-x{ font:inherit; font-size:22px; line-height:1; cursor:pointer; border:none; background:transparent;
  color:var(--ink-soft); padding:0 6px; border-radius:8px; margin:-2px -4px -2px 0 }
.rdr-x:hover{ color:var(--crimson); background:var(--bg-soft, rgba(0,0,0,.04)) }
/* mark finished + ToC */
.series-finish{ margin:26px 0 0; text-align:center }
.series-finish-btn{ font:inherit; font-family:var(--ui); font-size:13px; font-weight:600; cursor:pointer;
  border-radius:999px; padding:8px 18px; border:1px solid var(--crimson); color:var(--crimson); background:transparent }
.series-finish-btn:hover:not(:disabled){ background:var(--crimson); color:#fff }
.series-finish-btn:disabled{ cursor:default; border-color:var(--gold); color:var(--gold) }
.series-toc{ margin:26px 0 0; border:1px solid var(--line); border-radius:14px; background:var(--tile); padding:16px 18px }
.series-toc-h{ font-family:var(--display); font-weight:600; font-size:19px; margin:0 0 10px;
  display:flex; align-items:baseline; justify-content:space-between; gap:10px }
.series-toc-count{ font-family:var(--ui); font-weight:500; font-size:11.5px; color:var(--ink-soft);
  border:1px solid var(--line-2, var(--line)); border-radius:999px; padding:2px 9px }
.series-toc-list{ margin:0; padding:0 0 0 1.3em; display:flex; flex-direction:column; gap:6px; font-size:14.5px }
.series-toc-list a{ color:var(--ink); text-decoration:none; border-bottom:1px solid var(--crimson); padding-bottom:1px }
.series-toc-list a:hover{ color:var(--crimson) }
.series-toc-list li.cur span{ color:var(--ink-soft) } .series-toc-list li.cur em{ font-size:12px }
.series-meta{ margin:12px 0 0; font-size:12px; color:var(--ink-soft) }
.series-meta a{ color:var(--ink); border-bottom:1px solid var(--line); text-decoration:none }
/* MOBILE: the Aa panel becomes a bottom sheet — full-width, thumb-reachable,
   slides up over a dimmed backdrop. Bigger tap targets; bg scroll locked. */
@media (max-width:480px){
  .series-nav{ font-size:12.5px }
  .rdr-panel{ position:fixed; left:0; right:0; bottom:0; top:auto; min-width:0; z-index:60;
    border-radius:18px 18px 0 0; padding:16px 18px calc(18px + env(safe-area-inset-bottom));
    box-shadow:0 -12px 34px -14px var(--shadow, rgba(0,0,0,.45)); gap:12px;
    animation:rdrSheetUp .2s cubic-bezier(.22,.61,.36,1) both }
  .rdr-backdrop{ background:rgba(0,0,0,.34); z-index:59 }
  .rdr-row{ gap:8px }
  .rdr-opt{ font-size:13.5px; padding:7px 14px }
  .rdr-x{ font-size:26px; padding:2px 8px }
  body.rdr-panel-open{ overflow:hidden }
}
@keyframes rdrSheetUp{ from{ transform:translateY(100%) } to{ transform:translateY(0) } }
@media (prefers-reduced-motion:reduce){ .rdr-panel{ animation:none } }

/* "next puzzle in…" return hook beside the share button */
.dc-nextin{ display:inline-block; margin-left:12px; font-size:12.5px; color:var(--ink-soft);
  font-variant-numeric:tabular-nums }
