/* =============================================================
   Fair Business — mobile app shell.

   Single source of truth for the stack-style mobile experience:
   - sticky height variables (header, sub-header, internal tabs, bottom bar)
   - .fb-subheader (back · title · action strip below the site header)
   - .fb-hub (vertical menu of icon-rows; lives at /account/, /dashboard/,
     /dashboard/pending/)
   - .fb-skip-link (accessibility — first focusable element on every page)

   Everything in this file is mobile-only (≤1023px). Desktop is untouched.
   ============================================================= */

:root {
	/* Mobile site-header is the original main-header-inner row only —
	   utility-bar and mobile-search-row are hidden on ≤1023px via
	   bottom-bar.css. The original sets `.main-header-inner` height to
	   `--mobile-row1: 60px` (declared in public-company.css / design-
	   system.css). We mirror that value so sticky math stays correct. */
	--fb-h-header:    60px;
	--fb-h-subheader: 48px;   /* sub-header below it on detail pages */
	--fb-h-tabs:      44px;   /* page-internal tab strip */
	--fb-h-bottom:    64px;   /* bottom bar (excluding safe-area inset) */
}

/* Skip-link — keyboard users land here first; tab to skip past chrome.
   Visually hidden until focused, then jumps into view at top-left. */
.fb-skip-link {
	position: absolute;
	top: -40px;
	left: 8px;
	z-index: 200;
	padding: 8px 14px;
	background: var(--green-dark, #166534);
	color: #fff;
	border-radius: 0 0 8px 8px;
	font-size: 13px;
	font-weight: 600;
	text-decoration: none;
	transition: top .15s ease;
}
.fb-skip-link:focus { top: 0; outline: 2px solid #fff; outline-offset: 2px; }

/* Visually-hidden but still focusable target for the skip-link, plus any
   other off-screen accessible text (WP-standard convention). */
.screen-reader-text {
	border: 0;
	clip: rect(1px, 1px, 1px, 1px);
	-webkit-clip-path: inset(50%);
	clip-path: inset(50%);
	height: 1px;
	margin: -1px;
	overflow: hidden;
	padding: 0;
	position: absolute;
	width: 1px;
	word-wrap: normal !important;
}
/* Only reveal on focus if the element has actual content. Pure skip-link
   targets (empty <a id="fb-main">) stay invisible — they exist solely to
   anchor focus, no visible flash on jump. */
.screen-reader-text:not(:empty):focus {
	clip: auto !important;
	-webkit-clip-path: none;
	clip-path: none;
	display: block;
	height: auto;
	left: 8px;
	top: 8px;
	width: auto;
	z-index: 200;
}

/* =============================================================
   Sub-header (mobile only) — sticks below the site header.
   Three slots: back arrow (left, 44×44), title (centre-left, ellipsis),
   right action (button or overflow ⋯).
   ============================================================= */
.fb-subheader {
	display: none;             /* desktop: invisible */
	position: sticky;
	top: var(--fb-h-header);
	z-index: 80;               /* below site-header (90) + drawer (100+) */
	height: var(--fb-h-subheader);
	background: var(--white, #fff);
	border-bottom: 1px solid var(--slate-100, #f1f5f9);
	align-items: center;
	gap: 6px;
	padding: 0 4px 0 0;
}
@media (max-width: 1023px) {
	.fb-subheader { display: flex; }
}

.fb-subheader-back {
	flex-shrink: 0;
	width: 44px; height: 44px;
	display: inline-flex; align-items: center; justify-content: center;
	background: transparent;
	border: 0;
	border-radius: 8px;
	cursor: pointer;
	color: var(--slate-700, #334155);
	text-decoration: none;
	transition: background .15s ease;
}
.fb-subheader-back:hover,
.fb-subheader-back:active { background: var(--slate-100, #f1f5f9); color: var(--slate-900, #0f172a); }
.fb-subheader-back svg { width: 22px; height: 22px; }

.fb-subheader-title {
	flex: 1;
	min-width: 0;
	font-size: 16px;
	font-weight: 600;
	color: var(--slate-900, #0f172a);
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
	line-height: 1.2;
	padding: 0 4px;
}

.fb-subheader-action {
	flex-shrink: 0;
	display: inline-flex;
	align-items: center;
	gap: 6px;
}
/* Right-action button — used for "Save", "Filter", overflow ⋯ */
.fb-subheader-btn {
	display: inline-flex; align-items: center; justify-content: center;
	min-height: 36px;
	padding: 0 12px;
	background: transparent;
	border: 0;
	border-radius: 8px;
	cursor: pointer;
	color: var(--green-dark, #166534);
	font: inherit;
	font-size: 14px;
	font-weight: 600;
	text-decoration: none;
	transition: background .15s ease;
}
.fb-subheader-btn:hover { background: var(--slate-100, #f1f5f9); }
.fb-subheader-btn[disabled],
.fb-subheader-btn.is-disabled { color: var(--slate-400, #94a3b8); cursor: not-allowed; }
.fb-subheader-btn--icon { padding: 0; width: 40px; height: 40px; color: var(--slate-700, #334155); }
.fb-subheader-btn--icon svg { width: 20px; height: 20px; }
.fb-subheader-btn--save { color: var(--green-dark, #166534); font-weight: 700; }

/* When the form is dirty the Save button gets the active treatment.
   Until then it's hidden — no fake "Save" button appearing on a clean form. */
.fb-subheader-btn--save[hidden] { display: none; }

/* Page-internal tabs (e.g. complaint detail's Conversation/Notes/Files/Audit)
   stick directly below the sub-header. */
@media (max-width: 1023px) {
	.fb-page-tabs {
		position: sticky;
		top: calc(var(--fb-h-header) + var(--fb-h-subheader));
		z-index: 70;
		background: var(--white, #fff);
		border-bottom: 1px solid var(--slate-100, #f1f5f9);
	}
}

/* =============================================================
   Hub screen (customer / vendor / pending) — full mobile layout.
   On desktop these page templates redirect to first item; this CSS only
   ever activates on the mobile breakpoint.
   ============================================================= */
.fb-hub {
	max-width: 720px;
	margin: 0 auto;
	padding: 16px 16px 24px;
}

/* Identity card at the top — user (customer) or company (vendor) */
.fb-hub-identity {
	display: flex;
	align-items: center;
	gap: 14px;
	padding: 16px;
	background: var(--white, #fff);
	border: 1px solid var(--slate-100, #f1f5f9);
	border-radius: 14px;
	margin-bottom: 24px;
	box-shadow: 0 1px 0 rgba(15,23,42,.02);
}
.fb-hub-avatar {
	width: 56px; height: 56px;
	flex-shrink: 0;
	border-radius: 50%;
	overflow: hidden;
	background: var(--slate-100, #f1f5f9);
}
.fb-hub-avatar img { width: 100%; height: 100%; object-fit: cover; display: block; }
.fb-hub-avatar--logo { border-radius: 12px; }   /* vendor company logo = rounded square */
.fb-hub-identity-meta { min-width: 0; flex: 1; }
.fb-hub-name {
	font-size: 16px;
	font-weight: 700;
	color: var(--slate-900, #0f172a);
	overflow: hidden;
	text-overflow: ellipsis;
	display: -webkit-box;
	-webkit-line-clamp: 2;
	-webkit-box-orient: vertical;
	line-height: 1.3;
}
.fb-hub-sub {
	font-size: 13px;
	color: var(--slate-500, #64748b);
	margin-top: 2px;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

/* Section group */
.fb-hub-section { margin-bottom: 24px; }
.fb-hub-section-label {
	font-size: 11px;
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: .08em;
	color: var(--slate-500, #64748b);
	margin: 0 12px 8px;
}
.fb-hub-list {
	background: var(--white, #fff);
	border: 1px solid var(--slate-100, #f1f5f9);
	border-radius: 14px;
	overflow: hidden;
}

/* Hub row — primary tap-target for navigating into a section */
.fb-hub-row {
	display: flex;
	align-items: center;
	gap: 14px;
	min-height: 56px;
	padding: 12px 16px;
	color: var(--slate-900, #0f172a);
	text-decoration: none;
	border-bottom: 1px solid var(--slate-100, #f1f5f9);
	transition: background .15s ease;
}
.fb-hub-row:last-child { border-bottom: none; }
.fb-hub-row:hover,
.fb-hub-row:active { background: var(--slate-50, #f8fafc); }

.fb-hub-row-icon {
	flex-shrink: 0;
	width: 36px; height: 36px;
	border-radius: 10px;
	background: var(--green-50, #f0fdf4);
	color: var(--green-dark, #166534);
	display: inline-flex; align-items: center; justify-content: center;
}
.fb-hub-row-icon svg { width: 18px; height: 18px; }
.fb-hub-row-icon--neutral { background: var(--slate-100, #f1f5f9); color: var(--slate-600, #475569); }

.fb-hub-row-body { flex: 1; min-width: 0; }
.fb-hub-row-title {
	font-size: 15px;
	font-weight: 600;
	color: var(--slate-900, #0f172a);
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}
.fb-hub-row-sub {
	font-size: 12px;
	color: var(--slate-500, #64748b);
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
	margin-top: 1px;
}
.fb-hub-row-right {
	display: inline-flex;
	align-items: center;
	gap: 8px;
	flex-shrink: 0;
	color: var(--slate-400, #94a3b8);
}
.fb-hub-row-badge {
	min-width: 22px;
	height: 22px;
	padding: 0 7px;
	border-radius: 999px;
	background: var(--red-500, #ef4444);
	color: #fff;
	font-size: 11px;
	font-weight: 700;
	line-height: 22px;
	text-align: center;
	font-variant-numeric: tabular-nums;
}
.fb-hub-row-chevron { width: 18px; height: 18px; }

/* Sign-out row — visually distinct, lives at the very bottom of the hub.
   width:100% so the button spans the full hub column on mobile (was rendering
   at content-width because the parent .fb-hub doesn't enforce stretch on a
   <button>). Matches the sidebar-nav logout treatment used in /account/. */
.fb-hub-signout {
	display: flex; align-items: center; justify-content: center;
	gap: 8px;
	width: 100%;
	height: 48px;
	margin-top: 8px;
	background: transparent;
	border: 1px solid var(--red-100, #fee2e2);
	border-radius: 12px;
	color: var(--red-600, #dc2626);
	font-size: 14px;
	font-weight: 600;
	text-decoration: none;
	transition: background .15s ease, border-color .15s ease;
	font-family: inherit;
	cursor: pointer;
}
.fb-hub-signout:hover { background: var(--red-50, #fef2f2); border-color: var(--red-200, #fecaca); color: var(--red-700, #b91c1c); }
.fb-hub-signout svg { width: 16px; height: 16px; }

/* =============================================================
   Toast (floats above bottom bar, lifts above keyboard).
   .fb-toast lives in <body> and is positioned by mobile-keyboard.js
   when the keyboard opens.
   ============================================================= */
.fb-toast {
	position: fixed;
	left: 50%;
	bottom: calc(var(--fb-h-bottom) + env(safe-area-inset-bottom, 0) + 16px);
	transform: translateX(-50%) translateY(20px);
	z-index: 120;
	min-width: 240px;
	max-width: calc(100vw - 32px);
	padding: 12px 16px;
	background: var(--slate-900, #0f172a);
	color: #fff;
	border-radius: 10px;
	box-shadow: 0 12px 28px rgba(0,0,0,.18);
	font-size: 14px;
	font-weight: 500;
	opacity: 0;
	pointer-events: none;
	transition: opacity .2s ease, transform .2s ease, bottom .2s ease;
}
.fb-toast.is-visible {
	opacity: 1;
	transform: translateX(-50%) translateY(0);
	pointer-events: auto;
}
.fb-toast--success { background: var(--green-dark, #166534); }
.fb-toast--error   { background: var(--red-600, #dc2626); }

/* When keyboard is up, the bottom bar is hidden via translateY — so the
   toast's reference offset changes. The keyboard JS sets a CSS variable
   `--fb-keyboard-offset` on the body equal to the keyboard's intrusion. */
body.is-keyboard-open .fb-toast {
	bottom: calc(var(--fb-keyboard-offset, 0px) + 16px);
}

/* On desktop there's no bottom bar — toast doesn't need to clear 64px,
   24px from the viewport edge is enough. */
@media (min-width: 1024px) {
	.fb-toast { bottom: 24px; }
}

/* =============================================================
   Discard-changes confirm modal (fired by mobile-keyboard.js when
   tapping the sub-header back arrow on a dirty form).
   ============================================================= */
.fb-confirm-modal {
	position: fixed;
	inset: 0;
	/* Above the mobile drawer (1000) + its backdrop (999): a Sign-out tap inside the
	   open drawer/profile menu must show this confirm ON TOP, not behind it. */
	z-index: 1200;
	display: none;
	align-items: center;
	justify-content: center;
	padding: 20px;
}
.fb-confirm-modal.is-open { display: flex; }
.fb-confirm-scrim {
	position: absolute;
	inset: 0;
	background: rgba(15,23,42,.55);
}
.fb-confirm-card {
	position: relative;
	width: 100%;
	max-width: 360px;
	background: var(--white, #fff);
	border-radius: 14px;
	padding: 22px 22px 16px;
	box-shadow: 0 20px 50px rgba(15,23,42,.25);
}
.fb-confirm-title {
	margin: 0 0 6px;
	font-size: 17px;
	font-weight: 700;
	color: var(--slate-900, #0f172a);
}
.fb-confirm-body {
	margin: 0 0 18px;
	font-size: 14px;
	line-height: 1.5;
	color: var(--slate-600, #475569);
}
.fb-confirm-actions {
	display: flex;
	justify-content: flex-end;
	gap: 8px;
}
.fb-confirm-btn {
	min-height: 40px;
	padding: 0 16px;
	border: 0;
	border-radius: 10px;
	font: inherit;
	font-size: 14px;
	font-weight: 600;
	cursor: pointer;
	background: transparent;
	color: var(--slate-700, #334155);
	transition: background .15s ease;
}
.fb-confirm-btn:hover { background: var(--slate-100, #f1f5f9); }
.fb-confirm-btn--ghost { color: var(--slate-700, #334155); }
.fb-confirm-btn--danger {
	background: var(--red-500, #ef4444);
	color: #fff;
}
.fb-confirm-btn--danger:hover { background: var(--red-600, #dc2626); }

/* =============================================================
   Extend mobile site-header to 1023px (originally collapses at 860px).
   The bottom bar + sub-header activate at ≤1023px, which covers phones
   in landscape (e.g. 932px iPhone Pro Max). Without this, the desktop
   site-header (utility bar + 72px main row + mega panels) would render
   under those mobile-only chrome elements and create:
     - 108px of site-header pushing sub-header into the middle of the page
     - desktop mega-panels colliding with bottom bar fixed at bottom
     - duplicate identity (desktop avatar + bottom-bar slot 5)
   Replicates the original's `@media (max-width: 860px)` rules at the
   wider 1023px boundary so chrome stays internally consistent.
   ============================================================= */
@media (min-width: 861px) and (max-width: 1023px) {
	.site-header .utility-bar,
	.site-header .main-nav,
	.site-header .header-search,
	.site-header .mega-panel { display: none !important; }
	.site-header .header-actions .cta-primary,
	.site-header .header-actions .ghost-btn,
	.site-header .header-actions .lang-toggle,
	.site-header .header-actions .avatar-btn { display: none !important; }
	.site-header .lang-toggle-mobile,
	.site-header .mobile-toggle { display: inline-flex !important; }
	body[data-auth="in"]  .site-header .avatar-btn-mobile { display: inline-flex !important; }
	body[data-auth="out"] .site-header .mobile-login { display: inline-flex !important; }
	.site-header .main-header-inner {
		height: var(--mobile-row1, 60px) !important;
		gap: 0 !important;
		justify-content: space-between !important;
	}
	.site-header .container { padding: 0 16px !important; }
}

/* =============================================================
   Hide app-sidebar on mobile (the dashboard / account vertical nav).
   Mobile users land on the hub instead; the sidebar would duplicate.
   Desktop ≥1024px keeps the sidebar.
   ============================================================= */
@media (max-width: 1023px) {
	.app-sidebar { display: none !important; }
	.app-main    { grid-template-columns: 1fr !important; gap: 0 !important; padding: 0 !important; }

	/* Account hero (big user-card + stats above detail pages) duplicates
	   identity context already shown in the hub. The sub-header carries
	   the section name, so hiding the hero gives the form room to breathe. */
	.account-hero { display: none !important; }

	/* Restore some breathing room inside the main content area on mobile
	   after `padding: 0` zero-out above. The sub-header carries 48px of
	   chrome, so we just need standard page padding for the content. */
	.app-main > .app-content { padding: 16px !important; }
}

/* Drawer's user-menu section — duplicates the hub on mobile, so hide.
   Desktop drawer keeps it (no mobile hub there). */
@media (max-width: 1023px) {
	.mobile-drawer .sd-user-menu-section { display: none; }
}

/* =============================================================
   PHASE 4 — Inner components on mobile.

   - iOS zoom-on-focus guard for sub-16px inputs (--fs-md is 14px,
     which triggers Safari's auto-zoom; we force 16px in the app shell
     only on the mobile breakpoint so desktop layouts keep their tight
     typography).
   - Composer (.composer) mobile chrome — taller textarea, wrapped foot,
     full-width submit button, lift above the on-screen keyboard.
   - .fb-attach-drop tap target sized for thumbs.

   Hero / KPI strip: already covered by the `.account-hero { display: none }`
   rule earlier in this file. Identity context lives in the hub identity
   card and the sub-header title on detail pages — no separate KPI block
   is rendered on mobile, so no further styling is needed here.

   Key-value rows in status cards (e.g. complaint-detail's "Filed / Days
   open / Replies used") are inline-styled `flex; justify-content: space-
   between` and already wrap acceptably at narrow widths. No global rule
   added; refactoring every inline style is out of scope.
   ============================================================= */
@media (max-width: 1023px) {
	/* iOS Safari zooms in when a focused field has font-size < 16px. Force
	   ≥16px on every form control inside the app shell + hubs. Limited to
	   mobile so desktop's tighter 14px scale is untouched. */
	.app-content input[type="text"],
	.app-content input[type="email"],
	.app-content input[type="tel"],
	.app-content input[type="url"],
	.app-content input[type="password"],
	.app-content input[type="number"],
	.app-content input[type="search"],
	.app-content input[type="date"],
	.app-content textarea,
	.app-content select,
	.fb-hub input,
	.fb-hub textarea,
	.fb-hub select {
		font-size: 16px !important;
	}

	/* Composer — the reply/note/follow-up card. Existing desktop rules in
	   account.css and company-complaint-detail.css still apply; we only
	   widen breathing room and reshape the foot. */
	.composer { padding: 14px; }
	.composer textarea {
		min-height: 120px;
		font-size: 16px;
	}
	.composer-foot {
		flex-wrap: wrap;
		gap: 10px;
	}
	/* Quota line wraps to its own row above the action button so the
	   button gets full width — easier thumb target, no truncation. */
	.composer-foot .reply-quota {
		order: 2;
		width: 100%;
		font-size: 12px;
	}
	.composer-foot > div:not(.reply-quota) {
		order: 1;
		width: 100%;
	}
	.composer-foot > div:not(.reply-quota) .btn { width: 100%; justify-content: center; }
	.composer-foot > .btn { order: 1; width: 100%; justify-content: center; }

	/* Attachment drop — already vertical-padded for desktop, just allow
	   the inner row to wrap on very narrow screens so the helper text
	   doesn't overflow. */
	.fb-attach-drop {
		flex-wrap: wrap;
		min-height: 56px;
	}

	/* When the on-screen keyboard is open, lift the composer's last child
	   above the keyboard so the user can see what they're typing + the
	   submit button. mobile-keyboard.js sets `--fb-keyboard-offset` and
	   adds `body.is-keyboard-open`. The 16px subtraction accounts for the
	   composer card's own bottom padding. */
	body.is-keyboard-open .composer {
		margin-bottom: max(0px, calc(var(--fb-keyboard-offset, 0px) - 16px));
	}
}

/* =============================================================
   PHASE 5 — Filter bottom-sheet for archive / list pages.

   Desktop keeps the inline `<form class="list-toolbar">` row of selects.
   On mobile (≤1023px), `mobile-filter-sheet.js` rewrites each toolbar:
   - Search input stays in place at the top.
   - All non-search controls move into a `.fb-filter-sheet` container that
     starts off-screen (translateY(100%)) and slides up when opened.
   - A `.fb-filter-trigger` button replaces the inline selects in the
     toolbar; tapping it opens the sheet.

   While the sheet is open, the JS suppresses each select's inline
   `onchange="this.form.submit()"` (via stopImmediatePropagation in a
   capture-phase listener) so the user can stack multiple filter changes
   and apply them all in one go via the sheet's Apply button. On desktop
   the original inline auto-submit behaviour is untouched.
   ============================================================= */

/* Hide the trigger + the sheet on desktop. The mobile media query below
   flips them visible. If the user resizes from mobile → desktop after JS
   has enhanced a toolbar, this base rule keeps the sheet out of the way
   (the selects inside become inaccessible until reload, but the page no
   longer renders an orphaned card at the bottom). */
.fb-filter-trigger { display: none; }
.fb-filter-sheet   { display: none; }
.fb-filter-scrim   { display: none; }

@media (max-width: 1023px) {
	/* Toolbar becomes a tight horizontal flex row: search expands, trigger
	   button collapses to icon + label. The original "spacer" + results
	   info live inside but get collapsed since the sheet now owns the
	   secondary chrome. */
	.list-toolbar {
		display: flex;
		flex-wrap: wrap;
		gap: 8px;
		align-items: center;
	}
	.list-toolbar .search-input { flex: 1 1 200px; min-width: 0; }
	.list-toolbar .toolbar-spacer { display: none; }
	.list-toolbar .list-results-info {
		flex-basis: 100%;
		font-size: 12px;
		color: var(--slate-500, #64748b);
		padding: 4px 2px 0;
	}

	/* Filter trigger button — sits next to the search input. */
	.fb-filter-trigger {
		display: inline-flex;
		align-items: center;
		gap: 6px;
		height: 40px;
		padding: 0 14px;
		background: var(--white, #fff);
		border: 1px solid var(--slate-200, #e2e8f0);
		border-radius: 10px;
		color: var(--slate-700, #334155);
		font-size: 14px;
		font-weight: 600;
		cursor: pointer;
		flex: 0 0 auto;
		position: relative;
	}
	.fb-filter-trigger svg {
		width: 16px;
		height: 16px;
		stroke: currentColor;
		fill: none;
		stroke-width: 2;
	}
	.fb-filter-trigger-badge {
		display: inline-flex;
		align-items: center;
		justify-content: center;
		min-width: 20px;
		height: 20px;
		padding: 0 6px;
		background: var(--green-700, #15803d);
		color: #fff;
		border-radius: 10px;
		font-size: 11px;
		font-weight: 700;
		margin-left: 2px;
	}

	/* Hide the inline selects only AFTER the JS has wrapped them into the
	   sheet (gated by `data-fb-filter-enhanced="1"`, which the JS sets on
	   the toolbar before moving the selects). If JS never runs (network
	   error, browser without JS, very old engines) the selects stay
	   visible and the user can still filter — ugly fallback beats broken
	   feature. */
	.list-toolbar[data-fb-filter-enhanced="1"] > select { display: none !important; }

	/* Sheet container — fixed to bottom, off-screen until opened. */
	.fb-filter-sheet {
		position: fixed;
		left: 0;
		right: 0;
		bottom: 0;
		max-height: 80vh;
		background: var(--white, #fff);
		border-top-left-radius: 16px;
		border-top-right-radius: 16px;
		box-shadow: 0 -8px 24px rgba(15, 23, 42, .14);
		z-index: 1100;
		transform: translateY(100%);
		transition: transform .25s cubic-bezier(.2, .8, .2, 1);
		display: flex;
		flex-direction: column;
		padding-bottom: env(safe-area-inset-bottom, 0);
		visibility: hidden;
	}
	.fb-filter-sheet.is-open {
		transform: translateY(0);
		visibility: visible;
	}

	.fb-filter-sheet-head {
		display: flex;
		align-items: center;
		justify-content: space-between;
		padding: 14px 16px 10px;
		border-bottom: 1px solid var(--slate-100, #f1f5f9);
		flex-shrink: 0;
	}
	/* Drag-grab handle visual cue at the very top of the sheet. */
	.fb-filter-sheet-head::before {
		content: "";
		position: absolute;
		top: 6px;
		left: 50%;
		width: 36px;
		height: 4px;
		border-radius: 2px;
		background: var(--slate-200, #e2e8f0);
		transform: translateX(-50%);
	}
	.fb-filter-sheet-head { position: relative; padding-top: 18px; }
	.fb-filter-sheet-title {
		font-size: 16px;
		font-weight: 700;
		color: var(--slate-900, #0f172a);
	}
	.fb-filter-sheet-close {
		/* WCAG 2.5.5 (Level AAA) recommends 44x44 minimum for tap targets.
		   Bumped from earlier 32x32 — comfortably hit by thumbs without
		   the head row going taller (button is centered vertically). */
		width: 44px;
		height: 44px;
		display: inline-flex;
		align-items: center;
		justify-content: center;
		background: transparent;
		border: 0;
		color: var(--slate-500, #64748b);
		cursor: pointer;
		padding: 0;
		margin-right: -10px; /* reclaim some of the head's right padding */
	}
	.fb-filter-sheet-close svg { width: 20px; height: 20px; stroke: currentColor; fill: none; stroke-width: 2; }

	.fb-filter-sheet-body {
		overflow-y: auto;
		padding: 12px 16px;
		-webkit-overflow-scrolling: touch;
	}
	.fb-filter-sheet-row { margin-bottom: 14px; }
	.fb-filter-sheet-row:last-child { margin-bottom: 0; }
	.fb-filter-sheet-label {
		display: block;
		font-size: 12px;
		font-weight: 600;
		color: var(--slate-500, #64748b);
		text-transform: uppercase;
		letter-spacing: .04em;
		margin-bottom: 6px;
	}
	.fb-filter-sheet-row select {
		width: 100% !important;
		min-width: 0 !important;
		height: 44px !important;
		font-size: 16px !important;
		/* override inline `style="..."` from templates */
	}

	.fb-filter-sheet-foot {
		display: flex;
		gap: 10px;
		padding: 12px 16px;
		border-top: 1px solid var(--slate-100, #f1f5f9);
		flex-shrink: 0;
	}
	.fb-filter-sheet-reset,
	.fb-filter-sheet-apply {
		flex: 1;
		height: 44px;
		display: inline-flex;
		align-items: center;
		justify-content: center;
		font-size: 14px;
		font-weight: 600;
		border-radius: 10px;
		cursor: pointer;
		text-decoration: none;
	}
	.fb-filter-sheet-reset {
		background: var(--white, #fff);
		border: 1px solid var(--slate-200, #e2e8f0);
		color: var(--slate-700, #334155);
	}
	.fb-filter-sheet-apply {
		background: var(--green-700, #15803d);
		border: 1px solid var(--green-700, #15803d);
		color: #fff;
	}

	/* Scrim — covers the page while sheet is open, click to dismiss. */
	.fb-filter-scrim {
		display: block; /* override the desktop `display: none` base rule */
		position: fixed;
		inset: 0;
		background: rgba(15, 23, 42, .5);
		z-index: 1099;
		opacity: 0;
		pointer-events: none;
		transition: opacity .2s ease-out;
	}
	.fb-filter-scrim.is-open {
		opacity: 1;
		pointer-events: auto;
	}

	/* Lock body scroll while sheet is open so the underlying list doesn't
	   scroll-jack the touch gesture. */
	body.fb-filter-sheet-open {
		overflow: hidden;
	}
}

/* =============================================================
   PHASE 6 — Polish + accessibility.

   - prefers-reduced-motion: kill non-essential transitions/animations.
   - :focus-visible: explicit ring on every app-shell control. Browser
     defaults (especially iOS Safari) often render no visible focus,
     leaving keyboard / switch users adrift.
   - touch-action: manipulation: disables the 300ms double-tap-zoom
     hesitation on interactive controls — every tap responds instantly.
   - :active feedback: subtle press-state on hub list rows so taps feel
     responsive even before navigation completes.
   ============================================================= */

/* Reduced-motion guard. Sheet/scrim/toast/modal slide + fade are nice
   but not load-bearing; users who opted out of motion get instant state
   changes instead. The transform/visibility values are unchanged so the
   final visual state is the same — only the animation is suppressed. */
@media (prefers-reduced-motion: reduce) {
	.fb-filter-sheet,
	.fb-filter-scrim,
	.fb-toast,
	.fb-confirm-card,
	.fb-confirm-scrim {
		transition: none !important;
	}
}

/* Focus-visible ring for every interactive surface in the mobile shell.
   `:focus-visible` only triggers for keyboard / programmatic focus, so
   mouse and touch users don't see a stray outline after every tap. */
.fb-skip-link:focus-visible,
.fb-subheader-back:focus-visible,
.fb-subheader-btn:focus-visible,
.fb-subheader-btn--save:focus-visible,
.fb-filter-trigger:focus-visible,
.fb-filter-sheet-close:focus-visible,
.fb-filter-sheet-apply:focus-visible,
.fb-filter-sheet-reset:focus-visible,
.fb-confirm-btn:focus-visible {
	outline: 2px solid var(--green-700, #15803d);
	outline-offset: 2px;
}

/* Touch-action: manipulation strips the double-tap-zoom delay (~300ms)
   from buttons / links inside the app shell so taps register immediately.
   We don't blanket-apply because some elements (e.g. images, text blocks)
   benefit from native pinch/zoom. */
@media (max-width: 1023px) {
	.fb-subheader-back,
	.fb-subheader-btn,
	.fb-filter-trigger,
	.fb-filter-sheet-close,
	.fb-filter-sheet-apply,
	.fb-filter-sheet-reset,
	.fb-confirm-btn,
	.fb-hub-list a,
	.fb-hub-list button,
	.fb-bottom-bar a,
	.fb-bottom-bar button {
		touch-action: manipulation;
	}

	/* Active press feedback on hub list rows — a 60ms slate-50 wash so
	   the row visually acknowledges the tap before navigation kicks in.
	   Phones without :active support (none in our target range) just see
	   the default browser highlight. */
	.fb-hub-list a:active,
	.fb-hub-list button:active {
		background: var(--slate-50, #f8fafc);
	}
}

/* =============================================================
   B5 — bigger body fonts on mobile.

   The design-system tokens are sized for desktop (--fs-base: 13px,
   --fs-md: 14px, --fs-lg: 15px). On phone screens that reads small.
   Bumping each by +1 to +2px on the mobile breakpoint keeps the design
   system intact on desktop while giving phone users more comfortable
   body text. Phase 4 already forces ≥16px on form inputs to dodge iOS
   focus-zoom; this complements that for non-input text.
   ============================================================= */
@media (max-width: 1023px) {
	:root {
		--fs-xs:   12px; /* was 11 */
		--fs-sm:   13px; /* was 12 */
		--fs-base: 14px; /* was 13 */
		--fs-md:   15px; /* was 14 */
		--fs-lg:   17px; /* was 15 */
	}
}

/* =============================================================
   B6 — reviewer rating card on the profile page.

   Surfaces the author's rating prominently since the account-hero
   (which previously housed the rating stat) is hidden on mobile.
   Renders on both mobile + desktop; the form/section-head still follows.
   ============================================================= */
.fb-profile-rating-card {
	display: flex;
	align-items: center;
	gap: 14px;
	padding: 16px 18px;
	background: linear-gradient(135deg, var(--green-50, #f0fdf4), #fff);
	border: 1px solid var(--green-100, #dcfce7);
	border-radius: 14px;
	margin-bottom: 20px;
	box-shadow: 0 1px 0 rgba(15, 23, 42, .02);
}
.fb-profile-rating-star {
	width: 36px;
	height: 36px;
	fill: var(--amber-500, #f59e0b);
	flex-shrink: 0;
}
.fb-profile-rating-text { display: flex; flex-direction: column; gap: 2px; }
.fb-profile-rating-num {
	font-size: 28px;
	font-weight: 800;
	letter-spacing: -.02em;
	color: var(--slate-900, #0f172a);
	line-height: 1;
}
.fb-profile-rating-label {
	font-size: 13px;
	color: var(--slate-500, #64748b);
}
