/* Command Center — shared look for the whole app.
   Dark mode with light blue neon outlines. */

:root {
  --neon: #4fd8ff;
  --neon-dim: #3a5568;
  --bg: #060911;
  --card: #0d1420;
  --ink: #eaf6ff;
  --muted: #7c93a8;
  --danger: #ff5c7a;
}

* {
  box-sizing: border-box;
}

/* ---------- Boot intro ---------- */

#intro-screen {
  position: fixed;
  inset: 0;
  z-index: 9999;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--bg);
  transition: opacity 0.35s ease;
}

#intro-screen.intro-hide {
  opacity: 0;
  pointer-events: none;
}

#intro-content {
  text-align: center;
}

#intro-emoji {
  font-size: 64px;
  animation: intro-pop 0.5s ease-out;
}

#intro-title {
  margin: 10px 0 0;
  font-size: 32px;
  letter-spacing: 1px;
  color: var(--neon);
  opacity: 0;
  animation:
    intro-title-in 0.5s ease-out 0.25s forwards,
    intro-glow-pulse 1.4s ease-in-out 0.75s infinite;
}

@keyframes intro-pop {
  from { transform: scale(0); }
  80% { transform: scale(1.15); }
  to { transform: scale(1); }
}

@keyframes intro-title-in {
  from { opacity: 0; transform: translateY(8px); }
  to { opacity: 1; transform: translateY(0); }
}

@keyframes intro-glow-pulse {
  0%, 100% { text-shadow: 0 0 12px rgba(79, 216, 255, 0.6); }
  50% { text-shadow: 0 0 22px rgba(79, 216, 255, 1), 0 0 34px rgba(79, 216, 255, 0.6); }
}

/* ---------- Auth gate ----------
   Deliberately NOT position:fixed with its own overflow-y:auto -- an
   earlier version was, which meant it scrolled inside its own short
   nested box instead of the real page. iOS Safari's rubber-band bounce is
   a property of the actual document/viewport scrolling, not of generic
   overflow:auto divs (those only scroll -- and only then get momentum/
   elastic behavior -- when their content genuinely exceeds their height,
   which this short login form never did). Every other screen in Command
   Center bounces because it's normal in-flow body content; this is too,
   now, for the same reason. Nothing else can show through underneath
   while this is up -- #app-hub starts WITHOUT the "active" class (see
   index.html) and auth.js only adds it after a real sign-in, so this is
   genuinely the only visible content, not just visually stacked on top
   of a hidden-but-still-"active" hub. */

#auth-gate {
  background: var(--bg);
  transition: opacity 0.35s ease;
}

#auth-gate.auth-gate-hide {
  opacity: 0;
  pointer-events: none;
}

#auth-content {
  width: 100%;
  padding: 40px 20px 60px;
  text-align: center;
}

#auth-content h1 {
  color: var(--neon);
  text-shadow: 0 0 12px rgba(79, 216, 255, 0.6);
  margin: 10px 0 4px;
}

.auth-step {
  display: none;
}

.auth-step.active {
  display: block;
}

#gateForm,
#authForm {
  text-align: left;
}

.auth-two-buttons {
  display: flex;
  gap: 12px;
  margin-top: 16px;
}

.auth-two-buttons .btn {
  flex: 1;
  width: auto;
}

.btn-solid {
  background: var(--neon);
  color: var(--bg);
  text-shadow: none;
  box-shadow: 0 0 20px rgba(79, 216, 255, 0.5);
}

.auth-error {
  color: var(--danger);
  font-size: 14px;
  min-height: 18px;
  margin-top: 8px;
}

body {
  margin: 0;
  font-family: -apple-system, "Helvetica Neue", Arial, sans-serif;
  background: var(--bg);
  color: var(--ink);
  min-height: 100vh;
}

/* --- Top-level app switching (hub vs. a whole hobby) ---
   Kept separate from `.view`/`.active` further down, which each hobby uses
   internally for its OWN screens (list vs detail, home vs progress, etc).
   That way switching hobbies can never accidentally hide another hobby's
   or the hub's screens, and vice versa. */
.app-screen {
  display: none;
}

.app-screen.active {
  display: block;
}

/* Coasters (.co) and Working Out (.wt) each set their OWN "always display:
   flex" rule below, for their internal layout. A plain-vs-plain CSS rule
   is a tie by how specific it is, and ties go to whichever is written
   LATER in this file -- which was .co/.wt, not the rule above, so both
   sections were stuck showing all the time no matter what .active said.
   Naming both classes together like this counts as more specific, so
   these two lines always win instead of leaving it up to file order. */
.app-screen.co,
.app-screen.wt {
  display: none;
}

.app-screen.active.co,
.app-screen.active.wt {
  display: flex;
}

header.top {
  padding: 24px 20px 12px;
  text-align: center;
}

header.top h1 {
  margin: 0;
  font-size: 28px;
  letter-spacing: 1px;
  color: var(--neon);
  text-shadow: 0 0 12px rgba(79, 216, 255, 0.6);
}

header.top .sub {
  color: var(--muted);
  font-size: 14px;
  margin-top: 4px;
}

#logoutBtn {
  color: var(--neon);
  text-decoration: none;
}

/* --- Home grid of hobby icons --- */

.grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 16px;
  padding: 20px;
}

@media (min-width: 620px) {
  .grid {
    grid-template-columns: repeat(4, 1fr);
  }
}

.tile {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-height: 130px;
  border-radius: 20px;
  background: var(--card);
  border: 2px solid var(--neon);
  box-shadow: 0 0 14px rgba(79, 216, 255, 0.35), inset 0 0 14px rgba(79, 216, 255, 0.08);
  cursor: pointer;
  text-decoration: none;
  color: var(--ink);
  font-weight: 700;
  font-size: 16px;
  padding: 12px;
  -webkit-tap-highlight-color: transparent;
  touch-action: manipulation;
  position: relative;
}

.tile:active {
  transform: translateY(2px);
  box-shadow: 0 0 6px rgba(79, 216, 255, 0.25);
}

.tile .emoji {
  font-size: 40px;
}

.tile .icon-tile {
  width: 72px;
  height: 46px;
}

.icon-inline {
  width: 32px;
  height: 22.9px;
  vertical-align: -5px;
}

.icon-inline-small {
  width: 24px;
  height: 10.7px;
  vertical-align: -1px;
}

.tile.soon {
  border-color: var(--neon-dim);
  box-shadow: none;
  color: var(--muted);
}

.tile .badge {
  position: absolute;
  top: 8px;
  right: 8px;
  background: rgba(79, 216, 255, 0.15);
  border: 1px solid var(--neon-dim);
  padding: 2px 8px;
  border-radius: 10px;
  font-size: 10px;
  font-weight: 600;
  color: var(--muted);
}

/* --- Shared "page" chrome for hobby screens --- */

.page {
  padding: 16px 20px 60px;
}

/* A hobby's own credit line -- sits as a direct child of its #app-X
   container, AFTER every .view inside it (not inside any one .view's own
   .page). Since .view is display:none unless .active, this ends up
   rendering right below whichever sub-screen currently happens to be
   showing, the same "persistent across every sub-screen" effect Coasters
   and Working Out's scoped .app-footer rules already have (see those
   below), just without needing their extra flex-wrapper structure. */
.app-screen > .app-footer {
  text-align: center;
  padding: 14px 20px 32px;
  font-size: 12px;
  color: var(--muted);
}

a.back {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  color: var(--neon);
  text-decoration: none;
  font-weight: 700;
  padding: 10px 4px;
  min-height: 44px;
}

