body { margin: 0; font: 16px/1.4 system-ui, sans-serif; background: #f4f4f4; color: #222; }
/* phone first: one column with a 12 px gutter; a 640 px column on wider screens */
main { max-width: 640px; margin: 0 auto; padding: 12px; display: flex; flex-direction: column; gap: 12px; overflow-wrap: anywhere; }
main > * { min-width: 0; }
@media (min-width: 480px) { main { padding: 16px; } }
img, canvas { max-width: 100%; }
label { display: flex; flex-direction: column; gap: 4px; }
/* 16 px inputs: iOS zooms into anything smaller; 44 px tap targets */
input, button, select { font: inherit; font-size: 16px; padding: 10px; border-radius: 6px; border: 1px solid #aaa; min-width: 0; }
button, select, input:not([type=checkbox]):not([type=range]) { min-height: 44px; }
input[type=checkbox] { width: 24px; height: 24px; }
button { background: #2563eb; color: #fff; border: 0; cursor: pointer; touch-action: manipulation; }
button:disabled { background: #999; cursor: not-allowed; }
.error { color: #b91c1c; min-height: 1.4em; margin: 0; }
.room-code { font-size: 3rem; font-weight: bold; letter-spacing: .2em; margin: 0; }
.code-input { text-transform: uppercase; }
.join-qr { margin: 0; display: flex; flex-direction: column; align-items: center; gap: 4px; }
.join-qr img { width: min(60vw, 240px); height: auto; image-rendering: pixelated; background: #fff; }
.join-qr figcaption { font-size: .85rem; overflow-wrap: anywhere; }
.timer { font-size: 1.5rem; font-weight: bold; margin: 0 -12px; padding: 4px 12px; position: sticky; top: 0; z-index: 1; background: #f4f4f4e6; } /* always in view while scrolling or typing */
.meme { width: 100%; height: auto; display: block; }
.card { margin: 0; padding: 6px; background: #fff; border: 3px solid transparent; border-radius: 8px; }
.card.votable { cursor: pointer; }
.card.mine { border-color: #999; border-style: dashed; opacity: .7; }
.card.picked { border-color: #16a34a; background: #dcfce7; }
figcaption { text-align: center; padding-top: 4px; }
.winner { font-size: 1.5em; font-weight: bold; }
.meme.editor { touch-action: none; cursor: move; width: auto; max-height: 45vh; margin: 0 auto; } /* short enough to keep the text inputs below it in view */
.meme.editor.resize { cursor: nwse-resize; }
.meme.editor.rotate { cursor: grab; }
.box-list { display: flex; flex-direction: column; gap: 6px; }
.box-row { display: flex; gap: 6px; }
.box-row input { flex: 1; min-width: 0; box-sizing: border-box; } /* 44 px tall with its padding, like the buttons */
.box-row.selected input { border: 2px dashed #ca8a04; }
.size-row { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 12px; }
.size-row input[type=range] { flex: 1 1 120px; }
.size-row input[type=search] { flex: 1 1 160px; }
label.inline { flex-direction: row; align-items: center; }
.btn-row { display: flex; gap: 8px; }
.btn-row > * { flex: 1; }
/* caption screen (T-061-j): a phone shows every control and the timer without scrolling */
main.caption { padding-top: 6px; padding-bottom: 6px; gap: 6px; }
main.caption > p { margin: 0; }
main.caption > .error:empty { display: none; }
main.caption .leave { margin-top: 0; }
main.caption .round-row { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; position: sticky; top: 0; z-index: 1; margin: 0 -12px; padding: 0 12px; background: #f4f4f4e6; }
main.caption .round-row > * { margin: 0; }
main.caption .round-row .timer { position: static; padding: 0; background: none; }
/* the preview gets what the controls leave (about 420 px with 2 boxes, 520 px with the GIF rows), at least a quarter of the screen */
main.caption .meme.editor { max-height: max(25vh, calc(100vh - 430px)); max-height: max(25dvh, calc(100dvh - 430px)); }
main.caption:has(#gif-scrub:not([hidden])) .meme.editor { max-height: max(18vh, calc(100vh - 530px)); max-height: max(18dvh, calc(100dvh - 530px)); }
#gif-scrub, #gif-keys { flex-wrap: nowrap; }
#gif-scrub input[type=range] { flex: 1 1 60px; min-width: 0; }
#gif-label { font-size: .85rem; white-space: nowrap; }
#key-info { font-size: .75rem; line-height: 1.2; }
.reveal-count { margin: 0; font-weight: bold; text-align: center; }
.card.reveal .meme { width: auto; max-width: 100%; max-height: 60vh; margin: 0 auto; }
.sticker-row { align-items: center; }
.sticker-row.selected { outline: 2px dashed #ca8a04; border-radius: 6px; }
.sticker-thumb { width: 40px; height: 40px; object-fit: contain; background: repeating-conic-gradient(#ddd 0 25%, #fff 0 50%) 0 0 / 12px 12px; }
.grow { flex: 1; }
#gif-scrub button { min-width: 5em; }
.search-results { display: grid; grid-template-columns: repeat(auto-fill, minmax(72px, 1fr)); gap: 4px; }
.search-pick { min-height: 0; position: relative; display: flex; flex-direction: column; align-items: center; gap: 2px; padding: 3px; font-size: .7rem; background: #fff; color: #222; border: 1px solid #aaa; }
.search-pick:disabled { background: #eee; color: #888; }
.search-pick img { width: 100%; height: 56px; object-fit: contain; }
.search-pick .badge { position: absolute; top: 3px; right: 3px; padding: 0 3px; border-radius: 3px; background: #111c; color: #fff; font-size: .6rem; font-weight: bold; }
#create-more { height: 1px; }
.search-pick span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 100%; }
.gif-download, .png-download { align-self: center; }
.card .gif-download, .card .png-download { display: block; margin: 6px auto 0; }
#banner { position: sticky; top: 0; z-index: 2; margin: 0; padding: 8px; text-align: center; background: #facc15; color: #222; font-weight: bold; }
#banner[hidden], .size-row[hidden] { display: none; }
.leave { background: #6b7280; margin-top: 12px; }
main.admin { max-width: 1100px; }
.row { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }
.tabs { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 12px; border-bottom: 1px solid #ccc; padding-bottom: 8px; }
.tabs button { background: #e5e7eb; color: #222; }
.tabs button.active { background: #2563eb; color: #fff; }
.tabs .logout { margin-left: auto; background: #6b7280; color: #fff; }
button.secondary { background: #6b7280; }
.filters select, .filters input { min-width: 0; }
.count { margin: 0; color: #555; }
.tpl-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: 8px; }
.tpl { margin: 0; padding: 6px; background: #fff; border-radius: 8px; display: flex; flex-direction: column; gap: 4px; }
.tpl[hidden] { display: none; }
.tpl img { width: 100%; height: 110px; object-fit: contain; background: #eee; }
.tpl .src { font-size: .75rem; color: #6b7280; align-self: flex-start; }
.tpl figcaption { font-size: .85rem; padding: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tpl button { flex: 1; padding: 6px; font-size: .85rem; }
.tpl.disabled img { opacity: .35; }
.tpl.disabled { outline: 2px dashed #b91c1c; }
.filters #f-name { flex: 1 1 200px; }
table.list { width: 100%; border-collapse: collapse; background: #fff; }
.list th, .list td { padding: 6px 8px; border-bottom: 1px solid #e5e7eb; text-align: left; vertical-align: top; }
.list tr.clickable { cursor: pointer; }
.list tr.clickable:hover { background: #eef2ff; }
.scroll { overflow-x: auto; }
/* TV mode: thumbnails on phones, a big couch-readable screen on the TV (body.tv) */
.thumbs { display: grid; grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: 8px; }
.card.thumb .meme { width: auto; max-width: 100%; max-height: 30vh; margin: 0 auto; }
button.big { font-size: 1.5rem; min-height: 72px; }
/* a TV can't scroll: each TV screen is exactly one viewport, sized in vh; the meme area (.card.reveal, .thumbs, QR) takes what is left */
body.tv { height: 100vh; display: flex; flex-direction: column; } /* the reconnect banner takes its line out of the screen, not below it */
body.tv main { max-width: none; box-sizing: border-box; flex: 1; min-height: 0; margin: 0; font-size: 4vh; line-height: 1.25; padding: 2vh 4vw; gap: 1.5vh; }
body.tv main > *, body.tv h2, body.tv .scores { margin: 0; }
body.tv .error:empty { display: none; }
body.tv .room-code { font-size: 3em; text-align: center; }
body.tv .timer { font-size: 2em; text-align: center; }
body.tv .join-qr { flex: 1; min-height: 0; display: grid; grid-template-rows: minmax(0, 1fr) auto; justify-items: center; }
body.tv .join-qr img { width: auto; height: 100%; }
body.tv .join-qr figcaption { font-size: .6em; }
body.tv .card { display: grid; grid-template-rows: minmax(0, 1fr) auto; min-height: 0; }
body.tv .card .meme { width: 100%; height: 100%; max-height: none; object-fit: contain; } /* scaled up past the 600 px canvas */
body.tv .card figcaption { font-size: .7em; white-space: nowrap; overflow: hidden; display: flex; justify-content: center; } /* one line, so the meme keeps the height */
body.tv .card figcaption .who { min-width: 0; overflow: hidden; text-overflow: ellipsis; } /* long names are cut, the vote count never is */
body.tv .card.reveal { flex: 1; }
body.tv .thumbs { flex: 1; min-height: 0; grid-template-columns: repeat(auto-fit, minmax(min(30vh, 100%), 1fr)); grid-auto-rows: minmax(0, 1fr); }
body.tv .players { columns: 2; }
body.tv .leave { align-self: flex-start; font-size: 1rem; margin: 0; }
.tv-final { flex: 1; min-height: 0; display: flex; gap: 4vw; } /* scoreboard beside the winning memes */
.tv-winners { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1vh; }
.match-memes { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 8px; }
