/* The felt is SvgCardTable/Palette.h's "Card room green", and every other
   table colour is derived from it by the same arithmetic the Windows table
   uses: the bottom of the gradient is the base at 55%, a zone 76%, a lit zone
   14% towards white, the zone edge 60% and the label text 68%. */
:root {
  --felt-top: rgb(30 104 66);
  --felt-bottom: rgb(16 57 36);
  --zone-fill: rgb(22 79 50);
  --zone-hot: rgb(61 125 92);
  --zone-edge: rgb(165 195 179);
  --label: rgb(183 207 195);

  --page: #11161a;
  --chrome: #1b2227;
  --chrome-2: #242d33;
  --ink: #e8ece9;
  --ink-soft: #9fb0a8;
  --rule: #33403a;
  --accent: #f2c14e;
  --red: #ff6b6b;
  --suit-red: #d7263d;
  --settings: #083D28;            /* the Avalonia settings panel */

  --card-scale: 1;                /* Settings > Size > Cards */
  --cw: calc(clamp(42px, 5.6vw, 88px) * var(--card-scale));
  --ch: calc(var(--cw) * 1.4);
  --overlap-x: calc(var(--cw) * -0.7);
  --overlap-y: calc(var(--ch) * -0.74);

  color-scheme: dark;
}

* { box-sizing: border-box; }

/* A display rule below must not bring back something marked hidden. */
[hidden] { display: none !important; }

html, body { margin: 0; }
/* The scrollbar's room is kept whether or not there is one, so the table
   never changes width when a scrollbar comes and goes - as one did for a
   moment while the page loaded, before the bar's height was measured. Not
   in the phone layouts, which never scroll (and would show the room kept as
   an empty strip on a computer's short window). */
html:not(.phone-land):not(.phone-up) { scrollbar-gutter: stable; }

/* Touch: a quick double tap plays a card and makes a call, so it must not
   also zoom the page (pinching still does); no grey flash on a tap. */
html { touch-action: manipulation; -webkit-tap-highlight-color: transparent; }

body {
  background: var(--page);
  color: var(--ink);
  font: 14px/1.4 "Segoe UI", system-ui, -apple-system, sans-serif;
  min-height: 100vh;
}

/* --- The bar ------------------------------------------------------------ */

.bar {
  /* The bar stays at the top as the page scrolls, so the panel always opens
     right under it. It keeps clear of a phone's notch and corners, which the
     page is allowed under (viewport-fit=cover, for the phone layout). */
  position: sticky;
  top: 0;
  z-index: 25;
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  grid-template-areas: "title controls gear";
  align-items: center;
  gap: 8px 20px;
  padding: calc(10px + env(safe-area-inset-top, 0px)) calc(16px + env(safe-area-inset-right, 0px)) 10px calc(16px + env(safe-area-inset-left, 0px));
  background: var(--chrome);
  border-bottom: 1px solid var(--rule);
}
.bar h1 { grid-area: title; margin: 0; font-size: 17px; font-weight: 600; letter-spacing: .02em; white-space: nowrap; }
.bar .pip { color: var(--accent); }

.controls { grid-area: controls; display: flex; flex-wrap: wrap; align-items: center; gap: 8px 12px; }

button, select {
  font: inherit;
  color: var(--ink);
  background: var(--chrome-2);
  border: 1px solid var(--rule);
  border-radius: 6px;
  padding: 5px 12px;
  cursor: pointer;
}
button:hover:not(:disabled) { border-color: var(--zone-edge); }
button:focus-visible, select:focus-visible, input:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
button.primary { background: var(--felt-top); border-color: var(--zone-hot); min-width: 70px; }
button:disabled { opacity: .35; cursor: default; }
select { padding: 3px 6px; margin-left: 4px; }

/* A button's glyph: an Assets/Icons/btn-*.svg drawn as a mask in the colour of
   the button's text (index.html names each one's file). */
.ico {
  display: inline-block;
  width: 16px; height: 16px;
  margin: 0 6px 0 -2px;
  vertical-align: -3px;
  background-color: currentColor;
  -webkit-mask-size: contain; mask-size: contain;
  -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat;
  -webkit-mask-position: center; mask-position: center;
}

/* A practice table: nobody to chat with, and its own choices of hands to show. */
body.practice #btn-chat, body.practice #chat, body.practice #tab-players { display: none !important; }
body:not(.practice) .practice-only, body.practice .not-practice { display: none; }
/* At a server's table what it fixed when it was made is not offered at all
   (a practice table's player changes it), and what only a table played
   alone does is not offered anywhere at a server. */
body.remote:not(.practice) .table-set, body.remote .solo-set { display: none; }
/* A kibitzer watches: no chat, no seat. */
body.watching #btn-chat, body.watching #chat, body.watching #bidbox { display: none !important; }

/* The pack, when it may be dealt: a click on it deals. */
.pack.dealable { pointer-events: auto; cursor: pointer; }
.pack.dealable:hover .card:last-child, .pack.dealable:focus-visible .card:last-child { transform: translate(-2px, -3px); }
.pack.dealable:focus-visible { outline: 2px solid var(--accent); outline-offset: 4px; border-radius: 6px; }

/* The settings gear: quiet until pointed at, lit while the settings are open. */
.gear {
  grid-area: gear;
  display: grid;
  place-items: center;
  padding: 6px;
  background: transparent;
  border-color: transparent;
}
.gear:hover { background: rgb(255 255 255 / .08); }
.gear[aria-expanded="true"] { background: rgb(255 255 255 / .25); border-color: transparent; }
.gear img { display: block; transition: transform .3s ease; }
.gear[aria-expanded="true"] img { transform: rotate(45deg); }

/* --- Layout ------------------------------------------------------------- */

.layout {
  padding: 16px;
  max-width: 1500px;
  margin: 0 auto;
}
@media (max-width: 980px) {
  .layout { padding: 10px; }
}

/* --- The table ---------------------------------------------------------- */

.table {
  position: relative;
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  grid-template-rows: auto 1fr auto;
  grid-template-areas:
    ".    north ."
    "west centre east"
    ".    south .";
  gap: 10px;
  padding: 14px;
  min-height: max(calc(var(--ch) * 5.2), calc(100vh - var(--bar-height, 53px) - 32px));
  border-radius: 18px;
  background:
    radial-gradient(ellipse at 50% 35%, rgb(255 255 255 / .06), transparent 60%),
    linear-gradient(var(--felt-top), var(--felt-bottom));
  box-shadow: inset 0 0 0 1px rgb(0 0 0 / .4), inset 0 2px 30px rgb(0 0 0 / .35), 0 6px 24px rgb(0 0 0 / .4);
  overflow: hidden;
  user-select: none;
}

/* data-pos is where a seat sits, counted clockwise from the bottom: 0 is the
   player's own, 1 their left, 2 opposite, 3 their right. */
.seat { display: flex; flex-direction: column; align-items: center; gap: 6px; min-width: 0; }
.seat[data-pos="2"] { grid-area: north; }
.seat[data-pos="0"] { grid-area: south; }
.seat[data-pos="1"] { grid-area: west; justify-content: center; }
.seat[data-pos="3"] { grid-area: east; justify-content: center; }

/* A seat's name and what is beside it (its gear, the ?) and the trick's gear
   are drawn at --adorn: Settings > Size > Names and buttons, 125% at first. */
.label {
  font-size: calc(13px * var(--adorn, 1.25));
  color: var(--label);
  padding: calc(2px * var(--adorn, 1.25)) calc(10px * var(--adorn, 1.25));
  border-radius: 999px;
  background: var(--zone-fill);
  border: 1px solid transparent;
  white-space: nowrap;
  transition: background .2s, border-color .2s, color .2s;
}
.label .vul { color: var(--red); font-weight: 600; }
.label .role { opacity: .8; }
.label .hcp { opacity: .7; }