.card {
  background: var(--card);
  border-radius: 16px;
  padding: 16px;
  margin-bottom: 14px;
  border: 1px solid var(--neon-dim);
  box-shadow: 0 0 10px rgba(79, 216, 255, 0.12);
}

.btn {
  display: block;
  width: 100%;
  min-height: 60px;
  border-radius: 14px;
  background: transparent;
  border: 2px solid var(--neon);
  color: var(--neon);
  font-size: 18px;
  font-weight: 700;
  cursor: pointer;
  touch-action: manipulation;
  box-shadow: 0 0 14px rgba(79, 216, 255, 0.35);
}

.btn:active {
  transform: translateY(2px);
  box-shadow: 0 0 6px rgba(79, 216, 255, 0.2);
}

/* Lego's "Add a set" buttons: the CARD stays full width, but the buttons
   inside it shrink to a normal pill size and center themselves, instead
   of stretching edge to edge like the shared .btn default. Games was
   missed when this was written -- that's the whole reason its buttons
   looked wrong (2026-08-07). */
#app-lego .btn,
#app-movies .btn,
#app-games .btn,
#app-youtube .btn,
#app-songs .btn,
#app-books .btn {
  display: block;
  width: auto;
  min-width: 200px;
  padding: 0 28px;
  margin-left: auto;
  margin-right: auto;
}

/* The Rankings button renders as the LAST item inside each hobby's own
   list grid (Ben's ask: it should land in "the next slot" after however
   many things are already there, sized like whatever slot it lands in) --
   overrides the pill-shrink rule above just for this one button so it
   fills its grid cell exactly like the item cards next to it, instead of
   shrinking to a small centered pill. Written after that rule so it wins
   the tie (same specificity, later wins). */
#app-lego .rankings-slot-btn,
#app-movies .rankings-slot-btn,
#app-games .rankings-slot-btn,
#app-youtube .rankings-slot-btn,
#app-songs .rankings-slot-btn,
#app-books .rankings-slot-btn {
  width: 100%;
  min-width: 0;
  padding: 0 20px;
  margin-left: 0;
  margin-right: 0;
}

/* CSS Grid stretches every item in a row to match the row's TALLEST item
   by default -- fine when the item card next to it is plain single/double
   -line text, but Coasters' cards (name + park + a stats badge line) run
   noticeably taller, so the button was stretching well past its own
   60px-tall content into a big, mostly-empty box (found by Ben: "appears
   a little too tall"). Applies to every hobby, not just Coasters, since
   any button should keep its own natural height regardless of how tall
   its neighboring card happens to be. */
.rankings-slot-btn {
  align-self: start;
}

label {
  display: block;
  font-weight: 700;
  margin: 12px 0 6px;
  font-size: 14px;
  color: var(--muted);
}

input,
select {
  width: 100%;
  min-height: 48px;
  border-radius: 10px;
  border: 2px solid var(--neon-dim);
  background: #0a1018;
  color: var(--ink);
  padding: 0 12px;
  font-size: 16px;
}

input:focus,
select:focus {
  outline: none;
  border-color: var(--neon);
  box-shadow: 0 0 8px rgba(79, 216, 255, 0.4);
}

.empty {
  text-align: center;
  color: var(--muted);
  padding: 40px 20px;
}

/* An empty status message (like the movie/show video area between "no
   error" and "found a trailer") shouldn't still reserve its padded space
   with nothing in it -- that was the gap between the video and the
   "Change Trailer" button. */
.empty:empty {
  padding: 0;
}

.set-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 10px;
}

.set-row h3 {
  margin: 0 0 4px;
  color: var(--ink);
}

.set-details {
  font-size: 13px;
  color: var(--muted);
  line-height: 1.5;
}

.delete-btn {
  background: none;
  border: none;
  color: var(--danger);
  font-size: 22px;
  min-width: 44px;
  min-height: 44px;
  cursor: pointer;
}

/* Theme tabs -- filters a list screen (Lego, Movies, TV Shows, Songs, Books,
   YouTube) down to one theme, and makes the Rankings button on that screen
   rank just what's showing. Shows every real theme, even ones with nothing
   in them yet, so the whole catalog is browsable. */
.theme-tabs {
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem;
  margin: 4px 0 14px;
}

.theme-tab {
  min-height: 60px;
  padding: 0 1.1rem;
  border-radius: 14px;
  background: rgba(79, 216, 255, 0.08);
  border: 1px solid rgba(79, 216, 255, 0.2);
  color: var(--muted);
  font-size: 0.9rem;
  font-weight: 700;
  white-space: nowrap;
  cursor: pointer;
  touch-action: manipulation;
  transition: transform 0.15s, background 0.15s;
}

.theme-tab:active {
  transform: scale(0.95);
}

.theme-tab.active {
  color: var(--neon);
  background: rgba(79, 216, 255, 0.18);
  border-color: var(--neon);
  text-shadow: 0 0 8px rgba(79, 216, 255, 0.6);
}

.set-row {
  cursor: pointer;
}

/* On a wide screen (like an iPad), lay sets out in a grid instead of one
   stretched-out column -- same auto-fill pattern as Coasters' card-grid. */
#list {
  display: grid;
  grid-template-columns: 1fr;
  gap: 12px;
}

@media (min-width: 620px) {
  #list {
    grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  }
}

#list .card {
  margin-bottom: 0;
}

/* --- Full-screen "views" (list vs. a set's own detail screen) --- */
/* Same pattern as the Coasters app: only one view shows at a time, and
   each one is a real full screen with its own back button, not a small
   popup on top of the list. */

.view {
  display: none;
}

.view.active {
  display: block;
}

/* --- Set detail screen (#view-detail): full width, no .page cap --- */

.detail-header {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 12px;
  margin: 16px 20px 4px;
}

.back-btn {
  flex-shrink: 0;
  min-height: 60px;
  padding: 0 24px;
  border-radius: 14px;
  background: rgba(79, 216, 255, 0.1);
  border: 2px solid var(--neon);
  color: var(--neon);
  font-weight: 700;
  font-size: 16px;
  cursor: pointer;
  touch-action: manipulation;
}

.back-btn:active {
  background: rgba(79, 216, 255, 0.25);
}

.detail-header-text {
  flex: 1;
  min-width: 0;
}

.detail-header-text h2 {
  margin: 0;
  font-size: 24px;
  color: var(--ink);
}

.detail-header-text .subtle {
  margin: 4px 0 0;
  color: var(--muted);
  font-size: 14px;
}

/* Same "tap to play, can't pause/rewind, loops forever" video pattern as
   the Coasters app -- see coasters/script.js createVideoEmbed for the full
   reasoning. The iframe itself has pointer-events:none (taps pass through,
   can't be paused/rewound); a solid black button sits on top and is the
   ONLY tappable thing until the video actually starts playing. */
.video-frame {
  display: none;
  margin: 16px 20px;
  position: relative;
  border-radius: 16px;
  overflow: hidden;
  background: #000;
  border: 1px solid var(--neon-dim);
  aspect-ratio: 16 / 9;
}

.video-frame.loaded {
  display: block;
}

.video-frame iframe {
  display: block;
  width: 100%;
  height: 100%;
  border: 0;
  pointer-events: none;
}

.video-play-overlay {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: none;
  border-radius: inherit;
  background: #000;
}

.video-play-overlay.hidden {
  display: none;
}

/* A message shown INSIDE the black video-frame box itself (e.g. Books'
   "No trailer found for this one.") instead of the box disappearing and
   the message floating below it as plain text -- keeps the box's shape and
   position stable regardless of whether there's actually a video to show. */
