/* ==========================================================================
   Search Page — Polished UI (Gradio-quality)
   ========================================================================== */

/* ── Page layout ── */
.search-page {
    max-width: var(--container-max);
    margin: 0 auto;
    padding: 1.75rem 1.5rem 8.5rem;
}

/* ── Hero band tokens (light-core4 PR5a, retargeted PR7 3단계 배치3) ──
   The hero carried its light and dark colours as literals inside two separate
   rules. Literals cannot be reached by a token override, which is how PR4 lost
   the landing stat tiles, so they moved into tokens in PR5a.

   The two rules are deliberately NOT merged (see
   docs/service-platform/SEARCH_LITERAL_INVENTORY.md §6): merging would make the
   dark render resolve through a new cascade path, and identical-dark-SHA is the
   evidence this step rests on.

   PR7 3단계 retargets the light set onto canonical values: the dark gradient
   band becomes a light command surface with a faint deep-teal wash
   (color-mix, the same idiom target.css already uses at :192/197/279), border
   and shadow become canonical/neutral. glow is deactivated (transparent/0%)
   rather than retargeted — the approved light spec has no glow concept for
   this surface at all (docs/service-platform/previews/light-core4/
   light-search.html has no gradient/glow band). Dark stays exactly as it was
   (:132-138 below, untouched). */
:root {
    --color-search-hero-border: var(--color-border);
    --color-search-hero-glow: transparent;
    --color-search-hero-glow-extent: 0%;
    --color-search-hero-grad-start: color-mix(in srgb, var(--color-primary) 10%, var(--color-surface));
    --color-search-hero-grad-mid: color-mix(in srgb, var(--color-primary) 6%, var(--color-surface));
    --color-search-hero-grad-end: var(--color-surface);
    --color-search-hero-shadow: color-mix(in srgb, var(--color-text) 8%, transparent);

    /* Overlays that sit on the hero band (retargeted PR7 3단계 배치4). These
       rules had no [data-theme] variant pre-3단계 — the dark render depended
       on that single definition alone, which is exactly why 3단계 pins the
       pre-retarget values into :132 below rather than leaving these
       single-defined against a now-theme-variant canonical. */
    --color-search-context-bg: var(--color-surface);
    --color-search-context-border: var(--color-border);
    --color-search-action-bg: var(--color-surface);
    --color-search-action-border: var(--color-border);
    --color-search-action-bg-hover: var(--color-surface-hover);
    --color-search-action-border-hover: var(--color-border-strong);
    --color-search-intake-panel-bg: var(--color-surface);
    --color-search-intake-panel-border: var(--color-border);
    --color-search-intake-pill-bg: var(--color-surface-secondary);
    --color-search-intake-link-bg: var(--color-surface-secondary);
    --color-search-intake-link-bg-hover: var(--color-surface-hover);
    --color-search-intake-bar-border: var(--color-border);
    /* needs-spec-decision — the approved light spec has no glow concept;
       untouched by PR7 3단계. */
    --color-search-intake-bar-glow: rgba(96, 165, 250, 0.14);
    --color-search-intake-bar-glow-extent: 34%;
    --color-search-intake-bar-shadow: color-mix(in srgb, var(--color-text) 5%, transparent);

    /* PR5b-1 batch A — results table (retargeted PR7 3단계 배치4). Was
       theme-neutral single definition; now pinned at :132 for the same
       reason as the overlay tokens above. */
    --color-table-row-zebra: var(--color-surface-secondary);
    --color-table-frozen-shadow: color-mix(in srgb, var(--color-text) 8%, transparent);

    /* PR5b-1 batch B — assay type chips. A semantic set: each chip keeps its
       own token even where the value coincides with another (binding matches
       --color-primary), so retargeting one meaning cannot drag the others.
       Theme-neutral like batch A; values preserved from the literals. */
    --color-assay-binding: #2563eb;
    --color-assay-functional: #16a34a;
    --color-assay-admet: #d97706;
    --color-assay-toxicity: #dc2626;
    --color-assay-physchem: #7c3aed;

    /* PR5b-1 batch C — input card (retargeted PR7 3단계 배치5). No
       [data-theme] counterpart exists for .search-card, .query-textarea:focus
       or .btn-search — 3단계 pins the pre-retarget values into :190 below
       instead. */
    --color-search-card-border: var(--color-border);
    --color-search-card-shadow: color-mix(in srgb, var(--color-text) 5%, transparent);
    --color-search-focus-ring: var(--color-focus-ring);
    --color-search-btn-grad-a: var(--color-primary);
    --color-search-btn-grad-b: var(--color-primary-dark);
    --color-search-btn-shadow: color-mix(in srgb, var(--color-primary) 18%, transparent);
    /* Hover darkens the first stop only; the second is grad-b by reference so
       the pair cannot drift when the gradient is retargeted.
       needs-spec-decision — hover needs a step darker than --color-primary-dark
       and the approved spec has none yet; untouched by PR7 3단계. */
    --color-search-btn-grad-hover-a: #1d4ed8;
    --color-search-btn-shadow-hover: rgba(37, 99, 235, 0.25);

    /* PR5b-1 batch D — source guidance (light set; dark pairs below,
       retargeted PR7 3단계 배치5). The only body surface with a real
       [data-theme="dark"] rule, so grad-a/grad-b/tint-a/border are defined
       twice and both rules read the same names — 3단계 only retargets the
       light side here, dark stays exactly as PR5b left it. tint-b is
       needs-spec-decision (untouched, both themes).

       --color-sg-shadow and the sub-surface tokens below it were NOT paired
       pre-3단계: the dark rule overrides background/border-color only, so a
       dark value would have repainted a surface that never changed. PR7
       3단계 gives them a dark value now anyway, but as a pin (:190) freezing
       the pre-retarget appearance — not because the dark rule started
       overriding them.

       -border and -card-border hold the same value as the batch C card tokens
       and stay separate on purpose (SEARCH_PR5B_TOKEN_MAP.md). */
    --color-sg-grad-a: var(--color-surface);
    --color-sg-grad-b: var(--color-surface);
    --color-sg-tint-a: color-mix(in srgb, var(--color-primary) 8%, var(--color-surface));
    --color-sg-tint-b: rgba(14, 165, 233, 0.06);
    --color-sg-border: var(--color-border);
    --color-sg-shadow: color-mix(in srgb, var(--color-text) 5%, transparent);
    --color-sg-kicker-bg: color-mix(in srgb, var(--color-primary) 10%, var(--color-surface));
    --color-sg-context-border: color-mix(in srgb, var(--color-primary) 12%, var(--color-border));
    --color-sg-context-bg: color-mix(in srgb, var(--color-primary) 5%, var(--color-surface));
    --color-sg-badge-bg: var(--color-surface-secondary);
    --color-sg-card-border: var(--color-border);

    /* PR5b-1 batch E — search-scoped row action chips. --color-fav-chip-* stay
       keep-semantic (untouched) — favourite-active ≠ brand. --color-memo-chip-
       border is retargeted PR7 3단계 배치5 (follow-primary); it had no dark
       pair pre-3단계, so it gets a pin (:190) same as the rest of this batch. */
    --color-fav-chip-border: rgba(251, 191, 36, 0.35);
    --color-fav-chip-bg: rgba(251, 191, 36, 0.16);
    --color-fav-chip-text: #b45309;
    --color-memo-chip-border: color-mix(in srgb, var(--color-primary) 24%, var(--color-border));

    /* PR7 2단계 — 히어로 foreground를 전용 토큰으로 뽑아냄(값 보존). PR7 3단계
       (배치3)가 그 토큰들을 canonical(var(--color-text)/-secondary/
       -surface-secondary)로 재타겟했다 — 이 6개는 그때까지 다크 짝이 없었지만,
       이제 :140 다크 블록에 3단계 pin이 생겼다(정정: "다크 짝 없음"이었던 옛
       주석은 더 이상 맞지 않는다). */
    --color-search-hero-text: var(--color-text);
    --color-search-hero-text-muted: var(--color-text-secondary);
    /* .search-intake-rule p was 0.84, not 0.82 pre-retarget — a distinct value
       from the four -text-muted call sites above, caught by the dark render
       gate when it was first (wrongly) folded into -text-muted (act -> step2
       diff on search-hero-auth). Kept as a separate token rather than rounded
       into -muted; both now read the same canonical (-text-secondary) since
       the distinction that mattered was value-preservation pre-3단계, not a
       different canonical mapping. */
    --color-search-hero-text-subtle: var(--color-text-secondary);
    --color-search-hero-control-text: var(--color-text);
    /* Kicker only. .search-intake-pill and .search-intake-link read
       --color-search-hero-text (not this token) — see the -text pin below,
       which preserves that sharing. */
    --color-search-hero-chip-text: var(--color-text-secondary);
    --color-search-hero-chip-bg: var(--color-surface-secondary);
}
:root[data-theme="dark"] {
    --color-search-hero-border: rgba(59, 130, 246, 0.18);
    --color-search-hero-glow: rgba(59, 130, 246, 0.18);
    --color-search-hero-glow-extent: 40%;
    --color-search-hero-grad-start: #0a101e;
    --color-search-hero-grad-mid: #14284b;
    --color-search-hero-grad-end: #0a3a3a;

    /* PR7 3단계 — 다크 고정(pin). 이 7개는 라이트에서 canonical(테마별로 값이
       다름)로 재타겟됐고 3단계 전까지 다크 짝이 없었다. 다크 짝이 없으면 다크
       렌더가 canonical의 다크값을 새로 읽게 되므로, 옛 라이트 리터럴을 여기
       그대로 고정해 다크를 구조적으로 불변으로 만든다. */
    --color-search-hero-shadow: rgba(15, 23, 42, 0.08);
    --color-search-hero-text: var(--color-text-inverse);
    --color-search-hero-text-muted: rgba(255, 255, 255, 0.82);
    --color-search-hero-text-subtle: rgba(255, 255, 255, 0.84);
    --color-search-hero-control-text: var(--color-text-inverse);
    --color-search-hero-chip-text: rgba(255, 255, 255, 0.88);
    --color-search-hero-chip-bg: rgba(255, 255, 255, 0.14);

    /* PR7 3단계 — 다크 고정(pin), 배치4. 히어로 오버레이 패널 15개(context/
       action/intake-panel/intake-pill/intake-link bg·border류 + intake-bar-
       border/shadow + table-row-zebra/table-frozen-shadow) — 전부 3단계 전까지
       다크 짝이 없었다. --color-search-intake-bar-glow/-glow-extent는
       needs-spec-decision이라 여기 포함되지 않는다(위 라이트 :root에서도
       미변경). */
    --color-search-context-bg: rgba(255, 255, 255, 0.14);
    --color-search-context-border: rgba(255, 255, 255, 0.16);
    --color-search-action-bg: rgba(255, 255, 255, 0.15);
    --color-search-action-border: rgba(255, 255, 255, 0.3);
    --color-search-action-bg-hover: rgba(255, 255, 255, 0.25);
    --color-search-action-border-hover: rgba(255, 255, 255, 0.5);
    --color-search-intake-panel-bg: rgba(255, 255, 255, 0.1);
    --color-search-intake-panel-border: rgba(255, 255, 255, 0.16);
    --color-search-intake-pill-bg: rgba(15, 23, 42, 0.28);
    --color-search-intake-link-bg: rgba(15, 23, 42, 0.22);
    --color-search-intake-link-bg-hover: rgba(255, 255, 255, 0.22);
    --color-search-intake-bar-border: rgba(148, 163, 184, 0.18);
    --color-search-intake-bar-shadow: rgba(15, 23, 42, 0.05);
    --color-table-row-zebra: rgba(0,0,0,0.01);
    --color-table-frozen-shadow: rgba(0,0,0,0.08);

    /* PR5b-1 batch D — source guidance dark pairs. Exactly the five the dark
       rule overrode (PAIRED_SG_TOKENS in test_search_body_tokens.py) — these
       5 are unchanged by PR7 3단계, only their light counterparts moved. */
    --color-sg-grad-a: rgba(15, 23, 42, 0.98);
    --color-sg-grad-b: rgba(15, 23, 42, 0.94);
    --color-sg-tint-a: rgba(37, 99, 235, 0.18);
    --color-sg-tint-b: rgba(14, 165, 233, 0.12);
    --color-sg-border: rgba(59, 130, 246, 0.18);

    /* PR7 3단계 — 다크 고정(pin), 배치5. CTA 버튼(3) + source-guidance
       서브서피스(6) + search-card(2) + focus-ring(1) + memo-chip-border(1)
       = 13개. 전부 3단계 전까지 다크 짝이 없었다(test_search_body_tokens.py의
       STAGE3_PINNED_SG_TOKENS와 함께 확인).

       --color-search-focus-ring도 pin이 필요하다는 걸 렌더 게이트가 잡아냈다:
       canonical(--color-focus-ring, #0b8ea3)이 라이트·다크 양쪽에서 같은 값을
       내는 건 맞지만("테마 불변"), 그건 "재타겟 후 라이트·다크가 서로 같다"는
       뜻이지 "다크가 재타겟 전 값(rgba(37,99,235,0.1), 파란 계열)과 같다"는
       뜻이 아니다 — 다크 짝이 없던 단일정의 토큰이라 pin 없이는 다크도 새
       canonical 값을 그대로 물려받아 파란 포커스 링이 틸로 바뀐다
       (search-card-focus 다크 캡처 SHA가 실제로 바뀌어 잡힘). */
    --color-search-btn-grad-a: #2563eb;
    --color-search-btn-grad-b: #0f766e;
    --color-search-btn-shadow: rgba(37, 99, 235, 0.18);
    --color-search-focus-ring: rgba(37,99,235,0.1);
    --color-sg-shadow: rgba(15, 23, 42, 0.05);
    --color-sg-kicker-bg: rgba(37, 99, 235, 0.1);
    --color-sg-context-border: rgba(37, 99, 235, 0.12);
    --color-sg-context-bg: rgba(37, 99, 235, 0.05);
    --color-sg-badge-bg: rgba(15, 23, 42, 0.08);
    --color-sg-card-border: rgba(148, 163, 184, 0.18);
    --color-search-card-border: rgba(148, 163, 184, 0.18);
    --color-search-card-shadow: rgba(15, 23, 42, 0.05);
    --color-memo-chip-border: rgba(37, 99, 235, 0.24);
}

