
/* Light is the original warm cafe palette. Dark is its espresso sibling — deep warm browns,
   never neutral grey-black — and defines exactly the same variable set, so every rule below
   works in both without knowing which one is on.

   Three states, resolved here so no rule further down has to care:
     data-theme absent  → follow the operating system
     data-theme=light   → forced light, even on a dark OS
     data-theme=dark    → forced dark, even on a light OS  */
:root {
  --cream: #fbf5ec;
  --cream-deep: #f4e9da;
  --card: #fffcf7;
  --ink: #43301f;
  --ink-soft: #7b6455;
  --line: #ecdfcd;
  --accent: #e3899e;
  --accent-soft: #fdedf1;
  --mocha: #a8785a;
  --done: #6d9b62;
  --doing: #d3893c;
  --head-bg: rgba(251, 245, 236, 0.92);
  --hero-top: #fff8ef;
  --frame-top: #fffaf2;
  --doing-bg: #fff6ea;
  --doing-line: #f6e2c6;
  --shelf-bg: #fff8ef;
  --shelf-line: #f0e0c8;
  --pill-line: #f3d3db;
  --radius: 18px;
  --shadow: 0 1px 2px rgba(67, 48, 31, 0.05), 0 8px 24px rgba(67, 48, 31, 0.06);
}

/* The dark values live once, in a custom property block each selector below can pull in. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme='light']) {
    --cream: #1d1613;
    --cream-deep: #271e1a;
    --card: #261e19;
    --ink: #f2e4d5;
    --ink-soft: #bda491;
    --line: #3a2c25;
    --accent: #e79fb1;
    --accent-soft: #3a2229;
    --mocha: #d5a683;
    --done: #8fc084;
    --doing: #e2a763;
    --head-bg: rgba(29, 22, 19, 0.92);
    --hero-top: #2a2019;
    --frame-top: #2b211b;
    --doing-bg: #2e2318;
    --doing-line: #4a3721;
    --shelf-bg: #271d16;
    --shelf-line: #3f2f22;
    --pill-line: #5a3a43;
    --radius: 18px;
    --shadow: 0 1px 2px rgba(0, 0, 0, 0.3), 0 8px 24px rgba(0, 0, 0, 0.35);
  }
}

:root[data-theme='dark'] {
  --cream: #1d1613;
  --cream-deep: #271e1a;
  --card: #261e19;
  --ink: #f2e4d5;
  --ink-soft: #bda491;
  --line: #3a2c25;
  --accent: #e79fb1;
  --accent-soft: #3a2229;
  --mocha: #d5a683;
  --done: #8fc084;
  --doing: #e2a763;
  --head-bg: rgba(29, 22, 19, 0.92);
  --hero-top: #2a2019;
  --frame-top: #2b211b;
  --doing-bg: #2e2318;
  --doing-line: #4a3721;
  --shelf-bg: #271d16;
  --shelf-line: #3f2f22;
  --pill-line: #5a3a43;
  --radius: 18px;
  --shadow: 0 1px 2px rgba(0, 0, 0, 0.3), 0 8px 24px rgba(0, 0, 0, 0.35);
}

* { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  color-scheme: light dark;
  /* The footer is fixed, so an anchor jump has to stop short of it. */
  scroll-padding-bottom: 72px;
}

body {
  margin: 0;
  /* Room for the permanently visible footer bar. */
  padding-bottom: 58px;
  /* Thai has no word spaces; browsers without Thai line-breaking must still not overflow. */
  overflow-wrap: break-word;
  background: var(--cream);
  color: var(--ink);
  font-family: 'Noto Sans Thai', 'Segoe UI', system-ui, -apple-system, sans-serif;
  font-size: 17px;
  line-height: 1.75;
  letter-spacing: 0.01em;
}

h1, h2, h3, .brand {
  font-family: 'Mali', 'Noto Sans Thai', system-ui, sans-serif;
  font-weight: 600;
  line-height: 1.45;
  margin: 0 0 12px;
}

h1 { font-size: 1.7rem; }
h2 { font-size: 1.25rem; }
h3 { font-size: 1.05rem; }

p { margin: 0 0 16px; }

a { color: var(--mocha); text-underline-offset: 3px; }
a:hover { color: var(--accent); }

img { max-width: 100%; height: auto; border-radius: 12px; display: block; }

/* Visually hidden, still read by screen readers (status words on roadmap items). */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

.wrap {
  width: 100%;
  max-width: 720px;
  margin: 0 auto;
  padding: 0 18px;
}

/* ---------- header / nav ---------- */

