/* ==========================================================================
   Widget — Artistic Gallery Slider
   Figma node 66:299 (Gallery — A Closer Look). A heading row over a staggered
   run of photographs: a large landscape, a tall portrait and a small
   landscape, each hung at its own height, together exactly filling a 1920
   viewport edge to edge. From a fourth photograph the shapes repeat and the
   row becomes a horizontal scroller.

   Pressing View All Photos puts .is-grid on the block, which re-flows the
   same list into an even grid back on the 1440 site grid.

   Geometry is written in comp pixels multiplied by --o-ag-px, one comp pixel
   at the current width, so the numbers can be read straight off the Figma
   file. Three are rounded from the comp: the tall photograph is 440 wide
   rather than 430, both gaps are 100 rather than 110 and 100, and the small
   photograph drops 240 rather than 230. The row still totals exactly 1920.
   ========================================================================== */

.o-art-gallery {
	/*
	 * Fallbacks only. Elementor writes --o-ag-cols per breakpoint from the
	 * grid "Columns" control, and --o-ag-grid-ratio is set inline.
	 */
	--o-ag-cols: 2;
	--o-ag-grid-ratio: 1.5;

	display: flex;
	flex-direction: column;
	gap: var(--o-space-xl);
}

@media (min-width: 1025px) {
	.o-art-gallery {
		--o-ag-cols: 3;
	}
}

/* --------------------------------------------------------------------------
   Heading row
   Heading left, controls right. Wraps to two rows on narrow screens rather
   than letting the controls crush the heading.
   -------------------------------------------------------------------------- */
.o-art-gallery__head {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: space-between;
	gap: var(--o-space-md) var(--o-space-lg);
}

.o-art-gallery__heading {
	display: flex;
	flex-direction: column;
	gap: var(--o-space-sm);
}

.o-art-gallery__title {
	margin: 0;
	font-family: var(--o-font-ui);
	font-weight: var(--o-fw-semibold);
	font-size: var(--o-fs-h1); /* 32 -> 48, per the comp */
	line-height: 1.08;
	text-transform: uppercase;
}

/* The comp sets the heading and the link in navy on white, not body ink. */
.o-scheme-light .o-art-gallery__title,
.o-scheme-light .o-art-gallery__toggle {
	color: var(--o-navy);
}

.o-art-gallery__controls {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: var(--o-space-md) var(--o-space-lg);
}

.o-art-gallery__nav {
	display: flex;
	gap: 0.75rem;
}

/*
 * The listing modal's circular arrows, a size down: white disc, navy glyph,
 * inverting on hover.
 */
.o-art-gallery__arrow {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 48px;
	height: 48px;
	padding: 0;
	border: 0;
	border-radius: 50%;
	background-color: var(--o-white);
	color: var(--o-navy);
	box-shadow: var(--o-shadow-float);
	transition: background-color var(--o-transition), color var(--o-transition), opacity var(--o-transition);
}

.o-art-gallery__arrow:hover,
.o-art-gallery__arrow:focus-visible {
	background-color: var(--o-navy);
	color: var(--o-white);
}

/* The global focus ring squares its corners; this one should stay round. */
.o-art-gallery__arrow:focus-visible {
	border-radius: 50%;
}

/*
 * aria-disabled rather than disabled, so a keyboard user sitting on the
 * arrow is not thrown back to the top of the page when the row reaches its
 * end and the button would otherwise drop out of the focus order.
 */
.o-art-gallery__arrow[aria-disabled="true"] {
	opacity: 0.35;
	cursor: default;
}

.o-art-gallery__arrow[aria-disabled="true"]:hover {
	background-color: var(--o-white);
	color: var(--o-navy);
}

.o-art-gallery__arrow-glyph {
	display: block;
	width: 24px;
	height: 24px;
}