.video-frame-message {
  position: absolute;
  inset: 0;
  display: none;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 20px;
  color: var(--muted);
  font-size: 14px;
  background: #000;
  border-radius: inherit;
}

.video-frame-message.active {
  display: flex;
}

/* YouTube-only: this button doubles as a play/pause toggle (see youtube.js),
   so while playing it needs to stay in place and tappable -- just invisible,
   not display:none like the shared .hidden state above. */
#ytVideoPlayBtn.transparent {
  background: transparent;
}

/* Stat tiles -- 2 columns on a phone-width screen, 4 across on wider
   screens like an iPad, so the info reads as a real dashboard instead of
   one cramped line of text. */
.stat-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 12px;
  padding: 4px 20px 40px;
}

@media (min-width: 620px) {
  .stat-grid {
    grid-template-columns: repeat(4, 1fr);
  }
}

.stat-tile {
  background: var(--card);
  border: 1px solid var(--neon-dim);
  border-radius: 16px;
  padding: 16px 10px;
  text-align: center;
}

.stat-value {
  font-size: 22px;
  font-weight: 800;
  color: var(--neon);
  text-shadow: 0 0 10px rgba(79, 216, 255, 0.45);
}

/* --- Books --- */
/* Books has no trailer, so its detail screen shows real cover art instead --
   that's the "coolest part" moment here, the same role a trailer plays for
   every other hobby. Just an <img>, not a video-frame -- no play button, no
   autoplay black box, it's simply there. */
.book-cover {
  margin: 16px 20px;
  display: flex;
  justify-content: center;
}

.book-cover img {
  max-width: 220px;
  width: 100%;
  border-radius: 12px;
  border: 1px solid var(--neon-dim);
  box-shadow: 0 0 14px rgba(79, 216, 255, 0.25);
}

/* Stacked (cover column above trailer) by default -- there's not enough
   width on a phone-size screen to put a book cover and a 16:9 video side by
   side and still have either be worth looking at. On an iPad-width screen
   there's room, so they sit side by side instead -- same 620px breakpoint
   the stat-grid already uses to go from 2 to 4 columns. .video-frame is
   shared by every other hobby's video, so its own base rule is left alone
   -- only zeroed out here, scoped to when it's nested in this row. */
.book-media-row {
  display: flex;
  flex-direction: column;
  gap: 16px;
  margin: 16px 20px 6px;
}

.book-media-row .video-frame {
  margin: 0;
}

/* The cover, "Change Trailer" button, and its options list all live
   together in one column -- Change Trailer stays right under the cover
   it belongs to, instead of spanning the full width below the whole row. */
.book-cover-column {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.book-cover-column .book-cover {
  margin: 0;
}

/* .book-cover stretches to fill the column's width (so its image still
   centers itself across the full 220px), but the button should only be as
   wide as it needs to be and sit centered under it -- align-self here
   instead of the shared #app-books .btn auto-margins, since this button's
   own inline style needs left/right margin room for its bottom spacing. */
.book-cover-column #bookChangeTrailerBtn {
  align-self: center;
}

@media (min-width: 620px) {
  .book-media-row {
    flex-direction: row;
    /* Stretch (not flex-start) so .book-cover-column becomes exactly as
       tall as .video-frame -- that free space is what lets the button's
       margin-top:auto below push it down to sit level with the stat-grid
       (Author's row) instead of sticking right under the cover. */
    align-items: stretch;
  }
  .book-cover-column {
    flex: 0 0 220px;
  }
  .book-media-row .video-frame {
    flex: 1;
    min-width: 0;
    /* Opts back OUT of the row's stretch above -- keeps its own
       aspect-ratio-derived height exactly like before, so this change only
       ever affects the button's position, nothing about the video box. */
    align-self: flex-start;
  }
}

/* --- Movies & Shows --- */
/* Same list-of-cards layout as Lego's #list -- see there for why it's a
   grid on wider screens. movies.js reuses Lego's existing .set-row and
   .set-details classes for each row's look, so no new row styling is
   needed here, just the container. */

/* Coasters' videos are baked into the app ahead of time, so their
   video-frame just appears instantly, fully ready. A movie/show's trailer
   has to be looked up fresh over the network the first time, which takes
   a moment -- rather than leaving the whole box hidden (display:none)
   until that finishes and popping in abruptly once it's done, this shows
   the box immediately with a spinner in it, so the frame never seems to
   vanish and reappear -- it just fills in. */
.video-loading {
  position: absolute;
  inset: 0;
  display: none;
  align-items: center;
  justify-content: center;
  background: #000;
  border-radius: inherit;
}

.video-loading.active {
  display: flex;
}

.video-loading::after {
  content: "";
  width: 34px;
  height: 34px;
  border: 4px solid rgba(79, 216, 255, 0.25);
  border-top-color: var(--neon);
  border-radius: 50%;
  animation: video-loading-spin 0.8s linear infinite;
}

@keyframes video-loading-spin {
  to {
    transform: rotate(360deg);
  }
}

#movieList,
#showList,
#gameList,
#ytList {
  display: grid;
  grid-template-columns: 1fr;
  gap: 12px;
}

@media (min-width: 620px) {
  #movieList,
  #showList,
  #gameList,
  #ytList {
    grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  }
}

#movieList .card,
#showList .card,
#gameList .card,
#ytList .card {
  margin-bottom: 0;
}

/* Search results (only shown when a title matches more than one movie,
   show, or game) -- plain tappable rows, same .set-row look as everything
   else. */
#movieSearchResults:not(:empty),
#showSearchResults:not(:empty),
#gameSearchResults:not(:empty),
#ytSearchResults:not(:empty) {
  margin-top: 12px;
  display: grid;
  gap: 10px;
}

/* Trailer options (only shown once "Change Trailer" is tapped) -- same
   tappable-row look, indented under the detail screen's stat-grid width. */
#movieTrailerOptions:not(:empty),
#showTrailerOptions:not(:empty) {
  margin: 0 20px 20px;
  display: grid;
  gap: 10px;
}

.stat-label {
  margin-top: 6px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--muted);
}

/* ============================================================
   Working Out -- a faithful port of the standalone Workout Tracker
   app's own layout/components (same button shapes, same icon system,
   same spacing), just recolored to Command Center's dark + neon-blue
   palette instead of its own white-accent one. Everything below is
   scoped under .wt (workout.html's <body class="wt">) so it can't
   collide with Lego's or the home grid's styles.
   ============================================================ */

.wt * { box-sizing: border-box; }

/* Every tappable thing in this app is a real <button>, so one rule gives
   every button a satisfying little "press" -- shrink slightly on tap,
   spring back on release. */
.wt button { transition: transform 0.1s ease; }
.wt button:active { transform: scale(0.92); }

.wt {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
  overflow-wrap: break-word;
  overflow-x: hidden;
}

/* Same wrapper pattern as Coasters' #app/.views-wrap -- one flexible box
   that grows to fill the space, so the footer sticks to the bottom
   instead of everything overlapping. */
.wt .wt-app { flex: 1; display: flex; flex-direction: column; }
.wt .wt-views-wrap { flex: 1; }

.wt .view { padding: 20px 16px 48px; }
.hidden { display: none !important; }

.wt .app-footer {
  flex-shrink: 0;
  text-align: center;
  padding: 14px 16px 24px;
  font-size: 12px;
  color: var(--muted);
}

/* ---------- icons ---------- */
.wt .icon { display: inline-block; vertical-align: -4px; flex-shrink: 0; }
.wt .icon-sm { width: 16px; height: 16px; vertical-align: -3px; }
.wt .icon-md { width: 22px; height: 22px; vertical-align: -4px; }
.wt .icon-lg { width: 32px; height: 32px; vertical-align: -7px; }
.wt .icon-xl { width: 40px; height: 40px; }

