/* ZeroGrav DM: the rift, a hairline tear in the sky just outside Arania (js/song.js draws it). Only on a computer (a
   fine pointer and a screen at least 1024px wide). While the entrance is up it waits, like the corner UI
   (css/gate.css), and it's gone during the jump. What it does is js/song.js's business. */

/* ── the rift: three stages of the same tear (at rest, then wider, then gaping), one showing at a time; it grows
   quickly with each click and eases back to rest when the clicking stops ── */
.rift {
  --rk: 1;                                                            /* its scale, with the globe (js/song.js) */
  position: fixed; left: 0; top: 0; z-index: 4; display: block; width: 44px; height: 44px; margin: -22px 0 0 -22px; padding: 0;
  border: 0; border-radius: 50%; background: none; color: inherit; cursor: pointer; outline: none; -webkit-tap-highlight-color: transparent;
  opacity: 1; transition: opacity .6s ease;
}
.rift[hidden], .rift:not(.placed) { display: none; }
@media (pointer: coarse), (pointer: none), (max-width: 1023.98px) { .rift { display: none !important; } }
.rift:focus-visible { box-shadow: 0 0 0 1.5px rgba(231, 194, 122, .75); }
.rift svg { position: absolute; left: 50%; top: 50%; width: 60px; height: 60px; margin: -30px 0 0 -30px; overflow: visible; scale: var(--rk); pointer-events: none; transition: filter .4s ease; }
.rift:hover svg, .rift:focus-visible svg { filter: brightness(1.25); }
.rift .st { opacity: 0; transition: opacity 1.5s cubic-bezier(.4, 0, .2, 1); }
.rift .s0 { opacity: 1; }
.rift.lv1 .s0, .rift.lv2 .s0 { opacity: 0; }
.rift.lv1 .s1, .rift.lv2 .s2 { opacity: 1; }
.rift.lv1 .st, .rift.lv2 .st { transition-duration: .28s; }
/* at rest its light breathes, faintly; gaping, motes of light escape it */
.rift .s0 .glow { animation: rift-breath 4.2s ease-in-out infinite; }
@keyframes rift-breath { 50% { opacity: .35; } }
.rift .s2 .motes { transform-box: view-box; transform-origin: 30px 30px; animation: rift-motes 2.2s ease-out infinite; }
@keyframes rift-motes { 0% { transform: scale(.85); opacity: 0; } 20% { opacity: 1; } 100% { transform: scale(1.6); opacity: 0; } }
/* three: it tears open */
.rift .burst { opacity: 0; fill: url(#rift-light); transform-box: fill-box; transform-origin: center; }
.rift.bursting svg { animation: rift-burst .6s cubic-bezier(.3, 0, .2, 1) both; }
.rift.bursting .burst { animation: rift-burst-light .7s ease-out both; }
.rift.bursting { z-index: 24; }                                     /* (it tears open in its own warm light, above the grey) */
@keyframes rift-burst { 0% { scale: var(--rk); opacity: 1; filter: brightness(1); } 35% { scale: calc(var(--rk) * 1.6); opacity: 1; filter: brightness(1.9); } 100% { scale: calc(var(--rk) * 2.4); opacity: 0; filter: brightness(2.4); } }
@keyframes rift-burst-light { 0% { opacity: 0; transform: scale(.4); } 25% { opacity: 1; } 100% { opacity: 0; transform: scale(2.6); } }
/* found: the tear healed into a thin seam of gold, a keepsake */
.rift .seam { display: none; }
.rift.found .st { display: none; }
.rift.found .seam { display: inline; }
/* the entrance: it waits for the ring of light, like the corner UI (gate.js marks it .lit) */
html.gated .rift { opacity: 0; transition: opacity .4s cubic-bezier(.3, 0, .2, 1); }
html.gated .rift.lit { opacity: 1; }
/* gone during the jump, and on the drop back out of hyperspace; while the stars sing it has torn open */
html.jumping .rift, html.hyperspace-return .rift { opacity: 0; visibility: hidden; transition: opacity .3s ease, visibility 0s linear .3s; }
html.song .rift { pointer-events: none; }
.rift.gone { visibility: hidden; }

/* ── while the stars sing: the page goes grey behind a veil, and the stars (and their faint lines) stay above it ── */
.song-veil {
  position: fixed; inset: 0; z-index: 22; pointer-events: none;
  -webkit-backdrop-filter: grayscale(1) brightness(.84); backdrop-filter: grayscale(1) brightness(.84);
}
.song-veil[hidden] { display: none; }
.song-veil.fade { transition: opacity .45s ease; }
html.song .stars, html.song .star-lines { z-index: 26; }   /* above the gold at the edge, so the stars shine over it (the DM, 29 Sep 2026) */
html.song .star-lines line { stroke-opacity: .13; transition: stroke-opacity 1s ease; }
html.song .star-card { display: none; }
html.song .star { animation: none; opacity: 1; cursor: pointer; }
html.song .star::before { scale: 1.4; box-shadow: 0 0 7px 3px rgba(var(--c), 1), 0 0 28px 10px rgba(var(--c), .62), 0 0 62px 20px rgba(var(--c), .2); }
html.song .star:hover::before, html.song .star:focus-visible::before, html.song .star.aim::before { scale: 1.7; }
/* each star's target reaches about twice as far (js/song.js aims at the nearest): the pointer says so */
html.song-aim, html.song-aim * { cursor: pointer; }
html.song .star::after, html.song .star i { scale: 1.45; }
html.song .star:focus-visible { outline: none; }
html.song-snap .star::before { transition: none; }
/* a star's note: it flares, and a soft ripple spreads in its colour */
html.song .star.sing::before { animation: song-flare .75s cubic-bezier(.2, .7, .3, 1); }
@keyframes song-flare { 0% { scale: 2.5; box-shadow: 0 0 10px 5px rgba(255, 255, 255, .95), 0 0 34px 14px rgba(var(--c), .9), 0 0 90px 30px rgba(var(--c), .35); } }
/* the found tune played back: each flare stronger, and longer */
html.song .star.sing.strong::before { animation: song-flare-strong 1s cubic-bezier(.2, .7, .3, 1); }
@keyframes song-flare-strong { 0% { scale: 3.4; box-shadow: 0 0 14px 7px rgba(255, 255, 255, 1), 0 0 48px 20px rgba(var(--c), 1), 0 0 130px 44px rgba(var(--c), .45); } 30% { scale: 2.4; } }
.song-ripple {
  position: fixed; left: 0; top: 0; width: 64px; height: 64px; margin: -32px 0 0 -32px; z-index: 23; border-radius: 50%; pointer-events: none;
  box-shadow: 0 0 0 1.5px rgba(var(--c), .8), 0 0 14px 2px rgba(var(--c), .35), inset 0 0 12px 1px rgba(var(--c), .3);
}

/* the ring of light the rift sends out, and the wave that brings the colour back (js/song.js draws both) */
.song-ring { position: fixed; inset: 0; width: 100%; height: 100%; z-index: 24; pointer-events: none; overflow: visible; }
.song-ring[hidden] { display: none; }
.song-ring circle { fill: none; }
.song-ring .r-core { stroke: #fffaf0; stroke-width: 1.6; }
.song-ring .r-mid { stroke: rgba(255, 244, 222, .3); stroke-width: 6; }
.song-ring .r-wide { stroke: rgba(250, 236, 210, .09); stroke-width: 22; }
.song-ring.warm .r-core { stroke: #f3dca6; }
.song-ring.warm .r-mid { stroke: rgba(231, 194, 122, .3); }
.song-ring.warm .r-wide { stroke: rgba(231, 194, 122, .1); }

/* the way out: a small ×, top left */
.song-exit {
  position: fixed; top: calc(14px + env(safe-area-inset-top, 0px)); left: calc(16px + env(safe-area-inset-left, 0px)); z-index: 26;
  width: 32px; height: 32px; display: grid; place-items: center; margin: 0; padding: 0; border: 1px solid rgba(239, 226, 196, .2); border-radius: 50%;
  background: rgba(4, 6, 12, .45); color: var(--ink-2); cursor: pointer; opacity: 0; visibility: hidden;
  transition: opacity .5s ease, visibility 0s linear .5s, color .3s ease, border-color .3s ease; -webkit-tap-highlight-color: transparent;
}
html.song .song-exit.on { opacity: 1; visibility: visible; transition: opacity .8s ease .6s, visibility 0s, color .3s ease, border-color .3s ease; }
.song-exit:hover, .song-exit:focus-visible { color: var(--cream); border-color: rgba(239, 226, 196, .45); }
.song-exit:focus-visible { outline: 2px solid var(--brass-hi); outline-offset: 3px; }
.song-exit svg, .song-close svg { width: 10px; height: 10px; fill: none; stroke: currentColor; stroke-width: 1.5; stroke-linecap: round; }

/* ── how far along the song is: gold light spilling in at the screen's edge, from the bottom centre up both sides ── */
.song-edge { position: fixed; inset: 0; width: 100%; height: 100%; z-index: 25; pointer-events: none; opacity: 0; transition: opacity .7s ease; mix-blend-mode: screen; }
.song-edge.on { opacity: 1; }
.song-edge[hidden], .song-flare[hidden], .song-pulse[hidden] { display: none; }
/* the gold pulses with each note of the playback (js/song.js animates its opacity) */
.song-pulse {
  position: fixed; inset: 0; z-index: 25; pointer-events: none; opacity: 0; will-change: opacity; mix-blend-mode: screen;
  box-shadow: inset 0 0 70px 14px rgba(231, 194, 122, .15), inset 0 0 16px 2px rgba(243, 220, 166, .17);   /* (about 70% softer: the DM, 29 Sep 2026) */
}
.song-edge path { fill: none; stroke: #e7c27a; stroke-dasharray: 1 2; stroke-dashoffset: 1; transition: stroke-dashoffset .9s cubic-bezier(.3, .7, .2, 1); }
.song-edge.soft { filter: blur(11px); -webkit-mask-image: linear-gradient(to bottom, rgba(0,0,0,.3), #000 22%); mask-image: linear-gradient(to bottom, rgba(0,0,0,.3), #000 22%); }   /* (a slimmer glow along the top, where the stars are) */
.song-edge.soft path { stroke-width: 28; stroke-opacity: .55; }   /* (reaches about half as far in: the DM, 29 Sep 2026) */
.song-edge.line { filter: blur(3px); }
.song-edge.line path { stroke-width: 5; stroke-opacity: .6; }
.song-edge.whole { transition: opacity 2.4s ease .9s; }
.song-edge.whole path { transition: stroke-dashoffset .9s cubic-bezier(.3, .7, .2, 1), stroke-opacity .6s ease; stroke-opacity: 1; }
/* the ends meet at the top, and it flares */
.song-flare {
  position: fixed; left: 50%; top: 0; z-index: 25; width: 60vmin; height: 26vmin; margin: -13vmin 0 0 -30vmin; pointer-events: none; opacity: 0;
  background: radial-gradient(closest-side, rgba(255, 250, 236, .95), rgba(243, 220, 166, .55) 30%, rgba(231, 194, 122, .16) 62%, rgba(231, 194, 122, 0));
  mix-blend-mode: screen;
}
.song-flare.go { animation: song-top 2.2s cubic-bezier(.2, .6, .3, 1) both; }
@keyframes song-top { 0% { opacity: 0; scale: .3 .5; } 18% { opacity: 1; } 100% { opacity: 0; scale: 1.5 1.1; } }

/* ── the card ── */
.song-card-wrap {
  position: fixed; inset: 0; z-index: 27; display: grid; place-items: center; padding: 24px;
  background: radial-gradient(ellipse at 50% 50%, rgba(4, 6, 12, .6), rgba(4, 6, 12, .3) 70%); opacity: 0; transition: opacity .7s ease;
}
.song-card-wrap[hidden] { display: none; }
.song-card-wrap.on { opacity: 1; }
.song-card {
  --ck: clamp(1, var(--k, 1), 1.35);
  position: relative; width: min(calc(440px * var(--ck)), 100%); max-height: calc(100vh - 48px); overflow: auto;
  padding: calc(24px * var(--ck)) calc(30px * var(--ck)) calc(22px * var(--ck)); border-radius: 14px; text-align: left;
  background: rgba(10, 13, 26, .95); border: 1px solid rgba(231, 194, 122, .34); color: var(--cream);
  box-shadow: 0 18px 60px rgba(0, 0, 0, .6), 0 0 48px rgba(231, 194, 122, .09);
  translate: 0 28px; transition: translate 1.1s cubic-bezier(.2, .7, .2, 1);
  scrollbar-width: thin; scrollbar-color: rgba(239, 226, 196, .2) transparent;
}
.song-card-wrap.on .song-card { translate: 0 0; }
/* the card's glyph: the rift, small, a gold tear */
.song-sigil { display: block; width: calc(34px * var(--ck)); height: calc(14px * var(--ck)); margin: 0 0 calc(8px * var(--ck)) -2px; overflow: visible; }
.song-card h2 { margin: 0 32px 10px 0; font: 400 calc(27px * var(--ck))/1.1 "IM Fell English", Georgia, serif; color: var(--brass-hi); }
.song-card h2:focus { outline: none; }
.song-body { margin: 0; font: 400 calc(16px * var(--ck))/1.5 "Alegreya Sans", system-ui, sans-serif; color: #d9ccae; }
.song-body p { margin: 0 0 calc(10px * var(--ck)); }
.song-body p:last-child { margin-bottom: 0; }
.song-body strong { font-weight: 700; color: var(--cream); }
.song-body .song-subtext { margin-top: calc(-2px * var(--ck)); font: italic 400 calc(14px * var(--ck))/1.4 "Alegreya Sans", system-ui, sans-serif; color: var(--ink-2); }
.song-body u { text-decoration-color: rgba(239, 226, 196, .55); text-decoration-thickness: 1px; text-underline-offset: 3px; }
.song-accent { color: var(--brass-hi); }
.song-rows { margin: calc(16px * var(--ck)) 0 0; padding: calc(14px * var(--ck)) 0 0; border-top: 1px solid rgba(239, 226, 196, .12); }
.song-rows dt { margin: 0; font: 400 calc(12px * var(--ck))/1.2 "IM Fell English SC", Georgia, serif; letter-spacing: .14em; color: var(--ink-2); }
.song-rows dd { margin: 3px 0 calc(12px * var(--ck)); font: 400 calc(16px * var(--ck))/1.45 "Alegreya Sans", system-ui, sans-serif; color: var(--cream); }
.song-quote {
  margin: calc(8px * var(--ck)) 0 0; padding: 0; font: italic 400 calc(21px * var(--ck))/1.3 "IM Fell English", Georgia, serif; color: var(--brass-hi);
  text-shadow: 0 0 18px rgba(231, 194, 122, .28);
}
.song-quote::before { content: "\201C"; }
.song-quote::after { content: "\201D"; }
.song-rule { margin: calc(4px * var(--ck)) 0 0; font: 400 calc(13.5px * var(--ck))/1.45 "Alegreya Sans", system-ui, sans-serif; color: var(--ink-2); }
.song-sign {
  display: grid; grid-template-columns: 1fr auto; align-items: baseline; gap: calc(12px * var(--ck)) 12px; margin: calc(18px * var(--ck)) 0 0; padding-top: calc(10px * var(--ck));
  border-top: 1px solid rgba(239, 226, 196, .12);
}
.song-sign .song-mark { grid-area: 1 / 1; }
.song-sign .song-day { grid-area: 1 / 2; justify-self: end; white-space: nowrap; }
.song-sign .song-acts { grid-area: 2 / 1 / 3 / 3; }
/* the card's two buttons, in the middle of the signature: replay the solution, and reset (which asks "Sure?" in brass) */
.song-acts { display: flex; flex-wrap: wrap; justify-content: center; gap: 8px; }
.song-act {
  margin: 0; padding: calc(5px * var(--ck)) calc(11px * var(--ck)); border: 1px solid rgba(239, 226, 196, .3); border-radius: 999px; background: none; cursor: pointer;
  -webkit-tap-highlight-color: transparent; font: 400 calc(14px * var(--ck))/1 "Alegreya Sans", system-ui, sans-serif; color: var(--ink-2);
  transition: color .3s ease, border-color .3s ease, background-color .3s ease;
}
.song-act:hover, .song-act:focus-visible { color: var(--cream); border-color: rgba(239, 226, 196, .6); background: rgba(239, 226, 196, .06); }
.song-act.sure { color: var(--brass-hi); border-color: var(--brass-hi); }
.song-act:focus-visible { outline: 2px solid var(--brass-hi); outline-offset: 2px; }
.song-act[hidden] { display: none; }
.song-mark { font: 400 calc(17px * var(--ck))/1 "IM Fell English", Georgia, serif; color: var(--cream); }
.song-mark small { margin-left: .18em; font-family: "IM Fell English SC", Georgia, serif; font-size: .62em; letter-spacing: .02em; color: var(--brass-hi); }
.song-day { font: italic 400 calc(13px * var(--ck))/1 "IM Fell English", Georgia, serif; color: var(--ink-2); }
.song-close {
  position: absolute; top: 10px; right: 10px; width: 30px; height: 30px; display: grid; place-items: center; margin: 0; padding: 0;
  border: 0; border-radius: 50%; background: none; color: var(--ink-2); cursor: pointer; transition: color .3s ease; -webkit-tap-highlight-color: transparent;
}
.song-close:hover, .song-close:focus-visible { color: var(--cream); }
.song-close:focus-visible { outline: 2px solid var(--brass-hi); outline-offset: 1px; }

/* the jump takes the page away: nothing of this goes with it */
html.jumping :is(.song-veil, .song-ring, .song-edge, .song-flare, .song-pulse, .song-exit, .song-card-wrap) { display: none; }

@media (prefers-reduced-motion: reduce) {
  .rift .s0 .glow, .rift .s2 .motes { animation: none; }
  .rift .st, .rift.lv1 .st, .rift.lv2 .st { transition-duration: .2s; }
  .rift.bursting svg { animation: rift-fade .3s ease both; }
  @keyframes rift-fade { to { opacity: 0; } }
  .song-edge path, .song-edge.whole path { transition: none; }
  html.song .star.sing::before, html.song .star.sing.strong::before { animation: song-flare-still .6s ease; }
  @keyframes song-flare-still { 0% { box-shadow: 0 0 10px 5px rgba(255, 255, 255, .95), 0 0 34px 14px rgba(var(--c), .9); } }
  .song-card { translate: none; transition: none; }
  .song-flare.go { animation: song-top-still 1.4s ease both; }
  @keyframes song-top-still { 0%, 100% { opacity: 0; } 30% { opacity: .9; } }
}
