/*
 * Kataribe — landing r2
 *
 * The whole page is one grid of monospace cells: one font, one row height.
 * Hierarchy comes from weight and colour, never from a second typeface.
 *
 *   phone         40 columns   cord on column 1    words from column 4
 *   large screen  100 columns  cord on column 24   words from column 27
 *
 * Every horizontal measure is a number of columns (ch) and every vertical
 * measure a number of rows (--row), so the drawings and the words share cells.
 */

@font-face {
  font-family: "Kataribe Mono"; /* JetBrains Mono, subset; see fonts/LICENSE-JetBrainsMono.txt */
  src: url("../fonts/jetbrains-mono-kataribe.woff2") format("woff2");
  font-weight: 100 800;
  font-style: normal;
  font-display: swap;
}

/* Subset that only contains 語り部. */
@font-face {
  font-family: "Shippori Mincho K";
  src: url("../fonts/shippori-mincho-kataribe.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
  unicode-range: U+8A9E, U+308A, U+90E8;
}

:root {
  color-scheme: light dark;
  --paper: #f5f2ea;
  --ink: #15171c;
  --ink-2: #34363c;       /* running text */
  --muted: #5d5f66;       /* labels, dust */
  --accent: #b9801c;      /* knots (graphic, 3:1 on paper) */
  --accent-text: #855a0a; /* accent used on words (4.5:1 on paper) */
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --paper: #0e0f12;
    --ink: #f1ede4;
    --ink-2: #cfccc4;
    --muted: #a5a39c;
    --accent: #e6b655;
    --accent-text: #e6b655;
  }
}

/* Manual theme switch (js/being.js): an explicit choice wins over the system. */
:root[data-theme="dark"] {
  color-scheme: dark;
  --paper: #0e0f12;
  --ink: #f1ede4;
  --ink-2: #cfccc4;
  --muted: #a5a39c;
  --accent: #e6b655;
  --accent-text: #e6b655;
}
:root[data-theme="light"] {
  color-scheme: light;
  --paper: #f5f2ea;
  --ink: #15171c;
  --ink-2: #34363c;
  --muted: #5d5f66;
  --accent: #b9801c;
  --accent-text: #855a0a;
}

.theme-switch {
  position: fixed;
  top: 0.5rem;
  right: 0.75rem;
  z-index: 10;
  margin: 0;
  padding: 0.25rem 0.5ch;
  border: 0;
  background: var(--paper);
  color: var(--muted);
  font: inherit;
  font-family: "Kataribe Mono", ui-monospace, monospace;
  cursor: pointer;
}
.theme-switch:hover,
.theme-switch:focus-visible { color: var(--accent-text); }

*,
*::before,
*::after { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  background: var(--paper);
}

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  /* Lets the grid size itself from the real content width (no scrollbar). */
  container-type: inline-size;
  overflow-x: clip;
}

::selection { background: var(--accent); color: var(--paper); }

/* ── the grid ───────────────────────────────────────────────────────────── */

.page {
  --cols: 40;    /* columns in the grid */
  --spine: 1;    /* column of the long cord */
  --text: 4;     /* first column of the words */
  --measure: 35; /* longest line of words, in columns */

  /* One column is 0.6em in this font, so 40 columns are 24em. */
  --u: min(1.25rem, calc(100vw / 24));
  --row: calc(var(--u) * 1.45);

  position: relative;
  width: calc(var(--cols) * 1ch);
  margin-inline: auto;
  font-family: "Kataribe Mono", ui-monospace, "SF Mono", Menlo, Consolas, "DejaVu Sans Mono", monospace;
  font-size: var(--u);
  line-height: var(--row);
  font-weight: 400;
  font-variant-ligatures: none;
  font-synthesis: none;
  font-kerning: none;
  /* Keeps the stems of │ and ┬ on the same pixels where the system hints fonts. */
  text-rendering: geometricPrecision;
  -webkit-font-smoothing: antialiased;
}

@supports (width: 1cqi) {
  .page { --u: min(1.25rem, calc(100cqi / 24)); }
}

