/* =============================================================================
   IzeChat — post overflow menu as a Material 3 modal bottom sheet
   -----------------------------------------------------------------------------
   Presentation layer ONLY. The stock markup is a Bootstrap dropdown:

       <div class="dropdown tag_post_hdr_menu">
         <div class="dropdown-toggle" data-toggle="dropdown"> … </div>
         <ul class="dropdown-menu post-privacy-menu tag_create_menu"> <li><a …>
       </div>

   …which renders as a floating white card pinned to the chevron — i.e. a website
   popup. On mobile / inside the Android shell, ize-post-sheet.js suppresses that
   dropdown and re-presents the SAME <a> items inside the sheet below. Every
   onclick / href / class on those anchors is untouched: the sheet re-fires the
   original element, so all backend behaviour is bit-identical.

   Sizing follows the Material 3 bottom-sheet spec: 28dp top corners, 32×4dp drag
   handle, 56dp+ row targets, 24dp icons, scrim at 32–60% depending on theme.

   Colour comes from custom properties only — light / dark / AMOLED swap the
   property block, never a rule. Dark is keyed off #night-mode-css, which
   container.phtml treats as the single source of truth for "the page is dark".
   ========================================================================== */

/* ---------- Theme tokens ---------------------------------------------------- */
.ize-ps {
	--ize-ps-surface:   #ffffff;
	--ize-ps-ink:       #1c1e21;
	--ize-ps-ink-2:     #65676b;
	--ize-ps-hair:      rgba(0, 0, 0, .10);
	--ize-ps-handle:    rgba(0, 0, 0, .22);
	--ize-ps-press:     rgba(0, 0, 0, .07);
	--ize-ps-ripple:    rgba(0, 0, 0, .10);
	--ize-ps-danger:    #e02b3f;
	--ize-ps-danger-bg: rgba(224, 43, 63, .10);
	--ize-ps-scrim:     rgba(0, 0, 0, .40);
	--ize-ps-shadow:    0 -2px 20px rgba(17, 24, 39, .14);
}