.wt .app-title {
  font-size: 32px;
  font-weight: 800;
  margin: 8px 0 4px;
  color: var(--neon);
  text-shadow: 0 0 18px rgba(79, 216, 255, 0.5);
}
.wt .app-title.small { font-size: 24px; margin-top: 12px; }

.wt .app-subtitle {
  color: var(--muted);
  margin: 0 0 24px;
  font-size: 16px;
}

.wt .welcome-line {
  color: var(--muted);
  font-size: 15px;
  margin: 0 0 18px;
}
.wt .welcome-line span { color: var(--ink); font-weight: 700; }

.wt .streak-banner {
  display: flex;
  align-items: center;
  gap: 12px;
  min-height: 56px;
  padding: 0 16px;
  margin-bottom: 18px;
  border-radius: 14px;
  border: 1px solid var(--neon-dim);
  background: var(--card);
  font-size: 16px;
  font-weight: 800;
  color: var(--ink);
}
.wt .streak-banner-empty {
  font-weight: 700;
  color: var(--muted);
}
.wt .streak-banner-empty svg { opacity: 0.45; }

/* ---------- form fields ---------- */
.wt .field-label {
  display: block;
  font-size: 14px;
  color: var(--muted);
  margin: 18px 0 6px;
}
.wt .text-input {
  width: 100%;
  min-height: 52px;
  padding: 0 14px;
  border-radius: 12px;
  border: 1px solid var(--neon-dim);
  background: #0a1018;
  color: var(--ink);
  font-size: 17px;
  font-family: inherit;
}
.wt .text-input:focus { outline: none; border-color: var(--neon); }
.wt .textarea { min-height: 90px; padding: 12px 14px; resize: vertical; line-height: 1.4; }

.wt .auth-error {
  color: var(--danger);
  font-size: 14px;
  margin: 14px 0 0;
}

/* ---------- buttons ---------- */
.wt .btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  width: auto;
  min-height: 52px;
  border-radius: 12px;
  border: none;
  font-size: 16px;
  font-weight: 700;
  font-family: inherit;
  padding: 0 20px;
  cursor: pointer;
  text-decoration: none;
}
.wt .btn-solid { background: var(--neon); color: var(--bg); }
.wt .btn-outline {
  background: transparent;
  border: 1px solid var(--neon);
  color: var(--neon);
}
.wt .btn-ghost {
  background: transparent;
  border: 1px solid var(--neon-dim);
  color: var(--muted);
}
.wt .btn-small { min-height: 44px; font-size: 14px; padding: 0 14px; }

.wt .modal-buttons {
  display: flex;
  flex-direction: column;
  gap: 12px;
  margin-top: 24px;
}

/* ---------- header ---------- */
.wt .app-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin-bottom: 4px;
}
.wt .header-buttons { display: flex; flex-wrap: wrap; gap: 10px; }

/* ---------- category tiles ---------- */
.wt .surprise-me-btn {
  display: flex;
  width: 100%;
  align-items: center;
  justify-content: center;
  gap: 8px;
  margin-bottom: 18px;
}

.wt .tile-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 14px;
  margin-top: 8px;
}
.wt .category-tile {
  min-height: 130px;
  border-radius: 16px;
  border: 1px solid var(--neon-dim);
  background: var(--card);
  color: var(--ink);
  font-family: inherit;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 8px;
  cursor: pointer;
}
.wt .category-tile .tile-icon { display: flex; }
.wt .category-tile .tile-label { font-size: 17px; font-weight: 700; }

/* ---------- exercise list ---------- */
.wt .exercise-list {
  display: flex;
  flex-direction: column;
  gap: 12px;
  margin-top: 16px;
}
.wt .exercise-card {
  min-height: 64px;
  border-radius: 14px;
  border: 1px solid var(--neon-dim);
  background: var(--card);
  color: var(--ink);
  font-family: inherit;
  text-align: left;
  padding: 14px 16px;
  cursor: pointer;
  width: 100%;
}
.wt .exercise-card .ex-name { font-size: 17px; font-weight: 700; margin-bottom: 4px; }
.wt .exercise-card .ex-preview {
  font-size: 13px;
  color: var(--muted);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* ---------- exercise detail ---------- */
.wt .exercise-detail { margin: 8px 0 20px; }
.wt .detail-heading {
  font-size: 15px;
  color: var(--ink);
  margin: 18px 0 6px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.wt .detail-text { font-size: 16px; line-height: 1.5; color: #d8dbe1; margin: 0; }
.wt .detail-hint { font-size: 14px; color: var(--muted); margin: 0 0 12px; }

.wt .chip-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
}
.wt .chip-btn {
  min-height: 60px;
  border-radius: 12px;
  border: 1px solid var(--neon-dim);
  background: var(--card);
  color: var(--ink);
  font-family: inherit;
  font-size: 17px;
  font-weight: 700;
  cursor: pointer;
}
.wt .chip-btn:active { background: var(--neon); color: var(--bg); border-color: var(--neon); }

.wt .hold-timer-section {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 16px;
  padding: 24px 0;
  border-radius: 14px;
  border: 1px solid var(--neon-dim);
  background: var(--card);
}
.wt .hold-timer-display {
  font-size: 48px;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  color: var(--ink);
}
.wt .hold-timer-btn {
  min-width: 200px;
}
.wt .hold-timer-btn.running {
  background: var(--danger);
  color: var(--bg);
}

.wt .custom-reps-hint { margin-top: 18px; }
.wt .custom-reps-row {
  display: flex;
  gap: 10px;
}
.wt .custom-reps-row .text-input { flex: 1; }
.wt .custom-reps-row .btn { flex-shrink: 0; }

.wt .log-confirm {
  margin-top: 18px;
  font-size: 17px;
  font-weight: 700;
  color: #4ade80;
  text-align: center;
  opacity: 1;
  transition: opacity 0.4s ease;
}
.wt .log-confirm.fade-out { opacity: 0; }

@keyframes wtLogConfirmPop {
  from { transform: scale(0); }
  80% { transform: scale(1.15); }
  to { transform: scale(1); }
}
.wt .log-confirm.pop { animation: wtLogConfirmPop 0.3s ease-out; }

.wt .delete-exercise-btn {
  display: block;
  width: 100%;
  margin-top: 28px;
  color: var(--danger);
  border-color: var(--danger);
}

.wt .exercise-card.add-exercise-card {
  border-style: dashed;
  text-align: center;
  color: var(--muted);
  font-weight: 700;
}

/* ---------- progress / calendar ---------- */
.wt .calendar-nav {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 20px;
  margin: 16px 0;
}
.wt .calendar-month-label { font-size: 17px; font-weight: 700; min-width: 150px; text-align: center; }

.wt .calendar-grid {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 6px;
}
.wt .calendar-dow {
  text-align: center;
  font-size: 12px;
  color: var(--muted);
  padding-bottom: 4px;
}
.wt .calendar-day {
  aspect-ratio: 1;
  min-height: 38px;
  border-radius: 10px;
  border: 1px solid var(--neon-dim);
  background: var(--card);
  color: #d8dbe1;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 14px;
}
.wt .calendar-day.empty { border: none; background: transparent; }
.wt .calendar-day.worked-out {
  background: var(--neon);
  color: var(--bg);
  border-color: var(--neon);
  font-weight: 800;
}

.wt .totals-heading { margin-top: 28px; }
.wt .totals-list {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-top: 10px;
}
.wt .totals-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  min-height: 52px;
  border-radius: 12px;
  border: 1px solid var(--neon-dim);
  background: var(--card);
  padding: 0 16px;
  font-size: 15px;
}
.wt .totals-row .totals-name { font-weight: 700; }
.wt .totals-row .totals-count { color: var(--ink); font-weight: 800; }

.wt .log-history {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-top: 10px;
}
.wt .log-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  min-height: 56px;
  border-radius: 12px;
  border: 1px solid var(--neon-dim);
  background: var(--card);
  padding: 8px 8px 8px 16px;
  font-size: 14px;
}
.wt .log-row .log-info { flex: 1; min-width: 0; }
.wt .log-row .log-name { font-weight: 700; }
.wt .log-row .log-meta { color: var(--muted); font-size: 12px; }
.wt .log-row .btn-delete {
  min-height: 44px;
  min-width: 44px;
  border: none;
  background: transparent;
  color: var(--danger);
  font-size: 20px;
  font-family: inherit;
  cursor: pointer;
}

