/* =====================================================
   LOCAL GAME STYLES: Tuning Unisons
   Builds on top of ../../shared/global.css
   ===================================================== */

/* ─── Title ─── */
.gameMainTitle {
  text-align: center; font-size: 22px; font-weight: 900;
  color: var(--text-main); margin: 0; padding: 0 12px;
}
.diffBadge {
  display: inline-block; font-size: 13px; font-weight: 800;
  padding: 2px 10px; border-radius: 20px; margin-left: 8px;
  vertical-align: middle;
}
.diffBadge--adv { background: #a78bfa; color: #fff; }

/* ─── Modal titles ─── */
.modalTitle {
  text-align: center; font-size: 22px; font-weight: 900;
  margin-bottom: 4px; text-transform: uppercase; letter-spacing: 0.4px;
}

.modalTitlelb {
  text-align: center; font-size: 22px; font-weight: 900;
  margin-bottom: 10px; text-transform: uppercase; letter-spacing: 0.4px;
}

/* ─── Panels ─── */
.controlsPanel {
  background: var(--bg-surface); border: 2px solid rgba(255,255,255,0.08);
  border-radius: var(--radius-md); padding: 12px 12px; box-shadow: var(--shadow-soft);
  display: flex; flex-direction: column; gap: 8px;
}
body.light-theme .controlsPanel { border-color: rgba(0,0,0,0.06); }

/* ─── Nav actions row (collapses to icons individually) ─── */
.navActionsRow {
  display: flex;
  flex-wrap: nowrap;
  gap: 6px;
  width: 100%;
}
.navBtn {
  flex: 1 1 0;
  min-width: 0;
  height: 52px;
  padding: 0 6px;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  overflow: hidden;
}
.navBtn .ib-icon  { font-size: 19px; flex-shrink: 0; line-height: 1; display: none; }
.navBtn .ib-label {
  font-size: 18px;
  white-space: nowrap;
  overflow: hidden;
  min-width: 0;
}
.navBtn.icon-only {
  flex: 0 0 auto;
  width: 52px;
  padding: 0;
}
.navBtn.icon-only .ib-label { display: none; }
.navBtn.icon-only .ib-icon  { display: inline; }
.navBtn:disabled { opacity: 0.4; cursor: not-allowed; }

/* ─── Status / instruction text — lives in the controls column,
   above the answer buttons. The wrapper is given a fixed height in JS
   (sizeStatusText(), sized to fit the tallest of every possible message —
   the base instruction and every "Check Tuning" reveal variant — at the
   current column width), so switching between messages never shifts the
   layout below it; overflow:hidden is the hard cap in case any future
   text ever runs longer than that. The text itself is centered inside
   that fixed box. ─── */
.statusTextWrap {
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}
.statusText {
  text-align: center; font-size: 14px; font-weight: 600;
  color: var(--text-muted); margin: 0; line-height: 1.5;
  white-space: pre-line;
}
/* Applied only while showing a Check Tuning result. */
.statusText.reveal {
  font-size: 16px; font-weight: 800;
  color: var(--text-main); line-height: 1.35;
}

/* ─── Game body: two equal-width columns beneath the nav buttons,
   each centered within its own column, tops aligned to each other.
   The pianoboard is a normal in-flow image, centered horizontally by
   the rig column's flex alignment and top-aligned to the column; its
   own size is scaled by BOARD_SCALE in the JS. The hammer is
   absolutely positioned (relative to the rig column) and computed
   LAST in the JS, reading back the board's actual rendered position
   so its tip always lands exactly on the board's pin regardless of
   how the board ended up centered.

   Neither this row, the rig column, nor the controls column sets an
   explicit z-index alongside `position`, so none of them establishes
   its own stacking context — the negative z-index values on the
   board/hammer images below are free to compare against the page's
   normal (non-positioned) content overall, not just within a local
   wrapper. That's what lets the rig sit behind the nav pill, the
   title, and everything else on the page while still painting above
   the page's plain background. ─── */
/* The shared .app wrapper (in global.css) gets a solid background on
   wider screens but has no position/z-index of its own, so it never
   forms a stacking context — without this rule, the rig's negative
   z-index below would escape .app entirely and get compared at the
   page root, where it paints BEHIND .app's own opaque background
   (fully hidden). Giving #tuningApp (this page only) an isolating
   stacking context keeps the negative z-index comparison local: the
   rig then paints above #tuningApp's own background, but still below
   every normal (non-negative-z) element inside it — the header,
   title, nav pill and controls column all included. */
#tuningApp {
  position: relative;
  z-index: 0;
}

