/* UI colors are exclusively the site's paper and ink, plus their alpha values. */
:root { --paper:#fffef8;--ink:#141414; }
/* Site cursor: a 15px solid ink dot, becoming a 25px clear-fill/dark-stroke circle over interactive elements.
   Placement keeps the precise crosshair; its rule outranks the ID cursor below. */
body,#viewer,#viewport,#viewport canvas { cursor:url(cursor-dot.svg) 8 8, auto; }
#viewer button,#viewer input,#viewer textarea,#viewer label,#viewer summary,.room-trace .trace-photo,.room-trace.has-text p,.room-trace .trace-cover { cursor:url(cursor-ring.svg) 13 13, pointer; }
#viewport.placing-note,#viewport.placing-note canvas { cursor:crosshair; }
#satellite-links { position:absolute;inset:0;width:100%;height:100%;pointer-events:none;overflow:hidden; }
#satellite-links line { stroke:var(--ink);stroke-width:1;vector-effect:non-scaling-stroke; }
#through-time { left:24px;right:25px;top:24px;bottom:auto;width:auto; }
.time-bar { gap:22px;padding:0; }
#play { width:24px;height:27px; }
#play svg { width:100%;height:100%;stroke-width:1; }
.play-shape { fill:var(--ink); }
.pause-shape { stroke-width:1; }
.time-track { flex:1;position:relative;display:flex;align-items:center;min-width:0;height:32px; }
.time-track:before,.time-track:after { content:'';position:absolute;top:11px;width:10px;height:10px;border-radius:50%;background:var(--ink);pointer-events:none;z-index:1; }
.time-track:before { left:0; }.time-track:after { right:0; }
#time { width:100%;height:32px;margin:0; }
#time::-webkit-slider-runnable-track { height:1px;background:var(--ink);margin:0 7.5px; }
#time::-webkit-slider-thumb { width:15px;height:15px;margin-top:-7px;background:var(--ink);border:0; }
#time::-moz-range-track { height:1px;background:var(--ink); }
#time::-moz-range-thumb { width:15px;height:15px;background:var(--ink);border:0; }
#controls { bottom:24px;max-height:calc(100% - 110px); }
/* Leaf actions: the 5px dot sits on the spine inside the button, so the whole
   line — circle and label — is one hover target, filling solid with no ease. */
.tree-row.action-row:before { display:none; }
.tree-row.action-row button { display:flex;align-items:center;gap:21.5px;margin-left:-31.5px;padding:3px 8px 3px 0; }
.row-dot { width:10px;height:10px;border:1px solid var(--ink);border-radius:50%;background:var(--paper);flex-shrink:0;transition:none; }
.tree-row.action-row button:hover .row-dot,.tree-row.action-row button:focus-visible .row-dot { background:#141414; }
#controls.open~.presence,.presence { top:auto;bottom:28px; }
#note-help { font-size:14px;line-height:18px;font-weight:600; }
#session-clock { position:absolute;left:50%;bottom:28px;transform:translateX(-50%);z-index:3;white-space:nowrap; }
#pins, #pins * { -webkit-user-select:none;user-select:none; }
#pins img { -webkit-user-drag:none; }
.room-trace { pointer-events:none;filter:blur(var(--blur,0px)); }
.room-trace.has-image { max-width:180px; }
.placing-note .room-trace,.placing-note .room-trace .trace-photo,.placing-note .room-trace p { pointer-events:none; }
.room-trace .trace-photo { display:block;position:relative;width:50px;height:50px;opacity:1;pointer-events:auto;overflow:visible;margin:0;cursor:pointer; }
.room-trace .trace-photo img { position:absolute;left:50%;top:calc(50% - 3px);width:150px;height:130px;max-width:none;max-height:none;object-fit:contain;margin:0;transform:translate(-50%,-50%) scale(.26);filter:blur(6px);opacity:.82;mask-image:radial-gradient(ellipse at center,#141414 35%,#141414cc 65%,transparent 100%);transition:transform .75s cubic-bezier(.2,.7,.2,1),filter .7s,opacity .7s;transform-origin:center; }
.room-trace:hover .trace-photo img,.room-trace:focus-within .trace-photo img,.room-trace.expanded .trace-photo img { transform:translate(-50%,-50%) scale(1);filter:blur(0);opacity:.96;mask-image:radial-gradient(ellipse at center,#141414 62%,#141414ee 80%,transparent 100%); }
/* Depth traces: relief splats render the 3D version; hide the 2D overlay when close to the room. Show on hover or in satellite view. */
#viewport .room-trace.has-depth .trace-photo img { opacity:var(--satellite-photo-opacity,0);pointer-events:none; }
#viewport .room-trace.has-depth:hover .trace-photo img,
#viewport .room-trace.has-depth:focus-within .trace-photo img,
#viewport .room-trace.has-depth.expanded .trace-photo img { opacity:.96; }
.room-trace:hover,.room-trace:focus-within,.room-trace.expanded { z-index:2; }
.room-trace p { font-size:16px;line-height:18px;opacity:.85; }
.room-trace.has-text p { pointer-events:auto;transform:scale(.8);transform-origin:center;transition:transform .6s cubic-bezier(.2,.7,.2,1),opacity .5s; }
.room-trace.has-text:hover p,.room-trace.has-text:focus-within p,.room-trace.has-text.expanded p { transform:scale(1);opacity:1; }
.room-trace.has-image p { max-width:160px;font-size:13px;line-height:15px;text-align:center;margin:0 auto; }
.room-trace.has-image { width:160px;text-align:center; }
/* The photo box shrink-wraps the small resting splat and carries the 6px
   gap to the caption inside its own hoverable box, so the cursor never
   crosses a dead margin between image and text (which would collapse the
   expansion mid-motion). Hovering grows it to the full image. */
.room-trace.has-image .trace-photo { margin:0 auto;width:39px;height:40px;transition:width .75s cubic-bezier(.2,.7,.2,1),height .75s cubic-bezier(.2,.7,.2,1); }
.room-trace.has-image:hover .trace-photo,.room-trace.has-image:focus-within .trace-photo,.room-trace.has-image.expanded .trace-photo { width:150px;height:136px; }
#viewer { touch-action:none; }
#viewer #toast { top:84px;max-width:calc(100% - 40px);text-align:center; }
/* Song traces: a small bordered play chip; the embed mounts on demand. */
#note-song-input { display:block;width:100%;margin:10px 0 0;padding:6px 0;border:0;border-bottom:1px solid var(--ink);border-radius:0;background:transparent;color:var(--ink);font-size:12px;line-height:14px; }
#note-song-input:focus-visible { outline:none; }
#note-song-input::placeholder { color:var(--ink);opacity:.45; }
#song-hint { margin:6px 0 0; }
.room-trace.has-song { width:170px;text-align:center; }
.room-trace.has-song .trace-song { display:inline-flex;align-items:center;gap:8px;margin:0 auto;padding:4px 0;border:0;background:transparent;pointer-events:auto;cursor:pointer;font-size:12px;line-height:14px;white-space:nowrap;transform:scale(.8);transform-origin:center;opacity:.85;transition:transform .6s cubic-bezier(.2,.7,.2,1),opacity .5s; }
/* The chip label grows on hover exactly like the text traces. */
.room-trace.has-song:hover .trace-song,.room-trace.has-song:focus-within .trace-song { transform:scale(1);opacity:1; }
/* Dot states: startup clear + "Play song"; hover filled; once playing, filled
   + "Stop song"; playing+hover inverts back to clear. Filled ⇔ hover XOR play. */
.room-trace.has-song .trace-song .row-dot { width:10px;height:10px;border:1px solid var(--ink);border-radius:50%;flex-shrink:0;background:transparent;transition:background-color .2s; }
.room-trace.has-song .trace-song:hover .row-dot,.room-trace.has-song .trace-song:focus-visible .row-dot { background:var(--ink); }
.room-trace.has-song .trace-song[aria-expanded="true"] .row-dot { background:var(--ink); }
.room-trace.has-song .trace-song[aria-expanded="true"]:hover .row-dot,.room-trace.has-song .trace-song[aria-expanded="true"]:focus-visible .row-dot { background:transparent; }
/* The cover and the chip read as one button: hovering the cover also fills
   the chip's dot (and inverts it back while playing), exactly as hovering
   the chip itself does. */
.room-trace.has-song .trace-cover:hover + .trace-song .row-dot,
.room-trace.has-song .trace-cover:focus-visible + .trace-song .row-dot { background:var(--ink); }
.room-trace.has-song .trace-cover:hover + .trace-song[aria-expanded="true"] .row-dot,
.room-trace.has-song .trace-cover:focus-visible + .trace-song[aria-expanded="true"] .row-dot { background:transparent; }
/* The Spotify controller rides in a visually hidden stage: the chip plays
   the song directly, and no player UI ever opens in the room. */
.room-trace.has-song .song-stage { position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);pointer-events:none; }
/* Album cover above the play chip: the same treatment as the image traces —
   a small blurred splat at rest that grows and sharpens on hover, pushing the
   chip down, so song traces read differently from text-only traces. */
/* The cover box carries the 6px gap to the play chip inside its own
   hoverable box (same treatment as image traces): no dead margin between
   the album art and the chip, so the expansion never collapses while the
   cursor travels across. */
.room-trace.has-song .trace-cover { display:block;position:relative;width:39px;height:45px;margin:0 auto;overflow:visible;pointer-events:auto;transition:width .75s cubic-bezier(.2,.7,.2,1),height .75s cubic-bezier(.2,.7,.2,1); }
.room-trace.has-song .trace-cover img { position:absolute;left:50%;top:calc(50% - 3px);width:150px;height:130px;max-width:none;max-height:none;object-fit:cover;margin:0;transform:translate(-50%,-50%) scale(.26);filter:blur(6px);opacity:.82;mask-image:radial-gradient(ellipse at center,#141414 35%,#141414cc 65%,transparent 100%);transition:transform .75s cubic-bezier(.2,.7,.2,1),filter .7s,opacity .7s;transform-origin:center; }
.room-trace.has-song:hover .trace-cover,.room-trace.has-song:focus-within .trace-cover { width:150px;height:136px; }
.room-trace.has-song:hover .trace-cover img,.room-trace.has-song:focus-within .trace-cover img { transform:translate(-50%,-50%) scale(1);filter:blur(0);opacity:.96;mask-image:radial-gradient(ellipse at center,#141414 62%,#141414ee 80%,transparent 100%); }
.room-trace.has-song p { text-align:center; }
.room-trace:hover p,.room-trace:focus-within p { opacity:1; }
.room-trace .trace-photo img { pointer-events:none; }
#note-dialog { width:324px;max-width:calc(100% - 32px);max-height:calc(100dvh - 48px);padding:32px 12px 12px;border:0;background:transparent;color:var(--ink);overflow:auto; }
#note-dialog::backdrop { background:transparent;backdrop-filter:none; }
#viewer.trace-composing #viewport { filter:blur(18px); }
#viewport { transition:filter .5s; }
#viewer:after { content:'';position:absolute;inset:0;background:#fffef880;opacity:0;pointer-events:none;transition:opacity .5s;z-index:2; }
#viewer.trace-composing:after { opacity:1; }
#viewer.trace-composing .presence,#viewer.trace-composing #session-clock,#viewer.trace-composing #reflection { visibility:hidden; }
/* The composer mirrors the Controls circle tree: a 15px root circle by the
   title, 10px hollow section dots on a 1px spine, a 5px terminator. */
#note-dialog h2 { position:relative;display:flex;align-items:flex-start;gap:17px;font-size:16px;line-height:18px;font-weight:600;margin:0 0 26px; }
#note-dialog h2 .section-dot { position:relative;z-index:1;width:15px;height:15px;border:1px solid var(--ink);border-radius:50%;flex-shrink:0;background:var(--paper); }
#note-dialog .close-dialog { top:4px;right:12px;font-size:18px;line-height:18px; }
#note-form { position:relative;padding:0 0 36px 32px; }
#note-form:before { content:'';position:absolute;left:7px;top:-30px;bottom:3px;width:1px;background:var(--ink); }
#note-form:after { content:'';position:absolute;left:5px;bottom:0;width:5px;height:5px;border:1px solid var(--ink);border-radius:50%;background:var(--paper); }
.message-row,.add-trace-row { position:relative; }
.message-row:before,.add-trace-row:before,#save-note:before { content:'';position:absolute;left:-29px;top:4px;width:10px;height:10px;border:1px solid var(--ink);border-radius:50%;background:var(--paper);box-sizing:border-box; }
.message-row { margin-bottom:22px; }
.add-trace-row { font-size:16px;line-height:18px; }
.media-branches { margin-top:12px; }
#note-form .image-label,#note-form .song-label { position:relative;display:block;width:max-content;margin:0 0 12px;padding:0 0 0 14px;border:0;background:transparent;font-size:16px;line-height:18px;font-weight:350;cursor:pointer; }
#note-form .image-label:before,#note-form .song-label:before { content:'';position:absolute;left:-25px;top:8px;width:17px;height:1px;background:var(--ink); }
#note-form .image-label:after,#note-form .song-label:after { content:'';position:absolute;left:-10px;top:6px;width:5px;height:5px;border:1px solid var(--ink);border-radius:50%;background:var(--paper); }
#note-form .image-label:hover:after,#note-form .song-label:hover:after { background:var(--ink); }
#note-text { display:block;box-sizing:border-box;width:100%;max-width:100%;font-size:16px;line-height:18px;border:0;outline-offset:4px;margin:0;padding:0 2px 8px 0;resize:vertical;height:28px;min-height:28px;max-height:var(--message-max-height,180px);overflow:auto;background:transparent; }
#note-text::placeholder { color:#14141470; }
#note-text:focus-visible { outline:1px dotted #14141450;outline-offset:3px; }
#note-song-input { width:100%;min-width:0;margin:0 0 12px;font-size:14px; }
.image-label:hover { font-weight:700; }
#image-preview { margin-top:16px; }
#image-preview img { max-height:110px;max-width:160px; }
.image-options { display:flex;flex-direction:column;align-items:flex-start;gap:9px;margin:10px 0;font-size:12px;line-height:14px; }
.image-options label { display:flex;align-items:center;gap:5px; }
.image-options input { accent-color:var(--ink); }
#image-progress { font-size:10px;line-height:12px; }
#trace-storage { margin:23px 0 0;opacity:.58;font-size:10px;line-height:12px;color:var(--ink); }
.dialog-actions { margin-top:28px;justify-content:flex-start; }
#save-note { position:relative;display:inline-flex;align-items:center;font-size:16px;line-height:18px;font-weight:400; }
#save-note:hover:before { background:var(--ink); }
#session-clock,#load-detail,#navigation-hint,dialog small,.fine,#reflection small { color:var(--ink); }
#session-clock,#load-detail { opacity:.55; }
textarea { border-color:var(--ink); }
#leave,#return { border-color:var(--ink); }
.panel-clip { scrollbar-color:var(--ink) transparent; }
.loading-ring { border-color:#14141420;border-top-color:var(--ink); }
.loading-symbol { display:block;width:34px;height:34px;margin:0 auto 14px;fill:var(--ink);stroke:var(--ink);stroke-width:1.2;animation:loading-spin 2.4s cubic-bezier(.45,0,.55,1) infinite; }
@keyframes loading-spin { to { transform:rotate(360deg); } }
@media (prefers-reduced-motion:reduce) { .loading-symbol { animation:none; } }
@media(max-width:600px){#through-time{left:16px;right:17px;top:16px;width:auto}.time-bar{gap:15px}#time{width:100%}#controls{bottom:21px;max-height:calc(100% - 100px)}#controls.open~.presence,.presence{top:auto;bottom:24px;right:17px}#controls.open~.presence{top:71px;bottom:auto}#note-help{font-size:13px;line-height:16px}#session-clock{font-size:10px;bottom:24px}#controls.open~#session-clock{opacity:0}.room-trace p{font-size:14px;line-height:16px}#note-dialog{width:280px;max-height:calc(100% - 130px)}}
@media(prefers-reduced-motion:reduce){#viewport,#viewer:after,.room-trace,.room-trace .trace-photo img,.room-trace .trace-cover,.room-trace .trace-cover img,.room-trace .trace-song,.room-trace p{transition:none}}
/* A fresh visit always shows traces; the action only changes presentation. */
.traces-hidden #pins, .traces-hidden #satellite-links { visibility: hidden; pointer-events: none; }
#note-dialog { width:324px;max-height:var(--composer-max-height,calc(100dvh - 48px)); }
