:root {
  --bg: #f4f1ea;
  --panel: #ffffff;
  --ink: #23201b;
  --muted: #6b655c;
  --line: #d8d2c6;
  --line-strong: #b7ae9e;
  --accent: #2f6f4f;
  --accent-soft: #e4efe8;
  --given: #efeae0;
  --blank: #fbfaf6;
  --blank-hover: #f2efe6;
  --red: #b23b3b;
  --black: #23201b;
  --good: #2f6f4f;
  --bad: #c0392b;
  --shadow: 0 1px 2px rgba(0, 0, 0, .06), 0 4px 16px rgba(0, 0, 0, .05);
  font-family: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
}

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  -webkit-font-smoothing: antialiased;
}

.app {
  max-width: 540px;
  margin: 0 auto;
  padding: 24px 16px 64px;
}

/* Centred so the difficulty sits level with the title rather than riding above
   it — they read as one line. */
.topbar {
  display: flex;
  flex-wrap: wrap;
  gap: 16px;
  align-items: center;
  justify-content: space-between;
}

/* Zero flex-basis so the title yields space to the controls instead of pushing
   them onto their own line — a wrapped title beats a dropped header. */
.brand { flex: 1 1 0; min-width: 0; }

.brand h1 {
  margin: 0;
  font-size: 28px;
  letter-spacing: -.02em;
}

.controls {
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  gap: 8px;
  align-items: flex-end;
}

.new-btn {
  border: 1px solid var(--line-strong);
  background: var(--panel);
  color: var(--ink);
  font: inherit;
  font-size: 13px;
  padding: 7px 14px;
  border-radius: 8px;
  cursor: pointer;
  box-shadow: var(--shadow);
}

.new-btn:hover { background: var(--blank-hover); }
.new-btn:disabled { opacity: .5; cursor: default; }

.button-row { display: flex; gap: 8px; }

.puzzle-diff { font-size: 21px; font-weight: 600; text-transform: capitalize; line-height: 1.1; }

/* Status on the left, Hint on the right. Centred rather than baseline-aligned
   so the button sits level with the text rather than hanging below it. */
.statusbar {
  margin: 20px 2px 8px;
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
}

.statusbar .new-btn { flex: 0 0 auto; }

.status { font-size: 14px; }
.status.win { color: var(--good); font-weight: 600; }
.status.err { color: var(--bad); }

/* ---- hint panel ---- */

.hint-panel {
  margin: 0 2px 16px;
  padding: 14px 16px;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 12px;
  box-shadow: var(--shadow);
}

.hint-text {
  margin: 0 0 12px;
  font-size: 14px;
  line-height: 1.55;
}

.hint-nav {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
}

.hint-nav-btn {
  border: 1px solid var(--line-strong);
  background: var(--bg);
  color: var(--ink);
  font: inherit;
  font-size: 13px;
  padding: 6px 12px;
  border-radius: 8px;
  cursor: pointer;
}
.hint-nav-btn:hover:not(:disabled) { background: var(--blank-hover); }
.hint-nav-btn:disabled { opacity: .4; cursor: default; }

.hint-counter { font-size: 12px; color: var(--muted); }

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

.pool-wrap {
  display: flex;
  gap: 12px;
  align-items: stretch;
  justify-content: center;
}

/* ---- pool ---- */

.pool {
  flex: 0 1 auto;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 14px;
  padding: 12px 14px;
  box-shadow: var(--shadow);
}

.starter {
  flex: none;
  width: 96px;
  background: var(--panel);
  color: var(--ink);
  border: 1px solid var(--line);
  border-radius: 14px;
  padding: 12px 10px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 6px;
  text-align: center;
  box-shadow: var(--shadow);
}

.starter-label { font-size: 11px; text-transform: uppercase; letter-spacing: .09em; color: var(--muted); }

