:root {
  --paper: #F4EEE1;
  --ink: #2B2825;
  --gray: #57514B;
  --accent: #00A62E;
  /* The ink as a bare triple, so every hairline, hover wash and dimmed rule on
     the page can be written rgba(var(--ink-rgb), a) and invert with the reading
     light at its own weight. Changing one number here re-inks the whole book. */
  --ink-rgb: 43, 40, 37;
  --panel-w: clamp(330px, 40%, 560px);
}

/* ---- the dark page ----
   Scoped to the PANEL on purpose, not to :root. This is the reading light over
   the text and nothing else: the diorama beside it is a painting on paper and
   stays lit that way whatever the reader does to the type. */
#sg-panel.dark {
  color-scheme: dark;
  --paper: #191714;
  --ink: #EBE4D6;
  --gray: #9C9488;
  --accent: #3FE06B;
  --ink-rgb: 235, 228, 214;
}

* { box-sizing: border-box; }
html, body { margin: 0; height: 100%; overflow: hidden; background: #F4EEE1; }
canvas { display: block; }

/* ---- two-column shell: the book on the left, the room on the right ---- */
#sg-app {
  display: flex;
  width: 100vw;
  /* 100vh is the viewport with the browser's chrome HIDDEN — the largest it
     ever gets — so on a phone the foot of the page sat under the URL bar. dvh
     is the viewport actually on screen; the vh line above is the fallback for
     browsers without it, all of which are desktop, where the two agree. */
  height: 100vh;
  height: 100dvh;
  font-family: Georgia, 'Hiragino Mincho ProN', 'Yu Mincho', 'YuMincho', 'MS PMincho', 'Times New Roman', serif;
}
#sg-panel {
  width: var(--panel-w);
  flex: none;
  position: relative;
  overflow: hidden;
  background: var(--paper);
  color: var(--ink);
  border-right: 1px solid rgba(var(--ink-rgb), 0.12);
  transition: opacity 0.3s ease;
}
#sg-stage { flex: 1; position: relative; overflow: hidden; background: var(--paper); }

/* THE CAMERA'S GESTURES, ONLY WHERE THE CAMERA HAS ANY. In the look, a drag
   orbits — and the browser's own pan and double-tap zoom are competing for
   exactly those touches. Scoped to .ambient because while READING there is
   nothing to steer, and swallowing the reader's pinch there would take the
   browser's zoom away and give nothing back. */
#sg-app.ambient #sg-stage canvas,
#sg-app.explore #sg-stage canvas { touch-action: none; cursor: grab; }
#sg-app.ambient #sg-stage canvas:active,
#sg-app.explore #sg-stage canvas:active { cursor: grabbing; }
#sg-app.ambient #sg-panel,
#sg-app.explore #sg-panel { display: none; }

/* ---- grain and curtain ---- */
.sg-grain {
  position: absolute; inset: 0; width: 100%; height: 100%;
  pointer-events: none; opacity: 0.055; mix-blend-mode: multiply;
  image-rendering: pixelated;
}
.sg-curtain {
  position: absolute; inset: 0; pointer-events: none;
  opacity: 0; transition: opacity 0.42s ease;
}
.sg-curtain.closed { opacity: 1; transition: opacity 0.24s ease; }

