/* Dice: shared by turnkeeper.html and dm.html (js/dice.js draws these).
   The dice land in the roller's tray, centered on screen (clicks pass through it); the result
   card sits at the bottom. */
#diceLayer{position:fixed; inset:0 0 120px; z-index:400; pointer-events:none; display:flex; align-items:center; justify-content:center;}
#diceLayer[hidden]{display:none;}
#diceLayer canvas{display:block;}
.tray{position:relative; --rim:14px;}
#diceLayer[data-on] .tray{pointer-events:auto;}   /* while showing, a click on the tray keeps the roll; anywhere else puts it away */
.tray > *{position:absolute;}
.tray-rim{inset:calc(-1 * var(--rim)); background:var(--rimBg); box-shadow:0 18px 40px rgba(0,0,0,0.55);}
.tray-floor{inset:0; background:var(--floorBg);}
.tray-pic{inset:0; background-repeat:no-repeat; background-position:center; opacity:0.92;}
.tray-pic[data-fit="fit"]{background-size:contain;}
.tray-pic[data-fit="fill"]{background-size:cover;}
.tray-shade{inset:0; background:radial-gradient(ellipse at 50% 45%, transparent 50%, rgba(0,0,0,0.5) 100%), linear-gradient(180deg, rgba(0,0,0,0.35), transparent 14%);}
.tray-dice{inset:0;}
.tray[data-shape="square"] .tray-rim, .tray[data-shape="rect"] .tray-rim{border-radius:16px;}
.tray:is([data-shape="square"], [data-shape="rect"]) :is(.tray-floor, .tray-pic, .tray-shade){border-radius:5px;}
.tray[data-shape="hex"] :is(.tray-rim, .tray-floor, .tray-pic, .tray-shade){clip-path:polygon(25% 0, 75% 0, 100% 50%, 75% 100%, 25% 100%, 0 50%);}
.tray[data-shape="oct"] :is(.tray-rim, .tray-floor, .tray-pic, .tray-shade){clip-path:polygon(29.3% 0, 70.7% 0, 100% 29.3%, 100% 70.7%, 70.7% 100%, 29.3% 100%, 0 70.7%, 0 29.3%);}
.tray[data-shape="round"] :is(.tray-rim, .tray-floor, .tray-pic, .tray-shade){border-radius:50%;}
.tray:is([data-shape="hex"], [data-shape="oct"]){filter:drop-shadow(0 16px 22px rgba(0,0,0,0.55));}
/* The throw slider (next to the Roll buttons) and the style menu's section heads */
.throw-pick{display:inline-flex; align-items:center; gap:6px; font-size:0.78rem; color:var(--ink-dim);}
.throw-pick small{font-size:0.68rem; opacity:0.8;}
.throw-pick input{width:110px;}
.dice-style-menu .ds-head{grid-column:1 / -1; font-size:0.68rem; text-transform:uppercase; letter-spacing:0.06em; color:var(--sea); border-top:1px solid var(--border); padding-top:6px; margin-top:2px;}
.dice-style-menu .ds-head:first-child{border-top:none; padding-top:0; margin-top:0;}
.dice-style-menu input[type=url]{width:100%; min-width:0;}
.dice-style-menu{max-height:min(75vh, 640px); overflow-y:auto;}
.dice-card{position:fixed; left:50%; bottom:18px; transform:translateX(-50%); z-index:401; width:min(460px, calc(100vw - 32px));
  background:var(--panel); border:1px solid var(--sea); border-radius:8px; box-shadow:0 10px 30px rgba(0,0,0,0.5); padding:10px 14px 12px; pointer-events:auto;}
