/* The camp's in-game window and walk-up prompts (hub.js): one warm wood window (UI round A, "Lantern", Colin's pick:
   oak frame, walnut body, honey bevel; .maestri art/2's palette) with four tabs, Wardrobe · Codex · Board · Settings,
   plus the "E · Verb" bubbles over buildings.
   Barnaby's trading post (shop.js) wears the same window, so the slot, pane and button rules here serve both (the
   trading post has no footer, and shop.css scales these parts with the screen).
   Pixel rules (docs/research/game-shop-ui/README.md): flat fills, 1-art-pixel stepped corners instead of rounded ones, no blur
   or glow, no scaling on hover. A slot shows an icon and at most one number, and gold means one thing: the cursor. */

:root {
  --u: 2px;                                    /* one art pixel of the window chrome */
  --win: #62321d;                              /* walnut, opaque: the title buttons behind the window mustn't show through */
  --win-edge: #321007;
  --win-hi: rgba(234, 183, 109, 0.30);         /* the honey bevel just inside the edge */
  --win-in: rgba(50, 16, 7, 0.30);             /* the body, and the selected tab that opens onto it */
  --win-ink: #f4d995;                          /* words on the wood */
  /* a slot on the wood: dark oak, so every panel's light words read on it */
  --slot-bg: rgba(74, 36, 18, 0.94);
  --slot-lit: rgba(110, 57, 31, 0.97);         /* under the mouse */
  --slot-edge: #2a0d04;
  --slot-ring: rgba(234, 183, 109, 0.20);
  /* the A look's parchment rows, which a section opts into with .parch: cream paper, dark brown words, no outline */
  --parch: #f1d6a7;
  --parch-lit: #f6daaf;                        /* under the mouse */
  --parch-edge: #522919;
  --parch-ink: #321007;
  --parch-ink-dim: #7a4a2a;
  /* buttons: amber wood */
  --amber: #a25522; --amber-hi: #c47a42; --amber-lo: #5b2510;
  /* the textures under the fills (GPT Image 2.5, tiled at 128px): background: var(--parch-tex) 0 0 / 128px, var(--parch) */
  --wood-tex: url(art/ui/wood.webp);
  --parch-tex: url(art/ui/parchment.webp);
  --ok: #8fe36a;
  --short: #ff9696;                            /* a price you can't pay yet */
  /* square corners with one art pixel cut out of each: the pixel-art rounded rectangle */
  --notch: polygon(var(--u) 0, calc(100% - var(--u)) 0, calc(100% - var(--u)) var(--u), 100% var(--u), 100% calc(100% - var(--u)),
    calc(100% - var(--u)) calc(100% - var(--u)), calc(100% - var(--u)) 100%, var(--u) 100%, var(--u) calc(100% - var(--u)), 0 calc(100% - var(--u)),
    0 var(--u), var(--u) var(--u));
  --notch-top: polygon(var(--u) 0, calc(100% - var(--u)) 0, calc(100% - var(--u)) var(--u), 100% var(--u), 100% 100%, 0 100%, 0 var(--u), var(--u) var(--u));
  --ring: inset 0 0 0 var(--u) var(--slot-edge), inset 0 0 0 calc(var(--u) * 2) var(--slot-ring);
  --ring-on: inset 0 0 0 var(--u) var(--gold), inset 0 0 0 calc(var(--u) * 2) var(--win-edge);
}

/* ---------- in the world (the prompts round, Colin's pick: C's place on the ground, B's lettering) ---------- */
/* The "what to do" prompts (hub.js; world.js's path sign and coop.js's dig spots use the same look): small outlined
   words like the name tags, with the key as a gold [E] before them and no box. One you can use lies on the ground under
   its place (data-at="ground": the building or the dig spot, below everyone's feet), so it never meets a name, a bubble
   or an emote; a far building's name stays on the building, smaller and without a key (data-at="sign"). They step aside
   while the miner moves (hub.js adds .away on the change). The plank and stone colours stay for the touch pad below,
   the boards and the lake's Emotes button. */
:root {
  --plank: #8f5a30; --plank-hi: #b98048; --plank-lo: #643a1c; --plank-rim: #1c0e05; --plank-ink: #fff3d6;
  --stone: #a3a9b3; --stone-hi: #d2d7df; --stone-lo: #6c717b;
}
#app.hub-hover #world-canvas { cursor: pointer; }
.hub-prompt { translate: -50% -100%; display: flex; flex-direction: column; align-items: center; gap: 1px; pointer-events: auto; z-index: 2; transition: opacity .15s; }
.hub-prompt[data-at="ground"] { translate: -50% 0; }
.hub-prompt[hidden] { display: none; }
.hub-prompt.away { opacity: 0; pointer-events: none; }
/* pinned elements are placed with an inline transform (rock.js), so their own animations only touch opacity, scale or
   a child: an animated transform would override the placement */
.hub-prompt.in { animation: hub-pop .14s cubic-bezier(0, 0, .2, 1); }
.hub-prompt button { position: relative; display: block; padding: 2px 3px; border: 0; border-radius: 0; background: none; cursor: pointer;
  font: 700 0.95rem/1.15 var(--f-label); color: #fff6dc; text-shadow: var(--ol1), 0 2px 0 rgba(0, 0, 0, 0.45); white-space: nowrap; }
.hub-prompt button:hover, .hub-prompt button:focus-visible { color: var(--gold); }
.hub-prompt b { color: inherit; }
/* shop.css gives every kbd a keycap: none of that here */
.hub-prompt kbd { display: inline; min-width: 0; padding: 0; margin: 0 5px 0 0; border: 0; border-radius: 0; background: none; box-shadow: none;
  vertical-align: 1px; font: 700 0.95rem/1 var(--f-label); color: var(--gold); text-shadow: var(--ol1), 0 2px 0 rgba(0, 0, 0, 0.45); }
.hub-prompt kbd::before { content: "["; }
.hub-prompt kbd::after { content: "]"; }
.hub-prompt[data-at="sign"] button { font-size: 0.85rem; color: #e8dcc0; }
/* touch: no key letters (a tap is the way), slightly bigger words, a thin gold underline that says they're tappable,
   and the target a finger needs (44 px), invisible, round the words (a mouse gets the words alone) */
html[data-input="touch"] .hub-prompt kbd { display: none; }
html[data-input="touch"] .hub-prompt button::after { content: ""; position: absolute; top: 50%; left: 50%; width: max(100%, 44px); height: max(100%, 44px); translate: -50% -50%; }
html[data-input="touch"] .hub-prompt button { font-size: 1.05rem; text-decoration: underline 2px rgba(255, 225, 74, 0.85); text-underline-offset: 4px; }
html[data-input="touch"] .hub-prompt[data-at="sign"] button { font-size: 0.95rem; }
/* two choices (the headframe's digs, a dig spot's two digs) stand 44 px apart, middle to middle, so no tap lands on both */
html[data-input="touch"] .hub-prompt button + button { margin-top: 22px; }
@keyframes hub-pop { from { opacity: 0; scale: .9; } }

/* ---------- the touch pad: touch only, never by screen size (pad.js names the input on <html data-input>) ---------- */
/* a laptop's keyboard, mouse or controller never sees it; a tablet does, and so does a touchscreen PC once it's touched */
.touch-pad, .touch-pad button.use, .touch-pad button.dive { display: none; }
html[data-input="touch"] #app[data-screen="surface"] .touch-pad { display: flex; position: absolute; left: 12px; right: 12px; bottom: calc(env(safe-area-inset-bottom, 0px) + 12px);
  justify-content: space-between; pointer-events: none; z-index: 1; }
html[data-input="touch"] .touch-pad button { pointer-events: auto; width: 54px; height: 54px; border: 0; border-radius: 0; clip-path: var(--notch); background: var(--plank);
  box-shadow: inset 0 0 0 2px var(--plank-rim), inset 0 4px 0 var(--plank-hi), inset 0 -4px 0 var(--plank-lo); color: var(--plank-ink);
  font: 700 1.3rem/1 var(--f-label); text-shadow: 0 2px 0 var(--plank-rim); touch-action: none; user-select: none; -webkit-user-select: none; }
html[data-input="touch"] .touch-pad button:active { background: var(--plank-lo); }
html[data-input="touch"] .touch-pad button + button:not(.jump) { margin-left: 8px; margin-right: auto; }
/* the use button lights up green at a building; the dive button shows while flying */
html[data-input="touch"] #app[data-screen="surface"] .touch-pad button.use.ready { display: block; position: absolute; right: 64px; bottom: 0; margin: 0; background: #5f7d2c;
  box-shadow: inset 0 0 0 2px #1d2a0c, inset 0 4px 0 #86a84a, inset 0 -4px 0 #44591e; }
html[data-input="touch"] #app[data-screen="surface"].aloft .touch-pad button.dive { display: block; position: absolute; right: 64px; bottom: 0; margin: 0; }
/* the title's dig words sit above the pad */
html[data-input="touch"] #app[data-screen="surface"] .hero-dock { margin-bottom: 70px; }

/* ---------- the window: the tabs and × in one row, then the body ---------- */
.hub { padding: 0; border: 0; background: transparent; color: var(--ink); overflow: visible;
  width: min(calc(1060px * var(--ui, 1)), calc(100vw - 20px)); height: min(calc(720px * var(--ui, 1)), calc(100dvh - 20px)); max-width: none; max-height: none; }
.hub::backdrop { background: rgba(20, 8, 2, 0.6); }
.hub-panel { position: relative; display: grid; grid-template: auto minmax(0, 1fr) auto / minmax(0, 1fr) auto; height: 100%; overflow: hidden;
  background: var(--win); clip-path: var(--notch); box-shadow: inset 0 0 0 var(--u) var(--win-edge), inset 0 0 0 calc(var(--u) * 2) var(--win-hi); }
.hub[open] .hub-panel { animation: hub-in .16s cubic-bezier(0, 0, .2, 1); }
@keyframes hub-in { from { opacity: 0; transform: translateY(6px); } }
/* the selected tab names the panel, so the title is for screen readers only */
.hub-head { display: contents; }
/* a parchment slot (the A look's rows): sections opt in with .parch; .on, or focus, is the cursor's gold ring */
.parch { background: var(--parch-tex) 0 0 / 128px, var(--parch); color: var(--parch-ink); text-shadow: none; clip-path: var(--notch);
  box-shadow: inset 0 0 0 var(--u) var(--parch-edge), inset 0 calc(var(--u) * -2) 0 var(--u) rgba(122, 74, 42, 0.25); }
.parch:hover { background-color: var(--parch-lit); }
.parch.on, .parch:focus-visible { outline: none; box-shadow: inset 0 0 0 var(--u) var(--parch-edge), inset 0 0 0 calc(var(--u) * 2) var(--gold), inset 0 0 0 calc(var(--u) * 3) var(--parch-edge); }
.hub-sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
/* the camp window (UI round A, "Lantern", Colin's pick): one header row, the four tabs (or a tabless window's title) and
   ×; the codex's Ores · Landmarks switch under it when open; then the body. No title bar, building name, coin count or
   key hints. Scoped to #hub: the trading post wears the same frame with its own header (shop.css). */
#hub .hub-panel { grid-template: auto auto minmax(0, 1fr) / minmax(0, 1fr); padding: 0 calc(var(--u) * 4) calc(var(--u) * 4);
  background: var(--wood-tex) 0 0 / 128px, var(--win);
  box-shadow: inset 0 0 0 var(--u) var(--win-edge), inset 0 0 0 calc(var(--u) * 2) var(--win-hi), inset 0 0 0 calc(var(--u) * 3) var(--win-edge); }