.starter-card {
  background: var(--blank);
  color: var(--ink);
  border: 1px solid var(--line);
  border-radius: 9px;
  width: 56px;
  height: 74px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 26px;
  font-variant-numeric: tabular-nums;
}

.starter-note { font-size: 10px; line-height: 1.3; color: var(--muted); }

.pool-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 3px 0;
}

.pool-cards {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

.pool-card {
  min-width: 30px;
  padding: 3px 7px;
  border: 1px solid var(--line);
  border-radius: 7px;
  background: var(--blank);
  font-size: 15px;
  font-variant-numeric: tabular-nums;
  text-align: center;
}

.pool-card.used { opacity: .38; }

/* A blank pool slot is an unknown card, drawn as a dashed box (a "fill me in").
   The border is an inline SVG rather than `border: dashed` so the dashes can be
   made longer than the browser default; non-scaling-stroke keeps them the same
   length whatever the chip's width. */
.pool-card.blank {
  border: none;
  background-color: transparent;
  background-repeat: no-repeat;
  background-size: 100% 100%;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100' preserveAspectRatio='none'%3E%3Crect x='5' y='5' width='90' height='90' rx='9' fill='none' stroke='%23b7ae9e' stroke-width='1.5' stroke-dasharray='7 4' vector-effect='non-scaling-stroke'/%3E%3C/svg%3E");
}

/* Once its card is on the board the blank greys out, but only its content
   fades — the dashed border stays full strength so it is still easy to see. */
.pool-card.blank.used { opacity: 1; }
.pool-card.blank.used .chip-face { opacity: .38; }

.suit-red { color: var(--red); }
.suit-black { color: var(--black); }

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

.board {
  position: relative;
  margin: 16px auto 0;
  display: grid;
  grid-template-columns: 30px repeat(4, 1fr) 30px;
  gap: 7px;
  align-items: stretch;
  max-width: 468px;
  min-width: 420px;
}

.overlay {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  overflow: visible;
}

.hand-box { fill: none; stroke: var(--accent); stroke-width: 1.5; opacity: .5; }
.lead { stroke: var(--accent); stroke-width: 1.5; stroke-linecap: round; opacity: .5; }

.cell { display: flex; }

.card {
  width: 100%;
  aspect-ratio: 3 / 4;
  border-radius: 10px;
  border: 1px solid var(--line);
  background: var(--given);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 23px;
  font-variant-numeric: tabular-nums;
  user-select: none;
}

.card.blank {
  background: var(--blank);
  border: 1px dashed var(--line-strong);
  cursor: pointer;
  transition: background .12s, border-color .12s;
}

.card.blank:hover { background: var(--blank-hover); }
.card.blank.filled { border-style: solid; background: var(--panel); }
.card.blank.filled:hover { border-color: var(--accent); }
.card.blank.empty { color: var(--line-strong); font-size: 22px; }
.card.selected { border-color: var(--accent); box-shadow: 0 0 0 2px var(--accent-soft); }
.card.hinted { animation: hint-flash 1.6s ease; }

@keyframes hint-flash {
  0%, 100% { box-shadow: none; }
  25%, 60% { box-shadow: 0 0 0 3px var(--accent-soft), 0 0 0 4.5px var(--accent); }
}

/* perimeter value chips */

.val {
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 19px;
  font-weight: 600;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}

/* A hand score is never coloured "good". A shown clue you are matching (given)
   is emphasised; a score merely computed from your cards has no shown target, so
   it is de-emphasised in the same ink rather than greened as if it were correct.
   Only an outright error carries colour — plus the wavy underline below. */
.val.given { color: var(--ink); }
.val.computed { color: var(--ink); font-weight: 400; }
.val.bad { color: var(--bad); }
.val.blankval { color: var(--ink); font-weight: 400; }

/* A hand with no shown score can still change as cards move, so it wears a box:
   empty while incomplete, then holding the computed value. A given clue is a
   bare number, so boxed vs bare tells the solver which scores are theirs to
   move. */
.val.computed .score,
.val.blankval .score {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 26px;
  min-height: 24px;
  padding: 0 4px;
  border: 1.5px solid var(--line-strong);
  border-radius: 6px;
  box-sizing: border-box;
}

/* Colour is never the only signal. A contradicted score carries a wavy
   underline (the familiar "error" mark) so it stands apart for red-green
   colour-vision deficiency, not just by hue. */
.val.bad .score,
.total-row .total.bad {
  text-decoration: underline wavy var(--bad);
  text-decoration-thickness: 1.5px;
  text-underline-offset: 3px;
}

.square {
  border-radius: 9px;
  color: var(--ink);
  font-size: 18px;
}

.square.given { color: var(--ink); }
.square.bad { color: var(--bad); }
.square.blankval { color: var(--ink); }

.total-row {
  margin-top: 16px;
  display: flex;
  justify-content: flex-end;
  align-items: baseline;
  gap: 10px;
  padding-right: 2px;
}

.total-row .label { font-size: 13px; color: var(--muted); text-transform: uppercase; letter-spacing: .08em; }
.total-row .total {
  font-size: 24px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  min-width: 72px;
  text-align: right;
}
/* Green is reserved for one meaning only: the whole puzzle is solved. It never
   appears on an individual score, and always comes with the check, so success
   reads without relying on green. */
.total-row .total.solved { color: var(--accent); }
.total-row .total.bad { color: var(--bad); }
.total-row .total.blankval { color: var(--ink); font-weight: 400; }

.total-row .total.solved::after {
  content: " ✓";
  font-size: .7em;
  font-weight: 600;
}


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

.pagefoot {
  margin: 32px 0 0;
  padding-top: 16px;
  border-top: 1px solid var(--line);
}
.footlinks {
  margin: 10px 0 0;
  font-size: 12.5px;
  color: var(--muted);
}
.footlinks a { color: var(--muted); text-decoration: underline; }
.footlinks a:hover { color: var(--ink); }

.copyright {
  margin: 6px 0 0;
  font-size: 11.5px;
  line-height: 1.5;
  color: var(--muted);
}


/* ---- how-to page ---- */

.doc { max-width: 640px; }
.doc-head h1 { margin: 0 0 10px; font-size: 30px; letter-spacing: -.02em; }
.doc-lede { margin: 0 0 14px; font-size: 15px; line-height: 1.6; }
.doc-meta { margin: 0 0 14px; font-size: 12.5px; color: var(--muted); }

.doc-section {
  margin: 26px 0 0;
  padding: 18px 20px;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 14px;
  box-shadow: var(--shadow);
}
.doc-section h2 { margin: 0 0 10px; font-size: 19px; }
.doc-section h3 { margin: 20px 0 8px; font-size: 15px; }
.doc-section p { margin: 0 0 12px; font-size: 14px; line-height: 1.65; }
.doc-section ul { margin: 0 0 12px; padding-left: 20px; }
.doc-section li { font-size: 14px; line-height: 1.65; margin-bottom: 5px; }

.doc-note {
  padding: 10px 12px;
  background: var(--accent-soft);
  border-left: 3px solid var(--accent);
  border-radius: 0 8px 8px 0;
  font-size: 13.5px;
}
.doc-sub { color: var(--muted); font-size: 13px; }
.doc-caption { margin: 10px 0 0; color: var(--muted); font-size: 13px; }
.doc-figure { margin: 14px 0 16px; }

/* Inline card chip, echoing the pool's look at prose size. */
.pc {
  display: inline-block;
  min-width: 26px;
  padding: 1px 5px;
  margin: 0 1px;
  border: 1px solid var(--line);
  border-radius: 6px;
  background: var(--blank);
  font-size: 13px;
  text-align: center;
  white-space: nowrap;
}
.pc.blank { border-style: dashed; color: var(--muted); }

.mini-grid {
  display: grid;
  grid-template-columns: repeat(4, 40px);
  gap: 4px;
}
.mini-cell {
  height: 40px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1px dashed var(--line-strong);
  border-radius: 8px;
  background: var(--blank);
  color: var(--muted);
  font-size: 12px;
}
.mini-cell.sq { background: var(--accent-soft); border-style: solid; border-color: var(--accent); color: var(--accent); }

.doc-table { width: 100%; border-collapse: collapse; margin: 4px 0 14px; }
.doc-table th, .doc-table td {
  text-align: left;
  padding: 9px 10px;
  border-bottom: 1px solid var(--line);
  font-size: 13.5px;
  line-height: 1.55;
  vertical-align: top;
}
.doc-table th { font-size: 12px; text-transform: uppercase; letter-spacing: .04em; color: var(--muted); }
.doc-table td:last-child { width: 68px; white-space: nowrap; color: var(--accent); font-weight: 600; }

.doc-calc { list-style: none; padding-left: 0; }
.doc-calc li { padding: 5px 0; border-bottom: 1px solid var(--line); }
.doc-total { margin-top: 10px; font-size: 15px; }


.day-link { font-size: 13px; color: var(--accent); text-decoration: none; }
.day-link:hover { text-decoration: underline; }

/* Day navigation: prev / date / next between the header and the status line.
   The equal side columns keep the date on the page's centre line whichever
   links are present, while the links align inwards — right-aligned on the left,
   left-aligned on the right — so they sit against the date they step from
   rather than out at the page edges. */
.daynav {
  margin: 12px 2px 0;
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: baseline;
  gap: 16px;
}
.nav-prev { grid-column: 1; justify-self: end; }
.nav-date {
  grid-column: 2;
  text-align: center;
  color: var(--muted);
  font-size: 13px;
  white-space: nowrap;
}
.nav-next { grid-column: 3; justify-self: start; }

/* ---- first-visit greeting ---- */

.welcome-overlay {
  position: fixed;
  inset: 0;
  background: rgba(20, 18, 14, .28);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 16px;
  z-index: 30;   /* above the entry tool, which cannot be open this early */
}

.welcome-overlay[hidden] { display: none; }

.welcome {
  width: 100%;
  max-width: 400px;
  background: var(--panel);
  border-radius: 16px;
  box-shadow: 0 12px 40px rgba(0, 0, 0, .28);
  padding: 22px;
}

.welcome-title { margin: 0 0 10px; font-size: 17px; }
.welcome-text { margin: 0 0 18px; font-size: 14px; line-height: 1.5; color: var(--muted); }

.welcome-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
}

