:root {
  --ink: #1c1d20;
  --chassis: #eceef0;
  --paper: #f4f5f7;
  --paper-grid: #c4c8cf;
  --page: #dfe0e2;
  --muted: #676b72;
  --faint: #a3a7ae;
  --hairline: rgba(28, 29, 32, .22);
  --mono: 'IBM Plex Mono', ui-monospace, monospace;
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  height: 100%;
}

body {
  background: var(--page);
  font-family: var(--mono);
  color: var(--ink);
  user-select: none;
  -webkit-user-select: none;
  display: flex;
  align-items: center;
  justify-content: center;
}

@keyframes einkflash { 0%, 55% { filter: invert(1); } 100% { filter: invert(0); } }
@keyframes blinkcur { 0%, 49% { opacity: 1; } 50%, 100% { opacity: 0; } }
@keyframes rotatehint { 0%, 20% { transform: rotate(0deg); } 50%, 70% { transform: rotate(90deg); } 100% { transform: rotate(90deg); } }

/* ---- device shell: landscape shape, played sideways on a phone ---- */

.device {
  display: flex;
  flex-direction: column;
  width: 100%;
  height: 100%;
  max-width: 900px;
  max-height: 480px;
  background: var(--chassis);
  overflow: hidden;
}

@media (min-width: 900px) {
  .device {
    height: min(480px, calc(100vh - 48px));
    border: 1px solid var(--hairline);
    border-radius: 24px;
    box-shadow: 0 24px 60px rgba(28, 29, 32, .18);
  }
}

.device.flash { animation: einkflash .35s step-end; }

/* Portrait phones can't show the two-pane layout usefully — ask for a
   rotate instead of cramming it in. Gated to narrow viewports so a tall
   desktop window doesn't get mistaken for a phone. */
.rotate-hint { display: none; }
@media (orientation: portrait) and (max-width: 899px) {
  .device { display: none; }
  .rotate-hint {
    display: flex;
    position: fixed;
    inset: 0;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 18px;
    background: var(--page);
    color: var(--ink);
    text-align: center;
    padding: 24px;
  }
}
.rotate-phone {
  width: 34px;
  height: 56px;
  border: 2px solid var(--ink);
  border-radius: 8px;
  position: relative;
  animation: rotatehint 1.8s ease-in-out infinite;
}
.rotate-phone::after {
  content: '';
  position: absolute;
  left: 50%;
  bottom: 6px;
  width: 4px;
  height: 4px;
  margin-left: -2px;
  background: var(--ink);
  border-radius: 50%;
}
.rotate-text {
  font: 600 11px var(--mono);
  letter-spacing: 1.5px;
  line-height: 1.9;
}

/* ---- masthead ---- */

.masthead {
  flex: none;
  display: flex;
  align-items: baseline;
  gap: 8px;
  padding: 10px 16px;
  border-bottom: 1px solid var(--hairline);
}
.masthead-dot { width: 9px; height: 9px; background: var(--ink); border-radius: 3px; align-self: center; }
.masthead-name { font: 700 13px var(--mono); letter-spacing: 2px; }
.masthead-sub { font: 400 9px var(--mono); letter-spacing: 1px; color: var(--muted); }
.masthead-tag { margin-left: auto; font: 400 9px var(--mono); letter-spacing: 1px; color: var(--muted); }

/* ---- two-pane layout ---- */

.layout {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: row;
}
.pane {
  flex: 1;
  min-width: 0;
  min-height: 0;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
}
/* Left pane: a square sketch board that flexes to fill the column height,
   with the prompt row pinned below it. */
.pane-sketch {
  flex: 0.62;
  border-right: 1px solid var(--hairline);
  display: flex;
  flex-direction: column;
}
/* Right pane: pads, then the pad controls, then the one-line transport,
   spread to fill the column height. */
.pane-pads {
  flex: 1;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
}

/* ---- paper ---- */

.paper-card {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  margin: 12px 14px 0;
  border: 1px solid var(--hairline);
  border-radius: 12px;
  overflow: hidden;
}
.paper-wrap {
  position: relative;
  flex: 1;
  min-height: 0;
}
#paper {
  display: block;
  width: 100%;
  height: 100%;
  background: var(--paper);
  touch-action: none;
  cursor: crosshair;
}
.paper-empty {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  pointer-events: none;
}
.paper-empty > div {
  font: 400 10.5px var(--mono);
  color: #878b93;
  letter-spacing: 1px;
  text-align: center;
  line-height: 1.9;
}
.paper-empty.hidden { display: none; }