/* ── Page header (Hero) ── */
.search-hero {
    margin-bottom: 1.25rem;
    padding: 1rem 1.6rem;
    border-radius: 1.5rem;
    border: 1px solid var(--color-search-hero-border);
    background:
        radial-gradient(circle at top right, var(--color-search-hero-glow), transparent var(--color-search-hero-glow-extent)),
        linear-gradient(135deg, var(--color-search-hero-grad-start) 0%, var(--color-search-hero-grad-mid) 62%, var(--color-search-hero-grad-end) 100%);
    color: var(--color-search-hero-text);
    box-shadow: 0 18px 38px var(--color-search-hero-shadow);
}
[data-theme="dark"] .search-hero {
    border-color: var(--color-search-hero-border);
    background:
        radial-gradient(circle at top right, var(--color-search-hero-glow), transparent var(--color-search-hero-glow-extent)),
        linear-gradient(135deg, var(--color-search-hero-grad-start) 0%, var(--color-search-hero-grad-mid) 62%, var(--color-search-hero-grad-end) 100%);
}

.search-hero h1 {
    font-size: clamp(2.1rem, 4vw, 2.8rem);
    line-height: 0.96;
    font-weight: 700;
    letter-spacing: -0.02em;
    margin: 0 0 0.65rem;
    color: var(--color-search-hero-text);
}
.search-hero p {
    color: var(--color-search-hero-text-muted);
    font-size: 0.98rem;
    line-height: 1.7;
    margin: 0;
    max-width: 66ch;
}

.search-project-context {
    margin-top: 0.75rem;
    padding: 0.55rem 1rem;
    border-radius: 1.15rem;
    border: 1px solid var(--color-search-context-border);
    background: var(--color-search-context-bg);
    backdrop-filter: blur(10px);
    display: flex;
    gap: 0.75rem;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
}
.search-project-meta {
    display: flex;
    flex-direction: column;
    gap: 0.2rem;
}
.search-project-meta strong {
    font-size: 0.95rem;
    color: var(--color-search-hero-text);
}
.search-project-meta span {
    font-size: 0.8125rem;
    color: var(--color-search-hero-text-muted);
    line-height: 1.55;
}

.search-project-actions {
    display: flex;
    gap: 0.5rem;
    align-items: center;
    flex-wrap: wrap;
}
.search-project-actions label {
    font-size: 0.8125rem;
    color: var(--color-search-hero-text-muted);
    font-weight: 600;
}
.search-project-actions select,
.search-project-actions button {
    background: var(--color-search-action-bg);
    color: var(--color-search-hero-control-text);
    border: 1px solid var(--color-search-action-border);
    border-radius: 0.8rem;
    padding: 0.6rem 0.75rem;
    font: inherit;
    font-size: 0.9rem;
    cursor: pointer;
    transition: all var(--transition);
}
.search-project-actions select:hover,
.search-project-actions button:hover {
    background: var(--color-search-action-bg-hover);
    border-color: var(--color-search-action-border-hover);
}
.search-project-actions select option {
    background: var(--color-surface);
    color: var(--color-text);
}

.search-hero-kicker {
    display: inline-flex;
    align-items: center;
    padding: 0.3rem 0.7rem;
    margin-bottom: 0.7rem;
    border-radius: 999px;
    background: var(--color-search-hero-chip-bg);
    color: var(--color-search-hero-chip-text);
    font-size: 0.75rem;
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
}

.search-intake-handoff {
    display: flex;
    gap: 0.85rem;
    align-items: stretch;
    justify-content: space-between;
    flex-wrap: wrap;
    margin-top: 0.8rem;
}

.search-intake-rule,
.search-intake-links {
    border: 1px solid var(--color-search-intake-panel-border);
    border-radius: 1.05rem;
    background: var(--color-search-intake-panel-bg);
    backdrop-filter: blur(10px);
}

.search-intake-rule {
    flex: 1 1 28rem;
    padding: 0.85rem 1rem;
}