.dice-card[hidden]{display:none;}
.dice-card .dc-head{display:flex; align-items:baseline; gap:8px; padding-right:24px;}
.dice-card .dc-who{color:var(--sea); font-weight:600;}
.dice-card .dc-what{color:var(--ink-dim); font-size:0.85rem; overflow-wrap:anywhere;}
.dice-card .dc-total{font-family:var(--font-display); font-size:2rem; color:var(--ink); line-height:1.1; margin-top:2px;}
.dice-card .dc-total small{font-family:ui-monospace, Consolas, monospace; font-size:0.8rem; color:var(--ink-dim); margin-left:8px;}
.dice-card .dc-dice{display:flex; flex-wrap:wrap; gap:4px; margin-top:6px;}
.dice-card .dc-die{font-family:ui-monospace, Consolas, monospace; font-size:0.78rem; border:1px solid var(--border); border-radius:4px; padding:1px 6px; background:var(--panel2);}
.dice-card .dc-die.x{opacity:0.45; text-decoration:line-through;}
.dice-card .dc-die.n20{border-color:#f2c14e; color:#f2c14e;}
.dice-card .dc-die.n1{border-color:var(--danger); color:var(--danger);}
.dice-card .dc-nat{font-weight:700; margin-top:4px;}
.dice-card .dc-nat.n20{color:#f2c14e;}
.dice-card .dc-nat.n1{color:var(--danger);}
.dice-card .dc-close{position:absolute; top:4px; right:6px; background:none; border:none; color:var(--ink-dim); font-size:1.4rem; line-height:1; padding:0 4px; box-shadow:none;}
/* A crit's GIF or clip with its flavor banner right above it, centered over everything.
   Stays until the viewer clicks outside it or the ✕ (js/dice.js, showCritFx). Hits are gold on
   purple and blue with sparkles; misses are ember red and orange with rising embers. */
@property --ang{syntax:'<angle>'; initial-value:0deg; inherits:false;}
.crit-fx{--c1:#2a1050; --c2:#16306b; --c3:#5a3a0a; --glow:#ffd54a; --edge:#fff3b0; --ink1:#fff6c9; --ink2:#ffd54a; --ink3:#ff9d2e;
  position:fixed; inset:0; z-index:500; display:flex; align-items:center; justify-content:center; padding:16px;
  background:radial-gradient(circle at 50% 45%, rgba(255,220,120,0.18), rgba(0,0,0,0.55) 60%);}
.crit-fx.fail{--c1:#3a0606; --c2:#6b1a06; --c3:#2a0a02; --glow:#ff5a1f; --edge:#ffb36b; --ink1:#ffe0c0; --ink2:#ff7a2e; --ink3:#d81e1e;
  background:radial-gradient(circle at 50% 45%, rgba(255,80,20,0.2), rgba(0,0,0,0.6) 60%);}
/* A white flash as it arrives */
.crit-fx::before{content:""; position:fixed; inset:0; background:radial-gradient(circle at 50% 45%, rgba(255,255,255,0.9), transparent 55%); opacity:0; animation:cfFlash 0.7s ease-out; pointer-events:none;}
.crit-fx.fail::before{background:radial-gradient(circle at 50% 45%, rgba(255,120,40,0.9), transparent 55%);}
@keyframes cfFlash{0%{opacity:1;} 100%{opacity:0;}}

/* Banner and GIF move together, centered */
.cf-stage{position:relative; display:flex; flex-direction:column; align-items:center; gap:14px; max-width:min(640px, calc(100vw - 32px));
  animation:cfBurst 0.6s cubic-bezier(.2,1.6,.4,1) both;}
.crit-fx.fail .cf-stage{animation:cfSlam 0.55s cubic-bezier(.5,0,.6,1.4) both, cfShake 0.45s 0.5s both;}
@keyframes cfBurst{0%{transform:scale(0.4); opacity:0;} 100%{transform:scale(1); opacity:1;}}
@keyframes cfSlam{0%{transform:translateY(-60vh) scale(1.3); opacity:0;} 70%{opacity:1;} 100%{transform:none; opacity:1;}}
@keyframes cfShake{0%,100%{transform:none;} 20%{transform:translate(-8px,2px) rotate(-1deg);} 40%{transform:translate(7px,-2px) rotate(1deg);} 60%{transform:translate(-5px,1px);} 80%{transform:translate(3px,0);}}

/* The banner: a running light around the border, a slowly moving gradient inside */
.cf-banner{position:relative; padding:3px; border-radius:14px; max-width:100%;
  background:conic-gradient(from var(--ang), transparent 0deg, var(--glow) 40deg, var(--edge) 60deg, var(--glow) 80deg, transparent 130deg, transparent 180deg, var(--glow) 220deg, var(--edge) 240deg, var(--glow) 260deg, transparent 310deg);
  animation:cfSpin 3s linear infinite, cfPulse 1.6s ease-in-out infinite;}
@keyframes cfSpin{to{--ang:360deg;}}
@keyframes cfPulse{0%,100%{box-shadow:0 0 18px 2px color-mix(in srgb, var(--glow) 55%, transparent), 0 0 60px 8px color-mix(in srgb, var(--glow) 25%, transparent);}
  50%{box-shadow:0 0 28px 6px color-mix(in srgb, var(--glow) 80%, transparent), 0 0 90px 18px color-mix(in srgb, var(--glow) 35%, transparent);}}
.cf-panel{position:relative; overflow:hidden; border-radius:11px; padding:14px 26px 16px; text-align:center;
  background:linear-gradient(120deg, var(--c1), var(--c2), var(--c3), var(--c1)); background-size:300% 300%; animation:cfDrift 6s ease-in-out infinite;}
@keyframes cfDrift{0%,100%{background-position:0% 50%;} 50%{background-position:100% 50%;}}
/* A soft light band sweeping across the panel */
.cf-panel::after{content:""; position:absolute; inset:-50% auto -50% -40%; width:35%; transform:skewX(-20deg);
  background:linear-gradient(90deg, transparent, rgba(255,255,255,0.22), transparent); animation:cfSweep 2.6s ease-in-out infinite;}
@keyframes cfSweep{0%{left:-40%;} 60%,100%{left:130%;}}

/* The words: gold lettering with a shine running through, each letter popping in */
.cf-text{position:relative; z-index:1; margin:0; font-family:'Cinzel Decorative', var(--font-display), serif; font-weight:900;
  font-size:clamp(1.25rem, 4.2vw, 2.5rem); line-height:1.15; letter-spacing:0.03em; text-transform:uppercase; overflow-wrap:anywhere;}
.cf-text .w{display:inline-block; white-space:nowrap;}
.cf-text .l{display:inline-block; color:transparent; -webkit-background-clip:text; background-clip:text;
  background-image:linear-gradient(100deg, var(--ink3) 0%, var(--ink2) 30%, var(--ink1) 45%, #fff 50%, var(--ink1) 55%, var(--ink2) 70%, var(--ink3) 100%);
  background-size:300% 100%; animation:cfLetter 0.45s cubic-bezier(.2,1.8,.4,1) both, cfShine 2.4s linear infinite, cfWave 2.2s ease-in-out infinite;
  filter:drop-shadow(0 2px 0 rgba(0,0,0,0.6)) drop-shadow(0 0 8px color-mix(in srgb, var(--glow) 60%, transparent));}
.crit-fx.fail .cf-text .l{animation:cfDrop 0.4s cubic-bezier(.6,0,.8,1.6) both, cfShine 2.4s linear infinite, cfWave 1.6s ease-in-out infinite;}
@keyframes cfLetter{0%{transform:scale(0) rotate(-25deg); opacity:0;} 100%{transform:none; opacity:1;}}
@keyframes cfDrop{0%{transform:translateY(-40px) scale(1.6); opacity:0;} 100%{transform:none; opacity:1;}}
@keyframes cfShine{0%{background-position:100% 0;} 100%{background-position:-100% 0;}}
@keyframes cfWave{0%,100%{translate:0 0;} 50%{translate:0 -3px;}}

/* Sparkles (hit) and embers (miss) drifting out from the banner */
.cf-spark{position:absolute; z-index:2; width:var(--s); height:var(--s); pointer-events:none; left:var(--x); top:var(--y);
  background:radial-gradient(circle, #fff 0 20%, var(--glow) 40%, transparent 70%);
  clip-path:polygon(50% 0, 60% 40%, 100% 50%, 60% 60%, 50% 100%, 40% 60%, 0 50%, 40% 40%);
  animation:cfTwinkle var(--d) ease-in-out var(--delay) infinite;}
.crit-fx.fail .cf-spark{clip-path:circle(50%); background:radial-gradient(circle, #fff3c0 0 15%, var(--glow) 45%, transparent 70%); animation-name:cfEmber;}
@keyframes cfTwinkle{0%,100%{transform:scale(0) rotate(0deg); opacity:0;} 40%{transform:scale(1) rotate(90deg); opacity:1;} 70%{transform:translate(var(--dx), var(--dy)) scale(0.6) rotate(160deg); opacity:0.8;}}
@keyframes cfEmber{0%{transform:translate(0,0) scale(0.4); opacity:0;} 20%{opacity:1;} 100%{transform:translate(var(--dx), calc(var(--dy) - 40px)) scale(0); opacity:0;}}

/* The GIF */
.cf-box{position:relative;}
.cf-box img, .cf-box video{display:block; max-width:min(560px, calc(100vw - 32px)); max-height:55vh; border-radius:10px;
  box-shadow:0 0 0 2px color-mix(in srgb, var(--glow) 60%, transparent), 0 14px 40px rgba(0,0,0,0.65);}
.cf-close{position:absolute; top:-14px; right:-14px; width:34px; height:34px; border-radius:50%; border:1px solid var(--glow); background:#120a04; color:var(--edge);
  font-size:1.2rem; line-height:1; padding:0; cursor:pointer; box-shadow:0 0 12px color-mix(in srgb, var(--glow) 60%, transparent);}

/* Reduced motion: the same look, standing still */
@media (prefers-reduced-motion: reduce){
  .crit-fx::before, .cf-stage, .crit-fx.fail .cf-stage, .cf-banner, .cf-panel, .cf-panel::after, .cf-text .l, .crit-fx.fail .cf-text .l, .cf-spark{animation:none !important;}
  .cf-panel::after, .cf-spark{display:none;}
}
/* A typed damage roll (js/damage.js): each type in its color. An amount changed by resistance,
   vulnerability or immunity grows, then turns into the new amount with the word beside it */
.dc-parts{display:flex; flex-wrap:wrap; justify-content:center; gap:4px 14px; margin:2px 0 6px;}
.dc-part{color:var(--dc); font-weight:600; white-space:nowrap; display:inline-flex; align-items:baseline; gap:4px;}
.dc-part .dp-now, .dc-part .dp-was{font-size:1.25rem; display:inline-block;}
.dc-part em{font-style:normal; font-size:0.72rem; text-transform:uppercase; letter-spacing:0.05em; opacity:0; animation:dpWord 0.4s ease-out 1.8s forwards;}
.dc-part.changed .dp-was{color:var(--ink, #fff); animation:dpWas 1.8s ease-in forwards;}
.dc-part.changed .dp-now{font-size:0; opacity:0; animation:dpNow 0.5s ease-out 1.8s forwards; text-shadow:0 0 10px var(--dc);}
@keyframes dpWas{0%{transform:scale(1);} 60%{transform:scale(1.6); color:var(--dc); text-shadow:0 0 14px var(--dc);} 99%{transform:scale(1.7); opacity:1; font-size:1.25rem;} 100%{transform:scale(1.7); opacity:0; font-size:0;}}
@keyframes dpNow{0%{font-size:1.25rem; transform:scale(1.7); opacity:0;} 100%{font-size:1.25rem; transform:scale(1); opacity:1;}}
@keyframes dpWord{to{opacity:0.9;}}
.dc-math{font-size:0.72rem; opacity:0.75; text-align:center; margin-bottom:4px; line-height:1.35;}
@media (prefers-reduced-motion: reduce){ .dc-part.changed .dp-was{display:none;} .dc-part.changed .dp-now{font-size:1.25rem; opacity:1; animation:none;} .dc-part em{opacity:0.9; animation:none;} }