.ink-row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 9px 10px;
  border-top: 1px solid var(--hairline);
}
.ink-swatches { display: flex; gap: 12px; }
.ink-swatch {
  width: 22px;
  height: 22px;
  border-radius: 50%;
  cursor: pointer;
  flex: none;
  box-shadow: 0 0 0 1px rgba(28, 29, 32, .25);
}
.ink-swatch.selected { box-shadow: 0 0 0 3px var(--chassis), 0 0 0 4.5px var(--ink); }
.ink-hint {
  flex: 1;
  font: 400 8.5px var(--mono);
  color: var(--muted);
  letter-spacing: .5px;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ---- chips (UNDO / CLR / AI / DEL / PLAY) ---- */

.chip {
  font: 600 10px var(--mono);
  letter-spacing: 1px;
  padding: 6px 10px;
  border: 1px solid var(--hairline);
  border-radius: 7px;
  cursor: pointer;
  background: var(--chassis);
  color: var(--ink);
  flex: none;
}
.chip:active { background: var(--ink); color: var(--chassis); }
.chip-toggle.on { background: var(--ink); color: var(--chassis); }

/* ---- prompt row ---- */

.prompt-row {
  display: flex;
  margin: 12px 14px 14px;
  border: 1px solid var(--hairline);
  border-radius: 12px;
  overflow: hidden;
}
.prompt-lcd { flex: 1; padding: 8px 12px; overflow: hidden; }
.prompt-label {
  font: 600 8px var(--mono);
  color: var(--muted);
  letter-spacing: 2px;
  margin-bottom: 3px;
}
.prompt-text {
  font: 500 10.5px var(--mono);
  letter-spacing: .2px;
  line-height: 1.5;
  min-height: 32px;
}
.cursor {
  display: inline-block;
  width: 6px;
  height: 11px;
  background: var(--ink);
  margin-left: 3px;
  vertical-align: -1px;
  animation: blinkcur 1s step-end infinite;
}
.gen-btn {
  flex: none;
  width: 100px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--ink);
  color: var(--chassis);
  border: none;
  border-left: 1px solid var(--hairline);
  border-radius: 0;
  cursor: pointer;
  font: 700 11px var(--mono);
  letter-spacing: 1.5px;
  text-align: center;
  line-height: 1.5;
}
.gen-btn:active { opacity: .75; }
.gen-btn.waiting { background: var(--chassis); color: var(--ink); }

/* ---- pads ---- */

.pad-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 8px;
  margin: 12px 14px 0;
}
/* On a short landscape phone the column is proportionally wider, so narrow the
   sketch pane (keeps the square's mat small) and cap the pad size so the whole
   right column (8 pads + pitch + transport) still fits without scrolling. */
@media (max-height: 440px) {
  .pane-sketch { flex: 0.4; }
  .pad-grid { justify-items: center; }
  .pad { width: min(100%, 84px); }
  /* the narrowed ink row needs tighter swatches and no hint to fit UNDO/CLR */
  .ink-row { gap: 6px; padding: 9px 7px; }
  .ink-swatches { gap: 7px; }
  .ink-swatch { width: 18px; height: 18px; }
  .ink-hint { display: none; }
}
.pad {
  position: relative;
  display: flex;
  flex-direction: column;
  background: var(--paper);
  border: 1px solid var(--hairline);
  border-radius: 10px;
  overflow: hidden;
  cursor: pointer;
  min-width: 0;
}
.pad:active { filter: invert(1); }
.pad.selected { border: 2px solid var(--ink); }
.pad.playing { animation: einkflash .3s step-end; }
.pad-board {
  position: relative;
  width: 100%;
  aspect-ratio: 1;
}
.pad-thumb {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: contain;
  display: none;
}
.pad-blank {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font: 400 8px var(--mono);
  color: var(--faint);
  letter-spacing: 1px;
  background: repeating-linear-gradient(45deg, transparent 0 3px, rgba(28, 29, 32, .05) 3px 4px);
}
.pad.filled .pad-thumb { display: block; }
.pad.filled .pad-blank { display: none; }
.pad-strip {
  display: flex;
  align-items: center;
  gap: 5px;
  padding: 4px 7px;
  border-top: 1px solid var(--hairline);
  background: var(--chassis);
  color: var(--ink);
}
.pad.selected .pad-strip { border-top: 2px solid var(--ink); }
.pad-led {
  width: 7px;
  height: 7px;
  background: transparent;
  border: 1px solid var(--faint);
}
.pad-label { font: 600 9px var(--mono); letter-spacing: 1px; }
.pad-tag { margin-left: auto; font: 400 8px var(--mono); opacity: .65; }

/* ---- control strip ---- */