.seat.turn .label { background: var(--zone-hot); border-color: var(--accent); color: #fff; }

/* Told by more than colour, for anybody who does not see the gold or the red
   well. Both are drawn outside the label - a box-shadow and an outline - so
   neither moves anything on the table.

   Vulnerable: a thick red edge round the name, three pixels wide, so its
   width says it as well as its colour. */
.seat.vul .label { --ring-base: 3px; box-shadow: 0 0 0 3px var(--red); }

/* Whose turn it is to call or play: a gold ring pulsing round the name, as the
   Avalonia table's compass did (CardTable.cs) - once every 1.1 seconds it
   moves 4px outward while it thins from 4px to 2px and fades to a third, and
   back. A ring, with a gap before it, not a band against the name; and the gap
   starts outside a vulnerable edge, so the two can both be seen. */
.seat.turn .label { outline: 4px solid rgb(242 193 78 / 1); outline-offset: calc(var(--ring-base, 0px) + 2px);
  animation: turn-pulse .55s ease-in-out infinite alternate; }
@keyframes turn-pulse {
  from { outline-width: 4px; outline-offset: calc(var(--ring-base, 0px) + 2px); outline-color: rgb(242 193 78 / 1); }
  to   { outline-width: 2px; outline-offset: calc(var(--ring-base, 0px) + 6px); outline-color: rgb(242 193 78 / .35); }
}

/* The top right gear, small, beside a face-up hand's name. */
.hand-gear {
  display: inline-grid;
  place-items: center;
  width: calc(20px * var(--adorn, 1.25));
  height: calc(20px * var(--adorn, 1.25));
  margin: -2px -6px -2px calc(4px * var(--adorn, 1.25));
  padding: 0;
  vertical-align: middle;
  background: transparent;
  border: 0;
  border-radius: 50%;
  opacity: .75;
}
.hand-gear img { width: calc(13px * var(--adorn, 1.25)); height: calc(13px * var(--adorn, 1.25)); display: block; }
@media (hover: hover) {
  .hand-gear:hover { opacity: 1; background: rgb(255 255 255 / .14); }
}

/* Its flyout: the panel's green, the panel's gold for the order chosen. */
.sort-pop {
  position: fixed;
  z-index: 26;
  min-width: 190px;
  padding: 8px;
  border-radius: 8px;
  background: var(--settings);
  border: 1px solid rgb(255 255 255 / .14);
  box-shadow: 0 8px 24px rgb(0 0 0 / .45);
  color: #E8EEEA;
}
.sort-title { margin: 2px 4px 8px; font-size: 13px; font-weight: 600; color: #A8C2B6; }
.sort-pop [role=radiogroup] { display: flex; flex-direction: column; gap: 4px; }
.sort-pop button { text-align: left; background: transparent; border: 2px solid transparent; color: inherit; border-radius: 5px; padding: 5px 8px; }
.sort-pop button:hover { background: rgb(255 255 255 / .08); }
.sort-pop button[aria-checked="true"] { background: rgb(255 215 0 / .19); border-color: gold; }
.pile-size { margin: 10px 4px 2px; }
.pile-size label { display: flex; justify-content: space-between; font-size: 13px; color: #A8C2B6; }
.pile-size output { color: #E8EEEA; font-variant-numeric: tabular-nums; }
.pile-size input { width: 100%; margin: 6px 0 0; accent-color: var(--accent); }
.pile-size .reset { margin-top: 6px; font-size: 12px; padding: 3px 8px; }

/* Each pile - a hand, or the trick - has its own card size: the configured
   size times its own scale (--pile, set from the gear beside it). The overlap
   between a hand's cards is set by the script from the room the hand has, so
   bigger cards close up and smaller ones spread out; the values here are only
   what a hand starts with. */
.seat, .trick {
  --pw: calc(var(--cw) * var(--pile, 1));
  --ph: calc(var(--ch) * var(--pile, 1));
}
.hand { display: flex; min-height: var(--ph); }
.hand.across { flex-direction: row; }
.hand.across .card + .card { margin-left: var(--overlap-x); }
.hand.down { flex-direction: column; min-height: auto; min-width: var(--pw); }
.hand.down .card + .card { margin-top: var(--overlap-y); }
/* A gap between suits reads as a hand held by a person. */
.hand.across .card.suit-break { margin-left: calc(var(--overlap-x) + var(--pw) * .14); }
.hand.down .card.suit-break { margin-top: calc(var(--overlap-y) + var(--ph) * .06); }

.card {
  display: block;
  width: var(--pw, var(--cw));
  height: var(--ph, var(--ch));
  border-radius: calc(var(--pw, var(--cw)) * .07);
  box-shadow: 0 1px 3px rgb(0 0 0 / .45);
  background: #fff;
  -webkit-user-drag: none;
  transition: transform .15s ease, filter .2s;
}
/* The hand that is the player's to play from. Every card can be picked up;
   one that may not be played goes back, and the box top left says why. */
.card.mine { cursor: grab; touch-action: none; }
/* A card lifts under a pointer that hovers. A finger does not hover - a
   phone keeps a tapped card "hovered", which would look like the lift of a
   first tap - so there the lift is only the first tap's. */
@media (hover: hover) {
  .hand.across .card.mine:hover { transform: translateY(-18%); }
  .hand.down .card.mine:hover { transform: translateX(12%); }
}
/* A long press on a card is not a picture to save. */
.card { -webkit-touch-callout: none; user-select: none; }
.card.lifted { visibility: hidden; }
/* Double click: the first click lifts the card, ringed in gold, for the second to play. */
.hand.across .card.picked { transform: translateY(-22%); box-shadow: 0 0 0 2px gold, 0 6px 14px rgb(0 0 0 / .45); }
.hand.down .card.picked { transform: translateX(16%); box-shadow: 0 0 0 2px gold, 0 6px 14px rgb(0 0 0 / .45); }
.drag-card {
  position: fixed;
  z-index: 30;
  pointer-events: none;
  cursor: grabbing;
  box-shadow: 0 10px 24px rgb(0 0 0 / .5);
  transition: none;
}
.trick.drop-hot::before {
  content: "";
  position: absolute;
  inset: calc(var(--cw) * -.15);
  border-radius: 14px;
  border: 2px dashed var(--accent);
  background: rgb(242 193 78 / .08);
}

/* --- The middle --------------------------------------------------------- */

.centre { grid-area: centre; display: grid; place-items: center; min-width: 0; }
.centre > * { grid-area: 1 / 1; }

.trick {
  position: relative;
  width: calc(var(--pw) * 3.4);
  height: calc(var(--ph) * 2 + var(--pw) * 1.05);
}
.slot { position: absolute; width: var(--pw); height: var(--ph); }
.slot[data-pos="2"] { left: calc(50% - var(--pw) / 2); top: 0; }
.slot[data-pos="0"] { left: calc(50% - var(--pw) / 2); bottom: 0; }
.slot[data-pos="1"] { left: 0; top: calc(50% - var(--ph) / 2); }
.slot[data-pos="3"] { right: 0; top: calc(50% - var(--ph) / 2); }
/* The trick's own gear, for the size of its cards: its top right corner,
   where no card of the cross falls. */
.trick-gear {
  position: absolute;
  top: 0;
  right: 0;
  z-index: 2;
}
/* The trick's place, shown through the play so it is plain where a card goes
   without a card having to be held over it: a faint frame round the whole,
   and each card's place outlined until a card lands in it. The frame keeps
   off ::before, which is the drop highlight. */
.trick::after {
  content: "";
  position: absolute;
  inset: calc(var(--pw) * -.12);
  z-index: 0;
  border-radius: 14px;
  background: rgb(0 0 0 / .10);
  box-shadow: inset 0 0 0 1px rgb(255 255 255 / .14);
  pointer-events: none;
}
/* Before the deal, and while it goes out, there is no trick to mark. */
.table.idle .trick { visibility: hidden; }
.slot:empty {
  border: 1.5px dashed rgb(255 255 255 / .22);
  border-radius: calc(var(--pw) * .07);
}
.slot .card { position: absolute; inset: 0; transition: none; }
.slot .card.won { box-shadow: 0 0 0 2px var(--accent), 0 2px 8px rgb(0 0 0 / .5); }

.compass {
  position: absolute;
  left: 50%; top: 50%;
  width: calc(var(--cw) * .85); height: calc(var(--cw) * .85);
  transform: translate(-50%, -50%);
  border-radius: 50%;
  background: var(--zone-fill);
  border: 1px solid var(--zone-edge);
  font-size: calc(var(--cw) * .17);
  font-weight: 600;
  color: var(--label);
  z-index: 0;
}
.compass span { position: absolute; }
.compass span[data-pos="2"] { top: 6%; left: 50%; transform: translateX(-50%); }
.compass span[data-pos="0"] { bottom: 6%; left: 50%; transform: translateX(-50%); }
.compass span[data-pos="1"] { left: 10%; top: 50%; transform: translateY(-50%); }
.compass span[data-pos="3"] { right: 10%; top: 50%; transform: translateY(-50%); }
.compass span.vul { color: var(--red); }
.compass span.turn { color: var(--accent); }
.slot { z-index: 1; }

.banner {
  position: absolute;
  left: 50%; top: 50%;
  transform: translate(-50%, -50%);
  z-index: 5;
  padding: 14px 22px;
  border-radius: 12px;
  background: rgb(10 20 15 / .88);
  border: 1px solid var(--zone-edge);
  text-align: center;
  font-size: 15px;
  box-shadow: 0 8px 30px rgb(0 0 0 / .5);
  max-width: 90%;
}
.banner b { display: block; font-size: 20px; margin-bottom: 4px; }
.banner .plus { color: #7ee2a8; }
.banner .minus { color: var(--red); }

/* The state of the board, top left. On a phone it takes a row of its own
   rather than lying over North's hand. */
.info {
  position: absolute;
  top: 12px;
  left: 14px;
  z-index: 3;
  max-width: 230px;
  padding: 8px 12px;
  border-radius: 10px;
  background: rgb(0 0 0 / .22);
  color: var(--label);
  font-size: 13px;
  line-height: 1.5;
}
.info b { color: #fff; font-weight: 600; }
.info .k { color: var(--label); opacity: .85; }
.info .vul-yes { color: var(--red); }
.info .contract { font-size: 17px; font-weight: 600; color: #fff; margin-top: 2px; }
.info .status { color: var(--accent); font-weight: 600; min-height: 1.5em; }
.info .status.hint { color: #ffb4a8; }
.info .suit-red { color: #ff5a6e; }

/* The pack: a few backs squared up, each a hair lower than the one on it. */
.pack { position: absolute; z-index: 3; pointer-events: none; }
.pack .card { position: absolute; left: 0; top: 0; }
.pack .card:nth-child(1) { transform: translate(1.2px, 1.2px); }
.pack .card:nth-child(2) { transform: translate(.8px, .8px); }
.pack .card:nth-child(3) { transform: translate(.4px, .4px); }
/* A card on its way from the pack to a hand, over everything on the table. */
.deal-card {
  position: fixed;
  z-index: 15;
  pointer-events: none;
  transition: none;
  box-shadow: 0 2px 6px rgb(0 0 0 / .45);
}

/* Before the first deal: how a board goes, in the middle of the table. */
.welcome {
  position: absolute;
  left: 50%; top: 50%;
  transform: translate(-50%, -50%);
  z-index: 5;
  width: min(440px, 88%);
  padding: 14px 20px 12px;
  border-radius: 12px;
  background: rgb(10 20 15 / .9);
  border: 1px solid var(--zone-edge);
  box-shadow: 0 8px 30px rgb(0 0 0 / .5);
  font-size: 14px;
  line-height: 1.45;
}
.welcome .w-title { margin: 0 0 6px; font-size: 18px; font-weight: 700; color: #fff; }
.welcome ol { margin: 0; padding-left: 20px; }
.welcome li { margin: 4px 0; }
.welcome li b { color: var(--accent); }
.welcome .w-foot { margin: 10px 0 0; color: var(--ink-soft); font-size: 13px; }
/* A link that does something here: underlined, in the accent, no box. */
.welcome .w-link {
  padding: 0; border: 0; background: none; box-shadow: none;
  color: var(--accent); font-weight: 700; text-decoration: underline; text-underline-offset: 2px;
}
.welcome .w-link:hover { color: #fff; }

/* The Deal button, while a board waits for it: a slow glow, not a flash. */
#btn-deal.invite { animation: invite 1.8s ease-in-out infinite; }
@keyframes invite { 50% { box-shadow: 0 3px 0 rgb(0 0 0 / .45), 0 0 0 4px rgb(242 193 78 / .55); } }
@media (prefers-reduced-motion: reduce) { #btn-deal.invite { animation: none; border-color: var(--accent); } }

/* Buttons that do something stand up off the table, and go down when pressed -
   and stay down half a second (table.js adds .pressed), so a press is seen. */
.controls button, .bb-call, .bb-alert, .bb-hint, .pl-actions button, .pl-actions .button,
#set-done, .help-use, .help-no, .ask-buttons button, .chat form button[type="submit"] {
  background-image: linear-gradient(rgb(255 255 255 / .14), rgb(0 0 0 / .14));
  border-color: rgb(255 255 255 / .2) rgb(0 0 0 / .4) rgb(0 0 0 / .55);
  box-shadow: 0 3px 0 rgb(0 0 0 / .45), 0 4px 8px rgb(0 0 0 / .28);
  transition: transform .08s ease, box-shadow .08s ease, filter .15s ease;
}
:is(.controls button, .bb-call, .bb-alert, .bb-hint, .pl-actions button, .pl-actions .button,
    #set-done, .help-use, .help-no, .ask-buttons button, .chat form button[type="submit"]):hover:not(:disabled) { filter: brightness(1.12); }
:is(.controls button, .bb-call, .bb-alert, .bb-hint, .pl-actions button, .pl-actions .button,
    #set-done, .help-use, .help-no, .ask-buttons button, .chat form button[type="submit"]):is(:active, .pressed):not(:disabled) {
  transform: translateY(3px);
  background-image: linear-gradient(rgb(0 0 0 / .18), rgb(255 255 255 / .04));
  box-shadow: 0 0 0 rgb(0 0 0 / .45), inset 0 2px 5px rgb(0 0 0 / .5);
  animation: none;
}
:is(.controls button, .bb-call, .bb-alert, .bb-hint, .pl-actions button, .pl-actions .button,
    #set-done, .help-use, .help-no, .ask-buttons button, .chat form button[type="submit"]):disabled { box-shadow: none; background-image: none; }

/* The table, dimmed while the panel is open: waiting, not broken. */
.waiting {
  position: absolute; inset: 0;
  z-index: 8;
  display: grid; place-items: center;
  padding: 16px;
  text-align: center;
  font-size: 18px;
  color: #E8EEEA;
  background: rgb(0 0 0 / .55);
}

/* The splash, while the page loads: a small card in the middle of the screen,
   over everything, the table's felt glowing behind it. */
.splash {
  position: fixed;
  inset: 0;
  z-index: 100;
  display: grid;
  place-items: center;
  padding: 16px;
  background:
    radial-gradient(ellipse at 50% 45%, rgb(30 104 66 / .55), transparent 65%),
    var(--page);
  transition: opacity .35s ease;
}
.splash.done { opacity: 0; pointer-events: none; }
.splash-card {
  width: min(280px, 100%);
  padding: 22px 22px 18px;
  border-radius: 16px;
  background: var(--chrome);
  border: 1px solid var(--rule);
  box-shadow: 0 16px 40px rgb(0 0 0 / .5);
  text-align: center;
}
.splash-card img { display: block; margin: 0 auto 10px; border-radius: 18px; box-shadow: 0 4px 14px rgb(0 0 0 / .4); }
.splash-card h2 { margin: 0; font-size: 20px; font-weight: 600; }
.splash-version { margin: 2px 0 16px; font-size: 13px; color: var(--ink-soft); font-variant-numeric: tabular-nums; }
.splash-bar { position: relative; height: 6px; border-radius: 3px; background: rgb(255 255 255 / .1); overflow: hidden; }
.splash-fill { height: 100%; width: 0; border-radius: 3px; background: var(--accent); transition: width .15s linear; }
/* Before the pack has arrived there is nothing to count: a stripe that moves. */
.splash-bar.waiting .splash-fill { width: 35%; animation: splash-wait 1.1s ease-in-out infinite; }
@keyframes splash-wait { from { transform: translateX(-100%); } to { transform: translateX(290%); } }
.splash-status { margin: 10px 0 0; min-height: 1.4em; font-size: 12px; color: var(--ink-soft); font-variant-numeric: tabular-nums; }
.settings .about { margin-top: 18px; text-align: right; }
@media (prefers-reduced-motion: reduce) {
  .splash { transition: none; }
  .splash-bar.waiting .splash-fill { animation: none; width: 100%; opacity: .35; }
}

.suit-red { color: var(--suit-red); }

/* A suit, drawn from its SVG shape; it sits on the line like a letter. */
.glyph { display: inline-block; width: .9em; height: .9em; vertical-align: -.08em; margin-left: 1px; }

/* --- The auction, mid-table ---------------------------------------------- */

/* While the auction runs the middle of the table holds the history and,
   when the call is the player's, the bidding box beside it. */
/* Side by side, the two are one height: the box stretches to the history,
   which is ten ruled rounds, or more once a long auction adds rows. */
.auction-stage {
  position: relative;
  z-index: 4;
  display: none;
  align-items: stretch;
  justify-content: center;
  flex-wrap: wrap;
  gap: 14px;
}
.centre.bidding .auction-stage { display: flex; }
.centre.bidding .trick { visibility: hidden; }

/* The history, as the Avalonia panel prints it, on the same dark green. */
.auction-sheet { min-width: 0; }
.auction-stage .auction-sheet {
  display: flex;
  flex-direction: column;
  padding: 12px;
  border-radius: 8px;
  background: var(--settings);
  box-shadow: 0 3px 12px rgb(0 0 0 / .35);
}
/* Beside the bidding box the two are one height: the history's rows share it. */
.auction-stage .ag { flex: 1; grid-auto-rows: minmax(29px, 1fr); }
/* Minibridge: the one row of points announced, at its own height, not spread over an auction's. */
.auction-stage .ag.mini, html.phone-land .auction-stage .ag.mini, html.phone-up .auction-stage .ag.mini { flex: none; align-self: center; grid-auto-rows: minmax(34px, auto); }
.ag.mini .ag-cell:not(.ag-head) { font-size: 20px; font-weight: 600; }
/* Its panel is only as tall as its heading, the seats and the points - not
   stretched to the height of the bidding box beside it. */
.auction-stage .auction-sheet.mini,
html.phone-land .auction-stage .auction-sheet.mini,
html.phone-up .auction-stage .auction-sheet.mini { align-self: center; flex: none; }
.mini-title { margin: 0 0 8px; text-align: center; font-size: 14px; font-weight: 600; letter-spacing: .02em; color: rgb(255 255 255 / .85); }
/* Every box ruled on its right and bottom, the grid on its top and left, so
   each line is drawn once. East-West darker than the panel, North-South lighter. */
.ag {
  display: grid;
  grid-template-columns: repeat(4, minmax(56px, 1fr));
  border-top: 1px solid rgb(255 255 255 / .376);
  border-left: 1px solid rgb(255 255 255 / .376);
  color: #E8EEEA;
  font-variant-numeric: tabular-nums;
}
.ag-cell {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 29px;               /* an empty round as tall as a full one */
  padding: 3px 4px;
  font-size: 17px;
  white-space: nowrap;
  background: rgb(0 0 0 / .19);
  border-right: 1px solid rgb(255 255 255 / .376);
  border-bottom: 1px solid rgb(255 255 255 / .376);
}
.ag-cell.ns { background: rgb(255 255 255 / .12); }
.ag-head { font-size: 14px; font-weight: 600; color: rgb(255 255 255 / .82); background: rgb(0 0 0 / .31); }
.ag-head.ns { background: rgb(255 255 255 / .22); }
/* Partner's last call: a warm paper fill and a heavier border, drawn inside. */
.ag-cell.lit { background: #F4E7C2; color: #1E2A30; }
.ag-cell.lit::after { content: ""; position: absolute; inset: 0; border: 2px solid #C99A06; pointer-events: none; }

/* --- The bidding box ------------------------------------------------------ */

/* In the table's own colours: the dark green of the auction sheet and the
   panel, the application's buttons, and gold for what is chosen - the same
   gold that frames a chosen seat or card back in the settings. */
.bidbox {
  display: flex;
  flex-direction: column;
  width: 190px;
  padding: 8px;
  border-radius: 8px;
  background: var(--settings);
  border: 1px solid rgb(255 255 255 / .12);
  box-shadow: 0 3px 12px rgb(0 0 0 / .35);
  color: var(--ink);
  transition: border-color .2s, box-shadow .2s;
}
/* The player's turn: the box is lit as their seat's name is. */
.bidbox.my-turn { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent), 0 3px 12px rgb(0 0 0 / .35); }
.bidbox:focus { outline: none; }
/* Seven visual rows shared by the three columns, which stand on the button:
   levels fill all seven, denominations the lower five, answers the lower
   three. The rows share out whatever height the box has. */
.bb-cols {
  flex: 1;
  display: grid;
  grid-template-columns: repeat(3, 52px);
  grid-template-rows: repeat(7, minmax(28px, 1fr));
  justify-content: space-between;
  row-gap: 6px;
  margin-bottom: 8px;
}
.bb-col { display: contents; }
.bb-cell {
  position: relative;
  box-sizing: border-box;
  display: grid;
  place-items: center;
  border-radius: 6px;
  background: var(--chrome-2);
  border: 1px solid var(--rule);
  font-size: 15px;
  font-weight: 600;
  cursor: pointer;
  user-select: none;
}
.bb-cell .glyph { width: 18px; height: 18px; margin: 0; }
.bb-cell:hover:not(.disabled) { border-color: var(--zone-edge); }
.bb-cell.selected { background: rgb(255 215 0 / .19); border: 2px solid gold; }
.bb-cell.disabled { opacity: .3; cursor: default; }
/* The keyboard's place: a dashed ring just outside the box. */
.bb-cell.cursor::after {
  content: "";
  position: absolute;
  inset: -4px;
  border: 1.5px dashed var(--ink-soft);
  border-radius: 8px;
  pointer-events: none;
}
.bb-foot { display: flex; gap: 6px; }
/* Whose call the box is choosing, when the player has both hands. */
.bb-for {
  margin-bottom: 6px;
  padding: 4px 8px;
  border-radius: 6px;
  text-align: center;
  font-size: 13px;
  font-weight: 600;
  color: var(--ink-soft);
  background: rgb(255 255 255 / .06);
}
.bb-for.partner { color: #1E2A30; background: var(--accent); }
.bidbox.for-partner.my-turn { border-color: var(--accent); }
.bb-call {
  flex: 1;
  height: 40px;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 2px;
  background: var(--felt-top);
  border-color: var(--zone-hot);
  color: #fff;
  font-size: 17px;
  font-weight: 700;
}
.bb-call .glyph { width: 17px; height: 17px; }
/* Chosen but not yet the player's call: shown, not pressable. */
.bb-call:disabled { opacity: .55; }
/* Alert: the magenta an alerted call is ringed in. */
.bb-alert { height: 40px; padding: 0 10px; color: #ff7ad9; border-color: #C0189A; font-weight: 600; }
.bb-alert:not(:disabled) { background: rgb(224 64 184 / .16); animation: alert-on 1s ease-in-out 2; }
@keyframes alert-on { 50% { box-shadow: 0 0 0 3px rgb(224 64 184 / .45); } }

/* The hint: what the card calls for with this hand. */
.bb-hint { height: 40px; min-width: 34px; padding: 0 8px; font-weight: 700; }

/* A call in the auction answers a click with what it meant. */
.ag-cell.asks { cursor: help; }
@media (hover: hover) { .ag-cell.asks:hover { box-shadow: inset 0 0 0 1px rgb(255 255 255 / .55); } }

/* The help: the gear flyout's panel, a little wider, above the settings. */
.help-pop { z-index: 40; width: min(340px, calc(100vw - 16px)); padding: 10px 12px; }
.help-title { margin: 0 0 6px; font-weight: 600; display: flex; flex-wrap: wrap; align-items: center; gap: 4px 6px; }
.help-title .glyph { width: 15px; height: 15px; }
.help-call { white-space: nowrap; }
.help-text, .help-read { margin: 0 0 6px; font-size: 14px; line-height: 1.45; }
.help-read { color: #A8C2B6; }
.help-flag { font-size: 11px; font-weight: 700; letter-spacing: .03em; text-transform: uppercase; color: #ff7ad9;
             border: 1px solid #C0189A; border-radius: 4px; padding: 0 4px; }
.help-flag.quiet { color: #A8C2B6; border-color: rgb(255 255 255 / .3); }
.help-pop .help-use { margin-top: 4px; border: 2px solid gold; background: rgb(255 215 0 / .19); padding: 5px 10px; text-align: center; }
.help-pop .help-use .glyph { width: 14px; height: 14px; }
/* The suggestion taken at once, or not wanted. */
.help-buttons { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 4px; }
.help-pop .help-no { margin-top: 4px; padding: 5px 10px; border: 1px solid rgb(255 255 255 / .35); border-radius: 6px; background-color: rgb(255 255 255 / .06); color: inherit; }

/* The hint beside the hand to play from, and the cards that can be asked about. */
.hand-hint { margin-left: calc(4px * var(--adorn, 1.25)); padding: 0 calc(7px * var(--adorn, 1.25)); min-height: 0; height: calc(20px * var(--adorn, 1.25));
             line-height: 1; font-size: calc(12px * var(--adorn, 1.25)); font-weight: 700; border-radius: calc(10px * var(--adorn, 1.25)); border: 1px solid var(--accent); background: rgb(255 215 0 / .16); color: inherit; }
.slot .card { cursor: help; }

/* The play, trick by trick, on the Auction tab. */
.pr { display: flex; flex-direction: column; gap: 4px; margin-top: 6px; }
.pr-row { display: flex; align-items: center; gap: 4px; }
.pr-no { width: 22px; text-align: right; color: #A8C2B6; font-variant-numeric: tabular-nums; margin-right: 4px; }
.pr-card { display: inline-flex; align-items: center; gap: 2px; min-width: 58px; padding: 3px 6px; border-radius: 5px;
           background: rgb(0 0 0 / .19); border: 1px solid rgb(255 255 255 / .2); color: inherit; font-variant-numeric: tabular-nums; }
.pr-card .glyph { width: 14px; height: 14px; }
.pr-card.won { border-color: gold; background: rgb(255 215 0 / .14); }
.pr-seat { font-size: 11px; color: #A8C2B6; margin-right: 3px; }

/* An alerted call: ringed in magenta, for good. */
.ag-cell.alerted::before {
  content: "";
  position: absolute;
  inset: 2px 5px;
  border: 2px solid #E040B8;
  border-radius: 50%;
  pointer-events: none;
}

/* On a phone the controls go under the title, and the gear stays top right. */
@media (max-width: 700px) {
  .bar { grid-template-columns: minmax(0, 1fr) auto; grid-template-areas: "title gear" "controls controls"; }
  .table {
    grid-template-rows: auto auto 1fr auto;
    grid-template-areas:
      "info info   info"
      ".    north  ."
      "west centre east"
      ".    south  .";
  }
  .info { position: static; grid-area: info; max-width: none; justify-self: start; padding: 6px 10px; font-size: 12px; }
  .info .contract { font-size: 15px; }
}

@media (max-width: 560px) {
  :root { --cw: calc(clamp(34px, 11vw, 60px) * var(--card-scale)); }
  .table { padding: 8px; gap: 6px 4px; }
  /* The side labels are what set the width of the side columns, so they
     wrap here rather than squeezing the trick into East's hand. */
  .seat[data-pos="1"] .label, .seat[data-pos="3"] .label {
    white-space: normal;
    text-align: center;
    max-width: calc(var(--cw) * 1.6);
    font-size: calc(11px * var(--adorn, 1.25));
    line-height: 1.25;
    padding: 2px 6px;
    border-radius: 8px;
  }
  .bar { padding: calc(8px + env(safe-area-inset-top, 0px)) calc(12px + env(safe-area-inset-right, 0px)) 8px calc(12px + env(safe-area-inset-left, 0px)); }
  .centre.bidding { grid-column: 1 / -1; z-index: 4; }
  .auction-stage { gap: 8px; }
  .auction-stage .auction-sheet { padding: 6px; }
  .ag { grid-template-columns: repeat(4, minmax(40px, 1fr)); }
  .ag-cell { font-size: 14px; min-height: 24px; padding: 2px; }
  .ag-head { font-size: 11px; }
}

@media (prefers-reduced-motion: reduce) {
  .card, .label { transition: none; }
  /* Asked for no movement: the turn's ring stands still, wide and solid. */
  .seat.turn .label { animation: none; outline-width: 4px; outline-color: rgb(242 193 78 / .9); }
}

/* --- Settings ----------------------------------------------------------- */

/* A flyout from the gear, over the side panel: opaque, so nothing shows through. */
.settings {
  position: fixed;
  top: var(--bar-height, 53px);
  right: 0;
  bottom: 0;
  z-index: 20;
  width: min(max(380px, 30vw), 520px, 100%);
  display: flex;
  flex-direction: column;
  background: var(--settings);
  color: #E8EEEA;
  border-left: 1px solid rgb(255 255 255 / .12);
  box-shadow: -8px 0 24px rgb(0 0 0 / .4);
  animation: fly-in .18s ease-out;
}
.settings:focus { outline: none; }
@keyframes fly-in { from { transform: translateX(24px); opacity: 0; } }

/* Three tabs across the top: the settings, the auction, the scorecard. */
.tabs { display: flex; gap: 2px; padding: 10px 12px 0; border-bottom: 1px solid rgb(255 255 255 / .14); }
.tabs button {
  flex: 1;
  padding: 8px 6px;
  border: 0;
  border-radius: 8px 8px 0 0;
  background: transparent;
  color: #A8C2B6;
  font-weight: 600;
}
.tabs button:hover { color: #E8EEEA; background: rgb(255 255 255 / .06); }
.tabs button[aria-selected="true"] { color: #fff; background: rgb(255 255 255 / .12); box-shadow: inset 0 -3px 0 gold; }

.settings-body { flex: 1; overflow: auto; padding: 12px 16px 8px; }
.settings .pane-head { margin: 0 0 8px; font-size: 16px; font-weight: 600; }
.settings .suit-red { color: #ff6b7e; }
.settings h3 { margin: 16px 0 6px; font-size: 15px; font-weight: 600; }
.settings .note { margin: 4px 0 0; font-size: 12px; color: #A8C2B6; }
.settings .value { display: block; font-size: 13px; }
.settings output { font-variant-numeric: tabular-nums; }
.settings input[type="range"] { width: 100%; accent-color: var(--accent); margin: 6px 0 0; }
.settings .check { display: flex; align-items: center; gap: 8px; margin-top: 8px; cursor: pointer; }
.settings .check input { accent-color: var(--accent); width: 16px; height: 16px; }

/* The seats in a row; the player's framed in gold. */
.choice { display: flex; gap: 6px; }
.choice button {
  background: transparent;
  border: 2px solid rgb(255 255 255 / .25);
  border-radius: 5px;
  color: inherit;
}
.choice button[aria-checked="true"] { background: rgb(255 215 0 / .19); border-color: gold; }
.seats button, .clicks button, .orders button, .turns button, .systems button { flex: 1; padding: 6px 0; font-size: 13px; }
.settings p.value { margin: 10px 0 6px; }
.backs button { padding: 3px; line-height: 0; border-color: transparent; }
.backs img { width: 50px; height: 70px; border-radius: 4px; }

.settings-foot { display: flex; flex-direction: column; gap: 6px; padding: 10px 16px 14px; border-top: 1px solid rgb(255 255 255 / .1); }
.settings-foot button { width: 100%; padding: 7px 12px; }
/* Shown only on a phone on its side; see that block. */
.settings-foot .phone-only { display: none; }

/* The auction and the scorecard, in their tabs. */
.settings table { width: 100%; border-collapse: collapse; font-variant-numeric: tabular-nums; font-size: 14px; }
.scorecard th, .scorecard td { padding: 5px 6px; text-align: right; white-space: nowrap; }
.scorecard th { color: #A8C2B6; font-weight: 600; border-bottom: 1px solid rgb(255 255 255 / .18); }
.scorecard th:nth-child(2), .scorecard td:nth-child(2) { text-align: left; }
.scorecard tfoot td { border-top: 1px solid rgb(255 255 255 / .18); font-weight: 700; }
.scorecard tbody tr:last-child td { background: rgb(255 215 0 / .1); }

/* --- A phone on its side ---------------------------------------------------
   Landscape and under 500px tall. Height is what runs out, so everything is
   sized from it and the page never scrolls: the bar is one slim line with the
   board's state in it, the table fills the rest. The middle column holds
   partner across the top at a smaller size, the trick as a shallow diamond,
   and the player's hand along the bottom, as big as the height allows and
   running off the table's edge as a hand held up does - the indices are at
   the top of the cards. The side hands are the opponents', never played by
   the player, so they are drawn small: a back and a count, or when face up
   the suits written out. During the auction the history takes the left side
   and the bidding box the right, full height, with both hands still showing
   between them. Every rule is under html.phone-land, which also makes it win
   over the narrow-screen rules above that a small landscape phone matches. */

/* html.phone-land is set by the script when the table is laid out for a phone
   on its side: the phone really is landscape and under 500px tall, or it is
   held upright with "Turn the table sideways" on and the page is drawn turned
   (html.sideways, below). One set of rules serves both, which is why these are
   a class rather than a media query. */
html.phone-land { --view-h: 100dvh; }

/* The phone's safe areas - clear of the Dynamic Island, the rounded corners
   and the home bar - on the page's own four sides. env() reports them for the
   phone as it stands; when the page is turned they are swapped round (below). */
html.phone-land {
  --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);
}

html.phone-land {
  --room: calc(var(--view-h) - var(--bar-height, 36px) - var(--safe-b));
  --cw: calc(var(--room) * .21 * var(--card-scale));
  --ch: calc(var(--cw) * 1.4);
  --overlap-x: calc(var(--cw) * -0.7);
  --cw-top: calc(var(--room) * .15 * var(--card-scale));
  /* The trick takes what the two hands leave of the height. The top hand is
     about .21 of the room tall and the bottom one .235 (a fifth of it runs
     off the edge), plus labels and gaps; the trick is 1.3 cards tall. */
  --cw-trick: min(var(--cw), calc((var(--room) * (1 - .445 * var(--card-scale)) - 60px) / 1.85));
}

/* Step is in the panel's foot here, where the bar has no room for it. */
html.phone-land #btn-step { display: none; }

html.phone-land .settings-foot .phone-only { display: block; }

html.phone-land body { height: var(--view-h); overflow: hidden; }

html.phone-land .bar {
  grid-template-columns: auto auto minmax(0, 1fr) auto;
  grid-template-areas: "title controls info gear";
  gap: 4px 12px;
  padding: calc(4px + var(--safe-t)) calc(10px + var(--safe-r)) 4px calc(10px + var(--safe-l));
}

html.phone-land .bar h1 { font-size: 0; }

html.phone-land .bar h1 .pip { font-size: 18px; }

html.phone-land .controls { flex-wrap: nowrap; gap: 6px; }

html.phone-land .controls button { padding: 3px 10px; font-size: 13px; }

html.phone-land .gear { padding: 4px; }

/* The board's state, one line in the bar. */
html.phone-land .bar .info {
  grid-area: info;
  position: static;
  display: flex;
  align-items: baseline;
  gap: 0 10px;
  max-width: none;
  min-width: 0;
  padding: 0;
  overflow: hidden;
  background: none;
  font-size: 12px;
  line-height: 1.3;
  white-space: nowrap;
}

html.phone-land .bar .info > div { flex: none; }

/* Whose turn first, then the contract and tricks, the vulnerability, and the
   board last: if the line runs out, it is the least needed that goes. */
html.phone-land .bar .info .status { order: 1; }

html.phone-land .bar .info .contract { order: 2; }

html.phone-land .bar .info #tricks-row { order: 3; }

html.phone-land .bar .info .i-vul { order: 4; }

html.phone-land .bar .info .i-board { order: 5; }

html.phone-land .bar .info .k[data-short] { font-size: 0; }

html.phone-land .bar .info .k[data-short]::after { content: attr(data-short); font-size: 12px; }

html.phone-land .bar .info .contract { font-size: 13px; margin: 0; }

html.phone-land .bar .info .status { flex: none; min-height: 0; }

html.phone-land .bar .info .i-board { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; }

/* The felt runs to the screen's edges; what is on it keeps to the safe area. */
html.phone-land .layout { padding: 0; max-width: none; }

html.phone-land .table {
  height: calc(var(--view-h) - var(--bar-height, 36px));
  min-height: 0;
  padding: 4px calc(10px + var(--safe-r)) calc(4px + var(--safe-b)) calc(10px + var(--safe-l));
  gap: 4px 10px;
  border-radius: 0;
  box-shadow: inset 0 2px 30px rgb(0 0 0 / .35);
  grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
  grid-template-rows: auto minmax(0, 1fr) auto;
  grid-template-areas:
    "west north  east"
    "west centre east"
    "west south  east";
}

html.phone-land .label { font-size: calc(11px * var(--adorn, 1.25)); padding: 1px calc(8px * var(--adorn, 1.25)); }

html.phone-land .seat { gap: 3px; }

/* Partner at the smaller size. */
html.phone-land .seat[data-pos="2"] {
  --cw: var(--cw-top);
  --ch: calc(var(--cw-top) * 1.4);
  --overlap-x: calc(var(--cw-top) * -0.7);
}

/* The player's hand runs off the bottom edge by a fifth of a card. */
html.phone-land .seat[data-pos="0"] .hand { margin-bottom: calc(var(--ch) * -0.2); }

/* The trick as a flat diamond: the bottom card covers the lower seven
   tenths of the top one, which leaves the top card's index showing. */
html.phone-land .trick {
  --cw: var(--cw-trick);
  --ch: calc(var(--cw-trick) * 1.4);
  width: calc(var(--pw) * 3.4);
  height: calc(var(--ph) * 1.3);
}

html.phone-land .compass { display: none; }

/* The opponents, at the sides, beside the trick. */
html.phone-land .seat[data-pos="1"],
html.phone-land .seat[data-pos="3"] { align-self: center; }

html.phone-land .seat[data-pos="1"] { justify-self: end; }

html.phone-land .seat[data-pos="3"] { justify-self: start; }

html.phone-land .seat[data-pos="1"] .label,
html.phone-land .seat[data-pos="3"] .label { max-width: none; white-space: nowrap; }

html.phone-land .hand.mini { min-height: 0; min-width: 0; position: relative; align-items: center; gap: 6px; }

html.phone-land .mini .card { width: var(--cw-top); height: calc(var(--cw-top) * 1.4); }

html.phone-land .mini .count { font-size: 13px; font-weight: 600; color: var(--label); }

html.phone-land .suit-lines {
  display: grid;
  gap: 1px;
  padding: 5px 9px;
  border-radius: 8px;
  background: rgb(0 0 0 / .22);
  color: #E8EEEA;
  font-size: calc(14px * var(--pile, 1));
  font-weight: 600;
  line-height: 1.35;
  white-space: nowrap;
}

html.phone-land .suit-lines .glyph { margin: 0 5px 0 0; }

html.phone-land .suit-lines .void { color: var(--label); font-weight: 400; }

/* The auction: history on the left, the box on the right, full height;
   the middle stays open for the hands. */
html.phone-land .table.bidding .seat[data-pos="1"],
html.phone-land .table.bidding .seat[data-pos="3"] { visibility: hidden; }

/* Stretched over the whole table, the auction must let taps through between
   its two sides, to the hands and their gears; only the history and the box
   take them. */
html.phone-land .centre.bidding { grid-area: 1 / 1 / -1 / -1; z-index: 4; place-items: stretch; pointer-events: none; }

html.phone-land .auction-stage { justify-content: space-between; flex-wrap: nowrap; gap: 0; pointer-events: none; }

html.phone-land .auction-stage > * { pointer-events: auto; }

html.phone-land .auction-stage .auction-sheet { display: flex; padding: 6px; align-self: flex-start; max-height: 100%; overflow: auto; }

html.phone-land .auction-stage .ag { flex: none; grid-template-columns: repeat(4, minmax(36px, 44px)); grid-auto-rows: minmax(28px, auto); }

html.phone-land .auction-stage .ag-cell { min-height: 28px; padding: 0 2px; font-size: 13px; }

html.phone-land .auction-stage .ag-head { font-size: 11px; }

html.phone-land .bidbox { width: auto; padding: 6px; }

html.phone-land .bb-cols { grid-template-columns: repeat(3, 42px); grid-template-rows: repeat(7, minmax(18px, 1fr)); column-gap: 5px; row-gap: 4px; margin-bottom: 6px; }

html.phone-land .bb-cell { font-size: 14px; }

html.phone-land .bb-foot .bb-call,
html.phone-land .bb-foot .bb-alert,
html.phone-land .bb-foot .bb-hint { height: 32px; }

html.phone-land .bb-for { margin-bottom: 4px; padding: 2px 6px; font-size: 12px; }

/* --- Turned sideways --------------------------------------------------------
   A phone held upright, with "Turn the table sideways" on: the page is laid
   out as wide as the phone is tall and turned a quarter, so it reads the right
   way up with the phone held on its side. Safari cannot lock the orientation,
   and this works with Portrait Orientation Lock on, which many people leave on.
   The body is the page: fixed-position things inside it - the panel, a dragged
   card - are placed in its turned frame, and the script converts pointer and
   screen positions into that frame. */
html.sideways { --view-h: 100vw; overflow: hidden; }
/* Turned, the phone's top, right, bottom and left are other sides of the page. */
html.sideways.turn-left {
  --safe-l: env(safe-area-inset-top, 0px);
  --safe-r: env(safe-area-inset-bottom, 0px);
  --safe-t: env(safe-area-inset-right, 0px);
  --safe-b: env(safe-area-inset-left, 0px);
}
html.sideways.turn-right {
  --safe-l: env(safe-area-inset-bottom, 0px);
  --safe-r: env(safe-area-inset-top, 0px);
  --safe-t: env(safe-area-inset-left, 0px);
  --safe-b: env(safe-area-inset-right, 0px);
}
/* The panel keeps clear of the home bar and the corners too. */
html.phone-land .settings { padding-right: var(--safe-r); padding-bottom: var(--safe-b); }
html.sideways body {
  position: fixed;
  top: 0;
  left: 0;
  width: 100dvh;
  height: 100vw;
  min-height: 0;                  /* the page's own min-height is the upright phone's height */
  transform-origin: 0 0;
}
/* Top of the phone to the left - turned anticlockwise: the page's top must lie
   along what is then the top, the phone's right edge, so the page is turned a
   quarter clockwise and moved back across by the phone's width. */
html.sideways.turn-left body { transform: translateX(100vw) rotate(90deg); }
/* Top of the phone to the right - turned clockwise: the page's top lies along
   the phone's left edge. */
html.sideways.turn-right body { transform: translateY(100dvh) rotate(-90deg); }


/* --- The bidding sheet ------------------------------------------------------
   On a phone on its side the bidding box is three rows across the middle of
   the table, standing on the player's hand where the trick will be: levels,
   denominations, then the answers with Alert and the call. The script places
   it and sets the rows' height (--bb-row) from the room between the hands. */
html.phone-land .auction-stage .bidbox.sheet,
html.phone-up .auction-stage .bidbox.sheet {
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  display: block;
  padding: 6px;
}
.bb-sheet { display: grid; gap: 5px; }
.bb-line { display: flex; gap: 5px; height: var(--bb-row, 36px); }
.bb-line > * { flex: 1 1 0; min-width: 0; width: auto; height: 100%; margin: 0; }
.bb-line .bb-call { flex: 2 1 0; }
.bidbox.sheet .bb-for { margin-bottom: 5px; }

/* --- Touch ----------------------------------------------------------------
   A finger is not a mouse pointer: things to be tapped get room for one,
   about 40px, and the small gears keep their look with a bigger tap area
   round them. */
@media (pointer: coarse) {
  .hand-gear { position: relative; }
  .hand-gear::after { content: ""; position: absolute; inset: -10px; }
  .sort-pop button { min-height: 40px; }
  .sort-pop input[type="range"], .settings input[type="range"] { height: 32px; }
  .settings .check input { width: 22px; height: 22px; }
  .choice button { min-height: 40px; }
  .tabs button { min-height: 42px; }
  /* The tall bidding box, on a tablet. */
  .bb-cols { grid-template-rows: repeat(7, minmax(40px, 1fr)); }
  .bb-cell { min-height: 40px; }
  .bb-call, .bb-alert, .bb-hint { min-height: 44px; }
}
@media (pointer: coarse) {
  html.phone-land .controls button { min-height: 34px; }
  html.phone-land .gear { min-width: 36px; min-height: 36px; }
  /* The sheet's rows are already sized for a finger; the tall box's rules
     above are not for it. */
  html.phone-land .bb-cell { min-height: 0; }
  html.phone-land .bb-call, html.phone-land .bb-alert, html.phone-land .bb-hint { min-height: 0; }
}
/* No rubber-band bounce of a page that fits the screen. */
html.phone-land, html.phone-land body { overscroll-behavior: none; }

/* --- A phone held upright ---------------------------------------------------
   Portrait, under 500px wide, with "Turn the table sideways" off. Width is
   what runs out now, so the cards are sized from it and the page again never
   scrolls. The bar is the controls and the gear, with the board's state on a
   line under them. The player's hand runs across the bottom, the full width;
   partner is across the top, smaller; the trick is the usual cross in the
   middle, with the opponents either side of it drawn small - a back and a
   count, or their suits written out. In the auction the history stands in the
   middle and the bidding is the sheet of three rows, standing on the hand. */
html.phone-up {
  --view-h: 100dvh;
  --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);
  /* Thirteen cards across at about a third of a card each, with the suit gaps. */
  --cw: calc((100vw - var(--safe-l) - var(--safe-r) - 28px) / 5.1 * var(--card-scale));
  --ch: calc(var(--cw) * 1.4);
  --overlap-x: calc(var(--cw) * -0.7);
  --cw-top: calc(var(--cw) * .72);
}
/* The page fits the screen: neither it nor the document around it scrolls. */
html.phone-up, html.phone-up body, html.phone-land { overscroll-behavior: none; }
html.phone-up, html.phone-land { overflow: hidden; }
html.phone-up body { height: var(--view-h); overflow: hidden; }

html.phone-up .bar {
  grid-template-columns: auto minmax(0, 1fr) auto;
  grid-template-areas: "title controls gear" "info info info";
  gap: 2px 8px;
  padding: calc(4px + var(--safe-t)) calc(10px + var(--safe-r)) 4px calc(10px + var(--safe-l));
}
html.phone-up .bar h1 { font-size: 0; }
html.phone-up .bar h1 .pip { font-size: 18px; }
html.phone-up .controls { flex-wrap: nowrap; gap: 6px; }
html.phone-up .controls button { padding: 3px 10px; font-size: 13px; }
html.phone-up .gear { padding: 4px; }
html.phone-up #btn-step { display: none; }
html.phone-up .settings-foot .phone-only { display: block; }

/* The board's state, one line under the controls: whose turn first. */
html.phone-up .bar .info {
  grid-area: info;
  position: static;
  display: flex;
  align-items: baseline;
  gap: 0 10px;
  max-width: none;
  min-width: 0;
  padding: 0;
  overflow: hidden;
  background: none;
  font-size: 12px;
  line-height: 1.3;
  white-space: nowrap;
}
html.phone-up .bar .info > div { flex: none; }
html.phone-up .bar .info .status { order: 1; min-height: 0; }
html.phone-up .bar .info .contract { order: 2; font-size: 13px; margin: 0; }
html.phone-up .bar .info #tricks-row { order: 3; }
html.phone-up .bar .info .i-vul { order: 4; }
html.phone-up .bar .info .i-board { order: 5; flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
html.phone-up .bar .info .k[data-short] { font-size: 0; }
html.phone-up .bar .info .k[data-short]::after { content: attr(data-short); font-size: 12px; }

/* The felt to the screen's edges; what is on it inside the safe area. */
html.phone-up .layout { padding: 0; max-width: none; }
html.phone-up .table {
  height: calc(var(--view-h) - var(--bar-height, 60px));
  min-height: 0;
  padding: 4px calc(8px + var(--safe-r)) calc(4px + var(--safe-b)) calc(8px + var(--safe-l));
  gap: 4px 6px;
  border-radius: 0;
  box-shadow: inset 0 2px 30px rgb(0 0 0 / .35);
  grid-template-columns: auto minmax(0, 1fr) auto;
  grid-template-rows: auto minmax(0, 1fr) auto;
  grid-template-areas:
    "north north  north"
    "west  centre east"
    "south south  south";
}
html.phone-up .label { font-size: calc(11px * var(--adorn, 1.25)); padding: 1px calc(8px * var(--adorn, 1.25)); }
html.phone-up .seat { gap: 3px; }

/* Partner at the smaller size; the trick at the player's size, which the
   script brings down where it has to fit between the side hands or on a short
   screen. The player's hand runs off the bottom edge by a fifth of a card,
   the indices being at the top. */
html.phone-up .seat[data-pos="2"] {
  --cw: var(--cw-top);
  --ch: calc(var(--cw-top) * 1.4);
  --overlap-x: calc(var(--cw-top) * -0.7);
}
html.phone-up .seat[data-pos="0"] .hand { margin-bottom: calc(var(--ph) * -0.2); }

/* The opponents beside the trick, narrow: a back over its count, or the suits. */
html.phone-up .seat[data-pos="1"], html.phone-up .seat[data-pos="3"] { align-self: center; }
html.phone-up .seat[data-pos="1"] .label, html.phone-up .seat[data-pos="3"] .label { max-width: 76px; }
html.phone-up .hand.mini { min-height: 0; min-width: 0; flex-direction: column; align-items: center; gap: 2px; }
html.phone-up .mini .card { width: calc(var(--cw-top) * .8); height: calc(var(--cw-top) * 1.12); }
html.phone-up .mini .count { font-size: 12px; font-weight: 600; color: var(--label); }
html.phone-up .suit-lines {
  display: grid;
  gap: 0;
  padding: 4px 6px;
  border-radius: 8px;
  background: rgb(0 0 0 / .22);
  color: #E8EEEA;
  font-size: calc(12px * var(--pile, 1));
  font-weight: 600;
  line-height: 1.35;
  white-space: nowrap;
}
html.phone-up .suit-lines .glyph { margin: 0 4px 0 0; }
html.phone-up .suit-lines .void { color: var(--label); font-weight: 400; }

/* The auction: the side hands give way, the history stands in the middle,
   and the sheet stands on the hand (the script places it). */
html.phone-up .table.bidding .seat[data-pos="1"], html.phone-up .table.bidding .seat[data-pos="3"] { visibility: hidden; }
html.phone-up .centre.bidding { grid-column: 1 / -1; z-index: 4; place-items: stretch; pointer-events: none; }
html.phone-up .auction-stage { flex-direction: column; align-items: center; justify-content: flex-start; flex-wrap: nowrap; gap: 0; pointer-events: none; }
html.phone-up .auction-stage > * { pointer-events: auto; }
html.phone-up .auction-stage .auction-sheet { flex: none; padding: 6px; max-height: 100%; overflow: auto; }
html.phone-up .auction-stage .ag { flex: none; grid-template-columns: repeat(4, minmax(52px, 72px)); grid-auto-rows: minmax(24px, auto); }
html.phone-up .auction-stage .ag-cell { min-height: 24px; padding: 0 2px; font-size: 14px; }
html.phone-up .auction-stage .ag-head { font-size: 11px; }
html.phone-up .bb-for { margin-bottom: 4px; padding: 2px 6px; font-size: 12px; }

/* The sheet's rows are sized for a finger already. */
@media (pointer: coarse) {
  html.phone-up .controls button { min-height: 34px; }
  html.phone-up .gear { min-width: 36px; min-height: 36px; }
  html.phone-up .bb-cell, html.phone-up .bb-call, html.phone-up .bb-alert, html.phone-up .bb-hint { min-height: 0; }
}

/* --- System cards, in the panel's Systems tab ------------------------------ */
.syscard { padding: 4px 0 16px; border-bottom: 1px solid rgb(255 255 255 / .14); margin-bottom: 14px; }
.syscard:last-child { border-bottom: 0; }
.syscard-side { margin: 0; font-size: 12px; font-weight: 600; text-transform: uppercase; letter-spacing: .06em; color: var(--accent); }
.syscard h3 { margin: 2px 0 2px; font-size: 16px; }
.syscard-by { font-size: 12px; font-weight: 600; color: #A8C2B6; margin-left: 4px; }
.syscard h4 { margin: 12px 0 4px; font-size: 13px; color: #A8C2B6; }
.syscard-table { width: 100%; border-collapse: collapse; font-size: 13px; margin-top: 8px; }
.syscard-table th { text-align: left; vertical-align: top; width: 34%; padding: 4px 8px 4px 0; color: #A8C2B6; font-weight: 600; }
.syscard-table td { padding: 4px 0; border-bottom: 1px solid rgb(255 255 255 / .06); }
.syscard-list { margin: 0; padding-left: 18px; font-size: 13px; }
.syscard-list li { margin: 3px 0; }
.syscard-list b { color: #fff; }
/* A detail to be confirmed against the system's booklet. */
.sys-check { display: inline-block; margin-left: 4px; padding: 0 5px; border-radius: 4px; font-size: 11px; color: #1E2A30; background: var(--accent); }

/* --- Playing with others ------------------------------------------------- */

/* At a server's table the server keeps the clock: nothing is replayed,
   paused or stepped, and only the table's starter deals. */
body.remote .solo-only { display: none; }
body:not(.remote) .remote-only { display: none; }
/* Rebid and Replay: only at a social table, and only for its host. */
body:not(.remote.social.starter) .social-host-only { display: none; }

/* --- "Are you sure?" -------------------------------------------------------- */

.ask-veil { position: fixed; inset: 0; z-index: 60; display: flex; align-items: center; justify-content: center;
  padding: 16px; background: rgb(0 0 0 / .55); }
.ask-veil[hidden] { display: none; }
.ask-box { width: min(380px, 100%); padding: 18px 20px 16px; border-radius: 12px; border: 1px solid var(--rule);
  background: var(--chrome); color: var(--ink); box-shadow: 0 16px 40px rgb(0 0 0 / .5); }
.ask-box p { margin: 0 0 16px; font-size: 15px; line-height: 1.45; }
.ask-buttons { display: flex; justify-content: flex-end; gap: 10px; }
.ask-buttons button.danger { background: var(--red); border-color: var(--red); color: #1b1b1b; font-weight: 600; }

/* --- Chat ------------------------------------------------------------------ */

/* A drawer at the bottom right, over the felt's corner: it takes nothing from
   the table while it is shut, and a narrow slice while it is open. */
.chat { position: fixed; right: max(12px, env(safe-area-inset-right)); bottom: max(12px, env(safe-area-inset-bottom));
  z-index: 40; width: min(340px, calc(100vw - 24px)); max-height: min(70vh, 480px); display: flex; flex-direction: column;
  background: var(--chrome); color: var(--ink); border: 1px solid var(--rule); border-radius: 10px;
  box-shadow: 0 10px 30px rgb(0 0 0 / .45); }
.chat[hidden] { display: none; }
.chat-head { display: flex; align-items: center; justify-content: space-between; padding: 8px 12px; border-bottom: 1px solid var(--rule);
  cursor: move; user-select: none; touch-action: none; }
/* Moved or sized by the player, it is placed by left/top and a size of its own. */
.chat.placed { right: auto; bottom: auto; max-height: none; }
.chat.dragging { opacity: .92; box-shadow: 0 16px 40px rgb(0 0 0 / .55); }
/* The corner to size it by: two diagonal strokes, and a finger-sized area round them. */
.chat-grip { position: absolute; right: 0; bottom: 0; width: 22px; height: 22px; cursor: nwse-resize; touch-action: none;
  background: linear-gradient(135deg, transparent 55%, var(--ink-soft) 55%, var(--ink-soft) 62%, transparent 62%,
                                      transparent 72%, var(--ink-soft) 72%, var(--ink-soft) 79%, transparent 79%);
  border-bottom-right-radius: 10px; }
.chat-say { padding-right: 26px; }
.chat-head button { background: none; border: 0; color: var(--ink-soft); font-size: 20px; line-height: 1; cursor: pointer; padding: 0 4px; }
.chat-lines { list-style: none; margin: 0; padding: 8px 12px; overflow-y: auto; flex: 1 1 auto; min-height: 80px; font-size: 14px; }
.chat-lines li { margin: 0 0 6px; overflow-wrap: anywhere; }
.chat-lines .who { color: var(--accent); font-weight: 600; margin-right: 6px; }
.chat-lines .mine .who { color: #9FE3B5; }
.chat-lines .quick { font-size: 15px; }
.chat-lines .empty { color: var(--ink-soft); font-style: italic; }
.chat-quick { display: flex; flex-wrap: wrap; gap: 6px; padding: 8px 12px; border-top: 1px solid var(--rule); }
.chat-quick button { padding: 4px 8px; border-radius: 14px; font-size: 13px; }
.chat-say { display: flex; gap: 6px; padding: 0 12px 8px; }
.chat-say input { flex: 1 1 auto; min-width: 0; padding: 6px 8px; border-radius: 6px; border: 1px solid var(--rule);
  background: var(--chrome-2); color: var(--ink); font: inherit; }
.chat-note { margin: 0; padding: 0 12px 10px; font-size: 12px; color: var(--ink-soft); }
.chat-note:empty { display: none; }
#btn-chat .badge { display: inline-block; min-width: 18px; margin-left: 6px; padding: 0 5px; border-radius: 9px;
  background: var(--accent); color: #1b1b1b; font-size: 11px; font-weight: 700; line-height: 18px; text-align: center; }
#btn-chat .badge[hidden] { display: none; }
body.remote:not(.starter) .dealer-only { display: none; }
.players-note { color: var(--accent); }
.pl-actions { margin-top: 12px; flex-wrap: wrap; }
#players a.button { display: inline-flex; align-items: center; padding: 6px 12px; border-radius: 6px; color: inherit;
  text-decoration: none; border: 1px solid rgb(255 255 255 / .25); background: rgb(0 0 0 / .2); }
#banner a { display: block; margin-top: 6px; color: var(--accent); }
.pl-seat { display: flex; align-items: center; gap: 10px; padding: 6px 0; border-bottom: 1px solid rgb(255 255 255 / .12); }
.pl-name { width: 52px; font-weight: 600; }
.pl-who { flex: 1; color: #A8C2B6; }
.pl-kinds { display: inline-flex; gap: 4px; }
.pl-kinds button { padding: 3px 10px; }
.label .player { color: #F4E7C2; }
.label .player.open { color: #A8C2B6; font-style: italic; }
.link-status { padding: 6px 8px; border-radius: 6px; background: rgb(0 0 0 / .2); }
.link-status.network { color: #9FE3B5; }
.link-status.reconnecting, .link-status.failed { color: var(--accent); }

/* A notice from the club, at a server's table: in front of everything until it is read. */
dialog.notice {
  max-width: min(520px, calc(100vw - 32px)); width: 100%;
  background: var(--chrome); color: var(--ink); border: 1px solid var(--rule); border-radius: 12px; padding: 18px 20px;
  font: 15px/1.45 system-ui, sans-serif;
}
dialog.notice::backdrop { background: rgb(0 0 0 / .6); }
dialog.notice h2 { margin: 4px 0 10px; font-size: 19px; }
dialog.notice .notice-from, dialog.notice .notice-more { color: var(--ink-soft); font-size: 13px; margin: 0; }
dialog.notice .notice-text { white-space: pre-wrap; overflow-wrap: anywhere; margin: 0 0 12px; }
dialog.notice .notice-buttons { display: flex; justify-content: flex-end; margin-top: 12px; }
dialog.notice button { font: inherit; padding: 8px 16px; border-radius: 8px; border: 0; background: var(--accent); color: #1b1b1b; cursor: pointer; }

/* At a server's table, the title is the way back to its room. */
.bar h1 a.back-room { color: inherit; text-decoration: none; }
.bar h1 a.back-room:hover { text-decoration: underline; }

/* --- Looking through games (table.js) --------------------------------------
   The table on the left, and beside it the panel: which game, the steps
   through it, the auction at the top and the play below it, and playing on
   from where it stands. */
body.reviewing .layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr) min(380px, 36vw);
  gap: 14px;
  align-items: start;
  max-width: none;
}
.review {
  position: sticky;
  top: calc(var(--bar-height, 53px) + 16px);
  max-height: calc(100vh - var(--bar-height, 53px) - 32px);
  display: flex;
  flex-direction: column;
  background: var(--settings);
  color: #E8EEEA;
  border: 1px solid rgb(255 255 255 / .12);
  border-radius: 14px;
  box-shadow: 0 6px 24px rgb(0 0 0 / .4);
  overflow: hidden;
}
.review[hidden] { display: none; }
.review .pane-head { margin: 0; font-size: 16px; font-weight: 600; overflow-wrap: anywhere; }
.review .note { margin: 6px 0 0; font-size: 12px; color: #A8C2B6; }
.rv-head { padding: 12px 14px 10px; border-bottom: 1px solid rgb(255 255 255 / .12); }
.rv-games, .rv-steps { display: flex; gap: 6px; align-items: center; margin-top: 8px; }
.rv-games select { flex: 1; min-width: 0; margin: 0; }
.rv-games .note { margin: 0; white-space: nowrap; }
.rv-steps button { flex: 1; padding: 6px 4px; }
.rv-score { margin: 6px 0 0; font-size: 13px; font-weight: 600; color: #ffd966; }
.rv-score:empty { display: none; }
.rv-body { flex: 1; overflow: auto; overflow-x: hidden; padding: 10px 14px; }
.rv-body .auction-sheet { margin: 0 auto 10px; }
#rv-info p { margin: 8px 0 0; }
#rv-info ul { margin: 8px 0 0; padding-left: 18px; color: #ffcf8a; }
.rv-foot { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; padding: 10px 14px 12px; border-top: 1px solid rgb(255 255 255 / .12); }
.rv-foot label { font-size: 13px; }
.rv-foot select { margin: 0; }
/* What is still to come in the record is dimmed; the last call or card made is ringed. */
.ag-cell.ahead { opacity: .35; }
.pr-card.ahead { opacity: .35; }
.pr-card.at { outline: 2px solid gold; outline-offset: 1px; }
/* The board's box keeps to its usual size, clear of the top hand. */
body.reviewing .info { max-width: 200px; }
/* Nothing is dealt or played while a record is shown. */
body.reviewing .controls button { display: none; }
#auction-review { margin-top: 14px; }

/* Beside the panel the table is narrower than the window, so its cards are
   sized to the room the table has (the window less the panel's 380px and the
   gaps), not to the whole window - else the top hand runs under the board's box. */
@media (min-width: 1001px) {
  html:not(.phone-land):not(.phone-up) body.reviewing {
    --cw: calc(clamp(42px, (100vw - 430px) * .056, 88px) * var(--card-scale));
    --ch: calc(var(--cw) * 1.4);
    --overlap-x: calc(var(--cw) * -0.7);
    --overlap-y: calc(var(--ch) * -0.74);
  }
}

/* Narrower than that, the panel goes under the table, which keeps its width. */
@media (max-width: 1000px) {
  body.reviewing .layout { grid-template-columns: minmax(0, 1fr); }
  .review { position: static; max-height: none; }
}

/* On a phone the panel sits along the bottom, over the table. */
html.phone-land body.reviewing .layout, html.phone-up body.reviewing .layout { display: block; }
html.phone-land .review, html.phone-up .review {
  position: fixed; left: 0; right: 0; bottom: 0; top: auto; z-index: 15;
  max-height: none; border-radius: 14px 14px 0 0;
}
/* There the panel is only the steps: the auction and the play are on the gear's Auction tab. */
html.phone-land .rv-body, html.phone-up .rv-body { display: none; }
html.phone-land .rv-head, html.phone-up .rv-head { padding: 6px 10px; }
html.phone-land .rv-head .pane-head, html.phone-up .rv-head .pane-head, html.phone-land #rv-where { display: none; }
html.phone-land .rv-games, html.phone-land .rv-steps, html.phone-up .rv-games, html.phone-up .rv-steps { margin-top: 4px; }
html.phone-land .rv-steps button, html.phone-up .rv-steps button { padding: 3px 4px; }
html.phone-land .rv-foot, html.phone-up .rv-foot { padding: 6px 10px 8px; }
/* And one row: the game and the steps, then playing on. */
html.phone-land .review, html.phone-up .review { flex-direction: row; align-items: center; }
html.phone-land .rv-head, html.phone-up .rv-head { flex: 1; display: flex; gap: 8px; align-items: center; border-bottom: 0; min-width: 0; }
html.phone-land .rv-games, html.phone-up .rv-games { flex: 1; min-width: 0; margin: 0; }
html.phone-land .rv-steps, html.phone-up .rv-steps { flex: 1; margin: 0; }
html.phone-land .rv-foot, html.phone-up .rv-foot { border-top: 0; flex-wrap: nowrap; padding-left: 0; }
html.phone-land .rv-foot label, html.phone-up .rv-foot label, html.phone-up #rv-where,
html.phone-land .rv-score, html.phone-up .rv-score { display: none; }

/* --- A visitor's table of the day (/visit/play, table.js "Visitors") ------ */
body:not(.visitor) .visitor-only { display: none; }
body.visitor .not-visitor { display: none !important; }
.visit-note {
  position: absolute; left: 50%; top: 10px; transform: translateX(-50%); z-index: 6;
  max-width: min(560px, calc(100% - 28px)); padding: 10px 16px;
  background: rgb(8 61 40 / .95); color: #E8EEEA; border: 1px solid gold; border-radius: 10px;
  box-shadow: 0 6px 18px rgb(0 0 0 / .4); font-size: 14px; text-align: center;
}
.visit-note a { color: gold; font-weight: 600; }
.visit-note { cursor: pointer; }
.visit-note::after { content: " \00d7"; color: #A8C2B6; }
html.phone-land .visit-note, html.phone-up .visit-note { font-size: 12px; padding: 6px 10px; top: 4px; }
