/* ============================================================================
   grid.css — the frame for a page that IS a character grid.

   Lifted out of index.html unchanged on 2026-09-01 so the passage pages are
   the same material as the front door rather than DOM text with weather behind
   it. One copy, because two would drift the moment either was touched.
   ========================================================================== */

  /* ==========================================================================
     v2 — the whole page is one character grid.

     v1 was DOM text sitting on top of a canvas. However carefully the field
     carved around the words, they were still two materials in two layers, and
     Mike called it exactly right: flat UI with weather behind it.

     This is renga.room's actual architecture, ported. There is one buffer of
     characters. The type is written into it with put(), which also stamps a
     falloff into clear[], and density() ends with

         d -= 0.62 * clear          // the words push the dust away

     so the field is computed *around* the text rather than drawn behind it.
     And the return leg, from renga's draw loop:

         // text is on the surface too, so a crest disturbs it
         if (crest > 0.18 && buf.ch[i] !== null && Math.random() < crest*0.9)
           ch = ALPHAs()[random]

     A wave passing through a word replaces its letters. The text does not
     move — it churns in place. That is what "affected" meant.

     The only DOM is a handful of transparent anchors laid over the grid cells
     their labels occupy, so the links are real links: focusable, clickable,
     readable by a screen reader, crawlable. The canvas draws; the DOM means.
     ========================================================================== */

  html, body {
    height: 100%; margin: 0; overflow: hidden;
    overscroll-behavior: none;
    background: #05060a;
    -webkit-user-select: none; user-select: none;
    -webkit-tap-highlight-color: transparent;
  }
  canvas { display: block; position: fixed; inset: 0; z-index: 1; }

  /* Scrollbars belong to the world too: a thin ember thumb on nothing. */
  * { scrollbar-width: thin; scrollbar-color: rgba(232,148,58,.55) transparent; }
  *::-webkit-scrollbar { width: 6px; height: 6px; }
  *::-webkit-scrollbar-track { background: transparent; }
  *::-webkit-scrollbar-thumb { background: rgba(232,148,58,.45); border-radius: 0; }
  *::-webkit-scrollbar-thumb:hover { background: #e8943a; }
  *::-webkit-scrollbar-corner { background: transparent; }

  /* Real links, invisible, sitting exactly on the glyphs that name them. */
  .hit {
    position: fixed; display: block; z-index: 5;
    color: transparent; background: none; border: 0; padding: 0;
    font: inherit; cursor: pointer; text-decoration: none;
    -webkit-tap-highlight-color: transparent;
  }
  .hit:focus-visible { outline: 2px solid #e8943a; outline-offset: 2px; }

  /* Everything the canvas draws, said once for machines that cannot see it. */
  .sr { position: absolute; width: 1px; height: 1px; overflow: hidden;
        clip: rect(0 0 0 0); white-space: nowrap; border: 0; }


  /* ---- the instrument -----------------------------------------------------
     Not part of the world. This is the desk the world sits on, so it is plain
     DOM and looks like a control surface rather than like Sleepy Planet. */
  #panel {
    position: fixed; right: 0; top: 0; bottom: 0; width: 268px; z-index: 40;
    background: rgba(6,8,12,.94); border-left: 1px solid #1e2732;
    backdrop-filter: blur(14px); -webkit-backdrop-filter: blur(14px);
    font: 400 11px/1.5 "JetBrains Mono", ui-monospace, monospace;
    color: #9fb0c2; padding: 14px 16px 84px; overflow-y: auto;
    transform: translateX(100%); transition: transform .28s cubic-bezier(.2,.8,.3,1);
    -webkit-user-select: none; user-select: none;
  }
  #panel.open { transform: none; }
  #panel h2 { font-size: 10px; letter-spacing: .18em; text-transform: uppercase;
    color: #e8943a; margin: 0 0 14px; font-weight: 500; }
  #panel .row { margin: 0 0 11px; }
  #panel label { display: flex; justify-content: space-between; gap: 8px;
    font-size: 10px; letter-spacing: .06em; color: #7d8ea0; margin-bottom: 3px; }
  #panel label b { color: #cfdae6; font-weight: 400; font-variant-numeric: tabular-nums; }
  #panel input[type=range] { width: 100%; accent-color: #e8943a; height: 18px; margin: 0; }
  #panel .tools { display: flex; flex-wrap: wrap; gap: 4px; margin: 0 0 12px; }
  #panel .tools button { flex: 1 1 auto; min-width: 52px; padding: 7px 4px; font-size: 9.5px; }
  #panel .tools button.on { background: #e8943a; border-color: #e8943a; color: #05070b; }
  #panel button.wide { width: 100%; }
  body.editing { cursor: crosshair; }
  body.editing .hit { pointer-events: none; }
  #panel .grp { font-size: 9px; letter-spacing: .2em; color: #4d5b6a; margin: 18px 0 8px;
    padding-bottom: 4px; border-bottom: 1px solid #182029; font-weight: 400; }
  #panel .grp:first-child { margin-top: 0; }
  #panel input.chars { width: 100%; background: #04060a; border: 1px solid #1e2732;
    color: #cfdae6; font: 400 12px/1.4 "JetBrains Mono", monospace; padding: 6px 7px;
    border-radius: 2px; }
  #panel .hint { font-size: 9.5px; color: #5d6b7a; line-height: 1.45; margin: 2px 0 0; }
  #panel .acts { position: fixed; right: 0; bottom: 0; width: 268px;
    display: flex; gap: 8px; padding: 12px 16px; background: rgba(6,8,12,.98);
    border-top: 1px solid #1e2732; }
  #panel button { flex: 1; font: inherit; font-size: 10.5px; letter-spacing: .1em;
    text-transform: uppercase; padding: 9px 6px; cursor: pointer; border-radius: 2px;
    background: none; border: 1px solid #2a3644; color: #9fb0c2; }
  #panel button.primary { background: #e8943a; border-color: #e8943a; color: #05070b; font-weight: 500; }
  #panel button:hover { border-color: #e8943a; color: #e8943a; }
  #panel button.primary:hover { background: #f0a44c; color: #05070b; }
  #panel textarea { width: 100%; height: 84px; margin-top: 10px; resize: vertical;
    background: #04060a; border: 1px solid #1e2732; color: #7d8ea0;
    font: 400 9.5px/1.45 "JetBrains Mono", monospace; padding: 7px; border-radius: 2px; }
  /* Under the canvas, not over it. The field draws across the photograph so
     the ASCII sits on his face like it sits on everything else — he is in the
     space rather than pasted onto it. */
  #plate {
    position: fixed; z-index: 0; border-radius: 50%; object-fit: cover;
    object-position: center 30%; display: none;
    border: 1px solid #24303e; background: #0a0e14;
    filter: grayscale(1) contrast(1.06) brightness(0.92);
    box-shadow: 0 0 0 6px rgba(5,7,11,.9), 0 18px 50px -18px rgba(0,0,0,.9);
    pointer-events: none;
  }
  #cog { position: fixed; right: 12px; bottom: 12px; z-index: 41;
    width: 40px; height: 40px; display: grid; place-items: center; cursor: pointer;
    background: rgba(6,8,12,.75); border: 1px solid #1e2732; border-radius: 3px;
    color: #7d8ea0; font: 400 15px/1 "JetBrains Mono", monospace;
    backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px); }
  #cog:hover { color: #e8943a; border-color: #e8943a; }
  /* for visitors the cog is a weather switch with its name on it */
  #cog.weather { width: auto; height: 32px; padding: 0 12px; font-size: 11px;
    letter-spacing: .14em; text-transform: uppercase; white-space: nowrap; }
  #panel.open ~ #cog { right: 280px; }
  @media (max-width: 620px) { #panel { width: 100%; } #panel .acts { width: 100%; }
    #panel.open ~ #cog { right: 12px; bottom: 12px; } }

  @media (prefers-reduced-motion: reduce) { canvas { opacity: 0.55; } }

/* Nothing is pressable while the page is in pieces. The hit rectangles are
   invisible, so without this they stay clickable and keyboard-focusable over a
   screen that has fallen to the bottom. */
body.shattered .hit { pointer-events: none; opacity: 0; }
/* the seven-strike glimpse takes the whole screen (glimpse.js) */
body.glimpsing #cog, body.glimpsing #snd { pointer-events: none; opacity: 0; transition: opacity .2s; }
/* the secret instrument (strings.js) takes the whole screen and every finger */
body.strings #cog, body.strings #snd { pointer-events: none; opacity: 0; transition: opacity .2s; }
body.strings, body.strings canvas { touch-action: none; -webkit-touch-callout: none; }
/* the sound switch (sound.js), beside the weather and dressed like it */
#snd { position: fixed; right: 12px; bottom: 12px; z-index: 41; height: 32px; padding: 0 12px;
  cursor: pointer; background: rgba(6,8,12,.75); border: 1px solid #1e2732; border-radius: 3px;
  color: #56687a; font: 400 11px/1 "JetBrains Mono", monospace; letter-spacing: .14em;
  text-transform: uppercase; white-space: nowrap;
  backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px);
  transition: color .18s, border-color .18s; -webkit-tap-highlight-color: transparent; }
#snd:hover { color: #e8943a; border-color: #e8943a; }
#snd.on { color: #7d8ea0; }
#panel.open ~ #snd { display: none; }