/* A <button> wearing the "VIEW ALL PHOTOS ⟶" text-link treatment. */
.o-art-gallery__toggle {
	min-height: 44px;
	padding: 0;
	border: 0;
	background: none;
	font-size: var(--o-fs-body); /* The comp sets this link at 16, a step under the standard 18 */
}

.o-art-gallery .o-art-gallery__toggle:hover,
.o-art-gallery .o-art-gallery__toggle:focus-visible {
	color: var(--o-accent);
}

/* Once the grid is open the arrow points back. */
.o-art-gallery.is-grid .o-art-gallery__toggle .o-textlink__chevrons {
	rotate: 180deg;
}

/* --------------------------------------------------------------------------
   The row
   The track is the scroll container and also the size container the comp
   pixel is measured against, so the row scales to the space it actually has
   rather than to 100vw, which counts the scrollbar and would always overflow
   by its width.
   -------------------------------------------------------------------------- */
.o-art-gallery__track {
	container-type: inline-size;
	overflow-x: auto;
	overscroll-behavior-x: contain;
	scroll-snap-type: x mandatory;
}

/*
 * The scrollbar goes only once the script is running, because that is when
 * the arrows exist to replace it. Without the script it stays, as the one
 * visible sign to a mouse user that the row scrolls.
 */
.o-art-gallery.is-enhanced .o-art-gallery__track {
	scrollbar-width: none;
}

.o-art-gallery.is-enhanced .o-art-gallery__track::-webkit-scrollbar {
	display: none;
}

.o-art-gallery__track:focus-visible {
	outline-offset: -3px;
	border-radius: 0;
}

.o-art-gallery__list {
	/*
	 * One comp pixel. The row is drawn at 1920, scales down with the room it
	 * has, and stops growing at 1920 so an ultrawide screen does not get
	 * 1200px photographs - there the row simply centres.
	 */
	--o-ag-px: calc(min(100cqi, 1920px) / 1920);
	--o-ag-large: calc(880 * var(--o-ag-px));
	--o-ag-tall: calc(440 * var(--o-ag-px));
	--o-ag-small: calc(400 * var(--o-ag-px));
	--o-ag-gap: calc(100 * var(--o-ag-px));

	display: flex;
	align-items: flex-start;
	justify-content: center;
	gap: var(--o-ag-gap);
	width: max-content;
	min-width: 100%;
	margin: 0;
	padding: 0;
	list-style: none;
}

.o-art-gallery__item {
	flex: none;
	scroll-snap-align: start;
}

/*
 * The drops are measured against the tall photograph's width, so the
 * stagger keeps its proportions at every breakpoint below, where only the
 * three widths change.
 */
.o-art-gallery__item--large {
	--o-ag-ratio: 880 / 560;
	width: var(--o-ag-large);
	margin-top: calc(var(--o-ag-tall) * 80 / 440);
}

.o-art-gallery__item--tall {
	--o-ag-ratio: 440 / 620;
	width: var(--o-ag-tall);
}

.o-art-gallery__item--small {
	--o-ag-ratio: 4 / 3;
	width: var(--o-ag-small);
	margin-top: calc(var(--o-ag-tall) * 240 / 440);
}

.o-art-gallery__figure {
	margin: 0;
}

/* Cool grey underneath, so a photograph still loading reads as a frame. */
.o-art-gallery__frame {
	aspect-ratio: var(--o-ag-ratio);
	overflow: hidden;
	background-color: var(--o-rule-cool);
}

.o-art-gallery__img {
	display: block;
	width: 100%;
	height: 100% !important;
	object-fit: cover;
}

/*
 * The comp draws this in --o-ink-mist, which is 4.0:1 on white - short of
 * the 4.5:1 that text this size needs. --o-text-soft passes, and still reads
 * as a quiet caption.
 */
.o-art-gallery__caption {
	margin-top: var(--o-space-lg);
	color: var(--o-text-soft);
	font-family: var(--o-font-body);
	font-size: var(--o-fs-small);
	line-height: 1.4;
}