.site-head {
  position: sticky;
  top: 0;
  z-index: 10;
  background: var(--head-bg);
  backdrop-filter: blur(8px);
  border-bottom: 1px solid var(--line);
}

.site-head .wrap {
  display: flex;
  flex-direction: column;
  gap: 7px;
  padding-top: 10px;
  padding-bottom: 8px;
  min-width: 0;
}

/* Phone: brand and the theme button share the first line, the nav pills take the second. */
.head-top {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: center;
  gap: 8px;
  min-width: 0;
}

/* Row 1 = brand + the two collapsed pickers; row 2 = the nav (room to grow, TK s73 r2). */

.brand {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: 1.05rem;
  margin: 0;
  color: var(--ink);
  text-decoration: none;
}

/* One line that scrolls sideways, never two that stack: with five pills in six languages
   (ロードマップ, 개발 일지, …) wrapping made the sticky header 172px tall on a 390px phone —
   a fifth of the screen, before the fixed footer took its share. */
.nav {
  display: flex;
  flex-wrap: nowrap;
  overflow-x: auto;
  gap: 6px;
  scrollbar-width: none;
  margin: 0 -18px;
  padding: 0 18px 2px;
  /* Flex items default to min-width:auto, which would let the pill row push the whole
     document wider than the phone instead of scrolling inside itself. */
  min-width: 0;
  max-width: 100%;
}
.nav::-webkit-scrollbar { display: none; }

.nav a {
  flex: 0 0 auto;
  padding: 5px 11px;
  border-radius: 999px;
  border: 1px solid transparent;
  color: var(--ink-soft);
  text-decoration: none;
  font-size: 0.92rem;
}

.nav a:hover { background: var(--cream-deep); color: var(--ink); }

.nav a[aria-current='page'] {
  background: var(--accent-soft);
  border-color: var(--pill-line);
  color: var(--ink);
}

/* ---------- the collapsed pickers (language flag + theme face) ---------- */

details.pick { position: relative; }

details.pick > summary {
  list-style: none;
  cursor: pointer;
  width: 34px;
  height: 34px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--card);
  font-size: 1.02rem;
  line-height: 1;
}
details.pick > summary::-webkit-details-marker { display: none; }
details.pick > summary:hover,
details.pick[open] > summary { background: var(--cream-deep); }

.pick-menu {
  position: absolute;
  right: 0;
  top: calc(100% + 8px);
  z-index: 30;
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: 14px;
  box-shadow: var(--shadow);
  padding: 6px;
  display: grid;
  gap: 2px;
  min-width: 172px;
}

.pick-menu a,
.pick-menu button {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 12px;
  border-radius: 10px;
  border: 0;
  background: none;
  color: var(--ink);
  text-decoration: none;
  font: inherit;
  font-size: 0.92rem;
  cursor: pointer;
  text-align: left;
  white-space: nowrap;
}
.pick-menu a:hover,
.pick-menu button:hover { background: var(--cream-deep); }
.pick-menu a[aria-current='true'],
.pick-menu button[aria-pressed='true'] { background: var(--accent-soft); font-weight: 600; }

.pick-flag { width: 1.3em; text-align: center; }

/* The theme picker is dead weight without JS; the flag picker works scriptless. */
html:not(.js) .theme-pick { display: none; }

/* ---------- header controls (row 1, right side) ---------- */

.head-controls {
  display: flex;
  justify-content: flex-end;
  align-items: center;
  gap: 8px;
  min-width: 0;
}

/* ---------- page rhythm ---------- */

/* Breathing room under the sticky header. main IS a .wrap, and .wrap's own padding rule
   outranks a bare element selector (class beats element) — which is why this spacing NEVER
   applied until s73 r3. The compound selector wins. */
main.wrap { padding-top: 40px; padding-bottom: 8px; }

section { margin-bottom: 34px; }

.lede { font-size: 1.02rem; color: var(--ink-soft); }

.eyebrow {
  font-size: 0.8rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--mocha);
  margin-bottom: 6px;
}

.card {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 18px;
  margin-bottom: 14px;
}

a.card { display: block; text-decoration: none; color: inherit; }
a.card:hover { border-color: var(--pill-line); transform: translateY(-1px); transition: 120ms; }

.card h2, .card h3 { margin-bottom: 6px; }
.card p:last-child { margin-bottom: 0; }

/* ---------- home ---------- */

.hero {
  background: linear-gradient(170deg, var(--hero-top) 0%, var(--accent-soft) 100%);
  border: 1px solid var(--line);
  border-radius: 22px;
  padding: 26px 20px 22px;
  margin-bottom: 26px;
}