/* ---------- measurements ---------- */
.wt .chart-box {
  margin-top: 10px;
  border-radius: 14px;
  border: 1px solid var(--neon-dim);
  background: var(--card);
  padding: 12px;
}
.wt .chart-box svg { display: block; width: 100%; height: auto; }
.wt .chart-box polyline { stroke: var(--neon); }
.wt .chart-box circle { fill: var(--neon); }
.wt .chart-empty { color: var(--muted); font-size: 14px; text-align: center; padding: 20px 0; }
.wt .empty { color: var(--muted); font-size: 14px; text-align: center; padding: 20px 0; }

.wt .weight-history {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-top: 10px;
}
.wt .weight-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  min-height: 52px;
  border-radius: 12px;
  border: 1px solid var(--neon-dim);
  background: var(--card);
  padding: 0 8px 0 16px;
  font-size: 15px;
}
.wt .weight-row .weight-date { color: var(--muted); }
.wt .weight-row .weight-value { font-weight: 800; }
.wt .weight-row .btn-delete {
  min-height: 44px;
  min-width: 44px;
  border: none;
  background: transparent;
  color: var(--danger);
  font-size: 20px;
  font-family: inherit;
  cursor: pointer;
}

/* ---------- personal records ---------- */
.wt .pr-quickpicks { margin: 10px 0 18px; }
.wt .pr-quickpick-btn { font-size: 14px; }
.wt .pr-unit-btn { flex-shrink: 0; min-width: 56px; }
.wt .pr-unit-btn.active { background: var(--neon); color: var(--bg); border-color: var(--neon); }

.wt .pr-list {
  display: flex;
  flex-direction: column;
  gap: 16px;
  margin-top: 24px;
}
.wt .pr-card {
  border-radius: 14px;
  border: 1px solid var(--neon-dim);
  background: var(--card);
  padding: 16px;
}
.wt .pr-card-header {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  margin-bottom: 10px;
}
.wt .pr-card-name { font-size: 17px; font-weight: 800; }
.wt .pr-card-best { font-size: 15px; font-weight: 800; color: var(--ink); }
.wt .pr-card .chart-box { margin-top: 0; border: none; background: transparent; padding: 8px 0; }

.wt .leaderboard-row {
  display: flex;
  align-items: center;
  gap: 14px;
}
.wt .leaderboard-rank {
  font-size: 20px;
  font-weight: 800;
  color: var(--muted);
  width: 28px;
  text-align: center;
  flex-shrink: 0;
}
.wt .leaderboard-row.leaderboard-me .leaderboard-rank { color: var(--neon); }
.wt .leaderboard-name {
  flex: 1;
  font-size: 17px;
  font-weight: 800;
}
.wt .leaderboard-stats {
  text-align: right;
  font-size: 13px;
  color: var(--muted);
}
.wt .leaderboard-stats strong {
  display: block;
  font-size: 17px;
  color: var(--ink);
}

.wt .pr-history {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-top: 8px;
}
.wt .pr-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  min-height: 44px;
  border-radius: 10px;
  background: #0a1018;
  padding: 0 6px 0 12px;
  font-size: 14px;
}
.wt .pr-row .pr-date { color: var(--muted); }
.wt .pr-row .pr-value { font-weight: 700; }

/* ---------- workout routines ---------- */
.wt .routine-list {
  display: flex;
  flex-direction: column;
  gap: 16px;
  margin-top: 20px;
}
.wt .routine-card {
  border-radius: 14px;
  border: 1px solid var(--neon-dim);
  background: var(--card);
  padding: 16px;
}
.wt .routine-card-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 10px;
}
.wt .routine-card-name { font-size: 18px; font-weight: 800; }
.wt .routine-card ul {
  list-style: none;
  margin: 0 0 14px;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.wt .routine-card li {
  font-size: 14px;
  color: var(--muted);
  display: flex;
  justify-content: space-between;
}
.wt .routine-card li span:last-child { color: #d8dbe1; font-weight: 700; }
.wt .routine-card-buttons { display: flex; gap: 10px; }
.wt .routine-card-buttons .btn-solid { flex: 1; }
.wt .routine-card-buttons .btn-ghost { flex: 1; }

.wt .routine-picker-category { margin-top: 14px; }
.wt .routine-picker-category-name {
  font-size: 13px;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.03em;
  margin: 0 0 8px;
}
.wt .routine-picker-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}
.wt .routine-pick-btn {
  min-height: 44px;
  border-radius: 10px;
  border: 1px solid var(--neon-dim);
  background: var(--card);
  color: var(--ink);
  font-family: inherit;
  font-size: 14px;
  font-weight: 700;
  padding: 0 14px;
  cursor: pointer;
}
.wt .routine-pick-btn.added {
  background: var(--neon);
  color: var(--bg);
  border-color: var(--neon);
}

.wt .routine-selected-list {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-top: 10px;
}
.wt .routine-selected-row {
  display: flex;
  align-items: center;
  gap: 8px;
  min-height: 52px;
  border-radius: 12px;
  border: 1px solid var(--neon-dim);
  background: var(--card);
  padding: 0 8px 0 14px;
}
.wt .routine-selected-row .routine-selected-name {
  flex: 1;
  font-size: 14px;
  font-weight: 700;
}
.wt .routine-selected-row .text-input {
  width: 90px;
  min-height: 40px;
  font-size: 14px;
  padding: 0 10px;
  flex-shrink: 0;
}

/* ---------- badges ---------- */
.wt .badge-grid {
  display: flex;
  flex-direction: column;
  gap: 12px;
  margin-top: 16px;
}
.wt .badge-card {
  border-radius: 14px;
  border: 1px solid var(--neon-dim);
  background: var(--card);
  padding: 14px 16px;
  display: flex;
  align-items: center;
  gap: 14px;
  min-height: 72px;
}
.wt .badge-card.locked { opacity: 0.45; }
.wt .badge-card .badge-icon { display: flex; }
.wt .badge-card .badge-info { flex: 1; }
.wt .badge-card .badge-name { font-size: 16px; font-weight: 800; margin-bottom: 2px; }
.wt .badge-card .badge-desc { font-size: 13px; color: var(--muted); margin-bottom: 4px; }
.wt .badge-card .badge-progress { font-size: 12px; color: var(--ink); font-weight: 700; }

/* ============================================================
   Coasters -- a faithful port of the standalone Coaster Explorer
   app's own layout/components (same cards, tabs, chips, stat grids),
   just recolored to Command Center's neon-blue instead of its own
   cyan/magenta pair. Scoped under body.co so it can't collide with
   Lego's, Working Out's (.wt), or the home grid's styles. The
   magenta accent-2 (inversions) and green (ridden) stay as-is --
   functional secondary colors, not part of the app-identity palette.
   ============================================================ */

.co {
  --bg-panel: var(--card);
  --accent: var(--neon);
  --accent-2: #ff2fd0;
  --text: var(--ink);
  --text-dim: var(--muted);
  margin: 0;
  min-height: 100vh;
  font-family: system-ui, -apple-system, sans-serif;
  background: linear-gradient(160deg, var(--bg) 0%, var(--card) 55%, var(--bg) 100%);
  background-attachment: fixed;
  color: var(--text);
  display: flex;
  flex-direction: column;
}

.co * { -webkit-tap-highlight-color: transparent; touch-action: manipulation; }

.co #app { padding-bottom: 1rem; flex: 1; display: flex; flex-direction: column; }
.co .views-wrap { flex: 1; }

.co .back { padding-left: 1.25rem; }

.co .topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 0.75rem;
  padding: 1.25rem 1.25rem 1rem;
}