.search-intake-rule p {
    margin: 0.45rem 0 0;
    font-size: 0.875rem;
    line-height: 1.6;
    color: var(--color-search-hero-text-subtle);
}

.search-intake-pill {
    display: inline-flex;
    align-items: center;
    padding: 0.22rem 0.55rem;
    border-radius: 999px;
    background: var(--color-search-intake-pill-bg);
    color: var(--color-search-hero-text);
    font-size: 0.72rem;
    font-weight: 700;
    letter-spacing: 0.04em;
    text-transform: uppercase;
}

.search-intake-links {
    display: flex;
    gap: 0.5rem;
    flex-wrap: wrap;
    align-items: center;
    padding: 0.75rem;
    flex: 0 1 18rem;
}

.search-intake-link {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-height: 2.25rem;
    padding: 0.55rem 0.8rem;
    border-radius: 0.85rem;
    background: var(--color-search-intake-link-bg);
    color: var(--color-search-hero-text);
    text-decoration: none;
    font-size: 0.8125rem;
    font-weight: 600;
    transition: background var(--transition), transform var(--transition);
}

.search-intake-link:hover {
    background: var(--color-search-intake-link-bg-hover);
    transform: translateY(-1px);
}

.search-source-guidance {
    margin-bottom: 1rem;
    padding: 1.1rem 1.2rem;
    border: 1px solid var(--color-sg-border);
    border-radius: 1.3rem;
    background:
        linear-gradient(180deg, var(--color-sg-grad-a), var(--color-sg-grad-b)),
        linear-gradient(135deg, var(--color-sg-tint-a), var(--color-sg-tint-b));
    box-shadow: 0 14px 30px var(--color-sg-shadow);
}

[data-theme="dark"] .search-source-guidance {
    background:
        linear-gradient(180deg, var(--color-sg-grad-a), var(--color-sg-grad-b)),
        linear-gradient(135deg, var(--color-sg-tint-a), var(--color-sg-tint-b));
    border-color: var(--color-sg-border);
}

.search-source-guidance-head {
    display: flex;
    gap: 1rem;
    align-items: flex-start;
    justify-content: space-between;
    flex-wrap: wrap;
    margin-bottom: 1rem;
}

.search-source-guidance-copy {
    flex: 1 1 28rem;
}

.search-source-guidance-kicker {
    display: inline-flex;
    align-items: center;
    padding: 0.22rem 0.6rem;
    border-radius: 999px;
    background: var(--color-sg-kicker-bg);
    color: var(--color-primary);
    font-size: 0.72rem;
    font-weight: 700;
    letter-spacing: 0.05em;
    text-transform: uppercase;
}

/* PR7 4단계: --color-primary text on its own 10%-tint background falls just
   under WCAG AA (4.32:1) in light mode. --color-primary-dark already exists
   for exactly this pairing; dark mode is left alone since its own tint
   background is dark, not light, and doesn't have this problem. */
:root:not([data-theme="dark"]) .search-source-guidance-kicker {
    color: var(--color-primary-dark);
}

.search-source-guidance-copy h2 {
    margin: 0.55rem 0 0.4rem;
    font-size: 1.3rem;
    line-height: 1.2;
}

.search-source-guidance-copy p {
    margin: 0;
    color: var(--color-text-secondary);
    font-size: 0.95rem;
    line-height: 1.65;
    max-width: 62ch;
}

.search-source-guidance-context {
    flex: 0 1 20rem;
    display: flex;
    flex-direction: column;
    gap: 0.4rem;
    padding: 0.9rem 1rem;
    border-radius: 1rem;
    border: 1px solid var(--color-sg-context-border);
    background: var(--color-sg-context-bg);
}

.search-source-guidance-badge {
    display: inline-flex;
    align-self: flex-start;
    align-items: center;
    padding: 0.22rem 0.55rem;
    border-radius: 999px;
    background: var(--color-sg-badge-bg);
    color: var(--color-text);
    font-size: 0.72rem;
    font-weight: 700;
    letter-spacing: 0.04em;
    text-transform: uppercase;
}

.search-source-guidance-context strong {
    font-size: 0.98rem;
    color: var(--color-text);
}

.search-source-guidance-context p {
    margin: 0;
    color: var(--color-text-secondary);
    font-size: 0.85rem;
    line-height: 1.6;
}

.search-source-guidance-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
    gap: 0.8rem;
}

.search-source-guidance-card {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    min-height: 100%;
    padding: 1rem;
    border-radius: 1rem;
    border: 1px solid var(--color-sg-card-border);
    background: var(--color-surface);
}

.search-source-guidance-task {
    color: var(--color-text);
    font-size: 0.96rem;
    font-weight: 700;
    line-height: 1.45;
}

.search-source-guidance-source {
    color: var(--color-primary);
    font-size: 0.84rem;
    font-weight: 700;
    letter-spacing: 0.02em;
    text-transform: uppercase;
}

.search-source-guidance-detail {
    color: var(--color-text-secondary);
    font-size: 0.82rem;
    line-height: 1.5;
}

.search-source-guidance-note {
    flex: 1;
    margin: 0;
    color: var(--color-text-secondary);
    font-size: 0.88rem;
    line-height: 1.65;
}

/* ── Card panels ── */
.search-card {
    background: linear-gradient(180deg, var(--color-surface) 0%, var(--color-surface-elevated) 100%);
    border: 1px solid var(--color-search-card-border);
    border-radius: 1.35rem;
    padding: 1.45rem;
    margin-bottom: 1rem;
    box-shadow: 0 16px 32px var(--color-search-card-shadow);
    transition: border-color var(--transition);
}
.search-card:focus-within {
    border-color: var(--color-primary);
}

/* ── Input section ── */
.input-section {
    display: flex;
    flex-direction: column;
    gap: 1rem;
}
.input-row {
    display: flex;
    gap: 1rem;
    align-items: stretch;
}
.input-main { flex: 3; min-width: 0; display: flex; flex-direction: column; }
.input-sidebar { flex: 1; min-width: 180px; display: flex; flex-direction: column; gap: 0.75rem; }
.input-sidebar > div { position: relative; }

/* ── Form labels ── */
/* .field-label → .form-label (components.css §20) */

/* ── Query textarea ── */
.query-textarea {
    width: 100%;
    flex: 1;
    min-height: 7rem;
    padding: 0.85rem 1rem;
    border: 1px solid var(--color-border);
    border-radius: 0.95rem;
    font-size: 0.9375rem;
    font-family: var(--font-sans);
    line-height: 1.5;
    resize: vertical;
    background: var(--color-bg);
    color: var(--color-text);
    transition: border-color var(--transition), box-shadow var(--transition), background var(--transition);
}
.query-textarea:focus {
    outline: none;
    border-color: var(--color-primary);
    box-shadow: 0 0 0 3px var(--color-search-focus-ring);
    background: var(--color-surface);
}
.query-textarea::placeholder { color: var(--color-text-secondary); }

/* .field-select / .field-input → .form-input (components.css §20) */
/* search 전용 appearance:auto 는 form-input 기반에서도 자동 상속됨 */

/* ── Search button ── */
.search-actions {
    display: flex;
    align-items: center;
    gap: 0.75rem;
}
.btn-search {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    padding: 0.72rem 2rem;
    background: linear-gradient(135deg, var(--color-search-btn-grad-a), var(--color-search-btn-grad-b));
    color: var(--color-text-inverse);
    border: none;
    border-radius: 999px;
    box-shadow: 0 10px 18px var(--color-search-btn-shadow);
    font-size: 0.9375rem;
    font-weight: 600;
    font-family: var(--font-sans);
    cursor: pointer;
    transition: all var(--transition);
    min-width: 120px;
    height: 2.75rem;
}

.btn-search:hover { background: linear-gradient(135deg, var(--color-search-btn-grad-hover-a), var(--color-search-btn-grad-b)); box-shadow: 0 12px 24px var(--color-search-btn-shadow-hover); }
.btn-search:disabled { opacity: 0.5; cursor: not-allowed; }
.btn-search:active:not(:disabled) { transform: scale(0.98); }

.btn-search .btn-spinner {
    display: none;
    width: 16px; height: 16px;
    border: 2px solid rgba(255,255,255,0.3);
    border-top-color: var(--color-text-inverse);
    border-radius: 50%;
    animation: spin 0.7s linear infinite;
}
.btn-search.loading .btn-spinner { display: inline-block; }

.shortcut-hint {
    font-size: 0.75rem;
    color: var(--color-text-muted);
}
.shortcut-hint kbd {
    display: inline-block;
    padding: 0.1rem 0.375rem;
    background: var(--color-bg);
    border: 1px solid var(--color-border);
    border-radius: 3px;
    font-size: 0.6875rem;
    font-family: var(--font-sans);
    font-weight: 500;
    color: var(--color-text-secondary);
}

/* ── Example queries ── */
.examples-section {
    padding-top: 0.75rem;
    border-top: 1px solid var(--color-border-light);
}
.examples-label {
    font-size: 0.75rem;
    font-weight: 600;
    color: var(--color-text-muted);
    text-transform: uppercase;
    letter-spacing: 0.05em;
    margin-bottom: 0.5rem;
}
.example-chips { display: flex; flex-wrap: wrap; gap: 0.375rem; }
/* .example-chip → .chip (components.css §19) */

