/* Brentwood 100 grid (bw/hundred-grid).
   Modal chrome (overlay/dialog/close) comes from the shared bw-table-link style.

   The grid is 3 columns of SQUARE slots. A tile fills one slot, two stacked, or
   two side by side; packer.js decides which and writes the coordinates, so there
   is no auto-placement here — every cell is positioned explicitly.

   Legacy styles for the previous tile model are in style-legacy.css, still used
   by ?b100=legacy. */

.bw100 {
	--bw100-red: var(--global-palette1, #c8272c);
	--bw100-gap: .5rem;
	box-sizing: border-box;
	padding: 32px;
}
@media (max-width: 767px) {
	.bw100 { padding-left: 10px; padding-right: 10px; }
}

.bw100__grid {
	display: grid;
	grid-template-columns: repeat(3, 1fr);
	/* Row height is set in px by view.js, from the grid's own measured column
	   width, so a row is exactly as tall as a column is wide and a "tall" tile is
	   genuinely two squares. CSS can't express "row height = column width" on its
	   own: percentage padding resolves against width, but a row spanned by two
	   tiles has no single element to hang that off. The value below is only a
	   holding size for the moment before JS runs (the grid is hidden then anyway)
	   and for the no-JS path. */
	grid-auto-rows: minmax(180px, auto);
	gap: var(--bw100-gap);

	/* Hidden until packer.js has positioned everything. visibility rather than
	   display so images still load, and opacity so the reveal isn't a hard cut. */
	visibility: hidden;
	opacity: 0;
	transition: opacity .35s ease;
}
.bw100__grid.bw100--ready { visibility: visible; opacity: 1; }

/* Before the packer runs (and for ?b100=legacy) every cell is one square. */
.bw100__cell {
	position: relative;
	overflow: hidden;
	background: var(--global-palette9, #fff);
	border: 1px solid #fefefe;
	border-radius: 5px;
	box-shadow: 3px 3px 5px #ccc;
}

/* The whole tile is the button — every tile opens the pop-up. */
.bw100__tile {
	position: absolute;
	inset: 0;
	display: flex;
	width: 100%;
	height: 100%;
	margin: 0;
	padding: 0;
	border: 0;
	background: none;
	text-align: left;
	cursor: pointer;
	color: inherit;
	font: inherit;
}
.bw100__tile:focus-visible {
	outline: 3px solid var(--bw100-red);
	outline-offset: -3px;
}

/* The badge number. Sits in the corner of the whole tile rather than inside
   either half, so it lands in the same place whichever way a split tile is
   facing. Red on white keeps it legible over a photograph and over text. */
.bw100__num {
	position: absolute;
	top: .6rem;
	left: .6rem;
	z-index: 2;
	display: flex;
	align-items: center;
	justify-content: center;
	min-width: 1.85rem;
	height: 1.85rem;
	padding: 0 .4rem;
	border-radius: 4px;
	background: var(--bw100-red);
	color: #fff;
	font-size: .78rem;
	font-weight: 600;
	line-height: 1;
	box-shadow: 0 1px 3px rgba(0, 0, 0, .25);
}

/* --- media ------------------------------------------------------------- */
.bw100__media {
	position: relative;
	flex: 1 1 auto;
	min-width: 0;
	min-height: 0;
	overflow: hidden;
}
.bw100__img,
.bw100__video {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
	transition: transform .5s ease, opacity 1.1s ease;
}

/* Carousel: every image is stacked in the same box and cross-faded. Absolute
   positioning would collapse the media box, so the FIRST image stays in flow and
   sets the height; the rest sit on top of it.

   STACKING ORDER inside .bw100__media — anything added here needs a z-index or it
   will be painted over by the active picture:
       0  inactive images
       1  the active image
       2  everything that must read ON TOP of it — title, number, dots, play badge
   Giving the active image a z-index is what hid the title overlay: DOM order puts
   the title after the images, but z-index beats DOM order. */
.bw100__media > .bw100__img { position: absolute; inset: 0; opacity: 0; }
.bw100__media > .bw100__img:first-of-type { position: relative; }
.bw100__media > .bw100__img.is-active { opacity: 1; z-index: 1; }


.bw100__dots {
	position: absolute;
	right: .5rem;
	bottom: .5rem;
	z-index: 2;
	display: flex;
	gap: 4px;
}
.bw100__dot {
	width: 6px;
	height: 6px;
	border-radius: 50%;
	background: rgba(255, 255, 255, .55);
	box-shadow: 0 0 2px rgba(0, 0, 0, .5);
}
.bw100__dot.is-active { background: #fff; }


.bw100__tile:hover .bw100__img { transform: scale(1.04); }

/* Title over the media, for tiles showing media only. */
.bw100__media-title {
	position: absolute;
	inset: auto 0 0 0;
	z-index: 2;
	padding: 2.5rem .9rem .8rem;
	color: #fff;
	font-family: var(--global-heading-font-family, inherit);
	font-size: clamp(.95rem, 1.4vw, 1.15rem);
	line-height: 1.2;
	background: linear-gradient(to top, rgba(0, 0, 0, .72), rgba(0, 0, 0, 0));
}

/* Play badge for a video tile that only has a link (poster + pop-up embed). */
.bw100__play {
	position: absolute;
	z-index: 2;
	top: 50%;
	left: 50%;
	width: 54px;
	height: 54px;
	transform: translate(-50%, -50%);
	border-radius: 50%;
	background: rgba(0, 0, 0, .55);
}
.bw100__play::after {
	content: "";
	position: absolute;
	top: 50%;
	left: 54%;
	transform: translate(-50%, -50%);
	border-style: solid;
	border-width: 9px 0 9px 15px;
	border-color: transparent transparent transparent #fff;
}

/* --- text --------------------------------------------------------------- */
.bw100__text {
	position: relative; /* the overflow fade below anchors to THIS, not the cell */
	flex: 1 1 auto;
	min-width: 0;
	min-height: 0;
	/* Top padding clears the number badge; the bottom matches it exactly, because
	   the text is vertically centred and unequal padding would push it off-centre
	   by half the difference. */
	padding: 3rem 1.1rem;
	overflow: hidden;
	background: var(--global-palette9, #fff);

	/* Short entries would otherwise sit at the top of a square tile with a lot of
	   dead space under them. "safe" matters: on text too long for the tile it
	   falls back to top-aligned, so the first line is never scrolled out of view
	   by the centring. */
	display: flex;
	flex-direction: column;
	justify-content: center;
	justify-content: safe center;
}

/* The body clips inside ITS OWN box, not the tile's.
   `overflow: hidden` cuts at the padding edge, so with the clipping on .bw100__text
   the padding was applied and then overrun — text was drawn straight through it and
   sliced at the card boundary, giving a top inset and none at the bottom.
   flex-shrink with min-height:0 lets this box be shorter than its content, so the
   cut lands on ITS edge and the parent's padding survives underneath. */
.bw100__title {
	margin: 0 0 .45rem;
	font-size: clamp(.95rem, 1.4vw, 1.15rem);
	line-height: 1.2;
	color: var(--global-palette3, #4b5563);
}
.bw100__body {
	flex: 0 1 auto;
	min-height: 0;
	overflow: hidden;
	font-size: .84rem;
	line-height: 1.45;
	color: var(--global-palette4, #707d8e);
}
.bw100__body > :first-child { margin-top: 0; }
.bw100__body > :last-child { margin-bottom: 0; }

/* Text that runs past the tile fades out rather than being cut mid-letter —
   the pop-up has the rest, and every tile opens it. */
.bw100__text::after {
	content: "";
	position: absolute;
	inset: auto 0 3rem 0; /* sits on the clip line, i.e. above the bottom padding */
	height: 2.2rem;
	background: linear-gradient(to top, var(--global-palette9, #fff), rgba(255, 255, 255, 0));
	pointer-events: none;
}

/* --- the four content layouts ------------------------------------------- */
/* Which of the two halves shows, and in what order. The packer only ever picks
   a layout the tile can actually render (see bw_hundred_tile_data). */
.bw100__cell--media_only .bw100__text { display: none; }
.bw100__cell--text_only .bw100__media { display: none; }

/* Title lives over the media only when there's no text block to head. */
.bw100__cell:not(.bw100__cell--media_only) .bw100__media-title { display: none; }
.bw100__cell--media_only .bw100__text::after { display: none; }
.bw100__cell--text_only { background: var(--global-palette9, #fff); }

/* Wide tiles split left/right, tall tiles top/bottom. "text_media" means text
   first in reading order — left on a wide, top on a tall. */
/* The face is emitted media-first, so plain `row` puts the MEDIA on the left.
   The labels read the other way round — "Text | Media" means text first — so
   text_media is the reversed one. Getting this backwards is what put the old
   carousel controls on the text half of a split tile. */
.bw100__cell--wide .bw100__tile { flex-direction: row; }
.bw100__cell--tall .bw100__tile { flex-direction: column; }
.bw100__cell--wide.bw100__cell--text_media .bw100__tile { flex-direction: row-reverse; }
.bw100__cell--tall.bw100__cell--text_media .bw100__tile { flex-direction: column-reverse; }

/* A split tile gives each half half the tile. */
.bw100__cell--text_media .bw100__media,
.bw100__cell--media_text .bw100__media,
.bw100__cell--text_media .bw100__text,
.bw100__cell--media_text .bw100__text { flex: 1 1 50%; }

/* --- pop-up -------------------------------------------------------------- */
.bw100-modal__title {
	margin: 0 0 1rem;
	font-size: 1.6rem;
	line-height: 1.2;
}
.bw100-modal__gallery {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
	gap: .6rem;
	margin-bottom: 1.2rem;
}
.bw100-modal__figure { margin: 0; }
.bw100-modal__img { display: block; width: 100%; height: auto; border-radius: 2px; }
.bw100-modal__video {
	position: relative;
	width: 100%;
	aspect-ratio: 16 / 9;
	margin-bottom: 1.2rem;
	border: 0;
	background: #000;
}
.bw100-modal__video iframe,
video.bw100-modal__video { width: 100%; height: 100%; border: 0; }
.bw100-modal__body { font-size: 1rem; line-height: 1.6; color: var(--global-palette4, #707d8e); }

/* --- mobile -------------------------------------------------------------- */
/* Everything collapses to a square: a packed mosaic needs three columns to mean
   anything, and a tall tile on a narrow screen is just a very long box. The
   coordinates the packer wrote are overridden rather than recomputed, so no
   second pass is needed on resize. */
@media (max-width: 767px) {
	.bw100__grid { grid-template-columns: repeat(2, 1fr); }
	.bw100__grid > .bw100__cell {
		grid-column: auto !important;
		grid-row: auto !important;
	}
	.bw100__cell--wide .bw100__tile,
	.bw100__cell--tall .bw100__tile { flex-direction: column; }
	/* With no room to sit side by side, a split tile shows its media and leaves
	   the words to the pop-up. */
	.bw100__cell--text_media .bw100__text,
	.bw100__cell--media_text .bw100__text { display: none; }
	.bw100__cell--text_media .bw100__media,
	.bw100__cell--media_text .bw100__media { flex: 1 1 100%; }
	.bw100__cell--text_media .bw100__media-title,
	.bw100__cell--media_text .bw100__media-title { display: block; }
}
@media (max-width: 479px) {
	.bw100__grid { grid-template-columns: 1fr; }
}
