/* ==========================================================================
   Skinvestment — Liquid glass surface system

   WHY THIS IS CSS AND NOT THE WEBGL LIBRARY, BY DEFAULT
   ----------------------------------------------------
   @ybouane/liquidglass produces the most physically convincing result, but it
   works by rasterising the DOM behind each glass element to a canvas
   (html-to-image → SVG foreignObject) and running a WebGL shader over it. That
   is affordable for one bounded, mostly-static showpiece. It is not affordable
   for persistent chrome like a sticky header, because everything behind the
   header changes on every scroll frame, forcing a re-capture of the page.

   So the system is two tiers:
     Tier 1 (this file) — CSS. Real backdrop refraction via layered
       backdrop-filter, an edge bevel, a specular sweep and adaptive tint.
       Cheap, composited on the GPU, works on every modern browser, degrades
       cleanly. Used for the header, cards, the hero facts strip, the booking
       panel — everything persistent.
     Tier 2 (assets/js/glass.js) — the WebGL library, lazy-loaded, on the front
       page hero only, and only when the device and the visitor's preferences
       say it is welcome.

   The two tiers share the same tokens below, so the showpiece and the chrome
   read as one material.
   ========================================================================== */

:root {
	/* Material tuning. Everything about the glass is expressed here. */
	--glass-blur:        18px;   /* backdrop blur radius                       */
	--glass-blur-rim:     6px;   /* extra blur in the bevel ring — the "thick
	                                edge" that sells refraction                */
	--glass-saturate:    170%;   /* colour bloom picked up from the backdrop   */
	--glass-brightness:  108%;
	--glass-tint:        255 253 249;  /* --paper, as channels for rgb()       */
	--glass-tint-a:      0.14;   /* how much of the tint sits over the backdrop*/
	--glass-rim:          1.25px;/* bevel thickness                            */
	--glass-highlight:   0.55;   /* strength of the top-edge specular          */
	--glass-shadow:      0 18px 44px -20px rgb(43 36 31 / 0.42);
	--glass-radius:      var(--radius-lg);
}

/* --------------------------------------------------------------------------
   Base material
   -------------------------------------------------------------------------- */
.glass {
	position: relative;
	isolation: isolate;
	border-radius: var(--glass-radius);
	background: rgb(var(--glass-tint) / var(--glass-tint-a));
	box-shadow: var(--glass-shadow);
	/* The backdrop treatment. saturate() before blur() is deliberate: it lifts
	   the colour out of the photograph underneath before the blur averages it
	   into mush, which is what stops glass over imagery looking grey. */
	-webkit-backdrop-filter: saturate(var(--glass-saturate)) brightness(var(--glass-brightness)) blur(var(--glass-blur));
	backdrop-filter: saturate(var(--glass-saturate)) brightness(var(--glass-brightness)) blur(var(--glass-blur));
	/* Deliberately NO `will-change` here. `will-change: backdrop-filter` on
	   every glass element permanently promotes each one to its own compositor
	   layer, and the browser is already better at deciding that than we are.
	   Blanket will-change is how you turn an effect that costs nothing into one
	   that exhausts GPU memory. */
}

/* Edge refraction — OPT-IN via .glass--rim.
   A ring-shaped element with its *own* backdrop-filter. Because the ring is
   masked to only the outer --glass-rim of the box, the extra blur and the
   brightness lift read as light bending through a thicker piece of glass at the
   rim — the single cue that separates "liquid glass" from a plain frosted panel.

   It is opt-in because it is a SECOND backdrop-filter layer per element. Applied
   to every .glass on the page that doubles the GPU's backdrop work for a detail
   that is only legible on a large panel sitting over a photograph. Measured on
   an Intel HD 620: applying it to all ten glass elements on the front page made
   the compositor miss frames badly enough to stall screenshot capture. Use it on
   hero-scale glass over imagery, not on cards. */