.tuningGameBody {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  gap: 16px;
  margin-top: 10px;
}

.tuningRigWrap {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  flex: 1 1 0;
  min-width: 160px;
  padding-top: 0;
}
.pianoboardImg {
  position: relative; /* needed only so z-index below takes effect; no offsets, so it stays a normal in-flow flex item */
  display: block;
  pointer-events: none;
  user-select: none;
  -webkit-user-drag: none;
  z-index: -2;
}
/* The piano image is turned on its side with `rotate`, which does not change its layout box.
   The wrapper's height is therefore set to the TURNED height (image width = 0.5746 x its height),
   and the image is centred inside it. Change --piano-h to resize; the padding disappears automatically. */
.pianointroWrap {
  --piano-h: 200px;
  height: calc(var(--piano-h) * 0.5746);
  margin: 4px 0 12px;
  display: flex;
  align-items: center;
  justify-content: center;
}
.pianointroimg {
  flex: none;
  height: var(--piano-h);
  width: auto;
  max-width: none;
  rotate: -90deg;
  padding: 0;
}
.hammerImg {
  position: absolute;
  top: 0;
  left: 0;
  display: block;
  pointer-events: none;
  user-select: none;
  -webkit-user-drag: none;
  will-change: transform;
  z-index: -1;
}

.tuningControls {
  flex: 1 1 0;
  min-width: 130px;
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding-top: 0;
}

/* ─── Countdown timer, above the buttons ─── */
.timerBox {
  text-align: center;
  background: var(--bg-surface);
  border: 2px solid rgba(255,255,255,0.08);
  border-radius: var(--radius-md);
  padding: 8px 10px;
}
body.light-theme .timerBox { border-color: rgba(0,0,0,0.06); }
.timerLabel { font-size: 12px; font-weight: 800; letter-spacing: 0.5px; text-transform: uppercase; color: var(--text-muted); }
.timerValue { font-size: 36px; font-weight: 900; line-height: 1.1; color: var(--text-main); font-variant-numeric: tabular-nums; }
.timerTally { font-size: 12px; font-weight: 700; color: var(--text-muted); margin-top: 2px; }
/* Out of time: the clock counts up and turns red. */
.timerBox.late .timerLabel,
.timerBox.late .timerValue { color: var(--danger); }
.timerBox.late { border-color: var(--danger); }

.tuneAdjustRow {
  display: flex;
  gap: 10px;
}
.tuneAdjustBtn {
  flex: 1 1 0;
  height: 64px;
  font-size: 28px;
  font-weight: 900;
  border-radius: var(--radius-sm);
  border: 2px solid rgba(255,255,255,0.14);
  background: var(--bg-elevated);
  color: var(--text-main);
  cursor: pointer;
  box-shadow: var(--shadow-soft);
  transition: background-color 0.15s ease, border-color 0.15s ease;
}
body.light-theme .tuneAdjustBtn { border-color: rgba(0,0,0,0.12); }
/* Greyed out until the game begins; green once they are active. */
.tuneAdjustBtn:disabled { opacity: 0.4; cursor: not-allowed; }
.tuneAdjustBtn:not(:disabled) {
  background: var(--info-teal);
  border-color: var(--info-shadow);
  color: #fff;
}
.tuneAdjustBtn:not(:disabled):active { background: var(--info-shadow); }

#checkBtn, #playBtn, #repeatBtn {
  width: 100%;
}
.repeatRetryRow { display: flex; gap: 10px; }
.repeatRetryRow .btn { flex: 1 1 0; width: auto; min-width: 0; }
#repeatBtn.active {
  background: var(--accent);
  border-color: var(--accent-shadow);
  color: #fff;
}

/* No forced breakpoint here: the two columns above (.tuningRigWrap /
   .tuningControls) both shrink via flex:1 1 0 down to their own
   min-width, and .tuningGameBody's flex-wrap only drops the controls
   column onto its own line once the columns genuinely can't fit side
   by side any more (below roughly 160px + 130px + the 16px gap) — the
   existing `gap` on .tuningGameBody already spaces that wrapped line
   the same way it spaces the two columns when side by side, so nothing
   extra is needed for that case.*/

/* ─── Settings modal: Note Sound choice ─── */
.settingsSectionTitle {
  font-size: 15px; font-weight: 800; color: var(--text-main);
  margin: 4px 0 8px;
  text-align: left;
}
.settingsSectionTitle:first-child { margin-top: 0; }

