/* combat */
#combat{position:absolute;inset:0;z-index:25;display:none;align-items:center;justify-content:center;
  padding:14px;background:radial-gradient(120% 100% at 50% 40%,rgba(10,14,22,.82),rgba(4,6,10,.94))}
#combat.on{display:flex;animation:fadeIn .2s ease}
/* a jolt when the caller takes a piece out of you */
#combat.struck .cb{animation:struck .32s ease}
@keyframes struck{0%{transform:translateX(0)}20%{transform:translateX(-5px)}
  45%{transform:translateX(4px)}70%{transform:translateX(-2px)}100%{transform:translateX(0)}}
#combat.critical .cb{box-shadow:0 0 0 1px rgba(255,95,86,.5),0 0 60px -10px rgba(255,95,86,.55)}
#combat.critical .cb-top{background:rgba(255,95,86,.07)}
.cb-dmg{position:absolute;right:-4px;top:-14px;font-family:var(--mono);font-size:13px;font-weight:700;
  color:var(--bad);text-shadow:0 2px 8px #000;pointer-events:none;animation:dmgFloat .9s ease forwards}
@keyframes dmgFloat{0%{opacity:0;transform:translateY(6px)}18%{opacity:1;transform:translateY(-2px)}
  100%{opacity:0;transform:translateY(-18px)}}
/* What you take off them (gold for a want met), and guard they win back. */
.cb-dmg.deal{color:#ffe6a8;font-size:14px}
.cb-dmg.deal.good{color:#ffd34d;font-size:16px;text-shadow:0 0 10px rgba(255,211,77,.55),0 2px 8px #000;
  animation:dmgPunch 1s cubic-bezier(.2,1.6,.4,1) forwards}
.cb-dmg.up{color:var(--good)}
@keyframes dmgPunch{0%{opacity:0;transform:translateY(4px) scale(.6)}16%{opacity:1;transform:translateY(-4px) scale(1.35)}
  34%{transform:translateY(-6px) scale(1)}100%{opacity:0;transform:translateY(-20px) scale(1)}}
/* A meter's ghost: where it was, pale, draining after the hit. */
.cb-meters .bar{position:relative}
.cb-ghost{position:absolute;left:0;top:0;bottom:0;border-radius:var(--pill,6px);background:rgba(255,255,255,.62);
  transition:width .5s ease .32s;pointer-events:none}
/* Their face: rocked by a line that lands, coming at you on their turn. */
.cb-face.reel{animation:faceReel .45s ease}
.cb-face.lunge{animation:faceLunge .4s ease}
@keyframes faceReel{0%{transform:none}22%{transform:translateX(7px) rotate(12deg) scale(.92);filter:brightness(1.8)}
  55%{transform:translateX(-3px) rotate(-5deg)}100%{transform:none}}
@keyframes faceLunge{0%{transform:none}35%{transform:translateX(-8px) scale(1.22)}100%{transform:none}}
/* A run of wants met, on the turn badge. */
#cbTimer.hot{background:linear-gradient(90deg,#ff7a2f,#ffd34d);color:#2a1300;box-shadow:0 0 14px -2px rgba(255,150,50,.75);
  animation:hotPulse 1.1s ease-in-out infinite}
@keyframes hotPulse{50%{box-shadow:0 0 22px 0 rgba(255,170,60,.9)}}
/* Guard broken: the meter flares and the card lights up for a beat. */
#combat.broke .cb{animation:guardBreak .7s ease}
#combat.broke #cbFrus{animation:none}
#combat.broke .cb-meters .bar-row:first-child .bar{animation:barFlare .7s ease}
@keyframes guardBreak{0%{box-shadow:0 0 0 0 rgba(255,211,77,0)}25%{box-shadow:0 0 0 2px rgba(255,211,77,.8),0 0 70px 4px rgba(255,211,77,.55)}
  100%{box-shadow:0 0 0 0 rgba(255,211,77,0)}}
@keyframes barFlare{0%{background:rgba(10,2,20,.55)}20%{background:#ffd34d}100%{background:rgba(10,2,20,.55)}}
@media(prefers-reduced-motion:reduce){
  #combat.struck .cb{animation:none}
  .cb-face.reel,.cb-face.lunge,#combat.broke .cb,#cbTimer.hot{animation:none}
  .cb-ghost{transition:none}
  .cb-dmg,.cb-dmg.deal.good{animation:dmgFadeOnly .9s ease forwards}
  @keyframes dmgFadeOnly{0%{opacity:0}18%{opacity:1}100%{opacity:0}}
}
/* max-height in % of the padded overlay rather than vh: on a phone the browser
   chrome makes vh taller than the part of the page you can actually see. */
.cb{width:min(940px,97vw);max-height:100%;display:flex;flex-direction:column;overflow:hidden}
.cb-top{display:flex;gap:12px;padding:14px;border-bottom:1px dashed var(--line);align-items:center}
.cb-face{font-size:46px;animation:breathe 2.6s ease-in-out infinite}
@keyframes breathe{50%{transform:translateY(-4px) scale(1.04)}}
.cb-who{flex:1}
.cb-who h3{font-family:var(--mono);font-size:14px;letter-spacing:.14em;text-transform:uppercase}
.cb-who .sub{font-size:11px;color:var(--dim);margin-top:2px}
.cb-meters{width:min(300px,42%);display:flex;flex-direction:column;gap:5px}
.cb-meters .bar-row{position:relative}
/* The meters' names: four emoji were a legend you had to hover to read. */
.cb-meters .nm{flex:none;width:66px;font-size:10.5px;color:var(--dim);white-space:nowrap}
.cb-line{padding:12px 16px;font-size:15px;line-height:1.5;min-height:74px;background:rgba(11,15,22,.5)}
.cb-line .say{color:var(--text)} .cb-line .nar{color:var(--dim);font-style:italic;font-size:13px}
/* The tell, beside the caller's line. Flowing text, not a flex row, which
   squeezed it into a tall narrow column. */
.cb-tell{flex:none;padding:7px 16px;font-size:12.5px;line-height:1.38;
  background:rgba(11,15,22,.5);border-top:1px dashed rgba(255,179,71,.22)}
.cb-tell .tt{font-style:italic;color:#e3c68d}
.cb-tell .tw{color:var(--hold);font-family:var(--mono);font-size:11px;white-space:nowrap}
.cb-tell:empty{display:none}
/* A move the caller has already heard this call. */
.move .mw{float:right;font-family:var(--mono);font-size:9.5px;color:var(--dim);letter-spacing:.06em}
.move.worn .mn{opacity:.72}
/* The close, once earned: first, full width, and unmistakable. */
.move.primary{grid-column:1/-1;border-color:var(--good);
  background:linear-gradient(180deg,rgba(90,212,138,.18),rgba(90,212,138,.07));
  box-shadow:0 0 0 1px rgba(90,212,138,.22),0 10px 26px -14px var(--good)}
.move.primary:hover:not(:disabled){border-color:var(--good);background:rgba(90,212,138,.24)}
.move.primary .mn{font-weight:700}
.cb-log{padding:8px 16px;max-height:120px;font-size:12px;color:var(--dim);border-top:1px dashed var(--line);font-family:var(--mono)}
.cb-log div{padding:2px 0}
/* The moves get the remaining height and scroll (min-height:0 lets the grid
   shrink). The four backgrounds are a scroll shadow: visible exactly when
   there is more to scroll that way. */
/* `align-content:start`, so rows keep their content height rather than
   stretching (a lone End call button would otherwise grow). */
.cb-moves{display:grid;grid-template-columns:1fr 1fr;gap:7px;padding:12px;overflow-y:auto;min-height:0;
  align-content:start;
  background:
    linear-gradient(var(--ink2) 30%,rgba(21,27,37,0)) top/100% 22px no-repeat local,
    linear-gradient(rgba(21,27,37,0),var(--ink2) 70%) bottom/100% 22px no-repeat local,
    radial-gradient(farthest-side at 50% 0,rgba(0,0,0,.6),rgba(0,0,0,0)) top/100% 12px no-repeat,
    radial-gradient(farthest-side at 50% 100%,rgba(0,0,0,.6),rgba(0,0,0,0)) bottom/100% 12px no-repeat}
.cb-line{flex:none}
/* On a phone the flavour shrinks so more moves show without scrolling. */
@media(max-width:640px){
  .cb-moves{grid-template-columns:1fr}
  .cb-meters .nm{display:none}
  /* The title row goes; the turn badge floats in its corner. The HUD already
     shows the queue. */
  .cb{position:relative}
  .cb .sign-title{position:absolute;top:0;right:0;z-index:2;
    padding:7px 9px;border:0;background:none}
  .cb .sign-title>span:first-child{display:none}
  /* The meters get their own full-width row, two up. */
  .cb-top{flex-wrap:wrap;row-gap:9px}
  .cb-meters{width:100%;display:grid;grid-template-columns:1fr 1fr;gap:5px 14px}
  .cb-meters .bar-row{margin-top:0}
  .bar-row .val{width:auto;min-width:32px;font-size:11px}
  .bar{height:11px}
  /* "TURN 1" was breaking across two lines and taking the header with it. */
  .cb .sign-title .badge{flex:none;white-space:nowrap;letter-spacing:.1em;padding:3px 7px}
  /* Every row above the buttons is measured in buttons: the moves take what is
     left, so eight pixels of padding here is a move you can no longer reach
     without scrolling on a timer. */
  .cb-top{padding:8px 12px;gap:10px}
  /* Room for the floating badge on the name's row only. Names may take two
     lines, no more. */
  .cb-who{margin-right:62px;min-width:0}
  .cb-who h3{display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
  .cb-face{font-size:28px}
  .cb-who h3{font-size:13px;letter-spacing:.1em}
  .cb-line{min-height:0;padding:8px 14px;font-size:14px}
  .cb-tell{padding:6px 14px;font-size:12px}
  .cb-log{max-height:40px;padding:5px 14px}
  .hold-note{display:none}
  .cb-moves{padding:9px 10px;gap:6px}
}
/* 320px: the transcript goes first. */
@media(max-width:360px){
  .cb-log{display:none}
  .cb-line{min-height:0}
  .cb-who .sub{display:none}
  /* The caller's town keeps its last letters; the tracking goes instead. */
  .cb-who h3{font-size:12.5px;letter-spacing:.04em}
  .cb .sign-title .badge{padding:3px 6px;letter-spacing:.06em}
  /* Move explanations hidden: the emoji and line say enough. */
  .move .md{display:none}
  .move{padding:9px 11px}
}
/* Landscape: reclaim the height the transcript and the portrait were using. */
/* Landscape (~340px tall): everything but the buttons is cut back hard. */
@media(max-height:520px){
  .cb .sign-title{padding:5px 12px;font-size:10px}
  .cb-top{padding:6px 12px;gap:8px}
  .cb-face{font-size:24px;animation:none}
  /* The meters stay beside the name, two up. */
  .cb-top{flex-wrap:nowrap}
  .cb-meters{width:min(400px,54%);display:grid;grid-template-columns:1fr 1fr;gap:4px 18px}
  .cb-meters .bar-row{margin-top:0}
  .cb-line{min-height:0;padding:7px 12px;font-size:13px}
  .cb-meters .nm{display:none}
  .cb-log,.hold-note{display:none}
  .cb-moves{grid-template-columns:1fr 1fr;padding:8px 10px;gap:6px}
  /* The name and its emoji already say what a move does; the explanation is the
     first thing to go when there are 340px of screen to work with. */
  .move .md{display:none}
  .move{padding:7px 10px}
}
.move{text-align:left;background:rgba(34,43,59,.65);border:1px solid var(--line);border-radius:8px;
  padding:9px 11px;cursor:pointer;transition:.12s}
.move:hover:not(:disabled){border-color:var(--brand);background:rgba(255,111,145,.14)}
.move:disabled{opacity:.38;cursor:not-allowed}
.move .mn{font-size:14px} .move .md{font-size:11px;color:var(--dim);margin-top:2px}
.move .mk{display:inline-block;min-width:15px;margin-right:6px;padding:1px 4px;border-radius:4px;
  background:#0c1018;border:1px solid var(--line);font-family:var(--mono);font-size:10px;
  color:var(--hold);text-align:center;vertical-align:1px}
.move:focus-visible{outline:2px solid var(--hold);outline-offset:2px}
.move .mc{float:right;font-family:var(--mono);font-size:10px;color:var(--hold)}
/* ---- the moves, on a thumb ----
   A grid, not floats or flex: the cost sits in its own column and cannot
   overlap or push out a wrapped reply. No 1–9 key chip on touch. The target
   size comes from padding, not min-height, which on a grid item would stop
   the row growing for a wrapped reply. */
@media(pointer:coarse){
  .move{display:grid;grid-template-columns:1fr auto;column-gap:10px;align-items:center;
    padding:13px 12px}
  .move .mk{display:none}
  .move .mn{grid-column:1;grid-row:1;min-width:0;font-size:15px;line-height:1.3}
  .move .mc{grid-column:2;grid-row:1;float:none;justify-self:end;white-space:nowrap;
    font-size:11px;letter-spacing:.03em;color:var(--hold);opacity:.9}
  .move .mw{grid-column:1/-1;float:none;margin-top:3px}
  /* The explanation goes on touch. */
  .move .md{display:none}
  /* The close is the one you are playing for; make it read as a way out
     rather than the sixth grey rectangle. */
  .move.primary{padding:16px 12px}
  .move.primary .mn{font-size:16px}
}
/* 320px: 44px targets, which buys the fifth button. After the block above so
   it wins. */
@media(pointer:coarse) and (max-width:360px){
  .move{padding:11px 11px;column-gap:8px}
  .move .mn{font-size:14.5px}
  .move .mc{font-size:10.5px}
  .cb-line{font-size:13.5px}
}
/* The one button left when the call is over. Sized to the call card's own
   rhythm rather than to a settings row, and laid out as label + reward so the
   two never wrap through each other. */
/* Two classes to beat the coarse-pointer `.btn` rule later in the file.
   Nowrap: the label gives way first and the reward figure never moves (iOS
   fonts are wider than the test browser's, and a wrapped button is a slab). */
.btn.cb-end{display:flex;align-items:center;justify-content:center;gap:10px;flex-wrap:nowrap;
  min-height:0;padding:11px 14px;font-size:14px;line-height:1.25}
.btn.cb-end .ce-t{font-weight:600;letter-spacing:.01em;white-space:nowrap;
  min-width:0;overflow:hidden;text-overflow:ellipsis}
.btn.cb-end .ce-r{flex:0 0 auto;font-family:var(--mono);font-size:12px;color:var(--good);
  background:rgba(90,212,138,.12);border:1px solid rgba(90,212,138,.3);
  border-radius:999px;padding:2px 9px;white-space:nowrap}
@media(pointer:coarse){
  /* One line with a thumb floor; safe since it cannot wrap. */
  .btn.cb-end{min-height:46px;padding:12px 14px;border-radius:12px}
}
/* Narrow phones: the emoji is 22px of a button that has to fit a label and a
   figure on one line, and the telephone is the least of the three. */
@media(max-width:360px){
  .btn.cb-end{gap:8px;padding:12px 10px}
  .btn.cb-end .ce-t{font-size:13.5px}
  .btn.cb-end .ce-r{font-size:11px;padding:2px 7px}
}
.hold-note{padding:0 16px 12px;font-family:var(--mono);font-size:11px;color:var(--hold);opacity:.85}

/* ============================================================
   The channel an encounter arrived on
   One card for every channel; only the accent and engine/combat.js's two
   lines of wording change.
   ============================================================ */
#combat.ch-call .cb{--cbch:var(--hold)}
#combat.ch-mail .cb{--cbch:var(--brand)}
#combat.ch-text .cb{--cbch:var(--good)}
/* The hanging tab every .sign has, in the channel's colour. One element, no
   extra markup, and it is the first thing on the card the eye lands on. */
#combat[class*=ch-] .cb::before{background:var(--cbch,var(--brand))}
#combat[class*=ch-] .cb-top{border-bottom-color:var(--cbch,var(--line))}
/* The status line keeps the channel colour: held, or a thread to take time
   over. */
#combat[class*=ch-] .hold-note{color:var(--cbch,var(--dim))}
/* Written channels are a thread, so the transcript gets room. */
#combat.ch-mail .cb-log,#combat.ch-text .cb-log{max-height:168px;color:var(--text);
  border-top-color:var(--cbch)}
#combat.ch-mail .cb-log div,#combat.ch-text .cb-log div{padding:3px 0}
/* Nothing is ringing, so nothing pulses. The critical ring stays — running out
   of yourself is the same either way. */
#combat.ch-mail .cb-face,#combat.ch-text .cb-face{animation:none}
