/* ==========================================================================
   app.css — everything specific to this site.

   Bootstrap 5.3.8 is loaded first and provides the reset, the typography base,
   the light/dark machinery (data-bs-theme) and the utility classes. This file
   only adds what Bootstrap does not: the search field, the song list, the A-Z
   grid, and the handful of decisions that make the page feel like it was built
   for a phone rather than shrunk down to fit one.

   MOBILE FIRST, LITERALLY
   -----------------------
   Every rule below is written for a phone held in one hand. The only media
   query that changes layout is one that RELAXES things on larger screens, so
   there is no possibility of a desktop rule accidentally leaking down onto a
   phone. That is the practical difference between "mobile first" and "made
   responsive afterwards".
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. DESIGN TOKENS
   Colours are defined once here, in both schemes, and referenced everywhere
   else. Changing the venue's accent colour is a one-line edit.
   -------------------------------------------------------------------------- */

:root {
  /* The Nightlife Karaoke brand pink. Used exactly as supplied for anything
     that reads as the brand -- the logo, the active tab, a selected letter. */
  --k-accent: #eb0e8a;
  --k-accent-soft: rgba(235, 14, 138, 0.10);

  --k-page-bg: #ffffff;
  --k-surface: #ffffff;
  --k-header-bg: rgba(255, 255, 255, 0.92);
  --k-text: #17151c;
  --k-text-muted: #6a6577;

  /* The NIGHTLIFE half of the logo. The supplied brand files use pure black on
     white and pure white on black, so those are the values here rather than the
     page's slightly-softened text colour -- a logo should be the colour the
     brand says it is. The KARAOKE script carries its own pink inside the SVG. */
  --k-logo-ink: #000000;
  --k-border: #e6e3ec;
  --k-field-bg: #f3f1f7;
  --k-highlight-bg: rgba(235, 14, 138, 0.14);
  /* A darker shade of the brand pink, for accent text on a white page. The
     brand pink itself only reaches 4.2:1 on white, which is under the 4.5:1
     needed for small text; this shade is the same hue at 6.8:1. The brand
     colour stays untouched wherever it is a surface rather than a letterform. */
  --k-highlight-text: #b00a68;

  /* Touch targets. 48px is the size a fingertip reliably hits; Apple and
     Google both land in the 44-48px range, so we take the larger number and
     never go below it for anything tappable. */
  --k-tap: 48px;

  /* Horizontal breathing room, plus whatever the phone's rounded corners or
     notch need on top. */
  --k-gutter: 1rem;
}

/* Bootstrap 5.3 stamps data-bs-theme="dark" on <html>; the inline script in
   index.html sets it before first paint. */
[data-bs-theme="dark"] {
  /* The same brand pink. On the near-black page it reaches 4.4:1, comfortably
     past the 3:1 that buttons, borders and other interface shapes require. */
  --k-accent: #eb0e8a;
  --k-accent-soft: rgba(235, 14, 138, 0.18);

  --k-page-bg: #12101a;
  --k-surface: #1b1825;
  --k-header-bg: rgba(18, 16, 26, 0.92);
  --k-text: #f2eff7;
  --k-text-muted: #a49db4;
  --k-logo-ink: #ffffff;
  --k-border: #2c2739;
  --k-field-bg: #221e2e;
  --k-highlight-bg: rgba(235, 14, 138, 0.22);
  /* A tint of the brand pink rather than the brand pink itself: matched letters
     are small text on a dark ground, and this reaches 7.1:1 where the brand
     pink would manage 4.4:1. */
  --k-highlight-text: #ff6bb5;
}

/* --------------------------------------------------------------------------
   2. PAGE FRAME
   -------------------------------------------------------------------------- */

html {
  /* Stops the whole page bouncing when a list is scrolled to its end on iOS,
     which otherwise makes the sticky header look like it is coming loose. */
  overscroll-behavior-y: none;
}

body {
  background: var(--k-page-bg);
  color: var(--k-text);
  /* The system font stack means zero webfont downloads: no extra request, no
     flash of invisible text, and the page renders in whatever face the
     customer's phone already has loaded. On a weak signal this is worth more
     than any typeface choice. */
  font-family: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  -webkit-tap-highlight-color: transparent;
}

/* One column, centred, never wider than comfortable reading width. On a phone
   this is simply "the screen"; on a laptop it stops the song list stretching
   into an unreadable 2000px-wide row. */
.app-container {
  width: 100%;
  max-width: 640px;
  margin-inline: auto;
  padding-inline: max(var(--k-gutter), env(safe-area-inset-left));
  padding-inline-end: max(var(--k-gutter), env(safe-area-inset-right));
}

