/* the tokens (colours, radii, line width, shadow) live in tokens.css, linked before this file */

* { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body {
  margin: 0;
  background-color: var(--bg);
  background-image: radial-gradient(rgba(61, 51, 64, .07) 1.2px, transparent 1.4px);
  background-size: 22px 22px;
  color: var(--ink);
  font-family: var(--font);
  font-size: 16px;
  line-height: 1.4;
}
button, input { font: inherit; color: inherit; }
button { cursor: pointer; touch-action: manipulation; -webkit-tap-highlight-color: transparent; }
:focus-visible { outline: 3px solid #5aa9e6; outline-offset: 2px; }
[hidden] { display: none !important; }

/* --col-w is how wide the game column may get: 460px, and wider on a tall screen, as far as a room that fills the
   height asks for (800px at most, on a TV or a tall monitor). --side-w is the most the cards beside it take. The page
   grows past 1140px only to fit those two columns (1336px at most) */
.wrap {
  --col-w: clamp(460px, calc((100vh - 340px) * .9), 800px); --side-w: 460px;
  max-width: max(1140px, calc(var(--col-w) + var(--side-w) + 76px)); margin: 0 auto; padding: 16px 24px 32px;
}

.home { font-weight: 600; color: var(--ink); letter-spacing: -.01em; }
.home span { color: #e2674f; }
/* the faces of the boogers that share this browser: a row of its own, and only when there is more than one */
.roster { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin-bottom: 8px; }
.face {
  display: inline-flex; align-items: center; gap: 5px; min-height: 34px; padding: 1px 11px 1px 4px;
  background: var(--card); color: var(--ink);
  border: 2px solid var(--ink); border-radius: var(--r-pill);
  font-size: 14px; font-weight: 500;
}
.face canvas { width: 28px; height: 28px; }
.face[aria-pressed="true"] { background: var(--butter); box-shadow: var(--shadow-hard); cursor: default; }
.face.add { justify-content: center; min-width: 34px; padding: 1px 11px; color: var(--soft); border-style: dashed; }
.face:not([aria-pressed="true"]):hover { background: var(--butter); }
@media (pointer: coarse) { .face { min-height: 44px; } .face.add { min-width: 44px; } }
/* a phone has room for the faces, and one name: the booger whose turn it is */
@media (max-width: 560px) { .face:not(.add):not([aria-pressed="true"]) { padding: 1px 4px; } .face:not([aria-pressed="true"]) span { display: none; } }
.toy { color: var(--soft); font-size: 14px; letter-spacing: .08em; text-transform: uppercase; }

.banner {
  display: flex; flex-wrap: wrap; align-items: center; gap: 10px;
  margin-bottom: 14px; padding: 12px 16px;
  background: var(--butter); border: 2.5px solid var(--ink); border-radius: 18px;
}
.banner p { margin: 0; flex: 1 1 240px; }

main { display: grid; grid-template-columns: 460px minmax(0, 1fr); gap: 24px; align-items: start; justify-content: center; }
/* where the sticky tabs sit on phones and tablets, and what they take: the bars that stick under them start below */
.stage-col { --tabs-top: max(8px, env(safe-area-inset-top)); --tabs-h: 56px; }

/* ---------- left column ---------- */
.id-row { display: flex; align-items: center; gap: 8px; margin-bottom: 8px; }
.id-row .who { flex: 1; min-width: 0; display: grid; gap: 1px; }
.sub-row { display: flex; align-items: center; gap: 10px; min-width: 0; }
#name {
  width: 9.5ch; min-width: 4ch; max-width: 100%;
  padding: 0 4px; margin-left: -4px;
  font-weight: 600; font-size: 26px; line-height: 1.1;
  background: transparent; border: 0; border-bottom: 2.5px dashed transparent; border-radius: 4px;
  field-sizing: content;
}
/* the pencil beside the name: quiet, with no outline of its own, and no taller than the name (the margins give its
   touch size back to the row) */
.name-row { display: flex; align-items: center; gap: 2px; min-width: 0; }
.pencil { flex: none; display: grid; place-items: center; width: 32px; height: 32px; margin: -4px 0; padding: 0; background: transparent; border: 0; border-radius: var(--r-chip); }
.pencil svg { width: 20px; height: 20px; fill: none; stroke: var(--ink); stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.pencil .body { fill: var(--butter); }
@media (hover: hover) { .pencil:hover { background: var(--line); } }
@media (pointer: coarse) { .pencil { width: 44px; height: 44px; margin: -10px -6px -10px -4px; } }
#name:hover, #name:focus { border-bottom-color: var(--line); outline: none; }
#name:focus { border-bottom-color: var(--ink); }
@supports (field-sizing: content) { #name { width: auto; } }
#name:disabled { opacity: 1; -webkit-text-fill-color: var(--ink); }
#sub { color: var(--soft); font-size: 14px; white-space: nowrap; }

.chip, .btn {
  padding: 6px 14px;
  background: var(--card);
  border: var(--line-w) solid var(--ink); border-radius: var(--r-pill);
  box-shadow: var(--shadow-hard);
  font-size: 14px; font-weight: 500;
  transition: transform .06s, box-shadow .06s;
  text-decoration: none; color: var(--ink);
}
.chip:active, .btn:active { transform: translateY(2px); box-shadow: 0 1px 0 var(--ink); }
.chip[aria-expanded="true"] { background: var(--butter); }
.chip.warn { background: var(--coral); }
.chip:disabled { cursor: default; transform: translateY(2px); box-shadow: 0 1px 0 var(--ink); }
.btn { background: var(--butter); }
.btn.plain { background: var(--card); }
/* icon-only chips: sound and menu */
/* the gem counter: a chip to look at, not to press */
.coin-chip { display: inline-flex; align-items: center; gap: 5px; padding: 2px 10px 2px 6px; box-shadow: none; cursor: default; font-size: 14px; font-variant-numeric: tabular-nums; }
.coin-chip b { font-weight: 600; }
.coin-chip:active { transform: none; box-shadow: none; }
.chip.icon { flex: none; display: grid; place-items: center; width: 44px; height: 44px; padding: 0; }
.chip.icon svg { width: 24px; height: 24px; fill: none; stroke: var(--ink); stroke-width: 2.200; stroke-linecap: round; stroke-linejoin: round; }
.chip.icon .body { fill: var(--butter); }
#b-sound[aria-pressed="true"] .off, #b-sound[aria-pressed="false"] .on { display: none; }
#b-sound[aria-pressed="false"] .body { fill: #efe3cf; }

/* the menu: a panel of groups over the page (the owner's mockup, docs/mockups/menu.html). It opens right under the name
   row, where it sits in the markup (its top is left auto), and covers what is below without moving any of it, so it is
   never dimmed behind. On a phone it is the column's width; from 600px the groups become cards side by side */
#menu {
  position: absolute; z-index: 20; overflow: auto; overscroll-behavior: contain;
  padding: 12px 12px 14px; background: var(--card);
  border: var(--line-w) solid var(--ink); border-radius: var(--r-card); box-shadow: 0 4px 0 var(--ink);
  font-size: 14px;
}
@media (max-width: 599px) { .stage-col { position: relative; } #menu { left: 0; right: 0; } }
/* !important: the wide layouts hold everything in the column above the stage to a width (main's rules below); the panel is not */
@media (min-width: 600px) {
  .wrap { position: relative; }
  #menu { left: 50%; width: min(960px, calc(100vw - 24px)); max-width: none !important; margin: 0 !important; transform: translateX(-50%); padding: 14px 16px 16px; }
}
.m-top { display: flex; align-items: center; gap: 8px; margin-bottom: 6px; }
.m-top h2 { flex: 1; margin: 0; font-size: 18px; font-weight: 600; }
.m-top h2:focus { outline: none; }
.m-top h2:focus-visible { outline: 3px solid #5aa9e6; }
.m-grp { margin-top: 12px; }
.m-grp h3 { margin: 0 0 6px 2px; font-size: 14px; font-weight: 600; color: var(--soft); }
.m-tiles { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
.m-tile {
  display: flex; align-items: center; gap: 8px; min-height: 44px; padding: 6px 12px 6px 9px; text-align: left;
  background: #fff; color: var(--ink); text-decoration: none;
  border: 2px solid var(--ink); border-radius: var(--r-pill); font-size: 14px; line-height: 1.25;
}
.m-tile.wide { grid-column: 1 / -1; }
.m-tile .ic { width: 24px; height: 24px; }
.m-tile.warn { background: var(--coral); }
#m-import-go { justify-content: center; text-align: center; }
@media (hover: hover) { .m-tile:not(.warn):hover { background: var(--butter); } }
/* the account owner's row (S62): a link to the account page, its cloud filled by state. A rule cannot reach inside the
   <use> copy of the symbol, but a custom property inherits into it, so the symbol's path reads --acct-fill */
.m-row { display: flex; align-items: center; gap: 10px; margin-bottom: 8px; padding: 8px 10px; background: #fff; color: var(--ink); text-decoration: none; border: 2px solid var(--ink); border-radius: var(--r-tile); }
.m-row .ic { flex: none; width: 24px; height: 24px; }
.m-txt { flex: 1; min-width: 0; }
.m-row b { display: block; font-weight: 600; font-size: 14px; }
.m-row small { display: block; color: var(--soft); font-size: 13px; }
#m-acct[data-state="off"] { --acct-fill: var(--track); }
#m-acct[data-state="safe"] { --acct-fill: var(--mint); }
#m-acct[data-state="waiting"] { --acct-fill: var(--butter); }
@media (hover: hover) { .m-row:hover { background: var(--butter); } }
.m-set { display: grid; grid-template-columns: 76px 1fr; align-items: center; gap: 6px 10px; margin-top: 4px; }
.m-set > span { font-size: 14px; font-weight: 500; }
.m-set small { grid-column: 2; color: var(--soft); font-size: 13px; }
#menu .seg { gap: 6px; }
#menu .seg button { min-height: 36px; padding: 4px; font-size: 14px; }
/* the booger's card: on a phone only its Decorate button shows, as the approved mockup has it, and below bond level 5
   (no button yet) nothing of it */
.m-hero { margin-top: 0; }
.m-hero .m-me, .m-hero .m-facts { display: none; }
@media (max-width: 599px) { .m-hero.m-bare { display: none; } }
.m-tile.big { width: 100%; min-height: 52px; background: var(--butter); border-width: var(--line-w); box-shadow: var(--shadow-hard); font-size: 15px; font-weight: 600; }
.danger { margin-top: 14px; padding-top: 10px; border-top: 2px dashed var(--coral); }
.danger b { font-size: 14px; font-weight: 600; }
.danger p { margin: 2px 0 8px; font-size: 13.5px; color: var(--soft); }
/* the file picker behind "Open a save file": out of sight, but still clickable from script everywhere */
.vh { position: absolute; width: 1px; height: 1px; opacity: 0; overflow: hidden; clip-path: inset(50%); pointer-events: none; }
@media (min-width: 600px) {
  .m-top { margin-bottom: 10px; }
  .m-body { column-count: 2; column-gap: 14px; padding-bottom: 2px; }
  .m-grp { break-inside: avoid; margin: 0 0 14px; padding: 10px 12px 12px; background: #fff8ec; border: 2px solid var(--ink); border-radius: var(--r-tile); }
  .m-grp h3 { margin: 0 0 8px; font-size: 15px; color: var(--ink); }
  .m-tiles { grid-template-columns: 1fr; gap: 6px; }
  .m-tile { min-height: 40px; padding: 5px 12px 5px 8px; border-radius: var(--r-chip); }
  .m-row { margin-bottom: 6px; border-radius: var(--r-chip); }
  .m-set { grid-template-columns: 1fr; gap: 4px; margin-top: 0; }
  .m-set > span { margin-top: 4px; font-size: 13.5px; color: var(--soft); }
  .m-set small { grid-column: 1; }
  #menu .seg button { min-height: 32px; }
  /* the booger's card: its face, its facts and its own Gems, and what it holds to do across the card */
  .m-hero { display: grid; grid-template-columns: 84px 1fr; gap: 4px 12px; align-items: center; background: var(--card); }
  .m-hero .m-me { display: block; grid-row: 1; width: 84px; height: 84px; border: 2px solid var(--ink); border-radius: var(--r-tile); }
  .m-hero .m-facts { display: block; min-width: 0; }
  .m-facts b { display: block; font-size: 20px; font-weight: 600; line-height: 1.1; overflow-wrap: anywhere; }
  .m-facts span { display: block; color: var(--soft); font-size: 13.5px; }
  .m-facts .m-gems { display: inline-flex; align-items: center; gap: 4px; margin-top: 6px; padding: 1px 9px 1px 5px; border: 2px solid var(--ink); border-radius: var(--r-pill); background: #fff; color: var(--ink); font-weight: 600; font-variant-numeric: tabular-nums; }
  .m-hero .m-tile.big { grid-column: 1 / -1; justify-content: center; margin-top: 8px; border-radius: var(--r-pill); }
  .danger { display: flex; align-items: center; flex-wrap: wrap; gap: 10px 14px; margin-top: 10px; padding-top: 12px; }
  .danger p { flex: 1 1 260px; margin: 0; }
  .danger b { flex-basis: 100%; }
  .danger .m-tiles { display: flex; flex-wrap: wrap; gap: 8px; }
  .danger .m-tile { border-radius: var(--r-pill); }
}
/* a tablet: the booger's card is a band across the top, what it holds to do at its end, so the columns below come out even */
@media (min-width: 600px) and (max-width: 999px) {
  .m-hero { column-span: all; grid-template-columns: 84px 1fr auto; }
  .m-hero .m-tile.big { grid-column: 3; grid-row: 1; width: auto; margin-top: 0; padding: 6px 18px; }
}
@media (min-width: 1000px) { .m-body { column-count: 3; } }
@media (pointer: coarse) { .m-row { min-height: 44px; } .m-tile { min-height: 44px; } .m-tile.big { min-height: 52px; } #menu .seg button { min-height: 44px; } }
/* (the wall paint's swatches, .walls, left the menu for the walls' shelf in decorate mode: S51, 2026-10-18) */

.meters { display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px; margin-bottom: 8px; }
.meter {
  --c: var(--mint);
  display: flex; align-items: center; gap: 6px;
  padding: 4px 8px 4px 6px;
  background: var(--card); border: 2.5px solid var(--ink); border-radius: 99px;
}
.meter[data-k="tummy"] { --c: #f58aa0; }
.meter[data-k="energy"] { --c: #ffd166; }
.meter[data-k="fun"] { --c: #8ecbf2; }
.meter[data-k="clean"] { --c: #8fdcc4; }
.meter svg { flex: none; width: 19px; height: 19px; fill: var(--c); stroke: var(--ink); stroke-width: 1.800; stroke-linejoin: round; }
/* the bar carries the meter's name, as the pep and xp bars carry their numbers: no extra row, so the room keeps its height */
.bar { position: relative; flex: 1; min-width: 0; height: 16px; background: #efe3cf; border-radius: var(--r-pill); overflow: hidden; }
.bar i { display: block; height: 100%; width: 50%; background: var(--c, var(--mint)); border-radius: var(--r-pill); transition: width .5s; }
.bar b { position: absolute; inset: 0; display: grid; place-items: center; font-size: 12px; font-weight: 600; line-height: 1; white-space: nowrap; }
.meter { cursor: pointer; -webkit-tap-highlight-color: transparent; }
.meter.low { animation: low 1.1s ease-in-out infinite; }
.meter.low .bar i { background: var(--coral); }
@keyframes low { 50% { background: #ffe1d9; } }

/* bond, in the one place Home shows it: a strip between the meters and the room. One row, so it costs the room
   little: the bar holds what comes next, as the xp bar does on the hub */
.bond-strip { display: flex; align-items: center; gap: 8px; margin-bottom: 8px; padding: 4px 12px 4px 10px; background: var(--card); border: var(--line-w) solid var(--ink); border-radius: var(--r-pill); }
body:not([data-mode="home"]) .bond-strip { display: none; }
.bond-title { font-size: 13px; font-weight: 600; }
.bond-lvl { color: #d9503a; font-size: 13.5px; font-weight: 600; white-space: nowrap; font-variant-numeric: tabular-nums; }
.bond-lvl:empty { display: none; }
.bond-bar-track { position: relative; flex: 1; min-width: 0; height: 18px; background: #efe3cf; border: 1.5px solid var(--ink); border-radius: var(--r-pill); overflow: hidden; }
.bond-bar-track i { display: block; height: 100%; width: 0; background: var(--coral); transition: width .5s ease; }
.bond-bar-track em { position: absolute; inset: 0; padding: 0 8px; overflow: hidden; font-style: normal; font-size: 12px; font-weight: 500; line-height: 15px; text-align: center; white-space: nowrap; text-overflow: ellipsis; }

.stage {
  position: relative;
  border: 3px solid var(--ink); border-radius: 30px;
  box-shadow: 0 7px 0 rgba(61, 51, 64, .16);
  overflow: hidden;
  background: #f6ead6;
  aspect-ratio: 360 / 430;
}
.stage[data-mode="bouts"] { aspect-ratio: 360 / 250; }
/* Home fits the screen: the room takes the height the header, the status line and the dock leave (--chrome, measured in
   app/room-draw.js), never more than its full 360:430 (--stage-max). A shorter room is a shorter wall: the canvas keeps its floor
   and stays anchored to the bottom */
.stage[data-mode="home"] {
  --vh: 100vh;
  --h: clamp(min(280px, var(--stage-max, 561px)), calc(var(--vh) - var(--chrome, 340px)), var(--stage-max, 561px));
  aspect-ratio: auto; height: var(--h);
  /* the wall only shrinks so far (348 of the room's 430 units); past that the room gets narrower instead. Phones and
     tablets only: on a big screen the room's sides show more instead (the min-width: 821px rules below) */
  max-width: calc((var(--h) - 6px) * 360 / 348 + 6px); margin-inline: auto;
}
@supports (height: 100svh) { .stage[data-mode="home"] { --vh: 100svh; } }
.stage[data-mode="home"] #cv { position: absolute; left: 0; bottom: 0; }
#cv { display: block; width: 100%; height: 100%; touch-action: none; user-select: none; -webkit-user-select: none; cursor: pointer; }
#cv.washing { cursor: none; }
/* what the room otherwise needs a pointer for, as buttons in its corner: cleaning up (while there is a mess) and a
   cuddle (shown when the keyboard reaches it) */
.room-acts { position: absolute; left: 10px; bottom: 10px; display: flex; gap: 8px; }
.room-acts .chip { box-shadow: 0 2px 0 var(--ink); }
.seen-on-focus:not(:focus-visible) { position: absolute; width: 1px; height: 1px; padding: 0; overflow: hidden; clip-path: inset(50%); border: 0; }
/* Wash is a mode, and on a touch screen there is no sponge cursor to say so: while it is on, the way out sits in the
   room's top corner */
.wash-exit { position: absolute; top: 12px; right: 12px; z-index: 5; background: var(--mint); font-weight: 600; }
@media (pointer: coarse) { .room-acts .chip, .wash-exit { min-height: 44px; } }

/* the shelf: snacks or toys, in one row directly above the care buttons, tinted like the button that opened it and
   notched towards it. More tiles than fit scroll sideways. It takes no room of its own: it slides up over the status
   strip and the front of the room's floor, from a zero-height anchor above the buttons, so nothing under or around it
   moves. The strip it covers is said again in its first line (.shelf-say) */
.shelf-anchor { position: relative; }
.tray {
  --shelf: var(--card); --at: 50%;
  position: absolute; left: 0; right: 0; bottom: 0; z-index: 15;
  background: var(--shelf); border: 2.5px solid var(--ink); border-radius: 20px;
  box-shadow: 0 5px 0 rgba(61, 51, 64, .16);
  animation: drawerSlideUp .18s cubic-bezier(.16, 1, .3, 1);
}
@keyframes drawerSlideUp { from { opacity: 0; transform: translateY(12px); } to { opacity: 1; transform: none; } }
/* with nothing to say the line is gone and the tiles sit in the middle of the shelf. When a hint arrives the shelf
   grows upwards to hold it: the tiles are anchored from below, so they stay under the finger */
.shelf-say { margin: 0; padding: 5px 44px 0 14px; color: var(--ink); font-size: 13.5px; line-height: 1.3; text-align: center; }
.shelf-say:empty { display: none; }
.shelf-say:empty + .shelf-row { padding-top: 8px; }
.tray[data-kind="feed"] { --shelf: #ffe6ea; --at: calc(12.5% - 4px); }
.tray[data-kind="play"] { --shelf: #e2f1fc; --at: calc(37.5% - 1px); }
.tray::after {
  content: ''; position: absolute; left: var(--at); bottom: -8.5px; width: 13px; height: 13px; margin-left: -6.5px;
  background: var(--shelf); border: solid var(--ink); border-width: 0 2.5px 2.5px 0; transform: rotate(45deg);
}
.shelf-row { display: flex; gap: 8px; padding: 4px 10px 8px; overflow-x: auto; scrollbar-width: thin; border-radius: 18px; }
.tray button {
  position: relative; flex: none;
  width: 64px; height: 64px; padding: 3px 2px 2px;
  display: grid; justify-items: center; align-content: center; gap: 0;
  background: #fff; border: 2px solid var(--ink); border-radius: 16px;
  font-size: 12px; line-height: 1.15; white-space: nowrap;
  transition: transform .08s;
}
@media (hover: hover) { .tray button:hover { transform: translateY(-2px); background: #fff7e3; } }
.tray button canvas { width: 36px; height: 36px; margin-top: 2px; }
/* a snack can be dragged up into the room, so a vertical drag is the tile's own; sideways still scrolls the shelf */
.tray button { touch-action: pan-x; user-select: none; -webkit-user-select: none; }
.tile .mk { position: absolute; top: 2px; right: 5px; font-size: 12px; font-weight: 600; line-height: 1.1; }
.tile .mk.fav { color: #d9503a; }
.tile .mk.yuck { color: var(--soft); }
.tile .mk.new { top: 5px; width: 8px; height: 8px; background: #5aa9e6; border: 1.5px solid var(--ink); border-radius: 50%; }
/* the one its thought bubble asked for */
.tray .tile.want { background: var(--butter); box-shadow: 0 0 0 3px var(--butter), 0 0 0 5px var(--ink); animation: want .7s ease-in-out 3; }
@keyframes want { 50% { transform: translateY(-4px); } }
.tray .tile.locked .ic { font-size: 20px; margin-bottom: 1px; }
/* the decorate shelf (S51): wider tiles, for a name on two lines and a price; the action row under them. For a floor
   spot it docks at the top of the room, over the wall, under the room's Done chip (--dc-top, set by dcPlaceTray) */
.tray[data-kind="decor"] { --shelf: var(--card); }
.tray[data-kind="decor"]::after { display: none; }
.tray.dc-top { top: var(--dc-top, 0px); bottom: auto; }
.tray.dc-top .shelf-say { display: none; }
.tray.dc-top .shelf-row { padding-top: 8px; }
.tray .dc-tile { width: 76px; height: auto; min-height: 92px; padding: 4px 3px 5px; align-content: start; gap: 1px; white-space: normal; }
.tray .dc-tile canvas { width: 40px; height: 40px; margin-top: 0; }
.dc-tile .tn { display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; min-height: 2.3em; text-align: center; }
.dc-price { display: inline-flex; align-items: center; gap: 2px; font-weight: 600; font-variant-numeric: tabular-nums; }
.tray .dc-tile .dc-price .ic { font-size: 13px; margin: 0; }
/* a locked one shows its picture and what opens it ("Beat Duchess Dragonfluff") in its name's place, so it is no taller
   than the rest (its name is in its label), wrapped inside the tile with the padlock leading */
.dc-tile.locked .tn { display: none; }
.dc-tile.locked .dc-price { display: block; max-width: 100%; font-weight: 500; line-height: 1.15; text-align: center; overflow-wrap: anywhere; }
.tray .dc-tile.locked .dc-price .ic { display: inline-block; margin-right: 2px; vertical-align: -2px; }
.dc-act { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 8px; padding: 0 10px 10px; }
.dc-what { flex: 1 1 120px; min-width: 0; margin: 0; font-size: 14px; font-weight: 600; }
.tray .dc-act .btn { position: static; display: inline-flex; align-items: center; gap: 5px; width: auto; height: auto; padding: 6px 14px; border: var(--line-w) solid var(--ink); border-radius: var(--r-pill); font-size: 14px; white-space: nowrap; }
.tray .dc-act .btn { background: var(--butter); }
.tray .dc-act .btn.plain { background: var(--card); }
.tray .dc-act .btn[aria-disabled="true"] { background: var(--card); color: var(--soft); border-style: dashed; box-shadow: none; }
@media (pointer: coarse) { .tray .dc-act .btn { min-height: 44px; } }
@media (hover: hover) { .tray .dc-act .btn:hover { transform: none; background: var(--butter); } .tray .dc-act .btn.plain:hover, .tray .dc-act .btn[aria-disabled="true"]:hover { background: var(--card); } }
/* a phone: the item's name on a line of its own, the two buttons under it */
@media (max-width: 480px) { .dc-what { flex-basis: calc(100% - 60px); } }
/* the shelf's own close: it puts the shelf away and leaves decorating on, so a ring the shelf lay over can be tapped
   (the owner, 2026-10-18). At the row's end; on a phone beside the item's name, the buttons on the line below */
.tray .dc-shut { order: 3; flex: none; display: grid; place-items: center; width: 36px; height: 36px; margin-left: auto; padding: 0; background: var(--card); border: 2px solid var(--ink); border-radius: 50%; }
.tray .dc-shut .ic { width: 16px; height: 16px; }
.tray .dc-shut::before { content: ''; position: absolute; inset: -4px; }
@media (hover: hover) { .tray .dc-shut:hover { transform: none; background: var(--butter); } }
.tray .dc-shut:active { transform: translateY(1px); }
@media (pointer: coarse) { .tray .dc-shut { width: 44px; height: 44px; } }
@media (max-width: 480px) { .tray .dc-shut { order: 0; } }
/* the room's spots for the keyboard: out of sight (the ring of the focused one shows where it is), but focusable */
.dc-spots { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }

/* how many snacks lie on the floor, of the three it takes */
.pips { position: absolute; top: -9px; right: 18px; display: flex; gap: 3px; padding: 2px 6px; background: #fff; border: 2px solid var(--ink); border-radius: var(--r-pill); }
.pips i { width: 7px; height: 7px; background: #efe3cf; border: 1.5px solid var(--ink); border-radius: 50%; }
.pips i.on { background: #f0708b; }
/* a snack on its way from the shelf to the room, under the pointer */
.ghost { position: fixed; z-index: 20; width: 48px; height: 48px; margin: 0; pointer-events: none; filter: drop-shadow(0 4px 0 rgba(61, 51, 64, .22)); }
.tray button[aria-pressed="true"] { background: var(--butter); }

.tools { display: grid; grid-template-columns: repeat(4, 1fr); gap: 10px; margin-top: 12px; margin-bottom: 5px; }
.tools button {
  display: grid; justify-items: center; gap: 2px;
  padding: 9px 4px 7px;
  background: var(--tc, var(--card));
  border: 2.5px solid var(--ink); border-radius: 22px;
  box-shadow: 0 5px 0 var(--ink);
  font-weight: 500; font-size: 15px;
  transition: transform .06s, box-shadow .06s;
}
.tools button:active { transform: translateY(4px); box-shadow: 0 1px 0 var(--ink); }
#t-feed { --tc: #ffd0d8; }
#t-play { --tc: var(--sky); }
#t-wash { --tc: var(--mint); }
#t-light { --tc: var(--butter); }
#t-light[aria-pressed="false"] { --tc: var(--lilac); }
.tools button[aria-expanded="true"], #t-wash[aria-pressed="true"] { transform: translateY(3px); box-shadow: 0 2px 0 var(--ink); filter: saturate(1.3) brightness(.96); }
/* Wash is a mode, so while it is on its button wears a ring as well as sitting pressed */
#t-wash[aria-pressed="true"] { box-shadow: 0 2px 0 var(--ink), 0 0 0 3px var(--butter), 0 0 0 5.5px var(--ink); }
.tools svg { width: 30px; height: 30px; fill: #fff; stroke: var(--ink); stroke-width: 2.200; stroke-linejoin: round; stroke-linecap: round; }
.tools svg .cut { fill: none; }
.tools svg .leaf { fill: #8fd16f; }
#t-feed svg circle { fill: #f58aa0; }
#t-play svg circle { fill: var(--coral); }
#t-light svg path:first-child { fill: #fff3b8; }
#t-light[aria-pressed="false"] svg path:first-child { fill: #b9add6; }
.tools button.need { animation: need 1s ease-in-out infinite; }
@keyframes need { 50% { transform: translateY(-4px) rotate(-2deg); } }

/* the one status line: directly under the stage in every mode, and the bout caption while fighting */
.status { margin: 10px 4px 0; min-height: calc(2 * 1.3em + 4px); padding: 2px 6px; text-align: center; color: var(--soft); font-size: 15px; line-height: 1.3; }
.bout .status { color: var(--ink); font-weight: 500; }
/* a notice: the same line when it is telling the player something is in the way. A card that can't be missed, that
   stays on screen while the page scrolls, and that may carry the one button that fixes it */
.status.warn {
  position: sticky; top: 8px; bottom: 8px; z-index: 6;
  display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 6px 10px;
  margin-top: 8px; padding: 9px 14px;
  background: var(--butter); color: var(--ink); font-weight: 500; font-size: 16px;
  border: var(--line-w) solid var(--ink); border-radius: var(--r-tile); box-shadow: var(--shadow-hard);
}
@media (max-width: 899px) { .status.warn { top: calc(var(--tabs-top) + var(--tabs-h)); } }
.status.near { position: static; margin: 10px 0; }
.status.warn::before {
  content: '!'; flex: none; display: grid; place-items: center; width: 24px; height: 24px;
  background: var(--coral); border: 2px solid var(--ink); border-radius: 50%; font-weight: 600; font-size: 15px; line-height: 1;
}
.status.warn span { flex: 1 1 0; min-width: 9em; max-width: max-content; text-align: left; }
.status.warn .btn { background: #fff; font-weight: 600; }
.status.warn.pop { animation: notice .45s ease-out; }
@keyframes notice { 0% { transform: scale(.94); } 45% { transform: scale(1.04) rotate(-.6deg); } 100% { transform: none; } }
@media (pointer: coarse) { .status.warn .btn { min-height: 44px; } }
/* at Home the line always keeps two lines of room, so the shelf and the care buttons under it never move when a hint
   wraps or a short one replaces a long one. A one-line hint sits in the middle of it */
body[data-mode="home"] .status { margin-top: 4px; min-height: calc(2 * 1.3em); padding-block: 0; }
body[data-mode="home"] .status:not(.warn) { display: flex; align-items: center; justify-content: center; }

/* ---------- side column ---------- */
.side { display: grid; gap: 14px; }
.card { padding: 14px 16px; background: var(--card); border: var(--line-w) solid var(--ink); border-radius: var(--r-card); }
.card h2 { margin: 0 0 8px; font-size: 17px; font-weight: 600; display: flex; justify-content: space-between; }
.card h2 span { color: var(--soft); font-weight: 500; }
.small { margin: 0; font-size: 14.5px; color: var(--soft); }
.small b { color: var(--ink); font-weight: 500; }
.bond-bar { height: 14px; background: #efe3cf; border: 2px solid var(--ink); border-radius: 99px; overflow: hidden; margin-bottom: 8px; }
.bond-bar i { display: block; height: 100%; width: 0; background: var(--coral); transition: width .6s; }
.diary ol { list-style: none; margin: 0; padding: 0; max-height: 330px; overflow: auto; display: grid; gap: 9px; }
.diary li { font-size: 14.5px; line-height: 1.35; }
.diary time { display: block; font-size: 12px; color: var(--soft); letter-spacing: .04em; text-transform: uppercase; }
.diary li.new { animation: newnote .9s ease-out; }
.diary .chip { margin-top: 10px; }
@media (pointer: coarse) { .diary .chip { min-height: 44px; } }
@keyframes newnote { from { background: var(--butter); } to { background: transparent; } }

footer { margin-top: 26px; text-align: center; color: var(--soft); font-size: 13.5px; }
footer p { margin: 0; }

@media (max-width: 820px) {
  main { grid-template-columns: minmax(0, 1fr); justify-items: center; }
  .stage-col, .side { width: 100%; max-width: var(--col-w); }
  #log-card { display: none !important; } /* the inline Log expander under the moves takes over */
}
@media (min-width: 821px) {
  .logbox { display: none; }
  /* Bouts on a wide screen is one console down the middle: tabs, plates, arena, caption and moves, with the log and
     the stats under it instead of beside it */
  body[data-mode="bouts"] main { display: flex; flex-direction: column; align-items: center; gap: 0; max-width: 760px; margin: 0 auto; }
  body[data-mode="bouts"] .stage-col, body[data-mode="bouts"] .side { width: 100%; max-width: 600px; }
  body[data-mode="bouts"] .side { margin-top: 14px; }
  /* in a bout the console gets narrower on a short window, so the moves stay on screen under the arena, and wider on
     a tall one (760px at most), so the arena fills a big display */
  /* (453px is the bout's chrome above and below the arena: it grew by the 25px row on the foe's plate that says what it will do next) */
  /* (until 2026-10-15 the whole console, arena included, was this wide:
     body.bout .stage-col, body.bout .side { max-width: clamp(420px, calc((100vh - 453px) * 1.44), 760px); }
     Replaced at the owner's request: the arena now fills the page, as Home and the park do) */
  /* in a bout the arena is as wide as the page and as tall as the rest of the console leaves (--chrome, measured in
     fitStage), showing more sky and meadow round the circle (ROOM_PX in app/room-draw.js); the plates, the caption
     and the moves keep the console's width in the middle, narrower on a short window and wider on a tall one */
  body.bout main { max-width: none; }
  body.bout .stage-col { max-width: none; }
  body.bout .stage-col > :not(.stage), body.bout .side { width: 100%; max-width: clamp(420px, calc((100vh - 453px) * 1.44), 760px); margin-inline: auto; }
  /* (451px: the arena's 250 units with 40% more sky, at ROOM_PX. Taller showed mostly empty sky) */
  body.bout .stage[data-mode="bouts"] { aspect-ratio: auto; height: min(451px, max(220px, calc(100vh - var(--chrome, 453px)))); }
}
/* the hub on a wide screen: the fighter and sparring on the left, the gauntlets beside them, so the page is two short
   columns and not one long scroll */
@media (min-width: 1000px) {
  body[data-mode="bouts"]:not(.bout) main { max-width: 1080px; }
  body[data-mode="bouts"]:not(.bout) .stage-col { max-width: none; }
  /* everything above the hub keeps the width it has on a narrower screen, in the middle */
  body[data-mode="bouts"]:not(.bout) .stage-col > :not(#league) { max-width: 600px; margin-inline: auto; }
  .league.two { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.08fr); gap: 0 18px; align-items: start; }
  .league.two > .gz { margin-top: 0; }
}
/* Replaced 2026-10-15 at the owner's request (a bigger room on big screens, About and Diary under the care buttons);
   kept so it can come back. Home on a big screen: the game column is as wide as the window's height can use
   (--col-w), with the cards beside it, so the room fills a tall display instead of sitting small in a field of dots
@media (min-width: 900px) {
  body[data-mode="home"] main { grid-template-columns: minmax(460px, var(--col-w)) minmax(320px, 1fr); gap: 28px; max-width: calc(var(--col-w) + var(--side-w) + 28px); margin-inline: auto; }
  body[data-mode="home"] .side { margin-top: var(--side-top, 0px); }
}
@media (min-width: 821px) and (max-aspect-ratio: 4/5) {
  body[data-mode="home"] main { grid-template-columns: minmax(0, 1fr); justify-items: center; max-width: none; }
  body[data-mode="home"] .stage-col, body[data-mode="home"] .side { width: 100%; max-width: var(--col-w); }
  body[data-mode="home"] .side { margin-top: 0; }
}
*/
/* Home on a big screen: one column as wide as the page, the room filling the height the controls leave. The room
   shows more of itself past the booger's own size (ROOM_PX in app/room-draw.js), so a bigger box is more room, not a
   bigger booger. The controls keep the width they have on a tall screen, in the middle; About and Diary sit side by
   side under the care buttons */
@media (min-width: 821px) {
  body[data-mode="home"] main { grid-template-columns: minmax(0, 1fr); max-width: none; }
  body[data-mode="home"] .stage-col > :not(.stage) { max-width: max(var(--col-w), 720px); margin-inline: auto; }
  body[data-mode="home"] .stage[data-mode="home"] { --h: max(280px, calc(var(--vh) - var(--chrome, 340px))); max-width: none; }
  body[data-mode="home"] .side { grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); align-items: start; width: 100%; margin: 6px auto 0; }
}
@media (max-width: 420px) {
  .wrap { padding: 10px 10px 24px; }
  #name { font-size: 23px; }
  .meters { gap: 5px; }
  .meter { padding: 3px 6px 3px 4px; gap: 4px; }
  .meter svg { width: 16px; height: 16px; }
  .tools { gap: 7px; }
  .tools button { font-size: 14px; border-radius: 18px; }
  .stage { border-radius: 24px; }
}
@media (prefers-reduced-motion: reduce) {
  .meter.low, .tools button.need, .diary li.new, .tray, .tray .tile.want, .status.warn.pop, .result { animation: none; }
}

/* ---------- tabs ---------- */
/* a strip built to hold five: each tab is an icon over its label, as wide as its label needs plus a share of what is
   left. Nothing here sets a tab's width, so a fourth and fifth button drop in without a change */
.tabs { display: flex; gap: 4px; margin-bottom: 8px; padding: 3px; background: #efe3cf; border-radius: var(--r-tile); }
.tabs button {
  position: relative;
  flex: 1 1 auto; min-width: 0; min-height: 44px; padding: 3px 4px 2px;
  display: grid; justify-items: center; align-content: center; gap: 0;
  background: transparent; border: var(--line-w) solid transparent; border-radius: var(--r-chip);
  font-weight: 600; font-size: 12px; line-height: 1.15; white-space: nowrap; color: var(--ink);
  transition: background .15s;
}
.tabs button .ic { font-size: 20px; color: var(--soft); }
/* something is waiting on that tab: points to spend, or a booger rested and ready */
.tabs button.dot::after { content: ''; position: absolute; top: 1px; left: calc(50% + 9px); width: 9px; height: 9px; background: #e2674f; border: 1.5px solid var(--ink); border-radius: 50%; }
.tabs button[aria-selected="true"] { background: var(--card); border-color: var(--ink); box-shadow: var(--shadow-hard); }
.tabs button[aria-selected="true"] .ic { color: var(--ink); }
/* while a bout runs the tabs stay where they are, switched off: a dashed outline, and the way back still in sight.
   They also drop to one line there, which gives the arena back the height the icons took */
.tabs button:disabled { cursor: default; }
.tabs button:disabled:not([aria-selected="true"]) { border: var(--line-w) dashed var(--ink); }
body.bout .stage-col { --tabs-h: 46px; }
body.bout .tabs button { min-height: 34px; padding: 3px 4px; }
body.bout .tabs button .ic { display: none; }
body.bout .tabs button.dot::after { top: 3px; left: auto; right: 8px; }
/* the bout is over and the tabs work again, still one line tall: a finger gets its 44px from a strip above and below */
@media (pointer: coarse) { body.bout .tabs button:not(:disabled)::before { content: ''; position: absolute; inset: -7.5px -2.5px; } }
/* phones and tablets: the tabs stay at the top of the screen while a long page (the hub, a talent tree) scrolls under
   them. Stuck, the bar is a strip of page colour from 8px above the pill, so nothing shows over it or round its ends;
   the pill itself is drawn by ::before */
@media (max-width: 899px) {
  .tabs { position: sticky; top: calc(var(--tabs-top) - 8px); z-index: 10; margin-top: -8px; padding-top: 11px; background: var(--bg); border-radius: 0; }
  .tabs::before { content: ''; position: absolute; inset: 8px 0 0; z-index: -1; background: #efe3cf; border-radius: var(--r-tile); }
}

/* ---------- icons and the locked look ---------- */
/* an icon from the sprite at the end of index.html. It is 1em square, so the rule that sized an emoji icon sizes it too */
.sprite { position: absolute; width: 0; height: 0; overflow: hidden; }
svg.ic { flex: none; display: block; width: 1em; height: 1em; }
/* anything shut: a dashed ink outline, the card colour, no shadow, text at full strength. Never opacity alone. The
   element also carries the padlock (icon('lock')), its real name and one line saying what opens it. !important, like
   [hidden]: the state has to win over whatever component it lands on, in any stylesheet */
.locked { background: var(--card) !important; color: var(--ink); border: var(--line-w) dashed var(--ink) !important; box-shadow: none !important; opacity: 1 !important; cursor: default; }

/* ---------- bouts ---------- */
/* the slim bar under the tabs while a bout runs, where the name row was: the round, and Forfeit */
.bout-bar { display: flex; align-items: center; justify-content: flex-start; gap: 8px; min-height: 36px; margin-bottom: 8px; padding: 0 2px; }
.bout-bar b { font-size: 18px; font-weight: 600; }
#b-forfeit { margin-left: auto; }
/* from round 9: the chip beside the round. It gives way while Forfeit is armed, whose label needs the bar's width on a phone */
.tired { display: inline-flex; align-items: center; gap: 4px; padding: 2px 9px; background: #fff; border: 2px solid var(--ink); border-radius: var(--r-pill); font-size: 13px; font-weight: 500; white-space: nowrap; }
.tired .ic { width: 16px; height: 16px; }
.bout-bar.arming .tired { display: none; }
/* Fast, and what a boss hands over */
#b-fast { display: inline-flex; align-items: center; gap: 4px; margin-left: auto; }
#b-fast .ic { width: 16px; height: 16px; }
#b-fast[aria-pressed="true"] { background: var(--butter); transform: translateY(2px); box-shadow: 0 1px 0 var(--ink); }
#b-fast + #b-forfeit { margin-left: 0; }
.bout-bar.arming #b-fast { display: none; }           /* the armed Forfeit label needs the room, as with the Overtired chip */
@media (max-width: 420px) { .bout-bar { gap: 6px; } #b-fast, #b-forfeit { padding-inline: 10px; } }
@media (pointer: coarse) { #b-fast { min-height: 44px; } }

.tally .ic { display: inline-block; width: 14px; height: 14px; margin-right: 3px; vertical-align: -2px; }
.loot { margin-top: 10px; }
.loot-row { display: grid; grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr); gap: 8px; }
.loot-tile { display: grid; grid-template-columns: 56px minmax(0, 1fr); align-items: center; gap: 2px 8px; padding: 4px 8px 6px;
  background: var(--card); border: var(--line-w) solid var(--ink); border-radius: var(--r-tile); }
.loot-tile canvas { grid-row: 1 / span 2; width: 56px; height: 56px; }
.loot-tile b { align-self: end; font-size: 14px; font-weight: 600; line-height: 1.15; overflow-wrap: anywhere; }
.loot-tile .rar { align-self: start; justify-self: start; padding: 0 8px; border: 1.5px solid var(--ink); border-radius: var(--r-pill); font-size: 12px; }
.rar[data-rar="common"] { background: var(--rar-common); }
.rar[data-rar="rare"] { background: var(--rar-rare); }
.rar[data-rar="epic"] { background: var(--rar-epic); }
.rar[data-rar="legendary"] { background: var(--rar-legendary); }
.rar[data-rar="mythic"] { background: var(--rar-mythic); }
.loot-tile .btn { grid-column: 1 / -1; }
.loot-tile .btn:disabled { box-shadow: none; transform: translateY(3px); cursor: default; }
.loot-par { margin: 2px 0 0; text-align: center; font-size: 13px; color: var(--soft); }
/* the loot wheel (S45): the wheel and its caption side by side, in the moves' room (min-height is set from it) */
.loot-spin { display: flex; align-items: center; justify-content: center; gap: 14px; }
.loot-wheel { flex: none; border-radius: 50%; cursor: pointer; }
.loot-spin p { margin: 0; max-width: 11em; font-size: 15px; font-weight: 500; color: var(--soft); }
.loot-spin p b { color: var(--ink); font-size: 16px; font-weight: 600; }
/* a duplicate: what it paid instead, in the tally's good colour */
.loot-dup { grid-column: 1 / -1; display: inline-flex; align-items: center; justify-self: start; gap: 4px; padding: 1px 8px; background: var(--butter); border: 1.5px solid var(--ink); border-radius: var(--r-pill); font-size: 13px; font-weight: 600; font-variant-numeric: tabular-nums; }
@media (pointer: coarse) { .loot-tile .btn { min-height: 44px; } }
/* a short phone has no room for the tabs in a bout, now that the foe's plate has a row more. They are switched off
   there anyway, and the result card has Back, Rematch and Skills */
@media (max-width: 820px) and (max-height: 699px) {
  body.bout .tabs { display: none; }
  /* and the arena gives up what is still missing by getting narrower: 432px is everything else on the screen in the
     fullest state (Overtired, a wind-up, three chips, a two-line caption, four moves), measured, plus 6 */
  body.bout .stage { max-width: calc((100svh - 432px) * 360 / 250); margin-inline: auto; }
}

/* pep plates: a strip of their own directly above the arena, so the sky, the tree and the sparks stay in view */
.plates { display: flex; justify-content: space-between; gap: 8px; margin-bottom: 8px; }
.plate { flex: 1 1 0; min-width: 0; padding: 5px 9px 7px; background: var(--card); border: var(--line-w) solid var(--ink); border-radius: var(--r-chip); font-size: 13px; }
.plate.foe { text-align: right; }
.plate .who { display: flex; align-items: baseline; gap: 5px; line-height: 1.25; white-space: nowrap; }
.plate.foe .who { flex-direction: row-reverse; }
.plate .who b { min-width: 0; overflow: hidden; text-overflow: ellipsis; font-size: 15px; font-weight: 600; }
.plate .who b .ic { display: inline-block; width: 15px; height: 15px; margin-right: 3px; vertical-align: -2px; }
.plate .who span { color: var(--soft); font-size: 12.5px; }
.plate .who em { margin-left: auto; font-style: normal; font-size: 13px; font-weight: 600; font-variant-numeric: tabular-nums; }
.plate.foe .who em { margin: 0 auto 0 0; }
.pep { position: relative; height: 16px; margin-top: 3px; background: #efe3cf; border: 2px solid var(--ink); border-radius: var(--r-pill); overflow: hidden; }
.pep i { display: block; height: 100%; width: 100%; background: #f58aa0; transition: width .35s; }
.plate.foe .pep i { margin-left: auto; }
.pep::after { content: ''; position: absolute; inset: 0; background: repeating-linear-gradient(90deg, transparent 0 calc(25% - 1px), rgba(61, 51, 64, .35) calc(25% - 1px) 25%); }
.pep em { position: absolute; inset: 0; z-index: 1; display: grid; place-items: center; font-style: normal; font-size: 12px; font-weight: 600; line-height: 1; font-variant-numeric: tabular-nums; }
/* a chip's height is kept free beside the sparkle bar, so the arena below doesn't jump when the first status lands */
.sprow { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 6px; min-height: 22px; margin-top: 3px; }
.plate.foe .sprow { flex-direction: row-reverse; }
.spk { flex: 1 1 36px; height: 7px; background: #efe3cf; border: 1.5px solid var(--ink); border-radius: var(--r-pill); overflow: hidden; }
.spk span { display: block; height: 100%; width: 100%; background: var(--lilac); transition: width .35s; }
.plate.foe .spk span { margin-left: auto; }
.fx { display: flex; flex-wrap: wrap; gap: 4px; }
.fx:empty { display: none; }
.plate.foe .fx { justify-content: flex-end; }
.fx span { padding: 1px 7px; font-size: 12px; white-space: nowrap; border-radius: var(--r-pill); border: 1.5px solid var(--ink); background: #fff; }
.fx span.good { background: var(--butter); }
.fx span.bad { background: var(--lilac); }
.fx span, .nxt .intent { display: inline-flex; align-items: center; gap: 3px; }
.fx span i { font-style: normal; font-weight: 600; }
.fx span.bad { border-style: dashed; }                  /* with .good solid: a sign and a border, not colour alone */
.fx .ic, .nxt .ic { width: 13px; height: 13px; }
/* the foe's plate ends with what it will do next; the row keeps its height when it is empty */
.nxt { display: flex; min-height: 22px; margin-top: 3px; }
.plate.foe .nxt { justify-content: flex-end; }
.nxt .intent { padding: 1px 7px; background: #fff; border: 1.5px solid var(--ink); border-radius: var(--r-pill); font-size: 12px; white-space: nowrap; }

.moves { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin-top: 10px; }
.moves button {
  position: relative;
  display: grid; grid-template-columns: auto minmax(0, 1fr); align-content: center; align-items: center; gap: 0 9px;
  min-height: 64px; padding: 8px 10px 7px; text-align: left;
  background: var(--card); border: var(--line-w) solid var(--ink); border-radius: var(--r-tile);
  box-shadow: 0 5px 0 var(--ink);
  font-size: 14px; font-weight: 500; line-height: 1.2;
  transition: transform .06s, box-shadow .06s;
}
/* a move's category has a colour wherever the move is shown (a bout's buttons, the hub's kit, the Skills loadout,
   its picker and the move talents): paws coral, throws butter, sparkles lilac, naps sky, moods mint. The icon sits on
   a disc of it; the name beside it still says what the move is */
[data-cat="paws"] { --cat: var(--coral); }
[data-cat="throws"] { --cat: var(--butter); }
[data-cat="sparkles"] { --cat: var(--lilac); }
[data-cat="naps"] { --cat: var(--sky); }
[data-cat="moods"] { --cat: var(--mint); }
.moves button .ic { grid-row: span 2; width: 38px; height: 38px; padding: 7px; background: var(--cat, #fff); border: 2px solid var(--ink); border-radius: 50%; }
.moves button span { align-self: end; font-size: 15px; font-weight: 600; }
.moves button small { align-self: start; font-size: 12px; color: var(--soft); }
.moves button:active { transform: translateY(4px); box-shadow: 0 1px 0 var(--ink); }
.moves button:disabled { border-style: dashed; cursor: default; transform: translateY(3px); box-shadow: none; }
/* a move it can't afford still takes focus and a long press, and says what it needs */
.moves button[aria-disabled="true"] { background: var(--bg); border-style: dashed; cursor: default; transform: translateY(5px); box-shadow: none; }
.moves button[aria-disabled="true"] .ic { background: transparent; border-style: dashed; opacity: .45; }
.moves button[aria-disabled="true"] span { opacity: .5; }
.moves button[aria-disabled="true"] small { justify-self: start; padding: 0 7px; background: var(--coral); border: 1.5px solid var(--ink); border-radius: var(--r-pill); color: var(--ink); font-weight: 600; }
.moves button { user-select: none; -webkit-user-select: none; -webkit-touch-callout: none; }
@media (hover: hover) {
  .moves button::after { content: attr(data-key); position: absolute; top: 5px; right: 7px; min-width: 18px; padding: 1px 4px; border: 1.5px solid var(--ink); border-radius: 6px; background: #fff; font-size: 12px; font-weight: 600; line-height: 1.2; color: var(--soft); }
}
/* the result: a card that pops in over the arena when the bout ends, with what was won and the ways on. It covers
   the stage and nothing else: the tabs, the caption and the log stay in reach */
.result {
  position: absolute; inset: 16px; z-index: 10;
  display: flex; flex-direction: column; align-items: center; gap: 8px;
  padding: 12px 16px; overflow-y: auto; text-align: center;
  background: rgba(255, 250, 242, .96);
  border: 3px solid var(--ink); border-radius: var(--r-card);
  box-shadow: 0 8px 0 rgba(61, 51, 64, .25);
  animation: popIn .25s cubic-bezier(.175, .885, .32, 1.275);
}
@keyframes popIn { from { transform: scale(.92); opacity: 0; } to { transform: scale(1); opacity: 1; } }
/* centred, by margins: a card taller than a small arena then scrolls from its top */
.result > :first-child { margin-top: auto; }
.result > :last-child { margin-bottom: auto; }
.result h3 { margin: 0; font-size: 26px; font-weight: 600; line-height: 1.15; }
.result p { margin: 0; color: var(--soft); font-size: 14.5px; }
.tally { display: flex; flex-wrap: wrap; justify-content: center; gap: 5px 6px; }
.tally span { padding: 2px 10px; background: #fff; border: 2px solid var(--ink); border-radius: var(--r-pill); font-size: 13.5px; font-weight: 500; white-space: nowrap; font-variant-numeric: tabular-nums; }
.tally span.good { background: var(--butter); }
.tally .coin-won { display: inline-flex; align-items: center; gap: 4px; }
.tally .coin-won .vh { padding: 0; border: 0; }
.result .acts { display: flex; flex-wrap: wrap; justify-content: center; gap: 8px; margin-top: 4px; }
.result .acts .btn { flex: 1 1 auto; }
.result .acts .btn:first-child { flex-basis: 100%; }
@media (min-width: 821px) {
  /* the arena is big here, and so is the card that lands on it */
  .result { gap: 12px; }
  .result h3 { font-size: 34px; }
  .result p { font-size: 16px; }
  .tally span { padding: 3px 13px; font-size: 15.5px; }
  .result .acts { margin-top: 8px; }
  .result .acts .btn { padding: 9px 22px; font-size: 16px; }
}

/* the full log, folded away under the moves on narrow screens */
.logbox { margin-top: 10px; background: var(--card); border: var(--line-w) solid var(--ink); border-radius: var(--r-tile); }
.logbox summary { padding: 9px 14px; cursor: pointer; font-weight: 600; font-size: 14px; list-style: none; }
.logbox summary::-webkit-details-marker { display: none; }
.logbox summary::after { content: ' \25BE'; color: var(--soft); }
.logbox[open] summary::after { content: ' \25B4'; }
.logbox .blog { max-height: 220px; padding: 0 14px 12px; }

@media (pointer: coarse) {
  #b-forfeit, .result .btn, .logbox summary, .league .btn, .lhead .btn { min-height: 44px; }
  .logbox summary { display: flex; align-items: center; }
}

.league { margin-top: 12px; }
.lhead { display: grid; gap: 4px; margin-bottom: 10px; padding: 12px 14px; background: var(--card); border: var(--line-w) solid var(--ink); border-radius: var(--r-tile); }
.lhead b { font-size: 17px; font-weight: 600; }
.lhead span { font-size: 13.5px; color: var(--soft); }
.league > * + .lhead { margin-top: 12px; }
.league > .btn { width: 100%; margin-bottom: 10px; }
.rivals { display: grid; gap: 8px; }
.rival { display: grid; grid-template-columns: 56px 1fr auto; gap: 10px; align-items: center; padding: 6px 10px 6px 6px; background: var(--card); border: var(--line-w) solid var(--ink); border-radius: var(--r-tile); }
.rival canvas { width: 56px; height: 56px; }
.rival b { display: block; font-weight: 600; }
.rival small { color: var(--soft); font-size: 13px; }
.rival.beaten canvas { filter: saturate(.7); }
.rival.next { border-color: #e2674f; box-shadow: 0 0 0 3px var(--butter); }
.blog { list-style: none; margin: 0; padding: 0; max-height: 360px; overflow: auto; display: grid; gap: 6px; font-size: 14px; }
.blog li.new { font-weight: 600; }
/* each round opens with a small heading; the log is newest first, so the rule sits above it, between rounds */
.blog li.round { margin-top: 4px; padding-top: 6px; border-top: 2px dashed var(--line); color: var(--soft); font-size: 13px; font-weight: 600; font-variant-numeric: tabular-nums; }
.blog li.round:first-child { margin-top: 0; padding-top: 0; border-top: 0; }
/* the stats, in the hub's fighter card: two columns of cells, each a name, its number, and what it means under them */
.stats { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 6px 8px; margin: 0; font-size: 14px; }
.stat { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center; gap: 0 6px; padding: 4px 9px 5px; background: #fff; border: 2px solid var(--ink); border-radius: var(--r-chip); line-height: 1.25; }
.stats dt { display: flex; align-items: center; gap: 5px; font-weight: 500; }
.stats dt .ic { width: 16px; height: 16px; }
.stats dd { display: contents; }
.stats dd b { font-weight: 600; font-variant-numeric: tabular-nums; }
.stats dd small { grid-column: 1 / -1; font-size: 12px; font-weight: 400; color: var(--soft); }
/* the panel opens downwards inside the card, by its own height */
.fstats { display: grid; grid-template-rows: 0fr; visibility: hidden; transition: grid-template-rows .22s ease, visibility 0s .22s; }
.fstats.open { grid-template-rows: 1fr; visibility: visible; transition: grid-template-rows .22s ease; }
.fstats-in { min-height: 0; overflow: hidden; }
.fstats .stats { margin-top: 10px; padding-top: 10px; border-top: 2px dashed var(--line); }
/* a sprite icon beside words, on one line */
.mini span, .picker button, .dhead b, .ftitle b, .lrow b { display: inline-flex; align-items: center; gap: 4px; }
.mini .ic { width: 13px; height: 13px; }
.dhead .ic, .ftitle .ic, .lrow .ic { width: 18px; height: 18px; }
.stats dd { margin: 0; }
.stats p { grid-column: 1 / -1; margin: 2px 2px 0; }

@media (max-width: 420px) {
  .moves button { border-radius: 14px; }
  .plates { gap: 6px; }
  .plate { padding: 4px 8px 6px; }
  .result { inset: 8px; gap: 5px; padding: 6px 10px; }
  .result h3 { font-size: 20px; }
  .result p, .tally span { font-size: 13px; }
  .result .acts { gap: 6px; margin-top: 2px; }
}
/* on a short phone the arena is low, and the three ways on share one row so the longest card (a boss's) still fits it */
@media (max-width: 420px) and (max-height: 699px) {
  .result .acts { flex-wrap: nowrap; }
  .result .acts .btn, .result .acts .btn:first-child { flex: 1 1 auto; padding-inline: 8px; white-space: nowrap; }
}

/* ---------- bouts page: our fighter, next up, last bout, gauntlet ---------- */
.league section { margin-top: 12px; }
.league > .fighter { margin-top: 0; }
.fighter { padding: 10px 12px 12px; background: var(--card); border: var(--line-w) solid var(--ink); border-radius: var(--r-tile); }
.fhead { display: grid; grid-template-columns: 56px minmax(0, 1fr) auto; gap: 10px; align-items: center; }
.fhead canvas { width: 56px; height: 56px; }
/* Stats and Edit, beside the fighter */
.facts { align-self: start; display: flex; gap: 6px; }
.facts .btn { padding-inline: 12px; }
.fstats-btn[aria-expanded="true"] { background: var(--butter); transform: translateY(2px); box-shadow: 0 1px 0 var(--ink); }
@media (max-width: 480px) { .facts { flex-direction: column; } }
@media (pointer: coarse) { .facts .btn { min-height: 44px; } }
/* the hub's sections: the fighter, then Sparring and the Gauntlets as two tinted cards, each under its own heading */
.hub-main { display: grid; grid-template-columns: minmax(0, 1fr); gap: 12px; }
.league .hub-main > section { margin-top: 0; }
.hub-card { padding: 12px; border: var(--line-w) solid var(--ink); border-radius: var(--r-card); }
.hub-card.spar { --wash: var(--sky); }
.hub-card.gz { --wash: var(--butter); }
.hub-card { background: color-mix(in srgb, var(--wash, var(--line)) 32%, var(--card)); }
.hub-head { display: flex; align-items: center; gap: 10px; margin-bottom: 10px; }
.league .hub-head h3 { margin: 0; font-size: 18px; line-height: 1.2; }
.hub-ic { flex: none; display: grid; place-items: center; width: 38px; height: 38px; background: var(--wash); border: 2px solid var(--ink); border-radius: 50%; }
.hub-ic .ic { width: 22px; height: 22px; }
.hub-sub { margin: 12px 0 6px 4px; font-size: 14px; font-weight: 600; }
.hub-head + div > .hub-sub { margin-top: 0; }
/* one notice for the whole hub while the booger can't fight: what is so, and the way Home */
.gz-stop { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 10px; margin: 0; padding: 9px 14px; background: var(--butter); border: var(--line-w) solid var(--ink); border-radius: var(--r-tile); box-shadow: var(--shadow-hard); font-weight: 500; }
.gz-stop::before { content: '!'; flex: none; display: grid; place-items: center; width: 24px; height: 24px; background: var(--coral); border: 2px solid var(--ink); border-radius: 50%; font-weight: 600; font-size: 15px; line-height: 1; }
.gz-stop span { flex: 1 1 10em; }
.gz-stop .btn { background: #fff; font-weight: 600; }
@media (pointer: coarse) { .gz-stop .btn { min-height: 44px; } }
.ftitle { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0 8px; }
.ftitle b { font-size: 17px; font-weight: 600; }
.ftitle span { font-size: 14px; color: var(--soft); }
.xpbar { position: relative; height: 18px; margin: 3px 0 2px; }
.xpbar i { background: #8ecbf2; }
.xpbar em { position: absolute; inset: 0; display: grid; place-items: center; font-style: normal; font-size: 12px; font-weight: 600; line-height: 1; font-variant-numeric: tabular-nums; }
.frow { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.frec { display: block; font-size: 13px; color: var(--soft); font-variant-numeric: tabular-nums; }
.kit { list-style: none; display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin: 10px 0 0; padding: 0; }
.kit li { display: grid; grid-template-columns: auto minmax(0, 1fr); align-items: center; gap: 0 8px; padding: 3px 10px; background: #fff; border: 2px solid var(--ink); border-radius: 14px; line-height: 1.2; }
.kit .ic { grid-row: span 2; width: 30px; height: 30px; padding: 5px; background: var(--cat, #fff); border: 2px solid var(--ink); border-radius: 50%; }
.kit b { font-size: 14px; font-weight: 500; overflow-wrap: anywhere; }
.kit small { font-size: 13px; color: var(--soft); font-variant-numeric: tabular-nums; }
.rival.opp { grid-template-columns: 72px minmax(0, 1fr); padding: 8px 10px 10px 8px; }
.rival .go { grid-column: 1 / -1; display: grid; gap: 6px; }
.rival .go .acts { display: flex; flex-wrap: wrap; gap: 8px; }
.rival .go .btn.big { flex: 1 1 140px; padding: 9px 18px; font-size: 18px; font-weight: 600; }
.rival .go .btn.plain { flex: 0 1 auto; }
.league h3 { margin: 0 0 8px 4px; font-size: 16px; font-weight: 600; }
.league h3 small { display: block; font-weight: 400; font-size: 13px; color: var(--soft); }
.rival .acts { display: grid; gap: 6px; }
.rival .acts .btn { font-size: 13px; padding: 5px 10px; white-space: nowrap; }
.rival.opp canvas { width: 72px; height: 72px; }
.rival.lost { border-style: dashed; }
.mini { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 4px; }
.mini span { padding: 1px 7px; font-size: 12px; border: 1.5px solid var(--line); border-radius: 99px; background: #fff; color: var(--soft); }
/* the gauntlets: a chip per gauntlet, a strip of named tiles, the boss card, and the readiness and difficulty lines */
/* the three chips are one size: as wide as each other, a row of three where they fit, and every row as tall as the
   tallest chip, an open one included (owner, 2026-10-15) */
.gz-series { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); grid-auto-rows: 1fr; gap: 8px; margin-bottom: 10px; }
.gz-chip { display: grid; grid-template-columns: auto auto; justify-content: start; align-content: center; align-items: baseline; gap: 0 8px; padding: 6px 14px; background: var(--card);
  border: var(--line-w) solid var(--ink); border-radius: var(--r-tile); font-size: 14px; text-align: left; }
.gz-chip b { font-weight: 600; }
.gz-chip span { color: var(--soft); font-variant-numeric: tabular-nums; }
.gz-chip[aria-pressed="true"] { background: var(--butter); box-shadow: var(--shadow-hard); }
.gz-chip.locked { grid-template-columns: auto 1fr; cursor: default; }        /* S05's .locked gives the dashed border */
.gz-chip.locked small { grid-column: 2; font-size: 12px; color: var(--soft); }
.gz-chip .ic { width: 16px; height: 16px; align-self: center; }

/* the rivals in two rows (--cols, set in gzRender, is half of them), each tile at least 64px: where a row of half of
   them doesn't fit (a phone) they wrap into more rows instead. Nothing scrolls sideways. Was one row (until 2026-10-15):
   .gz-strip { display: flex; gap: 8px; margin: 0 0 10px; padding: 6px 4px 8px; list-style: none; overflow-x: auto; scrollbar-width: thin; } */
.gz-strip { display: grid; grid-template-columns: repeat(auto-fill, minmax(max(64px, calc((100% - (var(--cols, 7) - 1) * 8px) / var(--cols, 7))), 1fr)); gap: 8px; margin: 0 0 10px; padding: 6px 4px 8px; list-style: none; }
.gz-strip li { display: grid; }
.gz-tile { position: relative; flex: none; display: grid; justify-items: center; gap: 0; width: 100%; min-width: 0; padding: 4px 3px 5px;
  background: var(--card); border: var(--line-w) solid var(--ink); border-radius: var(--r-chip); line-height: 1.15; }
.gz-tile canvas { width: 48px; height: 48px; }
.gz-tile b { max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 12px; font-weight: 600; }
.gz-tile small { font-size: 12px; color: var(--soft); font-variant-numeric: tabular-nums; }
.gz-tile.next { background: var(--butter); box-shadow: 0 0 0 3px var(--butter), 0 0 0 5px var(--ink); }   /* the wanted snack tile's ring */
.gz-tile.locked { cursor: default; }
.gz-tile.locked canvas { filter: grayscale(1); }
.gz-mark { position: absolute; top: 3px; right: 3px; width: 16px; height: 16px; padding: 1px; background: var(--card); border-radius: 50%; }
.gz-tile.beaten .gz-mark { background: var(--mint); }
/* a rival that drops a look of the set (S45): a gift at the top left, faded once both looks are won */
.gz-drop { position: absolute; top: 4px; left: 4px; width: 14px; height: 14px; }
.gz-drop.got { opacity: .5; }

.gz-boss { display: grid; grid-template-columns: 72px minmax(0, 1fr); gap: 8px 10px; align-items: center; margin-top: 10px; padding: 8px 10px 10px 8px;
  background: var(--card); border: var(--line-w) solid var(--ink); border-radius: var(--r-tile); box-shadow: var(--shadow-hard); }
.gz-boss > canvas { width: 72px; height: 72px; }
.gz-binfo > b { display: flex; align-items: center; gap: 5px; font-size: 17px; font-weight: 600; }
.gz-binfo > b .ic { width: 18px; height: 18px; }
.gz-binfo small, .gz-wins { display: block; font-size: 13px; color: var(--soft); }
.gz-loot, .gz-shut, .gz-boss .go { grid-column: 1 / -1; }
.gz-loot { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 12px; }
.gz-look { display: grid; justify-items: center; margin: 0; font-size: 12px; }
.gz-look canvas { width: 44px; height: 44px; }
.gz-loot p { flex: 1 1 8em; margin: 0; font-size: 13px; color: var(--soft); }
.gz-shut { display: flex; align-items: center; gap: 6px; margin: 0; font-size: 14px; font-weight: 500; }
.gz-shut .ic { width: 18px; height: 18px; }
.gz-boss .go { display: grid; gap: 6px; }

.gz-ready { margin: 0; font-size: 13px; line-height: 1.3; color: var(--soft); }
.gz-odds { display: flex; align-items: center; gap: 6px; min-width: 124px; min-height: 20px; margin-top: 2px; font-size: 13px; }
.gz-odds b { display: inline; font-weight: 600; }
.gz-odds.wait b { color: var(--soft); font-weight: 500; }
.gz-pips { display: inline-flex; gap: 3px; }
.gz-pips i { width: 8px; height: 8px; background: var(--card); border: 1.5px solid var(--ink); border-radius: 50%; }
.gz-pips i.on { background: var(--ink); }
@media (pointer: coarse) { .gz-chip { min-height: 44px; } }

/* ---------- skills: classes and talent trees ----------
   Phones: header, loadout chips, a tree switcher, one tree, and the detail bar (pinned to the bottom once a talent is picked).
   900px and up: the side column goes away; a sticky left panel (loadout, detail) sits beside all three trees */
.ic { font-style: normal; }
.skills { display: grid; gap: 12px; }
.skills .lhead { margin: 0; }
.lrow { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: 4px 10px; }
.lhead .pts { padding: 1px 10px; background: var(--butter); border-radius: var(--r-pill); color: var(--ink); font-size: 14px; font-weight: 600; font-variant-numeric: tabular-nums; }
.lhead .pts.none { background: transparent; padding: 0; color: var(--soft); font-weight: 500; }
.skside { display: contents; }

.loadout { padding: 10px 12px 12px; background: var(--card); border: var(--line-w) solid var(--ink); border-radius: var(--r-tile); }
.loadout h3 { margin: 0 0 8px; font-size: 16px; font-weight: 600; }
.slots { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 8px; }
.slots button { display: grid; justify-items: center; align-content: center; gap: 2px; padding: 6px 4px; background: #fff; border: var(--line-w) solid var(--ink); border-radius: var(--r-chip); font-size: 13px; font-weight: 500; line-height: 1.2; overflow-wrap: break-word; }
.slots button .ic { width: 32px; height: 32px; padding: 5px; background: var(--cat, #fff); border: 2px solid var(--ink); border-radius: 50%; }
.slots button[aria-pressed="true"] { background: var(--butter); }
/* (until 2026-10-15 the slots were dashed, solid only while picked: a dashed outline means locked everywhere else) */
.loadout .lohint { margin: -4px 0 8px; font-size: 13px; color: var(--soft); }
.loadout.placing h3 { display: flex; align-items: center; gap: 6px; }
.loadout.placing h3 .ic { width: 26px; height: 26px; padding: 4px; background: var(--cat, #fff); border: 2px solid var(--ink); border-radius: 50%; }
/* a new move waiting for a slot: the slots wear the ring of a talent that can take a point */
.loadout.placing .slots button { box-shadow: 0 0 0 3px var(--butter); animation: canPulse 1.8s ease-in-out infinite; }
.loadout .lokeep { margin-top: 10px; }
.slots button.pop { animation: popIn .35s ease-out; }   /* a new move that went into an empty slot by itself */
@media (prefers-reduced-motion: reduce) { .loadout.placing .slots button { animation: none; } }
.picker { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin-top: 10px; padding-top: 10px; border-top: 2px dashed var(--line); }
.picker span { width: 100%; font-size: 13px; color: var(--soft); }
.picker button { padding: 4px 11px 4px 4px; background: #fff; border: 2px solid var(--ink); border-radius: var(--r-pill); font-size: 13.5px; }
.picker button .ic { width: 24px; height: 24px; padding: 4px; background: var(--cat, #fff); border: 1.5px solid var(--ink); border-radius: 50%; }
.picker button[aria-pressed="true"] { background: var(--butter); }

/* the tree switcher: the same pill strip as the tabs, with each tree's points in a badge */
.seg { display: flex; gap: 8px; padding: 4px; background: #efe3cf; border-radius: var(--r-pill); }
.seg button { flex: 1; display: flex; align-items: center; justify-content: center; gap: 6px; min-width: 0; padding: 6px 4px; background: transparent; border: var(--line-w) solid transparent; border-radius: var(--r-pill); font-size: 15px; font-weight: 600; color: var(--soft); transition: background .15s, color .15s; }
.seg button[aria-pressed="true"] { background: var(--card); color: var(--ink); border-color: var(--ink); box-shadow: var(--shadow-hard); }
.seg button b { min-width: 22px; padding: 0 6px; border: 1.5px solid currentColor; border-radius: var(--r-pill); font-size: 13px; font-weight: 600; line-height: 1.35; font-variant-numeric: tabular-nums; }

.trees { display: grid; gap: 10px; }
.ttree { padding: 10px 10px 12px; background: var(--card); border: var(--line-w) solid var(--ink); border-radius: var(--r-tile); }
.ttree h3 { margin: 0 0 8px 2px; font-size: 16px; font-weight: 600; }
.ttree h3 small { display: block; font-weight: 400; font-size: 13px; color: var(--soft); }
.tier { padding-top: 6px; }
.tier + .tier { margin-top: 6px; border-top: 2px dashed var(--line); }
/* a tier's label: its number, and for a shut one a padlock and the line that says what opens it. No banner: an open
   tier is plain from its tiles. One line tall open or shut, so a tree doesn't jump when a tier opens */
.tlabel { display: flex; align-items: center; gap: 5px; min-height: 20px; margin: 0 0 6px 2px; color: var(--soft); font-size: 12px; line-height: 1.25; }
.tlabel b { color: var(--ink); font-size: 13px; font-weight: 600; white-space: nowrap; }
.tlabel .ic { width: 15px; height: 15px; color: var(--ink); }
.tiles { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; }
/* a talent has three looks, and the selected one on top of them:
   shut: a dashed ink edge, its icon muted; can take a point: a solid ink edge inside a butter ring that breathes;
   has points: a teal edge on a wash of mint, with its rank in a filled counter (a darker one when it is full) */
.talent {
  position: relative;
  display: grid; justify-items: center; align-content: center; gap: 3px;
  min-height: 92px; padding: 8px 6px 7px;
  background: #fff; border: var(--line-w) solid var(--line); border-radius: var(--r-chip);
  font-size: 13.5px; line-height: 1.2; text-align: center;
  transition: transform .08s, box-shadow .08s;
}
.talent .ic { width: 34px; height: 34px; padding: 6px; background: var(--cat, var(--bg)); border: 2px solid var(--ink); border-radius: 50%; }
.talent .tn { font-weight: 500; }
.talent .rk { padding: 0 8px; border: 1.5px solid transparent; border-radius: var(--r-pill); font-size: 13px; color: var(--soft); font-variant-numeric: tabular-nums; }
.talent.can { border-color: var(--ink); box-shadow: 0 0 0 3px var(--butter); animation: canPulse 1.8s ease-in-out infinite; }
@keyframes canPulse { 50% { box-shadow: 0 0 0 5px var(--butter); } }
.talent.part, .talent.full { border-color: var(--teal); background: color-mix(in srgb, var(--mint) 22%, #fff); }
.talent.part .rk { background: var(--mint); border-color: var(--ink); color: var(--ink); font-weight: 600; }
.talent.full .rk { background: var(--teal); border-color: var(--ink); color: #fff; font-weight: 600; }
.talent.shut { background: var(--card); border: var(--line-w) dashed var(--ink); }
.talent.shut .ic { background: transparent; border-style: dashed; color: var(--soft); }
.talent[aria-pressed="true"] { background: var(--butter); border: var(--line-w) solid var(--ink); box-shadow: var(--shadow-hard); animation: none; }
.talent:active { transform: translateY(2px); }
@media (hover: hover) {
  .talent:not(.shut):not([aria-pressed="true"]):hover { background: #fff7e3; }
  .talent.can:hover { transform: translateY(-2px); }
}
@media (prefers-reduced-motion: reduce) { .talent.can { animation: none; } .fstats, .fstats.open { transition: none; } }
/* Undo and Reset, in the header: the two ways back, for the whole page */
.hacts { display: flex; gap: 8px; }
.lrow .pts { margin-left: auto; }
@media (max-width: 560px) { .hacts { flex-basis: 100%; justify-content: flex-end; } }
.hacts .btn { padding: 4px 13px; font-size: 13.5px; }
.hacts .btn.warn { background: var(--coral); font-weight: 600; }
.hacts .btn:disabled { border-style: dashed; box-shadow: none; transform: translateY(3px); color: var(--soft); cursor: default; }

/* the detail bar: what the selected talent does, what one more rank changes, and the only button that spends */
.tdetail { display: grid; gap: 3px; padding: 10px 14px 12px; background: var(--card); border: var(--line-w) solid var(--ink); border-radius: var(--r-tile); box-shadow: var(--shadow-hard); font-size: 14.5px; line-height: 1.3; }
.tdetail p { margin: 0; }
.dhead { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: 0 10px; }
.dhead b { font-size: 17px; font-weight: 600; }
.dmeta { font-size: 13px; color: var(--soft); }
.dtext { color: var(--soft); }
.dfx, .ddelta { font-weight: 500; font-variant-numeric: tabular-nums; }
.ddelta { font-weight: 600; }
.dmsg { min-height: calc(1.3em + 4px); padding: 2px 10px; background: #fff2ea; border-radius: var(--r-chip); font-weight: 500; }
/* the message line is the live region, so it is always rendered: an empty one keeps its line (Learn doesn't jump when a message arrives) */
.dmsg:empty { background: transparent; }
.tdetail.empty .dmsg:empty { min-height: 0; padding: 0; }
.dacts { display: flex; }
.dleft { margin-left: auto; font-size: 13px; color: var(--soft); font-variant-numeric: tabular-nums; }
.tdetail.peek { border-style: dashed; }
.tfoot { display: flex; flex-wrap: wrap; gap: 8px; }
.tfoot .btn { font-size: 13px; }

@media (max-width: 899px) {
  .skills.picked .ttree:not(.on) { display: none; }
  /* once a talent is picked the bar is pinned to the bottom of the screen while the tree scrolls under it;
     a tile given keyboard focus scrolls clear of it (--skbar is the bar's height, set from app/skills-ui.js). Only tiles:
     a page-wide scroll-padding would count the bar's own buttons as covered and scroll on every Learn */
  .skills.picked .tdetail:not(.empty) { position: sticky; bottom: max(8px, env(safe-area-inset-bottom)); z-index: 3; }
  .skills.picked:has(> .tdetail:not(.empty)) .talent { scroll-margin-bottom: calc(var(--skbar, 200px) + 20px); }
  /* pinned, the bar is kept small so the tree stays readable above it: tighter lines, and two lines of description */
  .tdetail { gap: 2px; padding: 8px 12px; }
  .tdetail .dtext { display: -webkit-box; -webkit-line-clamp: 2; line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; font-size: 13px; }
  .tdetail .ddelta { font-size: 13px; }
  /* the tree switcher sticks under the tabs, so another tree is one tap away from anywhere down the page */
  .skills .seg { position: sticky; top: calc(var(--tabs-top) + var(--tabs-h) - 6px); z-index: 8; margin-top: -6px; padding-top: 10px; background: var(--bg); border-radius: 0; box-shadow: 0 4px 4px -4px rgba(61, 51, 64, .1); }
  .skills .seg::before { content: ''; position: absolute; inset: 6px 0 0; z-index: -1; background: #efe3cf; border-radius: var(--r-pill); }
  .skills .talent { scroll-margin-top: calc(var(--tabs-top) + var(--tabs-h) + 66px); }
}
/* between the phone layout and the wide one, Skills keeps the phone column, centred as it is below 821px */
@media (min-width: 821px) and (max-width: 899px) {
  body[data-mode="skills"] main { grid-template-columns: minmax(0, 1fr); justify-items: center; }
  body[data-mode="skills"] .stage-col { width: 100%; max-width: var(--col-w); }
}
@media (min-width: 900px) {
  body[data-mode="skills"] main { grid-template-columns: minmax(0, 1fr); }
  body[data-mode="skills"] .stage-col > :not(#skills) { max-width: 460px; }
  .skills.picked { grid-template-columns: 220px minmax(0, 1fr); column-gap: 14px; align-items: start; }
  .skills.picked > .lhead { grid-column: 1 / -1; }
  .skside { display: grid; gap: 12px; grid-column: 1; grid-row: 2 / span 2; position: sticky; top: 12px; max-height: calc(100vh - 24px); overflow-y: auto; margin: -6px; padding: 6px; }
  .skills.picked > .seg { display: none; }
  .skills.picked > .trees { grid-column: 2; grid-row: 2; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; }
  .skills.picked > .tfoot { grid-column: 2; grid-row: 3; }
  .slots { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  /* a tree is about 200px wide here, so its tiles stack one per row, icon beside the name */
  .tiles { grid-template-columns: minmax(0, 1fr); }
  .talent { grid-template-columns: auto minmax(0, 1fr) auto; justify-items: start; align-items: center; gap: 8px; min-height: 52px; padding: 7px 10px; text-align: left; }
  .talent .ic { width: 30px; height: 30px; padding: 5px; }
  .tlabel { min-height: 34px; align-items: flex-start; }
  .tlabel .ic { margin-top: 1px; }
}
@media (pointer: coarse) {
  .slots button, .picker button, .seg button, .hacts .btn, .tfoot .btn, .class .btn { min-height: 44px; }
}

.ctitle { margin: 4px 0 10px; font-size: 20px; font-weight: 600; text-align: center; }
.classes { display: grid; gap: 10px; }
.class { display: grid; justify-items: center; gap: 4px; padding: 14px; text-align: center; background: var(--card); border: var(--line-w) solid var(--ink); border-radius: var(--r-card); }
.class .cicon { width: 34px; height: 34px; margin-inline: auto; }
.class b { font-size: 19px; font-weight: 600; }
.class p { margin: 0; color: var(--soft); font-size: 14px; }
.class .mini { justify-content: center; }
.class small { color: var(--soft); font-size: 13px; }
.class .btn { margin-top: 6px; }
@media (min-width: 560px) { .classes { grid-template-columns: repeat(3, 1fr); } }
body[data-mode="skills"] .side { display: none; }
body[data-mode="skills"] .status:empty { display: none; }

footer .credit { margin-top: 6px; font-size: 12.5px; display: flex; gap: 6px; justify-content: center; align-items: center; flex-wrap: wrap; }
footer .credit a { color: var(--soft); }
footer .made-by { display: inline-flex; align-items: center; gap: 5px; }
footer .made-by img { width: 18px; height: auto; display: block; }
/* reduced motion: the plates' bars and the xp bar jump to their new width. Here at the end, after the rules that set the slide */
@media (prefers-reduced-motion: reduce) { .pep i, .spk span, .xpbar i { transition: none; } }