.glass--rim::before {
	content: '';
	position: absolute;
	inset: 0;
	z-index: -1;
	border-radius: inherit;
	padding: var(--glass-rim);
	-webkit-backdrop-filter: blur(var(--glass-blur-rim)) brightness(1.22) saturate(140%);
	backdrop-filter: blur(var(--glass-blur-rim)) brightness(1.22) saturate(140%);
	/* mask-composite ring trick: fill minus content-box = the border ring. */
	-webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
	-webkit-mask-composite: xor;
	mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
	mask-composite: exclude;
	pointer-events: none;
}

/* Specular + bevel.
   A single gradient doing two jobs: a bright hairline along the top-left edge
   (light source is up and to the left, consistently across the whole site) and
   a soft fall-off across the face so the panel is not flat. */
.glass::after {
	content: '';
	position: absolute;
	inset: 0;
	z-index: -1;
	border-radius: inherit;
	pointer-events: none;
	background:
		linear-gradient(
			145deg,
			rgb(255 255 255 / var(--glass-highlight)) 0%,
			rgb(255 255 255 / 0.06) 26%,
			rgb(255 255 255 / 0) 52%
		);
	/* Inset hairlines: light on top, a faint dark on the bottom. This is the
	   bevel. Two 1px lines do more for the illusion than any amount of blur. */
	box-shadow:
		inset 0 1px 0 0 rgb(255 255 255 / 0.5),
		inset 0 -1px 0 0 rgb(43 36 31 / 0.09),
		inset 1px 0 0 0 rgb(255 255 255 / 0.18),
		inset -1px 0 0 0 rgb(43 36 31 / 0.05);
}

/* --------------------------------------------------------------------------
   Variants
   -------------------------------------------------------------------------- */

/* Over dark imagery — the hero. Tint shifts to the warm cream so the glass
   reads as part of this palette rather than a generic grey Apple panel. */
.glass--warm {
	--glass-tint: 248 242 233;      /* --cream */
	--glass-tint-a: 0.16;
	--glass-highlight: 0.42;
	color: var(--cream);
}

/* Over light, FLAT backgrounds — cards on cream.
   No backdrop-filter at all. There is no photograph behind these, only a solid
   colour: blurring a solid colour produces that same solid colour, so the filter
   costs a composited layer and buys literally nothing. The material still reads
   as glass because the bevel hairlines and specular gradient — which is what the
   eye actually keys off — are still there. */
.glass--light {
	--glass-tint: 255 253 249;
	--glass-tint-a: 0.86;
	--glass-highlight: 0.7;
	--glass-shadow: 0 12px 30px -18px rgb(43 36 31 / 0.3);
	-webkit-backdrop-filter: none;
	backdrop-filter: none;
	will-change: auto;
}

/* Deep clay glass for accents. */
.glass--clay {
	--glass-tint: 189 111 82;
	--glass-tint-a: 0.3;
	--glass-highlight: 0.35;
	color: var(--cream);
}

.glass--flush { --glass-radius: 0; --glass-shadow: none; }
.glass--pill  { --glass-radius: var(--radius-pill); }

/* --------------------------------------------------------------------------
   Interactive glass — buttons and cards
   The sweep is a masked gradient that travels across the face on hover. It
   animates `transform` only (never background-position), so it stays on the
   compositor.
   -------------------------------------------------------------------------- */