.hero h1 { margin-bottom: 10px; }
.hero p:last-child { margin-bottom: 0; }

.hero .cat { font-size: 2rem; line-height: 1; display: block; margin-bottom: 10px; }

.cards { display: grid; gap: 14px; }

.card-arrow { color: var(--accent); font-weight: 600; }

.strip { display: grid; gap: 10px; }

.strip .strip-item {
  display: flex;
  gap: 10px;
  align-items: flex-start;
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: 14px;
  padding: 12px 14px;
}

.strip .trophy { flex: 0 0 auto; }
.strip .when { display: block; font-size: 0.85rem; color: var(--ink-soft); }

/* ---------- roadmap ---------- */

.disclaimer {
  background: var(--accent-soft);
  border: 1px solid var(--pill-line);
  border-radius: 14px;
  padding: 12px 16px;
  font-size: 0.94rem;
  color: var(--ink-soft);
  margin-bottom: 26px;
}

.legend {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 16px;
  font-size: 0.9rem;
  color: var(--ink-soft);
  margin-bottom: 26px;
}

.rm-section { margin-bottom: 26px; }

.rm-section h2 {
  border-bottom: 2px solid var(--cream-deep);
  padding-bottom: 6px;
}

.rm-list { list-style: none; margin: 0; padding: 0; }

.rm-item {
  display: flex;
  gap: 10px;
  align-items: flex-start;
  padding: 9px 12px;
  border-radius: 12px;
}

.rm-item + .rm-item { margin-top: 2px; }

.rm-item .mark { flex: 0 0 auto; line-height: 1.75; }

.rm-item .body { flex: 1 1 auto; min-width: 0; }

.rm-item .note {
  display: block;
  font-style: italic;
  font-size: 0.9rem;
  color: var(--ink-soft);
  line-height: 1.6;
}

.rm-item.done .text { color: var(--ink-soft); }
.rm-item.done .mark { color: var(--done); }

.rm-item.doing {
  background: var(--doing-bg);
  border: 1px solid var(--doing-line);
}
.rm-item.doing .text { font-weight: 600; }

.rm-item.doing .cat-sit { margin-left: 6px; }

.rm-item.planned .mark { color: var(--ink-soft); }

/* Sections wear the same card the other pages use — the bare full-bleed lists were what
   made /roadmap read WIDER than its siblings (TK s73 r2). */
.rm-section {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 18px;
  margin-bottom: 14px;
}
.rm-section h2 { margin-top: 0; }

/* --- the one game-scale goal, above every section --- */
.rm-goal { border: 2px solid var(--accent); }
.rm-goal h2 { margin-top: 0; }
.rm-goal .rm-sublist { padding-left: 6px; margin-top: 12px; }
.rm-goal .lede { margin: 6px 0 0; }

/* --- subitem breakdowns (tap the big line, see the steps) --- */
.rm-details summary {
  display: flex; gap: 10px; cursor: pointer; list-style: none; position: relative;
}
.rm-details summary::-webkit-details-marker { display: none; }
.rm-details summary::after {
  content: "▸"; color: var(--ink-soft); font-size: 0.85em;
  position: absolute; right: 2px; top: 2px; transition: transform 0.15s ease;
}
.rm-details[open] summary::after { transform: rotate(90deg); }
.rm-item.has-subs { display: block; }
.rm-chip {
  display: inline-block; font-size: 0.72em; font-weight: 600; color: var(--ink-soft);
  background: var(--card); border: 1px solid var(--line); border-radius: 999px;
  padding: 1px 8px; margin-left: 6px; vertical-align: 1px; white-space: nowrap;
}
.rm-item.doing .rm-chip { color: var(--doing); }
.rm-sublist {
  list-style: none; margin: 8px 0 2px; padding: 0 0 0 30px;
  display: grid; gap: 6px;
}
.rm-subitem { display: flex; gap: 8px; font-size: 0.92em; }
.rm-subitem .mark { flex: 0 0 auto; width: 1.2em; text-align: center; }
.rm-subitem.done { color: var(--ink-soft); }
.rm-subitem.done .text { text-decoration: line-through; text-decoration-thickness: 1px; }
.rm-subitem.planned .mark { color: var(--ink-soft); }

.shelf { background: var(--shelf-bg); border: 1px solid var(--shelf-line); }

.shelf .rm-item { padding-left: 0; }

/* ---------- devlog ---------- */

.entry-list { display: grid; gap: 14px; }