.audioSourceGrid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 8px;
  width: 100%;
}
.diffOption {
  min-height: 54px;
  border-radius: var(--radius-sm);
  border: 2px solid var(--bg-elevated);
  background: var(--bg-elevated);
  color: var(--text-main);
  font-size: 14px;
  font-weight: 700;
  cursor: pointer;
  transition: background-color 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}
.diffOption:active { transform: scale(0.97); }
.diffOption:hover { background: var(--accent); border-color: var(--accent-shadow); color: #fff; }
body.light-theme .diffOption { border-color: rgba(0,0,0,0.08); }

/* Persistent-choice options (unlike a one-shot pick) show which one is
   currently active. */
.diffOption.selected {
  background: var(--accent);
  border-color: var(--accent-shadow);
  color: #fff;
}

/* ─── Intro / finish modals ─── */
.storyText { font-size: 16px; line-height: 1.5; text-align: center; color: var(--text-main); font-weight: 600; }
.storyHow  { font-size: 14px; line-height: 1.5; text-align: center; color: var(--text-muted); }
.finishStats { font-size: 14px; font-weight: 800; text-align: center; color: var(--text-muted); margin-top: 8px; }

#repeatBtn:disabled, #playBtn:disabled { opacity: 0.4; cursor: not-allowed; }


/* ─── Top Times leaderboard ─── */
.saveTimeBlock { margin-top: 16px; padding-top: 14px; border-top: 2px dashed rgba(255,255,255,0.1); display: flex; flex-direction: column; gap: 8px; }
body.light-theme .saveTimeBlock { border-top-color: rgba(0,0,0,0.1); }
.saveTimeBlock input {
  background: var(--bg-base); border: 2px solid var(--bg-elevated); border-radius: var(--radius-sm);
  color: var(--text-input); padding: 10px 12px; font-size: 14px; width: 100%;
}
.saveTimeBanner { text-align: center; font-size: 16px; font-weight: 900; color: var(--info-teal); margin: 0; }
.saveTimeNote { text-align: center; font-weight: 800; color: var(--info-teal); margin: 0; }
.saveTimeNote.error { color: #f87171; }
.timesTitle { text-align: center; font-size: 16px; font-weight: 900; color: var(--text-main); margin: 16px 0 8px; padding-top:10px; padding-bottom: 10px; }
.timesNote { text-align: center; font-size: 12px; font-weight: 700; color: var(--text-muted); margin: 0 0 8px; }
.timesList { display: flex; flex-direction: column; gap: 8px; max-height: 320px; overflow-y: auto; }
.timesRow { display: flex; align-items: center; gap: 10px; background: var(--bg-base); border-radius: var(--radius-sm); padding: 8px 12px; }
.timesRow.mine { outline: 2px solid var(--info-teal); }
.timesRank { font-weight: 900; color: var(--accent); width: 28px; flex-shrink: 0; }
.timesName { flex: 1; font-weight: 700; color: var(--text-main); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.timesTime { font-weight: 900; color: var(--accent); }
.timesMiss { font-size: 14px; color: var(--text-muted); flex-shrink: 0; }
.timesEmpty { text-align: center; color: var(--text-muted); font-weight: 700; font-size: 14px; }
@media (max-width: 480px) { .timesMiss { display: none; } }

.pageTimes { margin-top: 16px; }
#introModal .timesTitle { margin-top: 14px; }
#introModal .timesList { max-height: 170px; } /* about 3½ rows visible; scroll for the rest */

/* Leaderboard row tint by incorrect attempts: 1-3 yellow, over 3 red */
.timesRow.missLow  { background: color-mix(in srgb, #facc15 16%, var(--bg-base)); }
.timesRow.missHigh { background: color-mix(in srgb, #ef4444 20%, var(--bg-base)); }

/* Leaderboard heading row with the "Open Full Leaderboard" link */
.timesHead { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: center; column-gap: 12px; }
.timesHead .timesTitle { margin: 0; padding-top: 10px; padding-bottom: 6px; }
.linkBtn {
  background: none; border: 0; padding: 4px 2px; cursor: pointer;
  font: inherit; font-size: 16px; font-weight: 800; color: var(--accent); text-decoration: underline; padding-bottom: 16px;
}
.linkBtn:hover { filter: brightness(1.15); }
#fullLbModal .timesList { max-height: 60vh; }