.welcome-btn {
  flex: 1 1 auto;
  border: 1px solid var(--line-strong);
  border-radius: 9px;
  background: var(--panel);
  color: var(--ink);
  padding: 9px 14px;
  font: inherit;
  font-size: 13.5px;
  text-align: center;
  text-decoration: none;
  cursor: pointer;
  box-shadow: var(--shadow);
}

.welcome-btn:hover { background: var(--blank-hover); }

.welcome-primary {
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
}
.welcome-primary:hover { background: var(--accent); opacity: .92; }

/* ---- picker ---- */

.picker-overlay {
  position: fixed;
  inset: 0;
  background: rgba(20, 18, 14, .28);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 16px;
  z-index: 20;
}

.picker-overlay[hidden] { display: none; }

.picker { will-change: transform; }

.picker {
  width: 100%;
  max-width: 440px;
  background: var(--panel);
  border-radius: 16px;
  box-shadow: 0 12px 40px rgba(0, 0, 0, .28);
  overflow: hidden;
}

.picker-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 14px 16px;
  border-bottom: 1px solid var(--line);
  cursor: grab;
  touch-action: none;
  user-select: none;
}

.picker-head.dragging { cursor: grabbing; }

.picker-title { font-size: 15px; font-weight: 600; display: flex; align-items: center; gap: 8px; }
.picker-title::before {
  content: "";
  width: 16px;
  height: 10px;
  flex: none;
  background-image: radial-gradient(currentColor 1px, transparent 1.4px);
  background-size: 5px 5px;
  opacity: .4;
}