.entry-card { display: flex; flex-direction: column; gap: 10px; }

.entry-card .thumb { width: 100%; aspect-ratio: 16 / 9; object-fit: cover; }

.meta { font-size: 0.88rem; color: var(--ink-soft); }

.badge {
  display: inline-block;
  font-size: 0.75rem;
  padding: 1px 9px;
  border-radius: 999px;
  background: var(--accent-soft);
  border: 1px solid var(--pill-line);
  color: var(--mocha);
  vertical-align: middle;
}

.prose h2 { margin-top: 28px; }
.prose h3 { margin-top: 22px; }
.prose ul, .prose ol { padding-left: 22px; margin: 0 0 16px; }
.prose li { margin-bottom: 6px; }
.prose img { margin: 18px 0; }
.prose blockquote {
  margin: 18px 0;
  padding: 2px 16px;
  border-left: 3px solid var(--accent);
  color: var(--ink-soft);
}

.embed {
  position: relative;
  width: 100%;
  aspect-ratio: 16 / 9;
  margin: 18px 0;
  border-radius: 14px;
  overflow: hidden;
  background: var(--cream-deep);
}
.embed iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }

.back-link { display: inline-block; margin-bottom: 18px; font-size: 0.92rem; }

.empty {
  text-align: center;
  color: var(--ink-soft);
  padding: 26px 12px;
}

/* ---------- art gallery ---------- */

.art-section { margin-bottom: 30px; }

.art-grid {
  display: grid;
  /* minmax(0, …) so a wide strip can never push the column wider than the phone. */
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 12px;
}

.art-card {
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 10px;
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: 14px;
  padding: 10px;
}

/* Animation strips are far wider than tall — they get a whole row to themselves. */
.art-card.strip { grid-column: 1 / -1; }

.art-frame {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 132px;
  padding: 6px;
  border-radius: 10px;
  background: linear-gradient(170deg, var(--frame-top) 0%, var(--cream-deep) 100%);
}

.art-frame img {
  /* The whole point of the page: no smoothing, square pixels, whatever the zoom. */
  image-rendering: pixelated;
  border-radius: 0;
  display: block;
  /* Do NOT add width:auto here. The width/height attributes carry the whole-number zoom as
     a presentational hint, and width:auto quietly overrides it back to the file's native
     size — which is exactly what a browser check caught this doing.
     (No backticks in this file either: STYLES is a template literal.) */
  height: auto;
  max-width: 100%;
}

/* A strip keeps its native size and scrolls inside its own frame, so every frame of the
   animation stays crisp instead of being squashed to phone width. */
.art-card.strip .art-frame {
  justify-content: flex-start;
  overflow-x: auto;
  min-height: 0;
}

.art-card.strip .art-frame img { max-width: none; }

.art-card figcaption {
  font-size: 0.82rem;
  line-height: 1.65;
  color: var(--ink-soft);
}

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

/* Pinned to the bottom of the viewport and visible the whole time, with the page scrolling
   behind it. One slim row, because a permanent bar must not eat a phone screen — body has a
   matching padding-bottom so nothing ever hides underneath. */
.site-foot.is-sticky {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 20;
  margin: 0;
  border-top: 1px solid var(--line);
  background: var(--head-bg);
  backdrop-filter: blur(8px);
  padding: 9px 0;
  font-size: 0.78rem;
  color: var(--ink-soft);
}

.site-foot .wrap {
  display: flex;
  align-items: baseline;
  gap: 10px;
  min-width: 0;
}

.site-foot p { margin: 0; }

/* The tagline yields first: it truncates so the links never get pushed off a 390px screen. */
.foot-line {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}

.foot-links { flex: 0 0 auto; white-space: nowrap; }

/* ---------- wider screens ---------- */

@media (min-width: 600px) {
  body { font-size: 18px; padding-bottom: 52px; }
  h1 { font-size: 2rem; }
  .hero { padding: 34px 30px 30px; }
  .card { padding: 22px; }
  /* auto-fit, not a fixed count: the door row is four cards now and may grow again. */
  .cards { grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); }
  .art-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 14px; }
  .art-frame { min-height: 150px; }
  /* The mobile head-top grid (brand 1fr | pickers auto) is right at every width —
     the old desktop flex override was why the pickers hugged the brand on wide
     screens (TK s73 r3, the ghost). Only the nav loses its edge-bleed scroll here. */
  .nav { margin: 0; padding: 0; }
  .entry-card { flex-direction: row; align-items: flex-start; }
  .entry-card .thumb { width: 190px; flex: 0 0 190px; }
}
