/* =============================================================================
   Pad Machine v2 — folha de estilo única
   -----------------------------------------------------------------------------
   Estratégia: mobile-first de verdade. O layout base é o de tela pequena
   (tudo empilhado, listas com rolagem horizontal + snap) e o @media
   (min-width: 900px) apenas ENRIQUECE — nunca conserta.

   Índice
     1.  Tokens (:root)
     2.  Reset e base
     3.  Layout do app (.app / .stage)
     4.  Cabeçalho e transporte (.app-header / .transport / .btn / .bpm-field)
     5.  Barra de templates (.template-bar / .template-chip)
     6.  Grade de pads (.pad-grid / .pad)
     7.  Sequencer (.seq-grid / .seq-row / .seq-step)
     8.  Inspector (.inspector)
     9.  Overlay de destravar áudio (#start-overlay)
     10. Breakpoint ≥900px
     11. prefers-reduced-motion
   ========================================================================== */

/* -----------------------------------------------------------------------------
   1. TOKENS
   Paleta escura em oklch: a claridade (L) é perceptual, então um mesmo L
   entrega o mesmo contraste em qualquer matiz — é isso que garante o requisito
   de texto legível sobre pads de matiz arbitrário.
   -------------------------------------------------------------------------- */
:root {
  color-scheme: dark;

  /* Superfícies (neutros levemente azulados) */
  --bg:            oklch(0.15 0.014 265);
  --surface:       oklch(0.20 0.016 265);
  --surface-raised:oklch(0.25 0.018 265);
  --line:          oklch(0.33 0.020 265);
  --line-soft:     oklch(0.28 0.018 265);

  /* Tinta */
  --ink:           oklch(0.97 0.006 265);
  --ink-muted:     oklch(0.76 0.016 265);
  --ink-faint:     oklch(0.62 0.020 265);

  /* Acentos */
  --accent:        oklch(0.74 0.170 152);   /* tocar / ativo */
  --accent-ink:    oklch(0.18 0.050 152);
  --accent-2:      oklch(0.76 0.150 240);   /* cabeça de leitura / seleção */
  --focus:         oklch(0.88 0.130 215);

  /* Escala tipográfica fluida (base 16px no mobile → ~17px no desktop) */
  --font: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto,
          "Helvetica Neue", Arial, sans-serif;
  --fs-100: clamp(0.6875rem, 0.62rem + 0.30vw, 0.8125rem);  /* micro rótulos */
  --fs-200: clamp(0.8125rem, 0.76rem + 0.28vw, 0.9375rem);  /* corpo pequeno  */
  --fs-300: clamp(0.9375rem, 0.89rem + 0.28vw, 1.0625rem);  /* corpo / botões */
  --fs-500: clamp(1.25rem, 1.05rem + 1.00vw, 1.75rem);      /* título         */

  /* Ritmo espacial */
  --sp-1: 0.25rem;
  --sp-2: 0.5rem;
  --sp-3: 0.75rem;
  --sp-4: 1rem;
  --sp-5: 1.5rem;

  /* Formas */
  --r-sm: 0.5rem;
  --r-md: 0.75rem;
  --r-lg: 1rem;
  --r-pill: 999px;

  /* Alvo mínimo de toque — usado literalmente em todo botão */
  --tap: 2.75rem;   /* 44px */

  --shadow-2: 0 6px 20px oklch(0 0 0 / 0.45);

  /* Duração base das transições; zerada em prefers-reduced-motion */
  --t-fast: 110ms;
  --t-med: 180ms;
}

/* -----------------------------------------------------------------------------
   2. RESET E BASE
   -------------------------------------------------------------------------- */
*,
*::before,
*::after { box-sizing: border-box; }

:where(body, h1, p, figure) { margin: 0; }

html { -webkit-text-size-adjust: 100%; }

body {
  min-block-size: 100dvh;
  background-color: var(--bg);
  color: var(--ink);
  font-family: var(--font);
  font-size: var(--fs-300);
  line-height: 1.4;
  overscroll-behavior-y: none;   /* sem "pull to refresh" acidental tocando pad */
}

/* Todo controle herda a fonte da UI; 1rem mínimo em campos evita o zoom
   automático do Safari iOS ao focar um input. */
:where(button, input, select, textarea) {
  font: inherit;
  font-size: max(1rem, var(--fs-300));
  color: inherit;
}