/* ── Status banner ── */
.status-banner {
    display: none;
    align-items: flex-start;
    gap: 0.625rem;
    padding: 0.75rem 1rem;
    border-radius: var(--radius-sm);
    font-size: 0.875rem;
    line-height: 1.5;
    margin-bottom: 1rem;
}
.status-banner.visible { display: flex; }
.status-banner .status-icon { font-size: 1rem; flex-shrink: 0; margin-top: 0.1rem; }
.status-banner .status-text { flex: 1; }

.status-banner.info {
    background: var(--color-info-soft);
    border: 1px solid var(--color-primary-light);
    color: var(--color-info-strong);
}
.status-banner.error {
    background: var(--color-danger-soft);
    border: 1px solid var(--color-danger-border);
    color: var(--color-danger-strong);
}
.status-banner.success {
    background: var(--color-cta-light);
    border: 1px solid var(--color-cta);
    color: var(--color-cta-hover);
}

/* #249 2단계 — the sibling .info/.error banners above already read a
   theme-aware "-strong" token; .success used --color-cta-hover instead,
   which falls to 3.75:1 in dark (composites to #0c3031). */
:root[data-theme="dark"] .status-banner.success { color: var(--color-cta-strong); }

/* ── Loading overlay ── */
.loading-section {
    display: none;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding: 3rem 1rem;
    gap: 1rem;
}
.loading-section.active { display: flex; }

.loading-ring {
    width: 40px; height: 40px;
    border: 3px solid var(--color-border);
    border-top-color: var(--color-primary);
    border-radius: 50%;
    animation: spin 0.8s linear infinite;
}

.loading-text {
    font-size: 0.9375rem;
    color: var(--color-text-secondary);
    text-align: center;
}
.loading-sub {
    font-size: 0.8125rem;
    color: var(--color-text-muted);
}

/* ── Results panel ── */
.results-panel { display: none; }
.results-panel.visible { display: block; }

.search-intake-bar {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 1rem;
    margin-bottom: 0.85rem;
    padding: 1rem 1.1rem;
    border: 1px solid var(--color-search-intake-bar-border);
    border-radius: 1.1rem;
    background:
        radial-gradient(circle at top right, var(--color-search-intake-bar-glow), transparent var(--color-search-intake-bar-glow-extent)),
        linear-gradient(180deg, var(--color-surface) 0%, var(--color-surface-elevated) 100%);
    box-shadow: 0 14px 28px var(--color-search-intake-bar-shadow);
}

.search-intake-bar-copy {
    display: flex;
    flex-direction: column;
    gap: 0.22rem;
    min-width: 0;
}

.search-intake-bar-kicker {
    font-size: 0.72rem;
    font-weight: 700;
    color: var(--color-text-muted);
    letter-spacing: 0.08em;
    text-transform: uppercase;
}

.search-intake-bar-title {
    font-size: 1rem;
    line-height: 1.3;
    color: var(--color-text);
}

.search-intake-bar-summary {
    font-size: 0.8125rem;
    line-height: 1.55;
    color: var(--color-text-secondary);
    max-width: 62ch;
}

.search-intake-bar-meta {
    display: flex;
    flex-direction: column;
    gap: 0.55rem;
    align-items: flex-end;
    min-width: 15rem;
}

.search-intake-count {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-height: 1.9rem;
    padding: 0.25rem 0.75rem;
    border-radius: 999px;
    background: var(--color-primary-light);
    color: var(--color-primary-dark);
    font-size: 0.75rem;
    font-weight: 700;
}

.search-intake-bar-actions {
    display: flex;
    gap: 0.45rem;
    flex-wrap: wrap;
    justify-content: flex-end;
}

.search-intake-summary-link {
    text-decoration: none;
}

.results-toolbar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 0.75rem 1rem;
    background: var(--color-bg);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm) var(--radius-sm) 0 0;
    border-bottom: none;
}
.results-meta {
    display: flex;
    align-items: center;
    gap: 0.75rem;
}
.results-count {
    font-size: 0.8125rem;
    font-weight: 600;
    color: var(--color-text);
}
.results-badge {
    font-size: 0.6875rem;
    font-weight: 600;
    padding: 0.15rem 0.5rem;
    border-radius: 999px;
    background: var(--color-primary-light);
    color: var(--color-primary-dark);
}

/* #249 2단계 — --color-primary-dark text on its own --color-primary-light
   tint falls to 2.9:1 in dark (composites to #142647); background stays as-is. */
:root[data-theme="dark"] .results-badge { color: var(--color-primary-strong); }

.results-actions { display: flex; gap: 0.375rem; }
.btn-action {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    padding: 0.375rem 0.75rem;
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
    background: var(--color-surface);
    font-size: 0.8125rem;
    font-family: var(--font-sans);
    color: var(--color-text-secondary);
    cursor: pointer;
    transition: all var(--transition);
}
.btn-action:hover {
    border-color: var(--color-primary);
    color: var(--color-primary);
    background: var(--color-primary-light);
}

/* ── Data table ── */
.table-wrapper {
    overflow-x: auto;
    border: 1px solid var(--color-border);
    border-radius: 0 0 var(--radius-sm) var(--radius-sm);
    background: var(--color-surface);
}
.data-table {
    width: 100%;
    border-collapse: separate;
    border-spacing: 0;
    font-size: 0.8125rem;
    line-height: 1.5;
}
.data-table th {
    padding: 0.625rem 0.875rem;
    text-align: left;
    font-weight: 600;
    font-size: 0.75rem;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    color: var(--color-text-secondary);
    background: var(--color-bg);
    border-bottom: 2px solid var(--color-border);
    white-space: nowrap;
    position: sticky;
    top: 0;
    z-index: 1;
    cursor: pointer;
    user-select: none;
}
.data-table th:hover { color: var(--color-primary); }
.data-table th .sort-arrow { font-size: 0.625rem; margin-left: 0.25rem; opacity: 0.4; }
.data-table th.sorted .sort-arrow { opacity: 1; color: var(--color-primary); }

.data-table td {
    padding: 0.5rem 0.875rem;
    border-bottom: 1px solid var(--color-border-light);
    max-width: 300px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    color: var(--color-text);
}
.data-table tbody tr { transition: background var(--transition); }
.data-table tbody tr:hover td { background: var(--color-surface-hover); }
.data-table tbody tr:nth-child(even) td { background: var(--color-table-row-zebra); }
.data-table tbody tr:nth-child(even):hover td { background: var(--color-surface-hover); }

/* Numeric columns right-align */
.data-table td.numeric { text-align: right; font-variant-numeric: tabular-nums; }
.data-table th.numeric { text-align: right; }
.data-table td.result-entity-cell {
    white-space: normal;
    line-height: 1.35;
}
.result-entity-link {
    display: inline-flex;
    flex-direction: column;
    gap: 0.1rem;
    color: var(--color-primary);
    text-decoration: none;
    font-weight: 700;
}
.result-entity-link:hover { text-decoration: underline; }
.result-entity-primary { display: block; }

/* 이름이 없는 행 (L-11 C-12). 값이 있는 행과 구분되도록 흐리게 두되, 대비는
   유지한다 — 이건 "정보 없음" 표시이지 비활성 상태가 아니다. */
.result-entity-primary.is-missing {
    color: var(--color-text-secondary);
    font-weight: 400;
}
.result-entity-secondary {
    display: block;
    font-size: 0.6875rem;
    color: var(--color-text-secondary);
    font-weight: 500;
    line-height: 1.35;
}

/* ── Frozen columns (1st: checkbox, 2nd: first data col) ── */
.data-table th.frozen-col,
.data-table td.frozen-col {
    position: sticky;
    z-index: 2;
    background: var(--color-surface);
    box-sizing: border-box;
}
.data-table th.frozen-col {
    background: var(--color-surface-sunken);
    z-index: 3; /* above sticky header + sticky column intersection */
}
/*
 * frozen-col-end (COMPOUND ID column):
 * JS dynamically sets left to actual checkbox width (eliminates gap).
 * Left box-shadow provides sub-pixel safety margin.
 * Right box-shadow provides a visual separator from the scrolling area.
 */
.data-table td.frozen-col-end {
    border-right: 2px solid var(--color-border);
    box-shadow: -10px 0 0 0 var(--color-surface), 3px 0 6px -2px var(--color-table-frozen-shadow);
}
.data-table th.frozen-col-end {
    border-right: 2px solid var(--color-border);
    box-shadow: -10px 0 0 0 var(--color-surface-sunken), 3px 0 6px -2px var(--color-table-frozen-shadow);
}
.data-table tbody tr:hover td.frozen-col { background: var(--color-primary-light); }
.data-table tbody tr:hover td.frozen-col-end {
    box-shadow: -10px 0 0 0 var(--color-primary-light), 3px 0 6px -2px var(--color-table-frozen-shadow);
}
.data-table tbody tr:nth-child(even) td.frozen-col { background: var(--color-surface-elevated); }
.data-table tbody tr:nth-child(even) td.frozen-col-end {
    box-shadow: -10px 0 0 0 var(--color-surface-elevated), 3px 0 6px -2px var(--color-table-frozen-shadow);
}
.data-table tbody tr:nth-child(even):hover td.frozen-col { background: var(--color-primary-light); }
.data-table tbody tr:nth-child(even):hover td.frozen-col-end {
    box-shadow: -10px 0 0 0 var(--color-primary-light), 3px 0 6px -2px var(--color-table-frozen-shadow);
}

