/* Type: SF Mono — the font Claude Code shows in Terminal. Safari and every browser on iPhone/iPad
   reach it through ui-monospace; it can't be served as a web font (Apple's licence), so everywhere
   else falls back to Geist Mono, self-hosted (Google Fonts is blocked in mainland China) and cut
   lighter so it sits close to SF Mono Regular. */
@font-face {
  font-family: "Geist Mono Light";
  src: url("fonts/GeistMono-Light.woff2") format("woff2");
  font-weight: 400;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215;
}

:root {
  --bg: #fffffe;
  --ink: #242424;
  --mid: #3a3a3a;
  --dim: #6f6f6f;
  --wash: rgba(40, 38, 32, .05);
  --lh: 1.6;
  --gx: 3.8em;            /* horizontal gap between tree levels */
  --gy: 3.8em;            /* vertical gap between the branch boxes */
  --edge: 28px;           /* sound control: same distance from the bottom and the right */
  /* square box with its four corner pixels knocked out */
  --notch: polygon(1px 0, calc(100% - 1px) 0, calc(100% - 1px) 1px, 100% 1px,
                   100% calc(100% - 1px), calc(100% - 1px) calc(100% - 1px), calc(100% - 1px) 100%,
                   1px 100%, 1px calc(100% - 1px), 0 calc(100% - 1px), 0 1px, 1px 1px);
  font-size: clamp(18px, .42vw + 14px, 21px);
}

* { box-sizing: border-box; }

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

body {
  position: relative;
  min-height: 100vh; min-height: 100svh;
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font: 400 1rem/var(--lh) ui-monospace, "Geist Mono Light",
        "PingFang SC", "Hiragino Sans GB", "Noto Sans CJK SC", "Source Han Sans SC", "Microsoft YaHei",
        Menlo, Consolas, monospace;
  -webkit-font-smoothing: antialiased;
}

button { font: inherit; color: inherit; }
a { color: inherit; }
::selection { background: var(--ink); color: var(--bg); }

#board { position: relative; min-height: 100vh; min-height: 100svh; }

#wires {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  overflow: visible; pointer-events: none;
}
#wires path { fill: none; stroke: var(--ink); stroke-width: 1; shape-rendering: crispEdges; }
#wires rect { fill: var(--ink); shape-rendering: crispEdges; }

/* ---------- tree: horizontal (wide screens) ---------- */

#tree {
  position: relative;
  display: flex;
  align-items: center;
  min-height: 100vh; min-height: 100svh;
  padding: 10vh clamp(24px, 8vw, 150px) 36vh;
}

.col-root { flex: none; }

.col-branches {
  display: flex;
  flex-direction: column;
  gap: var(--gy);
  margin-left: var(--gx);
}

.branch { position: relative; }

.box {
  display: block;
  min-width: 8.2em;
  padding: .7em 1.5em;
  border: 1px solid var(--ink);
  background: transparent;
  text-align: center;
  white-space: nowrap;
  cursor: pointer;
  clip-path: var(--notch);
  transition: background-color .2s, opacity .3s steps(3);
}
#root { min-width: 0; cursor: default; }
#root:hover { background: transparent; }
.box:hover, .branch.open > .box { background: var(--wash); }
.box:focus-visible { background: rgba(40, 38, 32, .1); outline: none; }

.leaves {
  position: absolute;
  left: calc(100% + var(--gx));
  top: 50%;
  transform: translateY(-50%);
  margin: 0; padding: 0;
  list-style: none;
  white-space: nowrap;
}
.leaves.para {
  top: calc(50% - var(--lh) * .5em);   /* first line level with the box */
  transform: none;
  width: 50ch;
  white-space: normal;
}
.leaves p { margin: 0; }
.leaves a { text-decoration: none; }
.leaves a:hover, .leaves a:focus-visible, .leaves a.pinned { background: var(--wash); outline: none; }
.leaves u, .leaves a { text-decoration-thickness: 1px; text-underline-offset: 3px; }
.note { color: var(--dim); }
.open-quote { margin-left: -.32em; }   /* 《 sits in the right half of its square; pull it back into line */

/* streamed characters (set up by site.js) */
.js .branch:not(.shown) .leaves { display: none; }
.js .branch:not(.lit) > .box { opacity: 0; }
.js #root { animation: on .5s steps(4) both; }
@keyframes on { from { opacity: 0; } }
.c { opacity: 0; }
.c.on { opacity: 1; transition: opacity .3s; }
a .c.on, u .c.on { text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 3px; }
.leaves u { text-decoration: none; }
.js .leaves a { text-decoration: none; }

/* ---------- poster preview window ---------- */

.peek {
  position: absolute;
  z-index: 2;
  width: clamp(190px, 16vw, 270px);
  padding: 6px 6px 0;
  border: 1px solid var(--ink);
  background: var(--bg);
  clip-path: var(--notch);
  white-space: normal;
  display: none;
  opacity: 0;
  transition: opacity .2s steps(3);
}
.peek.shown { display: block; }
.peek.lit { opacity: 1; }
.peek-img {
  aspect-ratio: 1 / 1.414;
  background: rgba(40, 38, 32, .04);
  cursor: pointer;
}
.peek.pinned .peek-img { cursor: zoom-in; }
.peek-img img { display: block; width: 100%; height: 100%; object-fit: contain; }
.peek-bar {
  display: flex;
  align-items: center;
  gap: .35em;
  height: 2.1em;
  font-size: .8em;
  color: var(--mid);
  white-space: nowrap;
}
.peek-bar button {
  border: 0; background: none; padding: 0 .25em;
  line-height: 1.6; cursor: pointer; color: var(--ink);
}
.peek-bar button:hover, .pk-ext:hover { background: var(--wash); }
.pk-ext { color: var(--ink); text-underline-offset: 3px; text-decoration-thickness: 1px; }
.pk-sp { flex: 1; }
.peek:not(.multi) .pk-prev, .peek:not(.multi) .pk-next, .peek:not(.multi) .pk-n,
.peek:not(.pinned) .pk-close, .pk-ext:empty { display: none; }