/* Foco por teclado visível em toda a UI; ponteiro não ganha anel. */
:where(button, input, select, a):focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 2px;
}
:where(button, input, select):focus:not(:focus-visible) { outline: none; }

/* -----------------------------------------------------------------------------
   3. LAYOUT DO APP
   .app ocupa exatamente a viewport (dvh acompanha a barra do navegador móvel)
   e distribui: header / templates / stage. Só a .stage rola — assim o
   cabeçalho e os templates nunca somem e nada fica inalcançável.
   -------------------------------------------------------------------------- */
.app {
  block-size: 100dvh;
  display: grid;
  grid-template-rows: auto auto minmax(0, 1fr);
  gap: var(--sp-3);

  /* Notch/ilha do iPhone e barra de gestos */
  padding-block: calc(var(--sp-3) + env(safe-area-inset-top))
                 calc(var(--sp-3) + env(safe-area-inset-bottom));
  padding-inline: calc(var(--sp-3) + env(safe-area-inset-left))
                  calc(var(--sp-3) + env(safe-area-inset-right));
}

.stage {
  min-block-size: 0;          /* deixa o item de grid encolher e rolar */
  overflow-y: auto;
  overflow-x: hidden;
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
  padding-block-end: var(--sp-2);
  scrollbar-width: thin;
  scrollbar-color: var(--line) transparent;
}

/* Com o inspector aberto (bottom sheet), a .stage ganha folga no fim para que
   a última trilha não fique escondida atrás do painel. */
.app:has(.inspector:not([hidden])) .stage { padding-block-end: 6rem; }

.pad-section,
.seq-section {
  background-color: var(--surface);
  border: 1px solid var(--line-soft);
  border-radius: var(--r-lg);
  padding: var(--sp-3);
}

/* -----------------------------------------------------------------------------
   4. CABEÇALHO E TRANSPORTE
   -------------------------------------------------------------------------- */
.app-header {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-2) var(--sp-3);
}

.app-title {
  font-size: var(--fs-500);
  font-weight: 650;
  letter-spacing: -0.02em;
  line-height: 1.1;
}

.transport {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--sp-2);
}

/* Botão base — todos os botões da UI compartilham esta caixa. */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-2);
  min-block-size: var(--tap);
  min-inline-size: var(--tap);
  padding-inline: var(--sp-4);
  background-color: var(--surface-raised);
  color: var(--ink);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  font-size: var(--fs-300);
  font-weight: 550;
  cursor: pointer;
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
  user-select: none;
  transition: background-color var(--t-fast) ease-out,
              border-color var(--t-fast) ease-out,
              transform var(--t-fast) ease-out;
}

@media (hover: hover) {
  .btn:hover { background-color: color-mix(in oklab, var(--surface-raised), var(--ink) 10%); }
}
.btn:active { transform: scale(0.97); }

/* Tocar/Parar: verde sólido quando o transporte está rodando. */
.btn-play {
  font-weight: 650;
  padding-inline: var(--sp-5);
}
.btn-play[aria-pressed="true"] {
  background-color: var(--accent);
  border-color: var(--accent);
  color: var(--accent-ink);
}

/* Alternador genérico (metrônomo) — apagado quando desligado. */
.btn-toggle[aria-pressed="false"] { color: var(--ink-muted); }
.btn-toggle[aria-pressed="true"] {
  background-color: color-mix(in oklab, var(--accent-2), transparent 78%);
  border-color: var(--accent-2);
  color: var(--ink);
}

.bpm-field {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  min-block-size: var(--tap);
  padding-inline: var(--sp-3);
  background-color: var(--surface-raised);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
}
.bpm-field label {
  font-size: var(--fs-100);
  font-weight: 650;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-faint);
}
.bpm-field input {
  inline-size: 4.25rem;
  min-block-size: calc(var(--tap) - 0.75rem);
  padding: 0 var(--sp-1);
  background-color: transparent;
  border: none;
  border-radius: var(--r-sm);
  color: var(--ink);
  font-variant-numeric: tabular-nums;
  font-weight: 650;
  text-align: center;
}

/* -----------------------------------------------------------------------------
   5. BARRA DE TEMPLATES
   Fita rolável com snap: no celular os 9 templates não cabem, e rolar
   horizontalmente é melhor do que quebrar em 3 linhas de chips.
   -------------------------------------------------------------------------- */
.template-bar {
  display: flex;
  gap: var(--sp-2);
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scroll-snap-type: x proximity;
  scroll-padding-inline: var(--sp-2);
  padding-block-end: var(--sp-1);
  scrollbar-width: none;         /* a barra é curta e óbvia; o snap já orienta */
}

