/* Tinkerpile — one design language, everywhere. Palette/typography/button
   style are all taken directly from the parts catalog page
   (playground/templates/playground/parts_catalog.html, itself ported
   verbatim from site/parts-catalog.html) — that page is the reference;
   every other page matches it, not the other way round. --font is the
   SINGLE place the site's typeface is declared; nothing else in the
   codebase should set font-family on body text or headings. */
:root {
  --font: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  --bg: #eef5fb;
  --ink: #14212e;
  --muted: #5b6b7b;
  --accent: #d6262d;
  --accent2: #0b5cad;
  --card: #ffffff;
  --line: #d5e2ee;
  --chip: #e5eef7;
  --radius: 14px;
}
* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
body {
  font-family: var(--font);
  background: var(--bg); color: var(--ink);
  -webkit-tap-highlight-color: transparent;
}
h1, h2, h3, .brand { font-family: var(--font); }
.hidden { display: none !important; }
.muted { color: var(--muted); }
.small { font-size: 0.85em; }

/* top bar */
.topbar {
  display: flex; align-items: center; justify-content: space-between;
  padding: 8px 14px; background: var(--ink); color: #fff;
  position: sticky; top: 0; z-index: 50;
}
.brand { color: #fff; text-decoration: none; font-weight: 800; font-size: 1.3em; display: inline-flex; align-items: center; gap: 8px; }
.brand img { width: 1.15em; height: 1.15em; display: block; }
.topbar nav { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }
.topbar nav a { color: #fff; text-decoration: none; padding: 6px 10px; border-radius: 8px; }
.topbar nav a:hover { background: #3a3a44; }
.topbar nav a.nav-icon { display: inline-flex; align-items: center; padding: 6px 8px; }
.topbar nav a.nav-icon svg { display: block; }
.topbar nav a.nav-hidden { opacity: 0.45; }
.userchip {
  background: var(--accent2); color: #fff; border-radius: 20px;
  padding: 6px 12px; font-weight: 700;
}
/* who's-signed-in menu: plain <details>, so it opens/closes and is
   keyboard-reachable with no JS of its own */
.usermenu { position: relative; }
.usermenu > summary { list-style: none; cursor: pointer; display: inline-block; }
.usermenu > summary::-webkit-details-marker { display: none; }
.usermenu-pop {
  position: absolute; right: 0; top: calc(100% + 6px); z-index: 60;
  background: var(--card); border: 1px solid var(--line); border-radius: 10px;
  box-shadow: 0 8px 22px rgba(0, 0, 0, 0.18); padding: 4px; min-width: 150px;
  display: flex; flex-direction: column;
}
.topbar nav .usermenu-pop a {
  color: var(--ink); padding: 9px 12px; border-radius: 7px; white-space: nowrap;
}
.topbar nav .usermenu-pop a:hover { background: var(--chip); }
.page { padding: 14px; max-width: 1100px; margin: 0 auto; }

/* app-page (the 3D playground): canvas fills the whole viewport edge to
   edge; the topbar, brick picker and toolbar float on top of it as
   translucent HUD panels instead of taking their own layout space. */
body.app-page { height: 100vh; overflow: hidden; }
body.app-page .topbar {
  position: absolute; top: 0; left: 0; right: 0; z-index: 60;
  /* same solid --ink as every other page's navbar — was a translucent
     overlay before, which read as grey against the 3D scene behind it */
  background: var(--ink);
}
body.app-page .page { position: absolute; inset: 0; padding: 0; max-width: none; margin: 0; }

/* catalog-page: the browsable parts catalog brings its own full-width
   sticky header + its own self-contained styling (see parts_catalog.html)
   — undo .page's centred/max-width column so it isn't squeezed into it. */
body.catalog-page .page { padding: 0; max-width: none; margin: 0; }

/* lp-page: the LDraw instructions step-through player — same deal, full
   viewport height/width instead of being boxed into the narrow centred
   .page column (it has its own 3-pane layout + 3D canvas that wants the
   room). */
body.lp-page { height: 100vh; overflow: hidden; }
body.lp-page .page {
  padding: 10px 14px; max-width: none; margin: 0;
  height: calc(100vh - 57px); display: flex; flex-direction: column;
  box-sizing: border-box;
}

/* buttons — flat pill style, matching the parts catalog page's .btn/.seg
   button exactly (that page is this site's design reference, see the
   :root comment above): thin border, no drop-shadow, no press-down. */
.btn {
  appearance: none; border: 1px solid var(--line); background: var(--card); color: var(--ink);
  border-radius: 10px; padding: 10px 14px; font-size: 1em; font-weight: 600;
  cursor: pointer; min-height: 44px;
  font-family: inherit;
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
}
.btn:hover { border-color: var(--accent2); }
.btn.primary { background: var(--accent2); border-color: var(--accent2); color: #fff; }
.btn.big { font-size: 1.1em; padding: 12px 20px; }
.btn.danger { background: #fff; border-color: var(--accent); color: var(--accent); }
.btn.active { background: var(--accent2); border-color: var(--accent2); color: #fff; }
.btn:disabled { opacity: 0.45; cursor: default; }
.tag {
  display: inline-block; background: var(--chip); border-radius: 20px;
  padding: 3px 10px; font-size: 0.85em; margin: 2px;
}

/* playground layout: #app fills the full viewport (see body.app-page
   above); everything inside it is a floating HUD panel positioned on top
   of the full-bleed canvas, not a layout sibling squeezing the 3D view. */
#app { position: absolute; inset: 0; }
#stage { position: absolute; inset: 0; }
#viewport {
  position: absolute; inset: 0; border-radius: 0; border: none;
  background: #dfe9f5;
}
#gl { width: 100%; height: 100%; display: block; touch-action: none; }
/* "mix your own" swatch: a spectrum wheel, so it doesn't read as another
   fixed colour. Opens .mixer below, inside the card -- deliberately not a
   native <input type=color>, whose browser dialog floated over the toolbar. */
.swatch.picker {
  padding: 0; border: 2px solid var(--line); cursor: pointer;
  background: conic-gradient(red, yellow, lime, aqua, blue, magenta, red);
}
.swatch.picker.active { border-color: var(--accent2); box-shadow: 0 0 0 2px var(--accent2) inset; }
.mixer { grid-column: 1 / -1; display: flex; flex-direction: column; gap: 6px; margin-top: 6px; }
.mixer-chip {
  height: 26px; border-radius: 8px; border: 1px solid var(--line);
  font: 600 0.68em var(--font); color: #00000099; display: flex;
  align-items: center; justify-content: center; letter-spacing: .04em;
}
.mixer-row { display: flex; flex-direction: column; gap: 2px; }
.mixer-row span { font-size: 0.66em; font-weight: 700; color: var(--muted); }
.mixer-row input[type=range] {
  -webkit-appearance: none; appearance: none; width: 100%; height: 12px;
  border-radius: 6px; border: 1px solid var(--line); cursor: pointer;
}
.mixer-row input[type=range]::-webkit-slider-thumb {
  -webkit-appearance: none; appearance: none; width: 14px; height: 14px; border-radius: 50%;
  background: #fff; border: 2px solid var(--ink); cursor: pointer;
}
.mixer-row input[type=range]::-moz-range-thumb {
  width: 12px; height: 12px; border-radius: 50%; background: #fff; border: 2px solid var(--ink);
}

/* the drag-a-rectangle selection box (Select tool) — see core.js _marqueeStart */
.bp-marquee {
  position: absolute; z-index: 5; pointer-events: none; border-radius: 4px;
  border: 2px dashed var(--accent2); background: rgba(11, 92, 173, 0.12);
}

/* Excalidraw-style floating toolbar: one bar, top-center, icon tools.
   Shape-group buttons live inside it (#shape-slot) and open a tray of
   sizes/variants right below; a second floating panel at the bottom shows
   context-sensitive properties (color etc) for whatever is about to be
   placed, or whatever's currently selected. */
#toolbar {
  position: absolute; top: 56px; left: 50%; transform: translateX(-50%);
  z-index: 40; display: flex; gap: 6px; flex-wrap: wrap; align-items: center;
  justify-content: center; width: max-content; max-width: calc(100vw - 20px);
  background: rgba(255, 255, 255, 0.9); backdrop-filter: blur(6px);
  border-radius: var(--radius); padding: 8px; border: 1px solid var(--line);
  box-shadow: 0 8px 24px rgba(20, 30, 45, 0.14);
}
#toolbar .tbtn { padding: 7px 9px; min-height: 42px; }
#toolbar .sep { width: 2px; align-self: stretch; background: var(--line); }
.ttool { min-width: 44px; font-size: 1.15em; }
.icon { width: 20px; height: 20px; flex: none; display: block; }
.view-mode-label { font-size: 0.8em; font-weight: 700; letter-spacing: 0.02em; min-width: 20px; display: block; }

/* Left column: four cards of one width on one grid. Part slots (next
   part, goes with, recent parts) are the same --slot squares, three to a
   row; colours are squares four to a row across the same width. The
   icon inside a slot is positioned for its exact box (UI.setPartIcon), so
   the slot sizes stay fixed px. */
#leftpanel {
  --slot: 56px; --slot-gap: 6px;
  position: absolute; left: 12px; top: 128px; z-index: 40;
  width: calc(3 * var(--slot) + 2 * var(--slot-gap) + 20px);
  display: flex; flex-direction: column; gap: 8px;
}
.side-card {
  background: rgba(255, 255, 255, 0.94); backdrop-filter: blur(6px);
  border-radius: var(--radius); padding: 10px;
  border: 1px solid var(--line); box-shadow: 0 8px 24px rgba(20, 30, 45, 0.14);
}
.side-label { font-weight: 700; font-size: 0.78em; color: var(--muted); margin: 0 2px 8px; }
.side-keys { font-weight: 600; opacity: 0.75; margin-left: 4px; }
#propspanel { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 10px; }
/* a square like the slots; the 4:3 icon sits in its middle (the top and
   bottom eighths are border, so no neighbouring sprite shows) */
.props-current {
  box-sizing: border-box; width: var(--slot); height: var(--slot); flex: none; border-radius: 12px;
  border: solid #eef3f9; border-width: calc(var(--slot) / 8) 0; background-clip: padding-box;
  background-color: #eef3f9; background-repeat: no-repeat;
}
.props-text { flex: 1; min-width: 0; }
#propspanel .props-actions:not(:has(.btn:not(.hidden))) { display: none; }
#colorspanel:has(.colors.hidden) { display: none; }
.slot-grid { display: grid; grid-template-columns: repeat(3, var(--slot)); gap: var(--slot-gap); }
.hot-slot, .linked-pic {
  appearance: none; position: relative; width: var(--slot); height: var(--slot); padding: 4px;
  border: 2px solid var(--line); border-radius: 12px; background: #fff; cursor: pointer;
}
.hot-slot:hover:not(:disabled), .linked-pic:hover { border-color: var(--accent2); }
.hot-slot:disabled { opacity: 0.35; cursor: default; }
.hot-slot.active { border-color: var(--accent2); box-shadow: 0 0 0 2px var(--accent2) inset; background: #e8f0ff; }
/* the 4:3 icon box inside a slot (the slot less padding and border), centred
   (slotPic in playground.js computes the same box) */
.hot-pic {
  display: block; width: calc(var(--slot) - 12px); height: calc((var(--slot) - 12px) * 0.75);
  margin: calc((var(--slot) - 12px) / 8) auto 0; background-repeat: no-repeat;
}
.hot-key {
  position: absolute; left: 4px; bottom: 2px; font-size: 0.68em; font-weight: 800; color: var(--muted);
}
#colorspanel .colors { grid-template-columns: repeat(4, 1fr); gap: var(--slot-gap); }
.ask-input { width: 100%; font: inherit; padding: 10px 12px; border-radius: 10px; border: 1px solid var(--line); box-sizing: border-box; }
#colorspanel .swatch { min-height: 0; border-radius: 10px; }
/* shorter screens: smaller slots, so the column stays clear of the bottom dock */
@media (max-height: 860px) { #leftpanel { --slot: 46px; } }
@media (max-height: 720px) {
  #leftpanel { --slot: 40px; --slot-gap: 5px; }
  #linked-list .linked-pic:nth-child(n+4) { display: none; }    /* one row of "Goes with" */
}

/* Game-style bottom dock: a floating bar of big category buttons (picture
   of a real part + short label); the tray of parts slides up above it. */
#dock {
  position: absolute; left: 50%; bottom: 12px; transform: translateX(-50%);
  z-index: 45; width: min(1480px, calc(100vw - 24px));
  display: flex; flex-direction: column; align-items: center; gap: 8px; pointer-events: none;
}
#dock > * { pointer-events: auto; }
/* the tray still wants the whole width; the bar of categories does not */
#dock > #tray { align-self: stretch; }
#dockbar {
  background: rgba(255, 255, 255, 0.95); backdrop-filter: blur(6px);
  border: 1px solid var(--line); border-radius: 22px; padding: 8px;
  box-shadow: 0 10px 30px rgba(20, 30, 45, 0.2);
}
.dock-cats {
  display: flex; gap: 4px; overflow-x: auto; scrollbar-width: thin;
  justify-content: safe center; overscroll-behavior-x: contain;
}
.dock-cat {
  appearance: none; border: 2px solid transparent; background: var(--chip); color: var(--ink);
  font: inherit; font-weight: 700; font-size: 0.72em; line-height: 1.1; cursor: pointer;
  flex: none; width: 78px; padding: 6px 3px; border-radius: 16px;
  display: flex; flex-direction: column; align-items: center; gap: 4px;
  transition: transform 0.12s ease, background 0.12s ease;
}
.dock-cat:hover { transform: translateY(-3px); }
.dock-cat[aria-selected="true"] { background: var(--accent2); color: #fff; border-color: #003a80; transform: translateY(-4px); }

/* A part wears its category's colour (parts.CATEGORY_COLORS) while the tile
   behind it keeps its own background. The picture moves onto this layer,
   where the colour is multiplied into it -- the icon sheet is baked very
   light grey (tools/ldraw/bake_images.py MAIN_RGB) precisely so multiply
   lands the colour while keeping the moulded shading -- and the layer is
   then masked by the picture's own alpha, so the colour stops at the edge
   of the part instead of flooding the tile. */
.tinted { position: relative; }
.tinted::after {
  content: ''; position: absolute; pointer-events: none;
  left: 50%; top: 50%; transform: translate(-50%, -50%);
  width: var(--pic-w); height: var(--pic-h);
  background-image: var(--pic);
  background-size: var(--pic-size);
  background-position: var(--pic-pos);
  background-repeat: no-repeat;
  background-color: var(--cat);
  background-blend-mode: multiply;
  -webkit-mask-image: var(--pic); mask-image: var(--pic);
  -webkit-mask-size: var(--pic-size); mask-size: var(--pic-size);
  -webkit-mask-position: var(--pic-pos); mask-position: var(--pic-pos);
  -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat;
}
.dock-pic { width: 64px; height: 48px; border-radius: 10px; background-color: #fff; background-repeat: no-repeat; }
.dock-label { display: block; max-width: 100%; text-align: center; }

#tray {
  background: rgba(255, 255, 255, 0.97); backdrop-filter: blur(6px);
  border: 1px solid var(--line); border-radius: 22px; padding: 12px;
  box-shadow: 0 10px 30px rgba(20, 30, 45, 0.2);
  display: flex; flex-direction: column; gap: 10px; max-height: min(46vh, 420px);
  animation: tray-up 0.16s ease-out;
}
#tray.hidden { display: none; }
@keyframes tray-up { from { opacity: 0; transform: translateY(16px); } to { opacity: 1; transform: none; } }
.tray-head { display: flex; align-items: center; gap: 10px; flex: none; }
.tray-title { font-size: 1.15em; font-weight: 800; }
/* the LDraw credit: one quiet line at the foot of every drawer, never in the way */
.tray-credit { flex: none; margin: 0; font-size: 0.72em; color: #8a94a1; text-align: right; }
.tray-head .lp-search { flex: 1; max-width: 300px; margin-left: auto; min-height: 40px; }
.lp-count { color: var(--muted); font-size: 0.8em; flex: none; }
.lp-results {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(118px, 1fr)); gap: 8px;
  flex: 1; align-content: start; overflow-y: auto; min-height: 120px;
}
.lp-card {
  appearance: none; border: 1px solid var(--line); background: #fff; color: var(--ink);
  border-radius: 10px; padding: 6px; cursor: pointer; font: inherit;
  display: flex; flex-direction: column; align-items: center; gap: 2px;
  position: relative; text-align: center;
}
.lp-card.active { border-color: var(--accent2); border-width: 3px; background: #e8f0ff; }
.lp-card .th { width: 96px; height: 72px; background-color: #f4f7fb; border-radius: 8px; background-repeat: no-repeat; }
.lp-card b { font-size: 0.78em; line-height: 1.2; }
.lp-card .lv { position: absolute; top: 4px; left: 4px; font-size: 0.6em; font-weight: 700; padding: 1px 5px; border-radius: 5px; color: #fff; }
.lp-card .lv.l1 { background: #2e7d32; } .lp-card .lv.l2 { background: #1565c0; }
.lp-card .lv.l3 { background: #6a1b9a; } .lp-card .lv.l4 { background: #c62828; }
.lp-empty { grid-column: 1 / -1; color: var(--muted); text-align: center; padding: 20px 0; font-size: 0.9em; }
.props-label { font-weight: 800; margin: 2px 4px 2px; font-size: 0.85em; line-height: 1.25; }
.props-hint { color: var(--muted); font-size: 0.82em; margin: 0 4px 6px; }
.colors { display: grid; grid-template-columns: repeat(4, 1fr); gap: 10px; }
.swatch {
  aspect-ratio: 1; border-radius: 10px; border: 3px solid transparent;
  cursor: pointer; min-height: 42px;
}
.swatch.active { border-color: var(--ink); box-shadow: 0 0 0 2px #fff inset; }
.props-actions { display: flex; flex-basis: 100%; gap: 8px; margin-top: 10px; }
.props-actions .btn { flex: 1; }

.hudbar {
  background: #fff8e1; border: 2px solid #e8c547; border-radius: var(--radius);
  padding: 10px 12px; display: flex; gap: 10px; align-items: center; flex-wrap: wrap;
}

/* Baseplate modal: a row of look swatches (Classic Grey/Grass/Water/Road —
   purely cosmetic, doesn't clear the build) above the existing size picker
   (which does clear the build — kept visually distinct via the warning
   text already shown in the modal body). */
.basetype-row { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 12px; }
.basetype-btn {
  display: flex; align-items: center; gap: 7px; font: inherit; font-weight: 700;
  padding: 7px 12px 7px 7px; border-radius: 10px; border: 1px solid var(--line);
  background: #fff; color: var(--ink); cursor: pointer;
}
.basetype-btn.active { border-color: var(--accent2); border-width: 2px; background: #e8f0ff; }
.bt-swatch { display: inline-block; width: 22px; height: 22px; border-radius: 6px; flex: none; border: 1px solid rgba(0,0,0,.25); }
.sizerow-wrap { display: flex; flex-wrap: wrap; gap: 8px; }
.size-btn {
  font: inherit; font-weight: 700; padding: 8px 14px; border-radius: 10px;
  border: 1px solid var(--line); background: #fff; color: var(--ink); cursor: pointer;
}
.size-btn.active { border-color: var(--accent2); border-width: 2px; background: #e8f0ff; }

/* Template step-through bar on the playground itself ("ingest" a template):
   a SECOND floating bar, bottom-anchored, that appears alongside — not
   instead of — the normal left parts panel and top toolbar. */
#ingestbar {
  position: absolute; left: 10px; right: 10px; bottom: 122px; /* above the part dock */ z-index: 40;
  flex-direction: column; align-items: stretch; gap: 6px;
  background: rgba(255, 248, 225, 0.95); backdrop-filter: blur(6px);
  box-shadow: 0 8px 24px rgba(20, 30, 45, 0.14);
  max-width: 760px; margin: 0 auto;
}
.ing-head { font-size: 1.05em; display: flex; align-items: center; gap: 8px; }
.ing-head #ing-close { margin-left: auto; min-width: 34px; padding: 4px 8px; }
.ing-caption { font-size: 0.85em; color: var(--muted); }
.ing-controls { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
#ing-progfill { height: 100%; width: 0; background: #f5c400; transition: width .2s; }
/* "Parts in this step" modal rows (reuses .brick-btn, but its own colour
   dot — .swatch already means two different things elsewhere on this page
   (a big pickable colour button vs. a small read-only dot), so this picks
   a name that can't collide with either). */
.pit-dot { width: 22px; height: 16px; border-radius: 4px; flex: none; border: 1px solid rgba(0,0,0,.3); }

/* modal */
.modal {
  position: fixed; inset: 0; background: rgba(0,0,0,0.55); z-index: 100;
  display: flex; align-items: center; justify-content: center; padding: 16px;
}
.modal-box {
  background: #fff; border-radius: 18px; padding: 22px; max-width: 480px; width: 100%;
  border: 3px solid var(--ink);
}
.modal-box h2 { margin-top: 0; }
.modal-box img { width: 100%; border-radius: 10px; border: 1px solid var(--line); }
.modal-actions { display: flex; gap: 10px; margin-top: 14px; justify-content: flex-end; }
.modal-box label { display: block; margin: 10px 0 4px; font-weight: 700; }
.modal-box label.ps-check { display: flex; align-items: center; gap: 8px; font-weight: 500; }
.modal-box label.ps-check input { margin: 0; }
.modal-box input[type=text], .modal-box input[type=password], .modal-box textarea {
  width: 100%; padding: 10px; font-size: 1em; border-radius: 10px;
  border: 1px solid var(--line); font-family: inherit;
}

/* Quick-search modal (Space, from the playground canvas): a wider box so
   the same .lp-card grid used in the left panel can show more columns at
   once, for a fast type-and-Enter flow without leaving the keyboard. */

.bp-loading {
  position: fixed; inset: 0; z-index: 200; background: var(--bg); color: var(--ink);
  display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center; padding: 16px;
  font: 800 1.1em var(--font);
}

/* toast */
.toast {
  position: fixed; bottom: 24px; left: 50%; transform: translateX(-50%);
  background: var(--ink); color: #fff; padding: 12px 22px; border-radius: 30px;
  font-weight: 700; z-index: 200;
}

/* auth */
.auth-wrap { max-width: 560px; margin: 18px auto 40px; text-align: center; }
.auth-wrap h1 { font-size: 1.5rem; margin: 0 0 4px; }
/* Side by side once there is room for it: the words lead, the picture sits
   beside them. One column below that, words still first -- which is their
   order in the markup too, so a screen reader hears them first either way. */
.about { max-width: 760px; margin: 18px auto 10px; padding: 6px 20px 22px; border-bottom: 1px solid #dde3ea; color: #3a4552; line-height: 1.5; }
.about-words > :first-child { margin-top: 0; }
@media (min-width: 900px) {
  .about {
    max-width: 1120px; display: grid; gap: 32px 40px;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.05fr); align-items: center;
  }
  .about-shot { margin: 0; }
}
.about-shot { margin: 0 0 18px; }
.about-shot img { width: 100%; height: auto; display: block; border-radius: 12px; border: 1px solid #d6dee8; box-shadow: 0 6px 20px rgba(20, 33, 46, .12); }
.about-shot figcaption { font-size: .9rem; color: #5b6775; margin-top: 8px; text-align: center; }
.about h2 { font-size: 1.15rem; margin: 0 0 8px; color: #1f2a37; }
.about ul { padding-left: 1.2em; margin: 8px 0; }
.about li { margin: 4px 0; }
/* On the home page the picker shares the fold with the first thing a
   visitor reads, so it is trimmed: the cards are still well over a finger
   target and the fields still easy to hit, just not the whole screen. */
.profiles { display: flex; gap: 10px; flex-wrap: wrap; justify-content: center; margin: 14px 0; }
.profile-card {
  width: 92px; padding: 10px 6px; border-radius: 13px; cursor: pointer;
  border: 2px solid var(--line); background: var(--card); font-family: inherit;
  font-size: .92em;
}
.profile-card.active { border-color: var(--accent2); }
.profile-card .avatar {
  display: block; width: 44px; height: 44px; margin: 0 auto 6px; border-radius: 12px;
  background: var(--accent2); color: #fff; font-size: 1.45em; font-weight: 800;
  line-height: 44px;
}
.profile-card.other .avatar { background: var(--accent2); }
.profile-card.add .avatar { background: #1f9254; }
.profile-card.other:hover { border-color: var(--accent2); }
.profile-card.add:hover { border-color: #1f9254; }
.profile-card.add.active { border-color: #1f9254; }
.profile-card:hover { background: #f7fbff; }
.profile-card { transition: border-color .12s ease, background .12s ease; }
.profile-card .pname { font-weight: 700; word-break: break-word; }
/* the add card is an <a> (so it works with no JavaScript) but reads as a
   card, not as a link in the middle of one */
.profile-card.add, .profile-card.add:visited { text-decoration: none; color: inherit; }
.profile-card.add .pname { text-decoration: none; }
.pwform { max-width: 260px; margin: 0 auto; display: flex; flex-direction: column; gap: 7px; }
.pwform .pw-other { display: flex; flex-direction: column; gap: 7px; }
.pwform label { font-size: .92em; }
.pwform input[type=password], .pwform input[type=text] {
  padding: 8px 10px; font-size: 1em; border-radius: 10px; border: 2px solid var(--ink);
  text-align: center;
}
.pwform .btn.big { font-size: 1em; padding: 9px 18px; }
.plain-form { max-width: 340px; margin: 0 auto; display: flex; flex-direction: column; gap: 8px; text-align: left; }
.plain-form input { padding: 12px; font-size: 1.1em; border-radius: 12px; border: 2px solid var(--ink); }
/* the copy of it that opens under the Who's playing? cards: same size as the
   password form it sits in place of, rather than a wider one springing up */
#signupform { max-width: 260px; gap: 5px; }
#signupform input { padding: 8px 10px; font-size: 1em; border-radius: 10px; }
#signupform label { font-size: .92em; }
#signupform small { font-size: .78em; line-height: 1.35; display: block; margin: -2px 0 4px; }
#signupform .btn.big { font-size: 1em; padding: 9px 18px; margin-top: 4px; }
.form-error { color: var(--accent); font-weight: 700; margin: 2px 0; }

/* cards / lists — a big photo-like hero (our own real 3D renders) with the
   name/piece-count floated over it in a white pill, like a toy catalogue
   page: the picture of the thing you're building IS the card, not a small
   inset next to a wall of text. */
.list-wrap { max-width: 1040px; margin: 0 auto; }
.cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: 16px; }
.card {
  background: var(--card); border: 1px solid var(--line); border-radius: var(--radius);
  overflow: hidden; display: flex; flex-direction: column;
  box-shadow: 0 3px 0 rgba(35, 35, 43, 0.12);
  transition: transform .12s, box-shadow .12s;
}
.card:hover { transform: translateY(-3px); box-shadow: 0 8px 18px rgba(35, 35, 43, 0.18); }
/* the same flat colour the playground's sky is taken against
   (BrickEngine's scene.background, core.js), so a picture that does not fill
   this box has no visible edge: the box just looks like more sky */
.card-media { position: relative; background: #dfe9f5; }
/* A thumbnail is taken at 4:3 (BrickEngine.snapshot, 480x360) but a build
   sits in the middle of it with sky all round, so a 4:3 box spends most of a
   card's height on nothing. This box is shorter and the whole picture still
   fits inside it, side to side -- which works only because the box is the
   colour of that sky. The build is never cropped. */
.card img {
  width: 100%; aspect-ratio: 16 / 9; object-fit: contain; display: block;
}
.no-thumb { aspect-ratio: 16/9; display: flex; align-items: center; justify-content: center; font-size: 2.4em; }
.card-badge {
  position: absolute; left: 10px; bottom: 10px; max-width: calc(100% - 20px);
  background: rgba(255, 255, 255, 0.95); border-radius: 12px; padding: 6px 10px;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.15);
}
.card-badge b { display: block; font-size: 0.95em; line-height: 1.2; }
.card-badge span { font-size: 0.78em; color: var(--muted); font-weight: 700; }
.card-body { padding: 10px 12px 12px; display: flex; flex-direction: column; gap: 5px; flex: 1; }
.card h2 { margin: 0; font-size: 1em; }
.card-body > .muted { font-size: 0.84em; }
/* Each button is as wide as its own word and the row wraps when they no
   longer fit. They used to share the row equally and crop what did not fit,
   which cut "Instructions" at BOTH ends (centred text, hidden overflow) and
   left a button nobody could read. A second row is cheaper than that. */
.card-actions { display: flex; gap: 6px; margin-top: 8px; flex-wrap: wrap; align-items: stretch; }
.card-actions .btn { padding: 6px 11px; font-size: 0.88em; min-height: 38px; white-space: nowrap; }
.builds-section { font-size: 1.1em; margin: 28px 0 14px; }
.builds-section:first-of-type { margin-top: 8px; }
.progress-bar { height: 8px; background: var(--line); border-radius: 99px; overflow: hidden; }
.progress-fill { height: 100%; background: var(--accent2); }

/* instructions */
.instr-wrap { max-width: 980px; margin: 0 auto; }
.layerbar { display: flex; gap: 8px; flex-wrap: wrap; margin: 10px 0 16px; }
.instr-main { display: flex; gap: 16px; align-items: flex-start; }
.instr-view { flex: 1; background: var(--card); border: 1px solid var(--line);
  border-radius: var(--radius); padding: 14px; text-align: center; }
.instr-view img { width: 100%; max-width: 520px; border-radius: 10px; border: 1px solid var(--line); background: #dfe9f5; }
.stepnav { display: flex; gap: 10px; align-items: center; justify-content: center; margin: 12px 0; }
.stepcount { font-weight: 800; font-size: 1.1em; min-width: 90px; }
.steptext { font-size: 1.15em; font-weight: 700; }
.instr-side { width: 260px; flex: 0 0 auto; background: var(--card); border: 1px solid var(--line);
  border-radius: var(--radius); padding: 14px; }
.partslist { padding-left: 20px; }
.partslist li { margin: 4px 0; }
.dot { display: inline-block; width: 14px; height: 14px; border-radius: 4px;
  border: 1px solid #999; vertical-align: -2px; margin-right: 6px; }
.part-icon { width: 46px; height: 34px; object-fit: cover; border-radius: 6px;
  vertical-align: middle; margin-right: 8px; background: #dfe9f5; }

/* small screens: the left panel becomes a bottom sheet instead (not
   enough width for a sidebar), and other floating panels shrink to fit. */
@media (max-width: 760px) {
  #dock { bottom: 6px; width: calc(100vw - 12px); }
  .dock-cats { justify-content: flex-start; }
  .dock-cat { width: 70px; font-size: 0.66em; }
  .lp-results { grid-template-columns: repeat(auto-fill, minmax(104px, 1fr)); }
  .tray-head { flex-wrap: wrap; }
  .tray-head .lp-search { order: 3; max-width: none; flex-basis: 100%; }
  #leftpanel { top: auto; bottom: 124px; left: 6px; }
  #toolbar { top: 50px; padding: 6px; gap: 6px; }
  .instr-main { flex-direction: column; }
  .instr-side { width: auto; }
  .topbar nav { font-size: 0.9em; gap: 4px; }
}

/* ---------- LDraw instructions player (step-through + playback) ----------
   Full-height: .lp-wrap fills body.lp-page's .page, .lp-stage fills the
   rest of .lp-wrap below the title/level-picker row, and .lp-grid's three
   panes (parts list / 3D view / controls+parts-total) stretch to fill
   .lp-stage — so the 3D canvas actually uses the available screen instead
   of sitting in a small fixed-height box. */
.lp-wrap { flex: 1; min-height: 0; margin: 0; display: flex; flex-direction: column; gap: 10px; }
.lp-head { flex: none; display: flex; flex-wrap: wrap; gap: 10px 20px; align-items: flex-end; justify-content: space-between; }
.lp-head h1 { margin: 0; }
.lp-head p { margin: 4px 0 0; max-width: 62ch; }
.lp-levels { display: flex; gap: 8px; flex-wrap: wrap; }
.lp-levels .btn { flex-direction: column; gap: 0; line-height: 1.15; }
.lp-levels .btn small { font-weight: 600; font-size: 0.75em; opacity: 0.8; }
.lp-levels .btn[aria-pressed="true"], .lp-speed .btn[aria-pressed="true"] { background: var(--accent2); border-color: #003a80; color: #fff; box-shadow: 0 3px 0 #003a80; }
.lp-stage {
  flex: 1; min-height: 0; display: flex; flex-direction: column;
  background: var(--card); border: 1px solid var(--line); border-radius: var(--radius); overflow: hidden;
}
.lp-bar { flex: none; display: flex; justify-content: space-between; gap: 10px; flex-wrap: wrap; padding: 10px 14px; border-bottom: 2px solid var(--line); font-weight: 800; }
.lp-mode { font: 700 0.78em ui-monospace, Menlo, monospace; color: var(--accent2); letter-spacing: .04em; }
.lp-grid { flex: 1; min-height: 0; display: grid; grid-template-columns: 240px minmax(0, 1fr) 280px; }
.lp-pane { padding: 12px; overflow: auto; min-width: 0; }
.lp-left { border-right: 2px solid var(--line); }
.lp-right { border-left: 2px solid var(--line); }
.lp-pane h4 { margin: 0 0 10px; font: 700 0.78em ui-monospace, Menlo, monospace; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); }
.brick-btn { display: flex; gap: 8px; align-items: center; border: 2px solid var(--accent2); background: #eef4fc; border-radius: 10px; padding: 8px; margin-bottom: 8px; font-size: 0.9em; font-weight: 700; }
.brick-btn small, .lp-pane li small { display: block; font-weight: 400; color: var(--muted); font-size: 0.85em; }
.brick-btn .cnt, .lp-pane li .cnt { margin-left: auto; font-weight: 800; }
.lp-pane .swatch, .brick-btn .swatch { width: 22px; height: 16px; min-height: 0; border-radius: 4px; flex: none; border: 1px solid rgba(0,0,0,.3); }
.lp-pane ul { list-style: none; margin: 0; padding: 0; }
.lp-pane li { display: flex; gap: 8px; align-items: center; padding: 6px 0; border-bottom: 1px dashed var(--line); font-size: 0.9em; }
#partsTotal { margin-top: 10px; font: 700 0.78em ui-monospace, Menlo, monospace; color: var(--muted); }
.lp-centre { display: flex; flex-direction: column; min-width: 0; min-height: 0; }
.lp-three { position: relative; flex: 1; min-height: 0; background: #d3e8f8; }
#view { position: absolute; inset: 0; width: 100%; height: 100%; display: block; touch-action: none; cursor: grab; }
.lp-reset { position: absolute; right: 10px; top: 10px; min-height: 36px; padding: 6px 10px; }
.lp-hint { position: absolute; left: 10px; bottom: 10px; background: rgba(255,255,255,.85); font-size: 0.8em; padding: 4px 9px; border-radius: 999px; }
#caption { padding: 10px 14px; border-top: 2px solid var(--line); min-height: 48px; }
#caption .n { font: 800 0.78em ui-monospace, Menlo, monospace; color: #fff; background: var(--accent2); padding: 2px 7px; border-radius: 6px; margin-right: 8px; }
.lp-controls { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; padding: 10px 14px; border-top: 2px solid var(--line); }
.lp-speed { display: inline-flex; gap: 4px; align-items: center; font-weight: 700; }
.lp-speed .btn { min-height: 36px; padding: 6px 10px; }
.lp-prog { flex: 1; min-width: 120px; height: 10px; background: var(--line); border-radius: 99px; overflow: hidden; }
#progFill { height: 100%; width: 0; background: #f5c400; transition: width .2s; }
@media (max-width: 900px) {
  /* stacked panes need to scroll as a normal page, not be squeezed into
     a fixed viewport-height box like the 3-column desktop layout */
  body.lp-page { height: auto; overflow: visible; }
  body.lp-page .page { height: auto; }
  .lp-stage { display: block; }
  .lp-grid { display: block; }
  .lp-left, .lp-right { border: 0; border-top: 2px solid var(--line); max-height: none; overflow: visible; }
  .lp-left { order: 2; } .lp-centre { order: 1; } .lp-right { order: 3; }
  .lp-three { min-height: 340px; }
  .lp-prog { flex-basis: 100%; }
}
/* template cards with level badges — same Basic/Intermediate/Advance/Pro
   colour coding already used on the parts catalog page, for consistency */
.card .levels { display: flex; flex-wrap: wrap; gap: 6px; margin-top: auto; padding-top: 4px; }
.card .levels a {
  font-size: 0.78em; font-weight: 800; text-decoration: none; color: #fff;
  border-radius: 8px; padding: 4px 9px; transition: filter .1s;
}
.card .levels a:hover { filter: brightness(1.1); }
.card .levels a.lv-basic { background: #2e7d32; }
.card .levels a.lv-intermediate { background: #1565c0; }
.card .levels a.lv-advance { background: #6a1b9a; }
.card .levels a.lv-pro { background: #c62828; }

/* ---------- workspace: build title, hotbar, shared-build banner, My builds,
   share and shortcut dialogs (workspace.js) ---------- */
.doc-title {
  appearance: none; border: 0; background: transparent; color: var(--ink); font: inherit;
  font-weight: 800; max-width: 180px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  padding: 8px 6px; border-radius: 8px; cursor: text;
}
.doc-title:hover { background: var(--chip); }
#dockbar { display: flex; align-items: center; justify-content: center; max-width: 100%; }
#dockbar .dock-cats { flex: 0 1 auto; min-width: 0; }
.viewbar {
  position: absolute; top: 120px; left: 50%; transform: translateX(-50%); z-index: 41;
  display: flex; gap: 10px; align-items: center; flex-wrap: wrap; justify-content: center;
  width: max-content; max-width: calc(100vw - 24px); padding: 10px 14px; border-radius: var(--radius);
  background: #fff8e1; border: 2px solid #e8c547; box-shadow: 0 8px 24px rgba(20, 30, 45, 0.14);
}
body.viewing .edit-only, body.viewing #dock, body.viewing #leftpanel { display: none !important; }
.modal-box.wide { max-width: 820px; }
.ws-actions { display: flex; gap: 8px; flex-wrap: wrap; margin: 6px 0 12px; }
.ws-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 10px; max-height: 52vh; overflow-y: auto; }
.ws-card { position: relative; }
.ws-open {
  appearance: none; width: 100%; display: flex; flex-direction: column; gap: 4px; align-items: stretch;
  padding: 6px; border: 1px solid var(--line); border-radius: 10px; background: #fff; cursor: pointer;
  font: inherit; color: var(--ink); text-align: left;
}
.ws-open:hover { border-color: var(--accent2); }
.ws-open img, .ws-nothumb { width: 100%; aspect-ratio: 4 / 3; object-fit: cover; border-radius: 6px; background: #dfe9f5; display: block; }
.ws-open b { font-size: 0.9em; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ws-open small { color: var(--muted); font-size: 0.75em; }
.ws-del {
  position: absolute; top: 10px; right: 10px; appearance: none; border: 0; border-radius: 50%;
  width: 26px; height: 26px; background: rgba(255, 255, 255, 0.9); cursor: pointer; font-weight: 800;
}
.ws-linkrow { display: flex; gap: 8px; margin: 8px 0 0; }
.ws-linkrow input { flex: 1; min-width: 0; font: inherit; padding: 10px; border-radius: 10px; border: 1px solid var(--line); }
.ws-linkrow.hidden { display: none; }
.ws-keys { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 6px 32px; max-height: 70vh; overflow-y: auto; }
@media (max-width: 700px) { .ws-keys { grid-template-columns: 1fr; } }
.ws-keys h3 { margin: 6px 0 4px; font-size: 0.95em; }
.ws-keys dl { margin: 0; display: grid; grid-template-columns: auto 1fr; gap: 6px 10px; align-items: center; }
.ws-keys dt { white-space: nowrap; font-size: 0.85em; color: var(--muted); }
.ws-keys dd { margin: 0; font-size: 0.88em; }
kbd {
  display: inline-block; min-width: 1.6em; padding: 1px 6px; border-radius: 6px; text-align: center;
  border: 1px solid var(--line); border-bottom-width: 3px; background: #fff; color: var(--ink);
  font: 700 0.85em var(--font, inherit);
}
@media (max-width: 760px) {
  .doc-title { max-width: 110px; }
  .viewbar { top: 150px; }
}

/* ---------- Sets page ---------- */
.pager { display: flex; gap: 12px; align-items: center; justify-content: center; margin: 18px 0; }
.sets-head { display: flex; justify-content: space-between; align-items: flex-end; gap: 16px; flex-wrap: wrap; }
.set-filter { display: flex; gap: 8px; flex-wrap: wrap; margin: 4px 0 18px; }
.set-filter .chip {
  text-decoration: none; color: var(--ink); background: var(--chip); border: 2px solid transparent;
  padding: 6px 14px; border-radius: 999px; font-weight: 700; font-size: 0.9em;
}
.set-filter .chip.on { background: var(--accent2); color: #fff; }

/* ---------- My Builds page ---------- */
.mb-filter { display: flex; gap: 8px; flex-wrap: wrap; margin: 4px 0 18px; }
.mb-filter button.chip {
  appearance: none; border: 2px solid transparent; font: inherit; cursor: pointer;
  color: var(--ink); background: var(--chip); padding: 6px 14px; border-radius: 999px; font-weight: 700; font-size: 0.9em;
}
.mb-filter button.chip.on { background: var(--accent2); color: #fff; }
.card[hidden] { display: none; }
.set-card .card-media img { aspect-ratio: 4 / 3; object-fit: cover; display: block; width: 100%; }
.set-level {
  position: absolute; top: 10px; left: 10px; color: #fff; font-weight: 800; font-size: 0.78em;
  padding: 3px 10px; border-radius: 999px; box-shadow: 0 2px 6px rgba(0, 0, 0, 0.2);
}
.set-level.lv-basic { background: #2e7d32; } .set-level.lv-intermediate { background: #1565c0; }
.set-level.lv-advance { background: #6a1b9a; } .set-level.lv-pro { background: #c62828; }
.set-meta { display: flex; gap: 6px 14px; flex-wrap: wrap; color: var(--muted); font-size: 0.88em; }
.set-meta b { color: var(--ink); }
.set-by b { color: var(--accent2); }
.diff-row { display: flex; gap: 8px; flex-wrap: wrap; margin: 6px 0 4px; }
.diff-btn {
  appearance: none; border: 2px solid var(--line); background: #fff; border-radius: 12px; padding: 8px 14px;
  font: inherit; font-weight: 700; cursor: pointer; color: var(--ink);
}
.diff-btn.on { color: #fff; border-color: transparent; }
.diff-btn.on.lv-basic { background: #2e7d32; } .diff-btn.on.lv-intermediate { background: #1565c0; }
.diff-btn.on.lv-advance { background: #6a1b9a; } .diff-btn.on.lv-pro { background: #c62828; }
.auth-tabs { display: flex; gap: 8px; margin-bottom: 10px; }
.auth-tabs .btn[aria-pressed="true"] { background: var(--accent2); color: #fff; border-color: #003a80; }
/* ---- hover cards ----
   Shown from data-tip rather than the title attribute: the browser's own
   tooltip waits about a second and can't be styled. Keyboard focus gets
   one too, so the toolbar is readable without a mouse. */
[data-tip] { position: relative; }
[data-tip]::after {
  content: attr(data-tip);
  position: absolute; top: calc(100% + 9px); left: 50%; transform: translateX(-50%);
  z-index: 60; width: max-content; max-width: 230px; text-align: center;
  background: #1d2b3a; color: #fff; font-size: 12px; font-weight: 600; line-height: 1.35;
  padding: 7px 10px; border-radius: 9px; pointer-events: none;
  box-shadow: 0 8px 22px rgba(20, 30, 45, 0.28);
  opacity: 0; visibility: hidden; transition: opacity 0.1s ease 0.25s, visibility 0s linear 0.35s;
}
[data-tip]:hover::after, [data-tip]:focus-visible::after {
  opacity: 1; visibility: visible; transition-delay: 0.25s, 0s;
}
@media (prefers-reduced-motion: reduce) { [data-tip]::after { transition: none; } }

/* "Goes with": the slot picture is small and these are parts a child may
   not know by sight, so the card shows a bigger one with the name. */
.linked-pic { position: relative; }
/* beside the slot, not above it: this panel sits against the left edge of
   the screen, so a card centred on a slot hangs off it */
.linked-card {
  position: absolute; top: 50%; left: calc(100% + 9px); transform: translateY(-50%);
  z-index: 60; width: 148px; display: flex; flex-direction: column; align-items: center; gap: 4px;
  background: #fff; color: var(--ink); border: 1px solid var(--line); border-radius: 12px;
  padding: 8px; pointer-events: none; box-shadow: 0 10px 26px rgba(20, 30, 45, 0.24);
  opacity: 0; visibility: hidden; transition: opacity 0.1s ease 0.2s, visibility 0s linear 0.3s;
}
.linked-card b { font-size: 11.5px; font-weight: 700; text-align: center; line-height: 1.25; }
.linked-card-pic {
  display: block; width: 128px; height: 96px; border-radius: 8px;
  background: #f4f7fb; background-repeat: no-repeat;
}
.linked-pic:hover .linked-card, .linked-pic:focus-visible .linked-card {
  opacity: 1; visibility: visible; transition-delay: 0.2s, 0s;
}

/* a toolbar toggle that is on (e.g. "move the whole stack") */
.tbtn[aria-pressed="true"] { background: var(--accent2); color: #fff; border-color: #003a80; }
.auth-err { color: #c62828; font-weight: 700; min-height: 1.2em; margin: 6px 0 0; }
.set-byline { color: var(--muted); margin: -6px 0 10px; }
.card-actions a.btn, .sets-head a.btn, .ws-actions a.btn { text-decoration: none; }

/* admin panel (/staff/) — staff-only, reuses every token/button style above;
   just adds the side-nav + table/stat-card shapes nothing else needs. */
.admin-layout { display: flex; gap: 24px; align-items: flex-start; max-width: 1200px; margin: 0 auto; }
.admin-nav { flex: 0 0 160px; display: flex; flex-direction: column; gap: 4px; position: sticky; top: 70px; }
.admin-nav a {
  padding: 8px 12px; border-radius: 10px; color: var(--ink); text-decoration: none; font-weight: 600;
}
.admin-nav a:hover { background: var(--chip); }
.admin-nav a.on { background: var(--accent2); color: #fff; }
.admin-main { flex: 1; min-width: 0; }
.stat-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); gap: 12px; margin: 14px 0; }
.stat-card {
  background: var(--card); border: 1px solid var(--line); border-radius: var(--radius); padding: 14px 16px;
}
.stat-card .n { font-size: 1.8em; font-weight: 800; display: block; }
a.stat-card { text-decoration: none; color: inherit; }
a.stat-card:hover { border-color: var(--accent2); }
.stat-card .label { color: var(--muted); font-size: 0.85em; }
.admin-table-wrap { overflow-x: auto; }
.admin-table { width: 100%; border-collapse: collapse; background: var(--card); border-radius: var(--radius); overflow: hidden; }
.admin-table th, .admin-table td { padding: 9px 12px; border-bottom: 1px solid var(--line); text-align: left; white-space: nowrap; }
.admin-table th { background: var(--chip); font-size: 0.85em; text-transform: uppercase; letter-spacing: 0.03em; color: var(--muted); }
.admin-table td.wrap { white-space: normal; }
.admin-table tr:last-child td { border-bottom: none; }
.tag.ok { background: #d7f0db; color: #1b5e20; }
.tag.warn { background: #fde3cf; color: #a0450c; }
.flash { padding: 10px 14px; border-radius: 10px; margin: 10px 0; font-weight: 600; }
.flash-success { background: #d7f0db; color: #1b5e20; }
.flash-error { background: #fbd9d9; color: #8a1c1c; }
.admin-form { display: flex; flex-direction: column; gap: 10px; max-width: 520px; }
.admin-form label { font-weight: 700; }
.admin-form label.ps-check { display: flex; align-items: center; gap: 8px; font-weight: 500; }
.admin-form label.ps-check input { margin: 0; width: auto; }
.admin-form input[type=text], .admin-form select {
  border: 1px solid var(--line); border-radius: 8px; padding: 8px 10px; font: inherit; width: 100%;
}
.admin-search { display: flex; gap: 8px; margin: 10px 0; }
.admin-search input[type=text] { flex: 1; border: 1px solid var(--line); border-radius: 8px; padding: 8px 10px; font: inherit; }

/* staff settings: one card per choice */
.settings-form h2 { margin: 18px 0 4px; font-size: 1.15em; }
.choice-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 12px; margin: 10px 0 16px; }
.choice { display: grid; grid-template-columns: auto 1fr; gap: 4px 10px; align-items: start; background: var(--card); border: 2px solid var(--line); border-radius: var(--radius); padding: 12px 14px; cursor: pointer; }
.choice.on { border-color: var(--accent2); }
.choice input { margin-top: 3px; }
.choice b { font-size: 1.05em; }
.choice span { grid-column: 2; color: var(--muted); font-size: 0.92em; }

/* ask for help: the "?" in the top bar and its thread (help.js); the same
   thread classes dress the staff panel's Help page */
.help-btn {
  appearance: none; border: 2px solid #fff; background: transparent; color: #fff;
  width: 34px; height: 34px; border-radius: 50%; font: 800 1.1em var(--font);
  cursor: pointer; position: relative; display: inline-flex; align-items: center; justify-content: center;
}
.help-btn:hover { background: #3a3a44; }
.help-badge, .nav-count {
  position: absolute; top: -7px; right: -9px; min-width: 18px; height: 18px; padding: 0 5px;
  border-radius: 9px; background: var(--accent); color: #fff; font-size: 0.7em; line-height: 18px; text-align: center;
}
.nav-count { position: static; display: inline-block; margin-left: 4px; vertical-align: middle; }
.help-box { max-width: 520px; display: flex; flex-direction: column; max-height: calc(100vh - 32px); }
.help-intro { margin: 0 0 10px; }
.help-thread { overflow-y: auto; display: flex; flex-direction: column; gap: 8px; padding: 4px 0; min-height: 60px; max-height: 45vh; }
.help-msg {
  max-width: 85%; padding: 8px 12px; border-radius: 14px; background: var(--chip);
  font-size: 0.95em; white-space: pre-wrap; word-break: break-word;
}
.help-msg.me { align-self: flex-end; background: var(--accent2); color: #fff; }
.help-msg.staff { align-self: flex-start; }
.help-msg time { display: block; font-size: 0.75em; opacity: 0.7; margin-top: 2px; }
.help-empty { color: var(--muted); font-size: 0.95em; margin: 0; }
#help-form textarea, #help-reply-form textarea { width: 100%; margin-top: 10px; }
/* The support box: what is open, the form to start another, one request.
   The rows are kept tight -- they sit above the form on the same screen, and
   a tall list would push what you came to type off the bottom. */
.help-pane { display: flex; flex-direction: column; min-height: 0; }
.help-section { margin: 0 0 6px; font-size: 0.8em; font-weight: 700; text-transform: uppercase;
                letter-spacing: 0.05em; color: var(--muted); }
.help-open { margin-bottom: 10px; }
.help-cases { display: flex; flex-direction: column; gap: 4px; overflow-y: auto; max-height: 30vh; }
.help-case {
  appearance: none; text-align: left; font: inherit; cursor: pointer; display: flex; gap: 10px;
  align-items: baseline; padding: 6px 10px; border-radius: 10px;
  border: 1px solid var(--line); background: var(--card); color: inherit;
}
.help-case:hover { border-color: var(--accent2); }
.help-case.unread { border-color: var(--accent2); }
.help-case.closed { opacity: 0.72; }
/* the subject is what gives, so the tag and the date are never cut off */
.help-case-line { font-weight: 700; font-size: 0.92em; flex: 1; min-width: 0;
                  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.help-case-sub { font-size: 0.78em; color: var(--muted); white-space: nowrap; }
.help-cases-head { margin: 8px 0 2px; }
.help-case-head { margin: 0 0 8px; font-size: 1.05em; }
.help-tag { font-size: 0.72em; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; padding: 1px 7px;
            border-radius: 999px; background: var(--chip); color: var(--muted); }
.help-tag.new { background: var(--accent); color: #fff; }
.help-grow { flex: 1; }
.admin-tabs { display: flex; gap: 8px; flex-wrap: wrap; margin: 12px 0 16px; }
.admin-tabs .btn { text-decoration: none; }
.linkish.danger { color: var(--accent); }
.linkish.confirming { font-weight: 700; }
.help-kind { display: flex; flex-wrap: wrap; gap: 6px 18px; margin-top: 10px; font-weight: 600; }
.help-kind label { display: inline-flex; gap: 6px; align-items: center; cursor: pointer; }
.help-note { margin: 8px 0 0; font-size: 0.9em; color: var(--muted); }
.help-email-label { display: block; margin-top: 10px; font-size: 0.9em; font-weight: 600; }
#help-email { width: 100%; padding: 8px 10px; border-radius: 10px; border: 2px solid var(--line); font: inherit; }
.help-msg.wrong::before { content: "Something is wrong"; display: block; font-size: 0.75em; font-weight: 700; opacity: 0.8; }
.report-shot { display: block; max-width: 100%; width: 480px; border-radius: 10px; border: 1px solid var(--line); margin-top: 8px; }
.report-parts { font-size: 0.85em; color: var(--muted); margin-top: 6px; }
.staff-thread { max-height: none; margin: 12px 0 20px; }
.staff-thread .help-msg { max-width: 100%; align-self: stretch; white-space: normal; }
.staff-thread .help-body { white-space: pre-wrap; }
.staff-thread .help-msg.user-side { background: var(--card); border: 1px solid var(--line); }
.staff-thread .help-msg.user-side.unread { border-color: var(--accent2); border-width: 2px; }
.staff-thread .help-msg.staff-side { background: var(--chip); margin-left: 32px; }
.help-meta { font-size: 0.8em; color: var(--muted); margin-top: 4px; white-space: normal; }
.help-build summary { cursor: pointer; font-size: 0.85em; color: var(--muted); margin-top: 4px; }
.help-build pre { max-height: 220px; overflow: auto; font-size: 0.75em; white-space: pre-wrap; background: var(--chip); padding: 8px; border-radius: 8px; }
.admin-form textarea { padding: 10px; font-size: 1em; border-radius: 10px; border: 1px solid var(--line); font-family: inherit; }
.admin-table tr.unread td { font-weight: 700; }
.tag.new { background: var(--accent2); color: #fff; }

/* a page opened by one profile after another signed in on the device (base.html) */
.profile-bar { position: fixed; left: 50%; bottom: 18px; transform: translateX(-50%); z-index: 4000; max-width: min(680px, 92vw);
  background: #1f2937; color: #fff; padding: 12px 16px; border-radius: 12px; box-shadow: 0 8px 30px rgba(0,0,0,.35);
  display: flex; gap: 12px; align-items: center; font-size: 0.95em; }
.profile-bar .btn { flex: none; }

/* ---- a look round the playground (tour.js) ----
   The dark layer is a separate element from the spotlight, so the lit area
   is a real hole rather than a cut-out shadow: clicks inside it still reach
   the thing being explained. */
.tour { position: fixed; inset: 0; z-index: 2000; }
.tour-dim { position: absolute; inset: 0; background: rgba(12, 20, 30, .55); }
.tour-hole {
  position: absolute; border-radius: 14px; pointer-events: none;
  box-shadow: 0 0 0 9999px rgba(12, 20, 30, .55), 0 0 0 3px #fff;
  background: transparent; transition: top .18s ease, left .18s ease, width .18s ease, height .18s ease;
}
.tour-card {
  position: absolute; width: min(340px, calc(100vw - 20px));
  background: #fff; color: var(--ink); border-radius: 14px; padding: 14px 16px 12px;
  box-shadow: 0 16px 40px rgba(12, 20, 30, .32);
  transition: top .18s ease, left .18s ease;
}
.tour-step { font-size: .75rem; font-weight: 700; color: var(--muted); letter-spacing: .04em; }
.tour-title { font-size: 1.05rem; margin: 2px 0 6px; }
.tour-body { font-size: .92rem; line-height: 1.45; color: #3a4552; }
.tour-row { display: flex; align-items: center; gap: 8px; margin-top: 12px; }
.tour-grow { flex: 1; }
.tour-skip { appearance: none; border: 0; background: none; color: var(--muted); font: inherit; font-size: .88rem; cursor: pointer; text-decoration: underline; padding: 4px; }
.tour-row .btn { font-size: .9rem; padding: 7px 14px; }
.tour-back[disabled] { opacity: .4; cursor: default; }
@media (prefers-reduced-motion: reduce) { .tour-hole, .tour-card { transition: none; } }
/* a button that reads as a link (the walk-round link inside Contact support) */
.linkish { appearance: none; border: 0; background: none; padding: 0; font: inherit; color: var(--accent2); text-decoration: underline; cursor: pointer; }
.about-credit { font-size: 0.8em; color: #8a94a1; margin-top: 4px; }
/* the privacy page: a readable column of text */
.doc { max-width: 720px; margin: 24px auto 48px; padding: 0 20px; line-height: 1.6; color: #2c3640; }
.doc h1 { margin-bottom: 4px; }
.doc h2 { font-size: 1.2rem; margin: 28px 0 8px; }
.doc h3 { font-size: 1.02rem; margin: 20px 0 6px; }
.doc ul { padding-left: 1.2em; }
.doc li { margin: 5px 0; }
.doc-kids { background: #fff; border: 1px solid #dde3ea; border-radius: 14px; padding: 4px 20px 10px; margin-top: 18px; }
.doc-kids h2 { margin-top: 14px; }
.tray-credit a, .about-credit a { color: inherit; }