#hub .hub-head { grid-area: 1 / 1; display: flex; align-items: flex-end; gap: 8px; min-width: 0; padding: 12px 52px 0 4px; }
#hub .hub-where { display: none; align-self: center; min-width: 0; padding: 4px 4px 8px; }
#hub.tabless .hub-where { display: block; }
#hub .hub-where h2 { margin: 0; font: 700 1.35rem/1.1 var(--f-label); color: var(--win-ink); text-shadow: var(--ol); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
#hub .hub-tabs { flex: 1; padding: 0; gap: 4px; }
#hub .hub-tab { padding: 11px 18px 12px; clip-path: var(--notch); color: var(--ink-dim); background: rgba(50, 16, 7, 0.45); box-shadow: inset 0 0 0 var(--u) var(--win-edge); }
#hub .hub-tab:hover { color: var(--gold); }
#hub .hub-tab[aria-selected="true"] { clip-path: var(--notch-top); padding-bottom: 16px; margin-bottom: -4px; color: var(--gold); background: var(--win-in);
  box-shadow: inset var(--u) var(--u) 0 var(--win-edge), inset calc(var(--u) * -1) 0 0 var(--win-edge); }
/* the codex's switch: two small pills over the body */
#hub .hub-sub { grid-area: 2 / 1; display: flex; gap: 4px; margin-top: 4px; padding: 10px 14px 0; background: var(--win-in); }
#hub .hub-sub[hidden] { display: none; }
.hub-subtab { min-height: 40px; padding: 0 16px; border: 0; border-radius: 0; clip-path: var(--notch); background: transparent; cursor: pointer;
  font: 700 1rem/1 var(--f-label); color: var(--ink-dim); text-shadow: var(--ol1); }
.hub-subtab:hover { color: var(--gold); }
.hub-subtab[aria-pressed="true"] { background: var(--amber); color: var(--win-ink); box-shadow: inset 0 calc(var(--u) * -2) 0 var(--amber-lo), inset 0 0 0 var(--u) var(--win-edge); }
#hub .hub-body { grid-area: 3 / 1; margin: 4px 0 0; box-shadow: inset 0 0 0 var(--u) var(--win-edge); }
#hub .hub-sub:not([hidden]) + .hub-body { margin-top: 0; }
#hub .menu-close { top: 12px; right: 12px; }
/* a short window with no tab (Account, Music: SECTIONS fit) is only as tall as what's in it (fit-content: an open dialog is
   pinned to every edge, so plain auto would stretch it), centred, up to the usual cap, and
   scrolls past that; phones keep the full screen */