/* ── SQL accordion ── */
.sql-accordion {
    display: none;
    margin-top: 1rem;
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
    overflow: hidden;
}
.sql-accordion-header {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.75rem 1rem;
    background: var(--color-bg);
    border: none;
    width: 100%;
    text-align: left;
    font-size: 0.8125rem;
    font-weight: 600;
    font-family: var(--font-sans);
    color: var(--color-text-secondary);
    cursor: pointer;
    transition: all var(--transition);
}
.sql-accordion-header:hover {
    color: var(--color-text);
    background: var(--color-surface-hover);
}
.sql-accordion-header .chevron {
    font-size: 0.75rem;
    transition: transform 0.2s ease;
    color: var(--color-text-muted);
}
.sql-accordion.open .chevron { transform: rotate(90deg); }
.sql-accordion-header .sql-label { flex: 1; }
.sql-accordion-header .copy-sql {
    font-size: 0.75rem;
    font-weight: 500;
    color: var(--color-primary);
    opacity: 0;
    transition: opacity var(--transition);
}
.sql-accordion-header:hover .copy-sql { opacity: 1; }

.sql-accordion-body {
    display: none;
    border-top: 1px solid var(--color-border);
}
.sql-accordion.open .sql-accordion-body { display: block; }

.sql-code {
    margin: 0;
    padding: 1rem 1.25rem;
    background: var(--color-nav-bg);
    color: var(--color-nav-text);
    font-family: var(--font-mono);
    font-size: 0.8125rem;
    line-height: 1.7;
    overflow-x: auto;
    white-space: pre-wrap;
    word-break: break-word;
}

/* ── Typeahead dropdown ── */
.typeahead-wrapper { position: relative; }
.typeahead-dropdown {
    display: none; position: absolute; left: 0; right: 0; top: 100%;
    background: var(--color-surface); border: 1px solid var(--color-border);
    border-radius: 0 0 var(--radius-sm) var(--radius-sm);
    max-height: 240px; overflow-y: auto; z-index: 50;
    box-shadow: 0 4px 12px rgba(0,0,0,0.1);
}
.typeahead-dropdown.visible { display: block; }
.typeahead-item {
    padding: 0.5rem 0.75rem; cursor: pointer; font-size: 0.875rem;
    border-bottom: 1px solid var(--color-border-light); transition: background 0.15s;
}
.typeahead-item:hover { background: var(--color-bg); }
.typeahead-item .ta-name { font-weight: 600; }
.typeahead-item .ta-meta { font-size: 0.75rem; color: var(--color-text-muted); }

/* ── Post-filter panel ── */
.post-filter-panel {
    display: none; background: var(--color-surface); border: 1px solid var(--color-border);
    border-radius: var(--radius-sm); padding: 1rem; margin-bottom: 1rem;
}
.post-filter-panel.visible { display: block; }
.filter-row { display: flex; flex-wrap: wrap; gap: 1rem; align-items: flex-end; margin-bottom: 0.75rem; }
.filter-group { display: flex; flex-direction: column; gap: 0.25rem; }
.filter-group label { font-size: 0.75rem; font-weight: 600; color: var(--color-text-secondary); }
.filter-range { display: flex; gap: 0.5rem; align-items: center; }
.filter-range input[type="number"] {
    width: 80px; padding: 0.375rem 0.5rem; border: 1px solid var(--color-border);
    border-radius: var(--radius-sm); font-size: 0.8125rem; font-family: var(--font-sans);
}
.filter-checkboxes { display: flex; gap: 0.5rem; flex-wrap: wrap; }
.filter-checkboxes label {
    display: flex; align-items: center; gap: 0.25rem;
    font-size: 0.8125rem; color: var(--color-text); cursor: pointer;
}
.filter-count {
    font-size: 0.8125rem; font-weight: 600; color: var(--color-text-secondary);
}
.filter-zero-msg {
    display: none; padding: 1.5rem; text-align: center;
    color: var(--color-text-secondary); font-size: 0.9375rem;
}
.filter-zero-msg.visible { display: block; }
.grid-cap-msg {
    display: none;
    padding: 0.65rem 1rem;
    border: 1px solid var(--color-border);
    border-bottom: 0;
    border-radius: var(--radius-sm) var(--radius-sm) 0 0;
    background: var(--color-surface-elevated);
    color: var(--color-text-secondary);
    font-size: 0.8125rem;
}
.grid-cap-msg.visible { display: block; }
/* ── Assay Type chips (B/F/A/T/P) ── */
.filter-chips { display: flex; gap: 0.375rem; flex-wrap: wrap; }
.assay-chip {
    width: 2rem; height: 2rem; border-radius: 50%; border: 2px solid var(--color-border);
    background: var(--color-surface); font-size: 0.75rem; font-weight: 700;
    cursor: pointer; display: flex; align-items: center; justify-content: center;
    transition: all 0.15s; color: var(--color-text-secondary); font-family: var(--font-sans);
}
.assay-chip.active { color: var(--color-text-inverse); border-color: transparent; }
.assay-chip[data-type="B"].active { background: var(--color-assay-binding); } /* Binding — blue */
.assay-chip[data-type="F"].active { background: var(--color-assay-functional); } /* Functional — green */
.assay-chip[data-type="A"].active { background: var(--color-assay-admet); } /* ADMET — amber */
.assay-chip[data-type="T"].active { background: var(--color-assay-toxicity); } /* Toxicity — red */
.assay-chip[data-type="P"].active { background: var(--color-assay-physchem); } /* Physicochemical — violet */
.assay-chip:not(.active):hover { border-color: var(--color-primary); color: var(--color-primary); }
.assay-chip.unavailable, .assay-chip.unavailable:hover {
    opacity: 0.35; cursor: not-allowed; pointer-events: none;
}
label.unavailable { opacity: 0.35; cursor: not-allowed; }
label.unavailable input { pointer-events: none; }

/* ── Drug-likeness hint ── */
.filter-hint { font-size: 0.6875rem; color: var(--color-text-muted); font-weight: 400; }

.btn-filter-reset {
    padding: 0.375rem 0.75rem; border: 1px solid var(--color-border);
    border-radius: var(--radius-sm); background: var(--color-surface);
    font-size: 0.8125rem; cursor: pointer; color: var(--color-text-secondary);
    font-family: var(--font-sans);
}
.btn-filter-reset:hover { border-color: var(--color-primary); color: var(--color-primary); }
.btn-filter-toggle {
    padding: 0.375rem 0.75rem; border: 1px solid var(--color-border);
    border-radius: var(--radius-sm); background: var(--color-surface);
    font-size: 0.8125rem; cursor: pointer; color: var(--color-text-secondary);
    font-family: var(--font-sans);
}

/* ── View toggle ── */
.view-toggle { display: flex; gap: 0; border: 1px solid var(--color-border); border-radius: var(--radius-sm); overflow: hidden; }
.view-toggle button {
    padding: 0.375rem 0.625rem; background: var(--color-surface); border: none;
    font-size: 0.75rem; cursor: pointer; color: var(--color-text-secondary);
    font-family: var(--font-sans); transition: all 0.15s;
}
.view-toggle button.active { background: var(--color-primary); color: var(--color-text-inverse); }
.view-toggle button:not(.active):hover { background: var(--color-bg); }

/* #249 1단계 — white text on --color-primary fails WCAG AA in dark (3.67:1). */
:root[data-theme="dark"] .view-toggle button.active { background: var(--color-primary-on-fill); }

/* ── Card grid view ── */
.card-grid-view { display: none; }
.card-grid-view.visible { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: 1rem; padding: 1rem; border: 1px solid var(--color-border); border-radius: 0 0 var(--radius-sm) var(--radius-sm); background: var(--color-surface); }
.result-card {
    border: 1px solid var(--color-border); border-radius: var(--radius-sm);
    padding: 0.75rem; background: var(--color-bg); transition: border-color 0.15s;
}
.result-card:hover { border-color: var(--color-primary); }
.result-card .rc-structure { width: 100%; height: 120px; display: flex; align-items: center; justify-content: center; overflow: hidden; margin-bottom: 0.5rem; }
.result-card .rc-structure img { max-width: 100%; max-height: 120px; }
.result-card .rc-id {
    display: flex;
    flex-direction: column;
    gap: 0.1rem;
    font-weight: 600;
    font-size: 0.8125rem;
}
.result-card .rc-title-link {
    color: var(--color-text);
    text-decoration: none;
    font-weight: 700;
    font-size: 0.875rem;
    line-height: 1.35;
}
.result-card .rc-title-link:hover { color: var(--color-primary); text-decoration: underline; }
.result-card .rc-subtitle {
    font-size: 0.6875rem;
    color: var(--color-text-secondary);
    line-height: 1.35;
}
.result-card .rc-open-detail {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    margin-top: 0.35rem;
    font-size: 0.75rem;
    font-weight: 600;
    color: var(--color-primary);
    text-decoration: none;
}
.result-card .rc-open-detail:hover { text-decoration: underline; }
.result-card .rc-props { font-size: 0.75rem; color: var(--color-text-secondary); line-height: 1.6; }