.glass--interactive {
	overflow: clip;
	transition: transform var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
.glass--interactive:hover { transform: translateY(-3px); }

.glass--interactive .glass__sweep {
	position: absolute;
	inset: -40% -60%;
	z-index: -1;
	pointer-events: none;
	background: linear-gradient(
		100deg,
		transparent 35%,
		rgb(255 255 255 / 0.34) 50%,
		transparent 65%
	);
	transform: translateX(-70%);
	opacity: 0;
	transition: transform 0.9s var(--ease-out), opacity 0.35s linear;
}
.glass--interactive:hover .glass__sweep { transform: translateX(70%); opacity: 1; }

/* --------------------------------------------------------------------------
   Applied surfaces
   -------------------------------------------------------------------------- */

/* Header: transparent while it floats over the hero, glass once you scroll
   past. `.skin-header--stuck` is toggled from an IntersectionObserver sentinel
   in site.js. */
.skin-header--stuck {
	--glass-radius: 0;
	--glass-tint: 248 242 233;
	--glass-tint-a: 0.72;
	--glass-blur: 16px;
	--glass-shadow: 0 1px 0 0 rgb(43 36 31 / 0.08);
	background: rgb(var(--glass-tint) / var(--glass-tint-a));
	-webkit-backdrop-filter: saturate(var(--glass-saturate)) blur(var(--glass-blur));
	backdrop-filter: saturate(var(--glass-saturate)) blur(var(--glass-blur));
	color: var(--ink);
}
.skin-header--stuck::after {
	content: '';
	position: absolute; inset: 0; z-index: -1;
	box-shadow: inset 0 -1px 0 0 rgb(43 36 31 / 0.09), inset 0 1px 0 0 rgb(255 255 255 / 0.5);
	pointer-events: none;
}

/* Hero facts strip — the first glass a visitor meets. */
.skin-hero__facts.glass { --glass-radius: var(--radius-lg); }

/* Booking panel */
.skin-booking-panel.glass { padding: var(--gap-m); }

/* --------------------------------------------------------------------------
   When the WebGL tier is live, stand the CSS tier down.

   glass.js adds `.has-webgl-glass` to the capture root once init() resolves.
   Without these rules BOTH materials render on the same element — the injected
   WebGL canvas *and* the CSS backdrop-filter, tint, bevel and shadow beneath
   it. That reads as a doubled, offset panel with a heavier edge on one side,
   which is exactly the artefact that showed up in the first real render.

   The WebGL layer draws its own refraction, specular, rim light and shadow, so
   everything here is redundant once it is running.
   -------------------------------------------------------------------------- */
.has-webgl-glass [data-glass] {
	background: transparent;
	box-shadow: none;
	-webkit-backdrop-filter: none;
	backdrop-filter: none;
}
.has-webgl-glass [data-glass]::before,
.has-webgl-glass [data-glass]::after {
	display: none;
}
/* The library injects its canvas as the glass element's first child and sizes
   it to include the shadow halo, so it must not be clipped by our radius. */
.has-webgl-glass [data-glass] > canvas {
	pointer-events: none;
}

/* --------------------------------------------------------------------------
   Graceful degradation
   -------------------------------------------------------------------------- */

/* No backdrop-filter (older Firefox with the pref off, some embedded views):
   fall back to an opaque panel. Never leave text floating on a transparent tint
   it was never contrast-tested against. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
	.glass            { background: rgb(var(--glass-tint) / 0.92); }
	.glass--warm      { background: rgb(43 36 31 / 0.72); }
	.glass--light     { background: var(--paper); }
	.skin-header--stuck { background: var(--cream); }
	.glass--rim::before { display: none; }
}

/* The visitor has asked their OS to reduce transparency (macOS/iOS "Reduce
   Transparency", Windows "Transparency effects: off"). Honour it: solid
   surfaces, no blur, no sweep. */
@media (prefers-reduced-transparency: reduce) {
	.glass {
		background: rgb(var(--glass-tint) / 0.96);
		-webkit-backdrop-filter: none;
		backdrop-filter: none;
	}
	.glass--warm  { background: rgb(43 36 31 / 0.86); }
	.glass--light { background: var(--paper); }
	.glass--rim::before { display: none; }
	.glass__sweep  { display: none; }
	.skin-header--stuck { background: var(--cream); -webkit-backdrop-filter: none; backdrop-filter: none; }
}

@media (prefers-reduced-motion: reduce) {
	.glass--interactive,
	.glass--interactive:hover { transform: none; }
	.glass__sweep { display: none; }
}

/* Forced-colours (Windows High Contrast): drop the whole material and let the
   OS palette through. */
@media (forced-colors: active) {
	.glass {
		background: Canvas;
		border: 1px solid CanvasText;
		-webkit-backdrop-filter: none;
		backdrop-filter: none;
	}
	.glass--rim::before, .glass::after, .glass__sweep { display: none; }
}