/* ---------- full-screen poster ---------- */

#full {
  position: fixed; inset: 0; z-index: 10;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 12px;
  padding: 3vh 16px;
  background: rgba(255, 255, 254, .97);
}
#full[hidden] { display: none; }
.full-frame {
  margin: 0;
  padding: 8px;
  border: 1px solid var(--ink);
  background: var(--bg);
  clip-path: var(--notch);
}
.full-frame img {
  display: block;
  max-width: calc(100vw - 50px);
  max-height: calc(100vh - 150px); max-height: calc(100svh - 150px);
  width: auto; height: auto;
}
.full-cap { margin: 0; max-width: 60ch; text-align: center; font-size: .9em; line-height: 1.5; color: var(--mid); white-space: pre-line; text-wrap: balance; }
.full-cap a { text-underline-offset: 3px; text-decoration-thickness: 1px; }
.full-bar { display: flex; align-items: center; gap: 1.4em; font-size: .85em; }
.full-bar button { border: 0; background: none; padding: .25em .3em; cursor: pointer; }
.full-bar button:hover { background: var(--wash); }
#full:not(.multi) .fl-prev, #full:not(.multi) .fl-next, #full:not(.multi) .fl-n { display: none; }

/* ---------- sound: a circuit switch ---------- */

#sound {
  position: absolute;                 /* bottom-right corner of the page */
  right: var(--edge); bottom: calc(var(--edge) + 1px);   /* +1: the lowest pixel is the circle stroke, not the box edge */
  z-index: 5;
  display: block;
  padding: 0;
  border: 0; background: none;
  font-size: .8em;
  cursor: pointer;
}
#sound:focus-visible { outline: none; }
#sound:hover .sound-label, #sound:focus-visible .sound-label { color: var(--mid); }
.sound-line { display: flex; align-items: flex-end; gap: .6em; }
.sound-label { line-height: 1; margin-bottom: -.27em; }   /* centres the word on the wire */
#sound svg { display: block; overflow: visible; }
#sound .w, #sound .lever { fill: none; stroke: var(--ink); stroke-width: 1; }
#sound .w { shape-rendering: crispEdges; }
#sound .term { fill: var(--bg); stroke: var(--ink); stroke-width: 1; }
#sound .lever {
  transform-box: view-box;
  transform-origin: 26px 16.5px;
  transform: rotate(-30deg);
  transition: transform .4s steps(5);
}
#sound[aria-pressed="true"] .lever { transform: rotate(0); }

/* ---------- tree: top-down (narrow screens) ----------
   hilary tang centred at the top, the three boxes in a row beneath it, and each
   section hanging below. events sits first because its wire drops from the middle;
   writing's wire runs down the left edge, about's down the right edge. */

@media (max-width: 1179px) {
  /* phones: as large as possible while "Permaculture Design Course" (26 mono chars ≈ 15.6em)
     still fits on one line beside the list's 34px indent, 14px margin and the page gutters */
  :root { --edge: 20px; font-size: clamp(12px, calc((100vw - 88px) / 15.6 * .8), 16.8px); }   /* then 20% smaller */
  #tree {
    display: block;
    min-height: 0;
    padding: 80px 16px 34vh;   /* just clear of the sound switch in the top-right corner */
  }
  .col-root { display: flex; justify-content: center; }
  .col-branches {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 0 10px;          /* rows sit flush; each section brings its own top margin */
    margin: 2.6em 0 0;
  }
  .branch { display: contents; }
  .branch > .box { grid-row: 1; min-width: 0; width: 100%; padding: .65em .3em; }
  #writing > .box { grid-column: 1; }
  #events > .box { grid-column: 2; }
  #about > .box { grid-column: 3; }
  .leaves, .leaves.para {
    grid-column: 1 / -1;
    position: static;
    transform: none;
    width: auto;
    margin: 1.6em 14px .2em 34px;   /* right margin keeps text clear of about's wire */
    white-space: normal;
  }
  #events-list { grid-row: 2; }
  #writing-list { grid-row: 3; }
  #about-text { grid-row: 4; }
  .leaves.para {
    margin: 1.4em 0 0;
    padding: .9em 1.1em;
    border: 1px solid transparent;
    clip-path: var(--notch);
    transition: border-color .3s steps(3);
  }
  .leaves.para.lit { border-color: var(--ink); }   /* a box around about, phones only */
  .leaves.para { line-height: 1.5; }
  .leaves.para br:not(.keep) { display: none; }      /* one running paragraph; only "call, text…" on its own line */
  #sound { top: var(--edge); bottom: auto; font-size: .68em; }   /* phones: top right of the window, smaller */
  #sound svg { width: 60px; height: 13px; }
  .peek { position: relative; width: min(64vw, 260px); margin: .6em 0 .8em 1.4em; }
}

@media (prefers-reduced-motion: reduce) {
  .c.on, .box, .peek, #sound .lever, .leaves.para { transition: none; }
  .js #root { animation: none; }
}
