/* YBC Play - table styling. Everything scoped under .ybc-play so the theme's
   Visual Cloak rules and the drills CSS can never reach in.

   Sizing responds to this element's own rendered width via container
   queries, not the browser viewport.

   Card dimensions and the square's size are CSS variables, set once per
   breakpoint. Everything else derives from them - the seat circles'
   positions come from the square's size, so the two can never drift
   apart, and every card everywhere is one single size. */

.ybc-play {
	--felt: #16263F;
	--panel: #1E3355;
	--gold: #C9A227;
	--paper: #FDFCF8;
	--ink: #16263F;
	--red: #B3261E;
	--baize: #0f5132;
	--muted: #9FB3D0;

	/* One card size for the whole table. Proportions are deliberately
	   tighter than before (height is 1.38x width, was ~1.48x) - less dead
	   space above and below the figures means a smaller card carries the
	   same size rank and pip, which is what makes a single size workable
	   for both a 13-card fan and a long suit row. */
	--card-w: 2.2rem;
	--card-h: 3.05rem;
	--card-font: 1.35rem;
	--card-pip: 1.15rem;
	--card-overlap: -0.35rem;
	--card-radius: 4px;

	/* The square scales with the table rather than being a fixed width -
	   at a fixed 21rem it was eating ~44% of the table at the narrow end
	   of the desktop band, squeezing West/East into ~10rem each. */
	--square-w: 13rem;
	--circle-size: 1.7rem;
	--circle-gap: 2.2rem;

	container-type: inline-size;
	container-name: ybcplay;

	max-width: 66rem;
	margin: 0 auto;
	font-family: inherit;
	color: #fff;

	/* Scroll anchoring is built for content growing around a reader who is
	   staying put. This widget is the opposite case: it tears itself down
	   and rebuilds wholesale, several times per tap, so the anchor node
	   the browser picked is destroyed each time and it re-aims at
	   something else. Inside a Tutor lesson, where the drill is most of
	   the page height, that produced a scroll position that wandered and
	   oscillated until the table was off-screen entirely.

	   The heights below are reserved so there is nothing to compensate for
	   in the first place; this line stops the browser trying even if some
	   future change does shift a few pixels. Both, deliberately - the
	   reservations are the fix, this is the guarantee. */
	overflow-anchor: none;
}

.ybc-play .ybc-play-loading,
.ybc-play-locked p {
	color: inherit;
	text-align: center;
	padding: 1.5rem 0;
	margin: 0;
}