.template-chip {
  flex: 0 0 auto;
  scroll-snap-align: start;
  min-block-size: var(--tap);
  padding-inline: var(--sp-4);
  background-color: var(--surface);
  color: var(--ink-muted);
  border: 1px solid var(--line-soft);
  border-radius: var(--r-pill);
  font-size: var(--fs-200);
  font-weight: 600;
  white-space: nowrap;
  cursor: pointer;
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
  user-select: none;
  transition: background-color var(--t-fast) ease-out,
              color var(--t-fast) ease-out,
              border-color var(--t-fast) ease-out;
}
@media (hover: hover) {
  .template-chip:hover { color: var(--ink); border-color: var(--line); }
}
.template-chip[aria-pressed="true"] {
  background-color: var(--ink);
  border-color: var(--ink);
  color: var(--bg);
}

/* -----------------------------------------------------------------------------
   6. GRADE DE PADS
   Dirigida por --rows/--cols injetadas inline pelo JS. Nada de 150px fixo:
   a coluna é minmax(alvo de toque, tamanho máximo fluido) e o pad é quadrado
   por aspect-ratio — cabe em 4, 6 ou 8 colunas sem vazar a viewport.
   -------------------------------------------------------------------------- */
.pad-grid {
  --pad-max: clamp(3.5rem, 20vw, 8rem);

  display: grid;
  grid-template-columns: repeat(var(--cols, 4), minmax(var(--tap), var(--pad-max)));
  grid-template-rows: repeat(var(--rows, 2), auto);
  gap: clamp(var(--sp-2), 1.6vw, var(--sp-3));
  justify-content: center;
}

.pad {
  /* Cor derivada do matiz injetado pelo JS. Como a claridade do oklch é
     perceptual, o mesmo L rende o mesmo contraste em qualquer matiz: a tinta
     do pad fica entre 5,9:1 e 7,1:1 sobre a face em todos os 360 graus
     (≥4,7:1 nos estados iluminados). Era isso que o randomColor() hex do app
     antigo não conseguia garantir.  */
  --pad-face:     oklch(0.46 0.125 var(--pad-hue, 260));
  --pad-face-lit: oklch(0.58 0.160 var(--pad-hue, 260));
  --pad-glow:     oklch(0.72 0.180 var(--pad-hue, 260));
  --pad-ink:      oklch(0.98 0.030 var(--pad-hue, 260));

  /* container de consulta: a tipografia do pad acompanha a largura DELE, não
     a da viewport — num grid 6x6 no celular o rótulo continua cabendo. */
  container-type: inline-size;

  aspect-ratio: 1;
  min-block-size: var(--tap);
  min-inline-size: var(--tap);
  display: grid;
  grid-template-rows: 1fr auto;
  align-items: center;
  gap: var(--sp-1);
  padding: var(--sp-2);
  background-color: var(--pad-face);
  color: var(--pad-ink);
  border: 1px solid color-mix(in oklab, var(--pad-glow), transparent 65%);
  border-radius: var(--r-md);
  cursor: pointer;
  overflow: hidden;

  /* Toque: sem delay de 300ms, sem flash cinza do Android, sem seleção de texto
     ao segurar (o toque longo abre o inspector). */
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
  user-select: none;

  /* Só propriedades de composição — nunca `all`, nunca layout. */
  transition: transform var(--t-med) ease-out,
              background-color var(--t-med) ease-out,
              box-shadow var(--t-med) ease-out;
}

@media (hover: hover) {
  .pad:hover { background-color: color-mix(in oklab, var(--pad-face), var(--pad-face-lit) 35%); }
}

.pad-label {
  align-self: center;
  font-size: clamp(0.625rem, 17cqi, var(--fs-200));
  font-weight: 650;
  line-height: 1.15;
  text-align: center;
  text-wrap: balance;
  overflow-wrap: anywhere;
}

.pad-key {
  justify-self: center;
  min-inline-size: 1.5rem;
  padding: 0.1rem 0.4rem;
  background-color: oklch(0 0 0 / 0.28);
  border-radius: var(--r-sm);
  font-size: clamp(0.5625rem, 13cqi, var(--fs-100));
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  font-variant-numeric: tabular-nums;
}
.pad-key:empty { display: none; }

