/* ============================================================
   Soultale. A reading surface first, and a catalogue second.

   Themes are tokens only. Every component reads the tokens, so a new
   theme is six values and touches nothing else.
   ============================================================ */

/* Monster Friend, the fan face that carries the Undertale logo look. It is
   two fonts, not one: Back draws the shadow and Fore draws the fill, and the
   wordmark stacks them. */
@font-face { font-family: "Monster Friend Back"; src: url("/fonts/MonsterFriendBack.woff") format("woff"); font-display: block; }
@font-face { font-family: "Monster Friend Fore"; src: url("/fonts/MonsterFriendFore.woff") format("woff"); font-display: block; }
@font-face { font-family: "Bungee"; src: url("/fonts/bungee-400.woff2") format("woff2"); font-weight: 400; font-display: swap; }
@font-face { font-family: "Inter"; src: url("/fonts/inter-400.woff2") format("woff2"); font-weight: 400; font-display: swap; }
@font-face { font-family: "Inter"; src: url("/fonts/inter-600.woff2") format("woff2"); font-weight: 600; font-display: swap; }
@font-face { font-family: "Ubuntu"; src: url("/fonts/ubuntu-400.woff2") format("woff2"); font-weight: 400; font-display: swap; }
@font-face { font-family: "Ubuntu"; src: url("/fonts/ubuntu-700.woff2") format("woff2"); font-weight: 700; font-display: swap; }
@font-face { font-family: "Lexend"; src: url("/fonts/lexend-400.woff2") format("woff2"); font-weight: 400; font-display: swap; }
@font-face { font-family: "Atkinson Hyperlegible"; src: url("/fonts/atkinson-400.woff2") format("woff2"); font-weight: 400; font-display: swap; }
@font-face { font-family: "JetBrains Mono"; src: url("/fonts/jetbrainsmono-400.woff2") format("woff2"); font-weight: 400; font-display: swap; }
@font-face { font-family: "OpenDyslexic"; src: url("/fonts/opendyslexic-400.woff2") format("woff2"); font-weight: 400; font-display: swap; }
@font-face { font-family: "Comic Neue"; src: url("/fonts/comicneue-400.woff2") format("woff2"); font-weight: 400; font-display: swap; }

:root {
  --ui: "Inter", system-ui, sans-serif;
  --mono: "JetBrains Mono", ui-monospace, "SFMono-Regular", Menlo, monospace;
  --display: "Monster Friend Fore", "Bungee", "Inter", system-ui, sans-serif;
  --display-back: "Monster Friend Back", "Bungee", "Inter", system-ui, sans-serif;
  --reading: Georgia, "Times New Roman", serif;
  --reading-size: 18px;
  --reading-leading: 1.75;
  --measure: 40rem;
  --align: left;

  /* Classic, dark. Every other theme redefines only these. */
  --ground: #0d0d10;
  --panel: #141418;
  --raised: #1c1c22;
  --line: #26262e;
  --text: #e8e6ea;
  --muted: #9a97a3;
  --accent: #e23b4e;
  --accent-ink: #fff;
  --radius: 10px;
}