.picker-close {
  border: 0; background: transparent; cursor: pointer;
  font-size: 22px; line-height: 1; color: var(--muted);
}

.picker-body { padding: 16px; }

.picker-section { margin-bottom: 18px; }
.picker-section:last-child { margin-bottom: 0; }
.picker-label { font-size: 12px; color: var(--muted); text-transform: uppercase; letter-spacing: .07em; margin: 0 0 9px; }

.pick-row {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  align-items: center;
}

.deck-row { margin-bottom: 6px; }
.deck-row:last-child { margin-bottom: 0; }

/* `color` and `appearance` are set explicitly: without them iOS Safari paints
   button text in its own system blue, which left the ranks blue while the suit
   glyphs — which set their own colour — stayed red/black. */
.pick {
  appearance: none;
  -webkit-appearance: none;
  border: 1px solid var(--line);
  background: var(--blank);
  color: var(--ink);
  border-radius: 9px;
  font: inherit;
  font-size: 18px;
  min-width: 36px;
  padding: 7px 9px;
  cursor: pointer;
  font-variant-numeric: tabular-nums;
}

.pick:hover { background: var(--blank-hover); border-color: var(--line-strong); }

.pick-empty { font-size: 13px; color: var(--muted); }

/* ---- phones ----------------------------------------------------------------
   The board is the constraint: at its desktop metrics it is 420px wide, so a
   375px phone had to scroll sideways to see the right-hand column and its
   scores. Trimming the score gutters, the gap and the card text lets the whole
   grid fit on screen, which matters more here than card size. */