/* Whole pixels per cell: box-drawing glyphs then meet without seams. */
@supports (width: round(down, 1px, 1px)) {
  .page {
    --col: round(down, calc(min(1.25rem, calc(100cqi / 24)) * 0.6 + 0.01px), 1px);
    --u: calc(var(--col) / 0.6);
    --row: round(calc(var(--u) * 1.45), 1px);
  }
}

@media (min-width: 60em) {
  .page {
    --cols: 100;
    --spine: 24;
    --text: 27;
    --measure: 58;
    --u: min(1.25rem, calc((100vw - 2rem) / 60));
  }

  @supports (width: 1cqi) {
    .page { --u: min(1.25rem, calc((100cqi - 2rem) / 60)); }
  }

  @supports (width: round(down, 1px, 1px)) {
    .page {
      --col: round(down, calc(min(1.25rem, calc((100cqi - 2rem) / 60)) * 0.6 + 0.01px), 1px);
      --u: calc(var(--col) / 0.6);
    }
  }
}

h1, h2, p, dl, dt, dd, figure, pre { margin: 0; }
h1, h2, dt { font: inherit; }

/* ── drawings ───────────────────────────────────────────────────────────── */

.art {
  position: relative;
  display: block;
  /* A │ is a little taller than its row, which is what joins it to the next one.
     Clip the sides only, so the first and last rows keep that overlap. */
  overflow: hidden;
  overflow: clip visible;
  font: inherit;
  white-space: pre;
  color: var(--ink);
  -webkit-user-select: none;
  user-select: none;
}

/* js/being.js splits a drawing into three stacked layers of the same text. */
.art .l { display: block; }
.art .l + .l { position: absolute; top: 0; left: 0; }
.art .l-amber { color: var(--accent); }
.art .l-dust { color: var(--muted); }

.art-wide { display: none; }

@media (min-width: 60em) {
  .art-wide { display: block; }
  .art-narrow { display: none; }
}

/* A drawing that starts on the long cord instead of on the words column.
   It draws its own piece of that cord, so it covers the one behind it. */
.art-spine {
  margin-left: calc((var(--spine) - var(--text)) * 1ch);
  /* Paper over the cord, except a sliver at both ends where the two must join. */
  background: linear-gradient(var(--paper), var(--paper)) center / 100% calc(100% - 0.5em) no-repeat;
}

/* ── the long cord ──────────────────────────────────────────────────────── */

/* A run of │ wrapped to one character per row and clipped to its section. */
.cord {
  position: absolute;
  /* Each piece reaches a sliver into its neighbours, so no gap can open between them. */
  top: -0.25em;
  bottom: -0.25em;
  padding-top: 0.25em;
  left: calc(var(--spine) * 1ch);
  width: 1.5ch;
  overflow: hidden;
  white-space: normal;
  word-break: break-all;
  overflow-wrap: anywhere;
  color: var(--ink);
  pointer-events: none;
  -webkit-user-select: none;
  user-select: none;
}

/* A knot on the long cord. It sits in the cord's own cell. */
.bead {
  position: absolute;
  top: 0;
  left: calc((var(--spine) - var(--text)) * 1ch);
  z-index: 2;
  width: 1ch;
  background: var(--paper);
  color: var(--accent);
  font-weight: 400;
  -webkit-user-select: none;
  user-select: none;
}

.bead.open { color: var(--ink); }

/* The pulse that travels down the long cord (added by js/being.js). */
.spark {
  position: absolute;
  top: 0;
  left: calc(var(--spine) * 1ch);
  z-index: 1;
  width: 1ch;
  white-space: pre;
  color: var(--accent);
  pointer-events: none;
  -webkit-user-select: none;
  user-select: none;
  will-change: transform;
}

.spark[hidden] { display: none; }

/* ── the being and its name ─────────────────────────────────────────────── */

.hero {
  position: relative;
  padding-top: calc(2 * var(--row));
}

.entry {
  position: relative;
  padding: var(--row) 0 calc(2 * var(--row)) calc(var(--text) * 1ch);
}