[data-theme="vintage"] { --ground:#12110c; --panel:#1a1811; --raised:#231f16; --line:#332e20; --text:#ece5d2; --muted:#a8a08a; --accent:#c9a227; --accent-ink:#1a1811; }
[data-theme="lipstick"] { --ground:#140b0e; --panel:#1d1014; --raised:#26161b; --line:#3a2129; --text:#f2e4e8; --muted:#b294a0; --accent:#e8506e; --accent-ink:#1d1014; }
[data-theme="ocean"]    { --ground:#080f1a; --panel:#0e1826; --raised:#142033; --line:#1e2d45; --text:#dfe9f5; --muted:#8ba3bf; --accent:#3d9bff; --accent-ink:#08111d; }
[data-theme="cyber"]    { --ground:#0d0818; --panel:#150e24; --raised:#1d1430; --line:#2c1f47; --text:#e9e0f7; --muted:#a394c2; --accent:#a855f7; --accent-ink:#12091f; }
[data-theme="nature"]   { --ground:#080f0b; --panel:#0e1812; --raised:#142018; --line:#1f3128; --text:#e0efe5; --muted:#8fb09c; --accent:#3fbf7f; --accent-ink:#07120c; }

[data-mode="light"] {
  --ground:#f6f5f7; --panel:#fff; --raised:#f0eef2; --line:#e0dde4;
  --text:#17161a; --muted:#605c68; --accent:#c02539; --accent-ink:#fff;
}
[data-mode="light"][data-theme="vintage"] { --ground:#f7f3e7; --panel:#fffdf6; --raised:#f1ead6; --line:#e0d6bd; --text:#2a2415; --muted:#6d6448; --accent:#96760f; }
[data-mode="light"][data-theme="lipstick"] { --ground:#fdf2f4; --panel:#fff; --raised:#f8e6ea; --line:#efd3da; --text:#2b1219; --muted:#7a5764; --accent:#c2244a; }
[data-mode="light"][data-theme="ocean"] { --ground:#eef4fb; --panel:#fff; --raised:#e3edf8; --line:#cfdcec; --text:#0d1b2b; --muted:#4f6480; --accent:#1668c9; }
[data-mode="light"][data-theme="cyber"] { --ground:#f4effb; --panel:#fff; --raised:#ebe2f7; --line:#dccef0; --text:#1b1030; --muted:#5f5080; --accent:#7c2ecc; }
[data-mode="light"][data-theme="nature"] { --ground:#eef6f0; --panel:#fff; --raised:#e2f0e7; --line:#cde0d4; --text:#0d1c13; --muted:#4c6857; --accent:#1a8a54; }

[data-font="ubuntu"]   { --reading: "Ubuntu", sans-serif; }
[data-font="lexend"]   { --reading: "Lexend", sans-serif; }
[data-font="atkinson"] { --reading: "Atkinson Hyperlegible", sans-serif; }
[data-font="comic"]    { --reading: "Comic Neue", cursive, sans-serif; }
[data-font="mono"]     { --reading: var(--mono); }
[data-font="dyslexic"] { --reading: "OpenDyslexic", "Atkinson Hyperlegible", sans-serif; }
[data-align="center"]  { --align: center; }
[data-align="justify"] { --align: justify; }

* { box-sizing: border-box; }
html { scroll-behavior: smooth; }
body {
  margin: 0; background: var(--ground); color: var(--text);
  font-family: var(--ui); font-size: 15px; line-height: 1.55;
  -webkit-font-smoothing: antialiased;
}
a { color: inherit; }
button { font: inherit; color: inherit; background: none; border: none; cursor: pointer; }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 4px; }
.sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }

/* ---------- wordmark ---------- */
/* The wordmark stacks the two layers. The back layer is drawn by a sibling
   rather than a pseudo element, because it has to carry its own font family
   and sit in the same place to the pixel. */
.wordmark {
  font-family: var(--display); font-size: 1.1rem; letter-spacing: 0.02em;
  text-decoration: none; display: inline-grid; line-height: 1; position: relative;
}
.wordmark > span { grid-area: 1 / 1; }
.wordmark .back { font-family: var(--display-back); color: var(--accent); }
.wordmark .fore { font-family: var(--display); color: var(--text); }
.hero h1 .back, .hero h1 .fore { grid-area: 1 / 1; }
.hero h1.wordmark { font-size: clamp(2rem, 6vw, 4rem); }

/* ---------- shell ---------- */
.shell { display: grid; grid-template-columns: 300px minmax(0, 1fr); min-height: 100vh; }
/* No sidebar means one column. It must not be two, because with no aside in
   the markup the main panel becomes the first child and lands in whatever the
   first column is. */
.shell.wide { grid-template-columns: minmax(0, 1fr); }
/* Folds rather than vanishing. The column is a length at both ends, which is
   what lets it animate, and the panel clips its own contents so the text does
   not reflow on the way. The state is on the root, so the script in the head
   sets it before the first paint and the fold never plays on arrival. */
.shell { transition: grid-template-columns 0.24s ease; }
.side { overflow: hidden; }
.side > * { width: 300px; }
:root[data-side="closed"] .shell:not(.wide) { grid-template-columns: 0 minmax(0, 1fr); }
:root[data-side="closed"] .side { border-right-color: transparent; }
@media (max-width: 900px) {
  .shell, :root[data-side="closed"] .shell:not(.wide) { grid-template-columns: minmax(0, 1fr); }
}

/* ---------- sidebar ---------- */
.side {
  background: var(--panel); border-right: 1px solid var(--line);
  display: flex; flex-direction: column; max-height: 100vh; position: sticky; top: 0;
}
@media (max-width: 900px) { .side { display: none; } .side.open { display: flex; position: fixed; inset: 0; z-index: 40; max-height: none; } }
.side-head { display: flex; gap: 0.85rem; padding: 1rem; border-bottom: 1px solid var(--line); }
.side-head .cover { width: 62px; aspect-ratio: 1024 / 1600; border-radius: 6px; flex: none; overflow: hidden; }
.side-head h1 { font-size: 0.95rem; margin: 0 0 0.25rem; line-height: 1.3; font-weight: 600; }
.side-head p { margin: 0; font-size: 0.78rem; color: var(--muted); }
.side-list { overflow-y: auto; padding: 0.5rem 0 2rem; margin: 0; list-style: none; }
.side-list a {
  display: block; padding: 0.55rem 1rem; font-size: 0.85rem; text-decoration: none;
  color: var(--muted); border-left: 2px solid transparent;
}
.side-list a:hover { color: var(--text); background: var(--raised); }
.side-list a[aria-current="page"] { color: var(--accent); border-left-color: var(--accent); background: var(--raised); }
.side-group { padding: 1rem 1rem 0.35rem; font-size: 0.68rem; letter-spacing: 0.12em; text-transform: uppercase; color: var(--muted); }

/* ---------- bars ---------- */
.main { display: flex; flex-direction: column; min-height: 100vh; min-width: 0; }
/* Three columns, so the middle is centred against the window rather than
   against whatever the two sides happen to weigh. */
.bar {
  display: grid; grid-template-columns: 1fr auto 1fr; align-items: center;
  gap: 0.5rem; padding: 0.55rem 0.9rem;
  background: var(--panel); border-bottom: 1px solid var(--line);
  position: sticky; top: 0; z-index: 20;
}
.bar-side { display: flex; align-items: center; gap: 0.35rem; min-width: 0; }
.bar-side.end { justify-content: flex-end; }
.bar-mid { display: flex; justify-content: center; min-width: 0; }
.act-tag { display: flex; align-items: baseline; gap: 0.55rem; min-width: 0; }
.act-tag { font-family: var(--mono); }
.act-no { font-size: 0.78rem; letter-spacing: 0.06em; color: var(--accent); white-space: nowrap; }
.act-name {
  font-size: 0.82rem; letter-spacing: 0.01em; color: var(--text);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
@media (max-width: 700px) { .act-name { display: none; } }
.bar.bottom {
  display: flex; border-bottom: none; border-top: 1px solid var(--line);
  position: sticky; top: auto; bottom: 0;
}
.bar .spacer { flex: 1; }
.icon {
  width: 34px; height: 34px; display: inline-grid; place-items: center;
  border-radius: 8px; color: var(--muted); text-decoration: none;
}
.icon:hover { background: var(--raised); color: var(--text); }
.icon svg { width: 18px; height: 18px; stroke: currentColor; fill: none; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.bar .where { font-size: 0.8rem; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ---------- reading ---------- */
.reading { flex: 1; padding: clamp(1.5rem, 4vw, 3.5rem) 1.25rem 4rem; }
.reading-inner { max-width: var(--measure); margin: 0 auto; }
.chapter-no { font-size: 0.72rem; letter-spacing: 0.14em; text-transform: uppercase; color: var(--muted); margin: 0 0 0.5rem; }
.reading h1 { font-size: clamp(1.5rem, 3vw, 2rem); line-height: 1.2; margin: 0 0 2rem; font-weight: 600; }
.prose { font-family: var(--reading); font-size: var(--reading-size); line-height: var(--reading-leading); text-align: var(--align); }
.prose p { margin: 0 0 1.1em; }
.prose em, .prose i { font-style: italic; }
.bracket {
  font-family: var(--reading); font-style: italic; color: var(--muted);
  margin: 2.25rem 0 0; padding-top: 1.1rem; border-top: 1px solid var(--line);
}
.bracket p { margin: 0; }
.run + .run { margin-top: 3rem; }
.run-head {
  display: flex; align-items: baseline; gap: 0.75rem; margin: 0 0 1.5rem;
  padding-top: 2.5rem; border-top: 1px solid var(--line); font-size: 1.05rem; font-weight: 600;
}
.run-head .n { font-size: 0.72rem; color: var(--muted); font-family: var(--ui); }

/* ---------- catalogue ---------- */
.hero { position: relative; padding: clamp(2rem, 5vw, 4rem) clamp(1.25rem, 5vw, 4rem) 2.5rem; overflow: hidden; }
.hero::before {
  content: ""; position: absolute; inset: -30% -10% auto; height: 70%;
  background: radial-gradient(60% 100% at 30% 0%, var(--accent) 0%, transparent 70%);
  opacity: 0.16; pointer-events: none;
}
.hero-in { position: relative; display: flex; gap: clamp(1.25rem, 4vw, 3rem); max-width: 70rem; margin: 0 auto; flex-wrap: wrap; }
.hero .cover { width: min(230px, 40vw); aspect-ratio: 1024 / 1600; border-radius: var(--radius); flex: none; }
.hero-body { flex: 1 1 20rem; min-width: 0; }
.hero h1 { font-family: var(--display); font-size: clamp(1.6rem, 4vw, 2.6rem); line-height: 1.15; margin: 0 0 0.5rem; }
.hero .by { color: var(--muted); margin: 0 0 1rem; }
.chips { display: flex; flex-wrap: wrap; gap: 0.4rem; margin: 0 0 1.25rem; padding: 0; list-style: none; }
.chip {
  font-size: 0.72rem; padding: 0.25rem 0.6rem; border-radius: 999px;
  background: var(--raised); border: 1px solid var(--line); color: var(--muted);
}
.cta { display: flex; gap: 0.6rem; flex-wrap: wrap; margin: 0 0 1.25rem; }
.btn {
  display: inline-flex; align-items: center; gap: 0.45rem; padding: 0.6rem 1.1rem;
  border-radius: 8px; border: 1px solid var(--line); background: var(--raised);
  font-size: 0.85rem; font-weight: 600; text-decoration: none;
}
.btn.primary { background: var(--accent); border-color: var(--accent); color: var(--accent-ink); }
.btn:hover { filter: brightness(1.1); }
.blurb { color: var(--muted); max-width: 46rem; margin: 0 0 1.25rem; }

/* width:100% matters. The main panel is a column flexbox, and an auto margin
   on the cross axis cancels the stretch, so without a width this shrinks to
   its own contents and the grid inside it gets one column. */
.section {
  width: 100%; max-width: 70rem; margin-inline: auto;
  padding: 0 clamp(1.25rem, 5vw, 4rem) 3rem;
}
.section h2 {
  font-size: 0.95rem; margin: 0 0 1rem; padding-left: 0.6rem;
  border-left: 3px solid var(--accent);
}
.grid { display: grid; gap: 1.1rem; grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); }

/* The acts run along a line and wrap onto the next when the line runs out.
   The columns are a fixed width rather than a share of the row, so a cover is
   the same size whatever the window does and the last row does not stretch to
   fill itself. */
.rail {
  display: grid; grid-template-columns: repeat(auto-fill, 170px);
  justify-content: start; gap: 1.75rem 1.4rem; padding: 0.25rem 0 1rem;
}
.rail .card .t { font-size: 0.9rem; line-height: 1.35; margin-top: 0.15rem; }
.rail .card .s { font-size: 0.76rem; }
.rail .cover { border-radius: 10px; margin-bottom: 0.6rem; }
@media (max-width: 480px) { .rail { grid-template-columns: repeat(auto-fill, 140px); gap: 1.25rem 1rem; } }
.card { text-decoration: none; display: block; }
.card .cover { aspect-ratio: 1024 / 1600; border-radius: 8px; margin-bottom: 0.5rem; transition: transform 0.15s ease; }
.card:hover .cover { transform: translateY(-3px); }
.card .t { font-size: 0.8rem; line-height: 1.35; display: block; }
.card .s { font-size: 0.72rem; color: var(--muted); }
.card.held { opacity: 0.55; }

/* A generated cover. Real art drops into the same box. */
.cover { position: relative; display: grid; place-items: center; text-align: center; padding: 0.6rem; overflow: hidden;
  aspect-ratio: 1024 / 1600;
  background: linear-gradient(160deg, var(--raised), var(--panel)); border: 1px solid var(--line); }
.cover img { width: 100%; height: 100%; object-fit: cover; display: block; }
.cover .ct { font-family: var(--display); font-size: 0.62rem; line-height: 1.35; color: var(--text); }
.cover .cn { position: absolute; top: 0.4rem; left: 0.5rem; font-size: 0.58rem; color: var(--accent); letter-spacing: 0.1em; }

footer.site { border-top: 1px solid var(--line); background: var(--panel); margin-top: 2rem; }
footer.site .cols { max-width: 70rem; margin: 0 auto; padding: 2.5rem clamp(1.25rem, 5vw, 4rem); display: grid; gap: 2rem; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); }
footer.site h3 { font-size: 0.68rem; letter-spacing: 0.12em; text-transform: uppercase; color: var(--muted); margin: 0 0 0.7rem; }
footer.site ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.4rem; font-size: 0.82rem; }
footer.site a { color: var(--muted); text-decoration: none; }
footer.site a:hover { color: var(--text); }

/* ---------- options panel ---------- */
.opts {
  position: fixed; top: 0; right: 0; bottom: 0; width: min(320px, 88vw); z-index: 60;
  background: var(--panel); border-left: 1px solid var(--line);
  transform: translateX(100%); transition: transform 0.22s ease;
  overflow-y: auto; padding: 1rem 1rem 3rem;
}
.opts[data-open="true"] { transform: none; }
.opts h2 { font-size: 0.8rem; margin: 0 0 0.9rem; display: flex; align-items: center; }
.preview {
  border: 1px solid var(--line); border-radius: var(--radius); background: var(--raised);
  padding: 1.1rem; text-align: center; margin-bottom: 1rem;
  font-family: var(--reading); font-size: var(--reading-size); line-height: var(--reading-leading);
}
.opt-group { margin-bottom: 1.1rem; }
.opt-label { font-size: 0.68rem; letter-spacing: 0.12em; text-transform: uppercase; color: var(--muted); margin: 0 0 0.5rem; }
.seg { display: grid; grid-auto-flow: column; gap: 0; border: 1px solid var(--line); border-radius: 8px; overflow: hidden; }
.seg button { padding: 0.5rem; display: grid; place-items: center; color: var(--muted); }
.seg button[aria-pressed="true"] { background: var(--accent); color: var(--accent-ink); }
.seg button svg { width: 16px; height: 16px; stroke: currentColor; fill: none; stroke-width: 2; stroke-linecap: round; }
.tiles { display: grid; grid-template-columns: repeat(3, 1fr); gap: 0.45rem; }
.tile {
  border: 1px solid var(--line); border-radius: 8px; background: var(--raised);
  padding: 0.5rem 0.35rem; font-size: 0.76rem; text-align: center;
}
.tile[aria-pressed="true"] { background: var(--accent); border-color: var(--accent); color: var(--accent-ink); font-weight: 600; }
.size-row { display: flex; align-items: center; gap: 0.6rem; }
.size-row input { flex: 1; accent-color: var(--accent); }
.size-row .a1 { font-size: 0.72rem; color: var(--muted); }
.size-row .a2 { font-size: 1.05rem; color: var(--muted); }
.swatches { display: grid; grid-template-columns: repeat(3, 1fr); gap: 0.5rem; }
.swatch { border: 2px solid var(--line); border-radius: 8px; padding: 0; overflow: hidden; }
.swatch[aria-pressed="true"] { border-color: var(--accent); }
.swatch .sw { display: block; height: 40px; }
.swatch .sn { display: block; font-size: 0.7rem; padding: 0.3rem 0; color: var(--muted); }
.toggle-row { display: flex; align-items: center; justify-content: space-between; gap: 0.75rem; font-size: 0.82rem; }
.switch { position: relative; width: 44px; height: 24px; border-radius: 999px; background: var(--line); flex: none; }
.switch[aria-pressed="true"] { background: var(--accent); }
.switch::after { content: ""; position: absolute; top: 3px; left: 3px; width: 18px; height: 18px; border-radius: 50%; background: #fff; transition: transform 0.18s ease; }
.switch[aria-pressed="true"]::after { transform: translateX(20px); }
.opt-note { font-size: 0.72rem; color: var(--muted); margin: 0.45rem 0 0; }
.scrim { position: fixed; inset: 0; background: rgba(0,0,0,0.5); z-index: 50; opacity: 0; pointer-events: none; transition: opacity 0.2s; }
.scrim[data-open="true"] { opacity: 1; pointer-events: auto; }

@media (prefers-reduced-motion: reduce) { * { transition: none !important; animation: none !important; } html { scroll-behavior: auto; } }

/* ---------- wiki entry ---------- */
.infobox {
  float: right; width: 16rem; margin: 0 0 1.25rem 1.75rem;
  background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius);
  padding: 0.9rem 1rem; font-size: 0.8rem;
}
.infobox dl { margin: 0; }
.infobox div + div { margin-top: 0.55rem; border-top: 1px solid var(--line); padding-top: 0.55rem; }
.infobox dt { color: var(--muted); font-size: 0.66rem; letter-spacing: 0.1em; text-transform: uppercase; }
.infobox dd { margin: 0.15rem 0 0; }
.entry h2 { font-size: 1.05rem; margin: 2rem 0 0.6rem; font-family: var(--ui); }
.entry a { color: var(--accent); }
.cites { margin-top: 2.5rem; border-top: 1px solid var(--line); padding-top: 1rem; }
.cites h2 { font-size: 0.9rem; margin: 0 0 0.6rem; }
.chips a.chip:hover { border-color: var(--accent); color: var(--text); }
@media (max-width: 640px) { .infobox { float: none; width: auto; margin-left: 0; } }
