/* D3 v2: thổ cẩm made over the page, on dó paper. One explicit palette; reads the same in any OS theme. */

:root {
  --paper: #EAE3D2;
  --paper-deep: #DCD3BD;
  --cotton: #F3EEE2;
  --thread: #B8AD93;
  --indigo: #1F2D4A;
  --ink: #182238;
  --madder: #8F3328;
  --turmeric: #C79A2A;
  --forest: #45603F;
  --slate: #4A5468;

  --serif: "Fraunces", Georgia, "Times New Roman", serif;
  --sans: "Be Vietnam Pro", "Segoe UI", system-ui, -apple-system, Arial, sans-serif;

  --gutter: max(clamp(20px, 4vw, 64px), env(safe-area-inset-left), env(safe-area-inset-right));
  --max: 1280px;
  --measure: 34rem;
  --head: 64px;
  --stage-h: 282px; /* phone: loom.js sets the real height from the cell size */
  color-scheme: light only;
}

* { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
@media (pointer: fine) { html { overscroll-behavior: none; } }

body {
  margin: 0;
  background-color: var(--paper);
  /* dó paper: fibre noise (SVG turbulence, not an image file) over faint laid lines from the bamboo screen */
  background-image:
    url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='360' height='360'><filter id='f'><feTurbulence type='fractalNoise' baseFrequency='0.55 0.9' numOctaves='3' seed='7' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 0.45 0 0 0 0 0.40 0 0 0 0 0.30 0 0 0 0.09 0'/></filter><rect width='360' height='360' filter='url(%23f)'/></svg>"),
    repeating-linear-gradient(to bottom, rgba(120,105,75,0.028) 0 1px, transparent 1px 11px);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 1.0625rem;
  line-height: 1.6;
  overflow-x: hidden;
}

a { color: var(--madder); text-decoration-thickness: 1px; text-underline-offset: 0.16em;
    touch-action: manipulation; -webkit-tap-highlight-color: rgba(31,45,74,0.15); }
:focus-visible { outline: 2px solid var(--madder); outline-offset: 3px; }

.skip {
  position: absolute; left: var(--gutter); top: -3rem;
  background: var(--indigo); color: var(--cotton); padding: .6rem .9rem;
  font-weight: 500; text-decoration: none; z-index: 20;
}
.skip:focus { top: .5rem; }

.visually-hidden {
  position: absolute !important; width: 1px; height: 1px; margin: -1px; padding: 0;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* ---------- Header (sticky: the cloth lands here at the end) ---------- */

.top {
  position: sticky; top: 0; z-index: 10;
  height: var(--head);
  display: flex; align-items: center; gap: 1rem 1.6rem;
  padding: 0 var(--gutter);
  background-color: var(--paper);
}
.mark {
  display: inline-flex; align-items: center; min-height: 44px;
  font-family: var(--serif); font-weight: 500; font-size: 1.3rem; line-height: 1.2;
  color: var(--ink); text-decoration: none; letter-spacing: -0.005em;
  font-variation-settings: "opsz" 24;
}
.mark-slot {
  display: inline-block; width: 0; height: 22px; overflow: hidden;
  margin-right: 0; opacity: 0; vertical-align: middle;
  transition: width .5s cubic-bezier(.7,0,.3,1), margin-right .5s cubic-bezier(.7,0,.3,1), opacity .3s;
}
.mark-slot.on { width: 54px; margin-right: .65rem; opacity: 1; }
.mark-slot svg { display: none; width: 54px; height: 22px; }
.mark-slot svg.show { display: block; }

.nav { display: flex; gap: .25rem 1.3rem; margin-left: auto; }
.nav a, .lang a {
  position: relative; display: inline-block; color: var(--ink); text-decoration: none;
  font-weight: 500; font-size: .9375rem; padding: .7rem 0; min-height: 44px;
}
/* a weft bar that is woven in from the left on hover and focus */
.nav a::after, .lang a::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: .45rem; height: 3px;
  background: var(--indigo); transform: scaleX(0); transform-origin: left center;
  transition: transform .35s cubic-bezier(.7,0,.3,1);
}
.nav a:hover::after, .nav a:focus-visible::after { transform: scaleX(1); }
.lang { display: flex; align-items: center; gap: .55rem; }
.lang span { color: var(--thread); }
.lang a[aria-current="page"]::after { transform: scaleX(1); }
.lang a:not([aria-current]) { color: var(--slate); }
.lang a:not([aria-current]):hover::after, .lang a:not([aria-current]):focus-visible::after { transform: scaleX(1); background: var(--madder); }
.lang a:hover { color: var(--ink); }

/* ---------- Story: beats on the left, the loom pinned on the right ---------- */

main { position: relative; z-index: 1; }
.story { position: relative; max-width: var(--max); margin: 0 auto; }

.stage {
  position: sticky; top: var(--head); z-index: 4;
  height: var(--stage-h);
  overflow: visible;
  background-color: var(--paper);
  background-image:
    url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='360' height='360'><filter id='f'><feTurbulence type='fractalNoise' baseFrequency='0.55 0.9' numOctaves='3' seed='7' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 0.45 0 0 0 0 0.40 0 0 0 0 0.30 0 0 0 0.09 0'/></filter><rect width='360' height='360' filter='url(%23f)'/></svg>"),
    repeating-linear-gradient(to bottom, rgba(120,105,75,0.028) 0 1px, transparent 1px 11px);
}
.stage::after { /* a short paper fade under the pinned loom: copy passing beneath fades, no line is sliced */
  content: ""; position: absolute; left: 0; right: 0; bottom: -40px; height: 40px; pointer-events: none;
  background: linear-gradient(to bottom, var(--paper) 0%, rgba(234,227,210,0.92) 35%, rgba(234,227,210,0));
}
@media (min-width: 900px) { .stage::after { display: none; } }
.stage.travel { z-index: 11; } /* the folded cloth passes over the header on its way to the mark */
.loom {
  position: absolute; inset: 0; width: 100%; height: 100%;
  touch-action: pan-y; transform-origin: 0 0; will-change: transform;
  cursor: crosshair;
}
.cloth-fallback {
  position: absolute; left: 0; right: 0; bottom: 0; height: 60%; z-index: 0;
  background:
    repeating-linear-gradient(to bottom,
      var(--indigo) 0 30px, var(--cotton) 30px 36px, var(--indigo) 36px 56px,
      var(--madder) 56px 62px, var(--indigo) 62px 80px, var(--cotton) 80px 100px,
      var(--indigo) 100px 106px, var(--forest) 106px 112px, var(--indigo) 112px 130px);
}
.stage.has-canvas .cloth-fallback { display: none; }

.beats { position: relative; z-index: 1; padding: 0 var(--gutter); }
.beat {
  min-height: 72vh;
  display: flex; flex-direction: column; justify-content: center;
  padding: 2.5rem 0;
}
.beat-0 { min-height: calc(100vh - var(--head) - var(--stage-h)); padding-top: 1.5rem; }
.beat:last-child { min-height: 50vh; }
.beat-hold { min-height: 120vh; }
.beat-long { min-height: 100vh; }
.beat-in { max-width: var(--measure); }
.beat p { margin: 0 0 1rem; }
.beat p:last-child { margin-bottom: 0; }

.craft {
  font-family: var(--serif); font-style: italic; font-variation-settings: "opsz" 14;
  color: var(--slate); font-size: 1rem; margin: 0 0 .5rem !important;
}
h1 {
  font-family: var(--serif); font-weight: 400; font-variation-settings: "opsz" 144;
  font-size: clamp(2rem, 1.1rem + 3.4vw, 3.9rem);
  line-height: 1.12; letter-spacing: -0.012em;
  margin: 0 0 1.2rem; max-width: 19ch; color: var(--indigo); text-wrap: balance;
}
.lead { font-size: clamp(1.0625rem, 0.95rem + 0.4vw, 1.25rem); line-height: 1.5; margin: 0 0 .9rem !important; }
.hint, .small { color: var(--slate); font-size: .9rem; line-height: 1.5; }
h2 {
  font-family: var(--serif); font-weight: 500; font-variation-settings: "opsz" 36;
  font-size: clamp(1.5rem, 1.2rem + 1vw, 2.1rem);
  line-height: 1.18; letter-spacing: -0.008em; margin: 0 0 1rem; color: var(--indigo);
  text-wrap: balance;
}

/* shuttle wipe on each beat head: a paper bar passes left to right and uncovers the heading */
.beat-head { position: relative; display: inline-block; overflow: hidden; padding-right: .2em; }
.beat-head::after {
  content: ""; position: absolute; inset: 0; background: var(--paper);
  transform: translateX(0); transition: transform .8s cubic-bezier(.7,0,.3,1);
}
.beat.in .beat-head::after { transform: translateX(102%); }

/* lists: one indigo cell per item, the unit of the system */
.cells { list-style: none; margin: 0 0 1rem; padding: 0; }
.cells li { position: relative; padding: .4rem 0 .4rem 1.4rem; }
.cells li::before {
  content: ""; position: absolute; left: 0; top: calc(.4rem + .55em);
  width: .5em; height: .5em; background: var(--indigo);
  transform: scale(0); transform-origin: left center;
  transition: transform .4s cubic-bezier(.7,0,.3,1);
}
.beat.in .cells li::before { transform: scale(1); }
.beat.in .cells li:nth-child(2)::before { transition-delay: .08s; }
.beat.in .cells li:nth-child(3)::before { transition-delay: .16s; }
.beat.in .cells li:nth-child(4)::before { transition-delay: .24s; }
.beat.in .cells li:nth-child(5)::before { transition-delay: .32s; }
.beat.in .cells li:nth-child(6)::before { transition-delay: .40s; }

@media (min-width: 640px) { .cells.two { display: grid; grid-template-columns: 1fr 1fr; column-gap: 1.5rem; } }
.play { margin-top: .5rem; }
.count-btn {
  display: inline-flex; align-items: center; gap: .6rem;
  font: inherit; font-weight: 500; color: var(--ink); background: none;
  border: 1px solid var(--thread); padding: .55rem 1rem; min-height: 44px; cursor: pointer;
  touch-action: manipulation; transition: border-color .2s, transform .2s;
}
.count-btn .cell { width: .6em; height: .6em; background: var(--madder); transition: transform .45s cubic-bezier(.7,0,.3,1); }
.count-btn:hover, .count-btn:focus-visible { border-color: var(--indigo); }
.count-btn:hover .cell, .count-btn:focus-visible .cell { transform: rotate(45deg); }
.count-btn:active { transform: translateY(1px); }
.status { margin-top: .6rem !important; min-height: 1.4em; }

.mail { font-weight: 500; overflow-wrap: anywhere; display: inline-block; transition: transform .25s; }
.mail:hover, .mail:focus-visible { transform: translateY(-2px); text-decoration-thickness: 3px; }

/* the dye vat: a full-bleed wash that rises with beat 3, under the text */
.vat {
  position: fixed; left: 0; right: 0; bottom: 0; height: 100vh; z-index: 0;
  background: rgba(31,45,74,0.10); transform: scaleY(0); transform-origin: bottom;
  pointer-events: none;
}
html[data-dye="lac"] .vat { background: rgba(143,51,40,0.10); }

/* ---------- Footer: the back of the cloth ---------- */

.foot { position: relative; z-index: 1; max-width: var(--max); margin: 0 auto; padding: 2rem var(--gutter) 2.5rem; }
.reverse { display: block; width: 100%; height: 96px; }
.foot-craft { margin: .6rem 0 1.4rem; }
.foot-row { display: flex; flex-wrap: wrap; gap: .5rem 2rem; align-items: center; justify-content: space-between; }
.legal { margin: 0; font-size: .9375rem; max-width: 44rem; }
.copy { margin: .4rem 0 0; color: var(--slate); font-size: .875rem; }

/* ---------- Laptop: two columns, the loom takes the right seven-twelfths ---------- */

@media (min-width: 900px) {
  :root { --stage-h: calc(100vh - var(--head)); }
  .story { display: grid; grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); align-items: start; }
  .beats { order: 1; padding-left: var(--gutter); padding-right: 2rem; }
  .stage { order: 2; }
  .beat { min-height: 100vh; }
  .beat-0 { min-height: calc(100vh - var(--head)); padding-top: 0; }
  .beat:last-child { min-height: 70vh; }
  .beat-hold { min-height: 170vh; }
  .beat-long { min-height: 140vh; }
}

@media (max-width: 640px) {
  :root { --head: 104px; }
  .top { flex-wrap: wrap; align-content: center; gap: 0 1rem; }
  .mark { flex: 1 1 100%; min-height: 40px; font-size: 1.15rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .mark-name { overflow: hidden; text-overflow: ellipsis; }
  .nav { margin-left: 0; gap: 0 1rem; }
  .nav a, .lang a { font-size: .875rem; padding: .6rem 0; min-height: 44px; white-space: nowrap; }
  .lang { margin-left: auto; }
}

/* ---------- Reduced motion: the finished cloth and all the copy, still ---------- */

@media (prefers-reduced-motion: reduce) {
  .beat-head::after { display: none; }
  .cells li::before { transform: scale(1); transition: none; }
  .mark-slot, .nav a::after, .lang a::after, .count-btn .cell, .mail { transition: none; }
  .loom { will-change: auto; }
}