.entry h1 {
  font-size: 2em; /* one letter takes two columns and two rows */
  line-height: calc(2 * var(--row));
  font-weight: 300;
  letter-spacing: 0.5ch;
  white-space: nowrap;
}

.gloss {
  color: var(--muted);
  margin-top: var(--row);
}

.ja {
  font-family: "Shippori Mincho K", "Hiragino Mincho ProN", "Yu Mincho", "Noto Serif CJK JP", serif;
  color: var(--ink);
  margin-right: 1ch;
}

.def {
  max-width: calc(var(--measure) * 1ch);
  margin-top: var(--row);
  color: var(--ink);
}

@media (min-width: 60em) {
  /* The name sits in the clearing under the arc. */
  .entry {
    position: absolute;
    top: calc(10 * var(--row));
    left: calc(var(--text) * 1ch);
    width: calc(var(--measure) * 1ch);
    padding: 0;
  }

  .entry .cord { display: none; }
}

/* ── sections ───────────────────────────────────────────────────────────── */

.sec {
  position: relative;
  padding: calc(2 * var(--row)) 0 calc(2 * var(--row)) calc(var(--text) * 1ch);
}

.sec p,
.sec dd { max-width: calc(var(--measure) * 1ch); }

.sec p { color: var(--ink-2); }
.sec p + p { margin-top: var(--row); }

.sec h2 {
  position: relative;
  margin-bottom: var(--row);
  color: var(--muted);
}

.num {
  display: inline-block;
  min-width: 3ch;
  margin-right: 1ch;
  color: var(--accent-text);
}

.sec .say {
  color: var(--ink);
  font-weight: 700;
}

.strands { margin-top: calc(2 * var(--row)); }

.strand { position: relative; }
.strand + .strand { margin-top: var(--row); }

.strand dt {
  color: var(--ink);
  font-weight: 700;
}

.strand dd { color: var(--ink-2); }

.sec .art { margin-top: calc(2 * var(--row)); }

@media (min-width: 60em) {
  /* Labels move to the left of the cord and end at their knot. */
  .sec h2,
  .strand dt {
    position: absolute;
    top: 0;
    width: calc((var(--spine) - 1) * 1ch);
    text-align: right;
  }

  .sec h2 {
    top: calc(2 * var(--row));
    left: 0;
    margin: 0;
  }

  .strand dt { left: calc(var(--text) * -1ch); }

  .sec h2 .bead,
  .strand dt .bead { left: calc(var(--spine) * 1ch); text-align: left; }

  .num { min-width: 0; }
}

/* ── where the cord ends ────────────────────────────────────────────────── */

.end { padding-top: calc(3 * var(--row)); padding-bottom: calc(3 * var(--row)); }

.end .cord { bottom: calc(var(--row) - 0.25em); }

.sec .coda {
  color: var(--ink);
  font-weight: 500;
}

.cursor {
  position: absolute;
  bottom: 0;
  left: calc(var(--spine) * 1ch);
  color: var(--ink);
  -webkit-user-select: none;
  user-select: none;
}

.cursor.lit { color: var(--accent); }

.foot {
  display: flex;
  align-items: flex-start;
  gap: 2ch;
  padding: calc(4 * var(--row)) 0 calc(4 * var(--row)) calc(var(--text) * 1ch);
  color: var(--muted);
}

.foot .name { color: var(--ink); }

/* ── motion: only the text moves, and only if the reader allows it ──────── */

@media (prefers-reduced-motion: no-preference) {
  .cursor { animation: blink 1.2s steps(1, end) infinite; }

  /* The name breathes: same cells, slowly changing weight. */
  .entry h1 { animation: breathe 7s steps(16, end) infinite alternate; }
}

@keyframes blink {
  0%, 60% { opacity: 1; }
  60.01%, 100% { opacity: 0; }
}

@keyframes breathe {
  from { font-weight: 250; }
  to { font-weight: 450; }
}

@media print {
  .page { --u: 9pt; --row: 13pt; }
  .cursor, .entry h1 { animation: none; }
}
