/* corner.css -- the capsule in the bottom corner of the page.
 *
 * TWIN: store/corner.css is the same file, loaded by the store and the
 * affiliate hub. A sales page reaches the admin as ../admin/ and nothing
 * else, so it has its own copy here rather than a cross-folder link.
 * Change one, change the other.
 *
 * Lifted from the admin's own dark.css so the store, the affiliate hub and
 * the admin all carry the same control. scroll_nav.js puts the two jump
 * arrows in it; theme.js, where a page loads that too, puts the light/dark
 * switch above them. Whichever script runs first builds #ssm-corner and the
 * other joins it, so neither depends on load order.
 */
/* ==========================================================================
   THE CORNER CONTROL
   One capsule in the bottom right holding the theme switch above the two jump
   buttons: one outline, one shadow, one object. Built by two scripts --
   js/theme.js puts the switch in, js/scroll_nav.js the arrows -- and whichever
   runs first creates #ssm-corner for the other to join, so neither depends on
   the order they load in.
   ========================================================================== */
#ssm-corner {
	position: fixed;
	right: 20px;
	/* Clear of the notification, which slides in along the bottom. */
	bottom: 74px;
	z-index: 1000001;
	display: flex;
	flex-direction: column;
	align-items: center;
	width: 40px;
	overflow: hidden;
	border: 1px solid rgba(0, 0, 0, .08);
	border-radius: 999px;
	background: rgba(255, 255, 255, .86);
	-webkit-backdrop-filter: saturate(140%) blur(8px);
	backdrop-filter: saturate(140%) blur(8px);
	box-shadow: 0 2px 12px rgba(16, 24, 40, .14);
	/* Quiet until it is wanted. */
	opacity: .55;
	transition: opacity .2s ease, box-shadow .2s ease, background-color .2s ease;
	font-family: 'Open Sans', Arial, Helvetica, sans-serif;
	font-size: 12px;
	line-height: 1;
	color: #5b6672;
	user-select: none;
	-webkit-user-select: none;
}
#ssm-corner:hover,
#ssm-corner:focus-within { opacity: 1; box-shadow: 0 4px 18px rgba(16, 24, 40, .2); }
html[data-theme="dark"] #ssm-corner {
	background: rgba(34, 41, 51, .9);
	border-color: rgba(255, 255, 255, .12);
	color: #aab4c0;
	box-shadow: 0 2px 14px rgba(0, 0, 0, .5);
}
/* The hairline between the switch and the arrows, inset so the capsule's own
   edge stays unbroken. */
#ssm-corner .ssm-corner-rule {
	display: block;
	width: 26px;
	height: 1px;
	background: rgba(0, 0, 0, .12);
}
html[data-theme="dark"] #ssm-corner .ssm-corner-rule { background: rgba(255, 255, 255, .14); }

/* ---- the switch -------------------------------------------------------- */
/* Upright: sun at the top, moon at the bottom, the knob travelling between
   them. No chrome of its own -- the capsule above is the chrome now. */
#ssm-theme {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 5px;
	margin: 0;
	padding: 7px 0 6px;
	cursor: pointer;
}
#ssm-theme input {
	position: absolute;
	opacity: 0;
	width: 1px;
	height: 1px;
	margin: 0;
}
/* The track and its knob, stood on end. */
#ssm-theme .ssm-theme-track {
	position: relative;
	display: block;
	width: 20px;
	height: 36px;
	border-radius: 999px;
	background: #cbd3dc;
	transition: background-color .25s ease;
	flex: 0 0 auto;
}
#ssm-theme .ssm-theme-track:after {
	content: "";
	position: absolute;
	top: 3px;
	left: 2px;
	width: 16px;
	height: 16px;
	border-radius: 50%;
	background: #fff;
	box-shadow: 0 1px 3px rgba(0, 0, 0, .3);
	transition: transform .25s ease, background-color .25s ease;
}
/* Checked is dark, and dark is the bottom of the track. */
#ssm-theme input:checked + .ssm-theme-track { background: #3498db; }
#ssm-theme input:checked + .ssm-theme-track:after { transform: translateY(14px); }
#ssm-theme input:focus-visible + .ssm-theme-track {
	box-shadow: 0 0 0 3px rgba(52, 152, 219, .4);
}
/* The sun above and the moon below fade with the state, so which way is which
   is obvious without reading a label. */
#ssm-theme .ssm-theme-icon {
	display: flex;
	align-items: center;
	transition: opacity .25s ease;
}
#ssm-theme .ssm-theme-icon svg { display: block; }
#ssm-theme .ssm-theme-sun { opacity: 1; }
#ssm-theme .ssm-theme-moon { opacity: .35; }
html[data-theme="dark"] #ssm-theme .ssm-theme-sun { opacity: .35; }
html[data-theme="dark"] #ssm-theme .ssm-theme-moon { opacity: 1; }

/* ---- the jump buttons -------------------------------------------------- */
#ssm-scroll {
	display: flex;
	flex-direction: column;
	align-items: center;
	width: 100%;
}
/* A page with nowhere to scroll keeps the hairline to itself as well. */
#ssm-scroll.is-idle,
#ssm-scroll.is-idle + .ssm-corner-rule,
.ssm-corner-rule.is-idle { display: none; }