/* Flash do toque. `transition-duration: 0s` no estado ligado = feedback
   instantâneo; a saída (remoção da classe) volta a animar pelos ~180ms da
   regra base, virando um decay natural. */
.pad.is-hit,
.pad:active {
  background-color: var(--pad-face-lit);
  transform: scale(0.95);
  box-shadow: 0 0 0 2px var(--pad-glow),
              0 0 1.25rem color-mix(in oklab, var(--pad-glow), transparent 45%);
  transition-duration: 0s;
}

/* Disparo vindo do sequencer: anel, sem o "afundar" do toque manual — assim
   dá pra distinguir o que você tocou do que a máquina tocou. */
.pad.is-playing {
  background-color: color-mix(in oklab, var(--pad-face), var(--pad-face-lit) 55%);
  box-shadow: inset 0 0 0 2px var(--pad-glow);
}

/* -----------------------------------------------------------------------------
   7. SEQUENCER
   O scroller horizontal é a .seq-grid (e não cada .seq-steps isolada) porque
   as colunas de todas as trilhas precisam permanecer alinhadas ao rolar; com
   um scroller por linha as trilhas desalinhariam. .seq-steps vira
   `display: contents` para que os passos entrem direto na grade da linha, o
   que faz o .seq-row-label grudar de verdade na borda esquerda.
   -------------------------------------------------------------------------- */
.seq-grid {
  --label-w: clamp(3.5rem, 22vw, 7rem);
  --step-min: var(--tap);

  display: flex;
  flex-direction: column;
  gap: var(--sp-1);
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scroll-snap-type: x proximity;
  scroll-padding-inline-start: var(--label-w);
  scrollbar-width: thin;
  scrollbar-color: var(--line) transparent;
}

.seq-row {
  display: grid;
  grid-template-columns: var(--label-w) repeat(var(--steps, 16), minmax(var(--step-min), 1fr));
  gap: var(--sp-1);
  align-items: stretch;
  min-inline-size: 100%;
  inline-size: max-content;
}

.seq-row-label {
  position: sticky;
  inset-inline-start: 0;
  z-index: 1;
  display: flex;
  align-items: center;
  padding-inline: var(--sp-2);
  background-color: var(--surface);
  /* a sombra sólida cobre exatamente o gap à direita, para que os passos não
     apareçam por baixo do rótulo enquanto a linha rola */
  box-shadow: var(--sp-1) 0 0 0 var(--surface);
  border-radius: var(--r-sm);
  color: var(--ink-muted);
  font-size: var(--fs-100);
  font-weight: 650;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  user-select: none;
}

/* Os passos participam da grade da linha (colunas alinhadas entre trilhas). */
.seq-steps { display: contents; }

.seq-step {
  min-block-size: var(--tap);      /* alvo de toque de 44px também aqui */
  min-inline-size: var(--tap);
  padding: 0;
  background-color: var(--surface-raised);
  border: 1px solid var(--line-soft);
  border-radius: var(--r-sm);
  cursor: pointer;
  touch-action: manipulation;      /* o pintar-arrastando é gerido no JS */
  -webkit-tap-highlight-color: transparent;
  user-select: none;
  transition: background-color var(--t-fast) ease-out,
              border-color var(--t-fast) ease-out,
              box-shadow var(--t-fast) ease-out;
}

@media (hover: hover) {
  .seq-step:hover { border-color: var(--line); background-color: color-mix(in oklab, var(--surface-raised), var(--ink) 8%); }
}

/* Primeiro passo de cada tempo: um pouco mais claro + ponto de snap. */
.seq-step.is-beat {
  background-color: color-mix(in oklab, var(--surface-raised), var(--ink) 6%);
  border-color: var(--line);
  scroll-snap-align: start;
}

.seq-step.is-on {
  background-color: var(--accent);
  border-color: color-mix(in oklab, var(--accent), var(--ink) 25%);
}

/* Cabeça de leitura: anel que percorre a coluna atual, ligada ou não. */
.seq-step.is-current {
  box-shadow: inset 0 0 0 2px var(--accent-2);
}
.seq-step.is-current:not(.is-on) {
  background-color: color-mix(in oklab, var(--accent-2), transparent 80%);
}

/* -----------------------------------------------------------------------------
   8. INSPECTOR
   Bottom sheet no celular (perto do polegar), painel flutuante no desktop.
   `[hidden]` vence pela cascata — nada de !important para reconquistar isso.
   -------------------------------------------------------------------------- */