.app-main {
  /* Enough room at the bottom that the last song in a list is never hidden
     behind the phone's home indicator. */
  padding-bottom: calc(3rem + env(safe-area-inset-bottom));
  min-height: 60vh;
}

/* --------------------------------------------------------------------------
   3. HEADER
   The search box stays on screen at all times. A customer who has scrolled
   forty songs down and wants to try a different search should not have to
   scroll back up to do it — that is the single most common reason a mobile
   search page feels awkward.
   -------------------------------------------------------------------------- */

.app-header {
  position: sticky;
  top: 0;
  z-index: 20;
  background: var(--k-header-bg);
  /* The blur keeps the header legible while list content scrolls under it. */
  backdrop-filter: saturate(180%) blur(12px);
  -webkit-backdrop-filter: saturate(180%) blur(12px);
  border-bottom: 1px solid var(--k-border);
  padding-top: max(0.5rem, env(safe-area-inset-top));
  padding-bottom: 0.5rem;
}

.app-brand {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  padding-block: 0.375rem 0.625rem;
}

/* The heading is now a container for the logo; its own text is the
   visually-hidden name that screen readers announce. */
.app-title {
  display: flex;
  align-items: center;
  margin: 0;
  /* The wordmark inside the SVG is filled with currentColor, so setting the
     heading's colour is what makes NIGHTLIFE white on dark and black on light. */
  color: var(--k-logo-ink);
  /* Let the logo shrink on a very narrow phone rather than shouldering the
     theme toggle off the edge. */
  min-width: 0;
}

.app-logo {
  display: block;
  /* The artwork is 5795 x 688, an 8.4:1 strip. Width is what needs controlling;
     height follows from the aspect ratio, so the logo can never distort.
     min() keeps it proportional on small screens and stops it growing beyond a
     comfortable size on a tablet. */
  width: min(58vw, 232px);
  height: auto;
}

.theme-toggle {
  display: grid;
  place-items: center;
  width: var(--k-tap);
  height: var(--k-tap);
  /* Pull the button out to the edge so its generous tap area does not push the
     title inwards. Visual alignment and tap area are different things. */
  margin-right: -0.75rem;
  border: 0;
  border-radius: 50%;
  background: transparent;
  color: var(--k-text-muted);
  cursor: pointer;
}

.theme-toggle:active { background: var(--k-field-bg); }

/* Only one of the two icons is ever shown, chosen by the current theme. */
.icon-moon { display: none; }
[data-bs-theme="dark"] .icon-sun { display: none; }
[data-bs-theme="dark"] .icon-moon { display: block; }

/* All the inline SVGs in this page are line icons drawn with strokes, so they
   inherit the surrounding text colour and stay crisp at any size. */