.control-strip {
  display: flex;
  align-items: center;
  gap: 12px;
  margin: 0 14px;
  padding: 10px 12px;
  border: 1px solid var(--hairline);
  border-radius: 12px;
}
.sel-name {
  font: 600 9px var(--mono);
  letter-spacing: 1px;
  flex: none;
  min-width: 44px;
}
.fader-group { display: flex; align-items: center; gap: 8px; flex: 1; min-width: 0; }
.fader-label { font: 400 8px var(--mono); color: var(--muted); letter-spacing: 1px; }
.fader {
  flex: 1;
  position: relative;
  height: 26px;
  display: flex;
  align-items: center;
  touch-action: none;
  cursor: ew-resize;
}
.fader-track { width: 100%; height: 1.5px; background: var(--ink); }
.fader-center { position: absolute; left: 50%; top: 6px; bottom: 6px; width: 1.5px; background: var(--ink); }
.fader-knob {
  position: absolute;
  left: 50%;
  top: 4px;
  width: 12px;
  height: 18px;
  margin-left: -6px;
  background: var(--ink);
  border-radius: 4px;
  pointer-events: none;
}
.fader-value { font: 600 9px var(--mono); width: 26px; text-align: right; flex: none; }

/* ---- transport (one-line tempo / step indicator) ---- */