/* ---- the toolbar over the stage ---- */
.sg-tools {
  position: absolute; top: 16px; right: 16px; display: flex; gap: 8px; z-index: 5;
}
.sg-tools button {
  width: 38px; height: 38px; display: grid; place-items: center;
  background: rgba(244, 238, 225, 0.86); color: #2B2825;
  border: 1px solid rgba(43, 40, 37, 0.16); border-radius: 4px;
  cursor: pointer; padding: 0;
  -webkit-backdrop-filter: blur(3px); backdrop-filter: blur(3px);
}
.sg-tools button svg { width: 17px; height: 17px; display: block; }
.sg-tools button.on { background: #2B2825; color: #F4EEE1; border-color: #2B2825; }
@media (hover: hover) { .sg-tools button:hover { background: #2B2825; color: #F4EEE1; } }

/* the caption under the diorama — what you are looking at, said plainly */
/* The caption sits over the diorama, and the diorama is a different value on
   every page — grey ink on a night scene is unreadable and grey ink on a bright
   one is barely there. It carries its own piece of paper. */
.sg-caption {
  position: absolute; left: 18px; bottom: 16px; max-width: 46ch; z-index: 4;
  font-size: 13px; font-style: italic; color: #2B2825;
  background: rgba(244, 238, 225, 0.82); padding: 6px 11px; border-radius: 3px;
  margin: 0; pointer-events: none; opacity: 0; transition: opacity 0.5s ease;
}
.sg-caption.show { opacity: 1; }

/* ---- walking: the prompt, the conversation, the roster ----
   All three are pieces of paper laid on the diorama, because the diorama is a
   different value on every page and ink alone would be unreadable on half of
   them. Same reasoning as the caption above. */
.sg-prompt {
  position: absolute; left: 50%; transform: translateX(-50%); bottom: 74px; z-index: 5;
  background: rgba(43, 40, 37, 0.82); color: #F4EEE1; padding: 6px 14px; border-radius: 3px;
  font-size: 13px; letter-spacing: 0.02em; pointer-events: none;
  opacity: 0; transition: opacity 0.18s ease;
}
.sg-prompt.show { opacity: 1; }

.sg-talk {
  position: absolute; left: 50%; transform: translateX(-50%); bottom: 22px; z-index: 6;
  width: min(560px, calc(100% - 40px));
  background: rgba(244, 238, 225, 0.95); color: #2B2825;
  border: 1px solid rgba(43, 40, 37, 0.18); border-radius: 4px;
  padding: 14px 18px 12px; cursor: pointer;
  opacity: 0; pointer-events: none; transition: opacity 0.22s ease;
}
.sg-talk.show { opacity: 1; pointer-events: auto; }
.sg-talk b { font-weight: normal; color: #00A62E; font-size: 13px; letter-spacing: 0.06em; text-transform: uppercase; }
.sg-talk p { margin: 7px 0 0; font-size: 16px; line-height: 1.6; }
.sg-talk .hint { display: block; margin-top: 9px; font-size: 12px; color: #57514B; font-style: italic; }

.sg-roster {
  position: absolute; right: 16px; bottom: 16px; z-index: 4;
  background: rgba(244, 238, 225, 0.82); color: #57514B;
  padding: 5px 10px; border-radius: 3px; font-size: 12px; font-style: italic;
  opacity: 0; transition: opacity 0.3s ease; pointer-events: none;
}
.sg-roster.show { opacity: 1; }

/* ---- panel views ---- */
/* The bottom padding reserves the footer's height. Without it the last line of
   every chapter scrolls under the footer and is unreadable at the exact moment
   the reader reaches it. */
.sg-view { position: absolute; inset: 0; overflow-y: auto; padding: 74px 46px 62px; }
.sg-view.hidden { display: none; }

/* ---- the header ----
   The mark at the top left, above all three views. Fixed height, so the views
   can reserve exactly that much padding and nothing ever sits under it. */
.sg-head {
  position: absolute; top: 0; left: 0; right: 0; z-index: 3;
  display: flex; align-items: center; gap: 10px;
  padding: 14px 46px 10px;
  background: linear-gradient(var(--paper) 68%, rgba(0, 0, 0, 0));
  pointer-events: none;
}
.sg-head img {
  width: 34px; height: 34px; display: block; border-radius: 4px;
  /* The mark is a rose square. On the cream page it needs a hairline or it
     floats; on the dark reading light it needs the same hairline for the
     opposite reason. */
  box-shadow: 0 0 0 1px rgba(var(--ink-rgb), 0.14);
}
.sg-head .wm {
  font-size: 11.5px; letter-spacing: 0.2em; color: var(--gray);
}

/* ---- the footer ----
   Sits under all three views, at the foot of the reading panel. Deliberately
   quiet: two links and a button at 12px, one hairline above them. It is the
   only place in the book that points anywhere outside itself. */
.sg-foot {
  position: absolute; left: 0; right: 0; bottom: 0; z-index: 3;
  display: flex; align-items: center; justify-content: space-between;
  gap: 6px 14px; flex-wrap: wrap;
  padding: 10px 46px 12px;
  background: var(--paper);
  border-top: 1px solid rgba(var(--ink-rgb), 0.12);
  font-size: 12px; color: var(--gray); letter-spacing: 0.02em;
}
.sg-foot .right { display: flex; align-items: center; gap: 12px; }
.sg-foot a { color: var(--accent); text-decoration: none; border-bottom: 1px solid transparent; }
.sg-foot button.ca {
  font: inherit; font-family: inherit; color: var(--ink); background: none;
  border: 1px solid rgba(var(--ink-rgb), 0.28); border-radius: 3px;
  padding: 3px 9px; cursor: pointer; letter-spacing: 0.02em; white-space: nowrap;
}
.sg-foot button.ca .mono {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 11px; color: var(--gray); margin-left: 5px;
}
.sg-foot button.ca.done { border-color: var(--accent); color: var(--accent); }
/* The not-yet state: same shape as the button so the footer does not reflow on
   the day the address lands, but plainly not pressable. */
.sg-foot .ca.pending {
  border: 1px dashed rgba(var(--ink-rgb), 0.28); border-radius: 3px;
  padding: 3px 9px; color: var(--gray); letter-spacing: 0.02em; white-space: nowrap;
}
.sg-foot .ca.pending .mono {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 11px; margin-left: 5px; font-style: italic;
}
/* The refused-copy state shows the whole address, selected, so the keyboard can
   finish the job. It is allowed to wrap: the panel is narrower than a forty two
   character address at this size. */
.sg-foot button.ca.failed { border-color: var(--accent); max-width: 100%; white-space: normal; text-align: left; }
.sg-foot button.ca .mono.full { user-select: all; word-break: break-all; margin: 0; color: var(--ink); }
@media (hover: hover) {
  .sg-foot a:hover { border-bottom-color: var(--accent); }
  .sg-foot button.ca:hover { background: rgba(var(--ink-rgb), 0.06); }
}
/* This selector list lost its body to an over-eager cleanup and silently
   inherited the next rule's, which gave every focused footer link the padding
   and border of a page button. */
.sg-foot a:focus-visible, .sg-foot button.ca:focus-visible {
  outline: 2px solid var(--accent); outline-offset: 2px;
}

button.sg-btn {
  font-family: Georgia, 'Hiragino Mincho ProN', 'Yu Mincho', serif; font-size: 15px; background: none;
  border: 1px solid rgba(var(--ink-rgb), 0.3); color: var(--ink);
  padding: 7px 16px; border-radius: 3px; cursor: pointer;
}
/* An inline SVG with no width has no intrinsic size to fall back on inside a
   flex button — the two icon buttons in the page bar rendered as empty boxes
   until this existed. The toolbar over the stage had its own rule; these did
   not, which is exactly the kind of thing that only shows up on screen. */
button.sg-btn svg { width: 15px; height: 15px; display: block; stroke: currentColor; }
/* EVERY :hover IN THIS FILE IS GUARDED. A touch screen has no pointer that
   moves away: the browser applies :hover on tap and leaves it applied until
   something else is tapped, so a button the reader has finished with sits there
   lit, reading as still-pressed. :focus-visible is deliberately never inside
   these guards — that is the keyboard's affordance and it must survive on every
   device. */
@media (hover: hover) {
  button.sg-btn:hover { background: rgba(var(--ink-rgb), 0.06); }
}
button.sg-btn.on { background: var(--accent); border-color: var(--accent); color: var(--paper); }
button.sg-btn:focus-visible, .sg-tools button:focus-visible, .sg-menu li:focus-visible {
  outline: 2px solid var(--accent); outline-offset: 2px;
}

/* ---- the hanko ----
   A square of accent with the glyph knocked out of it. Square, not round, and
   never a coloured dot: at this size the cut-out glyph is what makes it read as
   a stamp pressed onto the page rather than as a bullet. */
.sg-seal {
  display: inline-grid; place-items: center;
  width: 1.35em; height: 1.35em; margin-right: 0.45em;
  background: var(--accent); color: var(--paper);
  font-size: 0.82em; line-height: 1; border-radius: 2px;
  vertical-align: -0.28em; letter-spacing: 0;
}

/* ---- title ---- */
.sg-title { display: flex; flex-direction: column; justify-content: center; }
.sg-title .jp {
  margin: 0 0 10px; font-size: clamp(26px, 3.4vw, 34px);
  letter-spacing: 0.32em; color: var(--ink); opacity: 0.85;
}
.sg-title h1 {
  font-weight: normal; font-size: clamp(30px, 4.6vw, 50px);
  letter-spacing: 0.01em; line-height: 1.12; margin: 0 0 10px;
}
.sg-title .ticker {
  margin: 0 0 16px; font-size: 13px; letter-spacing: 0.22em; color: var(--gray);
  display: flex; align-items: center;
}
.sg-title .sub { color: var(--gray); font-style: italic; margin: 0 0 8px; font-size: 17px; }
.sg-title .epi {
  margin: 0 0 28px; font-size: 15px; line-height: 1.6; max-width: 34ch;
  padding-left: 12px; border-left: 2px solid var(--accent);
}
/* the Japanese set beside an English heading, a size down and spaced out */
.jp-small { font-size: 0.62em; letter-spacing: 0.3em; color: var(--gray); margin-left: 0.5em; }
.sg-page .no .k {
  font-size: 1.5em; line-height: 1; margin-right: 0.35em; color: var(--accent);
  vertical-align: -0.12em; letter-spacing: 0;
}
.sg-title .row { display: flex; gap: 10px; flex-wrap: wrap; }
.sg-title .note { margin: 30px 0 0; font-size: 13px; color: var(--gray); line-height: 1.6; max-width: 44ch; }

/* ---- contents ---- */
.sg-menu h1 { font-weight: normal; letter-spacing: 0.02em; font-size: 29px; margin: 0 0 4px; }
.sg-menu .lede { color: var(--gray); font-style: italic; margin: 0 0 20px; font-size: 15px; }
.sg-menu ol { list-style: none; padding: 0; margin: 10px 0 0; }
.sg-menu li {
  display: flex; align-items: baseline; gap: 12px; padding: 9px 2px;
  border-bottom: 1px solid rgba(var(--ink-rgb), 0.09); cursor: pointer;
}
.sg-menu li .num {
  font-size: 14px; color: var(--gray); width: 34px; text-align: right; flex: none;
  letter-spacing: 0;
}
.sg-menu li .ttl { flex: 1; font-size: 17px; }
.sg-menu li .dt { font-size: 12px; color: var(--gray); flex: none; }
.sg-menu li.matter .ttl { font-style: italic; }
.sg-menu li.read .ttl { color: var(--gray); }
@media (hover: hover) { .sg-menu li:hover { background: rgba(var(--ink-rgb), 0.05); } }
.sg-menu-head { display: flex; align-items: baseline; gap: 12px; }
.sg-menu-head h1 { flex: 1; }

/* ---- the page's entrance ----
   The panel's half of the page turn: the heading and each paragraph rise a few
   pixels as they fade in, staggered, while the camera eases into the shot on the
   other side of the screen. Reduced motion turns the movement off and keeps the
   fade, which is the part that carries the page change. */
@keyframes sg-rise {
  from { opacity: 0; transform: translateY(7px); }
  to   { opacity: 1; transform: none; }
}
.sg-page .no, .sg-page h2, .sg-page .date, .sg-page p.rise {
  animation: sg-rise 0.5s ease both;
}
.sg-page h2 { animation-delay: 40ms; }
.sg-page .date { animation-delay: 80ms; }
@media (prefers-reduced-motion: reduce) {
  .sg-page .no, .sg-page h2, .sg-page .date, .sg-page p.rise {
    animation: none; opacity: 1; transform: none;
  }
}

/* ---- a page ---- */
.sg-page .no {
  font-size: 12px; letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--gray); margin: 0 0 8px;
}
.sg-page h2 { font-weight: normal; font-size: 30px; line-height: 1.2; margin: 0 0 6px; }
.sg-page .date { color: var(--gray); font-style: italic; margin: 0 0 22px; font-size: 14px; }
.sg-page p { font-size: 16.5px; line-height: 1.72; margin: 0 0 17px; }
.sg-page p.speaking { color: var(--accent); }
.sg-page .seal {
  margin: 24px 0 0; padding-top: 14px; font-size: 13px; color: var(--gray);
  border-top: 1px solid rgba(var(--ink-rgb), 0.12);
}
.sg-page .seal b { font-weight: normal; color: var(--accent); }
.sg-page .bar { display: flex; gap: 8px; align-items: center; margin: 26px 0 0; flex-wrap: wrap; }
.sg-page .bar .spacer { flex: 1; }

/* ---- the phone ----
   Everything here is a fix for something that was actually broken at 375px, not
   a precaution:

     the title clipped        clamp() with a vw term does not shrink below its
                              floor, and a 30px floor plus 0.32em letter-spacing
                              on the Japanese line is wider than the screen. The
                              floors come down and the tracking comes in.
     long words overflowed    a Solana-length token or an em-dashed clause has
                              no break opportunity, so overflow-wrap is set on
                              the panel rather than per element.
     the stage collapsed      a flexed canvas in a scrolling column goes to zero
                              height, so the stage keeps a fixed share.
     chrome piled up          caption, roster, prompt and talk box all sit at
                              the bottom of the stage. On a phone they overlap,
                              so they stack in a fixed order with the talk box
                              lowest and the roster moved to the top.
*/
@media (max-width: 900px) {
  #sg-app { flex-direction: column; }
  #sg-panel {
    width: 100%; height: 56%; flex: none; order: 2;
    border-right: none; border-top: 1px solid rgba(var(--ink-rgb), 0.12);
  }
  #sg-stage { width: 100%; height: 44%; flex: none; order: 1; }
  #sg-app.ambient #sg-stage,
  #sg-app.explore #sg-stage { height: 100%; }

  /* nothing in the panel may exceed the panel */
  #sg-panel, #sg-panel * { overflow-wrap: anywhere; }
  .sg-view { padding: 62px 22px 66px; }
  .sg-head { padding: 12px 22px 8px; }
  .sg-head img { width: 28px; height: 28px; }
  .sg-foot { padding: 8px 22px 10px; font-size: 11.5px; row-gap: 4px; }
  .sg-foot button.ca { padding: 2px 7px; }
  .sg-foot button.ca .mono { font-size: 10.5px; }

  .sg-title .jp { font-size: 22px; letter-spacing: 0.18em; margin-bottom: 6px; }
  .sg-title h1 { font-size: clamp(24px, 7.4vw, 34px); line-height: 1.14; }
  .sg-title .sub { font-size: 15px; }
  .sg-title .epi { font-size: 14px; margin-bottom: 20px; }
  .sg-title .note { font-size: 12.5px; }
  .sg-page h2 { font-size: clamp(21px, 6.4vw, 28px); }
  .sg-page p { font-size: 15.5px; line-height: 1.66; }
  .sg-menu li .dt { display: none; }         /* the date needs the width more than the reader needs it twice */
  .sg-menu li .ttl { font-size: 15.5px; }

  /* the stage chrome, stacked so nothing lands on anything else */
  .sg-caption { font-size: 11.5px; left: 10px; right: 10px; bottom: 10px; max-width: none; }
  .sg-roster { top: 66px; right: 10px; bottom: auto; font-size: 11px; }
  .sg-prompt { bottom: 92px; font-size: 12px; }
  .sg-talk { bottom: 12px; width: calc(100% - 20px); padding: 11px 13px 9px; }
  .sg-talk p { font-size: 14.5px; }
  .sg-tools { top: 10px; right: 10px; gap: 6px; }
  .sg-tools button { width: 34px; height: 34px; }
  /* walking, the caption would sit under the talk box; the talk box wins */
  #sg-app.explore .sg-caption { display: none; }
}

/* Very narrow, or a phone held upright with a small window: give the reader the
   text and let the diorama be a band at the top. */
@media (max-width: 400px) {
  #sg-panel { height: 62%; }
  #sg-stage { height: 38%; }
  .sg-view { padding: 58px 16px 50px; }
  .sg-head { padding: 10px 16px 6px; }
  .sg-foot { padding: 7px 16px 9px; }
  .sg-title .jp { font-size: 19px; letter-spacing: 0.12em; }
}