.icon,
.search-icon,
.empty-icon {
  width: 22px;
  height: 22px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* --------------------------------------------------------------------------
   4. THE SEARCH FIELD
   The one control that matters. It is deliberately the largest thing on the
   screen.
   -------------------------------------------------------------------------- */

.search-form { margin: 0; }

.search-field {
  position: relative;
  display: flex;
  align-items: center;
}

.search-icon {
  position: absolute;
  left: 0.875rem;
  color: var(--k-text-muted);
  pointer-events: none;
}

.search-input {
  width: 100%;
  height: 3.25rem;
  padding: 0 3rem 0 2.875rem;

  /* 16px is a hard floor, not a preference: mobile Safari zooms the entire
     page in whenever a focused input has smaller text, and the customer then
     has to pinch back out to read the results. 17px gives a little headroom. */
  font-size: 1.0625rem;
  font-weight: 500;

  color: var(--k-text);
  background: var(--k-field-bg);
  border: 1.5px solid transparent;
  border-radius: 14px;
  outline: none;
  transition: border-color 0.15s ease, background-color 0.15s ease;
}

.search-input::placeholder {
  color: var(--k-text-muted);
  font-weight: 400;
}

.search-input:focus {
  border-color: var(--k-accent);
  background: var(--k-surface);
}

/* The accent border above IS this field's focus indicator, so the page-wide
   focus ring is suppressed here. Two rings around the same box read as an
   error state rather than as focus. */
.search-input:focus-visible {
  outline: none;
  border-width: 2px;
}

/* iOS and Chrome both draw their own clear button inside type="search".
   Ours is bigger, matches the design and works everywhere, so theirs goes. */
.search-input::-webkit-search-decoration,
.search-input::-webkit-search-cancel-button,
.search-input::-webkit-search-results-button { -webkit-appearance: none; }

.search-clear {
  position: absolute;
  right: 0.25rem;
  display: grid;
  place-items: center;
  width: var(--k-tap);
  height: var(--k-tap);
  border: 0;
  border-radius: 50%;
  background: transparent;
  color: var(--k-text-muted);
  cursor: pointer;
}

.search-clear:active { color: var(--k-text); }

/* --------------------------------------------------------------------------
   5. MODE TABS
   -------------------------------------------------------------------------- */

.mode-tabs {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0.375rem;
  margin-top: 0.625rem;
  padding: 0.25rem;
  background: var(--k-field-bg);
  border-radius: 12px;
}

.mode-tab {
  min-height: 40px;
  border: 0;
  border-radius: 9px;
  background: transparent;
  color: var(--k-text-muted);
  font-size: 0.9375rem;
  font-weight: 600;
  cursor: pointer;
  transition: background-color 0.15s ease, color 0.15s ease;
}

/* The selected mode is filled with the brand pink in both themes. It is the
   most prominent control on the screen, so it is the right place for the brand
   colour to appear, and keeping it identical in light and dark means the site
   looks like itself whichever way round a customer's phone is set. */
.mode-tab.is-active {
  background: var(--k-accent);
  color: #fff;
}

/* --------------------------------------------------------------------------
   6. LISTS OF SONGS AND ARTISTS
   Rows are plain <li> elements with a button inside, rather than Bootstrap's
   list-group. A song row is a two-line block with its own tap behaviour, and
   writing it directly is clearer than overriding a component into shape.
   -------------------------------------------------------------------------- */

.song-list,
.artist-list {
  list-style: none;
  margin: 0;
  padding: 0;
}

.song-item,
.artist-item {
  border-bottom: 1px solid var(--k-border);
}

/* The tappable area fills the whole row. On a phone the row IS the button —
   there is no separate small target to aim at. */
.song-static,
.song-button,
.artist-button {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  width: 100%;
  min-height: 64px;
  padding: 0.75rem 0.25rem;
  border: 0;
  background: transparent;
  color: inherit;
  text-align: left;
  cursor: pointer;
}

.song-button:active,
.artist-button:active { background: var(--k-accent-soft); }

/* Rows in the artist view are a list, not a menu: every song there belongs to
   the artist already on screen, so there is nowhere for a tap to go. Giving
   them the look of a button and no behaviour would be worse than making them
   plainly static. */
.song-static { cursor: default; }

.song-text { flex: 1 1 auto; min-width: 0; }

/* The song title is the thing being looked for, so it gets the visual weight.
   Long titles wrap onto a second line rather than being cut off with an
   ellipsis: a singer needs the whole title to ask for it. */
.song-title {
  display: block;
  font-size: 1rem;
  font-weight: 600;
  line-height: 1.35;
  color: var(--k-text);
}

.song-artist {
  display: block;
  margin-top: 0.125rem;
  font-size: 0.875rem;
  line-height: 1.35;
  color: var(--k-text-muted);
}

.song-chevron {
  flex: 0 0 auto;
  color: var(--k-border);
}

.artist-button { justify-content: space-between; }

.artist-name {
  font-size: 1rem;
  font-weight: 600;
}

/* A quiet pill showing how many songs the artist has, so a customer can see at
   a glance whether it is worth opening. */
.artist-count {
  flex: 0 0 auto;
  min-width: 2.25rem;
  padding: 0.125rem 0.5rem;
  border-radius: 999px;
  background: var(--k-field-bg);
  color: var(--k-text-muted);
  font-size: 0.8125rem;
  font-variant-numeric: tabular-nums;
  text-align: center;
}

/* The part of the text that matched what was typed. Highlighting is what turns
   a list of thirty near-identical rows into something the eye can scan. */
mark.match {
  /* Colour and weight only, no highlighter pen. A search for "the beatles"
     matches the word "the" in a great many titles, and a background swatch on
     every one of them turns the list into stripes. Recolouring the matched
     letters is enough for the eye to find them and leaves the song titles
     readable. */
  /* Bootstrap's reboot gives <mark> its own padding and yellow background;
     both are cleared here so a highlighted word occupies exactly the space it
     would have occupied unhighlighted. */
  padding: 0;
  background: transparent;
  color: var(--k-highlight-text);
  font-weight: 800;
}

/* --------------------------------------------------------------------------
   7. A-Z LETTER GRID
   -------------------------------------------------------------------------- */

.letter-grid {
  display: grid;
  /* auto-fill with a minimum keeps the letters comfortably tappable on a small
     phone and simply fits more per row on a larger one — no breakpoints. */
  grid-template-columns: repeat(auto-fill, minmax(2.75rem, 1fr));
  gap: 0.375rem;
  margin: 0.875rem 0 1rem;
}

.letter-button {
  min-height: 46px;
  border: 1px solid var(--k-border);
  border-radius: 10px;
  background: var(--k-surface);
  color: var(--k-text);
  font-size: 1rem;
  font-weight: 600;
  cursor: pointer;
}

.letter-button.is-active {
  background: var(--k-accent);
  border-color: var(--k-accent);
  color: #fff;
}

/* Letters with no artists behind them are shown but cannot be tapped, so the
   grid keeps its familiar shape and nobody taps into an empty screen. */
.letter-button:disabled {
  opacity: 0.3;
  cursor: default;
}

/* --------------------------------------------------------------------------
   8. STATUS LINES, EMPTY STATES, BUTTONS
   -------------------------------------------------------------------------- */

.status-line {
  min-height: 1.25rem;
  margin: 0.875rem 0 0.5rem;
  font-size: 0.875rem;
  color: var(--k-text-muted);
}

.status-line.is-error { color: #d9534f; }
[data-bs-theme="dark"] .status-line.is-error { color: #ff8b86; }

.view-intro {
  margin: 1rem 0 0;
  font-size: 0.875rem;
  color: var(--k-text-muted);
}

.empty-state {
  padding: 2.5rem 1rem;
  text-align: center;
  color: var(--k-text-muted);
}

.empty-icon {
  width: 40px;
  height: 40px;
  margin-bottom: 0.875rem;
  color: var(--k-accent);
  opacity: 0.75;
}

.empty-title {
  margin: 0 0 0.375rem;
  font-size: 1.0625rem;
  font-weight: 600;
  color: var(--k-text);
}

.empty-hint {
  margin: 0 auto;
  max-width: 22rem;
  font-size: 0.9375rem;
}

/* Tappable example searches. They exist because the hardest moment for a new
   customer is the empty box: one tap shows them what the site does. */
.example-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  justify-content: center;
  margin-top: 1.25rem;
}

.example-chip {
  min-height: 40px;
  padding: 0 0.9rem;
  border: 1px solid var(--k-border);
  border-radius: 999px;
  background: var(--k-surface);
  color: var(--k-text);
  font-size: 0.9375rem;
  cursor: pointer;
}

.example-chip:active { background: var(--k-accent-soft); }

.load-more,
.back-button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.375rem;
  min-height: var(--k-tap);
  padding: 0 1.25rem;
  border: 1px solid var(--k-border);
  border-radius: 12px;
  background: var(--k-surface);
  color: var(--k-text);
  font-size: 0.9375rem;
  font-weight: 600;
  cursor: pointer;
}

.load-more {
  width: 100%;
  margin-top: 1.25rem;
}

.load-more:active,
.back-button:active { background: var(--k-accent-soft); }

.back-button {
  margin: 1rem 0 0.5rem;
  padding-left: 0.75rem;
}

.artist-heading {
  margin: 0.25rem 0 0;
  font-size: 1.375rem;
  font-weight: 700;
  line-height: 1.25;
}

/* --------------------------------------------------------------------------
   9. FOOTER
   -------------------------------------------------------------------------- */

/* Set from JavaScript to the live header height, so scrollIntoView() stops
   short of tucking content underneath the sticky header. */
.scroll-anchor { scroll-margin-top: var(--k-header-height, 8rem); }

.app-footer {
  padding-block: 1.5rem;
  padding-bottom: calc(1.5rem + env(safe-area-inset-bottom));
  border-top: 1px solid var(--k-border);
  color: var(--k-text-muted);
  font-size: 0.8125rem;
  text-align: center;
}

.app-footer p { margin: 0 0 0.25rem; }
.footer-note { opacity: 0.8; }

/* --------------------------------------------------------------------------
   10. ACCESSIBILITY AND MOTION
   -------------------------------------------------------------------------- */

/* A visible focus ring for anyone navigating by keyboard, without drawing one
   around every element a finger touches. */
:focus-visible {
  outline: 3px solid var(--k-accent);
  outline-offset: 2px;
  border-radius: 6px;
}

/* Respect a customer who has asked their phone to reduce motion. */
@media (prefers-reduced-motion: reduce) {
  * {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }
}

/* The only layout media query in the file, and it only loosens things up. */
@media (min-width: 480px) {
  :root { --k-gutter: 1.5rem; }
  .app-logo { width: 248px; }
}
