/* ==========================================================================
   strandshinttoday.com — theme "strandshint"
   Newspaper-style layout: one narrow serif text column, double rules, red accents.
   File order: variables -> foundation -> frame -> masthead/nav -> article head ->
   hint ladder -> board -> solver -> editorial block -> list -> navigation ->
   footer.
   ========================================================================== */

:root {
  --paper: #fbfaf6;
  --ink: #191714;
  --ink-soft: #3c3833;
  --muted: #6f695f;
  --rule: #ddd7ca;
  --rule-dark: #191714;
  --accent: #b3261e;
  --accent-soft: #fbeceb;
  --band: #f2efe7;
  --green: #1a6b47;
  --green-soft: #eef4f0;
  --green-rule: #cfe0d6;
  /* BOARD CELL background, much darker than --*-soft. Two dedicated tokens rather than editing
     --green-soft/--accent-soft: those two also fill the background of .reveal and of the word card
     in the solver, where the letters sit on a full-row background and bold would be glaring. The board is the opposite
     back — 48 small cells side by side, a background too pale makes the whole board look like one white block
     and the reader cannot tell which area belongs to which word. */
  --green-fill: #d8e9df;
  --green-line: #a7c9b6;
  --accent-fill: #f6d5d2;
  --accent-line: #dd9a94;
  --serif: Georgia, "Times New Roman", "Noto Serif", serif;
  --sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  --col: 680px;
  --wide: 960px;
  color-scheme: light;
}

* { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--serif);
  font-size: 18px;
  line-height: 1.62;
  -webkit-font-smoothing: antialiased;
}

img { max-width: 100%; height: auto; }
a { color: inherit; }

.wrap {
  max-width: var(--col);
  margin: 0 auto;
  padding: 0 22px 56px;
}

.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  background: var(--ink);
  color: var(--paper);
  padding: 10px 16px;
  font-family: var(--sans);
  font-size: 14px;
  z-index: 50;
}
.skip-link:focus { left: 0; }

/* --------------------------------------------------------- masthead + nav */

.masthead {
  border-bottom: 3px double var(--rule-dark);
  text-align: center;
}

.wordmark {
  display: inline-block;
  padding: 22px 22px 16px;
  text-decoration: none;
}

.wordmark-text {
  font-family: var(--serif);
  font-weight: 700;
  font-size: clamp(28px, 6.4vw, 44px);
  letter-spacing: -0.5px;
  line-height: 1;
  color: var(--ink);
}
/* The last word takes the accent color, like the demo: "Strands Hint Today" with Today in red.
   The text is wrapped in <b> by strands_wordmark_html() — see inc/assets.php. */
.wordmark-text b { color: var(--accent); font-weight: 700; }

.nav {
  border-bottom: 1px solid var(--rule);
  background: var(--paper);
  position: sticky;
  top: 0;
  z-index: 20;
}

.nav-inner {
  max-width: var(--wide);
  margin: 0 auto;
  padding: 0 22px;
  position: relative;
  min-height: 44px;
  display: flex;
  align-items: center;
  justify-content: center;
}

.nav-links { display: flex; gap: 26px; }

.nav-links a {
  font-family: var(--sans);
  font-size: 13px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--ink-soft);
  text-decoration: none;
  padding: 12px 0;
  border-bottom: 2px solid transparent;
}
.nav-links a:hover,
.nav-links a.active { color: var(--accent); border-color: var(--accent); }

.nav-toggle {
  display: none;
  position: absolute;
  left: 22px;
  background: none;
  border: 1px solid var(--rule);
  border-radius: 6px;
  padding: 5px 9px;
  font-size: 15px;
  cursor: pointer;
}

/* --------------------------------------------------------- article header */

.breadcrumb { margin: 18px 0 0; }
.breadcrumb ol {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin: 0;
  padding: 0;
  font-family: var(--sans);
  font-size: 12px;
  color: var(--muted);
}
.breadcrumb li + li::before { content: "\203A"; margin-right: 6px; color: var(--rule); }
.breadcrumb a { color: var(--accent); text-decoration: none; }
.breadcrumb a:hover { text-decoration: underline; }

/* Date strip: centered, runs the full width, the bottom rule continues the rule line of
   masthead and the menu bar. It sits OUTSIDE <main> so it is not constrained by .wrap to 680px —
   see the note in index.php. */
.dateline {
  text-align: center;
  font-family: var(--sans);
  font-size: 12px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted);
  border-bottom: 1px solid var(--rule);
  padding: 10px 22px;
  margin: 0 0 18px;
}
.dateline b { color: var(--accent); }
.dl-sep { color: var(--rule); }