.transport {
  flex: none;
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 0 14px 12px;
  padding: 8px 12px;
  border: 1px solid var(--hairline);
  border-radius: 12px;
}
.bpm-group {
  display: flex;
  align-items: center;
  gap: 6px;
  flex: none;
}
.bpm-value {
  display: flex;
  align-items: baseline;
  gap: 3px;
  justify-content: center;
  min-width: 44px;
  font: 600 11px var(--mono);
}
.bpm-unit {
  font: 400 8px var(--mono);
  color: var(--muted);
  letter-spacing: 1px;
}
.steps-bar {
  flex: 1;
  min-width: 0;
  display: grid;
  grid-template-columns: repeat(16, 1fr);
  gap: 3px;
  align-items: center;
}
.step-tick {
  height: 12px;
  min-width: 0;
  background: var(--paper);
  border: 1px solid var(--hairline);
  border-radius: 2px;
  cursor: pointer;
}
.step-tick.step-beat { background: #e4e6e9; }
.step-tick.hit { background: #b3b8bf; border-color: #9aa0a8; }
.step-tick.current { background: var(--ink); border-color: var(--ink); }

/* ---- phone landscape: three columns, nothing overflows ----

   The panes become `display: contents` so their children drop straight into
   one grid: sketch | prompt+controls | pads. The DOM (and the desktop
   layout above) is untouched.

   The device is sized in dvh and pinned sticky under a chrome-height spacer,
   so one upward flick collapses the browser bars and the app snaps to fill
   the screen. */

@media (orientation: landscape) and (max-height: 560px) {

  html {
    height: auto;
    overscroll-behavior-y: none;
  }
  body {
    display: block;
    height: auto;
    min-height: 100svh;
  }
  /* Real scroll room below the app: Safari only collapses its chrome once
     there is a decent amount to scroll, and it stays collapsed only if the
     page doesn't spring back. So: a generous spacer, no scroll-snap (snapping
     pulled the page straight back to the top and the bars returned), and a
     sticky device that stays pinned full-screen the whole way down. */
  body::after {
    content: '';
    display: block;
    height: 60vh;
  }
  /* Keep the chassis clear of the rounded display corners and the home
     indicator — edge-to-edge content gets clipped at the corners otherwise.
     env() covers notched devices; the floor covers the rest. */
  .device {
    position: sticky;
    top: 0;
    height: 100dvh;
    max-width: none;
    max-height: none;
    padding-left: max(7px, env(safe-area-inset-left));
    padding-right: max(7px, env(safe-area-inset-right));
    padding-bottom: max(5px, env(safe-area-inset-bottom));
  }

  .masthead { padding: 6px 6px; gap: 6px; }
  .masthead-sub { display: none; }

  .layout {
    display: grid;
    grid-template-columns: auto minmax(180px, 1fr) auto;
    /* the prompt card takes the slack; transport and pitch are content-sized
       so they can never outgrow their boxes on a short viewport */
    grid-template-rows: minmax(0, 1fr) auto auto;
    gap: 8px;
    padding: 8px 0 0;
    /* the sketch and pad columns measure themselves against this box */
    container-type: size;
  }
  .pane { display: contents; }

  /* column 1 — a true square sketch board, ink controls in a rail beside it.
     The board is sized off the column height, so the column shrink-wraps to
     square + rail and stands exactly as tall as the other two. */
  .paper-card {
    grid-column: 1;
    grid-row: 1 / -1;
    margin: 0;
    flex-direction: row;
  }
  /* The board's side is an explicit width, never one inferred from the height
     via aspect-ratio: a grid track can't hand an intrinsic width back to the
     item that's supposed to define it, and engines disagree about what to do
     with that. The vw cap guarantees the three columns always fit. */
  .paper-wrap { flex: none; height: 100%; width: 38vw; aspect-ratio: auto; }
  @supports (height: 1cqh) {
    .paper-wrap { width: min(calc(100cqh - 2px), 42vw); }
  }
  /* fixed rail — wide enough for UNDO/CLR in any fallback font, no wider */
  .ink-row {
    flex: none;
    width: 44px;
    flex-direction: column;
    align-items: stretch;
    gap: 9px;
    padding: 8px 5px;
    border-top: none;
    border-left: 1px solid var(--hairline);
  }
  .ink-swatches { flex-direction: column; gap: 9px; align-items: center; }
  .ink-swatch { width: 20px; height: 20px; }
  .ink-hint { display: none; }
  /* inks at the top of the rail, UNDO/CLR anchored to the bottom */
  .ink-row .chip { padding: 5px 2px; font-size: 8px; letter-spacing: .5px; text-align: center; }
  #undoBtn { margin-top: auto; }

  /* column 2 — prompt with GENERATE beneath it, transport on the bottom row */
  .prompt-row {
    grid-column: 2;
    grid-row: 1;
    margin: 0;
    flex-direction: column;
    min-height: 0;
  }
  /* the readout takes whatever height the column has spare; GENERATE keeps
     its own size at the bottom of the card */
  .prompt-lcd { flex: 1; min-height: 36px; overflow-y: auto; }
  .gen-btn {
    flex: none;
    width: 100%;
    padding: 13px 0;
    border-left: none;
    border-top: 1px solid var(--hairline);
  }
  /* Transport as an explicit two-row grid rather than a wrapping flex row:
     PLAY and the tempo group share the top row and stretch across it, the
     sixteen steps sit on the row below. Wrapping was reflowing PLAY onto its
     own line on narrow columns and spilling the steps out of the box. */
  .transport {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.5fr);
    align-items: center;
    grid-column: 2;
    grid-row: 2;
    margin: 0;
    gap: 8px;
    padding: 9px 10px;
  }
  .transport > .chip { grid-column: 1; padding: 9px 4px; text-align: center; }
  .bpm-group { grid-column: 2; justify-content: space-between; gap: 4px; }
  .bpm-group .chip { flex: none; padding: 9px 8px; }
  .bpm-value { flex: 1; min-width: 38px; }
  /* small squares — the column width sets the size, the ratio keeps them square */
  .steps-bar { grid-column: 1 / -1; gap: 2px; }
  .step-tick { height: auto; aspect-ratio: 1; border-radius: 2px; }

  /* column 3 — the eight pads, full height.

     The column is as wide as the height allows rather than a share of the
     width: the vertical room the four pad rows get decides the board size,
     and the column is two of those across. That keeps every board exactly
     square, so pad art fills it instead of being letterboxed. */
  .pad-grid {
    --pad-gap: 6px;
    /* row area = 100cqh − pad gaps − pad borders */
    --pad-w: calc((100cqh - 18px - 8px) / 4);
    grid-column: 3;
    grid-row: 1 / -1;
    margin: 0;
    min-height: 0;
    width: 20vw;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    grid-template-rows: repeat(4, auto);
    gap: var(--pad-gap);
    align-content: center;
    justify-items: stretch;
  }
  @supports (height: 1cqh) {
    .pad-grid { width: min(calc(2 * var(--pad-w) + var(--pad-gap)), 24vw); }
  }
  .pad { width: auto; min-height: 0; border-radius: 8px; }
  .pad-board { aspect-ratio: 1; flex: none; }
  /* the label rides on the board instead of sitting under it — a strip of its
     own would cost a sixth of every board's height, and the boards only have
     a quarter of the column to share */
  .pad-strip {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    gap: 3px;
    height: 13px;
    padding: 0 4px;
    background: rgba(236, 238, 240, .88);
  }
  .pad-led { width: 5px; height: 5px; }
  .pad-label { font-size: 7.5px; letter-spacing: .5px; }
  .pad-tag { font-size: 7px; }
  /* selection as an inset ring, so a selected pad doesn't grow 2px and shove
     the column out of its exact fit */
  .pad.selected { border-width: 1px; box-shadow: inset 0 0 0 2px var(--ink); }
  .pad.selected .pad-strip { border-top-width: 1px; }

  /* pitch strip, on the bottom row under the transport */
  .control-strip {
    grid-column: 2;
    grid-row: 3;
    margin: 0;
    gap: 8px;
    padding: 5px 10px;
  }
  .sel-name {
    min-width: 0;
    font-size: 8px;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
  }
  .control-strip .chip { padding: 5px 8px; font-size: 8px; }
  .fader-label { display: none; }
  .fader { height: 22px; }
  .fader-value { width: 20px; font-size: 8px; }
}