@media (max-width: 480px) {
  .app { padding: 20px 10px 48px; }

  /* Title and controls stack — there is no room to sit side by side. */
  .brand { flex: 1 1 100%; }
  .brand h1 { font-size: 24px; }
  .controls { flex-direction: row; align-items: center; gap: 10px; width: 100%; }
  .puzzle-diff { font-size: 14px; flex: 1 1 auto; }

  /* minmax(0,…) so a card's intrinsic width cannot push the track past its
     share and reintroduce a sliver of horizontal scroll. */
  .board { min-width: 0; width: 100%; grid-template-columns: 24px repeat(4, minmax(0, 1fr)) 24px; gap: 5px; }
  .card { font-size: 19px; border-radius: 8px; }
  .card.blank.empty { font-size: 18px; }
  .val { font-size: 16px; }
  /* The score box must fit inside the narrowed gutter or it spills over. */
  .val.computed .score,
  .val.blankval .score { min-width: 22px; min-height: 22px; padding: 0 2px; }

  .total-row { margin-top: 12px; gap: 8px; }
  .total-row .total { font-size: 21px; min-width: 62px; }

  .pool-wrap { gap: 8px; }
  .pool { padding: 10px; }
  .starter { width: 78px; padding: 10px 6px; }

  .hint-panel { padding: 12px 13px; }
  .hint-text { font-size: 13.5px; }
  .hint-nav-btn { padding: 7px 10px; }

  .daynav { margin-top: 12px; }

  .doc-section { padding: 15px 14px; }
  .doc-head h1 { font-size: 25px; }
  .mini-grid { grid-template-columns: repeat(4, 34px); }
  .mini-cell { height: 34px; }
}

/* Very small phones (SE-class): claw back a little more room. */
@media (max-width: 350px) {
  .app { padding: 18px 8px 44px; }
  .board { grid-template-columns: 20px repeat(4, minmax(0, 1fr)) 20px; gap: 4px; }
  .card { font-size: 17px; }
  .val { font-size: 14px; }
  .val.computed .score,
  .val.blankval .score { min-width: 18px; min-height: 20px; padding: 0 1px; }
}