h1.headline {
  font-family: var(--serif);
  font-weight: 700;
  font-size: clamp(29px, 5.2vw, 41px);
  line-height: 1.1;
  letter-spacing: -0.5px;
  margin: 18px 0 10px;
}

.standfirst {
  font-size: 20px;
  line-height: 1.5;
  color: var(--ink-soft);
  margin: 0 0 22px;
}

/* --------------------------------------------------------- prose (from DB) */

.prose p { margin: 0 0 18px; }
.prose h2 {
  font-family: var(--serif);
  font-size: 24px;
  line-height: 1.2;
  margin: 34px 0 10px;
  padding-top: 14px;
  border-top: 2px solid var(--rule-dark);
}
.prose h3 { font-family: var(--serif); font-size: 19px; margin: 24px 0 6px; }
.prose ul, .prose ol { margin: 0 0 18px; padding-left: 24px; }
.prose li { margin: 6px 0; }
.prose a { color: var(--accent); }

/* EXCEPTION FOR .prose a - read before editing the line above.
 *
 * '.prose a' is two identifiers (class + tag), stronger than any single-class rule. 
 * So EVERY shortcode block with a link placed in a post gets tinted red by it, regardless of which block
 * itself declares which color and on which line:
 *
 *   [button]          .btn text color #fff -> loses -> red text on red background, unreadable
 *   [recent_editions] .ed-item declares no color -> the whole title line is red, while
 *                     the same block placed outside the post is black again
 *
 * The fix is to redeclare here with enough specificity, NOT to lower '.prose a'
 * down — lowering it makes lowercase links in a post lose their color, and that is the thing
 * line above is made for. Adding a new link-bearing shortcode block means adding one line
 * to this list. */
.prose a.btn { color: #fff; }
.prose a.ed-item { color: var(--ink); }

/* Link in the FAQ answer. The FAQ tab block (layout/faq.php) sits OUTSIDE
 * .prose so it is not colored by '.prose a'; if not declared here it falls back to
 * 'a { color: inherit }' and the link differs only in lowercase by an underline. Declare
 * once for both paths — the [faq] shortcode and the FAQ tab. */
.faq-body a { color: var(--accent); }
.prose blockquote {
  margin: 20px 0;
  padding: 2px 0 2px 18px;
  border-left: 3px solid var(--accent);
  color: var(--ink-soft);
}
.prose table { width: 100%; border-collapse: collapse; font-size: 16px; margin: 0 0 20px; }
.prose th, .prose td { border-bottom: 1px solid var(--rule); padding: 9px 10px; text-align: left; }
.prose img { display: block; margin: 20px auto; }

/* The first H2 of the body has no separate rule: it sits right below the lead sentence, no need
   a rule to separate it from the part above. */
.prose > h2:first-child { margin-top: 0; padding-top: 0; border-top: 0; }

/* "About the puzzle" area - the [about] shortcode in the Content field, see
   inc/shortcodes.php. One CONTINUOUS block of text, exactly the demo's .evergreen.

   The main point is the three lines that remove the underline below. '.prose h2' draws a horizontal line on each
   heading to split the body into sections — right for an article, but in the
   intro it cuts one continuous flow of text into loose pieces, while the demo lets them run
   continuous. The double rule at the start of the section is the ONLY boundary. */
section.evergreen { border-top: 3px double var(--rule-dark); margin-top: 34px; padding-top: 18px; }
section.evergreen > .kicker { margin-bottom: 10px; }
.prose section.evergreen h2 { border-top: 0; padding-top: 0; margin: 22px 0 8px; }
.prose section.evergreen > h2:first-of-type { margin-top: 0; }
.prose section.evergreen h3 { margin: 18px 0 4px; }

/* --------------------------------------------------------- hint ladder */

.ladder { border-top: 2px solid var(--rule-dark); margin: 26px 0 30px; }

details.rung { border-bottom: 1px solid var(--rule); }

details.rung > summary {
  display: flex;
  align-items: baseline;
  gap: 14px;
  padding: 16px 2px;
  cursor: pointer;
  list-style: none;
  font-family: var(--serif);
}
details.rung > summary::-webkit-details-marker { display: none; }
details.rung > summary:hover .rung-title { color: var(--accent); }

.rung-label {
  font-family: var(--sans);
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--accent);
  flex: none;
  width: 82px;
  line-height: 1.3;
}
.rung-title { font-size: 19px; font-weight: 700; flex: 1; min-width: 0; }
.rung-cue {
  font-family: var(--sans);
  font-size: 12px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--muted);
  white-space: nowrap;
}
details.rung[open] .rung-cue { color: var(--accent); }
/* Both the TEXT and the arrow are generated here - the span in the HTML is left empty. The open tier must
   reads "Hide", not "Show"; see strands_render_rung(). */
