/* Charter's interface. A small vocabulary, used everywhere:
   walnut  the table and the ledge where a player's things sit
   vellum  documents: only things you read and sign are on it
   ink     text and rules
   gold    what you can do right now: one thing at a time
   wax     the constitution and the law: seals, stamps, refusals
   Type: one serif face at 12, 14, 16, 20, 28, 44; the title page alone has the --brand faces. Space: 4, 8, 12, 16, 24, 32.
   Corners are square. Banners, stamps and seals give the shapes. */
:root {
  --walnut-0: #150d07; --walnut-1: #1f140c; --walnut-2: #2c1d12; --walnut-3: #3c2919; --brass: #8f6f3a;
  --vellum: #efe4c8; --vellum-2: #e5d7b4; --vellum-3: #d3c295;
  --ink: #2a1f14; --ink-2: #5f4f3b; --ink-3: #85745b;
  --gold: #e8bb4d; --gold-2: #f6d27a; --gold-ink: #2b1d07;
  --wax: #8f1f17; --wax-2: #b23a2e; --wax-0: #7c1812;
  --pale: #e9dcc0; --pale-2: #b7a688;
  --serif: Palatino, "Palatino Linotype", "Book Antiqua", "Iowan Old Style", Georgia, serif;
  --mono: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  --brand-wordmark: "Grenze Gotisch", "Hoefler Text", Georgia, serif; /* the word Charter, and nothing else */
  --brand-text: "IM Fell English", "Hoefler Text", Palatino, Georgia, serif; /* the title page and document headings */
  --brand-sign: "Mrs Saint Delafield", "Snell Roundhand", "Segoe Script", var(--serif); /* a signature */
  --sign-ink: #1c2f6b;
  --act-hover: #4d3522; --act-hover-2: #443423; --field: #f8f1dd; --bright: #fff8e8; --err-ink: #fff3e8;
  --tool-off: #8a7a60; --need: #d9c8a4; --good: #1f6b3c; --stain: #785828;
  --roll-0: #6f5d3c; --roll-1: #8a7650; --roll-2: #a8956b; --roll-3: #b09c72; --roll-4: #b9a67c;
  --roll-5: #cdbc90; --roll-6: #d9c9a0; --roll-7: #e2d3ae; --roll-8: #f4ebd2;
  --ledge: 96px; --rail: 52px; --dock: 372px;
  --safe-t: env(safe-area-inset-top, 0px); --safe-r: env(safe-area-inset-right, 0px); --safe-b: env(safe-area-inset-bottom, 0px); --safe-l: env(safe-area-inset-left, 0px);
  --nav: 0px; --crown: 0px; --kb: 0px; --seen: 100dvh;
  --drop: color-mix(in srgb, var(--walnut-0) 60%, transparent);
  --s1: 4px; --s2: 8px; --s3: 12px; --s4: 16px; --s5: 24px; --s6: 32px;
  --paper: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='240' height='240'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.7' numOctaves='3'/%3E%3CfeColorMatrix values='0 0 0 0 .32 0 0 0 0 .22 0 0 0 0 .08 0 0 0 .10 0'/%3E%3C/filter%3E%3Crect width='240' height='240' filter='url(%23n)'/%3E%3C/svg%3E");
}
@font-face { font-family: "Grenze Gotisch"; font-weight: 700; font-display: swap; src: url(fonts/grenze-gotisch-700-charter.woff2) format("woff2"); }
@font-face { font-family: "IM Fell English"; font-display: swap; src: url(fonts/im-fell-english.woff2) format("woff2"); }
@font-face { font-family: "IM Fell English"; font-style: italic; font-display: swap; src: url(fonts/im-fell-english-italic.woff2) format("woff2"); }
/* The script is drawn very small for its size. Growing it here, not in the input's font size, means a
   letter it lacks falls back to a font at an ordinary size, so a name in any alphabet stays readable. */
@font-face { font-family: "Mrs Saint Delafield"; font-display: swap; size-adjust: 175%; src: url(fonts/mrs-saint-delafield.woff2) format("woff2"); }
* { box-sizing: border-box; }
html, body, #app { height: 100%; margin: 0; }
body { font: 14px/1.4 var(--serif); color: var(--pale); background: var(--walnut-0); overflow: hidden; overscroll-behavior: none; -webkit-text-size-adjust: 100%; text-size-adjust: 100%; -webkit-font-smoothing: antialiased; font-variant-numeric: lining-nums tabular-nums; }
button, input, textarea, select { font: inherit; color: inherit; }
button { cursor: pointer; background: none; border: 0; padding: 0; }
a { color: inherit; }
[hidden] { display: none !important; }
:focus-visible { outline: 2px solid var(--gold-2); outline-offset: 2px; }
.vellum :focus-visible { outline-color: var(--wax); }

