/*
 * Flexible Facet Search — 既定スタイル（最小限）
 *
 * 方針（AGENTS.md §7）
 *  - フォント・文字色・背景色はテーマから継承する。ここで指定しない。
 *  - 色や余白は --ffs-* のカスタムプロパティで上書きできるようにする。
 *  - 青紫系は使わない。
 *  - クラス名は必ず ffs- 接頭辞。
 *  - デスクトップは左に条件・右に結果。モバイルは条件を上に積む。
 *    **開閉は <details> だけで成立させる**（JSが無くても開閉でき、無効時に閉じたまま固まらない）。
 *  - タップ領域44px・prefers-reduced-motion・横スクロールを出さない。
 */

/*
 * 既定値は :root に置く（★P5R-13）。`.ffs` 自身に宣言すると、テーマが :root や body で
 * --ffs-accent を宣言しても **継承値より .ffs の宣言が必ず勝つ**ため、
 * 「色は --ffs-* で上書きできる」（AGENTS.md §7）が読み込み順に依存する担保になってしまう。
 * :root に置けば、テーマは :root（後読み）でも .ffs（詳細度）でも上書きできる。
 * 利用側は var(--ffs-x, 既定値) の形で参照し、この宣言が届かない環境でも壊れないようにする。
 */
:root {
	--ffs-accent: #1795d4;        /* 非テキスト用途（境界線・ドット）。白との比 3.34:1 */
	--ffs-accent-dark: #0f76ab;   /* 白抜き文字を載せる用途。白との比 5.03:1（WCAG AA） */
	--ffs-border: rgba(0, 0, 0, 0.14);
	--ffs-muted: rgba(0, 0, 0, 0.6);
	--ffs-surface: rgba(0, 0, 0, 0.03);
	--ffs-disabled: rgba(0, 0, 0, 0.38);
	--ffs-radius: 6px;
	--ffs-gap: 1rem;
	--ffs-tap-size: 44px;
}

/*
 * ★無彩色の4つは currentColor から作る（R4-MEDIUM/LOW-15）。
 * 上の rgba(0,0,0,…) は「明るい背景」を暗黙に前提にしていて、既存の暗いテーマへ後付けすると
 * 件数・補足説明・0件ヒント・区切り線が背景に埋もれる（白背景で 5.74:1 の --ffs-muted が
 * #1e1e1e 背景では 1.1:1 前後になる）。「フォント・文字色・背景色はテーマから継承する」
 * （AGENTS.md §7）という方針を色にも通すなら、基準はテーマの本文色＝currentColor が正しい。
 *
 * custom property はパース時にほぼ何でも通ってしまい「後勝ち」になるので、
 * color-mix() を解釈できない古いブラウザのために @supports で囲う（囲わないと
 * 上の rgba 宣言が上書きされ、その環境では色が invalid at computed value time になる）。
 * currentColor は**使う側の要素**で解決されるので、:root に置いても
 * .ffs-count / .ffs-hint はそれぞれの継承色を基準に濃さが決まる。
 * どれも --ffs-* なので、テーマは従来どおり固定色で上書きできる。
 */
@supports (color: color-mix(in srgb, currentColor 50%, transparent)) {
	:root {
		--ffs-border: color-mix(in srgb, currentColor 20%, transparent);
		--ffs-muted: color-mix(in srgb, currentColor 65%, transparent);
		--ffs-surface: color-mix(in srgb, currentColor 4%, transparent);
		--ffs-disabled: color-mix(in srgb, currentColor 45%, transparent);
	}
}

.ffs {
	box-sizing: border-box;

	/*
	 * ★外部由来テキスト（ターム名・投稿タイトル・抜粋・単位・補足説明）は
	 * どこに出ても折り返す（R4-MEDIUM-9）。overflow-wrap は継承プロパティなので、
	 * 器に1回だけ置けば .ffs-group / .ffs-chip__label / .ffs-terms__item /
	 * .ffs-excerpt / .ffs-range__unit / .ffs-hint / .ffs-facet__help まで全部届く。
	 * 要素ごとに列挙する形にしていると、選択肢のラベルは守られているのに
	 * **同じターム名を出す親グループの見出しだけが守られていない**、という
	 * 取りこぼしが必ず起きる（実測：360px で 63文字の1語を入れると scrollWidth が 551px）。
	 * white-space: nowrap の要素（.ffs-count）には効かないので、件数バッジは折れない。
	 */
	overflow-wrap: anywhere;
}

.ffs *,
.ffs *::before,
.ffs *::after {
	box-sizing: inherit;
}