details.rung:not([open]) .rung-cue::after { content: "Show \25BE"; }
details.rung[open] .rung-cue::after { content: "Hide \25B4"; }

.rung-body { padding: 0 2px 20px 96px; font-size: 17px; color: var(--ink-soft); }
.rung-body p { margin: 0 0 10px; }
.rung-body p:last-child { margin-bottom: 0; }

/* Editorial comment, printed right below the ladder - not a tier.

   Italic + a vertical rule to read instantly as the AUTHOR'S VOICE, separate from text generated by
   the template generates at the levels above. Negative top margin so it sticks to the ladder: it
   about the board just revealed, not a new paragraph of the article. */
.editor-note {
  border-left: 3px solid var(--rule-dark);
  padding: 2px 0 2px 14px;
  margin: -14px 0 30px;
  font-style: italic;
  font-size: 16.5px;
  color: var(--ink-soft);
}

.reveal { font-family: var(--serif); font-size: 24px; font-weight: 700; color: var(--ink); margin: 0 0 8px; }
.reveal.is-theme { color: var(--green); }
.reveal.is-span { color: var(--accent); }

.answers { list-style: none; padding: 0; margin: 6px 0 0; }
.answers li {
  display: flex;
  justify-content: space-between;
  align-items: center;
  border-bottom: 1px dotted var(--rule);
  padding: 8px 0;
}
.answers li b { font-size: 19px; color: var(--ink); }
.answers li span { font-family: var(--sans); font-size: 12px; color: var(--muted); }

/* --------------------------------------------------------- board */

.board-wrap { overflow-x: auto; }

.board {
  /* relative: anchor for the connecting-stroke SVG layer covering exactly the grid box.
     z-index: 0 so .board is a CLOSED stacking context. The board has three layers that must
     in order — tile background, connecting stroke, then the letter — and the letter can be on top thanks to
     z-index (see .cell-l). Without this line that z-index would climb out and
     stacking with the whole page, e.g. with the sticky header above. */
  position: relative;
  z-index: 0;
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  gap: 5px;
  max-width: 320px;
  margin: 8px 0 6px;
}
.board .cell {
  position: relative;
  aspect-ratio: 1 / 1;
  display: grid;
  place-items: center;
  border: 1px solid var(--rule);
  border-radius: 4px;
  background: #fff;
  font-family: var(--serif);
  font-weight: 700;
  font-size: clamp(14px, 4.2vw, 19px);
  color: var(--ink);
}
.board .cell.is-theme { background: var(--green-fill); border-color: var(--green-line); color: var(--green); }

/* The spangram also differs BY BORDER THICKNESS, not just by color. Green next to pink-red
   is exactly the pair that red-green color blindness cannot separate (see the note in the .strands block
   below); the thick border is a second channel, readable even when the two colors look like one.
   box-sizing: border-box at the top of the file so the 2px does not enlarge the cell. */
.board .cell.is-span {
  background: var(--accent-fill);
  border: 2px solid var(--accent-line);
  color: var(--accent);
}

/* The ordinal number of the cell within its word.
   Absolute in the corner, NOT a grid item: .cell is grid + place-items:center, so
   an element in the flow would become the second item and push the letter off center. */
.board .cell-step {
  position: absolute;
  top: 2px;
  left: 3px;
  font-family: var(--sans);
  font-size: clamp(8px, 2.2vw, 10px);
  font-weight: 600;
  line-height: 1;
  color: inherit;
  opacity: .68;
  pointer-events: none;
  /* On top of the connecting stroke: the number sits in the corner, and the corner is exactly where the stroke enters the cell. */
  z-index: 2;
}

/* The letter sits ON TOP of the connecting stroke. The stroke goes through the cell center, and a letter struck through the middle
   much harder to read — so the paint order is cell background, stroke, text. The cell background is below the stroke because
   DOM order (cell first, <svg> after, same paint step); text goes on top so it must rely on
   z-index, since there is no way to place it after the <svg> in the DOM. */
.board .cell-l { position: relative; z-index: 1; }

/* Stroke connecting letters within the same word - see strands_board_lines() to understand the system
   coordinates (cell = 10 units, gap = 1). */