html:has(#night-mode-css) .ize-ps,
html.ize-dark .ize-ps {
	--ize-ps-surface:   #212121;
	--ize-ps-ink:       #e4e6eb;
	--ize-ps-ink-2:     #b0b3b8;
	--ize-ps-hair:      rgba(255, 255, 255, .12);
	--ize-ps-handle:    rgba(255, 255, 255, .28);
	--ize-ps-press:     rgba(255, 255, 255, .09);
	--ize-ps-ripple:    rgba(255, 255, 255, .13);
	--ize-ps-danger:    #ff6b7d;
	--ize-ps-danger-bg: rgba(255, 107, 125, .14);
	--ize-ps-scrim:     rgba(0, 0, 0, .60);
	--ize-ps-shadow:    0 -2px 22px rgba(0, 0, 0, .55);
}

/* AMOLED: true black so the sheet costs no backlight on OLED panels. Applied by
   whatever sets .ize-amoled on <html>/<body>; falls back to the dark block above
   until that mode is switched on, so nothing regresses in the meantime.
   The last two selectors exist purely for specificity: :has(#night-mode-css)
   carries ID weight, so a plain .ize-amoled rule would LOSE to the dark block
   whenever both are active — which is exactly when AMOLED matters. */
html.ize-amoled .ize-ps,
body.ize-amoled .ize-ps,
html.ize-amoled:has(#night-mode-css) .ize-ps,
html:has(#night-mode-css) body.ize-amoled .ize-ps {
	--ize-ps-surface:   #000000;
	--ize-ps-ink:       #ededed;
	--ize-ps-ink-2:     #9aa0a6;
	--ize-ps-hair:      rgba(255, 255, 255, .16);
	--ize-ps-handle:    rgba(255, 255, 255, .32);
	--ize-ps-press:     rgba(255, 255, 255, .11);
	--ize-ps-ripple:    rgba(255, 255, 255, .16);
	--ize-ps-scrim:     rgba(0, 0, 0, .72);
	--ize-ps-shadow:    0 -1px 0 rgba(255, 255, 255, .10);
}

/* ---------- Root ------------------------------------------------------------ */
/* Sits above the fixed navbar (1045) and the bottom tab bar; below nothing else
   it opens, because a row always closes the sheet BEFORE firing its action. */
.ize-ps {
	position: fixed;
	inset: 0;
	z-index: 1200;
	display: none;
	/* No background here — the scrim child owns it so the two can fade on
	   different curves without the sheet inheriting opacity. */
}

.ize-ps.ize-ps-mounted { display: block; }

.ize-ps-scrim {
	position: absolute;
	inset: 0;
	background: var(--ize-ps-scrim);
	opacity: 0;
	transition: opacity 200ms linear;
	-webkit-tap-highlight-color: transparent;
}

.ize-ps.ize-ps-open .ize-ps-scrim { opacity: 1; }
.ize-ps.ize-ps-closing .ize-ps-scrim { opacity: 0; transition-duration: 180ms; }

/* ---------- Sheet ----------------------------------------------------------- */
.ize-ps-sheet {
	position: absolute;
	left: 0;
	right: 0;
	bottom: 0;
	margin: 0 auto;
	width: 100%;
	/* Phones get the full width; a tablet or a desktop browser that still lands
	   on the sheet gets a centred panel instead of a 1200px-wide slab. */
	max-width: 640px;

	display: flex;
	flex-direction: column;
	box-sizing: border-box;

	/* Adaptive height: hugs its content, and only starts scrolling when the list
	   would otherwise run under the status bar. dvh where supported so the
	   Android URL-less WebView chrome doesn't leave a gap. */
	max-height: calc(100vh - var(--ize-safe-top, 0px) - 32px);
	max-height: calc(100dvh - var(--ize-safe-top, 0px) - 32px);

	background: var(--ize-ps-surface);
	border-radius: 28px 28px 0 0;
	box-shadow: var(--ize-ps-shadow);
	overflow: hidden;

	/* Start off-screen. Only transform/opacity animate, so the whole open/close
	   stays on the compositor — no layout, no paint — which is what keeps it
	   smooth on entry-level hardware. */
	transform: translate3d(0, 100%, 0);
	opacity: 0;
	-webkit-tap-highlight-color: transparent;
}

/* M3 "emphasized decelerate": fast off the mark, long soft landing. */
.ize-ps.ize-ps-open .ize-ps-sheet {
	transform: translate3d(0, 0, 0);
	opacity: 1;
	transition: transform 320ms cubic-bezier(.05, .7, .1, 1),
	            opacity 160ms linear;
	will-change: transform;
}

/* M3 "emphasized accelerate": leaves quickly, no lingering. */
.ize-ps.ize-ps-closing .ize-ps-sheet {
	transform: translate3d(0, 100%, 0);
	opacity: 0;
	transition: transform 240ms cubic-bezier(.3, 0, .8, .15),
	            opacity 200ms 40ms linear;
	will-change: transform;
}

/* Finger is on the sheet: it tracks 1:1, so no transition may interfere. */
.ize-ps.ize-ps-drag .ize-ps-sheet { transition: none; }

/* Released below the dismiss threshold — spring back a touch faster than a
   cold open, otherwise the sheet feels like it is being dragged back by hand. */
.ize-ps.ize-ps-snap .ize-ps-sheet {
	transition: transform 260ms cubic-bezier(.05, .7, .1, 1);
}

/* ---------- Drag handle ----------------------------------------------------- */
.ize-ps-grip {
	flex: 0 0 auto;
	display: flex;
	align-items: center;
	justify-content: center;
	/* Generous: the whole strip is the drag surface, not just the 4px bar. */
	height: 26px;
	padding: 10px 0 6px;
	touch-action: none;
	cursor: grab;
}

.ize-ps-grip::before {
	content: '';
	display: block;
	width: 32px;
	height: 4px;
	border-radius: 2px;
	background: var(--ize-ps-handle);
}

/* ---------- List ------------------------------------------------------------ */
.ize-ps-list {
	flex: 1 1 auto;
	min-height: 0;
	overflow-y: auto;
	-webkit-overflow-scrolling: touch;
	/* Never hand the scroll to the feed underneath. */
	overscroll-behavior: contain;
	/* Clears the gesture bar / 3-button nav. var(--ize-safe-bottom) is the real
	   inset injected by the native shell; env() off-app. */
	padding: 2px 0 calc(10px + var(--ize-safe-bottom, 0px));
	margin: 0;
	list-style: none;
}

/* ---------- Groups + dividers ----------------------------------------------- */
/* Only BETWEEN groups — no hairline under every row, which is what made the old
   dropdown read as a form rather than a menu. */
.ize-ps-group { padding: 4px 0; }

.ize-ps-group + .ize-ps-group {
	border-top: 1px solid var(--ize-ps-hair);
}

/* ---------- Rows ------------------------------------------------------------ */
.ize-ps-row {
	position: relative;
	overflow: hidden;
	display: flex;
	align-items: center;
	gap: 20px;
	width: 100%;
	min-height: 60px;            /* > 48dp Android minimum, with room to breathe */
	padding: 12px 22px;
	margin: 0;
	border: 0;
	border-radius: 0;
	background: transparent;
	color: var(--ize-ps-ink);
	text-align: start;
	font: inherit;
	cursor: pointer;
	-webkit-tap-highlight-color: transparent;
	appearance: none;
	-webkit-appearance: none;
}

.ize-ps-row:focus { outline: none; }

/* Keyboard / switch-access users get a real focus ring; touch does not. */
.ize-ps-row:focus-visible {
	outline: 2px solid var(--main, #2196f3);
	outline-offset: -3px;
}

.ize-ps-ico {
	flex: 0 0 auto;
	width: 24px;
	height: 24px;
	display: flex;
	align-items: center;
	justify-content: center;
	color: var(--ize-ps-ink-2);
}

.ize-ps-ico svg { width: 24px; height: 24px; display: block; }

.ize-ps-txt {
	flex: 1 1 auto;
	min-width: 0;
	display: block;
}

.ize-ps-lbl {
	display: block;
	font-size: 16px;
	font-weight: 500;
	line-height: 1.35;
	letter-spacing: -.1px;
	color: var(--ize-ps-ink);
	word-break: break-word;
}

.ize-ps-sub {
	display: -webkit-box;
	-webkit-line-clamp: 2;
	-webkit-box-orient: vertical;
	overflow: hidden;
	margin-top: 2px;
	font-size: 13px;
	font-weight: 400;
	line-height: 1.35;
	color: var(--ize-ps-ink-2);
	word-break: break-word;
}

.ize-ps-sub:empty { display: none; }

/* ---------- Destructive ----------------------------------------------------- */
/* Its own group (so a divider always precedes it) plus its own colour, so Delete
   can never be hit by muscle memory aimed at the row above. */
.ize-ps-row.ize-ps-danger .ize-ps-lbl,
.ize-ps-row.ize-ps-danger .ize-ps-ico { color: var(--ize-ps-danger); }
.ize-ps-row.ize-ps-danger { --ize-ps-press: var(--ize-ps-danger-bg); }

/* ---------- Touch feedback -------------------------------------------------- */
/* Two layers: an instant press tint (never late, even mid-scroll) and a Material
   ripple that grows from the touch point. The ripple is a single transform+
   opacity animation on one pseudo-element — no extra nodes per press. */
.ize-ps-row:active { background: var(--ize-ps-press); }

.ize-ps-row::after {
	content: '';
	position: absolute;
	top: var(--ize-ps-ry, 50%);
	left: var(--ize-ps-rx, 50%);
	width: 12px;
	height: 12px;
	margin: -6px 0 0 -6px;
	border-radius: 50%;
	background: var(--ize-ps-ripple);
	opacity: 0;
	transform: scale(0);
	pointer-events: none;
}

.ize-ps-row.ize-ps-rippling::after {
	animation: ize-ps-ripple 480ms cubic-bezier(.2, 0, .2, 1) forwards;
}

@keyframes ize-ps-ripple {
	0%   { opacity: 1; transform: scale(0); }
	100% { opacity: 0; transform: scale(34); }
}

/* ---------- Page scroll lock ------------------------------------------------ */
/* Same contract as the comment sheet: stop the page scrolling, never move it, so
   dismissing lands the reader exactly where they were. */
html.ize-ps-lock,
body.ize-ps-lock { overflow: hidden; }

/* ---------- The dropdown this replaces -------------------------------------- */
/* Belt and braces: JS suppresses the Bootstrap toggle, but if a stray script ever
   opened the dropdown while the sheet is the active presentation, the old popup
   must not flash over it. Scoped to the sheet being mounted, so the desktop
   dropdown is completely untouched. */
html.ize-ps-lock .tag_post_hdr_menu .dropdown-menu { display: none !important; }

/* Bigger target on the chevron itself — 22px of SVG was a 22px tap target. */
@media (max-width: 800px) {
	.tag_post_hdr_menu > .dropdown-toggle {
		min-width: 40px;
		min-height: 40px;
		display: flex;
		align-items: center;
		justify-content: center;
		margin: -9px;              /* keeps the chevron optically where it was */
	}
}

/* ---------- Motion preferences ---------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
	.ize-ps-scrim,
	.ize-ps.ize-ps-open .ize-ps-sheet,
	.ize-ps.ize-ps-closing .ize-ps-sheet,
	.ize-ps.ize-ps-snap .ize-ps-sheet { transition: none; }
	.ize-ps-row.ize-ps-rippling::after { animation: none; }
}