.co .topbar h1 {
  margin: 0;
  font-size: 1.6rem;
  font-weight: 800;
  text-shadow: 0 0 14px rgba(79, 216, 255, 0.55);
  letter-spacing: -0.01em;
}
.co .topbar h1 .coaster-icon {
  vertical-align: -5px;
  margin-right: 4px;
  filter: drop-shadow(0 0 8px rgba(79, 216, 255, 0.55));
}

.co .subtle { color: var(--text-dim); margin: 0 1.25rem 1rem; font-size: 1rem; }

.co .app-footer {
  text-align: center;
  padding: 1.5rem 1.25rem 2rem;
  color: var(--text-dim);
  font-size: 0.8rem;
}

/* Cards (parks, coasters, search results) */
.co .card-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 1rem;
  padding: 0.5rem 1.25rem 2rem;
}

@media (min-width: 620px) {
  .co .card-grid { grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); }
}

.co .card {
  position: relative;
  background: var(--bg-panel);
  border: 1px solid rgba(79, 216, 255, 0.15);
  border-radius: 20px;
  padding: 1.5rem;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.4);
  cursor: pointer;
  min-height: 60px;
  transition: transform 0.12s ease, border-color 0.12s ease;
}

.co .rank-badge {
  position: absolute;
  top: 0.9rem;
  right: 1rem;
  font-size: 1.1rem;
  font-weight: 800;
  color: var(--accent-2);
  text-shadow: 0 0 8px rgba(255, 47, 208, 0.5);
}
.co .card:has(.rank-badge) .card-title { padding-right: 3rem; }

.co .star-btn, .co .ridden-btn {
  position: absolute;
  width: 60px;
  height: 60px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: none;
  border: none;
  font-size: 1.4rem;
  color: var(--text-dim);
  z-index: 2;
}
.co .star-btn { top: 0; left: 0; }
.co .ridden-btn { bottom: 0; right: 0; }
.co .star-btn:active, .co .ridden-btn:active { transform: scale(0.85); }
.co .star-btn.active {
  color: var(--accent);
  filter: drop-shadow(0 0 6px rgba(79, 216, 255, 0.6));
}
.co .ridden-btn.active {
  color: #39ff8f;
  text-shadow: 0 0 10px rgba(57, 255, 143, 0.6);
}
.co .card:has(.star-btn) .card-title,
.co .card:has(.star-btn) .card-result-type { padding-left: 2.4rem; }
.co .card:has(.ridden-btn) { padding-bottom: 3.75rem; }

.co .detail-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  margin: 0.5rem 1.25rem 1.25rem;
}

.co .favorite-toggle-btn, .co .ridden-toggle-btn {
  flex: 1;
  min-width: 160px;
  min-height: 60px;
  padding: 0 1.25rem;
  border-radius: 14px;
  background: rgba(79, 216, 255, 0.08);
  border: 1px solid rgba(79, 216, 255, 0.2);
  color: var(--text-dim);
  font-weight: 700;
  font-size: 1rem;
  transition: transform 0.12s ease, color 0.12s ease, border-color 0.12s ease;
}
.co .favorite-toggle-btn:active, .co .ridden-toggle-btn:active { transform: scale(0.97); }
.co .toggle-btn-content {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
}
.co .toggle-btn-content svg { flex-shrink: 0; }
.co .favorite-toggle-btn.active {
  color: var(--accent);
  border-color: var(--accent);
  text-shadow: 0 0 8px rgba(79, 216, 255, 0.6);
}
.co .favorite-toggle-btn.active svg { filter: drop-shadow(0 0 6px rgba(79, 216, 255, 0.6)); }
.co .ridden-toggle-btn.active {
  color: #39ff8f;
  border-color: #39ff8f;
  background: rgba(57, 255, 143, 0.08);
  text-shadow: 0 0 8px rgba(57, 255, 143, 0.6);
}

.co .sort-row {
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem;
  padding: 1rem 1.25rem 0.25rem;
}
.co .sort-btn {
  min-height: 60px;
  padding: 0 1.1rem;
  border-radius: 14px;
  background: rgba(79, 216, 255, 0.08);
  border: 1px solid rgba(79, 216, 255, 0.2);
  color: var(--text-dim);
  font-size: 0.9rem;
  font-weight: 700;
  white-space: nowrap;
  transition: transform 0.15s, background 0.15s;
}
.co .sort-btn:active { transform: scale(0.95); }
.co .sort-btn.active {
  color: var(--accent);
  background: rgba(79, 216, 255, 0.18);
  border-color: var(--accent);
  text-shadow: 0 0 8px rgba(79, 216, 255, 0.6);
}

.co .card:active {
  transform: scale(0.97);
  border-color: var(--accent);
}

.co .card-title { font-size: 1.25rem; font-weight: 700; }
.co .card-sub { color: var(--text-dim); font-size: 0.95rem; margin-top: 0.25rem; }
.co .card-count {
  display: inline-block;
  margin-top: 0.75rem;
  font-size: 0.8rem;
  font-weight: 700;
  color: var(--accent);
  background: rgba(79, 216, 255, 0.1);
  padding: 0.3rem 0.7rem;
  border-radius: 999px;
}
.co .card-badge {
  display: inline-block;
  margin-top: 0.75rem;
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--text-dim);
}
.co .card-result-type {
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: 0.35rem;
}

/* Buttons */
.co .detail-header {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.75rem;
  margin: 1rem 1.25rem 0.1rem;
}

.co .back-btn {
  display: inline-block;
  flex-shrink: 0;
  min-height: 60px;
  padding: 0 1.5rem;
  border-radius: 14px;
  background: rgba(79, 216, 255, 0.1);
  border: 1px solid var(--accent);
  color: var(--accent);
  font-weight: 700;
  font-size: 1rem;
}
.co .back-btn:active { background: rgba(79, 216, 255, 0.25); }

.co h2 { margin: 0; font-size: 1.7rem; font-weight: 800; }

.co .detail-header-text { flex: 1; min-width: 0; }
.co .detail-header-text .subtle { margin: 0.15rem 0 0; }

.co .park-link {
  margin: 0 1.25rem 1rem;
  font-size: 0.95rem;
  color: var(--accent);
  font-weight: 600;
  cursor: pointer;
  text-decoration: underline;
  text-underline-offset: 3px;
}

.co .stat-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 1rem;
  padding: 0.5rem 1.25rem;
}
@media (min-width: 620px) {
  .co .stat-grid { grid-template-columns: repeat(4, 1fr); }
}