@media (min-width: 761px) and (min-height: 501px) {
  #hub.fit { width: min(calc(720px * var(--ui, 1)), calc(100vw - 20px)); height: fit-content; max-height: min(calc(720px * var(--ui, 1)), calc(100dvh - 20px)); }
  #hub.fit .hub-panel { height: auto; max-height: inherit; grid-template-rows: auto auto minmax(0, auto); }
  #hub.fit .hub-body { overflow-y: auto; }
}
.hub-tabs { grid-area: 1 / 1; display: flex; align-items: flex-end; gap: 2px; min-width: 0; padding: 10px 8px 0 12px; overflow-x: auto; scrollbar-width: none; }
.hub-tab { position: relative; flex: none; min-height: 44px; padding: 10px 16px 12px; border: 0; border-radius: 0; background: transparent; cursor: pointer; clip-path: var(--notch-top);
  font: 700 1.08rem/1 var(--f-label); color: #fff; text-shadow: var(--ol1); }
.hub-tab:hover { color: var(--gold); }
.hub-tab[aria-selected="true"] { background: var(--win-in); color: var(--gold); }
.hub-tab-break { display: none; }
/* the trading post's balance (shop.js; the camp window shows no coins) */
.hub-coins { grid-area: 1 / 2; align-self: center; display: flex; align-items: center; gap: 6px; margin: 10px 60px 0 8px; padding: 1px 6px; border: 0; background: none;
  font: 700 1.25rem/1 var(--f-label); color: var(--gold); text-shadow: var(--ol); font-variant-numeric: tabular-nums; white-space: nowrap; }
button.hub-coins { cursor: pointer; }
button.hub-coins:hover { color: #fff; }
.hub-coins .coin-ico { width: max(35px, calc(35px / var(--ui, 1))); height: max(30px, calc(30px / var(--ui, 1))); vertical-align: 0; }
.hub .menu-close { top: 10px; right: 10px; width: 40px; height: 40px; border: 0; border-radius: 0; clip-path: var(--notch); background: var(--amber); cursor: pointer;
  box-shadow: inset 0 calc(var(--u) * -2) 0 var(--amber-lo), inset 0 0 0 var(--u) var(--win-edge); font: 700 1.5rem/1 var(--f-label); color: var(--win-ink); text-shadow: var(--ol1); }
.hub .menu-close:hover { color: var(--gold); background: var(--amber-hi); }
.hub-body { grid-area: 2 / 1 / 3 / 3; position: relative; min-height: 0; margin: 0 calc(var(--u) * 2); background: var(--win-in); }


/* ---------- controller glyphs (pad.js names them for the connected pad's family) ---------- */
.pad { display: inline-grid; place-items: center; min-width: 1.7em; height: 1.7em; padding: 0 5px; margin: 0 1px; border-radius: 999px; border: 2px solid #000;
  background: #5b2e17; box-shadow: inset 0 -2px 0 rgba(0, 0, 0, 0.35); font: 700 0.72rem/1 var(--f-label); color: #fff; text-shadow: none; vertical-align: middle; }
.pad-lb, .pad-rb, .pad-start { border-radius: 7px; font-size: 0.66rem; }
.pad-dpad { font-size: 0.9rem; }
.pad-a.pad-xbox { background: #3e9b39; } .pad-b.pad-xbox { background: #c7372f; } .pad-x.pad-xbox { background: #2d6cd1; } .pad-y.pad-xbox { background: #d9a400; color: #2a1a00; }
.pad-a.pad-ps { color: #8fb4ff; } .pad-b.pad-ps { color: #ff8f8f; } .pad-x.pad-ps { color: #ff9ad9; } .pad-y.pad-ps { color: #7fe3b8; }
.hub-prompt .pad { margin-right: 4px; }
/* the controller's cursor on anything outside the camp's window (menu, dig buttons) */
html[data-input="pad"] #app button:focus, html[data-input="pad"] #app a:focus, html[data-input="pad"] #app input:focus { outline: 3px solid var(--gold); outline-offset: 2px; }

/* ---------- shared parts: scrolling, split view, notes ---------- */
.hub-scroll { overflow-y: auto; overscroll-behavior: contain; min-height: 0; scrollbar-width: thin; scrollbar-color: rgba(244, 217, 149, 0.45) transparent; }
.hub-split { display: grid; height: 100%; min-height: 0; }
.hub-split > * { min-height: 0; padding: 14px 18px 18px; }
.hub-split > article { box-shadow: inset var(--u) 0 0 var(--win-edge); background: rgba(40, 14, 5, 0.22); }
/* a heading inside a page (the codex's "Unlocks in the wardrobe", the racks' kind, the board's "Earning XP"); its own
   class, so the window's Ores · Landmarks switch (#hub .hub-sub) never styles it */
.pg-h { display: flex; align-items: baseline; gap: 8px; margin: 16px 0 8px; font: 700 1rem/1.2 var(--f-label); color: var(--win-ink); text-shadow: var(--ol1); }
.pg-h small { font-size: 0.8rem; color: var(--ink-faint); }
.hub-note { margin: 12px 0 0; font: 600 0.88rem/1.4 var(--f-text); color: var(--ink-faint); text-shadow: var(--ol1); }
.hub p { text-shadow: var(--ol1); }
/* small labels inside panels read as plain lines, not shouty tags */
.hub .kicker { margin: 0 0 4px; font: 700 0.85rem/1.2 var(--f-label); letter-spacing: 0; text-transform: none; color: var(--ink-faint); text-shadow: var(--ol1); }
.hub em, .hub i:not(.rar):not(.check):not(.badge) { font-style: normal; }
.hub, .hub * { font-synthesis: none; }
.hub-link { padding: 0; border: 0; background: none; cursor: pointer; font: 700 1em/1.2 var(--f-label); color: var(--gold); text-shadow: var(--ol1); text-decoration: underline; text-underline-offset: 3px; }
.hub-link:hover { color: #fff; }
.coin-val, .coins { display: inline-flex; align-items: center; gap: 4px; }
.coins b { color: var(--gold); font-variant-numeric: tabular-nums; }

/* ---------- buttons inside windows: flat blue (green for the main action), a pixel bevel, gold text on hover ---------- */
.hub .btn { display: inline-flex; align-items: center; justify-content: center; gap: 6px; min-height: 44px; padding: 10px 16px; border: 0; border-radius: 0; clip-path: var(--notch);
  background: #a25522; box-shadow: inset 0 0 0 var(--u) var(--win-edge), inset 0 calc(var(--u) * 2) 0 rgba(255, 255, 255, 0.18), inset 0 calc(var(--u) * -2) 0 rgba(0, 0, 0, 0.3);
  font: 700 1.05rem/1 var(--f-label); color: #fff; text-shadow: var(--ol1); transform: none; transition: none; cursor: pointer; }
.hub .btn:hover { color: var(--gold); transform: none; }
.hub .btn:active { transform: none; box-shadow: inset 0 0 0 var(--u) var(--win-edge), inset 0 calc(var(--u) * 2) 0 rgba(0, 0, 0, 0.3); }
.hub .btn.primary { background: #347a22; }
.hub .btn.small { min-height: 36px; padding: 7px 12px; font-size: 0.95rem; }
.hub .btn.ghost { background: transparent; box-shadow: none; }
.hub .btn:focus-visible, html[data-input="pad"] .hub .btn:focus { outline: none; box-shadow: var(--ring-on); }
.hub .btn .coins b { color: var(--gold); }

/* ---------- slots: one look for ores, wares and wardrobe pieces ---------- */
.slot, .cx-slot, .wr-tile { --tc: #fff; position: relative; display: grid; place-items: center; padding: 0; border: 0; border-radius: 0; clip-path: var(--notch);
  background: var(--slot-bg); box-shadow: var(--ring); color: #fff; cursor: pointer; }
button.slot:hover, .cx-slot:hover, .wr-tile:hover { background: var(--slot-lit); }
.pa { position: relative; display: block; flex: none; overflow: hidden; }
.pa > img { position: absolute; left: 0; top: 0; width: 100%; height: 100%; object-fit: contain; image-rendering: pixelated; }
/* the count (or price) sits bottom-left, like a stack in a Terraria inventory */
.slot .n, .cx-slot .n { position: absolute; left: 5px; bottom: 5px; font: 700 0.85rem/1 var(--f-label); color: #fff; text-shadow: var(--ol1); font-variant-numeric: tabular-nums; pointer-events: none; }
.slot .badge, .wr-tile .check { position: absolute; top: 4px; right: 5px; font: 700 0.85rem/1 var(--f-label); font-style: normal; color: var(--ok); text-shadow: var(--ol1); pointer-events: none; }
.slot .rar, .wr-tile .rar { position: absolute; left: calc(var(--u) * 2); right: calc(var(--u) * 2); bottom: calc(var(--u) * 2); height: var(--u); background: var(--r, transparent); pointer-events: none; }
.slot.mythic, .cx-slot.mythic { box-shadow: inset 0 0 0 var(--u) var(--slot-edge), inset 0 0 0 calc(var(--u) * 2) color-mix(in srgb, var(--tc) 55%, transparent); }
.slot.mythic:not(.none), .cx-slot.mythic.struck { animation: myth-ring 1.6s steps(1) infinite; }
@keyframes myth-ring { 50% { box-shadow: inset 0 0 0 var(--u) var(--slot-edge), inset 0 0 0 calc(var(--u) * 2) color-mix(in srgb, var(--tc) 90%, #fff); } }
.slot.none { cursor: default; }
.slot.none .pa img { filter: brightness(0) opacity(0.4); }
/* Locked art stays readable: an ore not struck yet is its own picture in dim grey with a "?" over it, and a locked
   wardrobe piece is a pale silhouette (black ones vanished into the navy slots). */
.cx-slot.locked img { filter: grayscale(1) brightness(0.55) opacity(0.6); }
.wr-tile.locked > img { filter: brightness(0) invert(1) opacity(0.3); }
.cx-row.locked::before, .cx-hero.locked .cx-art::after { content: "?"; position: absolute; display: grid; place-items: center; pointer-events: none;
  font: 700 1.25rem/1 var(--f-label); color: #fff; text-shadow: var(--ol1); }
.cx-row.locked::before { left: 8px; top: 0; bottom: 0; width: 36px; }
/* gold means one thing: the slot the cursor is on */
.slot.sel, .slot:focus-visible, .hub [data-nav]:focus, html[data-input="pad"] .hub .slot:focus { outline: none; box-shadow: var(--ring-on); animation: none; z-index: 1; }
.slot.shake, .wr-tile.shake { animation: hub-shake .18s steps(3) 1; }
@keyframes hub-shake { 33% { translate: calc(var(--u) * -1) 0; } 66% { translate: var(--u) 0; } }

/* ---------- Barnaby's rewards box (rewardsBox in hub.js), above the codex and the landmarks ---------- */
/* a parchment strip (the Lantern UI): what he owes you with one green Claim, and the next milestone */
.rw { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 8px 12px; margin-top: 12px; padding: 8px 12px; }
.rw:empty { display: none; }
.rw p { margin: 0; font: 700 0.98rem/1.3 var(--f-label); color: var(--parch-ink-dim); text-shadow: none; }
.rw b { color: var(--parch-ink); }
.rw .rw-next, .rw .rw-note { flex-basis: 100%; font-size: 0.95rem; }
.rw .rw-note { color: #2f6b1c; }
.rw .coin-ico, .cx-mastery .coin-ico, .cx-facts .coin-ico { vertical-align: -2px; }
.nw { white-space: nowrap; }
/* claim buttons are green: gold means the cursor */
.hub .rw-claim { display: inline-flex; align-items: center; gap: 4px; min-height: 40px; background: #4f8f2a; color: #fff1d6;
  box-shadow: inset 0 calc(var(--u) * -2) 0 #2b5a14, inset 0 0 0 var(--u) var(--win-edge); }
.hub .rw-claim .coins b, .hub .cx-mastery .coins b { color: inherit; }
.hub-coins.pay, .coin-chip.pay { animation: hub-pay .4s steps(4); }
@keyframes hub-pay { 50% { color: #fff; } }

/* parchment in the codex (the Lantern UI): a row, a card or a chip reads dark ink on cream; .parch (above) gives the
   fill, these win over .slot's dark fill, and the cursor is the same gold ring as the wardrobe's rows */
.hub .cx-row.parch, .hub .gear-chip, .hub .ore-chip, .hub .lm-band { background: var(--parch-tex) 0 0 / 128px, var(--parch); color: var(--parch-ink); text-shadow: none;
  box-shadow: inset 0 0 0 var(--u) var(--parch-edge); }
.hub .cx-row.parch:hover, .hub .gear-chip:hover, .hub .ore-chip:hover, .hub .lm-band:hover { background: var(--parch-lit); }
.hub .cx-row.parch:focus, .hub .gear-chip:focus-visible, .hub .ore-chip:focus-visible, .hub .lm-band:focus, html[data-input="pad"] .hub .lm-band:focus {
  outline: none; box-shadow: inset 0 0 0 var(--u) var(--parch-edge), inset 0 0 0 calc(var(--u) * 2) var(--gold), inset 0 0 0 calc(var(--u) * 3) var(--parch-edge); }
.cx-card { clip-path: var(--notch); background: var(--parch-tex) 0 0 / 128px, var(--parch); box-shadow: inset 0 0 0 var(--u) var(--parch-edge); color: var(--parch-ink); }

/* ---------- ore codex ---------- */
.cx { grid-template-columns: minmax(300px, 0.85fr) 1.15fr; }
/* the codex (design round 4, option B): the count and rewards pinned, the ladder of ores scrolling under them */
.cx .cx-index { display: flex; flex-direction: column; min-height: 0; overflow: hidden; padding-bottom: 0; }
.cx-count { margin: 0; font: 700 1.05rem/1.2 var(--f-label); color: var(--ink-dim); text-shadow: var(--ol1); }
.cx-count b { font: 700 1.3rem/1 var(--f-num, system-ui, "Segoe UI", sans-serif); color: var(--win-ink); font-variant-numeric: tabular-nums; }
.cx-count .cx-num { font-family: var(--f-num, system-ui, "Segoe UI", sans-serif); }   /* numbers in --f-num: Mali's 7 reads as a ? */
.cx-list { flex: 1; min-height: 0; display: grid; align-content: start; gap: 4px; margin-top: 12px; padding-bottom: 14px; scroll-snap-type: y proximity; }
.cx-list > * { scroll-snap-align: start; }   /* the list never rests on half a row */
.cx-zone { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; margin: 10px 0 2px; padding-left: 10px; box-shadow: inset 3px 0 0 var(--zc); }
.cx-zone:first-child { margin-top: 0; }
.cx-zone b { font: 700 0.98rem/1.2 var(--f-label); color: var(--win-ink); text-shadow: var(--ol1); }
.cx-zone small { font: 700 0.88rem/1.2 var(--f-label); color: var(--ink-dim); text-shadow: var(--ol1); }
.cx-zone.myth b { color: #d9b8ff; }
/* a row per ore; one you've struck wears its ore's colour as a stripe down its left edge */
.hub .cx-slot.cx-row { width: 100%; height: 50px; display: grid; grid-template-columns: 36px minmax(0, 1fr) auto; place-items: center start; gap: 12px; padding: 0 14px 0 10px; text-align: left; animation: none; }
.hub .cx-row.parch.struck { box-shadow: inset 0 0 0 var(--u) var(--parch-edge), inset calc(var(--u) * 3) 0 0 var(--tc); }
.cx-row img { width: 34px; height: 34px; object-fit: contain; image-rendering: pixelated; }
.cx-nm { display: grid; gap: 4px; min-width: 0; }
.cx-nm b { font: 700 1.05rem/1 var(--f-label); color: var(--parch-ink); text-shadow: none; }
.cx-row.locked .cx-nm b { color: var(--parch-ink-dim); }
.cx-nm small { font: 700 0.9rem/1 var(--f-num, system-ui, "Segoe UI", sans-serif); color: var(--parch-ink-dim); text-shadow: none; }
.cx-n { justify-self: end; font: 700 1.05rem/1 var(--f-num, system-ui, "Segoe UI", sans-serif); color: var(--parch-ink); text-shadow: none; font-variant-numeric: tabular-nums; }
.cx-row.mastered::after { content: "★"; position: absolute; top: 4px; right: 6px; font: 700 0.75rem/1 var(--f-label); color: var(--amber); text-shadow: none; }
.hub .cx-row.locked::before { color: var(--parch-ink); text-shadow: none; }
.cx-src { margin-top: 10px; }
.cx-src a { color: var(--win-ink); }
/* Barnaby's hint at the Holy Ore: quiet, in the reading face (no italics in the camp window) */
.cx-hint { margin: 10px 0 0; font: 400 1rem/1.4 var(--f-text, var(--f-body)); color: var(--ink-dim); text-shadow: none; }
/* mastery pips: filled in the ore's colour; empty ones are outlined, so a grey ore's full pips never read as empty */
.cx-pips { display: inline-flex; gap: 3px; }
.cx-pips i { width: 12px; height: 12px; background: rgba(82, 41, 25, 0.16); box-shadow: inset 0 0 0 1px rgba(82, 41, 25, 0.55); }
.cx-pips i.on { background: var(--tc, #fff); box-shadow: inset 0 0 0 1px var(--parch-edge); }
.cx-pips.small i { width: 8px; height: 8px; }
.cx-page { --tc: #fff; }
.cx-hero { display: grid; grid-template-columns: 112px 1fr; gap: 16px; align-items: center; }
.cx-art { width: 112px; height: 112px; display: grid; place-items: center; }
.cx-art img { width: 96px; height: 96px; object-fit: contain; image-rendering: pixelated; }
.cx-hero.locked .cx-art { position: relative; }
.cx-hero.locked .cx-art img { filter: grayscale(1) brightness(0.55) opacity(0.6); }
.cx-hero.locked .cx-art::after { inset: 0; font-size: 2.6rem; color: var(--parch-ink); text-shadow: none; }
.cx-hero.mythic .cx-art { box-shadow: inset 0 0 0 var(--u) var(--parch-edge), inset 0 0 0 calc(var(--u) * 2.5) color-mix(in srgb, var(--tc) 70%, var(--parch-edge)); }
.cx-rank { margin: 0 0 2px; font: 700 0.95rem/1.2 var(--f-num, system-ui, "Segoe UI", sans-serif); color: var(--ink-dim); text-shadow: var(--ol1); }
.cx-name { margin: 0; font: 700 2.1rem/1 var(--f-label); text-shadow: var(--ol); }
.cx-line { margin: 6px 0 0; font: 600 1rem/1.4 var(--f-text, var(--f-body)); font-style: normal; color: var(--ink-dim); }
/* your strikes, then the facts: two parchment cards */
.cx-mine { display: grid; gap: 8px; margin-top: 16px; padding: 12px 14px; }
.cx-mine p { margin: 0; font-family: var(--f-text, var(--f-body)); color: var(--parch-ink-dim); text-shadow: none; }
.cx-mine b { color: var(--parch-ink); }
.cx-mine .cx-struck { font-size: 1.05rem; }
.cx-mastery { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 12px; }
.cx-facts { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); margin: 10px 0; }
.cx-facts > div { display: grid; gap: 3px; padding: 10px 14px; }
.cx-facts > div:nth-child(n + 3) { box-shadow: inset 0 var(--u) 0 rgba(82, 41, 25, 0.25); }
.cx-facts > div:nth-child(even) { border-left: var(--u) solid rgba(82, 41, 25, 0.25); }
.cx-facts dt { font: 700 0.88rem/1.1 var(--f-label); color: var(--parch-ink-dim); text-shadow: none; }
.cx-facts dd { margin: 0; font: 700 1.1rem/1.2 var(--f-num, system-ui, "Segoe UI", sans-serif); color: var(--parch-ink); text-shadow: none; }
.cx-facts .coins b { color: var(--parch-ink); }
.cx-link { padding: 0; border: 0; background: none; cursor: pointer; font: inherit; font-family: var(--f-label); color: var(--amber-lo); text-align: left; text-decoration: underline; text-underline-offset: 3px; text-shadow: none; }
.cx-link:hover { color: var(--amber); }
.cx-lore { max-width: 68ch; margin: 14px 0 0; font: 400 1rem/1.55 var(--f-text, var(--f-body)); color: var(--ink-dim); text-shadow: none; }
.cx-unlocks { display: flex; flex-wrap: wrap; gap: 6px; }
.gear-chip, .ore-chip { display: inline-flex; align-items: center; gap: 6px; min-height: 36px; padding: 4px 10px 4px 6px; border: 0; clip-path: var(--notch); cursor: pointer;
  font: 700 0.88rem/1.2 var(--f-label); }
.gear-chip img { width: 26px; height: 26px; object-fit: contain; image-rendering: pixelated; }
.gear-chip img.tall { object-fit: cover; object-position: top; }
.gear-chip.owned::after { content: "✓"; color: #2f6b1c; }
.ore-chip img { width: 24px; height: 24px; image-rendering: pixelated; }
.hub .ore-chip .ore-name { color: var(--parch-ink) !important; }   /* (hub.js colours ore names for the dark window) */
.ore-chip small { color: var(--parch-ink-dim); }
.ore-chip.locked img { filter: grayscale(1) brightness(0.55) opacity(0.6); }

/* ---------- landmarks ---------- */
.lm { grid-template-columns: minmax(280px, 0.8fr) 1.2fr; }
/* the watchtower (design round 5, option A): your count, Barnaby's rewards, then the shaft of nine painted bands */
.lm-count { margin: 0; font: 700 1.05rem/1.2 var(--f-label); color: var(--ink-dim); text-shadow: var(--ol1); }
.lm-count b { font: 700 1.3rem/1 var(--f-num, system-ui, sans-serif); color: var(--win-ink); font-variant-numeric: tabular-nums; }
.lm-count .lm-num { font-family: var(--f-num, system-ui, sans-serif); }
.lm-col { display: grid; gap: 4px; margin-top: 12px; }
.lm-band { --zc: #fff; position: relative; display: flex; align-items: center; gap: 0; min-height: 50px; padding: 0 14px 0 0; border: 0; clip-path: var(--notch); cursor: pointer; text-align: left; }
/* a strip of the landmark's own painting, edged in its colour; dark until you've dug that deep */
.lm-strip { position: relative; flex: none; align-self: stretch; width: 112px; overflow: hidden; box-shadow: inset calc(var(--u) * -2) 0 0 var(--zc); }
.lm-strip img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.lm-band:not(.reached) .lm-strip img { filter: brightness(0.2) saturate(0); }
.hub .lm-band:not(.reached) { background-color: #e2c696; }
.lm-band .t { display: grid; gap: 3px; flex: 1; padding-left: 14px; }
.lm-band b { font: 700 1.05rem/1.1 var(--f-label); color: var(--parch-ink); text-shadow: none; }
.lm-band small { font: 700 0.88rem/1 var(--f-num, system-ui, sans-serif); color: var(--parch-ink-dim); }
.lm-band:not(.reached) b { color: var(--parch-ink-dim); }
.lm-you { display: inline-flex; flex-direction: column; align-items: center; gap: 1px; }
.lm-you > span { display: block; overflow: hidden; clip-path: var(--notch); }
.lm-you small { font: 700 0.78rem/1 var(--f-label); color: var(--parch-ink); text-shadow: none; }
.lm-q { font: 700 1.1rem/1 var(--f-label); color: var(--parch-ink-dim); text-shadow: none; }
.lm-page { --zc: #fff; }
.lm-art { position: relative; margin: 0 0 12px; clip-path: var(--notch); overflow: hidden; aspect-ratio: 16 / 7; background: var(--well, #5f321d); box-shadow: inset 0 0 0 var(--u) var(--win-edge); }
.lm-art img { width: 100%; height: 100%; object-fit: cover; image-rendering: pixelated; display: block; }
.lm-art.dim img { filter: brightness(0.35) saturate(0.3); }
.lm-art .t { position: absolute; left: 0; right: 0; bottom: 0; padding: 30px 16px 12px; background: linear-gradient(transparent, rgba(40, 14, 5, 0.88)); }
.lm-span { margin: 0 0 4px; font: 700 0.95rem/1.2 var(--f-num, system-ui, sans-serif); color: #fff1d6; text-shadow: var(--ol1); }
.lm-art h3 { margin: 0; font: 700 1.9rem/1 var(--f-label); color: #fff1d6; text-shadow: var(--ol); }
.lm-page > p { max-width: 68ch; margin: 0 0 10px; font: 400 1.02rem/1.55 var(--f-text, var(--f-body)); color: var(--ink-dim); text-shadow: none; }
.lm-page .lm-status { color: var(--win-ink); font-weight: 700; }
.lm-page .lm-fact { padding: 10px 14px; clip-path: var(--notch); background: var(--parch-tex) 0 0 / 128px, var(--parch); box-shadow: inset 0 0 0 var(--u) var(--parch-edge), inset calc(var(--u) * 3) 0 0 var(--zc);
  color: var(--parch-ink); }
.lm-page .lm-reach { margin-top: 12px; }
.lm-ores { display: flex; flex-wrap: wrap; gap: 6px; }
.lm-markers { margin: 14px 0 0; }
.lm-markers summary { cursor: pointer; min-height: 32px; font: 700 1rem/1.6 var(--f-label); color: var(--win-ink); text-shadow: var(--ol1); }
.lm-markers ul { margin: 6px 0 0; padding-left: 1.2em; font: 400 1rem/1.5 var(--f-text, var(--f-body)); color: var(--ink-dim); }
.lm-markers li { margin: 4px 0; }

/* ---------- wardrobe (the Lantern UI, Colin's pick A): your miner on the stage, parchment rows, four buttons ---------- */
.wr { grid-template-columns: minmax(280px, 0.85fr) 1.15fr; }
.wr-stage { display: flex; flex-direction: column; gap: 12px; }
/* --head: the room over the miner's head; a hat taller than that grows the room (--over, profile.js) */
.wr-room { --head: 56px; position: relative; flex: 1; min-height: 250px; display: flex; align-items: flex-end; justify-content: center; padding: var(--head) 0 22px; clip-path: var(--notch);
  overflow: hidden; box-shadow: inset 0 0 0 var(--u) var(--win-edge);
  background: linear-gradient(transparent 76%, #5b3a1f 76%, #4a2e17 82%, #3a2312), linear-gradient(rgba(40, 14, 5, 0.3), rgba(40, 14, 5, 0.5)),
  url("art/pages/banner-customize.webp") center 30% / cover; }
.wr-av { position: relative; margin-top: max(0px, var(--over, 0px) - var(--head)); filter: drop-shadow(0 4px 0 rgba(0, 0, 0, 0.35)); }
.wr-av.pop { animation: hub-hop .12s steps(2) 1; }
.wr-av.secret > * { visibility: hidden; }
.wr-av.secret::after { content: "?"; position: absolute; inset: 0; display: grid; place-items: center; pointer-events: none;
  font: 700 5rem/1 var(--f-label); color: var(--ink-dim); text-shadow: var(--ol); }
@keyframes hub-hop { 50% { translate: 0 calc(var(--u) * -1); } }
.wr-ribbon { position: absolute; top: 12px; right: -34px; rotate: 35deg; padding: 4px 40px; background: #b8322a; box-shadow: 0 2px 0 #000, 0 -2px 0 #000; font: 700 0.8rem/1 var(--f-label);
  color: #fff; text-shadow: var(--ol1); }
.wr-ribbon[hidden] { display: none; }
/* the plate under the stage speaks only in the racks (what a piece is and how to get it): on your look the rows say it */
.wr.creator .wr-plate { display: none; }
.wr-plate .kicker { margin-bottom: 2px; }
.wr-plate h3 { margin: 0; font: 700 1.6rem/1.1 var(--f-label); color: var(--win-ink); text-shadow: var(--ol); }
.wr-status { margin: 6px 0 0; color: var(--ink-dim); font-weight: 600; }
.wr-prog { position: relative; margin-top: 8px; height: 18px; clip-path: var(--notch); background: rgba(40, 14, 5, 0.92); box-shadow: inset 0 0 0 var(--u) var(--win-edge); overflow: hidden; }
.wr-prog[hidden] { display: none; }
.wr-prog i { position: absolute; inset: 0 auto 0 0; background: var(--gold); box-shadow: inset 0 calc(var(--u) * -2) 0 #c98a12; }
.wr-prog span { position: relative; display: block; text-align: center; font: 700 0.75rem/18px var(--f-label); color: #fff; text-shadow: var(--ol1); }
.wr-acts { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 10px; }
.wr-acts:empty { display: none; }
.btn-ore { width: 20px; height: 20px; image-rendering: pixelated; }
/* Random, Undo, Name tag, Every piece: one row of small amber buttons under the rows */
.wr-tools { display: flex; flex-wrap: wrap; gap: 8px; }
.wr .wr-racks .wr-tools { margin-top: 12px; }
.wr-kinds { display: flex; flex-wrap: wrap; gap: 4px; margin-bottom: 10px; }
/* tiles are icon-only parchment slots: the name and how to get it are on the plate */
.wr-grid { display: grid; grid-template-columns: repeat(auto-fill, 64px); gap: 6px; }
.wr-tile { width: 64px; height: 64px; overflow: hidden; }
/* the creator: a parchment row per kind with what you're wearing. Only the row you're on (the cursor, a hover or a tap)
   shows ◀ ▶ and how many you own; a special skin's fixed rows always say Fixed. */
.wr-rows { display: grid; gap: 6px; }
.wr-row { display: grid; grid-template-columns: 52px minmax(0, 1fr) 44px 80px 44px; align-items: center; gap: 8px; min-height: 60px; padding: 4px 10px; outline: none; }
.hub .wr-row:focus, .hub .wr-row:focus-within { box-shadow: inset 0 0 0 var(--u) var(--parch-edge), inset 0 0 0 calc(var(--u) * 2) var(--gold), inset 0 0 0 calc(var(--u) * 3) var(--parch-edge);
  background-color: var(--parch-lit); }
.wr-row .wr-step, .wr-row .wr-count { visibility: hidden; }
.wr-row:focus .wr-step, .wr-row:focus-within .wr-step, .wr-row:focus .wr-count, .wr-row:focus-within .wr-count, .wr-row.fixed .wr-count { visibility: visible; }
.wr-ico { position: relative; display: grid; place-items: center; width: 48px; height: 48px; overflow: hidden; }
.wr-ico img { max-width: 40px; max-height: 40px; object-fit: contain; image-rendering: pixelated; }
.wr-ico img.char { position: absolute; left: 0; top: 0; width: 48px; height: 72px; max-width: none; max-height: none; object-fit: fill; }
.wr-ico img.cloth, .wr-tile.cloth > img { width: 72px; height: 51px; max-width: none; max-height: none; object-fit: fill; }
.wr-none { font: 700 1.3rem/1 var(--f-label); color: var(--parch-ink-dim); }
.wr-txt { display: grid; gap: 3px; min-width: 0; }
.wr-txt small { font: 700 0.88rem/1 var(--f-label); color: var(--parch-ink-dim); text-shadow: none; }
.wr-txt b { font: 700 1.15rem/1.15 var(--f-label); color: var(--parch-ink); text-shadow: none; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.wr-step { width: 40px; height: 40px; justify-self: center; border: 0; clip-path: var(--notch); background: var(--amber); cursor: pointer;
  box-shadow: inset 0 calc(var(--u) * -2) 0 var(--amber-lo), inset 0 0 0 var(--u) var(--win-edge); font: 700 1rem/1 var(--f-label); color: #fff1d6; text-shadow: var(--ol1); }
.wr-step:hover:not(:disabled) { color: var(--gold); background: var(--amber-hi); }
.wr-step:disabled { opacity: 0.35; cursor: default; }
.wr-count { text-align: center; font: 700 0.95rem/1.1 var(--f-num, system-ui, sans-serif); color: var(--parch-ink-dim); text-shadow: none; }
.wr-back { margin-bottom: 10px; }
.wr-kinds small, .wr .pg-h small { font-family: var(--f-num, system-ui, sans-serif); }   /* counts in the number face */

/* (.slot, later in this file, would paint them dark: the racks' tiles are parchment like the rows) */
.hub .wr-tile.parch { background: var(--parch-tex) 0 0 / 128px, var(--parch); box-shadow: inset 0 0 0 var(--u) var(--parch-edge); }
.hub .wr-tile.parch:hover { background: var(--parch-lit); }
.wr-tile > img { width: 48px; height: 48px; object-fit: contain; image-rendering: pixelated; }
.wr-tile.char > img { position: absolute; left: 0; top: 2px; width: 64px; height: 96px; object-fit: fill; }
.wr-tile .nm, .wr-tile .req { display: none; }
.wr-tile .none-ico { display: grid; place-items: center; width: 48px; height: 48px; font: 700 1.6rem/1 var(--f-label); color: var(--parch-ink-dim); }
.wr-tile .none-ico + .nm { display: none; }
.wr-tile.on { background-color: var(--parch-lit); }
.wr-tile .check { color: #2f6b1c; text-shadow: none; }
/* a locked piece is a soft dark silhouette on the parchment */
.wr-tile.parch.locked > img { filter: brightness(0) opacity(0.28); }
/* a secret piece gives nothing away, not even its outline: a "?" where the art would be */
.wr-tile.secret > img { visibility: hidden; }
.wr-tile.secret::before { content: "?"; position: absolute; inset: 0; display: grid; place-items: center; pointer-events: none;
  font: 700 1.6rem/1 var(--f-label); color: var(--parch-ink-dim); text-shadow: none; }
/* Rarity (Colin's pick B, "Frames", 8 Oct 2026): the tile's own frame takes its rarity's colour (darkened from Terraria's
   so each reads on parchment), thicker from uncommon up; epic and legendary add a soft inner rim in their colour, and
   now and then a band of light sweeps across a legendary one (held still with reduced motion). A secret's "???" has no
   rarity. The rows' ◀ ▶ and the racks go common first, legendary last (hub.js pieces()). */
.hub .wr-tile.parch[data-rar] { --rc: var(--parch-edge); --rw: var(--u); box-shadow: inset 0 0 0 var(--rw) var(--rc); }
.hub .wr-tile.parch[data-rar="uncommon"] { --rc: #2f9e44; --rw: calc(var(--u) * 2); }
.hub .wr-tile.parch[data-rar="rare"] { --rc: #2f6fd6; --rw: calc(var(--u) * 2); }
.hub .wr-tile.parch[data-rar="epic"], .hub .wr-tile.parch[data-rar="legendary"] { --rw: calc(var(--u) * 2);
  box-shadow: inset 0 0 0 var(--rw) var(--rc), inset 0 0 0 calc(var(--u) * 3) color-mix(in srgb, var(--rc) 40%, transparent); }
.hub .wr-tile.parch[data-rar="epic"] { --rc: #9b4ddb; }
.hub .wr-tile.parch[data-rar="legendary"] { --rc: #e39a07; }
.wr-tile[data-rar="legendary"]::after { content: ""; position: absolute; inset: 0; pointer-events: none; translate: -110% 0;
  background: linear-gradient(115deg, transparent 38%, rgba(255, 250, 225, 0.75) 50%, transparent 62%); animation: wr-shine 2.8s steps(14) infinite; }
@keyframes wr-shine { 0% { translate: -110% 0; } 50%, 100% { translate: 110% 0; } }
html[data-motion="reduce"] .wr-tile[data-rar="legendary"]::after { animation: none; display: none; }
/* the plate names it in the same colours, lightened to read on the wood */
.wr-plate .kicker[data-rar="common"] { color: #e2d2b8; } .wr-plate .kicker[data-rar="uncommon"] { color: #7ee07e; }
.wr-plate .kicker[data-rar="rare"] { color: #8fb4ff; } .wr-plate .kicker[data-rar="epic"] { color: #d0a4ff; }
.wr-plate .kicker[data-rar="legendary"] { color: #ffc23d; }
.hub .wr-tile.parch:focus, .hub .wr-tile.parch.sel { box-shadow: inset 0 0 0 var(--u) var(--parch-edge), inset 0 0 0 calc(var(--u) * 2) var(--gold), inset 0 0 0 calc(var(--u) * 3) var(--parch-edge); }
.req-ore { width: 18px; height: 18px; image-rendering: pixelated; }

/* ---------- guide and account: plain sections, readable text ---------- */
.gd, .ac { height: 100%; padding: 16px 22px 22px; }
/* the guide (design round 3, option D; the Lantern UI): the main rule and the ore ladder on parchment, three parchment
   steps, then tips and the way into a dig on the wood, the keys folded under one line */
.gd { display: grid; align-content: start; gap: 14px; padding-bottom: 24px; }   /* the last line clears the window's foot */
.gd h3 { margin: 0; font: 700 1.2rem/1.15 var(--f-label); color: var(--win-ink); text-shadow: var(--ol); text-wrap: balance; }
.gd p, .gd li, .gd dd { font: 400 1.02rem/1.45 var(--f-text); color: var(--ink-dim); text-shadow: none; }
.gd p { margin: 0; }
.gd b { color: var(--win-ink); }
/* links are underlined: gold means the cursor */
.gd a:not(.btn) { color: var(--win-ink); text-decoration: underline; text-underline-offset: 3px; }
.gd a:not(.btn):hover { color: var(--gold); }
.gd .pix { image-rendering: pixelated; }
.gd-lead { display: grid; gap: 12px; padding: 14px 16px 12px; }
.gd .parch h3, .gd .parch b { color: var(--parch-ink); text-shadow: none; }
.gd .parch p { color: var(--parch-ink-dim); }
.gd-lead h3 { font-size: 1.45rem; }
.gd-lead-text { display: grid; gap: 4px; }
/* the ladder: every ore commonest first, in runs by landmark, each run as wide as its ores */
/* each landmark as wide as its ores, but never narrower than its two-word name: when a row gets tight it wraps rather
   than squeezing "Magma Mantle" into one ore's width */
.gd-ladder { display: flex; flex-wrap: wrap; gap: 6px 2px; }
.gd-run { flex: var(--n, 1) 1 0; min-width: max(calc(var(--n, 1) * 34px), 84px); display: grid; gap: 4px; align-content: start; }
.gd-ores { display: grid; grid-template-columns: repeat(var(--n, 1), minmax(0, 1fr)); gap: 2px; padding: 4px 0; background: rgba(82, 41, 25, 0.12); box-shadow: inset 0 calc(var(--u) * -2) 0 var(--zc); }
.gd-run.myth .gd-ores { background: rgba(110, 70, 200, 0.14); }
.gd-ore { display: grid; place-items: center; min-width: 0; }
.gd-ore small { display: none; }
.gd-ores img { justify-self: center; width: min(36px, 90%); height: auto; aspect-ratio: 1; object-fit: contain; }
.gd-zone { font: 700 0.85rem/1.1 var(--f-label) !important; color: var(--parch-ink-dim) !important; text-shadow: none !important; text-align: center; }
.gd-run.myth .gd-zone { color: #6b3fa0 !important; }
.gd-steps { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 10px; }
.gd-step { position: relative; display: grid; grid-template-rows: auto auto 1fr; gap: 6px; padding: 10px 14px 12px; }
.gd-n { position: absolute; top: 8px; left: 10px; font: 700 1rem/1 var(--f-num); color: var(--parch-ink-dim); }
.gd-fig { display: grid; place-items: center; height: 58px; }
.gd-step h3 { font-size: 1.1rem; }
/* little copies of the dig's own parts */
.gd-ask { display: grid; gap: 2px; padding: 7px 14px; clip-path: var(--notch); background: var(--wood-tex) 0 0 / 128px, var(--win); box-shadow: inset 0 0 0 var(--u) var(--win-edge); text-align: center; }
.gd-ask small { font: 700 0.85rem/1 var(--f-num); color: var(--ink-dim); }
.gd .gd-ask b { font: 700 1.05rem/1.1 var(--f-label); color: var(--win-ink); text-shadow: var(--ol1); }
.gd-answer { display: flex; clip-path: var(--notch); background: var(--parch-lit); box-shadow: inset 0 0 0 var(--u) var(--parch-edge); }
.gd-answer span { padding: 8px 12px; font: 700 1.05rem/1 var(--f-label); color: var(--parch-ink); min-width: 7ch; }
.gd-answer i { display: grid; place-items: center; padding: 0 12px; font: 700 0.95rem/1 var(--f-label); font-style: normal; color: #fff1d6; text-shadow: var(--ol1); background: #4f8f2a; }
.gd-lamp { display: flex; align-items: center; gap: 10px; }
.gd-lamp img { width: 36px; height: 36px; object-fit: contain; }
.gd-bar { position: relative; display: block; width: 90px; height: 14px; clip-path: var(--notch); background: rgba(82, 41, 25, 0.25); box-shadow: inset 0 0 0 var(--u) var(--parch-edge); overflow: hidden; }
.gd-bar i { position: absolute; inset: 0 30% 0 0; background: #ffb340; box-shadow: inset 0 calc(var(--u) * -2) 0 #c97a12; }
.gd .gd-lamp b { font: 700 1.1rem/1 var(--f-num); color: var(--parch-ink); }
.gd-lower { display: grid; grid-template-columns: minmax(0, 1.25fr) minmax(0, 1fr); gap: 14px 28px; align-items: start; }
.gd-tips h3 { margin-bottom: 8px; font-size: 1.1rem; }
.gd-tips ul { margin: 0; padding-left: 1.1em; display: grid; gap: 6px; }
.gd-ctl { display: grid; gap: 12px; justify-items: start; }
/* the keys, folded: a quiet line that opens the list */
.gd-keyfold { width: 100%; }
.gd-keyfold summary { cursor: pointer; display: flex; align-items: center; gap: 6px; min-height: 40px; list-style: none; font: 700 1.05rem/1.2 var(--f-label); color: var(--win-ink); text-shadow: var(--ol1); }
.gd-keyfold summary::-webkit-details-marker { display: none; }
.gd-keyfold summary::after { content: "›"; font-size: 1.2rem; transition: rotate .15s; }
.gd-keyfold[open] summary::after { rotate: 90deg; }
.gd-keyfold summary:hover { color: var(--gold); }
html[data-motion="reduce"] { .gd-keyfold summary::after { transition: none; } }
.gd-keys { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 6px 12px; margin: 6px 0 0; }
.gd-keys > div { display: flex; align-items: center; gap: 8px; }
.gd-keys dt { flex: none; display: flex; }
.gd-keys dd { margin: 0; font-size: 0.95rem; line-height: 1.25; }
.gd .gd-start { display: inline-grid; place-items: center; width: fit-content; min-height: 48px; text-decoration: none; }
.gd-legal { text-align: center; }
.gd-legal a { display: inline-block; padding: 8px 4px; }
.gd .studio-credit { margin-top: -10px; font-size: 0.85rem; text-align: center; }
.gd .studio-credit span { display: inline-block; }
/* your account (option C, the Lantern UI): one centred column, the miner on a ledge, its name, three numbers on
   parchment and the folds */
.ac-col { max-width: 460px; margin: 0 auto; display: grid; justify-items: center; gap: 12px; text-align: center; }
/* the ledge grows past 214px only for a hat taller than its headroom (--over, profile.js), the shelf staying put */
.ac-ledge { width: 200px; min-height: 180px; display: grid; place-items: end center; padding-bottom: 6px; image-rendering: pixelated; }
.ac-fig { position: relative; overflow-x: clip; flex: none; margin-top: var(--over, 0px); }
.ac-name { margin: 0; font: 700 2rem/1.1 var(--f-label); color: var(--win-ink); text-shadow: var(--ol); overflow-wrap: anywhere; }
.hub .ac-go, .hub .ac-auth .btn { min-height: 44px; height: auto; }
.ac-hero { width: 100%; display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 10px; margin: 4px 0 0; }
.ac-num { display: grid; gap: 4px; padding: 10px 6px; min-width: 0; }
.ac-num b { font: 700 clamp(1.35rem, 5vw, 1.6rem)/1.1 var(--f-num, var(--f-label)); color: var(--parch-ink); text-shadow: none; font-variant-numeric: tabular-nums; white-space: nowrap; }
.ac-num span { font: 700 0.92rem/1.2 var(--f-label); color: var(--parch-ink-dim); text-shadow: none; }
/* the folds: "Achievements 2 of 6" (and the full record), and, signed in, your name, passkeys and Sign out */
.ac-more { width: 100%; text-align: left; }
.ac-more summary { cursor: pointer; min-height: 44px; display: flex; align-items: center; justify-content: center; gap: 8px; list-style: none;
  font: 700 1.02rem/1.2 var(--f-label); color: var(--win-ink); text-shadow: var(--ol1); }
.ac-more summary::-webkit-details-marker { display: none; }
.ac-more summary::after { content: "›"; font-size: 1.2rem; transition: rotate 0.15s; }
.ac-more[open] summary::after { rotate: 90deg; }
.ac-more summary:hover { color: var(--gold); }
.ac-more summary:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }
html[data-motion="reduce"] { .ac-more summary::after { transition: none; } }
.ac-more .ach-box-head { display: none; }   /* the fold's own line already says how many */
.ac-list { margin: 10px 0 6px; display: grid; }
.ac-list > div { display: flex; justify-content: space-between; gap: 12px; padding: 9px 4px; border-bottom: 2px solid var(--line);
  font: 700 1rem/1.3 var(--f-label); color: var(--ink-dim); text-shadow: var(--ol1); }
.ac-list dd { margin: 0; color: var(--win-ink); font-variant-numeric: tabular-nums; }
.ac-acct[open] summary { margin-bottom: 8px; }
.ac-save { width: 100%; display: grid; justify-items: center; gap: 10px; }
.ac-go { justify-content: center; min-width: 200px; min-height: 52px; padding-inline: 26px; font-size: 1.15rem; }
.ac-note { margin: 0; font: 600 1rem/1.35 var(--f-text, var(--f-label)); color: var(--ink-dim); text-shadow: var(--ol1); }
.ac-auth { text-align: left; }
.hub .ac-auth .answer-form input { background: var(--parch-lit); color: var(--parch-ink); border-color: var(--parch-edge); box-shadow: inset 0 0 0 var(--u) var(--parch-edge); text-shadow: none; }
.ac-auth .acct-body { display: grid; gap: 10px; }
.ac-auth .lede, .ac-auth .kicker { display: none; }
/* "Continue with Google" in Google's own light style (white, grey edge, the multicolour G); used wherever profile.js draws sign-in */
.btn.gsi { display: inline-flex; align-items: center; justify-content: center; gap: 12px; min-height: 44px; padding: 0 18px;
  background: #ffffff; color: #1f1f1f; border: 2px solid #321007; box-shadow: inset 0 0 0 1px #747775; text-shadow: none;
  font: 700 1.02rem/1 var(--f-label); }
.btn.gsi:hover, .btn.gsi:focus-visible { background: #f2f2f2; color: #1f1f1f; }
.gsi-logo { display: inline-grid; place-items: center; width: 20px; height: 20px; flex: none; }
/* the other sign-in buttons, each in its provider's own colours (their brand guidelines), the same size as Google's */
.btn.sso { display: inline-flex; align-items: center; justify-content: center; gap: 12px; min-height: 44px; padding: 0 18px;
  border: 2px solid #321007; box-shadow: none; text-shadow: none; font: 700 1.02rem/1 var(--f-label); }
.btn.sso-discord { background: #5865f2; color: #fff; }
.btn.sso-discord:hover, .btn.sso-discord:focus-visible { background: #4752c4; color: #fff; }
.btn.sso-microsoft { background: #fff; color: #5e5e5e; box-shadow: inset 0 0 0 1px #8c8c8c; font-family: "Segoe UI", var(--f-label); font-weight: 600; }
.btn.sso-microsoft:hover, .btn.sso-microsoft:focus-visible { background: #f3f3f3; color: #5e5e5e; }
.btn.sso-apple { background: #000; color: #fff; }
.btn.sso-apple:hover, .btn.sso-apple:focus-visible { background: #222; color: #fff; }
/* our own: the game's button, with the passkey mark */
.btn.sso-passkey { border: 0; text-shadow: var(--ol1); }
.btn.sso-passkey .gsi-logo, .sso-passkey-add .gsi-logo { width: 22px; height: 22px; }
.acct-passkeys { display: grid; gap: 8px; margin-top: 6px; }
.acct-hint { margin: 0; font: 600 0.95rem/1.4 var(--f-label); color: var(--ink-dim); text-shadow: var(--ol1); }
.acct-keys { display: grid; gap: 4px; margin: 0; padding: 0; list-style: none; }
.acct-keys li { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 4px 0 4px 2px; border-bottom: 2px solid var(--line);
  font: 700 0.92rem/1.3 var(--f-label); color: #fff; text-shadow: var(--ol1); }
.sso-passkey-add { justify-self: start; display: inline-flex; align-items: center; gap: 8px; }

/* ---------- phones: the window fills the screen and each section scrolls as one page ---------- */
@media (max-width: 760px) {
  .hub { width: 100vw; height: 100dvh; margin: 0; }
  .hub-panel { clip-path: none; }
  .hub-tabs { padding: calc(env(safe-area-inset-top, 0px) + 8px) 6px 0 8px; }
  .hub-tab { padding: 10px 11px 12px; font-size: 0.95rem; }
  .hub-coins { margin: calc(env(safe-area-inset-top, 0px) + 8px) 54px 0 4px; font-size: 1.05rem; }
  /* the four tabs share one row, each as wide as its name allows */
  #hub .hub-panel { padding: 0 calc(var(--u) * 3) calc(var(--u) * 3); }
  #hub .hub-head { gap: 3px; padding: calc(env(safe-area-inset-top, 0px) + 8px) 46px 0 0; }
  #hub .hub-where { padding-left: 8px; }
  #hub .hub-where h2 { font-size: 1.2rem; }
  #hub .hub-tabs { gap: 3px; }
  #hub .hub-tab { flex: 1 1 auto; min-width: 0; padding: 11px 4px 12px; font-size: 0.92rem; text-align: center; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  #hub .hub-tab[aria-selected="true"] { padding-bottom: 15px; }
  #hub .hub-sub { padding: 8px 10px 0; }
  .hub .menu-close { top: calc(env(safe-area-inset-top, 0px) + 8px); right: 6px; }
  .hub-body { margin: 0; }
  .hub-split { display: block; overflow-y: auto; overscroll-behavior: contain; }
  .hub-split > * { overflow: visible; }
  .hub-split > article { box-shadow: inset 0 var(--u) 0 var(--win-edge); }
  .wr-stage { position: sticky; top: 0; z-index: 2; background: var(--win); padding-bottom: 10px; box-shadow: inset 0 calc(var(--u) * -1) 0 var(--win-edge); }
  .wr-room { --head: 34px; flex: none; min-height: 0; padding: var(--head) 0 14px; }
  .wr-plate .wr-status { font-size: 0.88rem; }
  .wr-plate h3 { font-size: 1.25rem; }
  .wr-row { grid-template-columns: 48px minmax(0, 1fr) 44px 44px; }
  .wr-count { display: none; }
  .wr-grid { grid-template-columns: repeat(auto-fill, 64px); justify-content: center; }
  .cx .cx-index { overflow: visible; }
  .cx-list { overflow: visible; }
  .cx-hero { grid-template-columns: 80px 1fr; }
  .cx-art { width: 80px; height: 80px; }
  .cx-art img { width: 64px; height: 64px; }
  .cx-name { font-size: 1.6rem; }
  .cx-pips i { width: 14px; height: 14px; }
  .lm-strip { width: 84px; }
  .gd { padding: 12px 14px 18px; }
  .gd-steps { grid-template-columns: minmax(0, 1fr); gap: 8px; }
  .gd-step { grid-template-columns: 112px minmax(0, 1fr); grid-template-rows: auto 1fr; column-gap: 12px; row-gap: 2px; padding: 10px 12px 12px 10px; }
  .gd-fig { grid-row: 1 / 3; height: auto; min-height: 60px; }
  .gd-ask { padding: 6px 8px; }
  .gd-ask b { font-size: 0.85rem; }
  .gd-answer span { min-width: 0; padding: 6px 8px; font-size: 0.9rem; }
  .gd-bar { width: 40px; }
  .gd-lamp { gap: 6px; }
  .gd-lamp img { width: 28px; height: 28px; }
  /* the ladder turns into one row per landmark */
  .gd-ladder { display: grid; grid-template-columns: minmax(0, 1fr); gap: 2px; }
  .gd-run { min-width: 0; }
  .gd-run { grid-column: auto; grid-template-columns: 118px minmax(0, 1fr); align-items: center; gap: 8px; }
  .gd-run .gd-zone { order: -1; text-align: left; }
  .gd-ores { display: flex; flex-wrap: wrap; gap: 4px; padding: 3px 6px; box-shadow: inset var(--u) 0 0 var(--zc); }
  .gd-ores img { width: 28px; }
  /* a phone has room for each ore's name beside it */
  .gd-ore { display: inline-flex; align-items: center; gap: 4px; margin-right: 6px; }
  .gd-ore small { display: inline; font: 700 0.8rem/1 var(--f-label); color: var(--parch-ink); text-shadow: none; }
  /* the step's number sits above its picture instead of on its edge */
  .gd-step { padding-top: 26px; }
  .gd-n { top: 7px; left: 12px; }
  .gd-lower, .gd-keys { grid-template-columns: minmax(0, 1fr); }
  .ac-col { padding-inline: 16px; }
}

/* ---------- short screens (a phone held sideways): the window fills the screen and its header shrinks to one row ---------- */
/* The title bar goes (the lit tab already names the section) and the tabs move up beside the coins, which gives the
   body about 60px back; on a 390px-tall screen that's the difference between two settings rows and four. */
@media (max-height: 500px) {
  .hub { width: 100vw; height: 100dvh; margin: 0; }
  .hub-panel { clip-path: none; }
  #hub .hub-head { padding: calc(env(safe-area-inset-top, 0px) + 4px) 52px 0 calc(env(safe-area-inset-left, 0px) + 4px); }
  #hub .hub-tab { flex: none; min-height: 40px; padding: 8px 14px 9px; font-size: 0.95rem; }
  #hub .hub-tab[aria-selected="true"] { padding-bottom: 13px; }
  #hub .hub-where { padding: 2px 4px 6px; }
  #hub .hub-sub { padding-top: 6px; }
  #hub .hub-sub .hub-subtab { min-height: 36px; }
  .hub .menu-close { top: 4px; right: calc(env(safe-area-inset-right, 0px) + 6px); }
  /* a narrow one scrolls as one page (the phone layout): the wardrobe's preview scrolls away with it, not pinned */
  .wr-stage { position: static; }
}

html[data-motion="reduce"] {
  .hub[open] .hub-panel, .hub-prompt.in, .hub-prompt button, .hub-coins.pay, .coin-chip.pay, .slot, .cx-slot, .wr-av.pop, .wr-tile.shake, .slot.shake { animation: none !important; }
}