/* These are the admin's only buttons that are not meant to look like buttons,
   so every inherited button style is unset rather than overridden -- style.css
   gives every <button> a grey gradient, a border and a shadow. */
#ssm-corner .ssm-scroll-btn {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 38px;
	height: 27px;
	margin: 0;
	padding: 0;
	border: 0;
	border-radius: 0;
	background: none;
	box-shadow: none;
	color: inherit;
	cursor: pointer;
	transition: color .2s ease, background-color .2s ease, opacity .2s ease;
}
#ssm-corner .ssm-scroll-btn:hover:not(:disabled) { background: rgba(52, 152, 219, .14); color: #2c80b4; }
#ssm-corner .ssm-scroll-btn:focus-visible { outline: 2px solid #3498db; outline-offset: -2px; }
#ssm-corner .ssm-scroll-btn:disabled { opacity: .3; cursor: default; }
#ssm-corner .ssm-scroll-btn svg { display: block; }
html[data-theme="dark"] #ssm-corner .ssm-scroll-btn:hover:not(:disabled) {
	background: rgba(52, 152, 219, .22);
	color: #8fd0f7;
}
/* The corner's own reduced-motion block is gone too: it froze the switch knob
   and the arrows' hover fade on the same machines, which made the one control
   the crossfade starts from the one control that never moved. */

/* --------------------------------------------------------------------------
   THE CROSSFADE
   Switching themes repaints every colour on the page in one frame, which reads
   as a jolt. js/theme.js puts this class on <html> for the flip only.

   HOW IT USED TO WORK, AND WHY IT DOES NOT ANY MORE
     This rule used to be `html.is-theme-switching *` with twelve colour
     properties on it, so the browser interpolated every colour on the page,
     element by element, for a whole second. It looked right on paper and it
     could not hold a frame rate: a product page has about 1,600 elements, and
     with each one animating twelve properties -- plus its ::before and
     ::after -- that is tens of thousands of interpolations and a full-page
     repaint, sixty times a second. Measured in a browser it managed 9fps,
     with single frames taking 217ms. The fade was smooth in intent and
     visibly choppy in fact, and trimming the property list only brought it to
     20fps: the cost is repainting the page, not the length of the list.

     So nothing on the page transitions at all now. A single layer fades over
     the top instead, the swap happens behind it while it is opaque, and it
     fades away again. Opacity on one fixed element is composited on the GPU,
     so it costs no repaints and holds 60fps however large the page is. One
     element doing one cheap thing, rather than sixteen hundred doing twelve
     expensive ones.

   WHAT THE CLIENT SEES
     The page settles into the colour it is heading for, then the new theme
     appears out of it. Because the layer is the DESTINATION background, going
     to dark sinks into the dark background and comes back up in dark -- it
     reads as the page turning over rather than as a flash of something else.
     The switch itself sits above the layer and keeps its own fade, so the
     control the client is looking at stays lit while the page behind it
     changes.
   -------------------------------------------------------------------------- */

/* The two resting backgrounds, as tokens rather than numbers in a script.
   Declared outside the dark block so BOTH are readable in either theme, which
   is the point: the layer has to know the colour it is going to before the
   page gets there. #f1f1f1 is the light body, #14181d the dark one. */
:root {
	--ssm-fade-light: #f1f1f1;
	--ssm-fade-dark: #14181d;
}

#ssm-theme-fade {
	position: fixed;
	top: 0; right: 0; bottom: 0; left: 0;
	/* Below #ssm-corner (1000001) and above everything else. The switch stays
	   visible and its knob keeps sliding while the page behind it turns. */
	z-index: 1000000;
	pointer-events: none;
	opacity: 0;
	/* Its own layer, told so in advance: without this the browser promotes it
	   on the first frame of the fade, and that first frame is the one that
	   stutters. */
	will-change: opacity;
	transform: translateZ(0);
}
/* Half the second going in, half coming out. The swap happens at the join,
   when this is fully opaque and the page underneath cannot be seen. */
#ssm-theme-fade.is-in  { transition: opacity .5s ease-in;  opacity: 1; }
#ssm-theme-fade.is-out { transition: opacity .5s ease-out; opacity: 0; }

/* The corner is the one thing above the layer, so it is the one thing that
   still fades its own colours -- six elements, which costs nothing. Its knob
   keeps the quick .25s slide it has at rest: the knob is the direct answer to
   the click and should land straight away, while the page takes its second. */
html.is-theme-switching #ssm-corner,
html.is-theme-switching #ssm-corner * {
	transition: background-color 1s ease, border-color 1s ease,
	            color 1s ease, fill 1s ease, stroke 1s ease, opacity 1s ease;
}
html.is-theme-switching #ssm-theme .ssm-theme-track:after {
	transition: transform .25s ease, background-color 1s ease;
}

/* The page's gradient layer must be in its final state the moment the cover
   starts lifting, or it would still be fading in behind it and the reveal
   would show it mid-way. It is hidden while it changes, so it changes at
   once. */
html.is-theme-switching body::before { transition: none !important; }
/* The reduced-motion block that used to sit here killed every transition the
   crossfade depends on, so with "reduce motion" on in the operating system the
   themes swapped in one frame however long SWITCH_MS was set to. It is gone,
   together with the matching bail in js/theme.js -- see the note there. */