.co .stat-tile {
  background: var(--bg-panel);
  border: 1px solid rgba(79, 216, 255, 0.12);
  border-radius: 18px;
  padding: 1.25rem 0.75rem;
  text-align: center;
}
.co .stat-value {
  font-size: 1.9rem;
  font-weight: 800;
  color: var(--accent);
  text-shadow: 0 0 10px rgba(79, 216, 255, 0.45);
}
.co .stat-unit { font-size: 1rem; margin-left: 2px; color: var(--text-dim); font-weight: 600; }
.co .stat-label {
  margin-top: 0.35rem;
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--text-dim);
}

/* Inversions */
.co .chip-heading {
  margin: 1.5rem 1.25rem 0.5rem;
  font-size: 1rem;
  font-weight: 700;
  color: var(--text-dim);
  text-transform: uppercase;
  letter-spacing: 0.05em;
}
.co .chip-row { display: flex; flex-wrap: wrap; gap: 0.6rem; padding: 0 1.25rem 2rem; }
.co .chip {
  background: rgba(255, 47, 208, 0.12);
  border: 1px solid var(--accent-2);
  color: var(--accent-2);
  padding: 0.5rem 1rem;
  border-radius: 999px;
  font-size: 0.85rem;
  font-weight: 700;
}
.co .chip.none {
  border-color: var(--text-dim);
  color: var(--text-dim);
  background: rgba(127, 147, 171, 0.08);
}

/* Search (also used by the coaster picker inside the Compare tab) */
.co #searchInput, .co #pickerSearchInput {
  display: block;
  width: calc(100% - 2.5rem);
  min-height: 60px;
  margin: 1rem 1.25rem;
  padding: 0 1.25rem;
  border-radius: 16px;
  background: var(--bg-panel);
  border: 1px solid rgba(79, 216, 255, 0.25);
  color: var(--text);
  font-size: 1.05rem;
}
.co #searchInput::placeholder, .co #pickerSearchInput::placeholder { color: var(--text-dim); }
.co #searchInput:focus, .co #pickerSearchInput:focus { outline: none; border-color: var(--accent); }

.co .picker-header {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  margin: 1rem 1.25rem 1rem;
}
.co .picker-header #pickerSearchInput {
  width: auto;
  flex: 1;
  min-width: 0;
  margin: 0;
}

.co .empty-msg { color: var(--text-dim); padding: 1rem 1.25rem; font-size: 1rem; }

/* Tab bar -- sits right next to the title in the header */
.co .tabbar {
  display: flex;
  gap: 0.5rem;
}
.co .tab-btn {
  min-height: 60px;
  padding: 0 1.1rem;
  border-radius: 14px;
  background: rgba(79, 216, 255, 0.08);
  border: 1px solid rgba(79, 216, 255, 0.2);
  color: var(--text-dim);
  font-size: 0.9rem;
  font-weight: 700;
  white-space: nowrap;
  transition: transform 0.15s, background 0.15s;
  display: inline-block;
  text-decoration: none;
}
.co .tab-btn:active { transform: scale(0.92); }
.co .icon { vertical-align: -4px; margin-right: 2px; flex-shrink: 0; }
.co .tab-btn.active .icon {
  filter: drop-shadow(0 0 4px rgba(79, 216, 255, 0.6));
}
.co .tab-btn.active {
  color: var(--accent);
  background: rgba(79, 216, 255, 0.18);
  border-color: var(--accent);
  text-shadow: 0 0 8px rgba(79, 216, 255, 0.6);
}

/* Compare tab */
.co .compare-slots {
  display: flex;
  align-items: stretch;
  gap: 0.75rem;
  padding: 1rem 1.25rem 0.5rem;
}
.co .compare-slot { flex: 1; min-width: 0; }

.co .compare-slot-empty {
  width: 100%;
  min-height: 100px;
  border-radius: 20px;
  background: var(--bg-panel);
  border: 2px dashed rgba(79, 216, 255, 0.3);
  color: var(--text-dim);
  font-weight: 700;
  font-size: 0.95rem;
  line-height: 1.6;
}
.co .compare-slot-empty:active { transform: scale(0.97); }

.co .compare-slot-filled {
  min-height: 100px;
  border-radius: 20px;
  background: var(--bg-panel);
  border: 1px solid rgba(79, 216, 255, 0.2);
  padding: 1rem;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: 0.5rem;
}
.co .compare-change-btn {
  align-self: flex-start;
  min-height: 60px;
  padding: 0 1rem;
  border-radius: 10px;
  background: rgba(79, 216, 255, 0.1);
  border: 1px solid rgba(79, 216, 255, 0.25);
  color: var(--accent);
  font-weight: 700;
  font-size: 0.8rem;
}

.co .compare-vs {
  align-self: center;
  color: var(--accent-2);
  font-weight: 800;
  font-size: 0.9rem;
  text-shadow: 0 0 8px rgba(255, 47, 208, 0.5);
}

.co #compareTable { padding: 0.5rem 1.25rem 2rem; }

.co .compare-row {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: 0.75rem;
  padding: 0.85rem 0;
  border-bottom: 1px solid rgba(79, 216, 255, 0.1);
}
.co .compare-row:last-child { border-bottom: none; }

.co .compare-value {
  font-size: 1.1rem;
  font-weight: 700;
  text-align: center;
  color: var(--text);
}
.co .compare-value.win {
  color: var(--accent);
  text-shadow: 0 0 8px rgba(79, 216, 255, 0.6);
}

.co .compare-label {
  font-size: 0.75rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--text-dim);
  text-align: center;
  white-space: nowrap;
}

.co .closed-badge {
  display: inline-block;
  margin-top: 0.5rem;
  font-size: 0.75rem;
  font-weight: 800;
  letter-spacing: 0.03em;
  color: var(--danger);
  background: rgba(255, 92, 122, 0.12);
  border: 1px solid rgba(255, 92, 122, 0.4);
  padding: 0.3rem 0.7rem;
  border-radius: 999px;
}

.co .closed-notice {
  margin: 1rem 1.25rem;
  padding: 0.85rem 1.1rem;
  border-radius: 14px;
  background: rgba(255, 92, 122, 0.1);
  border: 1px solid rgba(255, 92, 122, 0.35);
  color: var(--danger);
  font-size: 0.9rem;
  font-weight: 600;
  line-height: 1.4;
}

.co .video-frame {
  display: none;
  position: relative;
  margin: 1rem 1.25rem;
  border-radius: 20px;
  overflow: hidden;
  background: var(--bg-panel);
  border: 1px solid rgba(79, 216, 255, 0.15);
  aspect-ratio: 16 / 9;
}
.co .video-frame.loaded { display: block; }
.co .video-frame iframe {
  display: block;
  width: 100%;
  height: 100%;
  border: 0;
  pointer-events: none;
}

.co .video-play-overlay {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: none;
  border-radius: inherit;
  background: #000;
}
.co .video-play-overlay.hidden { display: none; }

/* ============================================================
   Drums -- a mini menu (Drum Pad vs Metronome), built fresh for
   Command Center rather than ported from another app. Chrome (headers,
   buttons, back links, the menu tiles) stays on the shared --neon look
   like every other section. The four pad colors below are functional
   color-coding for the drum kit itself -- same idea as Coasters' magenta
   accent for inversions -- not a separate app identity.
   ============================================================ */

.hobby-menu-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 16px;
  margin-top: 8px;
}

@media (min-width: 480px) {
  .hobby-menu-grid {
    grid-template-columns: 1fr 1fr;
  }
}

.pad-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 16px;
  margin-top: 12px;
}

