/* ---- the public deck ---- */
body.deckpage { overflow: hidden; height: 100%; }
/* svh, not dvh: the dynamic unit tracks Chrome's collapsing address bar, so the deck
   grew as you swiped and was then a bar's height too tall when the list brought the bar
   back — which is what squashed the header. svh is the height with the bar showing and
   never changes, so the layout holds still. */
.app.deck { height: 100vh; height: 100svh; min-height: 0; position: relative; overflow: hidden; user-select: none; padding-bottom: env(safe-area-inset-bottom, 0px); box-sizing: border-box; }
/* Nothing may scroll the deck itself — only the panels inside it. Without this, a
   programmatic scroll anywhere inside can move the whole app and take the header
   off the top of the screen. */
body.deckpage { overflow: hidden; position: fixed; inset: 0; }

/* Fixed height, so nothing below can squeeze it however the viewport moves. */
.app.deck header { display: flex; align-items: center; gap: 14px; flex: 0 0 auto; min-height: 44px; }
.app.deck header .home { display: inline-flex; align-items: center; text-decoration: none; }
.app.deck header .room { color: var(--ink); flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.app.deck header .count { color: var(--grey); font-size: 11px; }

.app.deck .stage { flex: 1; position: relative; min-height: 0; }
.app.deck .card { position: absolute; inset: 0; display: flex; padding: 8px 26px 0; transition: transform .26s ease, opacity .26s ease; overflow-y: auto; }
.app.deck .card.out-up { transform: translateY(-22px); opacity: 0; }
.app.deck .card.out-down { transform: translateY(22px); opacity: 0; }
.app.deck .inner { width: 100%; margin: auto 0; }

.app.deck .who { display: flex; align-items: center; gap: 8px; font-size: 11px; color: var(--grey); }
.app.deck .who .src { color: var(--ink); }
.app.deck .title { margin-top: 16px; font-size: 22px; line-height: 1.35; word-break: break-word; }
.app.deck .rest { margin-top: 10px; font-size: 14px; line-height: 1.5; color: var(--grey); white-space: pre-wrap; }
.app.deck .link { display: block; margin-top: 14px; font-size: 12px; color: var(--grey); word-break: break-all; }
.app.deck .tally { margin-top: 20px; display: flex; gap: 16px; font-size: 11px; color: var(--grey); }
.app.deck .tally b { font-weight: 400; color: var(--ink); }

.joincard .title { margin-top: 0; }
.joincard .btn { display: inline-block; margin: 22px 14px 0 0; }
.joincard .small { color: var(--grey); text-decoration: none; }

.app.deck .validate { display: flex; justify-content: center; gap: 34px; padding: 4px 0 10px; }

.app.deck .side { position: absolute; right: 26px; bottom: 4px; display: flex; flex-direction: column; align-items: center; gap: 22px; }
.app.deck .sbtn { display: inline-flex; flex-direction: column; align-items: center; gap: 3px; background: none; border: 0; color: var(--grey); font-size: 10px; cursor: pointer; }
.app.deck .sbtn:hover, .app.deck .sbtn.has { color: var(--ink); }

.app.deck .nav { position: absolute; left: 26px; bottom: 4px; display: flex; flex-direction: column; align-items: center; gap: 22px; }
.app.deck .nav button { display: inline-flex; background: none; border: 0; color: var(--grey); opacity: .45; cursor: pointer; }
.app.deck .nav button.on { opacity: 1; }

.app.deck .sheet { position: absolute; inset: 0; background: var(--bg); transform: translateY(100%); transition: transform .28s ease; z-index: 10; display: flex; flex-direction: column; }
.app.deck .sheet.open { transform: translateY(0); }
.app.deck .sheet .close { background: none; border: 0; color: var(--grey); font: inherit; font-size: 12px; cursor: pointer; }
.app.deck .list { flex: 1; overflow-y: auto; padding: 8px 24px 20px; }
.app.deck .comment { padding: 12px 0; border-bottom: 1px solid var(--soft); }
.app.deck .comment .meta { display: flex; gap: 12px; font-size: 11px; color: var(--grey); }
.app.deck .comment .body { margin-top: 5px; font-size: 15px; line-height: 1.5; white-space: pre-wrap; word-break: break-word; }
/* 8px below the field before the keyboard starts, matching chat's own compose row —
   this one had 16px, sitting noticeably higher than everywhere else the keyboard is used. */
.app.deck .compose { display: flex; align-items: flex-end; gap: 12px; padding: 0 24px 8px; }
/* margin: 0 is the fix — without it this inherits the generic .field's 26px
   margin-bottom from style.css, which is what pushed the line so far above the
   keyboard. Chat's own compose row already zeroes this; this one never did. */
.app.deck .compose .field { flex: 1; margin: 0; border-bottom: 1px solid var(--line); }
.app.deck .compose input { width: 100%; background: none; border: 0; padding: 8px 0; font: inherit; font-size: 15px; color: var(--ink); }
.app.deck .compose.signedout { justify-content: center; padding-bottom: 22px; }

/* No desktop text bump: the deck now sits in a phone-sized frame at any width. */

/* While the keyboard is up, keep the comment line above it rather than under it. */
body.xkb-open .app.deck .sheet { padding-bottom: 232px; }
body.xkb-open .app.deck .list { padding-bottom: 8px; }
@media (min-width: 900px) { body.xkb-open .app.deck .sheet { padding-bottom: 0; } }

.app.deck .follow { margin-top: 10px; font-size: 11px; color: var(--grey); }
.app.deck .follow.on { color: var(--ink); }

.app.deck .older-mark { margin-top: 18px; font-size: 11px; color: var(--grey); }

/* ---- the ring: opens the card, and fills with what you've opened ---- */
.app.deck .validate { display: flex; justify-content: center; padding: 2px 0 12px; }
.ring { width: 76px; height: 76px; padding: 0; background: none; border: 0; color: var(--line); cursor: pointer; display: inline-flex; align-items: center; justify-content: center; transition: color .2s ease, transform .15s ease; }
.ring:hover { color: var(--grey); }
.ring:active { transform: scale(.94); }
/* A press gives the button focus, and the browser draws its own ring around it. Keep
   it for keyboard users, who need it; drop it for a finger, which doesn't. */
.ring:focus { outline: none; }
.ring:focus-visible { outline: 1px solid var(--grey); outline-offset: 3px; }
.ring { -webkit-tap-highlight-color: transparent; touch-action: none; }
.ring svg { display: block; }

.chart { position: absolute; inset: 0; background: var(--bg); z-index: 20; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 20px; padding: 40px 28px; }
.chart[hidden] { display: none; }
.key-row { display: flex; align-items: center; gap: 10px; padding: 5px 0; font-size: 12px; }
.key-dot { width: 10px; height: 10px; border-radius: 50%; flex-shrink: 0; }
.key-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.key-n { color: var(--grey); font-size: 11px; }

.endcard .title { margin-top: 0; }
.endcard .btn { display: inline-block; margin-top: 22px; }


.app.deck header { justify-content: flex-start; }

/* ---- a sheet in the corner, bending as each card turns ---- */
.app.deck header .book-mark { display: inline-flex; align-items: center; flex: 0 0 auto; margin-left: auto; color: var(--grey); opacity: .5; background: none; border: 0; padding: 0; cursor: pointer; }
.app.deck header .book-mark:hover { opacity: 1; }
/* The same weight and tone either way — only the shape says which view you're in. */
/* With a join beside it, the book no longer takes the slack — the join does. */
.app.deck header .deck-join ~ .book-mark { margin-left: 0; }
.app.deck header .book-mark svg { display: block; overflow: visible; }

.app.deck .sbtn.write .pencil-close { display: none; }
.app.deck .sbtn.write.on .pencil { display: none; }
.app.deck .sbtn.write.on .pencil-close { display: block; }
.app.deck .sbtn.write.on { color: var(--ink); }

.app.deck .who-count { width: 20px; height: 20px; border-radius: 50%; border: 1px solid var(--line); background: none; color: var(--grey); font: inherit; font-size: 11px; line-height: 1; cursor: pointer; display: inline-flex; align-items: center; justify-content: center; padding: 0; }
.app.deck .who-count:hover, .app.deck .who-count[aria-expanded="true"] { color: var(--ink); border-color: var(--ink); }
.app.deck .who-list { position: absolute; right: 30px; top: 0; background: var(--bg); border: 1px solid var(--line); border-radius: 3px; padding: 8px 12px; font-size: 12px; color: var(--ink); white-space: nowrap; z-index: 6; }
.app.deck .who-list div { padding: 3px 0; }

/* Writing in place, folded away until asked for — the same as a chat. */
.app.deck .compose.folded { display: none; }
/* The compose row now lives inside the sheet, so it's caught by the general .compose
   rule above rather than needing its own direct-child styling. */

.app.deck .nav button, .app.deck .sbtn { height: 20px; align-items: center; justify-content: center; }

body.writing .app.deck .nav,
body.writing .app.deck .validate,
body.writing .app.deck .side .sbtn:not(.write) { display: none; }
body.writing .app.deck .side { bottom: 10px; }

/* Kept: the icon brightens and a small word sits beneath it, outside the fixed-height button. */
.app.deck .sbtn#keepBtn.has { color: var(--ink); }
.app.deck .kept-mark { font-size: 10px; color: var(--ink); line-height: 1; margin-top: -16px; }

.app.deck .who .src { background: none; border: 0; padding: 0; font: inherit; color: var(--ink); cursor: pointer; }
.app.deck .who .src:hover { text-decoration: line-through; text-decoration-color: var(--grey); }

/* A way in, for anyone reading the deck without an account. Gone once they have one. */
.app.deck header .deck-join { margin-left: auto; margin-right: 14px; flex: 0 0 auto; font-size: 12px; color: var(--grey); text-decoration: none; border-bottom: 1px solid var(--line); padding-bottom: 1px; }
.app.deck header .deck-join:hover { color: var(--ink); border-bottom-color: var(--ink); }

/* The channel name is how you follow it. Nothing marks it when followed — the name
   sits in the channel's own colour, and that's enough going on already. */
.app.deck header button.room { background: none; border: 0; padding: 0; font: inherit; text-align: left; cursor: pointer; }

/* The source's two options, shown where you tapped. */
.app.deck .who { position: relative; }
.app.deck .src-menu { position: absolute; left: 0; top: 100%; margin-top: 6px; z-index: 8; background: var(--bg); border: 1px solid var(--line); border-radius: 4px; display: flex; flex-direction: column; min-width: 148px; }
.app.deck .src-menu[hidden] { display: none; }
.app.deck .src-menu button { background: none; border: 0; padding: 10px 14px; font: inherit; font-size: 13px; color: var(--ink); text-align: left; cursor: pointer; }
.app.deck .src-menu button:first-child { border-bottom: 1px solid var(--soft); }
.app.deck .src-menu button:hover { background: var(--soft); }
.app.deck .who .src.followed::after { content: '  following'; font-size: 11px; color: var(--grey); }

/* The channel's menu hangs from its name, as the source's does. */
.app.deck header .room-wrap { position: relative; flex: 1; min-width: 0; display: inline-flex; }
.app.deck header .room-wrap .src-menu { position: absolute; left: 0; top: 100%; margin-top: 8px; }

/* A long press shouldn't start selecting text or raise the system menu. */
.app.deck .stage { -webkit-touch-callout: none; -webkit-user-select: none; user-select: none; }
.app.deck .stage input { -webkit-user-select: text; user-select: text; }
/* The link holds its own long-press, so the browser's own menu stays out of the way. */
.app.deck .link { -webkit-touch-callout: none; -webkit-user-select: none; user-select: none; }

/* The link's menu hangs beneath it. */
.app.deck .inner { position: relative; }
.app.deck .link-menu { position: absolute; left: 0; margin-top: 4px; }




/* Drawing a line through words on a title asks the graph about them. */
.app.deck .title .w { cursor: text; }
.app.deck .title .w.lit { background: var(--soft); box-shadow: 0 0 0 2px var(--soft); border-radius: 2px; }
.app.deck .title { touch-action: pan-y; }


/* While it runs, the card's own controls stand down. */
body.scanning .app.deck .nav,
body.scanning .app.deck .side,
body.scanning .app.deck .validate { opacity: .25; transition: opacity .2s ease; }
@media (prefers-reduced-motion: reduce) { .app.deck .scan-cell { transition: none; } }

/* While the deck runs, the ring stops being a pie and becomes a field of squares —
   at half weight, so it sits back with the other marks rather than shouting. */
.app.deck .scan-cell { transition: opacity .24s linear; opacity: .45; }
body.scanning .app.deck .ring { color: var(--ink); }



/* While the report's search box has the keyboard, the keyboard rises above the overlay
   and the list leaves room for it beneath. */
/* Lifted out of the sheet and pinned to the bottom of the screen while the report's
   search box has it. Not scoped to .app.deck — it is a child of body while lent. */
body.report-typing .keyboard { position: fixed; left: 0; right: 0; bottom: 0; z-index: 60; background: var(--bg); max-width: 480px; margin: 0 auto; padding-bottom: calc(10px + env(safe-area-inset-bottom, 0px)); border-top: 1px solid var(--soft); }
body.report-typing .report-inner { padding-bottom: 300px; }

/* A small count on the write button when a card already has replies — otherwise the
   only way to know was to open it and find out. */
.sbtn.write { position: relative; }
/* A lighter fill than the icons' own grey — blended toward the background, solid
   rather than faded, so it stays readable without reading as heavy or transparent. */
.comment-count { position: absolute; top: -4px; right: -4px; min-width: 15px; height: 15px; padding: 0 3px; border-radius: 8px; background: color-mix(in srgb, var(--grey) 55%, var(--bg) 45%); color: var(--bg); font-size: 10px; line-height: 15px; text-align: center; font-variant-numeric: tabular-nums; }

/* A quiet report link on each comment, out of the way unless you go looking. */
.comment { position: relative; }
.comment-report { position: absolute; top: 12px; right: 0; background: none; border: 0; font-size: 11px; color: var(--grey); opacity: .4; cursor: pointer; padding: 2px 4px; }
.comment-report:hover { opacity: 1; }

/* The header here is a real <header>, so it inherits the exact same padding as every
   other page's header — no guessed offset. The close button carries .book-mark, the
   real book icon's own class, so margin-left:auto puts it in the identical spot the
   book sat in before you tapped it — the same rule doing the work, not a copy of it. */
.book-over .book-inner { padding-top: 64px; }

/* The invitation at the end of the deck, set apart from the older-cards button above it. */
.end-join { margin-top: 30px; padding-top: 22px; border-top: 1px solid var(--soft); }
.end-join .rest { margin: 0 0 4px; font-size: 14px; line-height: 1.5; color: var(--grey); }
.end-join .btn { margin-top: 16px; }
.end-join .small { display: block; margin-top: 12px; color: var(--grey); }

/* The run button: ink while the deck is running, grey at rest like its neighbours. */
/* Share stays grey like its neighbours — it does something, it is not a state. Its
   shape packs more corners into the same 20px than the box beside it, so the stroke is
   eased a little to land at the same visual weight. */
.app.deck .sbtn.share, .app.deck .sbtn.share:hover { color: var(--grey); }
.app.deck .sbtn.share svg { stroke-width: .85; }
.app.deck .sbtn.share:active { color: var(--ink); }