.o-art-gallery__accent {
	display: block;
	width: 56px;
	height: 12px;
	margin-top: var(--o-space-xl);
	background-color: var(--o-accent);
}

/* --------------------------------------------------------------------------
   Tablets and phones
   At comp proportions the small photograph would be 160px wide on a tablet,
   so below 1025 each shape takes a fixed share of the screen instead and the
   row always swipes. The gutter comes back so the first photograph does not
   start hard against the edge of a phone.
   -------------------------------------------------------------------------- */
@media (max-width: 1024px) {
	.o-art-gallery__track {
		scroll-padding-inline: var(--o-gutter);
	}

	.o-art-gallery__list {
		--o-ag-large: 72cqi;
		--o-ag-tall: 44cqi;
		--o-ag-small: 50cqi;
		--o-ag-gap: var(--o-space-md);

		justify-content: flex-start;
		padding-inline: var(--o-gutter);
	}
}

@media (max-width: 767px) {
	.o-art-gallery__list {
		--o-ag-large: 84cqi;
		--o-ag-tall: 58cqi;
		--o-ag-small: 68cqi;
	}
}

@media (max-width: 700px) {
	.o-art-gallery__head {
		align-items: flex-start;
	}
}

/* --------------------------------------------------------------------------
   Grid view
   The same list, re-flowed. The track stops scrolling and steps back onto the
   1440 site grid; every photograph takes one shape so the rows line up.
   -------------------------------------------------------------------------- */
.o-art-gallery.is-grid .o-art-gallery__track {
	width: 100%;
	max-width: calc(var(--o-container) + (var(--o-gutter) * 2));
	margin-inline: auto;
	padding-inline: var(--o-gutter);
	overflow: visible;
	scroll-snap-type: none;
}

.o-art-gallery.is-grid .o-art-gallery__list {
	display: grid;
	grid-template-columns: repeat(var(--o-ag-cols), minmax(0, 1fr));
	gap: var(--o-space-lg);
	width: auto;
	min-width: 0;
	padding-inline: 0;
}

.o-art-gallery.is-grid .o-art-gallery__item {
	--o-ag-ratio: var(--o-ag-grid-ratio);
	width: auto;
	margin-top: 0;
}

.o-art-gallery.is-grid .o-art-gallery__caption {
	margin-top: var(--o-space-sm);
}

.o-art-gallery.is-grid .o-art-gallery__accent {
	display: none;
}

@media (max-width: 767px) {
	.o-art-gallery.is-grid .o-art-gallery__list {
		gap: var(--o-space-sm);
	}
}

/* --------------------------------------------------------------------------
   Boxed
   With Content width set to anything but full bleed, the section already
   supplies the gutter, so the widget's own containers stand down rather than
   indent the heading and the grid a second time.
   -------------------------------------------------------------------------- */
.o-section__inner:not(.o-container--bleed) .o-art-gallery__head,
.o-section__inner:not(.o-container--bleed) .o-art-gallery.is-grid .o-art-gallery__track {
	max-width: none;
	padding-inline: 0;
}

.o-section__inner:not(.o-container--bleed) .o-art-gallery__list {
	padding-inline: 0;
}

.o-section__inner:not(.o-container--bleed) .o-art-gallery__track {
	scroll-padding-inline: 0;
}

/* --------------------------------------------------------------------------
   Row <-> grid morph
   The script names each frame for the length of a view transition. Each one
   glides and resizes from its old box to its new one; the snapshots fill the
   moving box and crop rather than stretch, so a tall photograph becoming a
   landscape cell never squashes on the way.
   -------------------------------------------------------------------------- */
::view-transition-group(*.o-ag-frame) {
	animation-duration: 600ms;
	animation-timing-function: cubic-bezier(0.2, 0.7, 0.2, 1);
}

::view-transition-old(*.o-ag-frame),
::view-transition-new(*.o-ag-frame) {
	height: 100%;
	object-fit: cover;
	overflow: clip;
}