.pad {
  min-height: 140px;
  border-radius: 20px;
  background: var(--card);
  border: 3px solid var(--neon);
  color: var(--neon);
  font-size: 20px;
  font-weight: 800;
  cursor: pointer;
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
  transition: transform 0.05s;
}

.pad:active,
.pad.hit {
  transform: scale(0.96);
  color: var(--bg);
}

.pad[data-drum="kick"]  { border-color: #ffb84f; color: #ffb84f; box-shadow: 0 0 14px rgba(255, 184, 79, 0.35); }
.pad[data-drum="snare"] { border-color: #ff6a4f; color: #ff6a4f; box-shadow: 0 0 14px rgba(255, 106, 79, 0.35); }
.pad[data-drum="hihat"] { border-color: #4fd8ff; color: #4fd8ff; box-shadow: 0 0 14px rgba(79, 216, 255, 0.35); }
.pad[data-drum="crash"] { border-color: #ffe14f; color: #ffe14f; box-shadow: 0 0 14px rgba(255, 225, 79, 0.35); }

.pad.hit[data-drum="kick"]  { background: #ffb84f; }
.pad.hit[data-drum="snare"] { background: #ff6a4f; }
.pad.hit[data-drum="hihat"] { background: #4fd8ff; }
.pad.hit[data-drum="crash"] { background: #ffe14f; }

.metronome-card {
  text-align: center;
  padding: 28px 16px;
}

.bpm-display {
  font-size: 48px;
  font-weight: 800;
  color: var(--neon);
  text-shadow: 0 0 12px rgba(79, 216, 255, 0.5);
}

.bpm-display .bpm-label {
  font-size: 16px;
  color: var(--muted);
  font-weight: 700;
}

#bpmSlider {
  width: 100%;
  margin: 20px 0;
  accent-color: var(--neon);
  height: 40px;
}

.beat-dot {
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: var(--neon-dim);
  box-shadow: none;
  margin: 8px auto 24px;
  transition: background 0.05s, box-shadow 0.05s;
}

.beat-dot.pulse {
  background: var(--neon);
  box-shadow: 0 0 16px rgba(79, 216, 255, 0.8);
}

/* ============================================================
   Coding -- Idea Lab & Build Log, built fresh for Command Center
   (third attempt at this hobby -- see PLAN.md). Same shared --neon
   look as the rest of the app, no separate accent color, per Ben.
   ============================================================ */

#codingIdeaCard {
  text-align: center;
}

.coding-idea-card-prompt {
  margin: 4px 0 14px;
  font-size: 16px;
  font-weight: 700;
  color: var(--muted);
}

.coding-idea-back-btn {
  display: block;
  margin: 0 auto 14px;
  padding: 6px 14px;
  border-radius: 8px;
  border: 1px solid var(--neon-dim);
  background: transparent;
  color: var(--muted);
  font-size: 13px;
  font-weight: 700;
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
}

.coding-idea-rolled-name {
  font-size: 21px;
  font-weight: 800;
  color: var(--ink);
  margin-bottom: 8px;
}

.coding-idea-rolled-desc {
  font-size: 15px;
  color: var(--muted);
  line-height: 1.5;
}

.coding-idea-actions {
  display: flex;
  gap: 10px;
  margin-top: 18px;
}

.coding-idea-actions button {
  flex: 1;
  min-height: 52px;
  border-radius: 12px;
  font-weight: 700;
  font-size: 14px;
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
}

.coding-idea-save-btn {
  border: 2px solid var(--neon);
  background: var(--neon);
  color: var(--bg);
}

.coding-idea-reroll-btn {
  border: 2px solid var(--neon-dim);
  background: transparent;
  color: var(--ink);
}

.coding-section-heading {
  font-size: 16px;
  color: var(--neon);
  margin: 26px 0 10px;
  text-shadow: 0 0 8px rgba(79, 216, 255, 0.4);
}

.coding-idea-row {
  background: var(--card);
  border: 1px solid var(--neon-dim);
  border-radius: 14px;
  padding: 14px 16px;
  margin-bottom: 12px;
}

.coding-idea-name {
  font-weight: 700;
  font-size: 16px;
  color: var(--ink);
}

.coding-idea-desc {
  font-size: 14px;
  color: var(--muted);
  margin-top: 4px;
  line-height: 1.4;
}

.coding-idea-meta {
  font-size: 12px;
  color: var(--muted);
  margin-top: 8px;
}

.coding-idea-row-actions {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: 10px;
}

.coding-idea-mark-built-btn {
  flex: 1;
  min-height: 44px;
  border-radius: 10px;
  border: 2px solid var(--neon);
  background: transparent;
  color: var(--neon);
  font-weight: 700;
  font-size: 14px;
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
}

.coding-idea-delete-btn {
  min-width: 44px;
  min-height: 44px;
  border: none;
  background: none;
  color: var(--danger);
  font-size: 20px;
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
}

.coding-built-badge {
  display: inline-block;
  padding: 6px 12px;
  border-radius: 8px;
  background: rgba(79, 216, 255, 0.12);
  border: 1px solid var(--neon);
  color: var(--neon);
  font-size: 13px;
  font-weight: 700;
}

.coding-idea-undo-btn {
  min-height: 36px;
  padding: 0 12px;
  border-radius: 8px;
  border: 1px solid var(--neon-dim);
  background: transparent;
  color: var(--muted);
  font-size: 13px;
  font-weight: 700;
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
}

/* ---------- Rankings (shared "reorder + Auto Rank" screen) ---------- */

.rank-list { list-style: none; margin: 0; padding: 0; }

.rank-actions-row {
  display: flex;
  gap: 10px;
  margin-bottom: 16px;
}

.rank-actions-row .btn {
  flex: 1;
  min-width: 0;
}

.rank-row {
  display: flex;
  align-items: center;
  gap: 10px;
  background: var(--card);
  border: 1px solid var(--neon-dim);
  border-radius: 14px;
  padding: 8px 10px;
  margin-bottom: 10px;
}

.rank-row.dragging {
  opacity: 0.9;
  border-color: var(--neon);
  box-shadow: 0 0 16px rgba(79, 216, 255, 0.35);
  z-index: 5;
  position: relative;
}

.rank-handle {
  font-size: 1.3rem;
  color: var(--neon);
  padding: 12px 8px;
  min-width: 44px;
  min-height: 44px;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: grab;
  touch-action: none; /* only the handle blocks page scroll -- the rest of the row still scrolls normally */
}

.rank-number {
  font-size: 1.2rem;
  font-weight: 700;
  color: var(--neon);
  min-width: 30px;
  text-align: center;
}

.rank-name {
  flex: 1;
  min-width: 0;
  font-size: 1rem;
  font-weight: 600;
  color: var(--ink);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.rank-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 8px;
  margin: 16px 20px 4px;
}

.rank-bar-left { display: flex; gap: 8px; flex-wrap: wrap; }

.rank-autorank-pair {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: 30px;
}

.rank-autorank-vs {
  font-weight: 700;
  font-size: 1.1rem;
  color: var(--muted);
}

.rank-autorank-card {
  flex: 1;
  min-height: 220px;
  background: var(--card);
  border: 2px solid var(--neon-dim);
  border-radius: 18px;
  color: var(--ink);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 16px 10px;
  cursor: pointer;
  touch-action: manipulation;
}

.rank-autorank-card:active {
  border-color: var(--neon);
  box-shadow: 0 0 14px rgba(79, 216, 255, 0.35);
}

.rank-autorank-name {
  font-size: 1.05rem;
  font-weight: 700;
  text-align: center;
  word-break: break-word;
}

