/*--------------------------------------------------------------
# SaveTrainer mobile app shell
#
# Below 840px -- the width the sidebar has always collapsed at -- SaveTrainer
# swaps its sidebar for a fixed top band, a fixed bottom tab bar and a More
# sheet. Everything here lives inside that one media query: above it, not a
# single rule applies and the desktop sidebar is untouched.
#
# The goal is that it stops reading as a website. Most of that is not layout:
# it is the tap that answers instantly, the chrome that never moves, the page
# that changes without flashing white, and geometry that respects the phone.
--------------------------------------------------------------*/

.st-app {
	display: none;
}

/* Narrow OR short. A phone turned sideways is wider than 840px on every model
   from the iPhone 14 up -- 844, 932, 956 -- so a width-only rule handed those
   members the 260px desktop sidebar, on a viewport 390px tall, with the
   sidebar's own min-height of 730px. Height is what actually separates the
   cases: phones in landscape top out around 440px, the shortest tablet in
   landscape is 744px. 500px sits between them with room either side, and it
   catches an unusually short desktop window too -- where the sidebar does not
   fit either. */
@media all and (max-width: 840px), all and (max-height: 500px) {

	:root {
		--st_app_top_h: 52px;
		--st_app_tabs_h: 56px;

		/* 12px, not the 10px iOS uses for tab labels -- that size is tuned for
		   eyes this product's members mostly do not have. 12 is the ceiling,
		   not a preference: "Community" set semibold is the widest label the
		   bar has to hold, and it starts clipping at 12.5px on a 360px phone.
		   Below 360 it steps back down (see the rule under this block). */
		--st_app_label: 12px;

		/* Insets for the fill behind each tab. Top is larger than bottom on
		   purpose: it lifts the fill off the bar's top edge, and sits the
		   content high inside it so the label has room beneath. */
		--st_tab_fill_top: 5px;
		--st_tab_fill_bottom: 2px;
		--st_tab_fill_side: 1px;

		--st_app_on_light: #5e6d8c;
		--st_app_ink: #253540;
		--st_app_rule: rgba(255, 255, 255, .12);
		--st_app_rule_light: rgba(37, 53, 64, .11);
		--st_app_press: #f1f4fa;

		/* One colour per destination in the More sheet. Each is darkened until
		   it clears 3:1 on white -- the mockup's hues read beautifully on navy
		   and several of them would have been invisible here. */
		--st_i_violet: #7c6bc4;
		--st_i_teal: #0f9e8e;
		--st_i_blue: #4c7df0;
		--st_i_pink: #e0559a;
		--st_i_amber: #b8730a;
		--st_i_indigo: #5a6bc8;
		--st_i_green: #2e9e5b;
	}

	/* A 320px screen cannot hold "Community" at 12px, so there it keeps the old
	   size rather than ellipsing a nav label. Phones this narrow are rare now,
	   but browser zoom lands here too. */
	@media all and (max-width: 359px) {

		:root {
			--st_app_label: 10.5px;
		}

	}

	/* Sideways, the two bands would otherwise eat 108px of a 390px-tall screen.
	   Trimming them hands nearly a quarter of the viewport back to the content,
	   and the labels still clear their icons at these heights. Must follow the
	   :root above, not precede it -- same specificity, so order decides. */
	@media all and (max-height: 500px) {

		:root {
			--st_app_top_h: 44px;
			--st_app_tabs_h: 52px;
			--st_tab_fill_top: 3px;
		}

		.st-app__sheet-head {
			padding-top: 8px;
			padding-bottom: 6px;
		}

		.st-app__list li > a {
			min-height: 46px;
		}

	}

	/*-- The old header steps aside ------------------------------------*/

	.st-app-shell .members-header,
	.st-app-shell .members-height-helper {
		display: none !important;
	}

	/* viewport-fit=cover lets the page run edge to edge, so the content has to
	   keep itself out of the notch in landscape as well as out from under the
	   bands.
	   The left padding is the sidebar's, and members.css only clears it below
	   840px -- which a phone in landscape is not. It has to be cleared here as
	   well, and out-specify .collapse-menu, or a member who left the sidebar
	   collapsed on desktop gets 64px of dead space down the side of the phone. */
	.st-app-shell .members-template .nm-page-wrap-inner,
	.st-app-shell.collapse-menu .members-template .nm-page-wrap-inner {
		padding-top: calc(var(--st_app_top_h) + env(safe-area-inset-top));
		padding-left: env(safe-area-inset-left);
		padding-right: env(safe-area-inset-right);
	}

	/* The sticky sub-menu pins itself to top:50px with z-index:999 -- both
	   written for the old 50px mobile header, which it would now sit 2px into
	   and paint over. It belongs under the band, at the band's height. */
	.st-app-shell .members-page-menu.stuck,
	.st-app-shell .members-page-menu-helper.stuck {
		top: calc(var(--st_app_top_h) + env(safe-area-inset-top)) !important;
		z-index: 50 !important;
	}

	/* Room under the last of the content for the tab bar. SaveTrainer has no
	   footer any more, so this sits on the content wrapper -- the last thing
	   on the page is now whatever the page itself ends with. */
	.st-app-shell .nm-page-wrap-inner {
		padding-bottom: calc(var(--st_app_tabs_h) + env(safe-area-inset-bottom) + 20px);
	}

	/* Plan Preview's floating CTA sticks itself to the bottom of the scrollport,
	   which under the shell is exactly where the tab bar is: it was parking 14px
	   up, inside the bar's 56px, and losing on z-index besides -- 8 against the
	   bar's 60 -- so the bar painted over it.

	   Lifted by the bar's own height, keeping the 14px as the gap above the bar
	   rather than above the viewport. It stays under the bar in stacking order,
	   which is the right way round: navigation is never something a page's CTA
	   should cover. Here rather than in savetrainer.css because the offset is
	   the bar's, and --st_app_tabs_h is only defined inside this query. */
	.st-app-shell .si-plan-cta--sticky {
		bottom: calc(var(--st_app_tabs_h) + env(safe-area-inset-bottom) + 14px);
	}

	/*-- Shell ---------------------------------------------------------*/

	.st-app-shell .st-app {
		display: block;
		font-family: 'Satoshi', 'Satoshi-Fallback', sans-serif;
	}

	/* Chrome is chrome: it is never selectable, never long-press-magnified,
	   and never waits 300ms to find out if you meant to zoom. */
	.st-app-shell .st-app,
	.st-app-shell .st-app * {
		-webkit-tap-highlight-color: transparent;
		-webkit-touch-callout: none;
		-webkit-user-select: none;
		user-select: none;
		touch-action: manipulation;
	}

	.st-app .screen-reader-text {
		position: absolute !important;
		width: 1px;
		height: 1px;
		padding: 0;
		margin: -1px;
		overflow: hidden;
		clip: rect(0, 0, 0, 0);
		white-space: nowrap;
		border: 0;
	}

	/*-- Top band ------------------------------------------------------*/

	.st-app__top {
		position: fixed;
		top: 0;
		left: 0;
		right: 0;
		z-index: 60;
		display: grid;
		grid-template-columns: 1fr auto 1fr;
		align-items: center;
		height: calc(var(--st_app_top_h) + env(safe-area-inset-top));
		padding: env(safe-area-inset-top) max(env(safe-area-inset-right), 6px) 0 max(env(safe-area-inset-left), 6px);
		background: var(--st_theme_dark);
		box-shadow: inset 0 -1px 0 var(--st_app_rule);
	}

	.st-app__edge {
		display: flex;
		flex-direction: column;
		align-items: center;
		justify-content: center;
		gap: 1px;
		min-width: 64px;
		min-height: 44px;
		padding: 2px 6px;
		color: #fff;
		text-decoration: none;
		transition: color .18s cubic-bezier(.22, 1, .36, 1);
	}

	.st-app__top > :nth-child(1) {
		justify-self: start;
	}

	.st-app__top > :nth-child(3) {
		justify-self: end;
	}

	.st-app__edge-icon {
		position: relative;
		display: block;
		line-height: 1;
	}

	.st-app__edge .lnr {
		display: block;
		font-size: 21px;
		line-height: 1;
	}

	.st-app__edge-label {
		font-size: var(--st_app_label);
		font-weight: 500;
		line-height: 1.2;
		letter-spacing: .005em;
	}

	.st-app__edge.is-current,
	.st-app__edge:hover {
		color: var(--st_theme_highlight);
	}

	/* The "New" flag on Assessment. A word does not survive at this size; a
	   dot does, and the word goes to screen readers instead. */
	.st-app__flag {
		position: absolute;
		top: -2px;
		right: -5px;
		width: 7px;
		height: 7px;
		background: var(--st_theme_accent);
		border: 1.5px solid var(--st_theme_dark);
		border-radius: 50%;
	}

	/* Same flag in the tab bar, where the surface behind it is white rather
	   than navy and the icon sits in a 48px pill. Positioned against the glyph
	   rather than the pill's corner, which would leave it floating. */
	.st-app__flag--tab {
		top: 0;
		right: 8px;
		border-color: #fff;
	}

	.st-app__tab.is-current .st-app__flag--tab {
		border-color: var(--st_theme_accent_light);
	}

	/* An expanding ring, not a shadow -- the one thing on this surface asking
	   to be noticed. It runs while the assessment is still untaken and, like
	   the unread-message dot in members.css, stops of its own accord rather
	   than pulsing at the member forever. */
	.st-app__flag--pulse {
		animation: stAppFlagPulse 2.6s 1.2s ease-out 100;
	}

	@keyframes stAppFlagPulse {
		0%  { box-shadow: 0 0 0 0 rgba(114, 216, 162, .65); }
		55% { box-shadow: 0 0 0 8px rgba(114, 216, 162, 0); }
		100% { box-shadow: 0 0 0 0 rgba(114, 216, 162, 0); }
	}

	.st-app__brand {
		display: flex;
		align-items: center;
		justify-content: center;
		padding: 0 8px;
		min-height: 44px;
	}

	.st-app__brand img {
		display: block;
		width: 142px;
		height: auto;
	}

	/* Navigation is under way. Answers the "did that register?" question on a
	   slow connection, which is the moment a web page feels least like an app. */
	.st-app__progress {
		position: absolute;
		left: 0;
		bottom: 0;
		width: 100%;
		height: 2px;
		transform: scaleX(0);
		transform-origin: 0 50%;
		background: var(--st_theme_highlight);
		opacity: 0;
	}

	.st-app.is-navigating .st-app__progress {
		opacity: 1;
		animation: stAppProgress 8s cubic-bezier(.12, .78, .28, 1) forwards;
	}

	/* Starts at 8% rather than 0, and covers most of its ground early. The old
	   curve spent its first 200ms under a fifth of the screen, so on a cached
	   page the line was a stub in the left corner and gone -- present, but not
	   perceivable. A progress line invisible on the fastest half of
	   navigations is not doing the job it exists for. */
	@keyframes stAppProgress {
		0%   { transform: scaleX(.08); }
		30%  { transform: scaleX(.72); }
		100% { transform: scaleX(.96); }
	}

	/* The finish, run by the page that just arrived. Starts where the outgoing
	   line plausibly got to, completes, then clears -- so a navigation always
	   ends with the same gesture whether the load took 80ms or two seconds. */
	.st-app.is-arriving .st-app__progress {
		opacity: 1;
		animation: stAppProgressDone .5s cubic-bezier(.22, 1, .36, 1) forwards;
	}

	@keyframes stAppProgressDone {
		0%   { transform: scaleX(.7); opacity: 1; }
		55%  { transform: scaleX(1); opacity: 1; }
		100% { transform: scaleX(1); opacity: 0; }
	}

	/*-- Tab bar -------------------------------------------------------*/

	.st-app__tabs {
		position: fixed;
		left: 0;
		right: 0;
		bottom: 0;
		z-index: 60;
		display: flex;
		height: calc(var(--st_app_tabs_h) + env(safe-area-inset-bottom));
		/* The bottom inset lifts the labels clear of the home indicator, which
		   on a home-screen install is also what lifts the outer two clear of
		   the display's rounded corners. The horizontal floor is for landscape,
		   and for the last couple of pixels of corner arc in portrait. */
		padding-bottom: env(safe-area-inset-bottom);
		padding-left: max(env(safe-area-inset-left), 4px);
		padding-right: max(env(safe-area-inset-right), 4px);
		background: #fff;
		box-shadow: 0 -1px 0 rgba(37, 53, 64, .1);
	}

	.st-app__tab {
		position: relative;
		flex: 1 1 0;
		display: flex;
		flex-direction: column;
		align-items: center;
		justify-content: center;
		gap: 2px;
		min-width: 0;
		padding: 0 2px;
		margin: 0;
		border: 0;
		background: none;
		font-family: inherit;
		text-decoration: none;
		cursor: pointer;
		-webkit-appearance: none;
		appearance: none;
	}

	/* More is the only tab that is a <button>; the other four are anchors. That
	   makes it the only one a theme or plugin button rule can reach, and one
	   of them paints it solid green on hover -- a state the other tabs have no
	   equivalent of, which is exactly why it looked wrong. Rather than chase
	   the rule, the tab declares its own surface in every state. Colour is
	   left alone here so the state rules below still own it. */
	.st-app__tabs .st-app__tab,
	.st-app__tabs .st-app__tab:hover,
	.st-app__tabs .st-app__tab:focus,
	.st-app__tabs .st-app__tab:active,
	.st-app__tabs .st-app__tab[aria-expanded="true"] {
		background: none;
		border: 0;
		box-shadow: none;
		text-shadow: none;
		text-transform: none;
		letter-spacing: .005em;
		color: var(--st_tab_ink);
	}

	/* Colour is pinned in the same breath. Leaving it to the state rules is
	   what let the stray rule through the first time -- it turned the icon and
	   label white on hover. The value arrives via a custom property, so the
	   states still choose it without any of them having to out-specify this. */
	.st-app__tab {
		--st_tab_ink: var(--st_app_ink);
	}

	.st-app__tab.is-current,
	.st-app__tab--more[aria-expanded="true"] {
		--st_tab_ink: var(--st_theme_green);
	}

	/* The children take the tab's colour rather than anything aimed at them
	   directly -- the icon font and the drawn dots both read currentColor. */
	.st-app__tabs .st-app__tab .lnr,
	.st-app__tabs .st-app__tab .st-app__tab-label,
	.st-app__tabs .st-app__tab:hover .lnr,
	.st-app__tabs .st-app__tab:hover .st-app__tab-label,
	.st-app__tabs .st-app__tab:focus .lnr,
	.st-app__tabs .st-app__tab:focus .st-app__tab-label,
	.st-app__tabs .st-app__tab:active .lnr,
	.st-app__tabs .st-app__tab:active .st-app__tab-label {
		color: inherit;
	}

	/* No background of its own any more -- the fill behind the whole tab does
	   that. The box stays because the flag and the unread dot position
	   against it. */
	.st-app__tab-icon {
		position: relative;
		display: flex;
		align-items: center;
		justify-content: center;
		width: 48px;
		height: 26px;
	}

	.st-app__tab .lnr {
		font-size: 22px;
		line-height: 1;
	}

	.st-app__tab-label {
		max-width: 100%;
		overflow: hidden;
		font-size: var(--st_app_label);
		font-weight: 500;
		line-height: 1.2;
		letter-spacing: .005em;
		text-overflow: ellipsis;
		white-space: nowrap;
	}

	/*-- Tab states ----------------------------------------------------
	 *
	 * One rounded rectangle behind the whole tab -- icon and label together --
	 * carries every state, and only its colour changes:
	 *
	 *   selected  mint, green icon and label, label semibold
	 *   pressed   mint, immediately -- the tap arrives at the finished state
	 *             rather than at a rehearsal of it
	 *   hover     the same mint; pointer devices only
	 *   pending   selected, moved optimistically by the tap, plus the top
	 *             band's progress line
	 *
	 * A selected tab keeps its mint through press and hover: the fill is
	 * saying "this is where you are", and the press should not overrule it.
	 *
	 * It is drawn as a pseudo-element rather than the tab's own background
	 * because the tabs are flush flex items -- a background on the tab itself
	 * would run edge to edge with no gap between neighbours.
	 *
	 * The side inset is 1px, which is all there is: the widest label is
	 * "Assessment" set semibold at 65.4px, inside a 75px tab on a 375px phone.
	 * The label is 87% of the tab, so the only real lever on horizontal
	 * breathing room is the type size, not this number.
	 *
	 * Vertically there was room, taken from the icon's box and the gap under
	 * it. The fill now starts 5px down rather than 2, so it is not riding the
	 * bar's top edge, and the content sits high inside it -- 1.8px above,
	 * 4.8px below -- so the label has space beneath rather than being centred
	 * between two equal slivers.
	 */

	.st-app__tab:before {
		content: "";
		position: absolute;
		top: var(--st_tab_fill_top);
		right: var(--st_tab_fill_side);
		bottom: var(--st_tab_fill_bottom);
		left: var(--st_tab_fill_side);
		border-radius: 12px;
		background: transparent;
		transition: background-color .18s ease;
	}

	/* Above the fill: the pseudo-element is painted first. */
	.st-app__tab-icon,
	.st-app__tab-label {
		position: relative;
	}

	.st-app__tab.is-current:before,
	.st-app__tab--more[aria-expanded="true"]:before {
		background: var(--st_theme_accent_light);
	}

	.st-app__tab.is-current .st-app__tab-label {
		font-weight: 600;
	}

	/* Pressing paints the selected state, not a grey waiting room. :active
	   fires on touch-down, so the mint lands under the finger immediately --
	   the optimistic is-current the tap applies on release then holds it
	   through the navigation, and the loaded page arrives already wearing it.
	   Grey is left to hover, which is a pointer hesitating rather than a
	   commitment, and never happens on touch at all. */
	.st-app__tab:active:before {
		background: var(--st_theme_accent_light);
	}

	.st-app__tab:active {
		--st_tab_ink: var(--st_theme_green);
	}

	/* The flag sits on whatever the fill currently is, so its ring matches. */
	.st-app__tab:active .st-app__flag--tab {
		border-color: var(--st_theme_accent_light);
	}

	/* One mint under the finger as well. The script moves is-current on
	   pointerdown, which is what actually does this; the rule is here so a
	   browser whose script failed still never shows two. */
	.st-app__tabs:has(.st-app__tab:active) .st-app__tab.is-current:not(:active):before {
		background: transparent;
	}

	.st-app__tabs:has(.st-app__tab:active) .st-app__tab.is-current:not(:active) {
		--st_tab_ink: var(--st_app_ink);
	}

	@media (hover: hover) {

		/* Hover is mint too, so the pointer previews exactly what a tap gives
		   rather than a grey rehearsal of it. */
		.st-app__tab:hover:before {
			background: var(--st_theme_accent_light);
		}

		.st-app__tab:hover {
			--st_tab_ink: var(--st_theme_green);
		}

		.st-app__tab:hover .st-app__flag--tab {
			border-color: var(--st_theme_accent_light);
		}

		/* One mint at a time. Without this the tab under the pointer and the
		   tab you are actually on both light up, and the bar stops answering
		   the question it exists to answer. The current tab yields, and takes
		   its ink and its flag ring back to the resting colours with it. */
		.st-app__tabs:has(.st-app__tab:hover) .st-app__tab.is-current:not(:hover):before {
			background: transparent;
		}

		.st-app__tabs:has(.st-app__tab:hover) .st-app__tab.is-current:not(:hover) {
			--st_tab_ink: var(--st_app_ink);
		}

		.st-app__tabs:has(.st-app__tab:hover) .st-app__tab.is-current:not(:hover) .st-app__flag--tab {
			border-color: #fff;
		}

	}

	/* Linearicons has no ellipsis, and "More" wants one rather than a second
	   hamburger -- so it is drawn, in currentColor, and follows the tab's
	   active and pressed states for free. */
	.st-app__dots {
		position: relative;
		display: block;
		width: 4px;
		height: 4px;
		border-radius: 50%;
		background: currentColor;
	}

	.st-app__dots:before,
	.st-app__dots:after {
		content: "";
		position: absolute;
		top: 0;
		width: 4px;
		height: 4px;
		border-radius: 50%;
		background: currentColor;
	}

	.st-app__dots:before {
		left: -7px;
	}

	.st-app__dots:after {
		left: 7px;
	}

	/* Unread notifications live in the sheet, so More carries their dot. The
	   base rule (members.css) puts it inline after the link text; here it
	   belongs on the icon. */
	.new-messages .st-app__tab--more .st-app__tab-icon:after {
		content: "";
		position: absolute;
		top: -3px;
		right: 7px;
		width: 8px;
		height: 8px;
		background: #eb5a46;
		border: 2px solid #fff;
		border-radius: 50%;
	}

	/*-- Pull to refresh -----------------------------------------------
	 *
	 * The browser's own is suppressed (from JS, so it is only ever off when
	 * this handler is actually live) and replaced, because the native one
	 * differs between Safari, Chrome and a home-screen install -- and in a
	 * shell that is pretending to be an app, a refresh that behaves three ways
	 * is worse than one we control.
	 */

	.st-app__refresh {
		position: fixed;
		top: calc(var(--st_app_top_h) + env(safe-area-inset-top));
		left: 50%;
		z-index: 55;
		display: flex;
		align-items: center;
		justify-content: center;
		width: 36px;
		height: 36px;
		margin: -46px 0 0 -18px;
		border-radius: 50%;
		background: #fff;
		box-shadow: 0 6px 16px -6px rgba(15, 22, 44, .4);
		opacity: 0;
		pointer-events: none;
		transition: transform .3s cubic-bezier(.32, .72, 0, 1), opacity .3s ease;
	}

	/* While a finger is on it the indicator tracks the pull directly, so the
	   transition has to be out of the way. */
	.st-app.is-pulling .st-app__refresh,
	html.st-app-pulling .nm-page-wrap-inner {
		transition: none;
	}

	/* The content travels with the finger and eases back on release. The bands
	   are fixed and sit outside this wrapper, so they hold still while it
	   moves -- which is the whole point: chrome stays, page gives. */
	.st-app-shell .nm-page-wrap-inner {
		transition: transform .34s cubic-bezier(.32, .72, 0, 1);
	}

	.st-app__refresh-spinner {
		width: 16px;
		height: 16px;
		border: 2px solid rgba(37, 53, 64, .16);
		border-top-color: var(--st_theme_green);
		border-radius: 50%;
	}

	.st-app__refresh.is-ready .st-app__refresh-spinner {
		border-color: var(--st_theme_accent_light);
		border-top-color: var(--st_theme_green);
	}

	.st-app.is-refreshing .st-app__refresh {
		opacity: 1;
		transform: translate3d(0, 70px, 0);
	}

	.st-app.is-refreshing .st-app__refresh-spinner {
		animation: stAppSpin .7s linear infinite;
	}

	@keyframes stAppSpin {
		to { transform: rotate(360deg); }
	}

	/*-- More sheet ----------------------------------------------------*/

	.st-app__scrim {
		position: fixed;
		inset: 0;
		z-index: 70;
		background: rgba(15, 22, 44, .55);
		opacity: 0;
		transition: opacity .32s cubic-bezier(.32, .72, 0, 1);
	}

	/* [hidden] would take these out of the layout mid-transition, so the
	   attribute stays as the semantic signal and visibility does the hiding
	   once the sheet has finished sliding out. */
	.st-app__scrim[hidden] {
		display: block;
		visibility: hidden;
		pointer-events: none;
		transition: opacity .32s cubic-bezier(.32, .72, 0, 1), visibility 0s .32s;
	}

	.st-app.is-open .st-app__scrim {
		opacity: 1;
	}

	.st-app__sheet {
		position: fixed;
		top: 0;
		right: 0;
		z-index: 80;
		display: flex;
		flex-direction: column;
		width: min(400px, 88vw);
		height: 100dvh;
		max-height: 100dvh;
		padding: env(safe-area-inset-top) env(safe-area-inset-right) env(safe-area-inset-bottom) 0;
		background: #fff;
		box-shadow: -24px 0 60px -12px rgba(11, 16, 33, .35);
		transform: translate3d(100%, 0, 0);
		transition: transform .42s cubic-bezier(.32, .72, 0, 1);
	}

	.st-app__sheet[hidden] {
		display: flex;
		visibility: hidden;
		pointer-events: none;
		transition: transform .34s cubic-bezier(.32, .72, 0, 1), visibility 0s .34s;
	}

	.st-app.is-open .st-app__sheet {
		transform: translate3d(0, 0, 0);
	}

	/* Live only while a finger is on the sheet, so the drag tracks 1:1. */
	.st-app.is-dragging .st-app__sheet,
	.st-app.is-dragging .st-app__scrim {
		transition: none;
	}

	/* Just a home for Close. The list starts as high as the chip's 44px target
	   allows, which is the point of dropping the heading. */
	.st-app__sheet-head {
		display: flex;
		align-items: center;
		justify-content: flex-end;
		padding: 14px 12px 10px 26px;
	}

	/* Named, not just marked with a glyph. Members here are largely 50+, and a
	   bare cross is the control people hesitate over -- it means "close" by
	   convention learned elsewhere, not by looking like anything. The word
	   removes the guess; the ink colour rather than the muted grey takes it
	   from 4.5:1 to roughly 9:1 for reading on a phone in daylight. */
	.st-app__sheet-close {
		position: relative;
		display: flex;
		align-items: center;
		gap: 7px;
		height: 36px;
		padding: 0 13px 0 11px;
		border: 0;
		border-radius: 10px;
		background: #eef1f7;
		color: var(--st_app_ink);
		font-family: inherit;
		font-size: 14px;
		font-weight: 600;
		line-height: 1;
		cursor: pointer;
		-webkit-appearance: none;
		appearance: none;
		transition: background-color .2s ease, transform .12s cubic-bezier(.22, 1, .36, 1);
	}

	.st-app__sheet-close .lnr {
		font-size: 13px;
	}

	/* The chip is sized to sit beside the heading rather than compete with it;
	   the target it answers to stays 44px. */
	.st-app__sheet-close:after {
		content: "";
		position: absolute;
		inset: -4px;
	}

	/* Pinned in every state for the same reason the tab bar is: a stray button
	   rule in the theme paints buttons green with white text on hover and
	   press, which turned the X and its label invisible against this chip.
	   Hover and press take the tab bar's mint, and the ink never moves. */
	.st-app__sheet-close,
	.st-app__sheet-close:hover,
	.st-app__sheet-close:focus,
	.st-app__sheet-close:active {
		color: var(--st_app_ink);
		border: 0;
		box-shadow: none;
		text-shadow: none;
	}

	.st-app__sheet-close .lnr,
	.st-app__sheet-close span,
	.st-app__sheet-close:hover .lnr,
	.st-app__sheet-close:hover span,
	.st-app__sheet-close:active .lnr,
	.st-app__sheet-close:active span {
		color: inherit;
	}

	.st-app__sheet-close:hover {
		background: var(--st_theme_accent_light);
	}

	.st-app__sheet-close:active {
		transform: scale(.94);
		background: var(--st_theme_accent_light);
	}

	.st-app__sheet-scroll {
		flex: 1 1 auto;
		padding: 0 0 calc(20px + env(safe-area-inset-bottom));
		overflow-y: auto;
		overscroll-behavior: contain;
		-webkit-overflow-scrolling: touch;
	}

	/*-- Sheet rows ----------------------------------------------------*/

	/* Deliberately loose selectors: the WP-admin-managed items land in this
	   list as raw <li> markup with their own classes, and they have to sit in
	   the rhythm without being rewritten. */
	.st-app__list {
		margin: 0;
		padding: 0;
		list-style: none;
	}

	.st-app__list li {
		position: relative;
		margin: 0;
		padding: 0;
		list-style: none;
		border-bottom: 0;
	}

	/* No dividers. The highlight is an inset rounded rectangle, so it is the
	   row's boundary -- a rule under every row would only draw the same
	   division twice. This is the shape the desktop sidebar's own menu items
	   already use, down to the 10px radius, so the sheet and the sidebar are
	   one component at two sizes. */
	.st-app__list li > a {
		display: flex;
		align-items: center;
		gap: 16px;
		min-height: 54px;
		margin: 0 12px;
		padding: 5px 14px;
		border-radius: 10px;
		color: var(--st_app_ink);
		font-size: 17px;
		font-weight: 500;
		line-height: 1.25;
		text-decoration: none;
		transition: background-color .12s ease, color .16s ease;
	}

	.st-app__list li > a:active {
		background: var(--st_app_press);
	}

	@media (hover: hover) {
		.st-app__list li > a:hover {
			background: var(--st_app_press);
		}
	}

	.st-app__list li > a .lnr {
		flex: 0 0 auto;
		width: 26px;
		color: var(--st_i_violet);
		font-size: 21px;
		text-align: center;
		transition: color .16s ease;
	}

	.st-app__list li > a svg {
		flex: 0 0 auto;
		width: 24px;
		min-width: 24px;
	}

	/* A colour per destination, so the sheet is scanned by shape and hue
	   rather than read line by line. Keyed off data-st-key, which the shell
	   stamps from the same nav list the sidebar uses. */
	.st-app__list [data-st-key="dashboard"] .lnr    { color: var(--st_i_indigo); }
	.st-app__list [data-st-key="assessment"] .lnr   { color: var(--st_i_green); }
	.st-app__list [data-st-key="my-plan"] .lnr      { color: var(--st_i_blue); }
	.st-app__list [data-st-key="workouts"] .lnr     { color: var(--st_i_indigo); }
	.st-app__list [data-st-key="plans"] .lnr        { color: var(--st_i_blue); }
	.st-app__list [data-st-key="plan-builder"] .lnr { color: var(--st_i_teal); }
	.st-app__list [data-st-key="challenges"] .lnr   { color: var(--st_i_green); }
	.st-app__list [data-st-key="history"] .lnr      { color: var(--st_i_violet); }
	.st-app__list [data-st-key="downloads"] .lnr    { color: var(--st_i_indigo); }
	.st-app__list [data-st-key="favorites"] .lnr    { color: var(--st_i_pink); }
	.st-app__list [data-st-key="trainers"] .lnr     { color: var(--st_i_violet); }
	.st-app__list [data-st-key="discussion"] .lnr   { color: var(--st_i_blue); }

	/* WP-admin-managed items carry classes, not keys. */
	.st-app__list .notifications-item .lnr { color: var(--st_i_amber); }

	/* "Return to Save Institute" keeps the inline SVG arrow it carries from the
	   menu item, colour baked into a presentation attribute. CSS outranks
	   those, so the arrow simply takes the row's ink. .st-return covers the
	   item wherever it is still passed through untouched. */
	.st-app__list .st-return a svg,
	.st-app__list [data-st-key="return"] a svg {
		width: 21px;
		height: 21px;
		stroke: currentColor;
	}

	.st-app__list li.is-active > a,
	.st-app__list li.current-menu-item > a,
	.st-app__list li.is-active > a .lnr,
	.st-app__list li.current-menu-item > a .lnr {
		color: var(--st_theme_green);
	}

	/* Every destination row says "this leads somewhere" -- except the account
	   block, which is the end of the line. Drawn with ::before and pushed last
	   by order, because ::after is already the unread-notification dot. */
	.st-app__list:not(.st-app__list--account) li > a:before {
		content: "\e876";
		order: 9;
		margin-left: auto;
		padding-left: 12px;
		font-family: 'linearicons';
		font-size: 13px;
		font-weight: normal;
		color: #9aa5bc;
		speak: never;
	}

	/* White text needs the darker brand green underneath it -- white on the
	   mint accent is 1.7:1, which is not readable at 11px or at any size. On
	   this green it is 5:1. */
	.st-app__tag {
		padding: 2px 8px;
		border-radius: 999px;
		background: var(--st_theme_green);
		color: #fff;
		font-size: 11px;
		font-style: normal;
		font-weight: 700;
		letter-spacing: .02em;
	}

	/* The one rule left in the sheet, and it separates the two groups rather
	   than the rows -- destinations above, account below. Inset to the same
	   12px the row highlights sit at. */
	.st-app__list--account {
		margin: 14px 12px 0;
		padding-top: 10px;
		border-top: 1px solid var(--st_app_rule_light);
	}

	.st-app__list--account li > a {
		min-height: 48px;
		margin: 0;
		font-size: 15.5px;
		font-weight: 400;
		color: var(--st_app_on_light);
	}

	/* Account rows are housekeeping, not destinations, so their icons stay the
	   colour of the words beside them and the colour coding means "somewhere
	   to go". */
	.st-app__list--account li > a .lnr {
		font-size: 18px;
		color: inherit;
	}

	/* The page footer's job on a phone belongs to the sheet, so the two never
	   both appear. Hiding it here rather than in savetrainer.css means it is
	   governed by this file's media query -- a separate max-width would show
	   both on a phone in landscape, which is 844px wide. */
	.st-app-shell .st-footer {
		display: none;
	}

	.st-app__legal {
		margin: 22px 0 0;
		padding: 0 26px;
		color: var(--st_app_on_light);
		font-size: 12.5px;
		line-height: 1.5;
	}

	.st-app__legal a {
		color: var(--st_app_on_light);
		text-decoration: underline;
		text-underline-offset: 2px;
		text-decoration-thickness: 1px;
	}

	.st-app__legal a:active {
		color: var(--st_app_ink);
	}

	.st-footer__mark {
		white-space: nowrap;
	}

	/*-- Focus ---------------------------------------------------------*/

	/* The sheet takes focus on open so its title is announced; that is a
	   programmatic focus, not a keyboard one, so it must not draw a ring. */
	.st-app__sheet:focus {
		outline: none;
	}

	/* :focus-visible alone is not enough here. Safari will match it on a button
	   that was tapped, and the shell hands focus back to More when the sheet
	   closes -- so a ring was being drawn round the whole tab and left there
	   after a touch that never asked for one. The ring is now gated on the
	   member having actually reached for a keyboard, and on the tabs it hugs
	   the icon pill rather than boxing the tab. */
	.st-app a:focus,
	.st-app button:focus {
		outline: none;
	}

	html.st-app-keyboard .st-app a:focus-visible,
	html.st-app-keyboard .st-app button:focus-visible {
		outline: 2px solid var(--st_theme_highlight);
		outline-offset: 2px;
		border-radius: 10px;
	}

	html.st-app-keyboard .st-app__tab:focus-visible {
		outline: none;
	}

	html.st-app-keyboard .st-app__tab:focus-visible .st-app__tab-icon {
		outline: 2px solid var(--st_theme_green);
		outline-offset: 2px;
	}

	html.st-app-keyboard .st-app__edge:focus-visible {
		outline-color: var(--st_theme_highlight);
	}

	/*-- The page beneath ----------------------------------------------*/

	html.st-app-locked,
	html.st-app-locked body {
		overflow: hidden;
	}

	/*-- Between pages -------------------------------------------------*/

	/* Cross-document view transitions: the two bands hold still and only the
	   content between them changes, so tapping a tab reads as a view change
	   rather than a page load. Browsers without support simply navigate.  */
	@view-transition {
		navigation: auto;
	}

	.st-app__top {
		view-transition-name: st-app-top;
	}

	.st-app__tabs {
		view-transition-name: st-app-tabs;
	}

	::view-transition-old(root) {
		animation-duration: .18s;
		animation-timing-function: cubic-bezier(.4, 0, 1, 1);
	}

	::view-transition-new(root) {
		animation-duration: .26s;
		animation-timing-function: cubic-bezier(0, 0, .2, 1);
	}

	/* The bands swap outright instead of cross-fading. By default a named
	   element fades its old snapshot out while the new one fades in, each with
	   its own opacity -- and two independently fading copies of the same
	   opaque thing never add back up to opaque. Composite alpha peaks below 1
	   partway through, so the bar and the mint on it went pale mid-navigation
	   and recovered on arrival. Naming these was meant to keep them still;
	   fading them was the opposite. */
	::view-transition-old(st-app-top),
	::view-transition-old(st-app-tabs) {
		animation: none;
		opacity: 0;
	}

	::view-transition-new(st-app-top),
	::view-transition-new(st-app-tabs) {
		animation: none;
		opacity: 1;
	}

	/*-- Reduced motion ------------------------------------------------*/

	@media (prefers-reduced-motion: reduce) {

		.st-app__sheet,
		.st-app__scrim,
		.st-app__tab-icon,
		.st-app__list li > a,
		.st-app__sheet-close {
			transition-duration: .01ms !important;
		}

		.st-app.is-navigating .st-app__progress {
			animation: none;
			opacity: 1;
			transform: scaleX(.35);
		}

		.st-app.is-arriving .st-app__progress {
			animation: none;
			opacity: 1;
			transform: scaleX(1);
		}

		.st-app__flag--pulse {
			animation: none;
		}

		.st-app.is-refreshing .st-app__refresh-spinner {
			animation: none;
		}

		::view-transition-group(*),
		::view-transition-old(*),
		::view-transition-new(*) {
			animation: none !important;
		}
	}

}