/* 支援技術にだけ渡す文言 */
.ffs-sr-only {
	position: absolute;
	width: 1px;
	height: 1px;
	margin: -1px;
	padding: 0;
	overflow: hidden;
	clip-path: inset(50%);
	white-space: nowrap;
	border: 0;
}

/* ------------------------------------------------------------------ 骨格 */

.ffs-layout {
	display: grid;
	grid-template-columns: 1fr;
	gap: var(--ffs-gap, 1rem);
	align-items: start;
}

@media (min-width: 48em) {
	.ffs-layout {
		/*
		 * 上限を 25rem まで許す（ユーザー要望・2026-07-29）。
		 * 日本語のターム名は「さいたま市」「石神井公園駅」のように長いものが多く、
		 * 20rem（320px）だと2列に詰めたときに折り返しが増えて見苦しくなる。
		 * 下限 15rem は変えない（狭い画面では結果側に幅を譲る）。
		 */
		grid-template-columns: minmax(15rem, 25rem) minmax(0, 1fr);
	}
}

.ffs-panel,
.ffs-main {
	min-width: 0; /* グリッド内で子が溢れないようにする（横スクロール対策） */
}

.ffs-main > * + * {
	margin-top: var(--ffs-gap, 1rem);
}

/* ------------------------------------------------------------ 通知・デバッグ */