/* ---------- the stage ---------- */
.stage { position: fixed; inset: 0; }
.stage canvas { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
.stage svg.board2d { position: absolute; inset: 48px calc(var(--rail) + var(--dockw, 0px)) var(--ledge) 0; width: calc(100% - var(--rail) - var(--dockw, 0px)); height: calc(100% - 48px - var(--ledge)); background: var(--walnut-1); }
.vignette { position: absolute; inset: 0; pointer-events: none; background: radial-gradient(ellipse 75% 75% at 50% 48%, transparent 60%, rgba(8, 4, 2, .55) 100%); }

/* A low quality tier leaves out what only costs. See TIERS in vendor/player.js. */
:root[data-tier="0"] .vignette, :root[data-tier="1"] .vignette { display: none; }

/* ---------- documents ---------- */
.vellum { background: var(--paper), var(--vellum); color: var(--ink); box-shadow: inset 0 0 40px color-mix(in srgb, var(--stain) 22%, transparent), 0 1px 0 var(--vellum-3), 0 10px 24px rgba(0,0,0,.45); }
.smallcaps { font-size: 12px; letter-spacing: .09em; text-transform: uppercase; color: var(--ink-2); }

/* ---------- controls ---------- */
.act { display: inline-flex; align-items: center; justify-content: center; gap: var(--s2); min-height: 40px; padding: 8px 18px; font-size: 16px; white-space: nowrap; color: var(--pale); background: var(--walnut-3); clip-path: polygon(6px 0, calc(100% - 6px) 0, 100% 6px, 100% calc(100% - 6px), calc(100% - 6px) 100%, 6px 100%, 0 calc(100% - 6px), 0 6px); transition: background .12s, transform .06s; }
@media (hover: hover) { .act:hover { background: var(--act-hover); } }
.act:active { transform: translateY(1px); }
.act:focus-visible { outline: none; box-shadow: inset 0 0 0 2px var(--gold-2); }
.vellum .act:focus-visible, .act.gold:focus-visible { outline: none; box-shadow: inset 0 0 0 2px var(--ink); }
.act:disabled { color: var(--pale-2); background: var(--walnut-2); cursor: default; }
.act.gold { background: var(--gold); color: var(--gold-ink); font-weight: 600; }
@media (hover: hover) { .act.gold:hover { background: var(--gold-2); } }
.act.gold:disabled { background: var(--vellum-3); color: var(--ink-2); font-weight: 400; }
.vellum .act { background: var(--ink); color: var(--vellum); }
@media (hover: hover) { .vellum .act:hover { background: var(--act-hover-2); } }
.vellum .act.gold { background: var(--gold); color: var(--gold-ink); }
@media (hover: hover) { .vellum .act.gold:hover { background: var(--gold-2); } }
.vellum .act:disabled { background: var(--vellum-3); color: var(--ink-2); }
.link { color: var(--ink-2); text-decoration: underline; text-underline-offset: 2px; font-size: 14px; }
@media (hover: hover) { .link:hover { color: var(--ink); } }
.input { width: 100%; padding: 8px 10px; font-size: 16px; color: var(--ink); background: var(--field); border: 1px solid var(--ink-3); border-radius: 0; }
.input:focus { outline: 2px solid var(--wax); outline-offset: 0; border-color: transparent; }
.input::placeholder { color: var(--ink-3); }

svg.res { width: 22px; height: 22px; display: inline-block; vertical-align: -5px; flex: none; }
svg.res.small { width: 16px; height: 16px; vertical-align: -3px; }
svg.ui { width: 22px; height: 22px; flex: none; }
svg.piece { width: 26px; height: 26px; flex: none; }
svg.shield { width: 16px; height: 19px; flex: none; vertical-align: -4px; clip-path: polygon(0 0, 100% 0, 100% 55%, 50% 100%, 0 55%); }

.cost { display: inline-flex; gap: var(--s2); align-items: center; font-variant-numeric: tabular-nums; }
.cost span { display: inline-flex; gap: 2px; align-items: center; }

/* ---------- banners of the houses ---------- */
.crown { position: fixed; top: 0; left: var(--s4); right: calc(var(--rail) + var(--dockw, 0px) + var(--s3)); display: flex; align-items: flex-start; gap: var(--s4); z-index: 11; pointer-events: none; }
.crown > * { pointer-events: auto; }
.heraldry { pointer-events: none; min-width: 0; flex: 1; }
.houses { position: relative; display: flex; gap: var(--s2); flex: none; }
.houses::before { content: ""; position: absolute; left: -8px; right: -8px; top: 0; height: 5px; background: var(--walnut-0); box-shadow: 0 1px 0 var(--brass); }
.banner { position: relative; width: 62px; text-align: center; cursor: default; }
.banner .cloth { position: relative; display: block; width: 62px; height: 74px; overflow: hidden; clip-path: polygon(0 0, 100% 0, 100% 100%, 50% 84%, 0 100%); transition: height .28s cubic-bezier(.2,.9,.3,1); }
.banner .cloth svg { position: absolute; inset: 0; width: 100%; height: 100%; opacity: .26; }
.banner .score { position: absolute; left: 0; right: 0; top: 12px; font-size: 28px; line-height: 1; color: var(--bright); text-shadow: 0 1px 2px rgba(0,0,0,.65); }
.banner .worn { position: absolute; left: 0; right: 0; top: 37px; display: grid; place-items: center; }
.banner .cloth .worn svg { position: static; width: 34px; height: 34px; opacity: 1; filter: drop-shadow(0 1px 1px #0009); }
.banner .name { display: block; margin-top: 2px; font-size: 12px; line-height: 1.15; color: var(--pale); text-shadow: 0 1px 2px #000; }
.banner.turn .cloth { height: 92px; }
.banner.won .cloth { height: 110px; }
.banner.you .name { color: var(--gold-2); }
.banner .quillmark { position: absolute; right: -2px; top: 52px; color: var(--gold-2); animation: scratch 1.1s ease-in-out infinite; filter: drop-shadow(0 1px 1px #000); }
.banner .quillmark svg { width: 18px; height: 18px; }
@keyframes scratch { 50% { transform: translate(-2px, 2px) rotate(-8deg); } }
.card-tip { position: absolute; top: calc(100% + 6px); left: 0; width: 200px; padding: var(--s3); text-align: left; z-index: 3; }
.banner .card-tip { visibility: hidden; opacity: 0; transition: opacity .1s; }
.banner:focus-within .card-tip, .banner.open .card-tip { visibility: visible; opacity: 1; }
@media (hover: hover) { .banner:hover .card-tip { visibility: visible; opacity: 1; } }
.card-tip .row { display: flex; flex-wrap: wrap; gap: var(--s2) var(--s3); margin-top: 6px; }

/* ---------- the herald: round and dice ---------- */
.herald { display: flex; align-items: stretch; pointer-events: none; }
.herald .tab { padding: 6px 14px 8px; background: var(--walnut-0); color: var(--pale-2); box-shadow: 0 1px 0 var(--brass); font-size: 14px; white-space: nowrap; }
.herald .die { margin-left: 2px; padding: 2px 12px 6px; background: var(--vellum); color: var(--ink); font-size: 28px; line-height: 1.1; min-width: 48px; text-align: center; box-shadow: 0 2px 0 var(--vellum-3); }
.herald .clock { align-self: flex-start; padding: 6px 10px 8px; color: var(--pale-2); font-size: 14px; text-shadow: 0 1px 3px #000; }
.herald .clock.soon { color: var(--gold-2); }
.caption { margin-top: var(--s1); max-width: 560px; font-size: 16px; line-height: 1.25; color: var(--bright); text-shadow: 0 1px 3px #000, 0 0 12px #000; pointer-events: none; opacity: 0; transition: opacity .25s; }
.caption.on { opacity: 1; }

/* ---------- what seats have declared ---------- */
.declared { position: fixed; left: var(--s3); bottom: calc(var(--ledge) + var(--s3)); max-width: 280px; padding: var(--s2) var(--s3); font-size: 14px; z-index: 9; }
.declared[hidden] { display: none; }
.declared .lbl { font-size: 12px; color: var(--ink-3); margin-bottom: 2px; }
.declared .line { display: flex; flex-wrap: wrap; gap: var(--s1) var(--s2); align-items: center; }
.declared .line.none { color: var(--ink-3); }
.declared .line b { font-weight: 600; }
.declared .chg { display: inline-flex; gap: 3px; align-items: center; }
.declaresheet .drow { display: grid; grid-template-columns: 24px 1fr 76px auto; align-items: center; gap: var(--s2); padding: var(--s1) 0; }
.declaresheet .drow svg.res { width: 22px; height: 22px; }
.declaresheet .drow input { width: 100%; padding: 4px 6px; font: inherit; font-variant-numeric: tabular-nums; background: var(--vellum); color: var(--ink); border: 1px solid var(--ink-3); }

/* ---------- the ledge: your hand and your actions ---------- */
.ledge { position: fixed; left: 0; right: 0; bottom: 0; height: var(--ledge); display: flex; align-items: center; gap: var(--s4); padding: 0 calc(var(--rail) + var(--s3)) 0 var(--s4); background: linear-gradient(var(--walnut-2), var(--walnut-1) 12px); box-shadow: 0 -1px 0 var(--brass); z-index: 10; }
/* It has become your turn: a line of gold runs out along the edge of the ledge, and is gone. */
.ledge::before { content: ""; position: absolute; left: 0; right: 0; top: -1px; height: 2px; background: var(--gold); transform: scaleX(0); pointer-events: none; }
/* The hand is a slight fan of stacks. A stack's edges show how many cards it holds, up to four; the number is exact. */
.hand { display: flex; gap: var(--s2); padding-right: var(--s1); }
.rcard { position: relative; flex: none; width: 50px; height: 72px; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px; background: var(--paper), var(--vellum); color: var(--ink); font-size: 20px; line-height: 1; rotate: calc(var(--fan) * .7deg); translate: 0 var(--dip); transform-origin: 50% 100%; box-shadow: var(--edges, 0 0 0 transparent), 0 3px 5px var(--drop); transition: translate .16s cubic-bezier(.2,.9,.3,1.2), rotate .16s; }
.rcard::before { content: ""; position: absolute; inset: 3px; border: 1px solid var(--vellum-3); pointer-events: none; }
.rcard[data-depth="2"] { --edges: 2px -2px 0 -1px var(--vellum-2), 2px -2px 0 0 var(--ink-3); }
.rcard[data-depth="3"] { --edges: 2px -2px 0 -1px var(--vellum-2), 2px -2px 0 0 var(--ink-3), 4px -4px 0 -1px var(--vellum-2), 4px -4px 0 0 var(--ink-3); }
.rcard[data-depth="4"] { --edges: 2px -2px 0 -1px var(--vellum-2), 2px -2px 0 0 var(--ink-3), 4px -4px 0 -1px var(--vellum-2), 4px -4px 0 0 var(--ink-3), 6px -6px 0 -1px var(--vellum-2), 6px -6px 0 0 var(--ink-3); }
.rcard svg.res { position: relative; width: 28px; height: 28px; }
.rcard b { position: relative; font-weight: 600; }
@media (hover: hover) { .rcard:hover { translate: 0 -8px; rotate: 0deg; } }
/* The cards a piece would take rise out of the hand, with the amount on them. */
.rcard.pays { translate: 0 -12px; rotate: 0deg; }
.rcard.pays::after { content: attr(data-pay); position: absolute; top: -8px; left: -6px; padding: 0 5px; font-size: 14px; font-weight: 600; background: var(--ink); color: var(--vellum); }
/* An empty place: you can see what you have none of. */
.rcard.none { background: none; box-shadow: inset 0 0 0 1px var(--walnut-3); }
.rcard.none::before { content: none; }
.rcard.none svg { opacity: .32; filter: grayscale(.6); }
.rcard.none b { display: none; }
.delta { position: fixed; z-index: 31; padding: 0 5px; font-size: 14px; font-weight: 600; background: var(--ink); color: var(--vellum); pointer-events: none; translate: -50% -70%; box-shadow: 0 2px 4px var(--drop); }
.delta.up { background: var(--vellum); color: var(--ink); }
.hand.many { display: grid; grid-template-rows: 1fr 1fr; grid-auto-flow: column; grid-auto-columns: 44px; flex: none; gap: var(--s1); }
.hand.many .rcard { width: 44px; height: 32px; flex-direction: row; font-size: 14px; rotate: 0deg; translate: 0 0; --edges: 0 0 0 transparent; }
.hand.many .rcard.none { box-shadow: inset 0 0 0 1px var(--walnut-3); }
.hand.many .rcard:hover, .hand.many .rcard.pays { translate: 0 -2px; }
.hand.many .rcard.pays::after { top: -6px; left: -4px; padding: 0 3px; font-size: 12px; z-index: 1; }
.hand.many .rcard svg.res { width: 16px; height: 16px; }
.tray { display: flex; gap: var(--s1); flex: 1; min-width: 0; }
.tool { position: relative; width: 66px; height: 72px; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px; font-size: 12px; line-height: 1.1; color: var(--pale); background: var(--walnut-2); box-shadow: inset 0 1px 0 var(--walnut-3), 0 3px 0 var(--walnut-0); transition: background .12s, color .12s, translate .1s cubic-bezier(.2,.9,.3,1.2); }
@media (hover: hover) { .tool:not(:disabled):hover { background: var(--walnut-3); translate: 0 -3px; } }
.tool:not(:disabled):active { translate: 0 2px; box-shadow: inset 0 1px 0 var(--walnut-3), 0 1px 0 var(--walnut-0); transition-duration: .04s; }
.tool.selected { background: var(--gold); color: var(--gold-ink); translate: 0 -4px; box-shadow: inset 0 1px 0 var(--gold-2), 0 3px 0 var(--walnut-0), 0 6px 8px var(--drop); }
@media (hover: hover) { .tool.selected:not(:disabled):hover { background: var(--gold); color: var(--gold-ink); translate: 0 -4px; box-shadow: inset 0 1px 0 var(--gold-2), 0 3px 0 var(--walnut-0), 0 6px 8px var(--drop); } }
.tool:disabled { color: var(--tool-off); background: transparent; box-shadow: inset 0 0 0 1px var(--walnut-2); cursor: default; }
.tool .nm { max-width: 62px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tool svg.piece { width: 22px; height: 22px; }
/* What a piece still needs: a number and a bare mark for each good, in up to two rows. A hairline of pale keeps a dark mark readable on the wood. */
.tool .need { display: flex; flex-wrap: wrap; justify-content: center; gap: 0 var(--s1); font-size: 14px; line-height: 1; color: var(--need); align-items: center; }
.tool .need span { display: inline-flex; align-items: center; gap: 1px; }
.tool .need svg.res { width: 15px; height: 15px; vertical-align: 0; filter: drop-shadow(0 0 .6px var(--pale)); }
.tool.sep { margin-left: var(--s3); }
.tray.many { overflow-x: auto; scrollbar-width: none; padding: var(--s2) 0 var(--s1); margin: calc(-1 * var(--s2)) 0 calc(-1 * var(--s1)); }
.tray.many .tool { flex: none; width: 60px; }
.tray.many .tool.sep { margin-left: var(--s1); }
.tray.many .tool .need { gap: 0 2px; font-size: 12px; }
.tray.many .tool .need svg.res { width: 13px; height: 13px; }
.endturn { flex: none; width: 136px; min-height: 64px; font-size: 20px; transition: background .12s, color .12s, translate .1s cubic-bezier(.2,.9,.3,1.2); }
@media (hover: hover) { .endturn:hover:not(:disabled) { translate: 0 -2px; } }
.endturn kbd { font: 12px var(--mono); opacity: .55; margin-left: 2px; }
.prompt { position: fixed; left: 50%; bottom: calc(var(--ledge) + var(--s2)); transform: translateX(-50%); max-width: min(620px, 60vw); padding: 6px 16px; font-size: 16px; text-align: center; color: var(--gold-ink); background: var(--gold); clip-path: polygon(8px 0, calc(100% - 8px) 0, 100% 50%, calc(100% - 8px) 100%, 8px 100%, 0 50%); z-index: 9; pointer-events: none; white-space: nowrap; }
.prompt.quiet { color: var(--pale); background: var(--walnut-0); }
.prompt.err { color: var(--err-ink); background: var(--wax); white-space: normal; clip-path: none; pointer-events: auto; }
.prompt.dock-open, .pennant.dock-open { left: calc(50% - var(--dockw, 0px) / 2 - var(--rail) / 2); }
/* It has become your turn, and no line of instruction is showing. */
.pennant { position: fixed; left: 50%; bottom: calc(var(--ledge) + var(--s3)); translate: -50% 0; padding: 6px 28px; font-size: 20px; color: var(--gold-ink); background: var(--gold); clip-path: polygon(10px 0, calc(100% - 10px) 0, 100% 50%, calc(100% - 10px) 100%, 10px 100%, 0 50%); z-index: 9; pointer-events: none; white-space: nowrap; }

/* ---------- slips: offers and picks on the table ---------- */
.slips { position: fixed; top: 128px; left: var(--s4); display: grid; gap: var(--s2); width: 238px; z-index: 9; }
.slip { padding: var(--s2) var(--s3); font-size: 14px; }
.slip .terms { display: flex; flex-wrap: wrap; align-items: center; gap: 2px var(--s3); margin: 2px 0 var(--s2); }
.slip .forline { display: inline-flex; align-items: center; gap: var(--s2); }
.slip .fine { margin-bottom: var(--s1); color: var(--ink-2); }
.slip .row { display: flex; gap: var(--s2); }
.slip .act { min-height: 30px; padding: 2px 12px; font-size: 14px; }
.pickmenu { position: fixed; padding: var(--s2); display: grid; gap: var(--s1); z-index: 15; }
.pickmenu .act { justify-content: flex-start; min-height: 32px; font-size: 14px; }
.tip { position: fixed; max-width: 280px; padding: var(--s2) var(--s3); font-size: 14px; pointer-events: none; z-index: 20; }
.tip h4 { margin: 0; font-size: 16px; font-weight: 600; }
.tip .row { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s2); margin-top: 4px; }
.tip .pips { color: var(--ink-3); letter-spacing: 1px; font-size: 12px; }

/* ---------- the rail: the things one click away ---------- */
.rail { position: fixed; top: 0; right: 0; bottom: 0; width: var(--rail); display: flex; flex-direction: column; gap: 2px; padding-top: var(--s2); background: var(--walnut-0); box-shadow: -1px 0 0 var(--brass); z-index: 13; }
.rail button { position: relative; width: var(--rail); height: 48px; display: grid; place-items: center; color: var(--pale-2); transition: color .12s, background .12s; }
@media (hover: hover) { .rail button:hover { color: var(--pale); background: var(--walnut-2); } }
.rail button:active svg { scale: .88; }
.rail button.on { color: var(--gold-ink); background: var(--gold); }
.rail button .count { position: absolute; right: 7px; top: 5px; font-size: 12px; line-height: 1; }
.rail button.attention { color: var(--gold-2); background: var(--walnut-3); }
.rail .spacer { flex: 1; }
.rail:empty, .houses:empty { display: none; }

/* ---------- the dock: one document at a time ---------- */
.dock { position: fixed; top: var(--s3); right: calc(var(--rail) + var(--s3)); max-height: calc(100vh - var(--ledge) - var(--s3) - var(--s3)); width: calc(var(--dock) - var(--s3) - var(--s3)); display: flex; flex-direction: column; z-index: 12; transform: translateX(calc(100% + var(--rail) + var(--s4))); transition: transform .24s cubic-bezier(.2,.9,.3,1), visibility 0s .24s; visibility: hidden; }
.dock.open { transform: none; visibility: visible; transition: transform .24s cubic-bezier(.2,.9,.3,1); }
.dock .grab { display: none; }
.dock .sheet { flex: 1; min-height: 0; overflow-y: auto; padding: var(--s4) var(--s4) var(--s4); scrollbar-width: thin; scrollbar-color: var(--vellum-3) transparent; }
.dock .x { position: absolute; top: var(--s2); right: var(--s2); width: 32px; height: 32px; display: grid; place-items: center; color: var(--ink-3); z-index: 2; }
@media (hover: hover) { .dock .x:hover { color: var(--ink); } }
.dock h2 { margin: 0 0 var(--s3); font-size: 20px; font-weight: 400; }

/* the charter: the same document from draft to monument */
.statement { margin: var(--s2) 0 var(--s3); font-size: 20px; line-height: 1.3; }
.statement .line { display: block; }
.statement .line + .line { margin-top: var(--s1, 4px); }
.english { white-space: pre-line; }
.titleline { color: var(--ink-2); font-size: 14px; font-style: italic; }
.diff { margin: 0 0 var(--s3); padding-left: var(--s3); border-left: 2px solid var(--wax); font-size: 14px; color: var(--ink); }
.diffby { color: var(--ink-2); }
.byline { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: 2px var(--s2); margin-bottom: 2px; font-size: 12px; letter-spacing: .04em; color: var(--ink-3); }
.notasked { padding: 1px 6px; border: 1px solid var(--wax); color: var(--wax); letter-spacing: 0; white-space: nowrap; }
/* Room for about 40 words, kept while they are being written, so that nothing below them moves. */
.described { margin: var(--s2) 0 var(--s3); }
.described.held { min-height: calc(18px + 4 * 1.32 * 17px); }
.lawrow .described.held, .momentdoc .described.held { min-height: 0; }
.described .saying { margin: 0; font-size: 17px; line-height: 1.32; }
.described .nowords { margin: 0; font-size: 14px; color: var(--ink-2); }
.described .ghost { display: grid; gap: calc(1.32 * 17px - 9px); padding-top: 7px; }
.described .ghost i { display: block; height: 9px; background: var(--vellum-3); opacity: .55; }
.described .ghost i:nth-child(1) { width: 92%; }
.described .ghost i:nth-child(2) { width: 84%; }
.described .ghost i:nth-child(3) { width: 58%; }
@media (prefers-reduced-motion: no-preference) { .described .ghost i { animation: ghost 1.6s ease-in-out infinite; } }
@keyframes ghost { 50% { opacity: .25; } }
.source { margin: var(--s3) 0; }
.source .sexp { margin-top: 0; }
.srcline { display: block; }
.advice { margin: 0 0 var(--s3); padding: var(--s2) var(--s3); background: color-mix(in srgb, var(--stain) 12%, transparent); font-size: 14px; line-height: 1.4; color: var(--ink-2); }
.advice p { margin: 0; font-style: italic; }
.advicehead { margin-bottom: 2px; font-size: 12px; letter-spacing: .04em; color: var(--ink-3); }
.conseq { margin: 0 0 var(--s3); border-top: 1px solid var(--vellum-3); }
.conseq .case { display: grid; grid-template-columns: 1fr; gap: 2px; padding: var(--s2) 0; border-bottom: 1px solid var(--vellum-3); }
.conseq .when { font-size: 12px; letter-spacing: .04em; color: var(--ink-2); }
.conseq .who { display: flex; flex-wrap: wrap; align-items: center; gap: 4px var(--s2); }
.conseq .who b { font-weight: 600; min-width: 62px; }
.conseq .chg { display: inline-flex; align-items: center; gap: 2px; font-variant-numeric: tabular-nums; }
.conseq .chg.up { color: var(--good); } .conseq .chg.down { color: var(--wax); }
.conseq .note { padding: var(--s2) 0; font-size: 14px; color: var(--ink-2); border-bottom: 1px solid var(--vellum-3); }
.conseq .note.win { color: var(--wax); font-weight: 600; }
.note-line { font-size: 14px; color: var(--ink-2); margin: 0 0 var(--s3); }
details.formal { margin: var(--s2) 0; }
details.formal summary { cursor: pointer; color: var(--ink-2); font-size: 14px; list-style: none; }
details.formal summary::before { content: "+ "; }
details.formal[open] summary::before { content: "− "; }
@media (hover: hover) { details.formal summary:hover { color: var(--ink); } }
.sexp { margin: var(--s2) 0 0; padding: var(--s2) var(--s3); font: 12px/1.5 var(--mono); color: var(--ink); background: color-mix(in srgb, var(--stain) 12%, transparent); white-space: pre-wrap; word-break: break-word; user-select: text; }

/* drafting */
.words { width: 100%; min-height: 84px; padding: var(--s3); font: 16px/1.35 var(--serif); color: var(--ink); background: var(--field); border: 1px solid var(--ink-3); resize: none; overflow: hidden; }
.words:focus { outline: 2px solid var(--wax); outline-offset: 0; border-color: transparent; }
.words::placeholder { color: var(--ink-3); font-style: italic; }
.draftbar { display: flex; align-items: center; gap: var(--s3); margin: var(--s2) 0 var(--s3); min-height: 40px; }
.draftbar .grow { flex: 1; }
.samples { display: flex; flex-wrap: wrap; gap: 2px var(--s3); margin-bottom: var(--s3); }
.status { display: flex; align-items: baseline; gap: var(--s2); font-size: 14px; color: var(--ink-2); min-height: 20px; }
.status .elapsed { margin-left: auto; font-variant-numeric: tabular-nums; color: var(--ink-3); }
.status.stalled { color: var(--wax); }
.status .tick { width: 7px; height: 7px; flex: none; background: var(--wax); align-self: center; }
.status .tick.beat { animation: beat .35s ease-out; }
@keyframes beat { from { transform: scale(1.9); } }
.retryline { margin: var(--s2) 0; font-size: 14px; color: var(--wax); }
.thought { margin: var(--s2) 0 0; font-size: 14px; font-style: italic; color: var(--ink-3); max-height: 3.9em; overflow: hidden; }
.clerk { margin: var(--s3) 0 0; padding: var(--s3) 0; border-top: 1px solid var(--vellum-3); font: 14px/1.5 var(--serif); font-style: italic; color: var(--ink); white-space: pre-wrap; word-break: break-word; min-height: 3em; }
.clerk .nib { display: inline-block; width: 2px; height: 1em; margin-left: 2px; vertical-align: -2px; background: var(--ink); }
.refusal { position: relative; margin: var(--s3) 0; padding: var(--s3) 0 var(--s4); }
.refusal .stampword { display: inline-block; padding: 2px 10px; margin-bottom: var(--s2); font-size: 20px; letter-spacing: .12em; color: var(--wax); border: 2px solid var(--wax); transform: rotate(-3deg); }
.refusal .stampword.fresh { animation: stampIn .28s cubic-bezier(.2,.9,.3,1.2); }
.refusal p { margin: 0; font-size: 16px; line-height: 1.35; }
.refusal.strike { padding-bottom: 0; }
.strikesamples { margin-top: var(--s3); font-size: 14px; color: var(--ink-2); }
.strikesamples .samples { margin: var(--s1) 0 0; }
.refusal.strike .formal { margin-top: var(--s3); }
.formalnote, .refusal .formalnote { margin: var(--s2) 0 0; font-size: 14px; color: var(--ink-2); }
.fail { margin: var(--s3) 0; font-size: 16px; }
.proposebar { position: sticky; bottom: calc(-1 * var(--s4)); margin: var(--s3) calc(-1 * var(--s4)) calc(-1 * var(--s4)); padding: var(--s3) var(--s4); background: var(--paper), var(--vellum-2); display: flex; align-items: center; gap: var(--s3); box-shadow: 0 -1px 0 var(--vellum-3); }
.proposebar .act { flex: 1; }
.proposebar svg.res { width: 20px; height: 20px; }
.dim { opacity: .45; }

/* the vote */
.signatures { margin: var(--s3) 0; display: grid; gap: 0; padding-right: 0; }
.momentdoc { min-height: 300px; position: relative; padding-bottom: 72px; }
.sigline { position: relative; display: flex; align-items: center; gap: var(--s2); height: 34px; border-bottom: 1px solid var(--ink-3); }
.sigline .nm { font-size: 14px; }
.stamp { margin-left: auto; padding: 0 8px; font-size: 14px; font-weight: 600; letter-spacing: .1em; border: 2px solid currentColor; transform: rotate(-4deg); }
.stamp.yes { color: var(--good); } .stamp.no { color: var(--wax); }
.stamp.fresh { animation: stampIn .28s cubic-bezier(.2,.9,.3,1.2) backwards; }
@keyframes stampIn { from { transform: scale(2.2) rotate(-14deg); opacity: 0; } 70% { transform: scale(.94) rotate(-3deg); opacity: 1; } }
.tally { display: flex; align-items: center; justify-content: space-between; margin: var(--s2) 0; font-size: 14px; color: var(--ink-2); min-height: 22px; }
.votebar { display: flex; gap: var(--s2); margin-top: var(--s2); }
.votebar .act { flex: 1; }
.sealmark { position: absolute; right: 0; bottom: 0; width: 96px; height: 96px; pointer-events: none; }
svg.wax { width: 96px; height: 96px; filter: drop-shadow(0 3px 2px rgba(0,0,0,.35)); }
/* The seal falls, meets the page at SEAL_FALL_MS in app.js, and a ring of wax spreads under it. */
.sealmark.fresh svg.wax { animation: sealDrop .36s cubic-bezier(.5,0,.8,.6) both, sealPress .2s ease-out .24s; }
@keyframes sealDrop { from { transform: scale(2.6) rotate(-24deg); opacity: 0; } 66%, to { transform: none; opacity: 1; } }
@keyframes sealPress { 40% { scale: 1.06 .96; } }
.sealmark.fresh::before { content: ""; position: absolute; inset: 8px; border-radius: 50%; border: 3px solid var(--wax-2); animation: waxRing .55s ease-out .24s both; }
@keyframes waxRing { from { transform: scale(.7); opacity: .9; } to { transform: scale(1.5); opacity: 0; } }
.outcome { margin-top: var(--s2); font-size: 20px; letter-spacing: .08em; }
.outcome.passed { color: var(--wax); }
.outcome.failed { color: var(--ink-3); }
.outcome.fresh { animation: outcomeIn .26s cubic-bezier(.2,.9,.3,1.2) .12s both; }
@keyframes outcomeIn { from { scale: 1.25; opacity: 0; } }
.outcome.failed.fresh { animation-name: outcomeSlump; }
@keyframes outcomeSlump { from { translate: 0 -8px; opacity: 0; } }
.flying { position: fixed; z-index: 40; pointer-events: none; overflow: hidden; }
.ripple { position: fixed; width: 12px; height: 12px; margin: -6px 0 0 -6px; border: 2px solid var(--pale); border-radius: 50%; z-index: 30; pointer-events: none; animation: ripple .9s ease-out forwards; }
.ripple.law { border-color: var(--wax-2); }
@keyframes ripple { to { transform: scale(13); opacity: 0; } }
.ripple.small { animation: rippleSmall .7s ease-out forwards; }
@keyframes rippleSmall { to { transform: scale(6); opacity: 0; } }
.flight { position: fixed; z-index: 30; display: flex; align-items: center; justify-content: center; gap: 2px; font-size: 14px; font-weight: 600; background: var(--paper), var(--vellum); color: var(--ink); pointer-events: none; box-shadow: 0 3px 5px var(--drop); }
.flight.chip { padding: 1px 5px 1px 2px; }
.flight.card { width: 32px; height: 46px; }
.flight.card svg.res { width: 22px; height: 22px; }
.flight.wornflight { width: 72px; height: 72px; background: none; box-shadow: none; }
.flight.wornflight svg { width: 72px; height: 72px; filter: drop-shadow(0 6px 6px #000a); }
.shard.dust { background: var(--pale); border-radius: 50%; box-shadow: none; }
.shard { position: fixed; width: 9px; height: 9px; margin: -4px 0 0 -4px; background: var(--gold-2); border-radius: 2px; z-index: 30; pointer-events: none; box-shadow: 0 0 6px var(--gold); }
.lawfire { position: fixed; width: 56px; height: 56px; margin: -28px 0 0 -28px; z-index: 30; pointer-events: none; }
.lawfire svg { display: block; width: 100%; height: 100%; }

/* in force, chronicle */
.lawrow { padding: var(--s3) 0; border-bottom: 1px solid var(--vellum-3); }
.lawrow.flash { animation: flash 1.2s ease-out; }
@keyframes flash { 0% { background: var(--gold-2); } 100% { background: transparent; } }
.lawrow summary { cursor: pointer; list-style: none; }
.lawrow summary::-webkit-details-marker { display: none; }
@media (hover: hover) { .lawrow summary:hover p { color: #000; } }
.lawrow .head { display: flex; align-items: baseline; justify-content: space-between; gap: var(--s2); }
.lawrow .num { font-size: 12px; color: var(--ink-3); white-space: nowrap; }
.lawrow .ttl { font-size: 14px; font-style: italic; color: var(--ink-2); }
.lawrow p { margin: 2px 0 0; font-size: 16px; line-height: 1.3; white-space: pre-line; }
.lawrow .meta { margin-top: 4px; font-size: 12px; color: var(--ink-3); }
/* A founding law's title is its author's plain name for it. Its exact statement is the small print. */
.lawrow.founding .ttl { font-size: 16px; font-style: normal; color: var(--ink); }
.lawrow.founding p { font-size: 14px; color: var(--ink-2); }
.empty { color: var(--ink-3); font-style: italic; }
.chron h3 { margin: var(--s4) 0 var(--s1); font-size: 12px; font-weight: 400; letter-spacing: .09em; text-transform: uppercase; color: var(--ink-3); }
.chron h3:first-child { margin-top: 0; }
.chron p { margin: 0 0 var(--s1); font-size: 14px; line-height: 1.35; }
.chron p.minor { color: var(--ink-3); font-size: 12px; }
.chron p.law { font-weight: 600; }
.chron svg.shield { width: 12px; height: 14px; margin-right: 4px; vertical-align: -2px; }
.toggleline { display: block; margin-bottom: var(--s3); }

/* ---------- table talk ---------- */
.talklines p { margin: 0 0 var(--s2); font-size: 14px; line-height: 1.35; }
.talklines svg.shield { width: 12px; height: 14px; margin-right: 4px; vertical-align: -2px; }
.talklines p.aside { color: var(--ink-2); font-style: italic; }
.talklines p.inner { color: var(--ink-3); font-size: 12px; padding-left: var(--s3); border-left: 1px solid var(--vellum-3); }
.talklines p.inner .smallcaps { font-size: 12px; margin-right: 4px; }
.talkinput { position: sticky; bottom: calc(0px - var(--s4)); display: flex; gap: var(--s1); padding: var(--s2) 0; background: var(--vellum); }
.talkinput .input { flex: 1; min-width: 0; }

/* ---------- watching a game from its log ---------- */
.replaybar { position: fixed; left: 0; right: var(--rail); bottom: 0; height: 56px; display: flex; align-items: center; gap: var(--s2); padding: 0 var(--s4); background: var(--walnut-1); box-shadow: 0 -1px 0 var(--brass); color: var(--pale); z-index: 20; }
.replaybar .scrub { flex: 1; min-width: 60px; accent-color: var(--gold); }
.replaybar .fine { color: var(--pale-2); white-space: nowrap; }

/* the trade document */
.tradesheet h3 { margin: 0 0 var(--s2); font-size: 12px; font-weight: 400; letter-spacing: .09em; text-transform: uppercase; color: var(--ink-2); }
.bankrow { display: flex; align-items: center; gap: var(--s2); padding: 4px 0; border-bottom: 1px solid var(--vellum-3); }
.bankrow .pay { min-width: 62px; display: inline-flex; align-items: center; gap: 2px; }
.bankrow .arrow { color: var(--ink-3); }
.bankrow button { width: 30px; height: 30px; display: grid; place-items: center; background: var(--field); box-shadow: inset 0 0 0 1px var(--vellum-3); }
@media (hover: hover) { .bankrow button:hover { background: var(--gold-2); } }
.offerform { margin-top: var(--s4); display: grid; gap: var(--s2); }
.pickrow { display: grid; grid-template-columns: 36px 1fr; gap: var(--s1); }
.pickrow .lbl { padding-top: 9px; font-size: 14px; color: var(--ink-2); }
.tiles { display: flex; flex-wrap: wrap; gap: var(--s1) 6px; }
.tile { width: 40px; display: grid; }
.tile .add { position: relative; height: 40px; display: grid; place-items: center; background: var(--field); box-shadow: inset 0 0 0 1px var(--vellum-3); }
@media (hover: hover) { .tile .add:hover { background: var(--gold-2); } }
.tile.in .add { background: var(--gold); box-shadow: inset 0 0 0 2px var(--ink); }
.tile.off:not(.in) .add svg { opacity: .32; }
.tile .n { position: absolute; top: -6px; right: -6px; min-width: 19px; height: 19px; padding: 0 3px; background: var(--ink); color: var(--vellum); font-size: 13px; line-height: 19px; text-align: center; font-variant-numeric: tabular-nums; }
.tile .left { position: absolute; right: 3px; bottom: 1px; font-size: 11px; line-height: 1; color: var(--ink-2); font-variant-numeric: tabular-nums; }
.tile.in .left { color: var(--gold-ink); }
.tile .less { height: 22px; margin-top: 2px; color: var(--ink); font-size: 18px; font-weight: 600; line-height: 1; background: var(--field); box-shadow: inset 0 0 0 1px var(--vellum-3); }
/* Hidden, and still taking its room: on a phone the sheet grows upward, so a new row would pull the tile off the finger. */
.tile .less:disabled { visibility: hidden; }
@media (hover: hover) { .tile .less:hover { background: var(--vellum-3); } }
.offernote { min-height: 20px; font-size: 14px; line-height: 20px; color: var(--ink-2); }
.offernote.stop { color: var(--wax); }
.selectline { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s2); }
.selectline select { flex: 1; padding: 5px 6px; background: var(--field); border: 1px solid var(--ink-3); color: var(--ink); }
.selectline .num { width: 48px; padding: 4px 6px; background: var(--field); border: 1px solid var(--ink-3); text-align: center; }

/* the table menu */
.menu { position: fixed; right: calc(var(--rail) + var(--s2)); bottom: var(--s3); width: 260px; padding: var(--s4); z-index: 14; display: grid; gap: var(--s2); }
/* The sound switches. An icon alone in the corner of the title page and the gathering, with words in the table's menu. */
.soundswitches { display: flex; gap: 2px; }
.soundswitch { position: relative; display: inline-flex; align-items: center; gap: var(--s2); min-width: 40px; height: 40px; padding: 0 var(--s2); justify-content: center; border-radius: 3px; color: inherit; transition: color .12s, background .12s, opacity .12s; }
.soundswitch svg { flex: none; width: 22px; height: 22px; }
.soundswitch.off { opacity: .55; }
.soundswitch.off::after { content: ""; position: absolute; left: 9px; top: 19px; width: 24px; height: 2px; background: currentColor; transform: rotate(-45deg); }
.soundcorner { position: fixed; top: calc(var(--s2) + env(safe-area-inset-top, 0px)); right: calc(var(--s2) + env(safe-area-inset-right, 0px)); z-index: 6; color: var(--pale); background: var(--drop); border-radius: 4px; }
.soundcorner[hidden] { display: none; }
@media (hover: hover) { .soundcorner .soundswitch:hover { background: var(--walnut-3); } .menu .soundswitch:hover { background: var(--vellum-2); } }
.menu .soundswitches { display: grid; gap: 0; margin: 0 calc(var(--s2) * -1); }
.menu .soundswitch { justify-content: flex-start; color: var(--ink-2); font-size: 15px; }
.menu .soundswitch .fine { margin-left: auto; font: 12px var(--mono); word-break: normal; }
.menu .soundswitch.off::after { left: 8px; }
.menu .code { font: 20px var(--mono); letter-spacing: .1em; }
.menu .fine { font: 12px/1.4 var(--mono); word-break: break-all; color: var(--ink-3); }

/* ---------- the scroll: the title page and the gathering ---------- */
.scroll { position: fixed; left: max(var(--s5), 7vw); top: 50%; transform: translateY(-50%); width: 400px; max-width: calc(100vw - 48px); max-height: calc(100dvh - 72px); display: flex; flex-direction: column; z-index: 5; }
.titlepage { position: relative; flex: 0 1 auto; min-height: 0; overflow-y: auto; padding: var(--s6) 28px 34px; scrollbar-width: thin; scrollbar-color: var(--vellum-3) transparent; }
.scroll::before { content: ""; position: absolute; z-index: 1; left: -3px; right: -3px; top: -5px; height: 11px; border-radius: 3px; background: linear-gradient(var(--roll-2), var(--vellum) 45%, var(--roll-4)); box-shadow: 0 2px 3px rgba(60, 40, 15, .35); pointer-events: none; }
/* The roller is as tall as the sheet, with the roll at its foot, so moving it by its own height travels exactly the sheet. */
.roller { position: absolute; z-index: 2; inset: 0 -10px; pointer-events: none; }
.roll { position: absolute; left: 0; right: 0; top: calc(100% - 12px); height: 24px; border-radius: 4px / 12px; background: var(--paper), linear-gradient(var(--roll-1), var(--roll-6) 18%, var(--roll-8) 40%, var(--roll-7) 62%, var(--roll-3) 84%, var(--roll-0)); box-shadow: 0 7px 12px rgba(0, 0, 0, .5); }
.roll::before, .roll::after { content: ""; position: absolute; top: 0; bottom: 0; width: 9px; border-radius: 50%; background: radial-gradient(ellipse at center, var(--roll-0) 0 22%, var(--roll-5) 24% 44%, var(--roll-1) 46% 56%, var(--roll-6) 58%); }
.roll::before { left: 0; } .roll::after { right: 0; }
svg.seal { position: absolute; left: 50%; top: 100%; width: 52px; height: 52px; margin: -26px 0 0 -26px; filter: drop-shadow(0 2px 2px rgba(0, 0, 0, .45)); }

/* The first visit. The fall follows dropCurve in vendor/player.js: a fall, then one small hop.
   While .waiting holds it, the scroll waits above the window for the board to start. */
.scroll.opening .titlepage { animation: sheetOpen var(--unroll) cubic-bezier(.45, .05, .25, 1) var(--unroll-at) both; }
.scroll.opening .roller { animation: rollerOpen var(--unroll) cubic-bezier(.45, .05, .25, 1) var(--unroll-at) both; }
.scroll.opening .roll { animation: rollThin var(--unroll) cubic-bezier(.45, .05, .25, 1) var(--unroll-at) both; }
.scroll.opening { --unroll: .42s; --unroll-at: 0s; }
.scroll.opening.whole { --unroll: 1.1s; --unroll-at: 1s; animation: scrollFall .7s linear .28s both; }
.scroll.waiting, .scroll.waiting .titlepage, .scroll.waiting .roller, .scroll.waiting .roll { animation-play-state: paused !important; }
@keyframes scrollFall {
  0% { translate: 0 -105vh; animation-timing-function: cubic-bezier(.55, .08, .9, .6); }
  62% { translate: 0 0; animation-timing-function: cubic-bezier(.2, .6, .5, 1); }
  81% { translate: 0 -11px; animation-timing-function: cubic-bezier(.5, 0, .8, .5); }
  100% { translate: 0 0; }
}
@keyframes sheetOpen { from { clip-path: inset(-12px -40px 100% -40px); } to { clip-path: inset(-12px -40px 0 -40px); } }
@keyframes rollerOpen { from { translate: 0 -100%; } to { translate: 0 0; } }
@keyframes rollThin { from { scale: 1 1.45; } to { scale: 1 1; } }
/* The change to and from the Library. TURN_MS in app.js is this length. */
.scroll.turning .titlepage { animation: sheetTurn .52s ease-in-out; }
.scroll.turning .roller { animation: rollerTurn .52s ease-in-out; }
@keyframes sheetTurn { 0%, 100% { clip-path: inset(-12px -40px 0 -40px); } 50% { clip-path: inset(-12px -40px 100% -40px); } }
@keyframes rollerTurn { 0%, 100% { translate: 0 0; } 50% { translate: 0 -100%; } }

/* the sheet */
.titlepage h1 { margin: 0; font: 700 62px/1 var(--brand-wordmark); text-align: center; color: var(--ink); }
.titlepage .sub { margin: var(--s1) 0 var(--s4); font: italic 17px/1.3 var(--brand-text); text-align: center; text-wrap: balance; color: var(--ink-2); }
.numerals { display: flex; justify-content: space-between; margin-bottom: var(--s2); padding: 5px 2px 4px; border-top: 1px solid var(--ink); border-bottom: 1px solid var(--ink); font: 14px/1 var(--brand-text); color: var(--ink); }
/* Each numeral opens its promise. The tap area reaches past the rules, and the row keeps its height. */
.numerals button { padding: 7px 5px; margin: -7px -5px; text-decoration: underline dotted var(--ink-3) 1px; text-underline-offset: 3px; transition: color .12s; }
@media (hover: hover) { .numerals button:hover { color: var(--wax); text-decoration: underline solid var(--wax) 1px; } }
.field { display: block; margin-bottom: var(--s3); }
.signline { display: block; width: 100%; height: 56px; padding: 12px 10px 0; font: 21px/40px var(--brand-sign); color: var(--sign-ink); caret-color: var(--sign-ink); background: none; border: 0; border-bottom: 1px solid var(--ink); border-radius: 0; outline: none; }
.signline:focus { border-bottom-color: var(--wax); box-shadow: 0 1px 0 var(--wax); }
.signlabel { display: block; margin-top: 3px; font: italic 13px/1.2 var(--brand-text); color: var(--ink-2); }
.seg { display: flex; gap: var(--s1); margin-bottom: var(--s1); align-items: center; }
.seg .lbl, .packs .lbl { flex: none; width: 56px; }
.seg button { width: 24px; height: 26px; padding: 0; color: var(--ink-2); font-size: 16px; line-height: 24px; border-bottom: 1px solid transparent; }
@media (hover: hover) { .seg button:hover { color: var(--ink); } }
.seg button.on { color: var(--ink); border-bottom-color: var(--ink); }
.seg button:disabled { opacity: .35; cursor: default; }
.packs { display: flex; align-items: center; gap: var(--s1); }
.worldbutton { flex: 1; min-width: 0; display: flex; align-items: baseline; gap: var(--s2); padding: 1px 0 0; line-height: 24px; font-size: 16px; text-align: left; color: var(--ink); border-bottom: 1px solid var(--ink-3); transition: border-color .12s; }
.worldname { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.chevron { margin-left: auto; padding-right: 2px; font-size: 24px; line-height: 20px; color: var(--ink-2); transition: translate .2s cubic-bezier(.2,.9,.3,1); }
@media (hover: hover) { .worldbutton:hover { border-bottom-color: var(--ink); } .worldbutton:hover .chevron { translate: 2px 0; } }
.worldbutton[aria-expanded="true"] { border-bottom-color: var(--wax); }
.worldbutton[aria-expanded="true"] .chevron { color: var(--wax); translate: 3px 0; }
.packnote { min-height: 2.6em; margin: var(--s1) 0 var(--s3); font-size: 14px; line-height: 1.3; color: var(--ink-2); }
.packnote b { font-weight: 600; color: var(--ink); }
.titlepage .act.gold { width: 100%; min-height: 48px; font-size: 20px; }
.joinline { display: flex; align-items: flex-end; gap: var(--s2); margin-top: var(--s3); }
.joinline .input { padding: 6px 2px; background: none; border: 0; border-bottom: 1px solid var(--ink-3); font-family: var(--mono); text-transform: uppercase; letter-spacing: .08em; }
.joinline .input:focus { outline: none; border-bottom-color: var(--wax); box-shadow: 0 1px 0 var(--wax); }
.joinline .input::placeholder { text-transform: none; letter-spacing: 0; font-family: var(--serif); }
.joinline .act { min-height: 34px; padding: 4px 16px; }
.tablelist { margin-top: var(--s2); display: grid; }
.tablelist .t { display: flex; align-items: center; justify-content: space-between; gap: var(--s2); padding: 5px 0; border-top: 1px solid var(--vellum-3); font-size: 14px; }
.tablelist .code { font-family: var(--mono); font-size: 14px; }
.tablelist .state { color: var(--ink-3); flex: 1; }
.errline { min-height: 20px; margin-top: var(--s2); color: var(--wax); font-size: 14px; }

/* The list of worlds: a second sheet behind the first. placePicker in app.js sets its place and how far it and
   the scroll move. The board's framing eases at about the same pace, in the player. */
.scroll { transform-origin: 0 0; transition: translate .34s cubic-bezier(.2,.9,.3,1), scale .34s cubic-bezier(.2,.9,.3,1), opacity .2s; }
.scroll.picking { translate: var(--pick-shift, 0) 0; scale: var(--pick-scale, 1); }
/* Room for the longest line of each world, so that the form holds still while worlds are compared. */
@media (min-height: 641px) {
  .titlepage .sub { min-height: 2.6em; }
  .scroll.picking .packnote { min-height: 3.9em; }
}
.picker { position: fixed; z-index: 4; display: flex; flex-direction: column; overflow: hidden; visibility: hidden; box-shadow: 0 10px 24px rgba(0,0,0,.45); transition: translate .34s cubic-bezier(.2,.9,.3,1), transform .3s cubic-bezier(.2,.9,.3,1), visibility 0s .34s; }
.picker.open { visibility: visible; translate: var(--pick-slide, 0) 0; transition: translate .34s cubic-bezier(.2,.9,.3,1), transform .3s cubic-bezier(.2,.9,.3,1); }
.picker.pulled { transition: none; }
/* The sheet's shading and the scroll's shadow on it lie over the rows, so a row's own colour does not hide them. */
.picker::after { content: ""; position: absolute; inset: 0; z-index: 2; pointer-events: none; box-shadow: inset 14px 0 12px -12px color-mix(in srgb, var(--stain) 70%, transparent), inset 0 0 40px color-mix(in srgb, var(--stain) 22%, transparent); }
.pickerhead { display: none; }
/* The last lines fade as they reach the foot, which says there is more, and no line is cut in half. */
.picker::before { content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: var(--s5); z-index: 2; pointer-events: none; background: linear-gradient(transparent, var(--vellum)); }
.worldlist { flex: 1; min-height: 0; overflow-y: auto; overscroll-behavior: contain; outline: none; padding: 0 var(--s3) var(--s5) var(--s4); scrollbar-width: thin; scrollbar-color: var(--vellum-3) transparent; }
/* A group's label stays in sight while its rows scroll under it. */
.worldgroup { position: sticky; top: 0; z-index: 1; padding: var(--s4) 0 var(--s1); background: var(--paper), var(--vellum); border-bottom: 1px solid var(--ink); }
.shelfrow { display: flex; align-items: flex-start; gap: var(--s3); width: 100%; padding: var(--s3) var(--s2); text-align: left; border-bottom: 1px solid var(--vellum-3); scroll-margin: 44px 0 var(--s5); }
[role="group"] .shelfrow:last-child { border-bottom: 0; }
@media (hover: hover) { .shelfrow:hover { background: color-mix(in srgb, var(--stain) 12%, transparent); } }
.shelfrow:focus-visible { outline-offset: -2px; }
.shelfrow[aria-selected="true"] { background: color-mix(in srgb, var(--stain) 18%, transparent); box-shadow: inset 3px 0 0 var(--wax); }
.shelfrow[aria-selected="true"] .shelfblurb, .shelfrow[aria-selected="true"] .smallcaps { color: var(--ink); }
.shelfrow svg.seal { position: static; flex: none; width: 26px; height: 26px; margin: 2px 0 0; }
.shelftext { flex: 1; min-width: 0; display: grid; gap: 2px; }
.shelfname { font: 20px/1.15 var(--brand-text); color: var(--ink); }
.shelfblurb { font-size: 14px; line-height: 1.3; color: var(--ink-2); }
.shelfback { align-self: center; flex: none; font-family: var(--brand-text); font-size: 16px; }

/* the constitution: on the other side of the sheet, and in the dock */
.constitution h2 { margin: 0 0 var(--s2); font: 400 28px/1.1 var(--brand-text); outline: none; }
.constitution .opening { margin: 0 0 var(--s3); font: italic 16px/1.3 var(--brand-text); text-wrap: pretty; color: var(--ink-2); }
.promises { margin: 0; padding: 0; list-style: none; border-top: 1px solid var(--ink); border-bottom: 1px solid var(--ink); }
.promises li + li { border-top: 1px solid var(--vellum-3); }
.promises summary { display: grid; grid-template-columns: 38px 1fr 14px; align-items: baseline; padding: 6px 0; cursor: pointer; list-style: none; }
.promises summary::after { content: "+"; justify-self: end; font-size: 14px; line-height: 1; color: var(--ink-3); opacity: 0; transition: opacity .12s; }
.promises details[open] summary::after { content: "−"; opacity: 1; }
.promises summary:focus-visible::after { opacity: 1; }
@media (hover: hover) { .promises summary:hover::after { opacity: 1; } }
@media (hover: none) { .promises summary::after { opacity: .7; } }
.promises summary::-webkit-details-marker { display: none; }
.promises .numeral { font: 14px/1 var(--brand-text); color: var(--ink-3); }
.promises .promise { font: 17px/1.25 var(--brand-text); text-wrap: balance; color: var(--ink); }
@media (hover: hover) { .promises summary:hover .numeral { color: var(--ink); } }
.promises details.here .numeral, .promises details.here .promise { color: var(--wax); }
.promises .behind { padding: 0 14px var(--s2) 38px; font-size: 14px; line-height: 1.35; color: var(--ink-2); }
.promises .behind code { display: block; font: 12px/1.4 var(--mono); word-break: break-word; }
.promises .behind p { margin: var(--s1) 0 0; }
.notpromised { margin: var(--s3) 0 0; font: italic 14px/1.3 var(--brand-text); color: var(--ink-2); }
/* On the scroll it stands like the title page: centred, with the wordmark's own weight of heading. */
.promisesheet h2 { font-size: 34px; text-align: center; }
.promisesheet .opening, .promisesheet .notpromised { text-align: center; text-wrap: balance; }
.promisesheet .shelfback { display: block; margin: var(--s2) auto 0; }
.lawshead { display: flex; align-items: baseline; justify-content: space-between; gap: var(--s2); padding-right: var(--s5); }
.empty .constitutionlink { font: inherit; }
.rail .numeralsmark { font: 13px/1 var(--brand-text); letter-spacing: .02em; }

@media (max-width: 560px) {
  .scroll { left: 16px; width: calc(100vw - 32px); max-width: none; }
  .titlepage { padding: var(--s5) var(--s5) 34px; }
  .numerals { padding-inline: 0; }
}
/* A short window: enough of the sheet shows to reach "Found a table", and the rest scrolls inside it. */
@media (max-height: 640px) {
  .titlepage { padding-top: var(--s4); }
  .titlepage h1 { font-size: 44px; }
  .titlepage .sub { margin-bottom: var(--s2); font-size: 15px; }
  .signline { height: 46px; padding-top: 6px; }
  .packnote { min-height: 0; margin-bottom: var(--s2); }
}
.seats { display: flex; gap: var(--s2); margin: var(--s4) 0; }
.seatbanner { width: 62px; text-align: center; font-size: 12px; line-height: 1.15; }
.seatbanner .cloth { display: block; position: relative; overflow: hidden; width: 62px; height: 66px; clip-path: polygon(0 0, 100% 0, 100% 100%, 50% 84%, 0 100%); animation: unfurl .3s cubic-bezier(.2,.9,.3,1) both; transform-origin: top; }
.seatbanner .cloth svg { position: absolute; inset: 0; width: 100%; height: 100%; opacity: .26; }
.seatbanner.empty .cloth { background: var(--vellum-2); box-shadow: inset 0 0 0 1px var(--vellum-3); animation: none; }
@keyframes unfurl { from { transform: scaleY(.1); } }
.bigcode { font: 28px var(--mono); letter-spacing: .16em; margin: var(--s1) 0; user-select: all; }
.gatherbar { display: flex; flex-wrap: wrap; gap: var(--s2); }
.gatherbar .act { flex: 1; }
.seatadd { flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; gap: var(--s1); }
.seatadd .act { flex: none; width: 100%; }
.seatadd p { margin: 0; font-size: 13px; line-height: 1.3; color: var(--ink-2); }
.gatherbar .act.gold { flex-basis: 100%; }

/* ---------- the proclamation ---------- */
.proclaim { position: relative; }
.proclaim .sealmark { right: 0; bottom: 48px; width: 64px; height: 64px; }
.proclaim svg.wax { width: 64px; height: 64px; }
.proclaim h2 { margin: var(--s1) 0 var(--s3); font-size: 28px; font-weight: 400; line-height: 1.15; }
.standing { display: flex; align-items: center; gap: var(--s2); padding: 6px 0; border-bottom: 1px solid var(--vellum-3); font-size: 16px; }
.standing b { margin-left: auto; font-size: 20px; font-weight: 600; }
.standing .fine { color: var(--ink-3); font-size: 12px; }
.proclaim .bar { display: flex; gap: var(--s2); margin-top: var(--s4); }
.proclaim .bar .act { flex: 1; }

@media (max-width: 860px) {
  :root { --dock: 300px; --ledge: 84px; }
  .tool { width: 54px; } .rcard { width: 40px; } .endturn { width: 96px; font-size: 16px; }
  .hand { gap: var(--s1); }
  .tray.many .tool { width: 46px; font-size: 11px; }
  .banner, .banner .cloth { width: 50px; }
}
/* ---------- a finger ---------- */
/* A move on its way to the server shows on the button that sent it. */
.busy { animation: busy .7s ease-in-out infinite alternate; cursor: progress; pointer-events: none; }
@keyframes busy { to { opacity: .55; } }
@media (pointer: coarse) {
  * { touch-action: manipulation; -webkit-tap-highlight-color: transparent; }
  .ledge, .rail, .crown, .act, .tool, .seg, .packs, .numerals, .pickrow, .bankrow, .replaybar { -webkit-user-select: none; user-select: none; -webkit-touch-callout: none; }
  /* The finger is down: this shows at once, with no transition. */
  .down { filter: brightness(.8); transition: none !important; }
  .vellum .down:not(.act) { background-color: color-mix(in srgb, var(--stain) 22%, transparent); filter: none; }
  /* A disabled tool says why when tapped. See bindTouch in app.js. */
  .tool:disabled { pointer-events: none; }
  .tray { min-height: 0; }
  /* Everything a finger aims at is at least 44 by 44. */
  .act, .slip .act, .pickmenu .act, .joinline .act { min-height: 44px; }
  .link { display: inline-flex; align-items: center; justify-content: center; min-width: 44px; min-height: 44px; }
  .toggleline { display: flex; margin-bottom: var(--s1); }
  .empty .constitutionlink { display: inline; min-height: 0; }
  .seg button { width: 44px; height: 44px; line-height: 44px; }
  .worldbutton { min-height: 44px; align-items: center; }
  .numerals { display: grid; grid-template-columns: repeat(5, 1fr); padding: 0; }
  .numerals button { min-height: 44px; margin: 0; padding: 0; }
  .signline, .joinline .input { min-height: 44px; }
  .dock .x { top: 0; right: 0; width: 44px; height: 44px; }
  .dock h2, .lawshead { padding-right: var(--s6); }
  .bankrow { flex-wrap: wrap; }
  .bankrow button { flex: none; width: 44px; height: 44px; }
  .tile { width: 44px; }
  .tile .add { height: 44px; }
  .tile .less { height: 44px; }
  .pickrow .lbl { padding-top: 11px; }
  .selectline .num, .selectline select, .declaresheet .drow input, .talkinput select, .talkinput .input { min-height: 44px; font-size: 16px; }
  .declaresheet .drow { grid-template-columns: 24px 1fr 64px auto; }
  details.formal summary { display: flex; align-items: center; min-height: 44px; }
  .promises summary { align-items: center; min-height: 44px; }
  .tablelist .t { min-height: 44px; }
  .replaybar .act { min-width: 44px; padding: var(--s1) var(--s2); }
  .replaybar .scrub { min-height: 44px; }
  .menu .link { justify-content: flex-start; }
  .banner { touch-action: manipulation; cursor: pointer; }
  /* A vote can always be cast, however long the rule is. */
  .votebar { position: sticky; bottom: calc(-1 * var(--s4)); z-index: 1; margin: var(--s2) calc(-1 * var(--s4)) calc(-1 * var(--s4)); padding: var(--s2) var(--s4) var(--s3); background: var(--paper), var(--vellum-2); box-shadow: 0 -1px 0 var(--vellum-3); }
  .sheet, .titlepage, .worldlist, .tray, .hand, .rail { overscroll-behavior: contain; -webkit-overflow-scrolling: touch; }
  /* Long words in a law's source, a name or a chat line never push the page sideways. */
  .sheet { overflow-wrap: anywhere; }
}

/* ---------- a phone upright: the board has the screen, the rail runs along the foot, and the dock is a sheet ---------- */
@media (max-width: 760px) and (orientation: portrait) {
  /* --ledge is everything at the foot of the screen, measured in updateInsets in app.js. */
  :root { --rail: 0px; --nav: 50px; --ledge: calc(var(--nav) + var(--safe-b)); }
  .rail { top: auto; left: 0; right: 0; bottom: 0; width: auto; height: calc(var(--nav) + var(--safe-b)); padding: 0 var(--safe-r) var(--safe-b) var(--safe-l); flex-direction: row; gap: 0; overflow-x: auto; scrollbar-width: none; box-shadow: 0 -1px 0 var(--brass); }
  .rail::-webkit-scrollbar, .tray::-webkit-scrollbar, .hand::-webkit-scrollbar { display: none; }
  .rail button { flex: 1 0 44px; width: auto; height: var(--nav); }
  .rail button .count { right: calc(50% - 22px); top: 6px; }
  .rail .spacer { display: none; }
  .ledge { bottom: calc(var(--nav) + var(--safe-b)); height: auto; flex-wrap: wrap; gap: 6px var(--s2); padding: var(--s2) calc(var(--s2) + var(--safe-r)) 6px calc(var(--s2) + var(--safe-l)); }
  .hand { flex: 1 1 0; min-width: 0; gap: var(--s1); padding: var(--s1) var(--s1) 0 0; overflow-x: auto; scrollbar-width: none; }
  .rcard { flex: 1 1 0; width: auto; min-width: 44px; max-width: 58px; height: 52px; font-size: 16px; rotate: 0deg; translate: 0 0; }
  .rcard svg.res { width: 22px; height: 22px; }
  .rcard.pays { translate: 0 -3px; }
  .rcard.pays::after { top: -3px; left: -1px; padding: 0 3px; font-size: 12px; }
  .endturn { order: 2; flex: none; width: 84px; min-height: 52px; padding: var(--s1); font-size: 16px; line-height: 1.1; white-space: normal; }
  .tray { order: 3; flex: 0 0 100%; gap: var(--s1); padding: var(--s1) 0 var(--s1); margin: 0; overflow-x: auto; scrollbar-width: none; }
  .tray:empty { display: none; }
  .tool, .tray.many .tool { flex: none; width: 62px; height: auto; min-height: 58px; padding: var(--s1) 0; font-size: 11px; }
  .tool .nm { max-width: 58px; }
  .tool svg.piece { width: 20px; height: 20px; }
  .tool .need { font-size: 12px; gap: 0 2px; }
  .tool .need svg.res { width: 13px; height: 13px; }
  .tool.sep, .tray.many .tool.sep { margin-left: var(--s1); }
  /* Many goods: the hand takes a whole row, in two lines, and End turn moves down beside the tools. */
  .ledge:has(.hand.many) .hand { flex: 0 0 100%; order: 1; }
  .ledge:has(.hand.many) .tray { flex: 1 1 0; min-width: 0; order: 2; }
  .ledge:has(.hand.many) .endturn { order: 3; }
  .hand.many { grid-template-rows: repeat(2, 40px); grid-auto-columns: minmax(38px, 1fr); }
  .hand.many .rcard { width: auto; min-width: 0; max-width: none; height: 40px; }
  .hand.many .rcard svg.res { width: 18px; height: 18px; }
  /* With the sheet up, the hand and End turn stay in sight, and the tools make way. */
  .ledge.sheetup .tray { display: none; }

  .crown { top: var(--safe-t); left: calc(var(--s2) + var(--safe-l)); right: calc(var(--s2) + var(--safe-r)); gap: var(--s2); flex-wrap: wrap; }
  .houses { gap: var(--s1); flex: 0 0 auto; }
  .banner, .banner .cloth { width: 44px; }
  .banner .cloth { height: 56px; }
  .banner.turn .cloth { height: 68px; }
  .banner.won .cloth { height: 80px; }
  .banner .score { top: 6px; font-size: 22px; }
  .banner .worn { top: 28px; }
  .banner .cloth .worn svg { width: 24px; height: 24px; }
  .banner .name { font-size: 11px; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
  .banner .quillmark { top: 36px; }
  .banner:nth-child(n+3) .card-tip { left: auto; right: 0; }
  .card-tip { max-width: calc(100vw - 16px); }
  .heraldry { flex: 1 1 auto; }
  .herald { justify-content: flex-end; }
  .herald .tab { padding: 6px var(--s2) var(--s2); font-size: 12px; }
  .herald .die { min-width: 36px; padding: 2px var(--s2) 6px; font-size: 20px; }
  .herald .clock { padding: 6px var(--s1); font-size: 12px; }
  .caption { position: fixed; left: var(--s2); right: var(--s2); top: calc(var(--crown) + var(--safe-t) + var(--s1)); max-width: none; font-size: 14px; text-align: center; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 3; overflow: hidden; }

  /* The sheet. It sits on the foot of the screen, and on the keyboard when that is open. */
  .dock { top: auto; left: 0; right: 0; bottom: var(--ledge); width: auto; max-height: calc(100dvh - var(--ledge) - var(--safe-t) - 40px); transform: translateY(calc(100% + var(--ledge) + var(--s4))); }
  .dock.open { transform: none; }
  .dock.pulled { transition: none; }
  .dock .grab { display: block; position: relative; flex: none; height: 22px; margin-right: 44px; touch-action: none; cursor: grab; }
  .dock .grab::before { content: ""; position: absolute; left: calc(50% + 22px); top: 9px; width: 40px; height: 4px; margin-left: -20px; background: var(--ink-3); opacity: .5; }
  .dock .grab::after { content: ""; position: absolute; inset: -12px 0 -12px; }
  .dock .sheet { padding: var(--s1) var(--s4) var(--s4); }
  .kb .dock { bottom: var(--kb); max-height: calc(var(--seen) - var(--s2)); }
  .kb .ledge, .kb .rail, .kb .prompt { display: none; }
  .proposebar { bottom: calc(-1 * var(--s4)); }

  .prompt { bottom: calc(var(--ledge) + 6px); max-width: calc(100vw - 16px); width: max-content; padding: var(--s1) var(--s3); font-size: 14px; line-height: 1.25; white-space: normal; clip-path: none; }
  .pennant { bottom: calc(var(--ledge) + var(--s2)); }
  .declared { left: var(--s2); bottom: calc(var(--ledge) + var(--s2)); max-width: calc(100vw - 16px); }
  .slips { left: var(--s2); right: var(--s2); width: auto; top: calc(var(--crown) + var(--safe-t) + var(--s2)); max-height: 40dvh; overflow-y: auto; }
  .menu { left: var(--s2); right: var(--s2); bottom: calc(var(--ledge) + var(--s2)); width: auto; max-height: calc(100dvh - var(--ledge) - 24px); overflow-y: auto; }
  .replaybar { right: 0; bottom: calc(var(--nav) + var(--safe-b)); height: auto; flex-wrap: wrap; padding: var(--s1) var(--s2); }
  .replaybar .scrub { flex: 1 1 100%; order: 9; }
  .stage svg.board2d { inset: var(--crown) 0 var(--ledge) 0; width: 100%; height: calc(100% - var(--crown) - var(--ledge)); }

  .scroll { left: max(var(--s3), calc(50vw - 220px)); width: min(440px, calc(100vw - 24px)); max-width: none; max-height: calc(100dvh - 44px); }
  .titlepage { padding: var(--s5) var(--s4) 34px; }
  .seats { flex-wrap: wrap; justify-content: center; }
  .conseq .who b { min-width: 52px; }
  .standing { flex-wrap: wrap; }
  .standing .fine { order: 3; flex: 1 0 100%; }
}

/* The smallest phones: five cards and End turn still fit in one row. */
@media (max-width: 340px) and (orientation: portrait) {
  .hand { gap: 3px; }
  .rcard { min-width: 40px; }
  .endturn { width: 68px; font-size: 15px; }
  .hand.many { grid-auto-columns: minmax(34px, 1fr); }
}
/* On a short screen the sheet scrolls, and the one thing it is for stays in reach. */
@media (pointer: coarse) and (max-height: 640px) {
  .titlepage .act.gold { position: sticky; bottom: 26px; z-index: 1; box-shadow: 0 -8px 12px -6px color-mix(in srgb, var(--vellum) 90%, transparent); }
}

/* ---------- a phone on its side: the rail stays at the right, and the ledge is one thin row ---------- */
@media (max-height: 500px) and (orientation: landscape) {
  :root { --rail: 44px; --ledge: 68px; }
  .rail { width: calc(var(--rail) + var(--safe-r)); padding: 0 var(--safe-r) 0 0; gap: 0; overflow-y: auto; scrollbar-width: none; }
  .rail::-webkit-scrollbar, .tray::-webkit-scrollbar, .hand::-webkit-scrollbar { display: none; }
  .rail button { flex: none; width: var(--rail); height: 44px; }
  .rail .spacer { flex: 1 0 0; min-height: 0; }
  .rail button .count { right: 3px; top: 3px; }
  .ledge { height: auto; min-height: 56px; gap: var(--s2); padding: 6px calc(var(--rail) + var(--safe-r) + var(--s2)) 6px calc(var(--s2) + var(--safe-l)); align-items: stretch; }
  .hand { flex: 0 1 auto; min-width: 88px; gap: var(--s1); padding-right: 0; overflow-x: auto; scrollbar-width: none; align-items: center; }
  .rcard { flex: none; width: 44px; height: 52px; font-size: 16px; rotate: 0deg; translate: 0 0; }
  .rcard svg.res { width: 22px; height: 22px; }
  .rcard.pays { translate: 0 -2px; }
  .hand.many { grid-template-rows: repeat(2, 25px); grid-auto-columns: 44px; flex: 0 1 auto; }
  .hand.many .rcard { width: 44px; height: 25px; font-size: 13px; }
  .hand.many .rcard svg.res { width: 15px; height: 15px; }
  .tray { flex: 1 1 0; min-width: 0; gap: var(--s1); overflow-x: auto; scrollbar-width: none; padding: 0; margin: 0; }
  .tool, .tray.many .tool { flex: none; width: 64px; height: 52px; font-size: 11px; }
  .tool .nm { max-width: 60px; }
  .tool svg.piece { width: 18px; height: 18px; }
  .tool .need { flex-wrap: nowrap; font-size: 12px; gap: 0 2px; }
  .tool .need svg.res { width: 12px; height: 12px; }
  .tool.sep, .tray.many .tool.sep { margin-left: var(--s1); }
  .endturn { flex: none; width: 76px; min-height: 48px; padding: var(--s1); font-size: 15px; line-height: 1.1; white-space: normal; }
  .crown { top: var(--safe-t); left: calc(var(--s2) + var(--safe-l)); right: calc(var(--rail) + var(--safe-r) + var(--s2)); gap: var(--s2); }
  .houses { gap: var(--s1); }
  .banner, .banner .cloth { width: 44px; }
  .banner .cloth { height: 46px; }
  .banner.turn .cloth { height: 56px; }
  .banner.won .cloth { height: 64px; }
  .banner .score { top: 4px; font-size: 20px; }
  .banner .name { font-size: 11px; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
  .banner .quillmark { top: 26px; }
  .herald .tab { padding: 4px var(--s2) 6px; font-size: 12px; }
  .herald .die { min-width: 34px; padding: 0 var(--s2) 4px; font-size: 20px; }
  /* The dock lies over the board at the right, over the ledge too, and it can be as tall as the screen. */
  .dock { top: var(--s1); right: calc(var(--rail) + var(--safe-r) + var(--s1)); width: min(360px, calc(100vw - var(--rail) - var(--safe-r) - var(--safe-l) - 16px)); max-height: calc(100dvh - var(--s2)); transform: translateX(calc(100% + var(--rail) + var(--safe-r) + var(--s4))); }
  .kb .dock { top: auto; bottom: var(--kb); max-height: calc(var(--seen) - var(--s1)); }
  .prompt { bottom: calc(var(--ledge) + 4px); padding: 2px var(--s3); font-size: 14px; white-space: normal; }
  .pennant { bottom: calc(var(--ledge) + var(--s1)); }
  .prompt.dock-open, .pennant.dock-open { display: none; }
  .declared { left: calc(var(--s2) + var(--safe-l)); bottom: calc(var(--ledge) + var(--s1)); }
  .slips { top: 80px; left: calc(var(--s2) + var(--safe-l)); }
  .menu { right: calc(var(--rail) + var(--safe-r) + var(--s1)); bottom: var(--s1); max-height: calc(100dvh - var(--s2)); overflow-y: auto; }
  .replaybar { right: calc(var(--rail) + var(--safe-r)); height: 48px; }
  .caption { font-size: 14px; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden; }
  .scroll { left: calc(var(--s3) + var(--safe-l)); width: min(400px, calc(100vw - 24px - var(--safe-l) - var(--safe-r))); max-height: calc(100dvh - 36px); }
  .stage svg.board2d { inset: 0 calc(var(--rail) + var(--safe-r)) var(--ledge) 0; width: calc(100% - var(--rail) - var(--safe-r)); height: calc(100% - var(--ledge)); }
}

/* ---------- the list of worlds, in a window too small to set it beside the board: pickerSheeted in app.js ---------- */
/* It rises from the foot of the screen. The scroll moves away, and the board has what is left above the sheet. */
@media (max-width: 999px), (max-height: 500px) and (orientation: landscape) {
  .scroll { transition: translate .3s cubic-bezier(.2,.9,.3,1), opacity .2s, visibility 0s; }
  .scroll.picking { translate: 0 -100dvh; scale: 1; opacity: 0; visibility: hidden; transition: translate .3s cubic-bezier(.2,.9,.3,1), opacity .2s, visibility 0s .3s; }
  .picker { z-index: 6; left: 0; right: 0; bottom: 0; height: 56dvh; transform: translateY(calc(100% + var(--s4))); box-shadow: 0 -6px 18px rgba(0,0,0,.4); }
  .picker::after { box-shadow: inset 0 0 40px color-mix(in srgb, var(--stain) 22%, transparent); }
  .picker.open { translate: none; transform: none; }
  .pickerhead { display: block; position: relative; flex: none; height: 22px; }
  .pickerhead .grab { position: absolute; inset: 0 44px 0 0; touch-action: none; cursor: grab; }
  .pickerhead .grab::before { content: ""; position: absolute; left: calc(50% + 22px); top: 9px; width: 40px; height: 4px; margin-left: -20px; background: var(--ink-3); opacity: .5; }
  .pickerhead .grab::after { content: ""; position: absolute; inset: -12px 0; }
  .pickerhead .x { position: absolute; top: 0; right: 0; z-index: 2; width: 44px; height: 44px; display: grid; place-items: center; color: var(--ink-2); }
  .worldlist { padding: 0 var(--s4) calc(var(--s5) + var(--safe-b)) var(--s4); }
  .worldgroup { padding-top: var(--s2); }
}
/* A phone on its side has no height to spare, so the sheet stands at the left, and the board beside it. */
@media (max-height: 500px) and (orientation: landscape) {
  .picker { right: auto; top: 0; width: min(340px, 46vw); height: auto; transform: translateX(calc(-100% - var(--s4))); }
  .pickerhead .grab { display: none; }
  .worldlist { padding-left: calc(var(--s3) + var(--safe-l)); }
}
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: .01ms !important; animation-delay: 0s !important; animation-iteration-count: 1 !important; transition-duration: .01ms !important; }
}