.board-lines {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
}
.board-lines polyline {
  fill: none;
  /* In viewBox units, so a cell = 10: the stroke is exactly 22% of the cell width at every board size.
     Put in CSS rather than an SVG attribute so it can be edited in one place.

     22% chosen by eye on a real board, not estimated. Thinner (11%) and the stroke
     becomes a thread fainter than the cell background — yet the stroke is what says which cell belongs to which word.
     Thicker (24% with a dark color) and the band covers the letter feet. With a light color like below
     it thickens safely, so use a value close to the above. */
  stroke-width: 2.2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* The stroke takes EXACTLY the cell's border color, not a darker tone.
   The cell border and the connecting stroke then form one system: the stroke reads as the border continuing through the gap
   to the neighboring cell, not a layer of tape pasted over the board. The dark-colored try
   (--green at 50%) separates better but looks like two different objects stacked on
   each other, and it presses down on the foot of the text.
   Fully opaque, no stroke-opacity: where two lines cross at the corner of the gap, the crossing spot
   does not darken into a strange dot. */
.board-lines .bp-theme { stroke: var(--green-line); }
.board-lines .bp-span { stroke: var(--accent-line); }

.board-legend {
  font-family: var(--sans);
  font-size: 12px;
  color: var(--muted);
  display: flex;
  flex-wrap: wrap;
  gap: 4px 16px;
  margin: 6px 0 0;
}
/* The number explanation takes a whole line: cramming it next to the two sample cells on a screen
   narrow the whole cluster breaks into three misaligned lines. */
.board-legend .sw-note {
  flex-basis: 100%;
  font-style: italic;
}
.board-legend i {
  width: 11px;
  height: 11px;
  border-radius: 2px;
  display: inline-block;
  margin-right: 5px;
  vertical-align: -1px;
}
.board-legend .sw-theme { background: var(--green-fill); border: 1px solid var(--green-line); }
.board-legend .sw-span { background: var(--accent-fill); border: 2px solid var(--accent-line); }

/* --------------------------------------------------------- solver

   Tool for the /strands-solver page. Reuses the SHAPE of .board above —
   6-column grid, square cells, same rounded corners and same font size — rather than building a separate board
   second looks different: two different boards on the same site are two things the user
   readers must learn separately. They differ exactly where they should: the other board is for READING, this one
   to CLICK, so the tiles here are bigger and have states.

   The three status colors borrow the theme's own palette: green = found (like the
   theme word), red = in the hint (like the spangram cell). The path fill color is
   comes from JS via --tint, because eight light colors side by side are data, not
   a design decision that needs pinning in CSS. */

.solver {
  border: 1px solid var(--rule);
  background: var(--band);
  padding: 16px;
  margin: 24px 0;
}

.sv-bar {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 14px;
}
.sv-bar button {
  font-family: var(--sans);
  font-size: 13px;
  font-weight: 700;
  padding: 9px 14px;
  border: 1px solid var(--rule-dark);
  border-radius: 4px;
  background: #fff;
  color: var(--ink);
  cursor: pointer;
}
.sv-bar button:hover { background: var(--paper); }
.sv-bar button[data-act="solve"] { background: var(--accent); border-color: var(--accent); color: #fff; }
.sv-bar button[data-act="solve"]:hover { background: #8f1d17; }
.sv-bar button[data-act="stop"] { margin-left: auto; }

/* While running, every button except Stop is unclickable. Clicking "Solve" again
   midway does nothing (JS blocks it), and a clickable button that does not respond
   looks exactly like a broken button. */
.solver.is-busy .sv-bar button:not([data-act="stop"]) { opacity: 0.45; pointer-events: none; }

.sv-board { display: flex; flex-wrap: wrap; gap: 20px; align-items: flex-start; }

.sv-grid {
  display: grid;
  grid-template-columns: repeat(var(--sv-cols, 6), 1fr);
  gap: 5px;
  width: 100%;
  max-width: 300px;
}
.sv-cell {
  aspect-ratio: 1 / 1;
  display: grid;
  place-items: center;
  padding: 0;
  border: 1px solid var(--rule);
  border-radius: 4px;
  background: var(--tint, #fff);
  font-family: var(--serif);
  font-weight: 700;
  font-size: clamp(15px, 4.6vw, 20px);
  color: var(--ink);
  cursor: pointer;
}
.sv-cell:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.sv-cell.is-empty { background: repeating-linear-gradient(135deg, #fff, #fff 4px, var(--band) 4px, var(--band) 8px); }
.sv-cell.is-found { background: var(--green-soft); border-color: var(--green-rule); color: var(--green); }
.sv-cell.is-hint { background: var(--accent-soft); border-color: #ecc6c4; color: var(--accent); }
.sv-cell.is-lit { border-color: var(--rule-dark); }

.sv-side { flex: 1 1 240px; min-width: 220px; }

/* The three text blocks below are anchored to `.solver` instead of standing alone: when the tool
   placed in the middle of a post (the [strands_solver] shortcode) it sits inside `.prose`,
   and `.prose p` — same two classes — would override the margin of a one-class selector. Anchor two classes
   is enough to tie, and this block comes later in the file so it wins. Without it the tool
   look different in the two places it can appear. */
.solver .sv-legend {
  font-family: var(--sans);
  font-size: 12px;
  color: var(--muted);
  margin: 0 0 10px;
}
.solver .sv-legend b { color: var(--ink-soft); }

.sv-type { font-family: var(--sans); font-size: 13px; color: var(--muted); }
.sv-type summary { cursor: pointer; font-weight: 700; color: var(--ink-soft); }
.sv-type textarea {
  display: block;
  width: 100%;
  margin-top: 8px;
  padding: 8px;
  border: 1px solid var(--rule);
  border-radius: 4px;
  background: #fff;
  font-family: ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace;
  font-size: 15px;
  line-height: 1.5;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  resize: vertical;
}

.solver .sv-status {
  font-family: var(--sans);
  font-size: 13px;
  color: var(--muted);
  margin: 14px 0 0;
  min-height: 1.5em;
}
.solver .sv-status.is-bad { color: var(--accent); }

.sv-out { margin-top: 4px; }

.sv-solution { border-top: 1px solid var(--rule); padding: 12px 0 4px; border-left: 3px solid transparent; }
/* The solution is being painted onto the board. Nine eight-hue color sets look similar, so if
   the list does not show which set is currently active, so each click only makes the board change
   color without answering the question "which one am I looking at". */
.sv-solution.is-shown { border-left-color: var(--accent); padding-left: 12px; }
.sv-solution-head {
  display: flex;
  align-items: baseline;
  gap: 10px;
  width: 100%;
  padding: 0 0 8px;
  border: 0;
  background: none;
  font-family: var(--sans);
  cursor: pointer;
  text-align: left;
}
.sv-rank { font-size: 12px; font-weight: 800; letter-spacing: 0.1em; color: var(--accent); }
.sv-count { font-size: 12px; color: var(--muted); }

.sv-words { display: flex; flex-wrap: wrap; gap: 6px; }
.sv-word {
  display: inline-flex;
  align-items: baseline;
  gap: 6px;
  padding: 5px 9px;
  border: 1px solid var(--rule);
  border-radius: 4px;
  background: #fff;
  font-family: var(--sans);
  font-size: 13px;
  font-weight: 700;
  color: var(--ink);
  cursor: pointer;
}
.sv-word:hover { border-color: var(--rule-dark); }
.sv-word-len { font-size: 11px; font-weight: 500; color: var(--muted); }
.sv-word.is-span { background: var(--accent-soft); border-color: #ecc6c4; color: var(--accent); }
.sv-word.is-span .sv-word-len { color: var(--accent); }
/* A rare word still shows - it is real and could be the answer - but faint, because the answer
   of Strands is almost always a word everyone knows. */
.sv-word.is-rare { color: var(--muted); font-weight: 500; }

/* Button that opens the rare words section. Looks like clickable text rather than a button
   action: it does nothing, it only reveals the rest. */
.sv-more {
  display: inline-block;
  margin-top: 10px;
  padding: 6px 0;
  border: 0;
  background: none;
  font-family: var(--sans);
  font-size: 13px;
  font-weight: 700;
  color: var(--accent);
  text-decoration: underline;
  text-underline-offset: 3px;
  cursor: pointer;
}

.solver .sv-phrase { display: flex; align-items: center; gap: 10px; margin: 10px 0 0; }
.sv-phrase-label {
  font-family: var(--sans);
  font-size: 11px;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--muted);
}

/* --------------------------------------------------------- editorial block */

.kicker {
  font-family: var(--sans);
  font-size: 12px;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--accent);
  margin: 0 0 8px;
}

.yesterday { background: var(--band); border: 1px solid var(--rule); padding: 16px 18px; margin: 24px 0; }
.yesterday .kicker { margin-bottom: 4px; }
.y-title { font-weight: 700; font-size: 19px; margin: 0 0 4px; }
.y-span { font-size: 15px; color: var(--muted); margin: 0 0 8px; }
.yesterday a { font-family: var(--sans); font-size: 13px; font-weight: 700; color: var(--accent); text-decoration: none; }
.yesterday a:hover { text-decoration: underline; }

.note, .callout {
  background: var(--band);
  border: 1px solid var(--rule);
  border-left: 4px solid var(--accent);
  padding: 13px 16px;
  margin: 20px 0;
  font-size: 16px;
}
.callout-title { display: block; margin-bottom: 5px; }

.steps { list-style: none; counter-reset: step; padding: 0; margin: 20px 0; }
.steps .step { counter-increment: step; border-top: 1px solid var(--rule); padding: 14px 0 14px 44px; position: relative; margin: 0; }
.steps .step::before {
  content: counter(step);
  position: absolute;
  left: 0;
  top: 14px;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: var(--accent);
  color: #fff;
  font-family: var(--sans);
  font-size: 13px;
  font-weight: 700;
  display: grid;
  place-items: center;
}
.step-title { display: block; font-size: 18px; margin-bottom: 3px; }
.step-body p:last-child { margin-bottom: 0; }

.faq-list { margin: 20px 0; }
details.faq { border-bottom: 1px solid var(--rule); padding: 13px 0; }
details.faq summary { font-weight: 700; font-size: 18px; cursor: pointer; list-style: none; }
details.faq summary::-webkit-details-marker { display: none; }
details.faq summary::after { content: "+"; float: right; color: var(--muted); }
details.faq[open] summary::after { content: "\2013"; }
.faq-body { color: var(--ink-soft); }
.faq-body p { margin: 9px 0 0; }

/* The FAQ block stands alone after the article (FAQ tab in admin). Unlike .faq-list which sits in the middle
   the article where there is a label and needs a top rule so it does not stick to the last paragraph. */
.faq-block { margin: 30px 0 0; }
.faq-block .faq-list { margin: 0; }

details.spoiler-block { border: 1px solid var(--rule); background: var(--band); border-radius: 4px; padding: 10px 14px; margin: 20px 0; }
details.spoiler-block summary {
  font-family: var(--sans);
  font-size: 13px;
  font-weight: 700;
  color: var(--muted);
  cursor: pointer;
  list-style: none;
}
details.spoiler-block summary::-webkit-details-marker { display: none; }
details.spoiler-block summary::before { content: "\1F512  "; }
.spoiler-body { margin-top: 10px; }
.spoiler-body p:last-child { margin-bottom: 0; }

.btn {
  display: inline-block;
  background: var(--accent);
  color: #fff;
  font-family: var(--sans);
  font-size: 14px;
  font-weight: 700;
  text-decoration: none;
  padding: 11px 20px;
  border-radius: 4px;
  margin: 4px 0 20px;
}
.btn:hover { background: #8f1d17; }

/* Game frame - ratio set via --stage-ratio so the layout does not jump when the iframe loads */
/* Game frame - matches the .game-stage declaration in docs/demo-strandshinttoday.html:
   vertical 3/4 frame, max 380px, centered. Those two numbers come from the width/height columns
   of the `game` row (see strands_render_game), so a game of a different shape only needs
   edited in admin; the values below are a fallback when the row has not declared a size.

   Why FIX the width instead of letting it fill the whole article column: the game inside switches by itself to
   horizontal layout when the frame is wider than 32rem, while one fixed ratio applies to every phone
   on a phone the frame would be shorter than the board itself. A narrow frame keeps ONE layout at
   every screen width.

   aspect-ratio rather than `padding-top: <percentage>`: percentage padding is
   projected from the width of the PARENT block, not its own. With max-width in place
   the two numbers differ, and the frame grows with the article column — double the
   it should. */
.game-stage {
  position: relative;
  width: 100%;
  max-width: var(--stage-max, 380px);
  aspect-ratio: var(--stage-aspect, 3 / 4);
  background: var(--band);
  border: 1px solid var(--rule);
  margin: 22px auto;
}
.game-stage iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }

/* Game runs DIRECTLY in the page, not via iframe (Options -> inline_game).

   Do NOT declare height or ratio here. The game's own CSS sets the height for the board
   flag by the block width, and use a container query to ask how wide the block is.
   Adding another aspect-ratio from the theme side gives two sources of truth for the same
   size, and the losing source overflows the frame without any warning.

   Also does not fix the width: this is exactly what is gained by dropping the iframe — the board takes
   the full width of the article column instead of a fixed 380px frame. */
.strands {
  margin: 22px auto;
  border: 1px solid var(--rule);
}

/* Color palette: the game borrows the site's, it does not bring its own palette.

   assets/strands.inline.css declares all the tokens for a STANDALONE page — green
   blue, 12px rounded corners, shadow, Outfit font. That set is right for the game page, and
   placed as-is in the middle of a cream paper page with a serif font, it reads like a
   the ad pasted over the article. The block below draws nothing; it only answers one
   sentence: where to get the color from.

   WHY write the class twice AND also add an attribute: the game's CSS attaches a prefix
   `.strands.strands` (0,2,0) and it loads AFTER this file, so to win it must
   clearly better on score, cannot tie. `.strands[data-strands]` is NOT enough: the attribute
   counts in the same column as a class, so it is also (0,2,0) — a tie, and in a tie the one loaded later
   wins. Measured when written, wrong: --accent in the game still comes out #2a6ab5, blue.
   The three pieces are (0,3,0), a sure win, independent of load order.

   But it still LOSES to two things of the game, and loses exactly where it should: dark mode
   (`[data-theme=dark]`) and high contrast (`[data-contrast=high]`) are also
   (0,3,0) but loads later, so when players change it themselves in the game settings,
   still wins.

   As for `[data-strands]`, let the selector state the condition itself: that is the mark
   "the game attached here".

   `inherit` and not `var()` with --ink, --accent, --accent-soft: three names
   this is the SAME in both palettes, and `--ink: var(--ink)` on the same element is
   self-referential — the CSS treats it as broken and drops the whole declaration, silently. `inherit` takes
   value of the parent element, i.e. of :root, i.e. of the site. */
.strands.strands[data-strands] {
  --bg: var(--paper);
  --surface: #fff;
  --surface-2: var(--band);
  --surface-3: var(--rule);
  --ink: inherit;
  --ink-soft: var(--muted);
  --line: var(--rule);
  --line-strong: var(--rule-dark);
  --accent: inherit;
  --accent-soft: inherit;
  --danger: var(--accent);
  --hint-ring: var(--accent);
  --font: var(--sans);
  /* The letter tiles in the game are ROUND, not rounded squares, so the two values
     this does not touch the board — they are buttons and dialogs. 4px is the rounded corner
     of .btn and .board .cell on the site. */
  --radius: 4px;
  --radius-lg: 8px;
  /* The site has no shadows at all: everything stands out with rule lines. */
  --shadow-1: none;
  --shadow-2: none;
  --shadow-3: none;
}

/* --found (blue = theme word) and --span (yellow = spangram) INTENTIONALLY have no
   in the list above, meaning the game keeps its own two colors, unlike the
   answer in `.board .cell` and in the solver (green / red). Two reasons:

   1. Green next to pink-red is exactly the pair that red-green colorblindness cannot separate. In
      for a static answer table that is tolerable because it comes with a text caption and
      the answer list right below; in the game these two colors are ALL
      the info "which word this cell already belongs to", nothing else to read.
   2. Players coming from real Strands are used to blue/yellow. Changing the colors here is
      forcing them to relearn a convention just to fit the color palette.

   To sync these two colors as well, declare --found/--found-line/--found-ink too
   and --span/--span-line/--span-ink into the block above; no game-side edit needed. */

.game-off {
  font-family: var(--sans);
  font-size: 14px;
  color: var(--muted);
  text-align: center;
  padding: 20px 12px;
  border: 1px solid var(--rule);
  background: var(--band);
}

/* --------------------------------------------------------- list */

.ed-block { border-top: 2px solid var(--rule-dark); margin-top: 36px; padding-top: 14px; }

.ed-list { display: block; }

/* Three cells in one row: date | #number - clue | spangram (right).
   Figures taken from docs/demo-strandshinttoday.html (.ed-row a / .ed-d / .ed-t / .ed-s). */
.ed-item {
  display: flex;
  justify-content: space-between;
  gap: 14px;
  align-items: baseline;
  padding: 12px 2px;
  border-bottom: 1px solid var(--rule);
  text-decoration: none;
}
/* Only a row that IS A LINK changes color on hover. The archive table prints <span.is-flat>
   for days with no article (see strands_render_row) — if that row lit up too
   it promises a click that does not exist. */
a.ed-item:hover .ed-title { color: var(--accent); }
.ed-item.is-flat { cursor: default; }
.ed-item.is-flat .ed-title { font-weight: 600; color: var(--ink-soft); }
.ed-date {
  font-family: var(--sans);
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--muted);
  width: 110px;
  flex: none;
}
.ed-title { font-weight: 700; font-size: 18px; flex: 1; min-width: 0; }
/* nowrap: a spangram is one word, wrapping mid-word would break the right column's row. */
.ed-meta { font-family: var(--sans); font-size: 12px; color: var(--muted); white-space: nowrap; }

/* Answer archive. Shares .ed-item/.ed-date/.ed-title/.ed-meta with the
   the article list — adds only what the article list does not have. */
/* = demo's .arch-year. RED text, thick underline - it is the archive divider,
   not a secondary label. */
.ed-month {
  font-family: var(--sans);
  font-size: 12px;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--accent);
  margin: 24px 0 0;
  padding-bottom: 6px;
  border-bottom: 2px solid var(--rule-dark);
}
.ed-block > .ed-month:first-of-type { margin-top: 10px; }
/* = demo's .arch-years. It is an <a> not a <button>: each year is a URL
   real, middle-click must open a new tab and sharing must work. */
.arc-years { display: flex; flex-wrap: wrap; gap: 8px; margin: 20px 0 4px; }
.arc-year {
  font-family: var(--sans);
  font-size: 13px;
  font-weight: 700;
  text-decoration: none;
  background: var(--paper);
  color: var(--ink-soft);
  border: 1px solid var(--rule);
  border-radius: 4px;
  padding: 8px 18px;
}
.arc-year:hover { border-color: var(--accent); color: var(--accent); }
.arc-year.is-on {
  background: var(--ink);
  color: var(--paper);
  border-color: var(--ink);
}
/* Source note below the list = demo's .arch-note. */
.arc-note { font-family: var(--sans); font-size: 13px; color: var(--muted); margin-top: 14px; }

.empty-note { font-family: var(--sans); font-size: 15px; color: var(--muted); background: var(--band); border: 1px solid var(--rule); padding: 14px 16px; }

.more-link { font-family: var(--sans); font-size: 14px; font-weight: 700; margin: 16px 0 0; }
.more-link a { color: var(--accent); text-decoration: none; }
.more-link a:hover { text-decoration: underline; }

.category-intro { margin-bottom: 26px; }

/* --------------------------------------------------------- navigation */

.pager { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; margin: 34px 0 0; }
.pager a {
  border: 1px solid var(--rule);
  padding: 13px 16px;
  text-decoration: none;
  background: #fff;
}
.pager a:hover { border-color: var(--accent); }
.pager-next { text-align: right; }
.pager-cue {
  display: block;
  font-family: var(--sans);
  font-size: 11px;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--accent);
  margin-bottom: 3px;
}
.pager b { font-size: 17px; font-weight: 700; }
.pager a:only-child { grid-column: 1 / -1; }

.paging { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin: 28px 0 0; font-family: var(--sans); font-size: 14px; }
.paging a, .paging .pg-current {
  display: inline-block;
  min-width: 38px;
  text-align: center;
  padding: 8px 10px;
  border: 1px solid var(--rule);
  text-decoration: none;
  background: #fff;
}
.paging a:hover { border-color: var(--accent); color: var(--accent); }
.paging .pg-current { background: var(--accent); border-color: var(--accent); color: #fff; font-weight: 700; }
.paging .pg-gap { color: var(--muted); }

/* --------------------------------------------------------- footer */

/* Background SAME as the page, not a grey strip: the demo keeps the footer seamless with the body
   the article, the double rule above is the only boundary. */
.site-footer { border-top: 3px double var(--rule-dark); background: var(--paper); margin-top: 44px; }

.footer-inner { max-width: var(--wide); margin: 0 auto; padding: 24px 22px 34px; text-align: center; }

.footer-wordmark {
  font-family: var(--serif);
  font-weight: 700;
  font-size: 22px;
  text-decoration: none;
  color: var(--ink);
  display: inline-block;
}
/* The last word of the site name takes the accent color - same rule as the masthead, see
   strands_wordmark_html() trong inc/assets.php. */
.footer-wordmark b { color: var(--accent); font-weight: 700; }

.footer-legal { display: flex; flex-wrap: wrap; justify-content: center; gap: 14px; margin: 14px 0; }
.footer-legal a { font-family: var(--sans); font-size: 12px; font-weight: 600; color: var(--muted); text-decoration: none; }
.footer-legal a:hover { color: var(--accent); }

/* A thin rule above separates the legal text from the link row. The copyright line sits right
   in this paragraph, not a separate tag — see layout/footer.php. */
.footer-disclaimer {
  font-family: var(--sans);
  font-size: 12px;
  line-height: 1.55;
  color: var(--muted);
  border-top: 1px solid var(--rule);
  padding-top: 14px;
  max-width: 640px;
  margin: 0 auto;
}

/* --------------------------------------------------------- mobile */

@media (max-width: 720px) {
  body { font-size: 17px; }

  .nav-inner { justify-content: flex-start; padding-left: 68px; }
  .nav-toggle { display: block; }
  .nav-links { display: none; flex-direction: column; gap: 0; width: 100%; padding: 6px 0 12px; }
  .nav-links.open { display: flex; }
  .nav-links a { padding: 10px 0; border-bottom: 1px solid var(--rule); }

  .ed-date { width: 88px; }

  .rung-body { padding-left: 2px; }
  .rung-label { width: 70px; }

  .pager { grid-template-columns: 1fr; }
  .pager-next { text-align: left; }

  .ed-date { width: auto; }
  .ed-title { flex-basis: 100%; }
}
