/* RiftLearn.
   The mat copies the arrangement Riftbound clients use, because that is the
   layout players already read without thinking: score ladders down both edges
   with the player's name beside them, legend and floating resources in the
   outer corners, two large battlefield boxes across the middle, runes and units
   in rows on your side, hand along the bottom between deck and trash. */
:root{
  --deep:#04101f; --mat:#14355e; --mat2:#0f2a4c; --matEdge:rgba(150,200,255,.28);
  --line:rgba(255,255,255,.11);
  --text:#eef4fb; --muted:#c2d4e8; --dim:#89a2c0;
  --gold:#f2cc7b; --green:#5fd3a0; --red:#ff8189; --blue:#75b8ff;
}
*{box-sizing:border-box}
body{margin:0;color:var(--text);font-size:15px;
  font-family:Inter,ui-sans-serif,system-ui,-apple-system,"Segoe UI",sans-serif;
  background:#060c15}
/* body.site in home.css paints the page; this stays for a bare app.css load. */
button{font:inherit;color:inherit;cursor:pointer}
h1,h2,h3{letter-spacing:-.01em}

/* The trainer gets its own width. The landing page keeps the 1180px reading
   measure; a board does not read, it is looked at, and it wants the room. */
#app .shell{max-width:1780px}
.wrap{display:grid;grid-template-columns:264px minmax(0,1fr) 372px;
  border:1px solid rgba(255,255,255,.10);border-radius:18px;overflow:hidden;
  background:#0b1626;box-shadow:0 24px 70px rgba(0,0,0,.35);margin-bottom:40px}
@media(max-width:1500px){.wrap{grid-template-columns:240px minmax(0,1fr) 340px}}
@media(max-width:1240px){.wrap{grid-template-columns:224px minmax(0,1fr)}
  .rail{grid-column:1/-1;border-left:0;border-top:1px solid var(--line);position:static;max-height:none}}
@media(max-width:860px){.wrap{grid-template-columns:1fr}
  .side{position:static;max-height:none;border-right:0;border-bottom:1px solid var(--line)}}

/* ---------- lesson list ---------- */
.side{background:#081221;border-right:1px solid var(--line);padding:18px 12px 14px;
  display:flex;flex-direction:column}
.sideHead{padding:0 6px 14px;margin-bottom:12px;border-bottom:1px solid var(--line)}
.sideKicker{margin:0;font-size:15px;font-weight:800;letter-spacing:-.01em;color:#fff}
.sideNote{color:var(--dim);font-size:11.5px;margin:5px 0 0;line-height:1.5}
.grp{font-size:9.5px;font-weight:800;letter-spacing:.12em;text-transform:uppercase;
  color:var(--dim);margin:14px 6px 5px}
.lsn{display:block;width:100%;text-align:left;background:none;border:1px solid transparent;
  border-radius:10px;padding:9px 10px;margin-bottom:3px;line-height:1.35}
.lsn:hover{background:#11233d;border-color:var(--line)}
.lsn.on{background:rgba(242,204,123,.13);border-color:rgba(242,204,123,.45)}
.lsn b{display:block;font-size:13px;font-weight:700}
.lsn small{display:block;color:var(--dim);font-size:11px;margin-top:2px}
.lsn .lsnBar{display:block;height:3px;border-radius:99px;margin-top:7px;
  background:rgba(255,255,255,.10);overflow:hidden}
.lsn .lsnBar i{display:block;height:100%;background:var(--green);border-radius:99px}
.sideBack{margin-top:auto;width:100%}
.tick{color:var(--green)}

/* ---------- main ---------- */
.main{padding:20px 20px 26px;min-width:0}
.top h1{margin:0;font-size:24px;letter-spacing:-.02em}
.top p{margin:5px 0 0;color:var(--muted);font-size:14px}
.vars{display:flex;gap:6px;margin:14px 0 8px;flex-wrap:wrap}
.vars button{background:#11233d;border:1px solid var(--line);border-radius:99px;
  padding:6px 13px;font-size:12.5px;font-weight:600;color:var(--muted)}
.vars button:hover{border-color:rgba(255,255,255,.26);color:#fff}
.vars button.on{background:var(--gold);color:#17100a;border-color:transparent}
.vars button.isTest{color:var(--gold)}
.vars button.isTest.on{color:#17100a}
.refs{color:var(--dim);font-size:11.5px;margin:0 0 10px}
.refs code{background:#0a1728;border:1px solid var(--line);border-radius:5px;padding:2px 5px;font-size:11px}

/* ---------- the mat ---------- */
.mat{position:relative;border-radius:14px;padding:16px 52px;
  background:
    radial-gradient(ellipse at 50% 40%,#1b4272 0%,#123054 55%,#0c2141 100%);
  box-shadow:inset 0 0 0 1px var(--matEdge), 0 10px 40px rgba(0,0,0,.5)}

/* score ladder + rotated player name, as in the client */
.lad{position:absolute;top:8px;bottom:8px;width:26px;display:flex;align-items:center;gap:3px;z-index:3}
.lad.you{left:8px;flex-direction:column-reverse}
.lad.foe{right:8px;flex-direction:column}
.lad i{width:20px;height:20px;border-radius:5px;display:grid;place-items:center;flex:0 0 auto;
  font:700 9.5px/1 system-ui;font-style:normal;color:#8fb0d4;
  background:rgba(255,255,255,.05);box-shadow:inset 0 0 0 1px rgba(255,255,255,.07)}
.lad i.on{background:var(--green);color:#04150e;box-shadow:none}
.lad.foe i.on{background:var(--red);color:#2a0508}
.lad .who{writing-mode:vertical-rl;font-size:8.5px;letter-spacing:.18em;text-transform:uppercase;
  color:#7f9fc4;margin-top:6px;white-space:nowrap;overflow:hidden;max-height:110px}
.lad.you .who{transform:rotate(180deg)}

/* rows */
.row{display:flex;align-items:flex-start;gap:8px;padding:4px 0;position:relative;z-index:2}
.row.mid{align-items:stretch}
/* The decorative corner brackets drew hairlines straight through adjacent
   labels at small widths. The tray already has an inset outline; that is
   enough framing without the collisions. */
.corner{position:relative}

/* align-items must not be left at stretch. A flex line stretches every item
   to the tallest one, which beats aspect-ratio, so a 50px rune sitting beside
   a 145px unit was being pulled to 50x145 and its art cropped to a strip. */
.tray{flex:1;min-width:0;min-height:96px;border-radius:8px;padding:6px;
  display:flex;gap:5px;flex-wrap:wrap;align-items:flex-start;align-content:flex-start;
  box-shadow:inset 0 0 0 1px rgba(160,205,255,.14);transition:.15s}
.tray{position:relative}
.tray.empty:before{content:attr(data-empty);position:absolute;inset:0;display:grid;place-items:center;
  color:rgba(190,220,255,.30);font-size:10.5px;letter-spacing:.04em;white-space:nowrap;pointer-events:none}
.tray.drop{box-shadow:inset 0 0 0 2px var(--gold);background:rgba(242,204,123,.09);cursor:pointer}
.tray.tight{min-height:0}

.stack{flex:0 0 auto;display:flex;flex-direction:column;align-items:center;gap:3px;min-width:52px}
.stack .bk{width:44px;aspect-ratio:.717;border-radius:5px;display:grid;place-items:center;
  background:linear-gradient(160deg,#28629f,#0f2846);box-shadow:inset 0 0 0 1px rgba(160,205,255,.4);
  font:800 13px/1 system-ui;color:#cfe6ff}
.stack small{font-size:8.5px;color:#7f9fc4;letter-spacing:.08em;text-transform:uppercase}

/* floating energy / power, as the client labels it */
.float{flex:0 0 auto;padding:5px 9px;border-radius:7px;box-shadow:inset 0 0 0 1px rgba(160,205,255,.18);
  font-size:10.5px;color:#a8c4e2;line-height:1.5;min-width:96px}
.float b{display:block;font-size:8.5px;letter-spacing:.12em;text-transform:uppercase;color:#7f9fc4;margin-bottom:2px}
.float span{display:flex;justify-content:space-between;gap:10px}
.float i{font-style:normal;color:var(--gold);font-weight:800}

/* battlefields: two big boxes */
.bfs{display:grid;grid-template-columns:1fr 1fr;gap:10px;margin:5px 0;flex:1}
@media(max-width:740px){.bfs{grid-template-columns:1fr}}
.bf{position:relative;border-radius:10px;padding:8px;min-height:230px;
  box-shadow:inset 0 0 0 1px rgba(160,205,255,.22);display:flex;flex-direction:column;gap:5px;
  background:rgba(9,28,53,.35)}
.bf.contested{box-shadow:inset 0 0 0 2px rgba(255,129,137,.6)}
.bf.mine{box-shadow:inset 0 0 0 2px rgba(95,211,160,.5)}
.bf.theirs{box-shadow:inset 0 0 0 2px rgba(255,129,137,.35)}
.bfTag{position:absolute;top:6px;right:6px;font-size:8.5px;font-weight:800;letter-spacing:.06em;
  text-transform:uppercase;padding:3px 7px;border-radius:99px;z-index:2}
.bfTag.mine{background:rgba(95,211,160,.25);color:#c5f2de}
.bfTag.theirs{background:rgba(255,129,137,.22);color:#ffd4d7}
.bfTag.free{background:rgba(255,255,255,.09);color:#9db9d8}
.bfTag.contested{background:rgba(255,129,137,.35);color:#ffe0e2}
.half{min-height:74px;border-radius:7px;padding:5px;display:flex;gap:5px;flex-wrap:wrap;
  align-items:flex-start;align-content:flex-start}
.half.foe{background:rgba(255,129,137,.07)}
.half.you{background:rgba(95,211,160,.07)}
.half.drop{box-shadow:inset 0 0 0 2px var(--gold);background:rgba(242,204,123,.13);cursor:pointer}
.bfCard{align-self:center}

/* ---------- cards ---------- */
/* flex-basis is the MAIN axis, so a fixed basis becomes the height inside any
   column flex (.stack, .runePick) and squashes the card into a square. Width
   plus aspect-ratio is correct in both directions, so the basis stays auto. */
.c{position:relative;width:104px;flex:0 0 auto;aspect-ratio:.717;border-radius:7px;overflow:hidden;
  background:linear-gradient(150deg,var(--dc,#626c79),#071322 78%);
  box-shadow:0 2px 6px rgba(0,0,0,.45), inset 0 0 0 1px rgba(255,255,255,.14);
  transition:transform .16s, box-shadow .16s;cursor:pointer}
.c img{width:100%;height:100%;object-fit:cover;display:block}
/* Exhausted has to be unmistakable. Rotating 90 degrees is the physical
   convention, but a rune icon is nearly symmetric, so on screen a turned rune
   looks like an untouched one. Dim it, drain the colour, and mark it.
   Exhaustion is the single most load-bearing state in the game. */
.c.ex{transform:rotate(90deg) scale(.78);filter:saturate(.35) brightness(.62)}
.c.ex:after{content:"";position:absolute;inset:0;border-radius:inherit;
  background:rgba(4,12,24,.45);box-shadow:inset 0 0 0 2px rgba(150,175,205,.55)}
/* a small bar, drawn upright once the card is rotated, reading as "spent" */
.c.ex:before{content:"";position:absolute;z-index:2;left:50%;top:50%;
  width:56%;height:4px;border-radius:2px;background:rgba(214,232,255,.85);
  transform:translate(-50%,-50%) rotate(-90deg);box-shadow:0 1px 3px rgba(0,0,0,.6)}
.c.sel{box-shadow:0 0 0 2px var(--gold), 0 4px 12px rgba(0,0,0,.5);z-index:4}
.c.hot:hover{transform:translateY(-5px)}
.c.ex.hot:hover{transform:rotate(90deg) scale(.84)}
.c.big{width:146px}
/* Battlefields are printed landscape. Forcing them into a portrait frame
   cropped the art and the title off the card. */
.c.land{aspect-ratio:1.395}
.c.land.big{width:212px}
/* A legend sits inside .stack, which is a COLUMN flex, so flex-basis there is
   the height, not the width. Setting both width and flex-basis to 100px was
   forcing a 100x100 square and cropping every legend art to a box. Let
   aspect-ratio decide the height. */
.c.legend{width:100px}
/* Exhaust or recycle, chosen per rune, so energy vs power is a real decision. */
.runePick{display:flex;flex-direction:column;align-items:stretch;gap:2px}
.runePick .ruse{display:flex;flex-direction:column;align-items:center;gap:0;
  font:600 9px/1.1 inherit;letter-spacing:.02em;cursor:pointer;
  padding:3px 4px;border-radius:4px;border:1px solid var(--line);
  background:rgba(4,16,31,.85);color:var(--muted)}
.runePick .ruse b{font:400 8px/1.1 inherit;opacity:.6}
.runePick .ruse:hover{border-color:var(--gold);color:var(--gold)}
.c.rune{width:50px;aspect-ratio:.7;border-radius:5px}
.c.rune.ex{transform:rotate(90deg) scale(.84)}
.c.back{background:linear-gradient(160deg,#28629f,#0f2846)}
.c.bad{animation:shake .45s}
@keyframes shake{0%,100%{transform:translateX(0)}25%{transform:translateX(-5px)}75%{transform:translateX(5px)}}
.c .n{position:absolute;left:3px;top:3px;min-width:19px;height:19px;border-radius:5px;
  background:rgba(4,16,31,.94);box-shadow:inset 0 0 0 1px rgba(255,255,255,.25);
  font:800 12px/19px system-ui;text-align:center;padding:0 4px}
.c .mt{position:absolute;right:3px;top:3px;min-width:19px;height:19px;border-radius:5px;
  background:rgba(242,204,123,.95);color:#17100a;font:800 12px/19px system-ui;text-align:center;padding:0 4px}
.c .d{position:absolute;right:2px;bottom:2px;background:rgba(255,129,137,.95);color:#2a0508;
  border-radius:4px;font:800 9.5px/1.4 system-ui;padding:1px 4px}
.c .kw{position:absolute;left:0;right:0;bottom:0;background:rgba(4,16,31,.92);
  font:800 9px/1.8 system-ui;letter-spacing:.03em;text-align:center;color:#cfe6ff}

/* ---------- hover preview ---------- */
#peek{position:fixed;z-index:80;width:380px;pointer-events:none;display:none;
  background:#0c2141;border-radius:12px;padding:10px;box-shadow:0 18px 50px rgba(0,0,0,.65),
  inset 0 0 0 1px rgba(160,205,255,.3)}
#peek.up{display:block}
#peek img{width:100%;border-radius:8px;display:block;margin-bottom:8px}
#peek h4{margin:0 0 3px;font-size:17px}
#peek .sub{color:var(--dim);font-size:12px;margin:0 0 9px}
#peek .st{display:flex;gap:6px;margin-bottom:7px}
#peek .st span{background:rgba(255,255,255,.07);border-radius:6px;padding:4px 9px;font-size:12px;color:var(--muted)}
#peek .st b{color:var(--gold)}
#peek .tx{font-size:14px;line-height:1.65;color:#dbe7f5;
  background:rgba(255,255,255,.06);border-radius:8px;padding:10px 12px;max-height:260px;overflow:auto}
.kwd{color:var(--gold);font-weight:700}
.ic{display:inline-grid;place-items:center;vertical-align:-2px;font-style:normal}
.ic.e{width:15px;height:15px;border-radius:50%;background:#1b3a63;box-shadow:inset 0 0 0 1px rgba(160,205,255,.4);
  font:800 9px/1 system-ui;color:#cfe6ff}
.ic.r{width:12px;height:12px;border-radius:50%;box-shadow:inset 0 0 0 1px rgba(0,0,0,.35)}
.ic.r.rainbow{background:conic-gradient(#dc684e,#c69d2f,#4a9e72,#32789f,#76479d,#c76c35,#dc684e)}
.ic.m,.ic.x,.ic.arrow{font-size:12px;color:var(--gold)}

/* ---------- right rail ---------- */
.rail{border-left:1px solid var(--line);background:#081221;padding:18px 15px;
  display:flex;flex-direction:column;gap:10px;max-height:100dvh;overflow-y:auto;position:sticky;top:0}
.prog{display:flex;gap:3px;margin:0 0 12px}
.prog i{height:3px;flex:1;border-radius:2px;background:#1b3454}
.prog i.on{background:var(--gold)}
.coach{border-radius:14px;padding:15px 16px;box-shadow:inset 0 0 0 1px rgba(242,204,123,.32);
  background:rgba(242,204,123,.07)}
.coach.bad{box-shadow:inset 0 0 0 1px rgba(255,129,137,.55);background:rgba(255,129,137,.09)}
.coach .say{margin:0;font-size:15px;font-weight:600;line-height:1.5}
.coach .hint{margin:8px 0 0;color:var(--muted);font-size:13px;line-height:1.55}
.coach .why{margin:10px 0 0;color:var(--muted);font-size:13px;line-height:1.65;
  padding-left:9px;box-shadow:inset 2px 0 0 rgba(95,211,160,.55)}
.coach .why b,.coach .say b{color:#fff}
.coach .caveat{margin:7px 0 0;color:var(--dim);font-size:11px;line-height:1.45}
.acts{display:flex;gap:5px;flex-wrap:wrap;margin-top:9px}
.btn{background:#1b3454;border:1px solid var(--line);border-radius:10px;padding:9px 14px;
  font-size:12px;font-weight:600}
.btn:hover{border-color:rgba(255,255,255,.3)}
.btn.gold{background:linear-gradient(135deg,#e8ba5f,#b97a2e);color:#17100a;border-color:transparent}
.btn.red{background:rgba(255,129,137,.2);border-color:rgba(255,129,137,.5)}
.btn.sm{padding:6px 11px;font-size:12px}
.quiz{display:flex;flex-direction:column;gap:5px;margin-top:9px}
.quiz button{text-align:left;background:#0f2440;border:1px solid var(--line);border-radius:8px;
  padding:8px 10px;font-size:12px;line-height:1.4}
.quiz button:hover{border-color:rgba(242,204,123,.5)}
.quiz button.right{background:rgba(95,211,160,.17);border-color:rgba(95,211,160,.55)}
.quiz button.wrong{background:rgba(255,129,137,.13);border-color:rgba(255,129,137,.5);opacity:.6}
.ai{border-radius:11px;padding:9px 11px;box-shadow:inset 0 0 0 1px rgba(117,184,255,.38);
  background:rgba(117,184,255,.09)}
.ai b{color:var(--blue);font-size:9.5px;letter-spacing:.09em;text-transform:uppercase;display:block;margin-bottom:3px}
.ai p{margin:0;font-size:12px;line-height:1.5;color:var(--muted)}
.checks{display:flex;flex-direction:column;gap:3px;margin-top:8px}
.checks div{font-size:11px;color:var(--dim);display:flex;gap:6px;align-items:baseline}
.checks div.ok{color:var(--green)}
.checks div.now{color:var(--gold);font-weight:600}
.logBox{border-radius:14px;box-shadow:inset 0 0 0 1px var(--line);background:rgba(10,26,46,.5);
  padding:8px 9px;flex:1;min-height:110px;display:flex;flex-direction:column}
.logBox h4{margin:0 0 7px;font-size:10px;letter-spacing:.12em;text-transform:uppercase;color:var(--dim)}
.logList{overflow-y:auto;flex:1;display:flex;flex-direction:column-reverse;gap:2px;max-height:200px}
.logList div{font-size:11px;line-height:1.45;color:var(--muted);padding:2px 0;
  border-bottom:1px solid rgba(255,255,255,.04)}
.logList .you{color:#c5f2de}.logList .foe{color:#ffd4d7}.logList .sys{color:var(--dim)}
.done{border-radius:11px;padding:12px;box-shadow:inset 0 0 0 1px rgba(95,211,160,.45);
  background:rgba(95,211,160,.09)}
.done h3{margin:0 0 4px;font-size:14.5px}
.done p{margin:0 0 9px;color:var(--muted);font-size:12px;line-height:1.55}

/* Tests read differently from lessons: same machinery, but the hint is withheld
   until a mistake, so the learner has to read the board rather than follow
   instructions. The pill is marked so the difference is visible before you
   click it. */
.vars button.isTest{background:rgba(95,211,160,.13);color:#b6e8d1;
  border-color:rgba(95,211,160,.4)}
.vars button.isTest.on{background:var(--green);color:#04150e;border-color:transparent}

/* ---------- card gallery (deck training) ----------
   A deck list is a set of cards with reasons, not a position, so the board is
   replaced wholesale. Cards stay hoverable, which is where the rules text is. */
.gallery{display:grid;gap:12px;padding:4px 0;
  grid-template-columns:repeat(auto-fill,minmax(164px,1fr))}
.gcard{margin:0;background:#0d1a2c;border:1px solid var(--line);border-radius:12px;
  overflow:hidden;display:flex;flex-direction:column;cursor:help;transition:.15s}
.gcard:hover{border-color:rgba(242,204,123,.5);transform:translateY(-2px)}
.gcard img{width:100%;aspect-ratio:.717;object-fit:cover;display:block;background:#050b14}
.gcard figcaption{padding:9px 10px 11px;display:flex;flex-direction:column;gap:4px}
.gcard figcaption b{font-size:12.5px;line-height:1.3}
.gcard figcaption span{color:var(--muted);font-size:11.5px;line-height:1.5}
.gcard .gtag{align-self:flex-start;font-style:normal;font-size:9.5px;font-weight:800;
  letter-spacing:.08em;text-transform:uppercase;color:var(--gold);
  background:rgba(242,204,123,.11);border:1px solid rgba(242,204,123,.28);
  border-radius:99px;padding:2px 7px;margin-top:2px}
.emp{color:var(--gold);font-weight:800;letter-spacing:.04em}
.c.empowered{box-shadow:0 0 0 2px var(--gold), 0 0 14px rgba(242,204,123,.45)}
.mat.gal{padding:14px 12px}

/* ---------- narrow screens ----------
   A playmat has a minimum sensible width: squeeze it below that and cards get
   clipped where you cannot reach them. Below 760px the whole mat scrolls
   sideways as one piece instead, so the layout stays intact and every card
   stays reachable. The page itself never scrolls horizontally. */
@media(max-width:760px){
  .mat{overflow-x:auto;overflow-y:hidden;padding:10px 12px;
    -webkit-overflow-scrolling:touch}
  .matIn{min-width:780px}
  .mat.gal{overflow:visible}
  .mat.gal .matIn{min-width:0}
}

/* ---------- signalling ----------
   Naming a region of the board and pointing at it. Mayer's signalling
   principle: cue the essential material. And spatial contiguity: the caption
   is anchored to the region, not left in the rail across the screen. */
.mat.dimmed .row > *,
.mat.dimmed .lad{opacity:.26;filter:saturate(.5);transition:opacity .2s}
/* Never set position here: the score ladders are absolutely positioned and
   forcing them to relative drops them out of place. z-index alone lifts a lit
   region above the dimming. */
.mat.dimmed [data-zone].lit{opacity:1;filter:none;z-index:5}

/* the outline is drawn as a sibling so it can sit above the dimming */
.spotBox{position:absolute;z-index:4;pointer-events:none;border-radius:12px;
  box-shadow:0 0 0 2px var(--gold), 0 0 0 7px rgba(242,204,123,.20),
             0 0 26px rgba(242,204,123,.35);
  animation:spotIn .22s ease-out}
@keyframes spotIn{from{opacity:0;transform:scale(.97)}to{opacity:1;transform:none}}

/* the caption sits above the outline, or below it when there is no room */
.spotTag{position:absolute;left:50%;bottom:100%;transform:translate(-50%,-9px);
  max-width:none;
  background:var(--gold);color:#17100a;font-size:12px;font-weight:800;
  letter-spacing:.02em;white-space:nowrap;padding:4px 11px;border-radius:99px;
  box-shadow:0 6px 18px rgba(0,0,0,.45)}
.spotTag:after{content:'';position:absolute;left:50%;top:100%;
  transform:translateX(-50%);border:6px solid transparent;border-top-color:var(--gold)}
/* near the top of the mat there is no room above, so the caption flips */
.spotBox.low .spotTag{bottom:auto;top:100%;transform:translate(-50%,9px)}
.spotBox.low .spotTag:after{top:auto;bottom:100%;
  border-top-color:transparent;border-bottom-color:var(--gold)}

/* while hunting for a region, every region invites a click */
.mat.hunting [data-zone]{cursor:pointer;border-radius:12px;
  box-shadow:inset 0 0 0 1px rgba(242,204,123,.30);transition:.14s}
.mat.hunting [data-zone]:hover{box-shadow:inset 0 0 0 2px var(--gold);
  background:rgba(242,204,123,.10)}
.mat.hunting .lad[data-zone]{box-shadow:0 0 0 1px rgba(242,204,123,.30)}
.mat.hunting .lad[data-zone]:hover{box-shadow:0 0 0 2px var(--gold)}

/* The score ladders are tall and narrow, so a caption centred above them
   collides with its neighbour. Theirs goes to the outside of each ladder. */
.spotBox.vert .spotTag{bottom:auto;top:50%;left:auto;right:100%;
  transform:translate(-11px,-50%)}
.spotBox.vert .spotTag:after{top:50%;left:100%;bottom:auto;transform:translateY(-50%);
  border-top-color:transparent;border-left-color:var(--gold)}
.spotBox.vert.rightSide .spotTag{right:auto;left:100%;transform:translate(11px,-50%)}
.spotBox.vert.rightSide .spotTag:after{left:auto;right:100%;
  border-left-color:transparent;border-right-color:var(--gold)}

/* The Rune Deck is a separate pile and should not read as another Main Deck. */
.bk.rd{background:linear-gradient(155deg,#4a3a6e,#241a3c);
  border-color:rgba(190,160,255,.34)}
.bk.set{background:linear-gradient(155deg,#6e5a2a,#3c2f14);
  border-color:rgba(242,204,123,.42)}

/* ================= playmat polish =================
   Closer to how the official client presents a board: a deeper, cleaner mat,
   corner brackets on each zone rather than flat outlines, and battlefields
   that read as inset panels with a lit centre. Nothing here changes what any
   element means or where it sits; it is the same board, better dressed. */

.mat{
  background:
    radial-gradient(ellipse at 50% 34%, rgba(64,126,204,.34) 0%, transparent 62%),
    radial-gradient(ellipse at 50% 100%, rgba(20,58,110,.55) 0%, transparent 55%),
    linear-gradient(180deg, #16385f 0%, #102a4c 44%, #0a1d38 100%);
  box-shadow:
    inset 0 0 0 1px rgba(150,200,255,.22),
    inset 0 1px 0 rgba(190,225,255,.16),
    inset 0 0 90px rgba(4,14,30,.6),
    0 18px 60px rgba(0,0,0,.55);
}
/* a faint centre line, the way a real mat is printed */
.matIn{position:relative}
.matIn:before{content:'';position:absolute;left:-18px;right:-18px;top:50%;height:1px;
  background:linear-gradient(90deg,transparent,rgba(160,205,255,.20) 18%,
    rgba(160,205,255,.20) 82%,transparent);pointer-events:none}

/* zones get corner brackets instead of a full box */
.tray{box-shadow:none;background:rgba(8,24,46,.30);border-radius:10px}
.tray:before,.tray:after,
.bf:before,.bf:after{content:'';position:absolute;width:14px;height:14px;
  pointer-events:none;opacity:.55}
.tray:before{left:5px;top:5px;border-left:2px solid rgba(160,205,255,.5);
  border-top:2px solid rgba(160,205,255,.5);border-radius:4px 0 0 0}
.tray:after{right:5px;bottom:5px;border-right:2px solid rgba(160,205,255,.5);
  border-bottom:2px solid rgba(160,205,255,.5);border-radius:0 0 4px 0}
/* the empty-state label must clear the brackets */
.tray.empty:before{content:attr(data-empty);position:absolute;inset:0;width:auto;height:auto;
  display:grid;place-items:center;border:0;opacity:1;
  color:rgba(190,220,255,.34);font-size:11px;letter-spacing:.05em;white-space:nowrap}
.tray.empty:after{opacity:0}

.bf{
  background:
    radial-gradient(ellipse at 50% 45%, rgba(88,150,225,.16) 0%, transparent 70%),
    rgba(7,22,44,.46);
  box-shadow:inset 0 0 0 1px rgba(160,205,255,.20), inset 0 0 40px rgba(3,12,26,.55);
  border-radius:12px;
}
.bf:before{left:7px;top:7px;border-left:2px solid rgba(160,205,255,.55);
  border-top:2px solid rgba(160,205,255,.55);border-radius:4px 0 0 0}
.bf:after{right:7px;bottom:7px;border-right:2px solid rgba(160,205,255,.55);
  border-bottom:2px solid rgba(160,205,255,.55);border-radius:0 0 4px 0}
.bf.contested{box-shadow:inset 0 0 0 2px rgba(255,129,137,.55),
  inset 0 0 46px rgba(120,20,30,.30)}

/* the two halves read as territory without shouting */
.half.foe{background:linear-gradient(180deg,rgba(255,129,137,.11),transparent)}
.half.you{background:linear-gradient(0deg,rgba(95,211,160,.11),transparent)}

/* cards sit on the mat rather than floating above it */
.c{box-shadow:0 3px 10px rgba(0,0,0,.5), 0 0 0 1px rgba(0,0,0,.35)}
.c.hot:hover{box-shadow:0 8px 22px rgba(0,0,0,.6), 0 0 0 2px var(--gold)}

/* deck and trash piles look like stacks */
.bk{position:relative}
.bk:after{content:'';position:absolute;inset:0;border-radius:inherit;pointer-events:none;
  box-shadow:inset 0 1px 0 rgba(255,255,255,.16), inset 0 -2px 0 rgba(0,0,0,.35)}

/* the score ladders, tidier */
.lad i{box-shadow:inset 0 0 0 1px rgba(160,205,255,.16)}
.lad i.on{box-shadow:inset 0 0 0 1px rgba(242,204,123,.5), 0 0 10px rgba(242,204,123,.35)}

/* ================= design pass two =================
   Card backs, motion, and depth. Nothing here changes geometry: no widths, no
   flex-basis, no aspect-ratio, because that is what broke the art twice. */

/* A face-down card was a flat blue rectangle. Give it a printed back. */
.c.back{
  background:
    radial-gradient(circle at 50% 42%, rgba(150,205,255,.20) 0%, transparent 46%),
    linear-gradient(160deg,#2a5f97 0%, #17395f 52%, #0d2340 100%);
}
.c.back:before{content:'';position:absolute;inset:9px;border-radius:4px;
  border:1px solid rgba(160,205,255,.28)}
/* the diamond in the middle, drawn rather than loaded */
.c.back:after{content:'';position:absolute;left:50%;top:50%;width:34%;height:24%;
  transform:translate(-50%,-50%) rotate(45deg);
  border:2px solid rgba(180,215,255,.42);border-radius:3px;
  box-shadow:0 0 14px rgba(120,180,255,.22)}

/* Cards lift rather than jump, and only the ones you can act on. */
.c{transition:transform .16s ease, box-shadow .16s ease, filter .16s ease}
.c.hot{cursor:pointer}
.c.hot:hover{transform:translateY(-6px) scale(1.02)}
.c.sel{transform:translateY(-6px)}

/* State changes should be noticed. A card arriving, or a battlefield changing
   hands, currently just appears. */
@keyframes cardIn{from{opacity:0;transform:translateY(9px) scale(.96)}
  to{opacity:1;transform:none}}
.tray .c,.half .c{animation:cardIn .2s ease-out}
.c.ex{animation:none}          /* rotation and the entry animation fight */

@keyframes zonePulse{0%{box-shadow:inset 0 0 0 1px rgba(160,205,255,.20), inset 0 0 40px rgba(3,12,26,.55)}
  45%{box-shadow:inset 0 0 0 2px rgba(242,204,123,.75), inset 0 0 46px rgba(90,70,20,.35)}
  100%{box-shadow:inset 0 0 0 1px rgba(160,205,255,.20), inset 0 0 40px rgba(3,12,26,.55)}}
.bf.justScored{animation:zonePulse .7s ease-out}

/* The score ladder should read at a glance: a filled column, not nine chips. */
.lad i{transition:background .25s, box-shadow .25s}
.lad i.on{background:linear-gradient(90deg,var(--gold),#e0b264)}
.lad.foe i.on{background:linear-gradient(90deg,var(--red),#d9636b)}

/* Depth under the whole board, so it sits on the page rather than in it. */
.wrap{box-shadow:0 26px 80px rgba(0,0,0,.45), 0 2px 0 rgba(255,255,255,.04) inset}

/* The log reads as a feed rather than a wall. */
.logList div{padding:3px 0;border-bottom:1px solid rgba(255,255,255,.05)}
.logList div:last-child{border-bottom:0}
.logList div.you{color:#c9e6d8}
.logList div.foe{color:#f2c9cc}

/* ---------- phase flash ----------
   One or two words in the centre of the board, ~900ms, then gone. Long
   enough to read at roughly 500ms a word, short enough not to be a wall. */
.flash{position:absolute;inset:0;display:grid;place-items:center;z-index:12;
  pointer-events:none;animation:flashIn .22s ease-out}
.flash b{display:block;font-size:34px;font-weight:900;letter-spacing:.16em;
  text-transform:uppercase;color:#fff;text-align:center;
  text-shadow:0 2px 0 rgba(0,0,0,.55), 0 0 34px rgba(120,190,255,.75)}
.flash i{display:block;margin-top:8px;font-style:normal;font-size:14px;
  font-weight:700;letter-spacing:.07em;color:rgba(214,232,255,.92);
  text-align:center;text-shadow:0 1px 3px rgba(0,0,0,.7)}
.flash.out{animation:flashOut .26s ease-in forwards}
@keyframes flashIn{from{opacity:0;transform:scale(1.14)}to{opacity:1;transform:none}}
@keyframes flashOut{to{opacity:0;transform:scale(.96)}}

/* the board dims very slightly behind a flash so the word reads */
.flash:before{content:"";position:absolute;inset:0;
  background:radial-gradient(ellipse at 50% 50%, rgba(4,14,30,.55) 0%, transparent 62%)}

/* "your move" cue: the one message that must NOT time out, because it is
   telling the player to do something. */
.coach.yours{box-shadow:inset 0 0 0 2px var(--gold);background:rgba(242,204,123,.12)}
.coach.yours .say:before{content:"YOUR MOVE";display:block;font-size:10.5px;
  font-weight:900;letter-spacing:.16em;color:var(--gold);margin-bottom:6px}

/* ---------- optional account ----------
   Signing in only carries progress between devices, so this is a quiet control
   in the crumb bar, never a gate and never a modal over the board. */
/* Layout applies to BOTH slots. Only margin-left:auto is specific to the crumb
   bar, and only the colour needs the extra specificity, to beat home.css's
   ".crumb span" rule. Scoping the whole thing to .crumb left the front-page
   slot without position:relative, so its panel escaped to the page corner and
   the button looked dead. */
.acct { display: flex; align-items: center; gap: 8px; position: relative; }
.crumb .acct { margin-left: auto; }
.acctOn { font-size: 12px; color: #6fcf97; font-weight: 700; white-space: nowrap; }
.crumb .acctOn { font-size: 12px; color: #6fcf97; font-weight: 700; white-space: nowrap; }
.acctBox {
  position: absolute; right: 0; top: calc(100% + 8px); z-index: 40; width: 290px;
  background: #101c2e; border: 1px solid rgba(120,160,220,.3); border-radius: 12px;
  padding: 14px; box-shadow: 0 18px 44px rgba(0,0,0,.55);
  display: flex; flex-direction: column; gap: 8px;
}
.acctBox b { font-size: 14px; color: #eaf2ff; }
.acctBox p { margin: 0; font-size: 12px; line-height: 1.55; color: #a9bcd4; }
.acctBox input {
  background: #16243a; border: 1px solid rgba(120,160,220,.3); border-radius: 8px;
  padding: 8px 10px; color: #eaf2ff; font: inherit; font-size: 13px; width: 100%;
}
.acctOr { text-align: center; font-size: 11px; color: #7f93ac; letter-spacing: .08em;
  text-transform: uppercase; }
.acctErr { color: #ff9d8a !important; font-size: 12px; }

/* ---------- mobile notice ----------
   Shown once when a lesson is opened on a small or touch screen. The board is
   usable there, it is simply not what it was drawn for, so this says so and
   gets out of the way. */
.mobNote {
  position: fixed; left: 12px; right: 12px; bottom: 12px; z-index: 90;
  background: #101c2e; border: 1px solid var(--gold, #f2cc7b); border-radius: 14px;
  padding: 15px 16px; box-shadow: 0 20px 50px rgba(0,0,0,.6);
  animation: mobIn .22s ease-out;
}
.mobNote b { display: block; font-size: 14.5px; color: var(--gold, #f2cc7b); margin-bottom: 6px; }
.mobNote p { margin: 0 0 12px; font-size: 12.5px; line-height: 1.6; color: #b9c9de; }
.mobNoteBtns { display: flex; gap: 8px; flex-wrap: wrap; }
@keyframes mobIn { from { opacity: 0; transform: translateY(10px) } to { opacity: 1; transform: none } }
@media (min-width: 821px) and (pointer: fine) { .mobNote { max-width: 420px; right: auto; } }

/* The front-page copy of the account control sits under the hero buttons, so
   it reads as an offer rather than a requirement. */
.acctHome { margin: 14px 0 0 !important; justify-content: flex-start; }
.acctHome .acctBox { left: 0; right: auto; }