.search-page-intake .row-actions,
.search-page-intake .rc-actions {
    display: flex;
    gap: 0.35rem;
    flex-wrap: wrap;
    justify-content: flex-start;
    white-space: normal;
    text-align: left;
}

.search-page-intake .row-actions {
    min-width: 16.5rem;
    max-width: 18rem;
    padding-right: 0.6rem;
}

.search-page-intake .inline-action-chip,
.search-page-intake .inline-detail-link {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-height: 1.9rem;
    padding: 0.26rem 0.62rem;
    border: 1px solid var(--color-border);
    border-radius: 999px;
    background: var(--color-surface);
    color: var(--color-text-secondary);
    font-size: 0.72rem;
    font-weight: 600;
    line-height: 1.2;
    text-decoration: none;
    cursor: pointer;
    transition: border-color var(--transition), background var(--transition), color var(--transition);
}

.search-page-intake .inline-action-chip:hover,
.search-page-intake .inline-detail-link:hover {
    border-color: var(--color-primary);
    background: var(--color-primary-light);
    color: var(--color-primary);
}

.search-page-intake .inline-fav-btn,
.search-page-intake .inline-memo-btn,
.search-page-intake .inline-tray-btn {
    margin-left: 0;
    width: auto;
    height: auto;
}

.search-page-intake .inline-fav-btn.active {
    border-color: var(--color-fav-chip-border);
    background: var(--color-fav-chip-bg);
    color: var(--color-fav-chip-text);
    font-size: 0.72rem;
}

.search-page-intake .inline-memo-btn.active {
    border-color: var(--color-memo-chip-border);
    background: var(--color-primary-light);
    color: var(--color-primary);
}

.search-page-intake .inline-tray-btn.active {
    border-color: transparent;
    background: var(--color-cta);
    color: var(--color-text-inverse);
}

/* #249 1단계 — white text on --color-cta fails WCAG AA in dark (2.53:1). */
:root[data-theme="dark"] .search-page-intake .inline-tray-btn.active {
    background: var(--color-cta-on-fill);
}

.search-page-intake .inline-action-chip.grayed {
    opacity: 0.45;
}

.search-page-intake .inline-detail-link {
    color: var(--color-primary);
}

/* ── Project Tray / Action hub ── */
.floating-action-bar {
    display: none;
    position: fixed;
    left: 50%;
    bottom: 1.15rem;
    transform: translateX(-50%);
    width: min(1240px, calc(100vw - 1.5rem));
    background: linear-gradient(180deg, rgba(15, 23, 42, 0.98) 0%, rgba(15, 23, 42, 0.95) 100%);
    color: var(--color-nav-text);
    padding: 0.9rem 1rem 0.85rem;
    border: 1px solid rgba(255, 255, 255, 0.1);
    border-radius: 18px;
    box-shadow: 0 22px 52px rgba(15, 23, 42, 0.28);
    z-index: 100;
    flex-direction: column;
    gap: 0.8rem;
    align-items: stretch;
    white-space: normal;
}
.floating-action-bar.visible { display: flex; }

/* When the fixed project tray is shown, reserve bottom space so it never covers the
   last result rows. (Toggled by renderProjectTray via body.project-tray-visible.) */
body.project-tray-visible .workbench-main {
    padding-bottom: 13rem;
}

/* Above the sidebar breakpoint (900px) the workbench sidebar occupies a fixed column,
   so center the fixed tray over the content area instead of the whole viewport —
   otherwise it sits too far left and overlaps the sidebar. Below 900px the sidebar is
   off-canvas and the viewport-centered base rule is already correct. */
@media (min-width: 901px) {
    .floating-action-bar {
        left: calc(50% + var(--workbench-sidebar-width) / 2);
        width: min(1240px, calc(100vw - var(--workbench-sidebar-width) - 1.5rem));
    }
}

.project-tray-header {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 1rem;
}
.project-tray-header-copy {
    display: flex;
    flex-direction: column;
    gap: 0.2rem;
    min-width: 0;
}
.project-tray-kicker {
    font-size: 0.72rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: rgba(255, 255, 255, 0.7);
}
.project-tray-help {
    font-size: 0.81rem;
    color: rgba(255, 255, 255, 0.72);
    line-height: 1.45;
}
.project-tray-meta {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    flex-shrink: 0;
}
.fab-count {
    font-size: 0.875rem;
    font-weight: 700;
    color: var(--color-text-inverse);
}
.project-tray-clear {
    padding: 0.34rem 0.7rem;
    border: 1px solid rgba(255, 255, 255, 0.18);
    border-radius: 999px;
    background: rgba(255, 255, 255, 0.07);
    color: var(--color-text-inverse);
    font-size: 0.8125rem;
    font-weight: 600;
    cursor: pointer;
    font-family: var(--font-sans);
    transition: all 0.15s;
}
.project-tray-clear:hover { background: rgba(255, 255, 255, 0.14); border-color: rgba(255, 255, 255, 0.28); }
.project-tray-clear:disabled { opacity: 0.35; cursor: not-allowed; }
.project-tray-items {
    display: flex;
    gap: 0.55rem;
    overflow-x: auto;
    padding: 0.05rem 0 0.1rem;
    min-height: 2.7rem;
    scrollbar-width: thin;
}
.project-tray-items::-webkit-scrollbar { height: 8px; }
.project-tray-items::-webkit-scrollbar-thumb {
    background: rgba(255, 255, 255, 0.18);
    border-radius: 999px;
}
.project-tray-empty {
    display: none;
    align-items: center;
    justify-content: center;
    min-height: 2.75rem;
    padding: 0.55rem 0.75rem;
    border: 1px dashed rgba(255, 255, 255, 0.18);
    border-radius: 14px;
    color: rgba(255, 255, 255, 0.7);
    font-size: 0.8125rem;
    line-height: 1.45;
    background: rgba(255, 255, 255, 0.04);
}
.project-tray-actions {
    display: flex;
    align-items: center;
    gap: 0.45rem;
    flex-wrap: wrap;
}
.fab-btn {
    padding: 0.375rem 0.75rem; border: 1px solid rgba(255,255,255,0.2);
    border-radius: 6px; background: none; color: var(--color-nav-text);
    font-size: 0.8125rem; cursor: pointer; font-family: var(--font-sans); transition: all 0.15s;
}
.fab-btn:hover { border-color: rgba(255,255,255,0.5); background: rgba(255,255,255,0.1); }
.fab-btn:disabled { opacity: 0.4; cursor: not-allowed; }
.inline-tray-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.7rem;
    height: 1.7rem;
    margin-left: 0.25rem;
    border: 1px solid var(--color-border);
    border-radius: 999px;
    background: var(--color-bg);
    color: var(--color-text-secondary);
    font-size: 0.95rem;
    font-weight: 700;
    cursor: pointer;
    transition: all 0.15s ease;
}
.inline-tray-btn:hover { border-color: var(--color-primary); color: var(--color-primary); background: var(--color-primary-light); }
.inline-tray-btn.active {
    border-color: transparent;
    background: var(--color-cta);
    color: var(--color-text-inverse);
}

/* #249 1단계 — white text on --color-cta fails WCAG AA in dark (2.53:1). */
:root[data-theme="dark"] .inline-tray-btn.active {
    background: var(--color-cta-on-fill);
}

.project-tray-chip {
    display: inline-flex;
    align-items: flex-start;
    gap: 0.5rem;
    min-width: 0;
    max-width: min(20rem, 100%);
    padding: 0.55rem 0.7rem;
    border: 1px solid rgba(255, 255, 255, 0.14);
    border-radius: 14px;
    background: rgba(255, 255, 255, 0.06);
    color: var(--color-text-inverse);
    flex: 0 0 auto;
}
.project-tray-chip-main {
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 0.14rem;
}
.project-tray-chip-label {
    font-size: 0.875rem;
    font-weight: 700;
    line-height: 1.35;
    color: var(--color-text-inverse);
    text-decoration: none;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 16rem;
}
.project-tray-chip-label:hover { text-decoration: underline; }
.project-tray-chip-meta {
    font-size: 0.72rem;
    color: rgba(255, 255, 255, 0.72);
    line-height: 1.3;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 16rem;
}
.project-tray-chip-type {
    display: inline-flex;
    align-items: center;
    padding: 0.18rem 0.45rem;
    border-radius: 999px;
    background: rgba(255, 255, 255, 0.12);
    font-size: 0.68rem;
    font-weight: 700;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: rgba(255, 255, 255, 0.88);
    flex-shrink: 0;
}
.project-tray-chip-remove {
    appearance: none;
    border: none;
    background: rgba(255, 255, 255, 0.08);
    color: var(--color-text-inverse);
    width: 1.6rem;
    height: 1.6rem;
    border-radius: 999px;
    cursor: pointer;
    font-size: 0.95rem;
    line-height: 1;
    flex-shrink: 0;
    transition: all 0.15s ease;
}
.project-tray-chip-remove:hover { background: rgba(255, 255, 255, 0.18); }
.project-tray.drag-over {
    border-color: rgba(96, 165, 250, 0.7);
    box-shadow: 0 0 0 4px rgba(37, 99, 235, 0.16), 0 22px 52px rgba(15, 23, 42, 0.32);
}