.ybc-play-locked {
	color: var(--ink, #16263F);
}

/* ------------------------------------------------------- deal panel

   Each widget waits behind its own button, so a lesson holding several
   drills does not deal them all at page load. Deliberately understated
   and compact: on a lesson page this sits inline in the reading flow,
   several times over, and should read as part of the lesson rather than
   as a game demanding attention.

   The theme's "Visual Cloak" CSS styles buttons globally with
   !important, so every property here that matters is stated explicitly
   rather than inherited - the same lesson the drills plugin learned the
   hard way. */

.ybc-play-start {
	background: var(--baize);
	border: 8px solid var(--gold);
	border-radius: 22px;
	padding: 2.2rem 1.1rem;
	text-align: center;
}

.ybc-play .ybc-play-deal {
	background: var(--gold);
	color: var(--ink);
	border: 0;
	border-radius: 8px;
	padding: 0.7rem 1.6rem;
	font-family: inherit;
	font-size: 1rem;
	font-weight: 700;
	line-height: 1.2;
	cursor: pointer;
	text-transform: none;
	letter-spacing: normal;
}

.ybc-play .ybc-play-deal:hover,
.ybc-play .ybc-play-deal:focus {
	background: #DCB63F;
	color: var(--ink);
}

.ybc-play .ybc-play-deal[disabled] {
	opacity: 0.7;
	cursor: default;
}

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

.ybc-play-table {
	background: var(--baize);
	border: 8px solid var(--gold);
	border-radius: 22px;
	padding: 1.1rem;
}

/* Result screen: cards run flush to the panel's left and right edges, so
   West/East get the full width rather than losing it to padding. */
.ybc-play-table.is-result {
	padding-left: 0.25rem;
	padding-right: 0.25rem;
}

.ybc-play-head {
	display: flex;
	align-items: baseline;
	justify-content: space-between;
	gap: 0.5rem;
	padding: 0 0.25rem 0.6rem;
}

.ybc-play-endnow {
	display: block;
	margin: 0 0 0.6rem auto;
	font: inherit;
	font-size: 0.75rem;
	color: var(--muted);
	background: transparent;
	border: 1px solid var(--muted);
	border-radius: 999px;
	padding: 0.25rem 0.75rem;
	cursor: pointer;
}

.ybc-play-endnow:hover {
	color: #fff;
	border-color: #fff;
}

.ybc-play-endnow:disabled {
	opacity: 0.4;
	cursor: default;
}

.ybc-play-contract {
	font-size: 1.25rem;
	font-weight: 600;
	letter-spacing: 0.02em;
}

.ybc-play-meta {
	font-size: 0.8125rem;
	color: var(--muted);
	display: flex;
	gap: 0.9rem;
}

.ybc-play-meta strong {
	color: #fff;
	font-weight: 600;
}

.ybc-play-seat {
	font-size: 0.6875rem;
	color: var(--gold);
	letter-spacing: 0.12em;
	margin-bottom: 0.3rem;
	text-align: center;
}

.ybc-play-seat.is-active {
	color: #fff;
}

/* South's marker: a small circle plus a stretched pill reading "You",
   sitting between the square and South's own cards. */
.ybc-play-youbadge {
	display: flex;
	align-items: center;
	justify-content: center;
	margin: 0.4rem 0 0.9rem;
}

.ybc-play-youbadge .ybc-play-seatcircle {
	margin: 0;
	position: relative;
	z-index: 1;
}

.ybc-play-youpill {
	background: var(--gold);
	color: var(--ink);
	font-weight: 700;
	font-size: 0.85rem;
	padding: 0.3rem 1rem 0.3rem 1.3rem;
	border-radius: 999px;
	margin-left: -0.85rem;
}

.ybc-play-seatcircle {
	width: var(--circle-size);
	height: var(--circle-size);
	border-radius: 50%;
	background: #fff;
	color: var(--red);
	font-weight: 700;
	font-size: 0.85rem;
	display: flex;
	align-items: center;
	justify-content: center;
	flex-shrink: 0;
	margin: 0.9rem auto 0;
}

.ybc-play-north.is-active .ybc-play-seatcircle {
	box-shadow: 0 0 0 3px var(--gold);
}

.ybc-play-west .ybc-play-seatcircle,
.ybc-play-east .ybc-play-seatcircle {
	margin: 0;
}

.ybc-play-north,
.ybc-play-south {
	text-align: center;
}

.ybc-play-west,
.ybc-play-east {
	display: flex;
	flex-direction: row;
	align-items: center;
	justify-content: space-between;
	gap: 1.1rem;
}

/* Live play's middle row uses the same three-track pattern as the result
   grid: equal minmax(0, 1fr) tracks either side of an auto-sized square,
   so the square is centred by construction here too. Previously this was
   a centred flex row, which clustered West, the square and East in the
   middle and left large empty margins outside them on a wide table.

   Within each side track the seat block spreads (space-between), pushing
   the card-back stack out toward the table edge while its seat circle
   stays tucked against the square - which is what fills the space the
   old layout was wasting. */
.ybc-play-middle {
	display: grid;
	grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
	align-items: center;
	column-gap: 0.4rem;
	margin: 0.25rem 0;
	min-height: var(--square-w);
}

.ybc-play-centre {
	position: relative;
	flex: 0 0 auto;
	align-self: center;
	width: var(--square-w);
	aspect-ratio: 1 / 1;
	border: 9px solid var(--gold);
	border-radius: 18px;
	display: flex;
	align-items: center;
	justify-content: center;
	padding: 0.5rem;
	text-align: center;
}

/* ------------------------------------------------- result screen layout
   One CSS Grid, five columns:

     [west cards] [W circle] [square] [E circle] [east cards]

   The two card columns are equal 1fr tracks, so the square is dead
   centre BY CONSTRUCTION - no calculation, no measurement, and nothing
   West or East contain can move it. The circles are ordinary grid items
   either side of the square, so they track it automatically.

   This replaced an absolutely-positioned layout whose circle offsets
   were calc() arithmetic over a clamp(), plus a separate flex fallback
   below the desktop breakpoint. The seam between those two modes is what
   came apart at intermediate widths. There is no seam here - the same
   grid restacks to one column on a narrow screen (below), so there is no
   mode to switch between. */

.ybc-play-resultgrid {
	display: grid;
	/* minmax(0, 1fr), NOT 1fr: plain 1fr means minmax(auto, 1fr), whose
	   auto minimum stops a track shrinking below its content's
	   min-content width. A long suit would then widen its own track,
	   the two side tracks would stop being equal, and the square would
	   drift off centre - defeating the whole point of this grid. The 0
	   minimum lets the tracks stay equal and lets the JS safety net
	   compress an overlong row instead. */
	grid-template-columns: minmax(0, 1fr) auto auto auto minmax(0, 1fr);
	align-items: center;
	column-gap: 0.6rem;
	margin: 0.5rem 0;
}

/* min-width: 0 lets a long suit row shrink inside its track rather than
   forcing the track wider (which is what would push the square off
   centre).

   Deliberately NO justify-self here: that would shrink the item to its
   content width, and the JS safety net measures this element to learn how
   much room the grid gave it. Shrink-to-fit meant it measured the
   overflowing content instead of the track and concluded everything fit,
   so compression never ran. Stretching (the default) makes the measurement
   the track width, which is what it needs. The rows inside hug the centre
   via their own justify-content. */
.ybc-play-rg-west,
.ybc-play-rg-east {
	min-width: 0;
}

.ybc-play-waiting {
	color: var(--muted);
	font-size: 0.875rem;
	margin: 0;
	line-height: 1.4;
}

/* ----------------------------------------------------------- card faces
   One size everywhere, from the variables above. Legality is the
   server's job, so every card looks the same whether or not it can be
   played right now. */

.ybc-play-hand {
	display: flex;
	justify-content: center;
	padding-top: 0.15rem;
	min-width: var(--card-w);
	min-height: var(--card-h);
}

.ybc-play-card {
	width: var(--card-w);
	height: var(--card-h);
	flex: 0 0 auto;
	background: var(--paper);
	border: 1px solid #C9C4B6;
	border-radius: var(--card-radius);
	margin-left: var(--card-overlap);
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	line-height: 1;
	font-size: var(--card-font);
	font-weight: 700;
	color: var(--ink);
}

.ybc-play-card:first-child {
	margin-left: 0;
}

.ybc-play-card.is-red {
	color: var(--red);
}

.ybc-play-card .ybc-play-pip {
	font-size: var(--card-pip);
}

.ybc-play-card.is-gap {
	margin-left: 0.3rem;
}

.ybc-play-card.is-active-hand {
	cursor: pointer;
}

.ybc-play-card.is-active-hand:focus-visible {
	outline: 2px solid var(--gold);
	outline-offset: 2px;
}

/* Fixed compass positions for the trick in progress - each card is pinned
   independently to the centre box, so one appearing or disappearing never
   shifts any other. Offsets derive from the square's own size, so they
   stay correct as it scales. */
.ybc-play-trickgrid {
	position: absolute;
	inset: 0;
}

.ybc-play-card.trick-pos-n,
.ybc-play-card.trick-pos-s {
	position: absolute;
	left: 50%;
	margin-left: 0;
	transform: translateX(-50%);
}

.ybc-play-card.trick-pos-n {
	top: 0.6rem;
}

.ybc-play-card.trick-pos-s {
	bottom: 0.6rem;
}

.ybc-play-card.trick-pos-e,
.ybc-play-card.trick-pos-w {
	position: absolute;
	top: 50%;
	margin-left: 0;
	transform: translateY(-50%);
}

.ybc-play-card.trick-pos-e {
	right: 0.6rem;
}

.ybc-play-card.trick-pos-w {
	left: 0.6rem;
}

/* ----------------------------------------------------------- card backs
   A light cream/tan landscape (sideways) shape, softly patterned. */

/* North's row of backs. The side strips got a minimum size long ago,
   when West and East emptying mid-hand was found to collapse their
   containers; the top row never did, so North playing its LAST card
   dropped the widget's height and shifted the page. Same fault, same
   remedy - and the one row where it had not been applied. */
.ybc-play-backs {
	display: flex;
	justify-content: center;
	min-height: var(--card-h);
}

.ybc-play-backs.is-side {
	flex-direction: column;
	align-items: center;
	min-width: var(--card-h);
	min-height: var(--card-w);
}

.ybc-play-back {
	width: var(--card-w);
	height: var(--card-h);
	background-color: #E7D4A1;
	background-image:
		repeating-linear-gradient(45deg, rgba(255, 255, 255, 0.45) 0 3px, transparent 3px 13px),
		repeating-linear-gradient(-45deg, rgba(255, 255, 255, 0.45) 0 3px, transparent 3px 13px);
	border: 2px solid var(--gold);
	border-radius: var(--card-radius);
	box-shadow: inset 0 0 0 2px rgba(255, 255, 255, 0.5);
	margin-left: var(--card-overlap);
	flex-shrink: 0;
}

.ybc-play-back:first-child {
	margin-left: 0;
}

.ybc-play-backs.is-side .ybc-play-back {
	width: var(--card-h);
	height: var(--card-w);
	margin-left: 0;
	margin-top: calc(var(--card-w) * -0.67);
}

.ybc-play-backs.is-side .ybc-play-back:first-child {
	margin-top: 0;
}

/* --------------------------------------------------------------- coach */

.ybc-play-coach {
	background: var(--panel);
	border-left: 3px solid var(--gold);
	border-radius: 0 6px 6px 0;
	padding: 0.6rem 0.75rem;
	margin-top: 0.6rem;
	font-size: 0.875rem;
	line-height: 1.45;
	min-height: 2.9em;
}

.ybc-play-lasttrick {
	color: #fff;
	font-size: 1rem;
	text-align: center;
	margin: 0.6rem 0 0;
	line-height: 1.35;
	min-height: 2.7em;
}

/* ------------------------------------------------ message surfaces

   All three of these keep their space whether or not they have anything
   to say. An element that appears and disappears changes the widget's
   height, and a widget that changes height makes the page scroll away
   from the table on every tap (see the root rule above).

   Two consequences worth knowing before editing any of them:

   - is-empty hides with visibility, NOT display:none. display:none would
     take the space back and reintroduce exactly the bug.
   - The reserved heights are sized for TWO lines of their own font size.
     A message long enough to wrap onto a third line grows the widget
     again. Keep messages short, and if a longer one is genuinely needed,
     raise the reservation here rather than letting it overflow.
   - Every reservation is in em, NOT rem, and equals line-height x 2. That
     is deliberate and load-bearing: six responsive tiers further down
     this file change the font-size of these three elements, and a rem
     value would stay put while the text around it grew - stale at four
     of the seven widths, which is precisely the "one fact, two copies,
     one of them drifts" failure this codebase keeps hitting. em resolves
     against the element's own font-size, so a tier that changes the font
     changes the reservation with it and there is only ever one number to
     keep right. If you add a tier, set font-size only and leave these
     alone. */

/* The follow-suit notice. Blue, deliberately not red: playing the wrong
   suit while you are still learning the one rule is an expected part of
   the drill, not an error, and this message fires a lot.

   Near-white text on a SOLID blue fill. Two earlier attempts used a tinted
   background with coloured text and both came back as unreadable - a tint
   over a dark panel leaves very little contrast, and the text colour was
   doing the work a background should do. #FFFFFF on #1D4E89 is roughly
   8:1, which clears WCAG AA for body text with room to spare and does not
   depend on judging a hue by eye.

   :empty hides the box without reclaiming its space - the reservation
   still applies, so an arriving message never shifts the page. */
.ybc-play-status {
	color: #FFFFFF;
	background: #1D4E89;
	border: 0;
	border-left: 5px solid #7FB2F0;
	border-radius: 0 6px 6px 0;
	font-size: 1rem;
	font-weight: 600;
	text-align: left;
	padding: 0.6rem 0.75rem;
	margin: 0.6rem 0 0;
	line-height: 1.35;
	min-height: 2.7em;
}

.ybc-play-status:empty {
	visibility: hidden;
}

/* Lesson notes: one panel at the end of a hand. What happened in this
   deal first, then the standing lesson text. */
.ybc-play-notes {
	margin-top: 0.8rem;
}

/* Quiet grey-blue label, as on the Bridge IQ cards. Gold on dark green is
   the TABLE's language; these panels are not the table. */
.ybc-play-notes-title {
	font-size: 0.8125rem;
	font-weight: 700;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: #5A6B7C;
	margin-bottom: 0.5rem;
}

.ybc-play-notes p {
	margin: 0 0 0.7rem;
	font-size: 1rem;
	line-height: 1.6;
	color: var(--ink);
	/* The panel spans the full table width, which on a desktop is well
	   over 100 characters a line. Comfortable reading is 65-75, so the
	   text is capped independently of the panel it sits in. */
	max-width: 42em;
}

/* A second heading inside the same panel needs air above it. */
.ybc-play-notes-title.is-second {
	margin-top: 0.9rem;
}

.ybc-play-notes p:last-child {
	margin-bottom: 0;
}

.ybc-play-setdone {
	color: var(--muted);
	font-size: 0.875rem;
	margin: 0;
	align-self: center;
}

/* The winning card, during the pause between tricks.

   Everything here stays INSIDE the card's own box. An earlier version
   scaled the card up and raised it, which read as the card jumping -
   West and East appeared to drop, North and South to slide right. Scale
   grows a card about its centre, so in a grid of four it looks like
   movement even though no sibling has shifted.

   So: an inset ring in the card's white space and a warm tint, with one
   short pulse of the ring. No transform, no z-index, no change of size -
   nothing that can move anything. */
.ybc-play-card.is-trick-winner {
	box-shadow: inset 0 0 0 4px var(--gold);
	background-color: #FFF6DC;
	animation: ybc-play-winpulse 0.55s ease-out 1;
}

@keyframes ybc-play-winpulse {
	0%   { box-shadow: inset 0 0 0 0 var(--gold); }
	55%  { box-shadow: inset 0 0 0 7px var(--gold); }
	100% { box-shadow: inset 0 0 0 4px var(--gold); }
}

/* Anyone who has asked not to see motion gets the ring without the
   pulse - the card is still unmistakably marked. */
@media (prefers-reduced-motion: reduce) {
	.ybc-play-card.is-trick-winner {
		animation: none;
	}
}

.ybc-play-debug {
	font-family: ui-monospace, Menlo, Consolas, monospace;
	font-size: 0.75rem;
	line-height: 1.4;
	color: var(--gold);
	background: rgba(0, 0, 0, 0.35);
	border-radius: 6px;
	padding: 0.4rem 0.5rem;
	margin: 0.6rem 0 0;
	text-align: center;
	word-break: break-all;
}

.ybc-play-lasttrick.is-empty,
.ybc-play-coach.is-empty {
	visibility: hidden;
}

/* ------------------------------------------------------ end-of-hand result */

.ybc-play-centre-message {
	text-align: center;
	padding: 0 0.4rem;
}

.ybc-play-result-headline {
	font-size: 0.9375rem;
	font-weight: 600;
	color: #fff;
	line-height: 1.25;
}

.ybc-play-result-sub {
	font-size: 0.6875rem;
	color: var(--muted);
	margin-top: 0.35rem;
	line-height: 1.35;
}

.ybc-play-result-hand {
	text-align: center;
}

.ybc-play-side-suits {
	display: flex;
	flex-direction: column;
	gap: 0.3rem;
}

.ybc-play-side-suit-row {
	display: flex;
	justify-content: flex-start;
}

.ybc-play-side-suit-row.is-end {
	justify-content: flex-end;
}

.ybc-play-result-buttons {
	display: flex;
	gap: 0.5rem;
	margin-top: 0.75rem;
}

.ybc-play-result-buttons button {
	flex: 1;
	font: inherit;
	font-size: 0.8125rem;
	padding: 0.6rem 0;
	border-radius: 8px;
	border: 1px solid #C9C4B6;
	background: var(--paper);
	color: var(--ink);
	cursor: pointer;
}

.ybc-play-result-buttons button.is-primary {
	background: var(--gold);
	color: var(--ink);
	border-color: var(--gold);
	font-weight: 600;
}

/* ----------------------------------------------------- container queries
   NOTE: these tiers set their variables on .ybc-play-TABLE, not on
   .ybc-play. .ybc-play is the query container, and a size container query
   cannot style its own container - it would be circular. Writing these as
   `.ybc-play { --card-w: ... }` makes the whole tier silently inert, which
   is exactly what happened between v0.19.0 and v0.21.0: every size fell
   back to the base values with no error anywhere. The table is a
   descendant, so it can be styled, and everything that uses these
   variables lives inside it. */

/* Below ~44rem the square has to give up room or the side tracks can't
   hold a realistic suit even compressed. It stays centred either way -
   the grid guarantees that - so shrinking it here costs nothing
   structural and buys the side hands several cards of headroom. */
@container ybcplay (max-width: 43.9rem) {
	.ybc-play-table {
		--square-w: 12rem;
	}
}
/* Narrow screens: the SAME grid restacks to a single column - the side
   hands sit above and below the square, each with its circle. This is a
   different column count, not a different layout mechanism, so there is
   no handover between two systems that can disagree. Grid areas keep the
   reading order sensible (west, square, east) regardless. */
@container ybcplay (max-width: 35.9rem) {
	/* Mobile: East and West turn side-on - each hand becomes a single
	   vertical strip of landscape cards down its edge, the way IntoBridge
	   handles the same problem. That is what lets the five-column grid
	   survive at phone width: a 13-card hand needs no horizontal room at
	   all, so the square stays genuinely centred instead of everything
	   stacking into a tall column.

	   The cards are landscape but their figures are NOT rotated - rank and
	   pip sit side by side, upright, in the top-left corner. Two reasons:
	   our figures are centre-indexed, so a rotated card would read
	   sideways; and stacking vertically means each card only shows its top
	   sliver, so the figures have to live in that sliver to be visible at
	   all. That is also how a real fanned hand shows its index. */
	.ybc-play-rg-west .ybc-play-side-suit-row,
	.ybc-play-rg-east .ybc-play-side-suit-row {
		flex-direction: column;
		align-items: flex-start;
	}

	.ybc-play-rg-west .ybc-play-card,
	.ybc-play-rg-east .ybc-play-card {
		width: var(--card-h);
		height: var(--card-w);
		flex-direction: row;
		align-items: flex-start;
		justify-content: flex-start;
		gap: 0.15rem;
		padding: 0.1rem 0 0 0.2rem;
		margin-left: 0;
		margin-top: calc(var(--card-w) * -0.45);
		font-size: calc(var(--card-font) * 0.75);
		line-height: 1;
	}

	.ybc-play-rg-west .ybc-play-card:first-child,
	.ybc-play-rg-east .ybc-play-card:first-child {
		margin-top: 0;
	}

	.ybc-play-rg-west .ybc-play-card .ybc-play-pip,
	.ybc-play-rg-east .ybc-play-card .ybc-play-pip {
		font-size: calc(var(--card-pip) * 0.75);
	}

	/* "10" is two characters wide, so it pushed its suit pip right and made
	   those cards read differently from the rest. Giving the rank a fixed
	   width puts every pip at the same offset regardless of the rank. */
	.ybc-play-rg-west .ybc-play-card > span:first-child,
	.ybc-play-rg-east .ybc-play-card > span:first-child {
		min-width: 1.3em;
		text-align: center;
	}

	/* Three-class specificity so this beats the base .ybc-play-card:first-child
	   rule (two classes), which was still applying its own horizontal margin
	   to the first card of each suit and knocking it out of line with the
	   rest of the strip. */
	.ybc-play-rg-west .ybc-play-side-suit-row .ybc-play-card,
	.ybc-play-rg-east .ybc-play-side-suit-row .ybc-play-card {
		margin-left: 0;
	}

	/* Alignment is set on each CARD (align-self), not left to the row's
	   align-items. Relying on the container left East's first card of each
	   suit sitting out of line while West - which aligns the other way -
	   was fine. align-self on the item itself wins over any container
	   alignment, so every card lines up regardless of what else is trying
	   to position it. */
	/* East uses the SAME alignment as West (flush right) rather than
	   mirroring it. Mirroring is what the design wants, but the
	   left-aligned arrangement kept leaving East's first card of each suit
	   out of line, through some mechanism I could not identify without
	   being able to inspect the page - and align-self on the cards did not
	   override it, which rules out ordinary container alignment. West's
	   right-aligned arrangement has been correct throughout, so both
	   strips now use it. A tidy strip on the wrong side of its track beats
	   a ragged one on the right side; the visual difference is small since
	   the track is barely wider than a card. */
	.ybc-play-rg-east .ybc-play-side-suit-row {
		align-items: flex-end;
	}

	.ybc-play-rg-east .ybc-play-side-suit-row .ybc-play-card {
		align-self: flex-end;
	}

	.ybc-play-rg-west .ybc-play-side-suit-row .ybc-play-card {
		align-self: flex-end;
	}

	/* Each strip hugs the square. */
	.ybc-play-rg-west .ybc-play-side-suit-row {
		align-items: flex-end;
	}
}
/* Phone widths. Two things overflow here without their own tier: the
   three-track live-play row (square plus both opponents' stacks), and
   North/South's own 13-card fan, which at the next size up is wider than
   the screen on its own.

   Card overlap is kept near zero here deliberately: our rank and pip sit
   in the CENTRE of the card, so overlapping hides the only information
   on it. A narrow card at full visibility beats a wider card with its
   middle covered. 13 cards at this size come to ~21.5rem, inside a
   typical ~23rem phone container. */
@container ybcplay (max-width: 25.9rem) {
	.ybc-play-table {
		--card-w: 2rem;
		--card-h: 2.76rem;
		--card-font: 1.25rem;
		--card-pip: 1.05rem;
		--card-overlap: -0.3rem;
		--square-w: 9rem;
		--circle-size: 1.4rem;
	}

	.ybc-play-table {
		padding: 0.5rem;
		border-width: 5px;
	}

	.ybc-play-west,
	.ybc-play-east {
		gap: 0.35rem;
	}

	.ybc-play-centre {
		border-width: 5px;
		border-radius: 12px;
		padding: 0.25rem;
	}

	.ybc-play-youpill {
		font-size: 0.75rem;
		padding: 0.25rem 0.7rem 0.25rem 1rem;
	}

	.ybc-play-status {
		font-size: 1rem;
	}

	.ybc-play-lasttrick {
		font-size: 0.875rem;
	}
}
/* Smallest phones (~320px). A 13-card fan at the tier above is 21.5rem,
   which overflows a ~20rem container, so cards step down once more. */
@container ybcplay (max-width: 21.4rem) {
	.ybc-play-table {
		--card-w: 1.6rem;
		--card-h: 2.2rem;
		--card-font: 1rem;
		--card-pip: 0.85rem;
		--card-overlap: -0.25rem;
		--square-w: 8rem;
		--circle-size: 1.25rem;
	}
}

@container ybcplay (min-width: 30rem) {
	.ybc-play-table {
		--card-w: 2.5rem;
		--card-h: 3.45rem;
		--card-font: 1.5rem;
		--card-pip: 1.3rem;
		--card-overlap: -0.4rem;
		--square-w: 15rem;
	}
}

@container ybcplay (min-width: 48rem) {
	.ybc-play-table {
		--card-w: 2.8rem;
		--card-h: 3.85rem;
		--card-font: 1.75rem;
		--card-pip: 1.5rem;
		--card-overlap: -0.5rem;
		--card-radius: 6px;
		--circle-size: 2.1rem;
		--circle-gap: 2.6rem;
		/* Scales with the table, with a floor so the trick cards inside it
		   always have room. */
		--square-w: 19rem;
	}

	.ybc-play-table {
		padding: 1.5rem 1.75rem;
	}

	.ybc-play-table.is-result {
		padding-left: 0.5rem;
		padding-right: 0.5rem;
	}

	.ybc-play-contract {
		font-size: 1.625rem;
	}

	.ybc-play-meta {
		font-size: 0.9375rem;
		gap: 1.25rem;
	}

	.ybc-play-seat {
		font-size: 0.75rem;
		margin-bottom: 0.5rem;
	}

	.ybc-play-seatcircle {
		font-size: 1rem;
	}

	.ybc-play-middle {
		margin: 1.1rem 0;
		gap: 1.5rem;
	}

	.ybc-play-centre {
		padding: 0.9rem;
	}

	.ybc-play-waiting {
		font-size: 0.9375rem;
	}

	.ybc-play-coach {
		font-size: 0.9375rem;
		padding: 0.9rem 1.1rem;
		margin-top: 0.9rem;
	}

	.ybc-play-lasttrick {
		font-size: 1.1875rem;
	}

	.ybc-play-status {
		font-size: 1.375rem;
	}

	.ybc-play-result-headline {
		font-size: 1.25rem;
	}

	.ybc-play-result-sub {
		font-size: 0.875rem;
	}

	/* Result grid at desktop width: roomier gaps. The column structure
	   itself needs no change - it is the same grid at every width. */
	.ybc-play-resultgrid {
		column-gap: 1rem;
		margin: 1.1rem 0;
	}
}

@container ybcplay (min-width: 72rem) {
	.ybc-play-table {
		--card-w: 3.2rem;
		--card-h: 4.4rem;
		--card-font: 2.05rem;
		--card-pip: 1.75rem;
		--card-overlap: -0.6rem;
		--square-w: 22rem;
	}

	.ybc-play-table {
		padding: 2rem 2.25rem;
	}

	.ybc-play-table.is-result {
		padding-left: 0.5rem;
		padding-right: 0.5rem;
	}

	.ybc-play-contract {
		font-size: 1.875rem;
	}

	.ybc-play-result-headline {
		font-size: 1.375rem;
	}

	.ybc-play-result-sub {
		font-size: 0.9375rem;
	}
}

/* Server-side diagnostic block, only rendered under debug="1". Sits
   outside .ybc-play so it survives even when the widget itself fails
   to resolve a deal - the case where it is most needed. */
.ybc-play-diag {
	font-family: ui-monospace, Menlo, Consolas, monospace;
	font-size: 0.75rem;
	line-height: 1.5;
	white-space: pre-wrap;
	word-break: break-all;
	background: #16263F;
	color: #C9A227;
	border: 1px solid #C9A227;
	border-radius: 6px;
	padding: 0.7rem 0.85rem;
	margin: 0 0 0.8rem;
}

/* ------------------------------------------- MiniBridge decisions

   The audit and the contract panels, shown under the table so the
   student can still see the cards they are being asked about. Buttons
   are stated explicitly rather than inherited, because the theme's
   "Visual Cloak" CSS styles buttons globally with !important. */

.ybc-play-decide {
	background: var(--panel);
	border-left: 3px solid var(--gold);
	border-radius: 0 8px 8px 0;
	padding: 0.85rem 1rem;
	margin-top: 0.7rem;
}

.ybc-play-decide-step {
	font-size: 0.75rem;
	font-weight: 700;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: var(--gold);
	margin-bottom: 0.5rem;
}

.ybc-play-decide p {
	margin: 0 0 0.6rem;
	font-size: 0.9375rem;
	line-height: 1.55;
	color: #fff;
}

.ybc-play-decide-q {
	font-weight: 700;
}

.ybc-play-decide-row {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 0.4rem;
	margin-bottom: 0.45rem;
}

.ybc-play-decide-label {
	font-size: 0.875rem;
	font-weight: 700;
	color: #fff;
	min-width: 6.5rem;
}

.ybc-play .ybc-play-choice {
	background: var(--gold);
	color: var(--ink);
	border: 0;
	border-radius: 7px;
	padding: 0.45rem 0.9rem;
	font-family: inherit;
	font-size: 1rem;
	font-weight: 700;
	line-height: 1.2;
	cursor: pointer;
	text-transform: none;
	letter-spacing: normal;
	min-width: 3rem;
}

.ybc-play .ybc-play-choice.is-red {
	color: #B00020;
}

.ybc-play .ybc-play-choice:hover:not([disabled]),
.ybc-play .ybc-play-choice:focus:not([disabled]) {
	background: #DCB63F;
}

.ybc-play .ybc-play-choice[disabled] {
	opacity: 0.45;
	cursor: default;
}

/* The audit panel sits above the table, so it needs a bottom margin
   rather than a top one. */
.ybc-play-decide.is-above {
	margin-top: 0;
	margin-bottom: 0.7rem;
}

/* The steps the student did not have to do. Quieter than the rest of the
   panel - it is context, not an instruction. */
.ybc-play-decide-passed {
	color: var(--muted);
	font-size: 0.875rem;
	font-style: italic;
}

/* ------------------------------------- reading panels

   The two panels the student READS rather than plays: the set-up text
   above the table and the lesson notes below it. Both sit outside the
   green baize, on the page background, so they are free to use the same
   treatment as the Bridge IQ search results - dark text on an off-white
   card with a thin border and a green accent down the left.

   Why light rather than the table's own palette: 95% of the readership
   is over 65, and these are the parts they sit and read rather than
   glance at. Dark navy on off-white is roughly 14:1, against about 8:1
   for white on the dark panel - both pass AA, the light version clears
   AAA at any size. Body text is 1rem at line-height 1.6 for the same
   reason.

   Everything inside the baize stays dark. The cards, the seat circles,
   the trick square and the contract header read as the table, and the
   table is not a document. The follow-suit notice stays white on blue
   too: it interrupts play and is meant to be loud. */
.ybc-play-auction,
.ybc-play-notes {
	background: #F6F8F6;
	border: 1px solid #DCE4DC;
	border-left: 4px solid var(--baize);
	border-radius: 0 8px 8px 0;
	color: var(--ink);
	font-size: 1rem;
	line-height: 1.6;
	padding: 0.9rem 1.1rem;
}

.ybc-play-auction {
	margin-bottom: 0.7rem;
}

.ybc-play-auction p {
	margin: 0 0 0.7rem;
}

.ybc-play-auction p:last-child {
	margin-bottom: 0;
}


/* Dummy fanned on a side strip, during play.

   The result screen's side-hand renderer is reused here, but the two
   containers are nothing alike: on the result screen it sits in a grid
   column sized for a full hand, while the live table's side strip is a
   flex row sized for a compact stack of backs. Nothing constrained its
   width, so a seven-card suit ran out under the seat circle and over the
   square's border.

   Overlapping leftwards fixes it, and ranks sit at the top-left of a card
   face so every rank stays readable with only the right edge covered.

   From the FOURTH card. Two earlier thresholds were wrong in opposite
   directions: every card (a two-card suit showed a sliver and then the
   second card on top of it), then the sixth - read off a screenshot where
   five cards happened to reach the square's border and looked like they
   fitted. They did not; five pushed the seat circle into the border. A
   four-card suit is the widest that sits comfortably, so that is where
   the fan starts.

   One threshold for every width that lays the strip out horizontally.
   Below 35.9rem the question does not arise: that tier turns the strips
   side-on and a thirteen-card hand needs no horizontal room at all.

   Scaling the cards down instead is not an option: the stylesheet warns
   that overriding --card-w silently disables a responsive tier. */
.ybc-play-west.is-dummy .ybc-play-side-suit-row .ybc-play-card:nth-child(n+4),
.ybc-play-east.is-dummy .ybc-play-side-suit-row .ybc-play-card:nth-child(n+4) {
	margin-left: calc(var(--card-w) * -0.5);
}

/* Later cards sit on top of earlier ones, so the fan reads left to right
   with each rank visible at the left edge of its card. */
.ybc-play-west.is-dummy .ybc-play-side-suit-row,
.ybc-play-east.is-dummy .ybc-play-side-suit-row {
	justify-content: flex-start;
}

.ybc-play-west.is-dummy .ybc-play-side-suit-row .ybc-play-card {
	position: relative;
}

/* ------------------------------------------------- the auction

   The record sits in the centre square, which is already a fixed size
   reserved for the trick area - so it costs no layout and nothing moves
   when the last call is made and the first card is led. */
.ybc-play-auctiongrid {
	width: 100%;
	padding: 0.35rem 0.4rem;
	font-size: 0.9375rem;
	color: #fff;
}

.ybc-play-auctionrow {
	display: grid;
	grid-template-columns: repeat(4, 1fr);
	text-align: center;
}

.ybc-play-auctionrow.is-head .ybc-play-auctioncell {
	color: var(--gold);
	font-size: 0.75rem;
	font-weight: 700;
	letter-spacing: 0.06em;
	border-bottom: 1px solid rgba(201, 162, 39, 0.4);
	padding-bottom: 0.15rem;
	margin-bottom: 0.2rem;
}

.ybc-play-auctioncell {
	padding: 0.12rem 0;
	line-height: 1.3;
	min-height: 1.3em;
}

.ybc-play-auctioncell.is-turn {
	color: var(--gold);
	font-weight: 700;
}

/* ------------------------------------------------- the bidding box

   A real bidding box, not a row of web buttons: five columns in the
   order a physical box is laid out - No Trumps first, suits downward in
   rank - with the levels rising down. One tap per bid.

   This replaced a level-then-denomination pair of rows, chosen on the
   reasoning that 14 targets beat 37 on a phone. Measuring a real box
   killed that: five columns across a phone gives cells around 60px,
   which is a comfortable target, and the two-step cost a tap on every
   bid while hiding the very colours the student was choosing between.

   Card faces rather than buttons is most of what makes it read as
   premium - white, rounded, a soft shadow, the pip in its own colour.
   Stated explicitly rather than inherited, because the theme's "Visual
   Cloak" CSS styles buttons globally with !important. */

/* The bidding screen is held to the width of a real bidding box and
   centred, inside the table's own green frame - so it reads as part of
   the table rather than a web form that has taken the page over.

   The cap is on the BOX, not on the screen. Capping the screen squeezed
   the hand along the bottom into an overlapping fan, which it has no
   need to be: cards are 3.2rem on a wide screen, so thirteen of them
   want about 42rem while a bidding box wants about 22. Two different
   widths, so two different rules. */
.ybc-play-bidscreen {
	display: flex;
	flex-direction: column;
	gap: 0.6rem;
	box-sizing: border-box;
	max-width: 100%;
	overflow-x: hidden;
	background: var(--baize);
	border: 8px solid var(--gold);
	border-radius: 22px;
	padding: 0.9rem;
}

.ybc-play-bidrecord,
.ybc-play-bidbox {
	width: 100%;
	max-width: 23rem;
	margin: 0 auto;
	box-sizing: border-box;
	background: #F6F8F6;
	border: 1px solid #DCE4DC;
	border-left: 4px solid var(--baize);
	border-radius: 0 8px 8px 0;
	padding: 0.8rem 0.9rem;
}

.ybc-play-bidbox-title {
	font-size: 0.8125rem;
	font-weight: 700;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: #5A6B7C;
	margin-bottom: 0.5rem;
}

.ybc-play-bidgrid {
	display: grid;
	grid-template-columns: repeat(5, 1fr);
	gap: 0.3rem;
}

/* Sized, not stretched. aspect-ratio against a full-width column made
   every card enormous; a stated minimum keeps the tap target honest at
   any width. */
.ybc-play .ybc-play-bidcard {
	display: flex;
	align-items: center;
	justify-content: center;
	gap: 0.1rem;
	min-height: 2.5rem;
	background: #fff;
	color: var(--ink);
	border: 1px solid #C9D2C9;
	border-radius: 7px;
	box-shadow: 0 1px 2px rgba(22, 38, 63, 0.14);
	font-family: inherit;
	font-size: 0.9375rem;
	font-weight: 700;
	line-height: 1;
	padding: 0.15rem;
	cursor: pointer;
	text-transform: none;
	letter-spacing: normal;
}

.ybc-play .ybc-play-bidcard .ybc-play-bidcard-dn {
	font-size: 1rem;
}

.ybc-play .ybc-play-bidcard.is-red .ybc-play-bidcard-dn {
	color: var(--red);
}

.ybc-play .ybc-play-bidcard:hover:not([disabled]) {
	border-color: var(--baize);
	box-shadow: 0 2px 6px rgba(22, 38, 63, 0.22);
}

/* Unavailable, not absent. On a physical box every card is still there,
   and the student is meant to see WHY a call cannot be made - so these
   fade rather than being repainted grey, and the pip keeps its colour.

   The same state covers the robots' turns, when the whole box is inert.
   It stays on screen throughout: drawing it only on the student's turn
   made it disappear for each reveal and return afterwards, resizing the
   screen twice a round. */
.ybc-play .ybc-play-bidcard[disabled] {
	opacity: 0.32;
	box-shadow: none;
	cursor: default;
}

.ybc-play-bidrow {
	display: flex;
	gap: 0.3rem;
	margin-top: 0.4rem;
}

.ybc-play .ybc-play-bidcall {
	flex: 1 1 0;
	min-height: 2.6rem;
	border: 0;
	border-radius: 7px;
	color: #fff;
	font-family: inherit;
	font-size: 1.0625rem;
	font-weight: 700;
	line-height: 1.1;
	cursor: pointer;
	text-transform: none;
	letter-spacing: normal;
	box-shadow: 0 1px 2px rgba(22, 38, 63, 0.18);
}

.ybc-play .ybc-play-bidcall.is-dbl   { background: #C0392B; }
.ybc-play .ybc-play-bidcall.is-pass  { background: var(--baize); }
.ybc-play .ybc-play-bidcall.is-rdbl  { background: #2B5DA8; }

.ybc-play .ybc-play-bidcall[disabled] {
	opacity: 0.3;
	box-shadow: none;
	cursor: default;
}

/* Your own hand, along the bottom. Already inside the green frame, so
   it needs no border of its own. */
.ybc-play-bidhand {
	padding: 0.1rem 0;
}

/* On a wide screen the hand has room to sit apart exactly as it does at
   the table, so nothing is done to it.

   On a narrow one it does not: thirteen cards at 2rem is 26rem, inside a
   viewport narrower than that, centred - so it spilled off BOTH sides.
   Below 36rem the hand is fanned, which brings it to roughly 7.6 card
   widths and fits every tier with room to spare. Ranks sit top-left on a
   card face, so each one stays readable. */
@container ybcplay (max-width: 35.9rem) {
	.ybc-play-bidhand .ybc-play-card {
		margin-left: calc(var(--card-w) * -0.45);
	}

	.ybc-play-bidhand .ybc-play-card:first-child {
		margin-left: 0;
	}
}

.ybc-play-bidwarn {
	color: var(--ink);
	font-size: 0.9375rem;
	line-height: 1.5;
	margin: 0;
}

/* The auction record on the bidding screen is read, not glanced at, so
   it takes the light treatment rather than the table's dark palette. */
.ybc-play-bidrecord .ybc-play-auctiongrid {
	color: var(--ink);
	font-size: 1rem;
	padding: 0;
}

.ybc-play-bidrecord .ybc-play-auctionrow.is-head .ybc-play-auctioncell {
	color: #5A6B7C;
	border-bottom-color: #DCE4DC;
}

.ybc-play-bidrecord .ybc-play-auctioncell.is-turn {
	color: var(--baize);
}

/* Reopen the auction after play has started. Sits on the contract line,
   so it is small and quiet - it is a reference, not an action. */
.ybc-play .ybc-play-reviewbid {
	background: transparent;
	color: var(--gold);
	border: 1px solid var(--gold);
	border-radius: 6px;
	padding: 0.15rem 0.55rem;
	margin-left: 0.6rem;
	font-family: inherit;
	font-size: 0.8125rem;
	font-weight: 700;
	line-height: 1.4;
	cursor: pointer;
	text-transform: none;
	letter-spacing: normal;
	vertical-align: middle;
}

.ybc-play .ybc-play-reviewbid:hover {
	background: var(--gold);
	color: var(--ink);
}

/* The editors-only message preview. Plain and dense on purpose: it is a
   checking tool, not something a student ever sees. */
.ybc-play-preview {
	background: #FFFDF5;
	border: 1px dashed #C9A227;
	border-radius: 8px;
	padding: 0.8rem 0.9rem;
	color: var(--ink);
	font-size: 0.875rem;
	line-height: 1.45;
}

.ybc-play-preview-turn {
	font-weight: 700;
	margin: 0.6rem 0 0.3rem;
	color: var(--baize);
}

.ybc-play-preview-row {
	display: flex;
	gap: 0.6rem;
	padding: 0.25rem 0;
	border-top: 1px solid #EFEBDD;
}

.ybc-play-preview-call {
	flex: 0 0 3.2rem;
	font-weight: 700;
}

.ybc-play-preview-row.is-right .ybc-play-preview-call {
	color: var(--baize);
}

.ybc-play-preview-row.is-wrong .ybc-play-preview-call {
	color: #B00020;
}