.ffs-notices,
.ffs-debug {
	border: 1px solid var(--ffs-border, rgba(0, 0, 0, 0.14));
	border-left: 4px solid var(--ffs-accent, #1795d4);
	border-radius: var(--ffs-radius, 6px);
	background: var(--ffs-surface, rgba(0, 0, 0, 0.03));
	padding: 0.8em 1em;
	margin: 0 0 var(--ffs-gap, 1rem);
	font-size: 0.9em;
}

.ffs-notices__title {
	margin: 0 0 0.4em;
	font-weight: 700;
}

.ffs-notices__list {
	margin: 0;
	padding-left: 1.2em;
}

.ffs-debug__sql pre {
	overflow-x: auto;
	white-space: pre-wrap;
	word-break: break-all;
}

/* --------------------------------------------------------------- 条件パネル */

.ffs-filters__title {
	margin: 0 0 0.6em;
	font-size: 1.1em;
}

.ffs-facet {
	border: 1px solid var(--ffs-border, rgba(0, 0, 0, 0.14));
	border-radius: var(--ffs-radius, 6px);
	margin: 0 0 0.6em;
}

/*
 * <summary> の UA 既定は display: list-item で、その ::marker が開閉三角として描かれる。
 * ここで display: flex にすると Chrome / Firefox で **マーカーが消える**ので、
 * 代替のインジケータを ::after で必ず用意する（★P5R-11）。
 * これが無いと collapsed=true のファセットは「開けることに気づけない」＝事実上使われなくなる。
 */
.ffs-facet__summary {
	display: flex;
	align-items: center;
	gap: 0.5em;
	min-height: var(--ffs-tap-size, 44px);
	padding: 0.5em 0.8em;
	cursor: pointer;
	font-weight: 700;
	list-style: none; /* Firefox の ::marker を消す（下の ::after で代替する） */
}

.ffs-facet__summary::-webkit-details-marker {
	display: none; /* Safari の既定マーカーを消す */
}

.ffs-facet__label {
	flex: 1 1 auto;
	min-width: 0;
}

/* 開閉インジケータ（閉じている間は右向き、開くと下向き） */
.ffs-facet__summary::after {
	content: "";
	flex: 0 0 auto;
	width: 0;
	height: 0;
	margin-left: auto;
	border-top: 0.32em solid transparent;
	border-bottom: 0.32em solid transparent;
	border-left: 0.45em solid currentcolor;
	transform-origin: 0.18em 50%;
	transition: transform 0.15s ease;
}

.ffs-facet[open] > .ffs-facet__summary::after {
	transform: rotate(90deg);
}

.ffs-facet--selected > .ffs-facet__summary {
	border-left: 3px solid var(--ffs-accent, #1795d4);
}

.ffs-facet__badge::after {
	content: "";
	display: inline-block;
	width: 0.6em;
	height: 0.6em;
	border-radius: 50%;
	background: var(--ffs-accent, #1795d4);
}

.ffs-facet__body {
	border: 0;
	margin: 0;
	padding: 0 0.8em 0.8em;
}

.ffs-facet__help {
	margin: 0 0 0.5em;
	font-size: 0.85em;
	color: var(--ffs-muted, rgba(0, 0, 0, 0.6));
}

.ffs-facet__clear,
.ffs-summary__clear,
.ffs-chips__clear {
	margin: 0.5em 0 0;
	font-size: 0.9em;
}

/*
 * JS 無効時にこれらが唯一の解除手段になるので 44px を確保する（★P5R-10。AGENTS.md §7）。
 * em は自身の縮小 font-size に乗るため、44px を保証したい箇所では --ffs-tap-size（px）を直接使う。
 */
.ffs-facet__clear a,
.ffs-summary__clear a,
.ffs-chips__clear a {
	display: inline-flex;
	align-items: center;
	min-height: var(--ffs-tap-size, 44px);
}

/* ---------------------------------------------------------- コントロール */

.ffs-control,
.ffs-control__sublist {
	list-style: none;
	margin: 0;
	padding: 0;
	display: grid;
	grid-template-columns: 1fr;
	gap: 0.1em 0.6em;
}

@media (min-width: 30em) {
	.ffs-control[data-ffs-columns="2"],
	.ffs-control__sublist[data-ffs-columns="2"] {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}

	.ffs-control[data-ffs-columns="3"],
	.ffs-control__sublist[data-ffs-columns="3"] {
		grid-template-columns: repeat(3, minmax(0, 1fr));
	}

	.ffs-control[data-ffs-columns="4"],
	.ffs-control__sublist[data-ffs-columns="4"] {
		grid-template-columns: repeat(4, minmax(0, 1fr));
	}
}

/* 階層タクソノミーのグループ（親ターム名 ＋ 入れ子の選択肢一覧・P5R-15） */
.ffs-control__group {
	grid-column: 1 / -1;
	min-width: 0;
}

.ffs-group {
	margin: 0.4em 0 0.1em;
	font-size: 0.8em;
	font-weight: 700;
	color: var(--ffs-muted, rgba(0, 0, 0, 0.6));
}

.ffs-option {
	display: flex;
	align-items: center;
	gap: 0.4em;
	min-width: 0;
}

.ffs-option__label {
	display: flex;
	align-items: center;
	gap: 0.35em;
	min-height: var(--ffs-tap-size, 44px); /* ラベルがタップ対象になる */
	min-width: 0;
	cursor: pointer;
	line-height: 1.3;
}

/*
 * ★短い日本語の語を語中で割らない（S2）。
 *
 * 既定の折り返しは CJK を1文字単位で割るので、狭い列では
 * 「1LDK」→「1LD／K」「マンション」→「マンシ／ョン」のように**単語が分断される**。
 * 読めはするが体裁が悪く、日本語サイトが主戦場のこのプラグインでは常時起きるので、
 * 既定CSSで面倒を見る。ポートフォリオ用のスクリーンショットを撮って初めて気づいた
 * （DOM も aria も正しいので自動テストでは1件も落ちなかった）。
 *
 * `.ffs` の overflow-wrap: anywhere は**残す**。keep-all だけだと、列に収まらないほど
 * 長い語がはみ出して横スクロールが出る（AGENTS.md §7）。2つ併せて
 * 「収まるうちは割らない・収まらなければ割る」になる。
 * 回帰は tools/checks/browser.mjs の S2 検査で見る。
 */
.ffs-option__text,
.ffs-group,
.ffs-chip__label {
	word-break: keep-all;
}

.ffs-option__input:disabled + .ffs-option__label {
	color: var(--ffs-disabled, rgba(0, 0, 0, 0.38));
	cursor: not-allowed;
}

.ffs-count {
	font-size: 0.8em;
	color: var(--ffs-muted, rgba(0, 0, 0, 0.6));
	white-space: nowrap;
}

.ffs-hint {
	margin: 0.4em 0 0;
	font-size: 0.8em;
	color: var(--ffs-muted, rgba(0, 0, 0, 0.6));
}

/* AND / OR 切り替え */

.ffs-match {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 0.3em;
	margin: 0 0 0.5em;
	font-size: 0.85em;
}

/*
 * ★ラジオとラベルを1つの折り返し単位にする（S1）。
 * .ffs-match は flex-wrap するので、input と label が別々のフレックスアイテムだと
 * **両者の間で改行され**、狭いサイドバーで行末に「ラベルの無いラジオ」が取り残される。
 * 包むだけでは足りず、包んだ側を折り返し単位（inline-flex ＋ nowrap）にする必要がある。
 */
.ffs-match__item {
	display: inline-flex;
	align-items: center;
	gap: 0.2em;
	white-space: nowrap;
}

.ffs-match__label {
	display: inline-flex;
	align-items: center;
	min-height: var(--ffs-tap-size, 44px); /* 親の font-size: 0.85em に乗らない px 指定（P5R-10） */
	padding: 0 0.4em;
	cursor: pointer;
}

/* 範囲 */

.ffs-range__field {
	display: flex;
	align-items: center;
	gap: 0.4em;
	margin: 0 0 0.4em;
}

.ffs-range__label {
	min-width: 3.5em;
	font-size: 0.85em;
	color: var(--ffs-muted, rgba(0, 0, 0, 0.6));
}

.ffs-range__input {
	flex: 1 1 auto;
	min-width: 0;
	min-height: var(--ffs-tap-size, 44px);
}

/* ボタン */

.ffs-button {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 0.35em;
	min-height: var(--ffs-tap-size, 44px);
	padding: 0.35em 0.9em;
	border: 1px solid var(--ffs-border, rgba(0, 0, 0, 0.14));
	border-radius: var(--ffs-radius, 6px);
	background: transparent;
	color: inherit;
	cursor: pointer;
	text-decoration: none;
}

/*
 * 白抜き文字を載せる塗りは --ffs-accent-dark（白との比 5.03:1）を使う（★P5R-12）。
 * --ffs-accent（#1795d4）は白との比が 3.34:1 しかなく、WCAG 2.1 AA の通常文字 4.5:1 に届かない。
 * --ffs-accent は境界線・ドットなど**非テキスト用途（3:1 で足りる）**に限定する。
 */
.ffs-button--primary {
	border-color: var(--ffs-accent-dark, #0f76ab);
	background: var(--ffs-accent-dark, #0f76ab);
	color: #fff;
}

.ffs-button--selected {
	border-color: var(--ffs-accent-dark, #0f76ab);
	box-shadow: inset 0 0 0 1px var(--ffs-accent-dark, #0f76ab);
}

/* 色だけで状態を表さない（AGENTS.md §7・P5R-16） */
.ffs-button--selected::before {
	content: "\2713"; /* ✓ */
	flex: 0 0 auto;
	font-weight: 700;
}

.ffs-button--disabled {
	color: var(--ffs-disabled, rgba(0, 0, 0, 0.38));
	cursor: not-allowed;
}

.ffs-actions {
	margin-top: 0.8em;
}

/* ------------------------------------------------------------ 概要・チップ */

.ffs-summary {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 0.6em var(--ffs-gap, 1rem);
}

.ffs-total {
	margin: 0;
	font-weight: 700;
}

.ffs-sort {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 0.4em;
	margin-left: auto;
}

/*
 * ★ファセットの <select>（ui=select）も並び替えと同じ扱いにする（R4-MEDIUM-8）。
 * ここが抜けていると、サポート済みの表示形式のひとつだけがモバイルで高さ19pxになり、
 * 「タップ領域44px」（AGENTS.md §7 / requirements.md §15）を満たさない。
 * em ではなく px 変数を使う理由は P5R-10 と同じ（親の縮小 font-size に乗せない）。
 */
.ffs-sort__select,
.ffs-control__select {
	min-height: var(--ffs-tap-size, 44px);
	max-width: 100%;
}

.ffs-chips__list {
	list-style: none;
	display: flex;
	flex-wrap: wrap;
	gap: 0.4em;
	margin: 0;
	padding: 0;
}

.ffs-chip__link {
	display: inline-flex;
	align-items: center;
	gap: 0.4em;
	min-height: var(--ffs-tap-size, 44px); /* 自身の font-size: 0.9em に乗らない px 指定（P5R-10） */
	padding: 0.2em 0.7em;
	border: 1px solid var(--ffs-accent-dark, #0f76ab);
	border-radius: 999px;
	text-decoration: none;
	font-size: 0.9em;
}

/* ---------------------------------------------------------------- 結果 */

.ffs-results {
	list-style: none;
	display: grid;
	grid-template-columns: 1fr;
	gap: var(--ffs-gap, 1rem);
	margin: 0;
	padding: 0;
}

@media (min-width: 40em) {
	.ffs-results {
		grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr));
	}
}

.ffs-item {
	border: 1px solid var(--ffs-border, rgba(0, 0, 0, 0.14));
	border-radius: var(--ffs-radius, 6px);
	padding: 0.8em;
	min-width: 0;
}

.ffs-item img {
	max-width: 100%;
	height: auto;
	border-radius: var(--ffs-radius, 6px);
}

.ffs-title {
	margin: 0.3em 0;
	font-size: 1.05em;
}

.ffs-terms {
	list-style: none;
	display: flex;
	flex-wrap: wrap;
	gap: 0.3em;
	margin: 0 0 0.4em;
	padding: 0;
	font-size: 0.8em;
	color: var(--ffs-muted, rgba(0, 0, 0, 0.6));
}

.ffs-terms__item {
	border: 1px solid var(--ffs-border, rgba(0, 0, 0, 0.14));
	border-radius: var(--ffs-radius, 6px);
	padding: 0.05em 0.5em;
}

.ffs-excerpt,
.ffs-meta {
	margin: 0.3em 0 0;
	font-size: 0.9em;
	color: var(--ffs-muted, rgba(0, 0, 0, 0.6));
}

.ffs-empty {
	border: 1px dashed var(--ffs-border, rgba(0, 0, 0, 0.14));
	border-radius: var(--ffs-radius, 6px);
	padding: 1.2em;
	text-align: center;
	color: var(--ffs-muted, rgba(0, 0, 0, 0.6));
}

/* -------------------------------------------------------------- ページャ */

.ffs-pager__list {
	list-style: none;
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
	gap: 0.3em;
	margin: 0;
	padding: 0;
}

.ffs-pager__link,
.ffs-pager__current,
.ffs-pager__ellipsis {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-width: var(--ffs-tap-size, 44px);
	min-height: var(--ffs-tap-size, 44px);
	padding: 0 0.5em;
	border: 1px solid var(--ffs-border, rgba(0, 0, 0, 0.14));
	border-radius: var(--ffs-radius, 6px);
	text-decoration: none;
}

.ffs-pager__current {
	border-color: var(--ffs-accent-dark, #0f76ab);
	background: var(--ffs-accent-dark, #0f76ab);
	color: #fff;
	font-weight: 700;
}

.ffs-pager__ellipsis {
	border-color: transparent;
}

/* -------------------------------------------------------- 読み込み中（JS時のみ） */

/*
 * `aria-busy` は JS が器（.ffs）に付け外しする（assets/js/ffs.js）。
 * JS が無い環境では属性自体が付かないので、この節はまるごと無効になる。
 * 件数の読み上げは [data-ffs-summary] の aria-live が担うので、ここは視覚的な合図だけ。
 */
.ffs[aria-busy="true"] .ffs-main {
	position: relative;
	opacity: 0.55;
	transition: opacity 0.15s linear;
}

.ffs[aria-busy="true"] .ffs-main::before {
	content: "";
	position: absolute;
	top: 0;
	left: 0;
	right: 0;
	height: 3px;
	border-radius: 3px;
	background: var(--ffs-accent, #1795d4);
	transform-origin: 0 50%;
	animation: ffs-progress 1.1s ease-in-out infinite;
}

@keyframes ffs-progress {
	0% {
		transform: scaleX(0.05);
	}

	50% {
		transform: scaleX(1);
	}

	100% {
		transform: scaleX(0.05);
	}
}

/*
 * ★読み込み中でもクリックは殺さない（P6R-1）。
 * `pointer-events: none` を置くと、応答が返ってこないあいだページ送りリンクを押せなくなり、
 * 「JSが失敗してもGETフォーム（素のリンク）で動く」という前提が、失敗ではなく**停滞**のときだけ
 * 破れる。二重送信は AbortController が捨てるので、物理的に押せなくする必要はない。
 * 読み込み中であることは上の帯と opacity で伝える。
 */

/* デバッグパネル（5断片の外）は JS が差し替えないので、無リロード更新後は初回描画時の値のまま。 */
.ffs [data-ffs-debug][data-ffs-stale="true"] {
	opacity: 0.6;
}

/* ------------------------------------------------------------------ その他 */

.ffs :focus-visible {
	outline: 2px solid var(--ffs-accent-dark, #0f76ab);
	outline-offset: 2px;
}

/* JS がページ送りでフォーカスを移す先（アウトラインは :focus-visible だけに出す）。 */
.ffs [data-ffs-results]:focus {
	outline: none;
}

@media (prefers-reduced-motion: reduce) {
	.ffs *,
	.ffs *::before,
	.ffs *::after {
		transition: none !important;
		animation: none !important;
	}

	/* 動きを止めるかわりに、読み込み中であることは帯の表示だけで伝える。 */
	.ffs[aria-busy="true"] .ffs-main::before {
		transform: scaleX(1);
	}
}