/* ── Quota badge ── */
.quota-badge {
    display: none; align-items: center; justify-content: center;
    padding: 0.125rem 0.625rem; border-radius: 999px;
    font-size: 0.75rem; font-weight: 600; line-height: 1.4;
    background: var(--color-primary); color: var(--color-text-inverse);
    margin-left: 0.5rem; white-space: nowrap;
    transition: background 0.3s;
}
.quota-badge.warning { background: var(--color-warning); }
.quota-badge.danger { background: var(--color-danger); }

/* #249 1단계 — .quota-badge inherits white text (--color-text-inverse); the
   dark warning/danger accent values fail WCAG AA against it (1.67:1/2.77:1). */
:root[data-theme="dark"] .quota-badge.warning { background: var(--color-warning-on-fill); }
:root[data-theme="dark"] .quota-badge.danger { background: var(--color-danger-on-fill); }

/* ── Quota warning toast ── */
.quota-warning-toast {
    display: none; align-items: center; gap: 0.5rem;
    padding: 0.625rem 1rem; margin-top: 0.5rem;
    background: var(--color-warning-soft); border: 1px solid var(--color-warning); border-radius: var(--radius-sm);
    font-size: 0.8125rem; color: var(--color-warning-strong);
    animation: slideDown 0.3s ease-out;
}
.quota-warning-toast.visible { display: flex; }
.qwt-icon { font-size: 1rem; }
.qwt-link { color: var(--color-warning-strong); font-weight: 600; text-decoration: underline; margin-left: auto; }
@keyframes slideDown {
    from { opacity: 0; transform: translateY(-8px); }
    to { opacity: 1; transform: translateY(0); }
}

/* ── Quota nudge (post-exhaustion) ── */
.quota-nudge {
    display: none; padding: 0.75rem 1rem; margin-bottom: 1rem;
    background: var(--color-warning-soft); border: 1px solid var(--color-warning); border-radius: var(--radius-sm);
    font-size: 0.875rem; color: var(--color-warning-strong);
}
.quota-nudge.visible { display: flex; align-items: center; gap: 0.75rem; }
.quota-nudge a { color: var(--color-warning-strong); font-weight: 600; text-decoration: underline; }

/* ── Help trigger ("?") ── */
.help-trigger {
    display: inline-flex; align-items: center; justify-content: center;
    width: 1rem; height: 1rem; margin-left: 0.25rem;
    border: 1px solid var(--color-border); border-radius: 50%;
    background: var(--color-bg); color: var(--color-text-muted);
    font-size: 0.625rem; font-weight: 700; font-family: var(--font-sans);
    cursor: pointer; line-height: 1; padding: 0;
    vertical-align: middle; transition: all var(--transition);
}
.help-trigger:hover,
.help-trigger.active {
    border-color: var(--color-primary); color: var(--color-primary);
    background: var(--color-primary-light);
}

/* ── Help popover ── */
.help-popover {
    display: none; position: absolute; top: calc(100% + 8px); right: 0; z-index: 9999;
    width: 320px; max-width: calc(100vw - 2rem);
    background: var(--color-surface); border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    box-shadow: 0 12px 32px rgba(0,0,0,0.18);
    font-size: 0.8125rem; line-height: 1.5;
}

.help-popover-header {
    display: flex; align-items: center; justify-content: space-between;
    padding: 0.625rem 0.75rem;
    border-bottom: 1px solid var(--color-border);
    font-weight: 600; font-size: 0.8125rem;
    color: var(--color-text);
}
.help-popover-close {
    background: none; border: none; font-size: 1.125rem;
    color: var(--color-text-muted); cursor: pointer; padding: 0; line-height: 1;
}
.help-popover-close:hover { color: var(--color-text); }

.help-popover-body {
    padding: 0.75rem; margin: 0;
}
.help-popover-body dt {
    font-weight: 600; color: var(--color-text);
    margin-top: 0.5rem; font-size: 0.8125rem;
}
.help-popover-body dt:first-child { margin-top: 0; }
.help-popover-body dd {
    margin: 0.125rem 0 0 0;
    color: var(--color-text-secondary); font-size: 0.75rem; line-height: 1.5;
}

.help-popover-tip {
    padding: 0.5rem 0.75rem;
    border-top: 1px solid var(--color-border);
    background: var(--color-primary-light);
    border-radius: 0 0 var(--radius-md) var(--radius-md);
    font-size: 0.75rem; color: var(--color-primary);
    font-weight: 500;
}

/* ── Responsive ── */
@media (max-width: 640px) {
    .search-page { padding: 1.25rem 1rem 2rem; }
    .search-card { padding: 1rem; }
    .search-intake-handoff { flex-direction: column; }
    .search-intake-links { width: 100%; }
    .search-intake-link { flex: 1 1 9rem; }
    .search-intake-bar { flex-direction: column; }
    .search-intake-bar-meta { align-items: stretch; min-width: 0; }
    .search-intake-bar-actions { justify-content: flex-start; }
    .search-source-guidance { padding: 1rem; }
    .search-source-guidance-head { flex-direction: column; }
    .search-source-guidance-context { width: 100%; }
    .input-row { flex-direction: column; }
    .input-sidebar { min-width: 0; flex-direction: row; gap: 0.75rem; }
    .input-sidebar > div { flex: 1; }
    .btn-search { width: 100%; }
    .shortcut-hint { display: none; }
    .results-toolbar { flex-direction: column; gap: 0.5rem; align-items: flex-start; }
    .data-table th, .data-table td { padding: 0.375rem 0.5rem; font-size: 0.75rem; }
    .filter-row { flex-direction: column; }
    .floating-action-bar {
        left: 0.75rem;
        right: 0.75rem;
        width: auto;
        transform: none;
        gap: 0.65rem;
        padding: 0.85rem 0.8rem 0.8rem;
    }
    .project-tray-header { flex-direction: column; align-items: stretch; }
    .project-tray-meta { justify-content: space-between; width: 100%; }
    .project-tray-items { padding-bottom: 0.2rem; }
    .project-tray-chip { max-width: 100%; }
    .project-tray-chip-label, .project-tray-chip-meta { max-width: 12rem; }
    .search-page-intake .row-actions { min-width: 12rem; }
    .card-grid-view { grid-template-columns: 1fr; }
}

/* ── Disambiguation panel ── */
.disambiguation-panel {
    display: none; flex-wrap: wrap; gap: 0.5rem;
    padding: 0 0 1rem; margin-top: -0.5rem;
}
.disambiguation-panel.visible { display: flex; }
.disambiguation-btn {
    display: flex; flex-direction: column; gap: 0.125rem;
    padding: 0.625rem 1rem; background: var(--color-surface);
    border: 1px solid var(--color-border); border-radius: var(--radius-md);
    cursor: pointer; text-align: left; font-family: var(--font-sans);
    transition: border-color var(--transition), box-shadow var(--transition);
}
.disambiguation-btn:hover { border-color: var(--color-primary); box-shadow: 0 2px 8px rgba(0,0,0,0.08); }
.disambiguation-btn strong { font-size: 0.9375rem; color: var(--color-text); }
.disam-meta { font-size: 0.75rem; color: var(--color-text-muted); }

/* ── Feedback bar ── */
.feedback-bar {
    display: none; align-items: center; gap: 0.75rem;
    padding: 0.625rem 1rem; margin-top: 1rem;
    background: var(--color-bg); border: 1px solid var(--color-border);
    border-radius: var(--radius-sm); font-size: 0.875rem;
}
.fb-label { color: var(--color-text-secondary); }
.fb-btn {
    background: none; border: 1px solid var(--color-border); border-radius: var(--radius-sm);
    padding: 0.25rem 0.625rem; font-size: 1.125rem; cursor: pointer;
    transition: all 0.15s;
}
.fb-btn:hover:not(:disabled) { border-color: var(--color-primary); transform: scale(1.1); }
.fb-btn:disabled { opacity: 0.4; cursor: default; }
.fb-thanks { display: none; font-size: 0.8125rem; color: var(--color-success); font-weight: 500; }

/* ── Grayed buttons (non-auth) ── */
.grayed { opacity: 0.35; cursor: pointer; transition: opacity 0.15s; }
.grayed:hover { opacity: 0.55; }

/* ── JS-controlled initially-hidden elements ── */
#fg-retry { display: none; }
.phase2-cta { display: none; }