.inspector {
  position: fixed;
  inset-block-end: 0;
  inset-inline: 0;
  z-index: 20;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-2);
  padding: var(--sp-3)
           calc(var(--sp-3) + env(safe-area-inset-right))
           calc(var(--sp-3) + env(safe-area-inset-bottom))
           calc(var(--sp-3) + env(safe-area-inset-left));
  background-color: var(--surface-raised);
  border-block-start: 1px solid var(--line);
  border-start-start-radius: var(--r-lg);
  border-start-end-radius: var(--r-lg);
  box-shadow: var(--shadow-2);
}
.inspector[hidden] { display: none; }

.inspector-sample,
.inspector-key {
  min-block-size: var(--tap);
  padding-inline: var(--sp-3);
  background-color: var(--surface);
  color: var(--ink);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
}
.inspector-sample { flex: 1 1 10rem; }
.inspector-key {
  flex: 0 0 3.5rem;
  inline-size: 3.5rem;
  text-align: center;
  font-weight: 700;
  text-transform: uppercase;
}
.inspector-close { flex: 0 0 auto; margin-inline-start: auto; }

/* -----------------------------------------------------------------------------
   9. OVERLAY DE DESTRAVAR ÁUDIO
   O navegador exige um gesto antes do primeiro som; a tela inteira é o botão.
   -------------------------------------------------------------------------- */
#start-overlay {
  position: fixed;
  inset: 0;
  z-index: 50;
  display: grid;
  place-content: center;
  gap: var(--sp-2);
  padding: var(--sp-5);
  background-color: color-mix(in oklab, var(--bg), transparent 8%);
  color: var(--ink);
  border: none;
  font-size: var(--fs-500);
  font-weight: 650;
  letter-spacing: -0.01em;
  cursor: pointer;
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
}
#start-overlay[hidden] { display: none; }

/* -----------------------------------------------------------------------------
   10. ≥900px — enriquecimento
   Pads e sequencer deixam de empilhar e passam a dividir a largura; a barra
   de templates deixa de ser fita e quebra em linhas; o inspector solta do
   rodapé e vira painel.
   -------------------------------------------------------------------------- */
@media (min-width: 900px) {
  .app {
    gap: var(--sp-4);
    padding-inline: calc(var(--sp-5) + env(safe-area-inset-left))
                    calc(var(--sp-5) + env(safe-area-inset-right));
  }

  .template-bar {
    flex-wrap: wrap;
    overflow-x: visible;
  }

  .stage {
    display: grid;
    grid-template-columns: minmax(18rem, 2fr) minmax(0, 3fr);
    align-items: start;
    /* Centra o bloco verticalmente quando sobra altura, em vez de deixar um
       vazio grande embaixo. `safe` garante que, se o conteudo for MAIOR que a
       area, ele volte a alinhar no inicio e continue rolavel (centrar sem
       `safe` corta o topo, que fica inalcancavel). */
    align-content: safe center;
    gap: var(--sp-4);
  }

  .pad-section,
  .seq-section { padding: var(--sp-4); }

  .pad-grid { --pad-max: clamp(4.5rem, 9vw, 8.5rem); }

  .seq-grid { --label-w: 7rem; }

  .app:has(.inspector:not([hidden])) .stage { padding-block-end: var(--sp-2); }

  .inspector {
    inset-block-end: var(--sp-5);
    inset-inline: auto var(--sp-5);
    inline-size: min(26rem, calc(100vw - 2 * var(--sp-5)));
    border-radius: var(--r-lg);
    border: 1px solid var(--line);
  }
}

/* Passos mais compactos SÓ com ponteiro preciso (mouse/trackpad em tela larga).
   Em qualquer aparelho de toque o alvo continua sendo os 44px de --tap. */
@media (min-width: 900px) and (pointer: fine) {
  .seq-grid { --step-min: 1.5rem; }
  .seq-step { min-inline-size: 1.5rem; min-block-size: 2.25rem; }
}

/* -----------------------------------------------------------------------------
   11. MOVIMENTO REDUZIDO
   Estados continuam mudando de cor (o feedback é informação), mas nada anima.
   -------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  /* Sem !important: cada regra abaixo repete o seletor da regra que anima e
     vem depois no arquivo, então vence por ordem com a mesma especificidade. */
  .btn,
  .template-chip,
  .pad,
  .seq-step { transition: none; }

  .pad.is-hit,
  .pad:active { transform: none; }

  .btn:active { transform: none; }
}