/* ── Login benefits modal ── */
.login-modal-backdrop {
    display: none; position: fixed; inset: 0; z-index: 210;
    background: rgba(0, 0, 0, 0.5); backdrop-filter: blur(3px);
    align-items: center; justify-content: center; padding: 1rem;
}
.login-modal {
    background: var(--color-surface); border-radius: var(--radius-md);
    box-shadow: var(--shadow-lg); max-width: 420px; width: 100%; padding: 1.75rem;
}
.login-modal h3 {
    font-size: 1.25rem; font-weight: 700; margin: 0 0 1rem; color: var(--color-text);
}
.login-benefits-list {
    list-style: none; padding: 0; margin: 0 0 1.25rem;
}
.login-benefits-list li {
    padding: 0.375rem 0; font-size: 0.875rem; color: var(--color-text);
    border-bottom: 1px solid var(--color-border);
}
.login-benefits-list li:last-child { border-bottom: none; }
.login-modal-actions {
    display: flex; align-items: center; gap: 1rem;
}
.login-modal-cta {
    display: inline-block; padding: 0.625rem 1.25rem; font-size: 0.9375rem;
    font-weight: 600; text-decoration: none; border-radius: var(--radius-sm);
    color: var(--color-text-inverse);
}
.login-modal-dismiss {
    background: none; border: none; color: var(--color-text-muted);
    cursor: pointer; font-size: 0.875rem; font-family: var(--font-sans);
}
.login-modal-dismiss:hover { color: var(--color-text); }

/* ── Analyze dropdown (per-row) ── */
.analyze-dropdown { position: relative; display: inline-block; }
.inline-analyze-btn {
    background: none; border: none; cursor: pointer;
    font-size: 1rem; padding: 0.125rem 0.25rem; color: var(--color-text-muted);
    transition: color 0.15s;
}
.inline-analyze-btn:hover { color: var(--color-primary); }
.analyze-menu {
    display: none; position: absolute; right: 0; top: 100%; z-index: 50;
    background: var(--color-surface); border: 1px solid var(--color-border);
    border-radius: var(--radius-sm); box-shadow: var(--shadow-md);
    min-width: 140px; padding: 0.25rem 0;
}
.analyze-menu.visible { display: block; }
.analyze-menu-item {
    display: block; padding: 0.5rem 0.875rem; font-size: 0.8125rem;
    color: var(--color-text); text-decoration: none; white-space: nowrap;
    transition: background 0.1s;
}
.analyze-menu-item:hover { background: var(--color-bg); color: var(--color-primary); }

/* ── Onboarding overlay ── */
.onboarding-overlay {
    display: none; position: fixed; inset: 0; z-index: 200;
    background: rgba(0, 0, 0, 0.5); backdrop-filter: blur(4px);
    align-items: center; justify-content: center;
    padding: 1rem;
}
.onboarding-content {
    background: var(--color-surface); border-radius: var(--radius-md);
    box-shadow: var(--shadow-lg); max-width: 640px; width: 100%;
    max-height: 85vh; overflow-y: auto; padding: 2rem;
}
.onboarding-title {
    font-size: 1.5rem; font-weight: 700; color: var(--color-text);
    margin: 0 0 0.25rem;
}
.onboarding-subtitle {
    font-size: 0.9375rem; color: var(--color-text-muted);
    margin: 0 0 1.5rem; line-height: 1.5;
}
.onboarding-category { margin-bottom: 1.25rem; }
.onboarding-category h3 {
    font-size: 0.8125rem; font-weight: 600; color: var(--color-text-muted);
    margin: 0 0 0.5rem; text-transform: uppercase; letter-spacing: 0.03em;
}
.onboarding-chips { display: flex; flex-wrap: wrap; gap: 0.375rem; }
.onboarding-actions {
    display: flex; align-items: center; gap: 1rem;
    margin-top: 1.5rem; padding-top: 1rem;
    border-top: 1px solid var(--color-border);
}
.onboarding-start {
    padding: 0.625rem 1.5rem; font-size: 0.9375rem; font-weight: 600;
    border-radius: var(--radius-sm); border: none; cursor: pointer;
}
.onboarding-skip {
    background: none; border: none; color: var(--color-text-muted);
    cursor: pointer; font-size: 0.875rem; font-family: var(--font-sans);
}
.onboarding-skip:hover { color: var(--color-text); }

@media (max-width: 640px) {
    .onboarding-content { padding: 1.25rem; max-height: 90vh; }
    .onboarding-chips { flex-direction: column; }
}

/* ── Failure guidance ── */
.failure-guidance {
    display: none; padding: 1rem 1.25rem; margin-bottom: 1rem;
    background: var(--color-info-soft); border: 1px solid var(--color-primary-light); border-radius: var(--radius-sm);
    font-size: 0.875rem; color: var(--color-info-strong);
}
.failure-guidance.visible { display: block; }
.failure-guidance h4 {
    font-size: 0.875rem; font-weight: 600; margin: 0 0 0.5rem; color: var(--color-info-strong);
}
.suggestion-chips { display: flex; flex-wrap: wrap; gap: 0.375rem; margin-bottom: 0.75rem; }
.suggestion-chip {
    font-size: 0.8125rem; padding: 0.375rem 0.75rem;
    border: 1px solid var(--color-primary-light); border-radius: 999px;
    background: var(--color-surface); color: var(--color-primary-dark);
    cursor: pointer; transition: all 0.15s; font-family: var(--font-sans);
}
.suggestion-chip:hover { background: var(--color-primary-light); border-color: var(--color-primary); }
.search-tips { margin: 0; padding: 0 0 0 1.25rem; color: var(--color-text-secondary); }
.search-tips li { margin-bottom: 0.25rem; font-size: 0.8125rem; }
/* .failure-retry → .btn-outline (components.css §19) */

/* ── Search Filter Positioning ── */
.search-filter-relative {
    position: relative;
}

/* ── Onboarding Learn More Link ── */
.onboarding-learn-more {
    font-size: 0.8125rem;
    color: var(--color-text-muted);
    text-decoration: none;
}

/* ── Save rationale popover ── */
.save-rationale-popover {
    position: absolute;
    right: 0;
    top: 100%;
    z-index: 100;
    background: var(--color-bg);
    border: 1px solid var(--color-border);
    border-radius: 0.5rem;
    padding: 0.75rem;
    box-shadow: 0 4px 12px rgba(0,0,0,0.1);
    min-width: 300px;
    max-width: min(360px, calc(100vw - 2rem));
}
.save-rationale-title {
    font-size: 0.875rem;
    font-weight: 700;
    color: var(--color-text);
    margin-bottom: 0.5rem;
}
.save-rationale-chip-row {
    display: flex;
    flex-wrap: wrap;
    gap: 0.375rem;
    margin-bottom: 0.5rem;
}
.save-rationale-chip {
    border: 1px solid var(--color-border);
    background: var(--color-bg);
    color: var(--color-text);
    border-radius: 999px;
    padding: 0.35rem 0.65rem;
    font-size: 0.75rem;
    cursor: pointer;
    transition: border-color 0.15s, color 0.15s, background 0.15s;
}
.save-rationale-chip:hover {
    border-color: var(--color-primary);
    color: var(--color-primary);
    background: rgba(37, 99, 235, 0.06);
}
.save-rationale-note {
    width: 100%;
    resize: vertical;
    border: 1px solid var(--color-border);
    border-radius: 0.375rem;
    padding: 0.5rem;
    font-size: 0.8125rem;
    font-family: inherit;
    min-height: 3rem;
}
.save-rationale-note:focus {
    outline: none;
    border-color: var(--color-primary);
}
.save-rationale-status {
    min-height: 1rem;
    margin-top: 0.35rem;
    font-size: 0.75rem;
    color: var(--color-text-muted);
}
.save-rationale-status.error {
    color: #b91c1c;
}
.save-rationale-actions {
    display: flex;
    justify-content: flex-end;
    margin-top: 0.5rem;
}
.save-rationale-skip-btn {
    background: none;
    border: 1px solid var(--color-border);
    border-radius: 0.375rem;
    padding: 0.375rem 0.75rem;
    font-size: 0.8125rem;
    cursor: pointer;
    color: var(--color-text-muted);
}

/* 긴 서술 컬럼 한 줄 자르기 (L-11 D-05).
   행을 구분하는 값(assay_description)이 화면 안에 들어와야 "왜 다른 행인지" 가
   보인다. 전문은 title 툴팁으로 준다 — 표를 세로로 늘리지 않는다. */
.data-table td.result-cell-clamp {
    max-width: 320px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* ── 프로젝트 트레이 접기 (L-11 D-09) ──────────────────────────────────────
   fixed 트레이가 236px 로 뷰포트의 17~30% 를 상시 점유했다. 0건일 때도 그랬다 —
   아무것도 담지 않았는데 결과를 그만큼 좁은 창으로 보게 된다.

   ★ **닫기가 아니라 접기다.** 헤더와 담긴 개수는 접힌 상태에서도 보인다. 완전히
     없애면 담아둔 항목에 다시 갈 경로가 사라진다. */
.project-tray.collapsed .project-tray-items,
.project-tray.collapsed .project-tray-empty,
.project-tray.collapsed .project-tray-actions,
.project-tray.collapsed .project-tray-help {
    display: none;
}

.project-tray.collapsed .project-tray-header {
    margin-bottom: 0;
}

/* 접혔으면 아래 여백도 같이 줄인다 — 안 줄이면 없는 트레이만큼 빈 공간이 남는다. */
body.project-tray-visible.project-tray-collapsed .workbench-main {
    padding-bottom: 4.5rem;
}
