/* Neuji.Web page-specific styles (marketing funnel, account, search shell).
   Layered over the shared design system in _content/Neuji.Web.Shared/app.css. */

/* Primary nav. flex-wrap + min-width:0 are the universal safety net (the row can wrap rather than
   overflow); the marketing header additionally collapses to a disclosure menu — see below. */
.header-nav { display: flex; align-items: center; flex-wrap: wrap; gap: 0.5rem; min-width: 0; justify-content: flex-end; }

/* Marketing header: a native <details> disclosure (accessible, no JS, CSP-safe). Inline by default;
   collapses to a hamburger menu when the viewport is narrow OR the text is scaled up. The breakpoint is
   in EM so it responds to the user's font size: Firefox-for-Android applies the Android OS font scale as a
   global text-zoom that enlarges the em/rem basis, so an em media query fires at a wider viewport when the
   font is large — switching to the compact menu exactly when the inline bar would otherwise overflow
   (WCAG 1.4.10 Reflow). (Harmless on Chrome, which doesn't scale web text for the OS setting.) */
.nav-disclosure { position: relative; }
.nav-toggle {
    display: none;  /* desktop: hidden (nav is inline) */
    align-items: center; justify-content: center; width: 2.75rem; height: 2.75rem;
    border-radius: var(--radius); background: var(--surface-2); border: 1px solid var(--border);
    color: var(--text); cursor: pointer; list-style: none;
}
.nav-toggle::-webkit-details-marker { display: none; }
.nav-toggle::marker { content: ""; }
.nav-toggle:hover { background: var(--surface); }
.nav-disclosure > summary:focus-visible { outline: 2px solid var(--ring); outline-offset: 2px; }
/* Hamburger icon: three bars that morph to an X when open. */
.nav-toggle-bars, .nav-toggle-bars::before, .nav-toggle-bars::after {
    content: ""; display: block; width: 1.15rem; height: 2px; background: currentColor; border-radius: 2px;
    transition: transform 0.2s ease, opacity 0.2s ease;
}
.nav-toggle-bars { position: relative; }
.nav-toggle-bars::before { position: absolute; top: -0.4rem; inset-inline-start: 0; }
.nav-toggle-bars::after { position: absolute; top: 0.4rem; inset-inline-start: 0; }
.nav-disclosure[open] .nav-toggle-bars { background: transparent; }
.nav-disclosure[open] .nav-toggle-bars::before { transform: translateY(0.4rem) rotate(45deg); }
.nav-disclosure[open] .nav-toggle-bars::after { transform: translateY(-0.4rem) rotate(-45deg); }

/* Chromium 131+ hides a closed <details>' content through the ::details-content pseudo (content-visibility),
   which author `display` on the CHILDREN no longer overrides — so the inline-on-desktop state of this disclosure
   silently collapsed there (the nav vanished from the desktop header). Force the slot visible as the default
   (author rules beat UA rules), and re-assert the UA hiding ONLY in the narrow/hamburger state below. Engines
   without ::details-content ignore both rules and keep working via the child display overrides. */
.nav-disclosure::details-content { content-visibility: visible; }

@media (max-width: 34em) {
    .nav-toggle { display: inline-flex; }
    .nav-disclosure:not([open])::details-content { content-visibility: hidden; }
    .nav-disclosure > .header-nav {
        position: absolute; top: calc(100% + 0.5rem); inset-inline-end: 0;
        flex-direction: column; align-items: stretch; gap: 0.35rem;
        min-width: 12rem; max-width: min(16rem, 80vw); padding: 0.5rem;
        background: var(--bg-elevated); border: 1px solid var(--border);
        border-radius: var(--radius-lg); box-shadow: var(--shadow-lg); z-index: var(--z-dropdown);
    }
    .nav-disclosure:not([open]) > .header-nav { display: none; }
    .nav-disclosure > .header-nav .btn { width: 100%; justify-content: flex-start; }
}
@media (prefers-reduced-motion: reduce) {
    .nav-toggle-bars, .nav-toggle-bars::before, .nav-toggle-bars::after { transition: none; }
}

/* Breathing room between page content and the footer (footer-scoped so it never affects the
   footer-less search app; on short pages the flex layout makes the extra space invisible). */
.app-footer { margin-top: clamp(2.5rem, 5vw, 4rem); }

.footer-grid { display: flex; flex-wrap: wrap; gap: 2rem; justify-content: space-between; align-items: start; }
/* Reflow safety at large OS text (WCAG 1.4.4 Resize Text / 1.4.10 Reflow): the footer columns are flex
   children whose default min-width:auto floors them at their content's min-content — and the support-email
   token (e.g. support@neuji.co.uk) is unbreakable, so at ~200% text on a narrow viewport it forced a
   sub-pixel horizontal overflow. min-width:0 lets each column shrink, and overflow-wrap:anywhere lets the
   email break across lines instead of pushing past the viewport. */
.footer-grid > * { min-width: 0; }
.app-footer address, .app-footer address a { overflow-wrap: anywhere; }

/* ------------------------------- Hero ----------------------------------- */
.hero {
    text-align: center;
    position: relative;
    overflow: hidden;
    /* generous bottom padding = the silk current's own stage below the copy */
    padding: clamp(3rem, 8vw, 6rem) 1.25rem clamp(11rem, 24vw, 15rem);
    /* Ultrawide floor: past ~3.3:1 the hero becomes a sliver whose bottom-left corner sits ABOVE the drawn
       current (viewBox y < ~430), where no crop of the static art can reach it. 30vw is a no-op at common
       widths (the content is taller through ~2560px wide) and only stretches the stage on ultrawide, keeping
       the corner inside the locus the ribbons are generated to hug (branding/tools/silk_current.py). min()
       against svh so the floor never exceeds the initially-visible viewport (100svh minus the 4rem header);
       the vh line is the fallback for engines without svh. */
    min-height: min(30vw, calc(100vh - 4rem));
    min-height: min(30vw, calc(100svh - 4rem));
    background:
        radial-gradient(60% 60% at 50% 0%, color-mix(in srgb, var(--brand) 12%, transparent), transparent 70%);
}
/* Short viewports (landscape phones, half-height windows): the fold cuts deep into the hero, which slides
   the display's bottom-left corner into the CROP'S INTERIOR (the xMaxYMin slice is computed from the box,
   not the visible part) — beyond what any edge-hugging geometry can reach. Shrinking the stage below the
   copy pulls the hero height toward the viewport, which walks the corner back onto the covered locus.
   em-based so OS text zoom shifts the breakpoint with the content. */
@media (max-height: 33em) {
    .hero { padding-block: 1.5rem clamp(3rem, 8vw, 5rem); }
}
/* Narrow (portrait-phone) viewports: a slightly shorter stage keeps the fold near the drawn field's bottom
   edge, where the hugger ribbons guarantee corner ink — and trims dead scroll below the copy. */
@media (max-width: 30em) {
    .hero { padding-bottom: clamp(7rem, 18vw, 9rem); }
}
.hero > :not(.hero-bands) { position: relative; z-index: 1; }
/* The copy pool: a soft elliptical well of background color painted behind and around the copy block. It sizes
   itself to the copy (any engine, locale, or text-zoom — no measurement), so the waves flow UNBROKEN behind it
   while the words float on quiet dark. */
/* The copy stack rides a quiet glass panel (owner: dark, mildly translucent, small padding) — the ribbons
   stay continuous behind it, dimmed just enough to read over. */
.hero-copy { position: relative; background: color-mix(in srgb, var(--bg) 58%, transparent);
    -webkit-backdrop-filter: blur(5px); backdrop-filter: blur(5px);
    border: 1px solid color-mix(in srgb, var(--border) 55%, transparent);
    border-radius: var(--radius-lg, 16px); padding: clamp(1.25rem, 3vw, 2rem);
    max-width: 54rem; margin-inline: auto; }
/* The silk current: one static SVG of 16 gradient-stroked ribbons behind the hero (geometry + corner
   invariants live in Home.razor / branding/tools/silk_current.py). One spectrum gradient strokes every
   ribbon; hue-rotating the group makes the color travel through the current — a single composited filter,
   zero JS. */
.hero-bands { position: absolute; inset: 0; z-index: 0; pointer-events: none; }
.hero-bands svg { width: 100%; height: 100%; display: block;
    /* Soft entrance, owner-tuned (2026-07-18): the old 0.6s-hold + 0.35s fade read as absence-then-POP
       ("appears abruptly after the main content"). Now the field starts blooming almost immediately and
       breathes in over ~1.6s — long enough to feel like the page settling, never a pop. Opacity-only
       (compositor-friendly; reduced-motion reveals instantly via the media block below). */
    animation: hero-svg-reveal 1.6s cubic-bezier(0.22, 0.61, 0.36, 1) 0.15s backwards; }
/* Fit the portrait composition to the INITIALLY-VISIBLE area (100svh minus the header), not the full hero:
   large text stretches the hero to 2-3x the viewport, and a slice crop computed from that whole box goes so
   narrow that the entries and pinch fall off the LEFT edge — the opening view kept only the right-side climb.
   Capped to the first screen, the box aspect stays near the drawing's and the whole bend is in view at every
   text size. The drawing's lowest strands run parallel to its bottom edge, so the field simply ENDS there
   (no chopped strokes) and the stage below stays quiet. The vh line is the fallback for engines without svh. */
.hero-bands .flow-portrait { height: min(100%, calc(100vh - 4rem)); }
.hero-bands .flow-portrait { height: min(100%, calc(100svh - 4rem)); }
@keyframes hero-svg-reveal { from { opacity: 0; } to { opacity: 1; } }
/* Two fields, one current: the landscape field serves boxes wider than ~0.93:1, where its S/waist stays
   inside the top-right-anchored crop. A PORTRAIT box would crop that field to a bendless close-up of the
   straight climb, so narrow-and-tall viewports swap in the portrait-native field (720x1280) whose full
   quarter-bend composition lives inside every phone crop (geometry + corner proofs: silk_current.py).
   em width so OS text zoom moves the toggle with the content; the orientation guard (zoom-independent, unlike
   an em min-height, which 200% text would push past every phone) keeps short-wide windows (landscape phones)
   on the landscape field, whose own invariants cover them. */
.hero-bands .flow-portrait { display: none; }
@media (max-width: 44em) and (orientation: portrait) {
    .hero-bands .flow-land { display: none; }
    .hero-bands .flow-portrait { display: block; }
}
/* the silk current's life: the 40s hue crawl on the group + the FAN BREATH on each ribbon — every path
   rotates around its field's waist by its own --fan factor (outer ribbons swing most), so the whole current
   fans out and gathers back, subtly, forever. Zero-start keyframes (no first-frame jump). */
.hero-flow { animation: hero-pulse-hue 40s linear infinite; will-change: filter; }
.hero-flow path { transform-box: view-box; transform-origin: 657px 672px;
    animation: hero-fan 15s ease-in-out infinite alternate; }
/* the portrait field breathes around ITS waist — keep in sync with data-waist / silk_current.py PORT_WAIST
   (same specificity as the rule above; source order makes this override win for the portrait field) */
.flow-portrait path { transform-origin: 400px 700px; }
@keyframes hero-pulse-hue { from { filter: hue-rotate(0deg); } to { filter: hue-rotate(360deg); } }
@keyframes hero-fan { from { transform: rotate(0deg); } to { transform: rotate(calc(var(--fan, 0) * 2.6deg)); } }
@media (prefers-reduced-motion: reduce) { .hero-flow, .hero-flow path { animation: none; } .hero-bands svg { animation: none; } }
@media (forced-colors: active) { .hero-bands { display: none; } }
.hero-eyebrow {
    display: inline-flex; align-items: center; gap: 0.4rem;
    font-size: 0.8125rem; font-weight: 600; color: var(--brand-strong);
    background: var(--brand-soft); padding: 0.35rem 0.8rem; border-radius: var(--radius-pill);
    margin-bottom: 1.25rem;
}
.hero h1 {
    font-size: clamp(2.25rem, 6vw, 3.75rem); line-height: 1.05; letter-spacing: -0.03em;
    /* max-width in ch keeps a comfortable measure, but ch is the width of the "0" glyph — which differs
       between fonts, so `system-ui` resolving to different fonts (notably Firefox vs Chromium on Linux)
       makes the column compute to different widths and the heading wrap at different points. text-wrap
       balance evens the line lengths so it reads intentionally in either case. */
    max-width: 18ch; margin: 0 auto 1rem; text-wrap: balance;
}
.hero .lede {
    font-size: clamp(1.05rem, 2.5vw, 1.3rem); color: var(--text-muted);
    max-width: 56ch; margin: 0 auto 2rem; text-wrap: pretty; }
.hero-cta { display: flex; gap: 0.75rem; justify-content: center; flex-wrap: wrap; }
/* Let the CTA labels WRAP instead of overflowing: .btn is white-space:nowrap by default, so a long label
   ("Start searching privately") forces horizontal scroll at large text. Scoped to the hero so other buttons keep
   their single-line treatment. max-width:100% lets the button shrink to the viewport at ~200% text / ~360px. */
.hero-cta .btn { white-space: normal; max-width: 100%; line-height: 1.25; }
.hero-trust { margin-top: 1.5rem; font-size: 0.875rem; font-weight: 500; color: var(--text); }
.hero-nerd { margin-top: 0.45rem; font-size: 0.8125rem; color: var(--text-muted); letter-spacing: 0.01em; }

/* ------------------------- Feature row / value -------------------------- */
.value-grid {
    display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
    gap: 1.25rem; padding: 2rem 0;
}
/* exactly-three variant (Why Neuji): capped width + centered, so three cards sit as a balanced center row */
.value-grid--three { max-width: 56rem; margin-inline: auto; }
.value-card { padding: 1.5rem; }
.value-card h3 { font-size: 1.0625rem; margin-bottom: 0.4rem; }
.value-card p { color: var(--text-muted); font-size: 0.9375rem; }
/* Facet glyphs (LandingIcons) on a soft paper chip — the hand-made register, no renders, no emoji. */
.value-icon {
    width: 64px; height: 64px; border-radius: var(--radius);
    display: grid; place-items: center; margin-bottom: 0.9rem;
    background: color-mix(in srgb, var(--brand-soft) 55%, transparent);
}
.value-icon .fi { width: 34px; height: 34px; display: block; }
.sc-point-ico .fi { width: 1.35rem; height: 1.35rem; display: block; margin-inline: auto; }

.appearance-row { display: flex; align-items: center; justify-content: space-between; gap: 1rem; padding: 0.75rem 0; flex-wrap: wrap; }
.appearance-row + .appearance-row { border-top: 1px solid var(--border); }
.appearance-row .label { font-weight: 600; }
.appearance-row .desc { font-size: 0.8125rem; color: var(--text-muted); }

.section { padding: clamp(2rem, 5vw, 4rem) 0; }
.section-title { text-align: center; font-size: clamp(1.5rem, 4vw, 2rem); margin-bottom: 0.5rem; }
.section-sub { text-align: center; color: var(--text-muted); max-width: 52ch; margin: 0 auto 2rem; }

/* --- Landing editorial bands: copy beside a FLUX paper-craft still-life -------------------------
   Two columns on wide viewports, stacked on narrow (and under large-OS-font: an em breakpoint, so
   Firefox text-zoom collapses it exactly when it would otherwise crowd). Left-aligned copy inside a
   band (the centered .section-title/.section-sub defaults are overridden here on purpose). */
.editorial { display: grid; grid-template-columns: 1fr 1fr; gap: clamp(1.5rem, 4vw, 3.5rem);
    align-items: center; max-width: 68rem; margin-inline: auto; }
.editorial-copy { min-width: 0; }
.editorial-copy .section-title, .editorial-copy .section-sub { text-align: start; margin-inline: 0; max-width: none; }
.editorial-copy .section-sub { margin-block: 0 1.5rem; }
.section-eyebrow { display: block; text-transform: uppercase; letter-spacing: 0.12em; font-size: 0.75rem;
    font-weight: 700; color: var(--brand); margin-bottom: 0.6rem; }
.editorial-media { min-width: 0; margin: 0; }
/* Paper World scenes v2: frameless — the drawing sits directly on the page (no panel, no radius,
   no shadow box). Paper tones ride theme tokens so the same geometry holds contrast on both
   grounds: warm sand against the light page, cream against the dark. The toggle attribute wins
   over the OS hint in both directions. */
.editorial-media .scene-ill, .audience-lead .scene-ill { display: block; width: 100%; height: auto; }
.scene-ill { --pw-a: #EBD9B8; --pw-b: #DCC49B; --pw-c: #B99A66; --pw-shadow: rgba(74, 52, 22, 0.14); }
@media (prefers-color-scheme: dark) {
    :root:not([data-theme="light"]) .scene-ill { --pw-a: #FFF6EC; --pw-b: #EFE0C8; --pw-c: #C9AC78; --pw-shadow: rgba(0, 0, 0, 0.38); }
}
:root[data-theme="dark"] .scene-ill { --pw-a: #FFF6EC; --pw-b: #EFE0C8; --pw-c: #C9AC78; --pw-shadow: rgba(0, 0, 0, 0.38); }
.editorial-media img { display: block; width: 100%; height: auto; border-radius: var(--radius-lg);
    box-shadow: var(--shadow-lg); }
.editorial--reverse .editorial-media { order: -1; }   /* image leads on wide; still stacks copy-first on narrow */

@media (max-width: 52em) {
    .editorial { grid-template-columns: 1fr; }
    .editorial--reverse .editorial-media { order: 0; }   /* on stack, copy reads first everywhere */
}

/* Full-width lead image (audience section): a quiet band above the card grid. */
.audience-lead { margin: 0 auto 2.25rem; max-width: 68rem; }
.audience-lead img { display: block; width: 100%; height: auto; border-radius: var(--radius-lg); box-shadow: var(--shadow-lg); }

/* Closing brand moment: the detailed crane at hero scale + a quiet caption. */
.brand-moment { text-align: center; }
.brand-moment-crane { width: clamp(6rem, 16vw, 9.5rem); height: auto; color: var(--text);
    filter: drop-shadow(0 8px 24px color-mix(in srgb, var(--brand) 22%, transparent)); }
/* The tagline ("Folded to fly."), not a caption: upright, weighted, near-heading scale — it names
   the mark above it. Set in the standard stack (the Inter Brand subset carries only the five
   wordmark glyphs, so using it here would fall back mid-line). */
.brand-moment-caption { color: var(--text); font-weight: 600; font-size: clamp(1.2rem, 1.05rem + 0.8vw, 1.5rem); letter-spacing: -0.01em; margin: 0.6rem 0 1.9rem; }

.danger-zone { border-color: color-mix(in srgb, var(--danger) 45%, var(--border)); }

/* ------------------------------ API keys -------------------------------- */
.keys-table { width: 100%; border-collapse: collapse; font-size: 0.9rem; }
.keys-table th, .keys-table td { text-align: start; padding: 0.65rem 0.6rem; border-bottom: 1px solid var(--border); }
.keys-table th { font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.04em; color: var(--text-muted); }
.keys-table code { font-family: var(--font-mono); font-size: 0.85em; }
.key-reveal { display: block; margin-top: 0.5rem; padding: 0.6rem 0.75rem; background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); font-family: var(--font-mono); word-break: break-all; user-select: all; }
.danger { color: var(--danger); }

/* ------------------------------ Legal ----------------------------------- */
.legal h2 { font-size: 1.2rem; margin: 1.75rem 0 0.5rem; }
.legal p, .legal li { color: var(--text); }
.legal ul { margin: 0.5rem 0 0.5rem 1.25rem; display: flex; flex-direction: column; gap: 0.35rem; }
/* "English governs" notice on legal pages: shown for non-English UI, hidden for English. Follows the
   <html lang> the i18n switcher sets, so it toggles on the no-postback language change (no JS needed). */
.legal-lang-notice {
    margin: 0 0 1.5rem;
    padding: 0.7rem 0.9rem;
    border-inline-start: 3px solid #4f46e5;
    background: rgba(79, 70, 229, 0.06);
    border-radius: 0.4rem;
    font-size: 0.9rem;
    line-height: 1.5;
    color: var(--text);
}
html[lang="en"] .legal-lang-notice { display: none; }

/* ------------------------------- FAQ ------------------------------------ */
/* Breathing room under the "Questions, answered" title (owner: the first card sat too close). */
.faq { max-width: 720px; margin: 1.75rem auto 0; display: flex; flex-direction: column; gap: 0.75rem; }
.faq details { border: 1px solid var(--border); border-radius: var(--radius); background: var(--surface); padding: 0 1.1rem; }
.faq summary { cursor: pointer; font-weight: 600; padding: 1rem 0; list-style: none; display: flex; justify-content: space-between; align-items: center; }
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after { content: "+"; color: var(--text-muted); font-size: 1.25rem; }
.faq details[open] summary::after { content: "−"; }
.faq details p { padding-bottom: 1rem; color: var(--text-muted); }

/* ------------------------------ App shell ------------------------------- */
.app-bar { display: flex; align-items: center; justify-content: space-between; gap: 0.75rem 1rem;
    flex-wrap: wrap; padding: 0.85rem 1.25rem; border-bottom: 1px solid var(--border); }
/* The outlet cell: empty (and collapsed) on non-results pages; on results it carries the compact box.
   Below 64em it wraps to its own full-width line (Google mobile's shape); at ≥64em the single row forms and
   the box's start edge lands EXACTLY on the results spine (inset minus the bar's own padding). */

/* Early-adopter badge on the logo: a small, understated star marker shown only for early-adopter members.
   In-flow (a flex child of .brand-mark, which provides the gap) so it contributes to width and never overflows
   the header on reflow; sized in em (scales with the wordmark + the OS font, no fixed px); RTL-safe via the
   logical margin (none here — the flex gap handles spacing in both directions). */
.ea-badge {
    display: inline-flex; align-items: center; justify-content: center; flex: none;
    width: 1.15em; height: 1.15em; border-radius: 50%;
    /* early-adopter GOLD (owner: distinct from brand) + a pinch downward (owner-tuned optical seat) */
    color: #f5b942;
    background: color-mix(in srgb, #f5b942 16%, transparent);
    margin-block-start: 0.08em;
}
.ea-badge-icon { width: 0.8em; height: 0.8em; display: block; }
/* Inline nav-item glyph (Settings/Account/Sign out in the search header). em-sized so it scales with the
   OS/text-zoom font; flex:none keeps it from shrinking. The .btn parent already supplies inline-flex +
   align-items:center + a logical gap, so the icon sits beside the label and the pair flips correctly in RTL. */
.nav-ico { inline-size: 1.1em; block-size: 1.1em; flex: none; }
/* The signed-in start screen. It stages the shared <SilkCurrent /> ribbons (.hero-bands, absolute
   inset:0) behind the search box: position:relative anchors the layer and the :not() lift keeps
   the box + suggestions above it. NO overflow:hidden here — the silk SVGs self-clip (UA default
   svg overflow + the slice crop), so nothing escapes the stage, and clipping the stage would
   truncate the autosuggest dropdown. */
.search-home { min-height: calc(100vh - 4rem); min-height: calc(100svh - 4rem); position: relative; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 1.25rem; text-align: center; padding: 2rem 1.25rem clamp(4rem, 16vh, 12rem); }
/* Full-viewport WITHOUT assuming the bar's height: .app-bar is content-sized (menu button + padding
   lands a couple px past the 4rem token, more under text zoom or when the EA badge wraps), so the
   calc() above over-shoots and leaves a phantom 2-3px scrollbar on an otherwise fixed screen. When
   the layout holds the start screen, make the page the column instead: body fills the small viewport,
   main takes whatever the bar leaves, .search-home fills main — exact by construction. The calc()
   rule stays as the fallback for engines without :has(); min-height must yield to the flex fill or
   it would re-introduce the overshoot it exists to approximate. Under text zoom the content's own
   min-content height wins and the page scrolls, which is the correct reflow behavior. */
body:has(> main > .search-home) { min-height: 100svh; display: flex; flex-direction: column; }
body:has(> main > .search-home) > main { flex: 1; display: flex; flex-direction: column; min-height: 0; }
body:has(> main > .search-home) .search-home { flex: 1; min-height: 0; }
.search-home > :not(.hero-bands) { position: relative; z-index: 1; }

/* ------------------------------ Search pill ----------------------------- */
/* The form is a two-row STACK — the bar row (back affordance + pill) and, when a view is active,
   the under-row carrying the view chip. The FORM is the autosuggest anchor (position:relative +
   data-autosuggest-anchor), so the .sc-suggest panel opens below the WHOLE stack: the chip stays
   on-screen while autocomplete is open, by construction. */
.search-form { display: flex; flex-direction: column; gap: 0.4rem; width: 100%; max-width: 640px; margin: 0 auto; position: relative; }
.search-bar { display: flex; gap: 0.5rem; align-items: center; width: 100%; }
.search-pill {
    flex: 1; min-width: 0; display: flex; align-items: center; gap: 0.5rem;
    background: var(--input-bg); border: 1px solid var(--border-strong); border-radius: var(--radius-pill);
    background: var(--input-bg); border: 1px solid var(--border-strong); border-radius: var(--radius-pill);
    /* End + block padding are EQUAL on purpose: the Search button lives INSIDE the pill at its far
       end (flat start edge, pill-rounded outer edge) and stretches to the row, so the gap above,
       below and beside it reads as one even hairline. */
    padding: 0.25rem 0.25rem 0.25rem 0.4rem; transition: border-color 0.15s ease, box-shadow 0.15s ease;
}
.search-pill:focus-within { border-color: var(--brand); box-shadow: 0 0 0 3px color-mix(in srgb, var(--brand) 22%, transparent); }
.search-pill-icon { color: var(--text-subtle); display: inline-flex; flex: none; }
/* "+" menu — replaces the magnifier on the left of the pill; a hover-darkening circle that opens a popup of
   search modes (verticals) + time filters. Native <details>; items are no-JS submit buttons. */
.search-plus { position: relative; display: inline-flex; flex: none; }
.search-plus-btn {
    display: inline-flex; align-items: center; justify-content: center; inline-size: 2rem; block-size: 2rem;
    border-radius: 50%; cursor: pointer; list-style: none; color: var(--text-subtle); background: transparent;
    border: 0; padding: 0; transition: background 0.12s ease, color 0.12s ease;
}
.search-plus-btn::-webkit-details-marker { display: none; }
.search-plus-btn::marker { content: ""; }
.search-plus-btn:hover, .search-plus[open] > .search-plus-btn { background: var(--surface-2); color: var(--text); }
.search-plus-btn:focus-visible { outline: 2px solid var(--brand-strong); outline-offset: 1px; }
.search-plus-ico { font-size: 1.5rem; line-height: 1; margin-block-start: -0.12rem; }
.search-plus-menu {
    /* min() caps the panel at the viewport: at 200% text a fixed 13rem (=416px) would force horizontal
       scroll — and Chromium keeps a CLOSED details' content BOX in layout (content-visibility:hidden),
       so an oversized panel phantom-overflows the page even while the menu is shut. */
    position: absolute; inset-block-start: calc(100% + 0.5rem); inset-inline-start: 0; z-index: 45;
    min-inline-size: min(13rem, calc(100vw - 1.5rem));
    background: var(--surface, #fff); color: var(--text, #19172a); border: 1px solid var(--border, #ddd); border-radius: var(--radius);
    box-shadow: var(--shadow-lg, 0 16px 48px rgba(16,12,40,.16)); padding: 0.35rem; display: flex; flex-direction: column; gap: 0.05rem;
    /* The menu grew (verticals + views + times + actions): scroll inside itself rather than clip on
       short handsets or at 200% text. vh fallback then dvh (dynamic-toolbar-aware) — house pattern. */
    max-block-size: calc(100vh - 6rem); max-block-size: calc(100dvh - 6rem); overflow-y: auto; overscroll-behavior: contain;
}
.search-plus-group { display: flex; flex-direction: column; gap: 0.05rem; }
/* The active view reads pressed (explicit-string aria-pressed — Blazor minimizes BOOL attribute
   values into invalid ARIA, so the markup binds literal "true"/"false"). */
.search-plus-item[aria-pressed="true"] { font-weight: 600; color: var(--brand-strong); }
.search-plus-label { font-size: 0.68rem; text-transform: uppercase; letter-spacing: 0.04em; color: var(--text-muted); padding: 0.3rem 0.55rem 0.2rem; }
.search-plus-item {
    display: flex; align-items: center; gap: 0.5rem; inline-size: 100%; text-align: start; background: transparent;
    border: 0; cursor: pointer; padding: 0.45rem 0.55rem; border-radius: var(--radius-sm, 6px); color: var(--text); font: inherit; text-decoration: none;
}
.search-plus-item:hover, .search-plus-item:focus { background: var(--surface-2); outline: none; }
.search-plus-item:focus-visible { outline: 2px solid var(--brand-strong); outline-offset: -2px; }
.search-plus-divider { border: 0; border-block-start: 1px solid var(--border); margin: 0.3rem 0.1rem; }
.search-pill-input { flex: 1; min-width: 0; border: none; outline: none; background: transparent; color: var(--text); font: inherit; padding: 0.5rem 0; }   /* min-width:0 — an input's implicit min-width:auto would refuse to shrink and force page overflow at 200% text */
.search-pill-input::placeholder { color: var(--text-subtle); }
.search-pill-clear { border: none; background: transparent; color: var(--text-subtle); cursor: pointer; font-size: 1rem; padding: 0.25rem 0.5rem; border-radius: 50%; display: none; }
.search-pill-clear.visible { display: inline-flex; }
/* Signed-in chrome: collapse the header's right-side controls into a top-right hamburger + vertical panel. */
.header-menu { position: relative; display: inline-flex; }
.header-menu-btn {
    display: inline-flex; align-items: center; justify-content: center; inline-size: 2.4rem; block-size: 2.4rem;
    border-radius: var(--radius); background: var(--surface-2); border: 1px solid var(--border); color: var(--text);
    cursor: pointer; list-style: none; padding: 0;
}
.header-menu-btn::-webkit-details-marker { display: none; }
.header-menu-btn::marker { content: ""; }
.header-menu-btn:hover { background: var(--surface); }
.header-menu-btn:focus-visible { outline: 2px solid var(--ring, var(--brand-strong)); outline-offset: 2px; }
.header-menu[open] .nav-toggle-bars { background: transparent; }
.header-menu[open] .nav-toggle-bars::before { transform: translateY(0.4rem) rotate(45deg); }
.header-menu[open] .nav-toggle-bars::after { transform: translateY(-0.4rem) rotate(-45deg); }
.header-menu-panel {
    position: absolute; inset-block-start: calc(100% + 0.4rem); inset-inline-end: 0; z-index: 50; min-inline-size: 13rem;
    background: var(--surface, #fff); color: var(--text, #19172a); border: 1px solid var(--border, #ddd); border-radius: var(--radius);
    box-shadow: var(--shadow-lg, 0 16px 48px rgba(16,12,40,.16)); padding: 0.4rem; display: flex; flex-direction: column; gap: 0.1rem;
}
.header-menu-panel .btn { inline-size: 100%; justify-content: flex-start; gap: 0.55rem; }
.header-menu-panel form { inline-size: 100%; margin: 0; }
.header-menu-section { padding: 0.15rem 0.4rem 0.4rem; }
.header-menu-label { display: block; font-size: 0.68rem; text-transform: uppercase; letter-spacing: 0.04em; color: var(--text-muted); padding: 0.15rem 0.15rem 0.35rem; }
/* Theme segmented in the header dropdown: three EQUAL options that fill the panel and stay on ONE line at
   normal font. The base 0.8rem option padding is a razor-tight fit for "System" in a 13rem panel (~196px of
   buttons in ~195px of panel) — Firefox's wider text metrics tip it into a wrap. flex:1 1 0 = equal thirds;
   tighter side padding buys slack; nowrap keeps the single word intact; overflow-x lets it scroll (never
   wrap/clip) when the OS font is enlarged. */
.header-menu-seg { inline-size: 100%; overflow-x: auto; }
.header-menu-seg .segmented-option { flex: 1 1 0; padding-inline: 0.4rem; white-space: nowrap; }
.header-menu-divider { border: 0; border-block-start: 1px solid var(--border); margin: 0.3rem 0.1rem; }
.header-menu-switch {
    display: flex; align-items: center; justify-content: space-between; gap: 0.6rem; inline-size: 100%;
    background: transparent; border: 0; cursor: pointer; padding: 0.45rem 0.5rem; border-radius: var(--radius-sm, 6px);
    color: var(--text); font: inherit; text-align: start;
}
.header-menu-switch:hover { background: var(--surface-2, #f3efe4); }
.header-menu-switch:focus-visible { outline: 2px solid var(--ring, var(--brand-strong)); outline-offset: -2px; }
/* Scoped to .header-menu-switch: the view/settings switch (.switch + .switch-thumb, app.css) shares the
   .switch-thumb class, so an UNSCOPED .switch-thumb here would bleed onto it (wrong size + a leftover
   translateY(-50%) made the thumb straddle the track). Keep these track/thumb styles to the header menu only. */
.header-menu-switch .switch-track {
    flex: none; inline-size: 2.2rem; block-size: 1.25rem; border-radius: 999px; background: var(--border-strong, #c4bca7);
    position: relative; transition: background 0.15s ease;
}
.header-menu-switch .switch-thumb {
    position: absolute; inset-block-start: 0.15rem; inset-inline-start: 0.15rem; inline-size: 0.95rem; block-size: 0.95rem;
    border-radius: 50%; background: #fff; box-shadow: 0 1px 2px rgba(0,0,0,.3); transition: inset-inline-start 0.15s ease;
}
.header-menu-switch[aria-checked="true"] .switch-track { background: var(--brand); }
.header-menu-switch[aria-checked="true"] .switch-thumb { inset-inline-start: 1.1rem; }
@media (prefers-reduced-motion: reduce) { .header-menu-switch .switch-track, .header-menu-switch .switch-thumb { transition: none; } }
.search-pill-clear:hover { background: var(--surface-2); color: var(--text); }
/* The Search button is PART OF the input: it occupies the pill's far end, its start edge is
   flattened (the pill's curve belongs to the pill; only the button's OUTER edge stays rounded), and
   the ✕ clear sits at its immediate start. Slimmer padding than a free-standing .btn so the pill
   keeps its height; align-self:stretch fills the pill row so its top/bottom gaps equal the pill's
   block padding (the even-hairline geometry). In RTL everything mirrors via the logical radii. */
.search-submit {
    border-start-start-radius: var(--radius-sm); border-end-start-radius: var(--radius-sm);
    border-start-end-radius: var(--radius-pill); border-end-end-radius: var(--radius-pill);
    padding-block: 0; padding-inline: 0.6rem 0.95rem; flex: none; align-self: stretch;   /* icon-only; tighter START padding pulls the glyph toward the query (owner-directed), the rounded OUTER edge keeps its breathing room */
}
.search-submit-ico { display: block; width: 1.15rem; height: 1.15rem; fill: none; stroke: currentColor; stroke-width: 2.2; stroke-linecap: round; }

/* The active view's chip — rides the UNDER-ROW below the field (the pill's horizontal space is for
   the query); its ✕ re-runs the search without the view. Long names ellipsize. The under-row is
   part of the form stack, so the autosuggest panel (anchored to the form) opens BELOW it and the
   chip stays visible while suggestions are up. */
/* The under-row has a FIXED rem block-size: the suggest panel pulls up by exactly this amount when a chip
   exists (below), so the chip's vertical position is IDENTICAL whether the panel is open or closed — the
   panel wraps the row rather than pushing it. Single-line rem-sized content fits at every text zoom. */
.search-under { display: flex; align-items: center; gap: 0.4rem; padding-inline-start: 0.4rem; block-size: 2.1rem; position: relative; z-index: 41; }
/* The lead-in shown only while the panel is open ("Searching in · <chip>") — the allowed horizontal shift. */
.search-under-prefix { display: none; font-size: 0.8rem; color: var(--text-muted); white-space: nowrap; }
.search-form[data-suggest-open] .search-under-prefix { display: inline; }
.search-form[data-suggest-open] .search-under { padding-inline-start: 0.75rem; }   /* align with the panel's items */
/* Integrate the chip row INTO the open panel: the panel rises by the under-row's exact height and pads its
   top by the same amount, so its first band IS the chip row (which, being z-raised and absolutely untouched,
   keeps its exact Y and a live ✕). No chip ⇒ the base geometry below the form applies unchanged. */
.search-form[data-suggest-open]:has(.search-under) .sc-suggest {
    inset-block-start: calc(100% - 2.1rem);
    padding-block-start: 2.1rem;
}
.search-form.is-anchored[data-suggest-open]:has(.search-under) .sc-suggest {
    max-block-size: calc(var(--search-vvh, 100dvh) - var(--search-anchor-bottom, 5.25rem) - 0.25rem + 2.1rem);
}
.search-view-chip {
    flex: none; display: inline-flex; align-items: center; gap: 0.15rem;
    padding: 0.15rem 0.25rem 0.15rem 0.65rem;
    background: var(--brand-soft); color: var(--brand-strong);
    border-radius: var(--radius-pill); font-size: 0.8rem; font-weight: 600; max-width: 10rem;
}
[dir="rtl"] .search-view-chip { padding: 0.15rem 0.65rem 0.15rem 0.25rem; }
.search-view-chip-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.search-view-chip-x {
    flex: none; border: 0; background: transparent; color: inherit; cursor: pointer;
    font-size: 0.72rem; line-height: 1; padding: 0.25rem 0.35rem; border-radius: 50%;
}
.search-view-chip-x:hover { background: color-mix(in srgb, var(--brand-strong) 18%, transparent); }
.search-view-chip-x:focus-visible { outline: 2px solid var(--brand-strong); outline-offset: 1px; }

/* Post-navigation result focus: pointer-origin navigations focus the first result QUIETLY (20-search adds
   .focus-quiet from the tracked input modality); keyboard-origin ones keep the ring — WCAG 2.4.7 requires
   visible focus for keyboard users, so this is never a blanket outline:none on links, and deliberately NOT a
   :focus:not(:focus-visible) rule either: engines classify late programmatic focus erratically, and that
   selector's failure mode silences the KEYBOARD ring. This class fails the safe way (a spurious ring). */
.focus-quiet:focus { outline: none; }

/* The site menu's appearance block hides under the account-synced preference (default on = attr absent). */
:root[data-menu-appearance="off"] .header-menu-appearance { display: none; }

/* ---- Reverse image search (camera button, capture sheet, results) ---- */
.search-pill-camera {
    display: inline-flex; align-items: center; justify-content: center; flex: none;
    inline-size: 1.9rem; block-size: 1.9rem; margin-inline-end: 0.15rem; border-radius: 50%;
    color: var(--text-muted); text-decoration: none; cursor: pointer;
}
.search-pill-camera:hover { color: var(--text); background: var(--surface-2); }
.search-pill-camera:focus-visible { outline: 2px solid var(--brand-strong); outline-offset: 1px; }
.search-camera-ico { inline-size: 1.15rem; block-size: 1.15rem; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linejoin: round; }

body.lens-sheet-open { overflow: hidden; }
.lens-sheet {
    position: fixed; inset: 0; z-index: var(--z-modal, 10000); display: flex; align-items: center; justify-content: center;
    padding: 1rem; background: color-mix(in srgb, #000 55%, transparent);
}
.lens-sheet-panel {
    inline-size: min(30rem, 100%); max-block-size: min(90vh, 90dvh); overflow-y: auto;
    background: var(--surface); color: var(--text); border: 1px solid var(--border);
    border-radius: var(--radius); box-shadow: var(--shadow-lg); padding: 1rem;
    display: flex; flex-direction: column; gap: 0.75rem;
}
.lens-sheet.is-busy .lens-sheet-panel { opacity: 0.6; pointer-events: none; }
.lens-sheet-head { display: flex; align-items: center; justify-content: space-between; gap: 0.5rem; }
.lens-sheet-head h2 { font-size: 1.05rem; margin: 0; }
.lens-sheet-close { border: 0; background: transparent; color: var(--text-muted); cursor: pointer; font-size: 1rem; padding: 0.25rem 0.4rem; border-radius: 50%; }
.lens-sheet-close:hover { color: var(--text); background: var(--surface-2); }
.lens-sheet-cam { display: flex; flex-direction: column; gap: 0.5rem; }
.lens-sheet-cam video { inline-size: 100%; border-radius: var(--radius-sm); background: #000; aspect-ratio: 4 / 3; object-fit: cover; }
.lens-sheet-btn { inline-size: 100%; white-space: normal; }
.lens-sheet-url { display: flex; flex-wrap: wrap; gap: 0.4rem; }
.lens-sheet-url .field-input { flex: 1 1 12rem; min-inline-size: 0; }
.lens-sheet-status { font-size: 0.8125rem; margin: 0; min-block-size: 1.2rem; }
.lens-sheet-privacy { font-size: 0.75rem; margin: 0; border-block-start: 1px solid var(--border); padding-block-start: 0.6rem; }

.lens-page { padding: 1.25rem; max-inline-size: 72rem; }
.lens-head { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 1rem; margin-block-end: 1rem; }
.lens-head-text { min-inline-size: 0; }
.lens-h1 { font-size: 1.35rem; margin: 0; }
.lens-h1:focus { outline: none; }
.lens-sub { font-size: 0.85rem; margin: 0.15rem 0 0; }
.lens-thumb { flex: none; }
.lens-thumb img { max-inline-size: 8rem; max-block-size: 8rem; border-radius: var(--radius-sm); border: 1px solid var(--border); display: block; }
.lens-alert { display: flex; flex-wrap: wrap; align-items: center; gap: 0.75rem; }
.lens-count { font-size: 0.85rem; margin-block-end: 0.75rem; display: flex; gap: 0.3rem; }
.lens-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr)); gap: 0.9rem; }
.lens-card {
    display: flex; flex-direction: column; gap: 0.5rem; text-decoration: none; color: inherit; min-inline-size: 0;
    border: 1px solid var(--border); border-radius: var(--radius); padding: 0.6rem; background: var(--surface);
}
.lens-card:hover { border-color: var(--border-strong); background: var(--surface-2); }
.lens-card:focus-visible { outline: 2px solid var(--brand-strong); outline-offset: 2px; }
.lens-card-thumb { aspect-ratio: 4 / 3; overflow: hidden; border-radius: var(--radius-sm); background: var(--surface-2); }
.lens-card-thumb img { inline-size: 100%; block-size: 100%; object-fit: cover; display: block; }
.lens-card-title { font-size: 0.9rem; font-weight: 600; overflow-wrap: anywhere; }
.lens-card-source { font-size: 0.78rem; color: var(--success); overflow-wrap: anywhere; }
.lens-card-price { font-size: 0.85rem; font-weight: 600; }
.lens-chooser { display: flex; flex-wrap: wrap; gap: 1rem; }
.lens-choice {
    flex: 1 1 18rem; min-inline-size: 0; display: flex; flex-direction: column; gap: 0.6rem; align-items: flex-start;
    border: 1px solid var(--border); border-radius: var(--radius); padding: 1rem; background: var(--surface);
}
.lens-choice-h { font-size: 1rem; margin: 0; }
.lens-choice .field-input { inline-size: 100%; }
.lens-privacy { font-size: 0.8rem; margin-block-start: 1rem; }

/* compact variant for the results header */
.search-form.compact { max-width: none; margin: 0; }
.search-form.compact .search-pill { padding: 0.2rem 0.2rem 0.2rem 0.4rem; }

/* ------------------- Handset anchored search (21-search-anchor.ts) -------------------
   Google-style takeover on narrow viewports: focusing the input pins the whole form stack to the
   top of the screen, an opaque backdrop covers the page, and the suggestions get the remaining
   height. JS-only enhancement — without JS none of these classes ever appear. The 34em query in
   the module is the SAME em breakpoint as the nav hamburger (reflow mandate). */
html.search-anchored { overflow: hidden; }                       /* scroll lock — docs-cmdk precedent */
.search-anchor-back { display: none; }                           /* dormant outside anchored mode (and for no-JS) */
.search-anchor-backdrop { position: fixed; inset: 0; z-index: calc(var(--z-modal) - 1); background: var(--bg); }
.search-form.is-anchored {
    position: fixed; inset-block-start: 0; inset-inline: 0; z-index: var(--z-modal);
    max-width: none; margin: 0;
    padding: 0.5rem 0.75rem; padding-block-start: max(0.5rem, env(safe-area-inset-top));
    background: var(--bg-elevated);
    animation: search-anchor-in 0.16s ease-out;                  /* global reduced-motion kill-switch nulls this */
}
@keyframes search-anchor-in { from { opacity: 0; transform: translateY(-0.4rem); } }
.search-form.is-anchored .search-anchor-back {
    display: inline-flex; align-items: center; justify-content: center; flex: none;
    inline-size: 2.25rem; block-size: 2.25rem; border-radius: 50%;
    border: 0; padding: 0; background: transparent; color: var(--text-subtle); cursor: pointer;
}
.search-form.is-anchored .search-anchor-back:hover { background: var(--surface-2); color: var(--text); }
.search-anchor-back:focus-visible { outline: 2px solid var(--brand-strong); outline-offset: 1px; }
.search-anchor-back-ico { inline-size: 1.15rem; block-size: 1.15rem; fill: none; stroke: currentColor; stroke-width: 2.2; stroke-linecap: round; stroke-linejoin: round; }
[dir="rtl"] .search-anchor-back-ico { transform: scaleX(-1); }   /* .sc-back precedent */
/* Suggestions own the takeover surface: full bar width, room down toward the keyboard, full-bleed
   list (no card chrome). dvh tracks the Android WebView's adjustResize viewport; on iOS the keyboard
   OVERLAYS the layout viewport, so 21-search-anchor.ts mirrors visualViewport.height into
   --search-vvh while anchored — and the form's MEASURED bottom into --search-anchor-bottom — so the
   final declaration caps the panel EXACTLY flush against the keyboard (viewport minus the real
   header stack minus the 0.25rem panel gap) at any text size, with or without the chip row.
   Degradation chain: no JS ⇒ no anchored mode and no panel at all (plain GET form); JS but a var
   missing ⇒ falls back to 100dvh / the 5.25rem header estimate (≈ the old fixed 5.5rem cap);
   older engines without var() take the plain vh/dvh lines above. */
.search-form.is-anchored .sc-suggest {
    inset-inline: 0; max-width: none;
    max-block-size: calc(100vh - 5.5rem); max-block-size: calc(100dvh - 5.5rem);
    max-block-size: calc(var(--search-vvh, 100dvh) - var(--search-anchor-bottom, 5.25rem) - 0.25rem);
    overflow-y: auto; overscroll-behavior: contain;
    border-inline: 0; border-radius: 0; box-shadow: none;
}

/* ------------------------------ Results --------------------------------- */
.results-search { padding: 1rem 1.25rem; border-bottom: 1px solid var(--border); background: var(--bg-elevated); padding-inline-start: var(--results-inset); }
.results-search .search-form.compact { max-width: var(--results-measure); }
/* ═══ Results spine (Google/Kagi/Bing geometry): everything on ONE start-aligned vertical axis. ═══
   --results-inset is the start gutter shared by the header search box, tabs, filters, and results.
   Logical properties throughout — RTL mirrors automatically. Text verticals read at a 44rem measure;
   media verticals (.is-media: images/videos/shopping) earn 74rem. The freed end side stays clean
   (the future knowledge-rail slot). */
:root { --results-inset: 1.25rem; --results-measure: 44rem; --results-measure-wide: 74rem; }
@media (min-width: 48em) { :root { --results-inset: 2.5rem; } }
@media (min-width: 64em) { :root { --results-inset: clamp(8rem, 10vw, 10.5rem); } }

.results-wrap { max-width: none; margin: 0; padding: 1rem 1.25rem 4rem; padding-inline-start: var(--results-inset); }
.results-wrap > * { max-width: var(--results-measure); }
/* chrome rows span the wide line on every vertical, so the tab/filter axis never jumps between verticals;
   the square-layout tile grid is media-forward, so it earns the wide measure too */
.results-wrap > .search-tabs, .results-wrap > .results-controls,
.results-wrap > .active-filters, .results-wrap > .results-grid { max-width: var(--results-measure-wide); }
.results-wrap.is-media > * { max-width: var(--results-measure-wide); }

/* vertical tabs */
.search-tabs { display: flex; gap: 0.25rem; border-bottom: 1px solid var(--border); margin-bottom: 1.25rem; overflow-x: auto; }
.search-tab { padding: 0.6rem 0.9rem; font-weight: 600; font-size: 0.92rem; color: var(--text-muted); border-bottom: 2px solid transparent; white-space: nowrap; }
.search-tab:hover { color: var(--text); text-decoration: none; }
.search-tab.active { color: var(--brand); border-bottom-color: var(--brand); }
.search-tab.is-disabled { opacity: 0.45; cursor: not-allowed; }   /* kind with no live source (provider pivot) */

/* images grid */
.image-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 0.5rem; }
.image-cell { display: block; aspect-ratio: 3/2; border-radius: var(--radius); overflow: hidden; background: var(--surface-2); border: 1px solid var(--border); }
.image-cell img { width: 100%; height: 100%; object-fit: cover; }
.view-ico { width: 0.95rem; height: 0.95rem; flex: 0 0 auto; }

/* ===== Image VIEW MODES (Part C) — data-view-mode on #image-grid; each cell wrap carries --ar = width/height (fallback 1.5). GRID (default) = the rules above. ===== */
/* JUSTIFIED — Google-style variable-width rows filled to a shared height (flex-grow ∝ aspect). */
#image-grid[data-view-mode="justified"] { display: flex; flex-wrap: wrap; gap: 0.5rem; --rh: clamp(140px, 22vw, 200px); }
/* Flexbox-justified: basis = the image's NATURAL width at the row height (--ar × --rh) so a row fills then WRAPS;
   flex-grow ∝ aspect then justifies each row edge-to-edge (the last row stretches — standard). */
#image-grid[data-view-mode="justified"] > .image-cell-wrap { flex: calc(var(--ar, 1.5)) 1 calc(var(--ar, 1.5) * var(--rh)); height: var(--rh); min-width: 0; }
/* MASONRY — Pinterest columns, full tile aspect, no shape crop. */
#image-grid[data-view-mode="masonry"] { display: block; column-width: 190px; column-gap: 0.5rem; }
#image-grid[data-view-mode="masonry"] > .image-cell-wrap { break-inside: avoid; margin: 0 0 0.5rem; aspect-ratio: var(--ar, 1.5); width: 100%; }
/* Justified/masonry: the WRAP defines the cell's shape (uniform row height / the image's true aspect) —
   the inner .image-cell must FILL it, never impose the grid mode's fixed 3:2 (which left justified rows
   ragged and masonry columns gapped). This override shipped with Part C and was LOST when the filmstrip
   mode retired: the removal took the shared three-mode rule down with it. Mode-scoped; grid untouched. */
#image-grid[data-view-mode="justified"] .image-cell,
#image-grid[data-view-mode="masonry"] .image-cell { aspect-ratio: auto; width: 100%; height: 100%; }

/* video / shopping cards */
.card-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(190px, 1fr)); gap: 1rem; }
.media-card { display: block; color: inherit; }
.media-card:hover { text-decoration: none; }
.media-card:hover .media-title { color: var(--brand); }
.media-thumb { position: relative; aspect-ratio: 16/9; border-radius: var(--radius); overflow: hidden; background: var(--surface-2); border: 1px solid var(--border); }
.media-thumb.shopping { aspect-ratio: 1/1; }
.media-thumb img { width: 100%; height: 100%; object-fit: cover; }
.media-badge { position: absolute; bottom: 6px; inset-inline-end: 6px; background: rgba(0,0,0,0.78); color: #fff; font-size: 0.72rem; font-weight: 600; padding: 0.1rem 0.35rem; border-radius: 4px; }
.media-title { font-weight: 600; font-size: 0.92rem; margin-top: 0.5rem; line-height: 1.3; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.media-price { font-weight: 700; color: var(--text); margin-top: 0.2rem; }
.media-meta { color: var(--text-muted); font-size: 0.82rem; margin-top: 0.15rem; }
.media-body { min-width: 0; }

/* ═══ Results CONTROLS row — ONE line per vertical: re-search controls (time chips / filter selects) at the
   START, the presentation seg (view modes / Standard|Square layout) pushed to the END. The nav/form children
   keep their own internal behavior (incl. the 34em pills⇄menu collapse); this wrapper only owns the axis. ═══ */
.results-controls { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem 1rem; margin: 0.25rem 0 0.75rem; }
.results-controls > .view-seg { margin-inline-start: auto; }
.view-seg { display: inline-flex; flex-wrap: wrap; gap: 0.15rem; padding: 0.2rem; background: var(--surface-2); border: 1px solid var(--border); border-radius: var(--radius-pill); }
.view-opt { display: inline-flex; align-items: center; gap: 0.35rem; min-width: 0; white-space: nowrap; cursor: pointer; font-size: 0.8125rem; color: var(--text-muted); background: transparent; border: 0; border-radius: var(--radius-pill); padding: 0.25rem 0.7rem; }
.view-opt:hover { color: var(--text); }
.view-opt.active { background: color-mix(in srgb, var(--accent) 14%, var(--surface)); color: var(--text); box-shadow: inset 0 0 0 1px var(--accent); }
.view-opt:focus-visible { outline: 2px solid var(--brand-strong); outline-offset: 1px; }
.view-ico { width: 0.95rem; height: 0.95rem; flex: 0 0 auto; }
.view-ico rect { fill: currentColor; }

/* LIST mode — a dense horizontal row: thumbnail left, title/price/meta flowing right. Grid mode stays untouched. */
.card-grid[data-view-mode="list"] { grid-template-columns: 1fr; gap: 0.5rem; }
.card-grid[data-view-mode="list"] .media-card { display: flex; gap: 0.9rem; align-items: flex-start; }
.card-grid[data-view-mode="list"] .media-thumb { flex: 0 0 118px; }
.card-grid[data-view-mode="list"] .media-thumb.shopping { flex-basis: 84px; }
.card-grid[data-view-mode="list"] .media-body { flex: 1 1 auto; }
.card-grid[data-view-mode="list"] .media-body > :first-child { margin-top: 0; }

/* ═══ Square layout — a media-forward tile GRID (web + news render through it; the standard row list is the
   sibling layout). Column count derives from a rem minimum, so OS text zoom grows tiles into FEWER columns
   (reflow, never overflow) and phone widths converge on one column. Cards stretch per grid row; the meta line
   pins to the card FOOT so a row of sources reads level. ═══ */
.results-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(15rem, 100%), 1fr)); gap: 1.4rem 1.1rem; padding-block: 0.25rem 0.5rem; }
.sq-card { display: flex; flex-direction: column; min-width: 0; }
.sq-media { position: relative; aspect-ratio: 4 / 3; border-radius: var(--radius); overflow: hidden; background: var(--surface-2); border: 1px solid var(--border); }
.sq-media-link { display: block; block-size: 100%; line-height: 0; }
.sq-thumb { inline-size: 100%; block-size: 100%; object-fit: cover; display: block; }
/* No thumbnail → a stable host-tinted monogram tile (--tile-hue is hashed from the host server-side; mixing
   against the theme's own surface/text keeps it legible in BOTH themes). */
.sq-fallback { display: flex; align-items: center; justify-content: center; block-size: 100%;
    background: color-mix(in oklab, hsl(var(--tile-hue) 65% 52%), var(--surface-2) 82%);
    color: color-mix(in oklab, hsl(var(--tile-hue) 65% 52%), var(--text) 40%);
    font-size: 2.4rem; font-weight: 700; user-select: none; }
.sq-body { display: flex; flex-direction: column; flex: 1 1 auto; min-width: 0; padding-block-start: 0.55rem; }
.sq-card .result-title { font-size: 0.95rem; line-height: 1.35; margin-bottom: 0.2rem; }
.sq-card .result-desc { font-size: 0.85rem; }
/* Tiles bound their text so one verbose result can't stretch its whole grid row — DEFAULTS only: an explicit
   designer clamp (rt-clamp-*) wins. */
.sq-card .result-title:not([class*="rt-clamp"]), .sq-card .result-desc:not([class*="rt-clamp"]) {
    display: -webkit-box; -webkit-box-orient: vertical; overflow: hidden; -webkit-line-clamp: 3; }
.sq-meta { display: flex; align-items: center; flex-wrap: wrap; gap: 0.35rem; min-width: 0;
    margin-block-start: auto; padding-block-start: 0.5rem; color: var(--text-subtle); font-size: 0.8rem; }
.sq-meta-ico { inline-size: 1rem; block-size: 1rem; border-radius: 3px; flex: none; }
.sq-meta-src { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
/* The system tools overlay the MEDIA corner (the tools element is absolute at the CARD's top-end — the media
   block is the card's top, so they coincide) — never the text. Hover/focus-reveal like the image grid; a
   ranked card and touch devices keep them visible. */
.sq-card .result-card-tools { opacity: 0; transition: opacity 0.12s ease; }
.sq-card:hover .result-card-tools, .sq-card:focus-within .result-card-tools,
.sq-card .rank-control[open] { opacity: 1; }
.sq-card:has(.rank-chip-pinned, .rank-chip-raised, .rank-chip-lowered, .rank-chip-blocked) .result-card-tools { opacity: 1; }
@media (hover: none) { .sq-card .result-card-tools { opacity: 1; } }

/* flow-root: the rank-tools FLOAT (below) must never poke past a short row into the next result */
.result-item { padding: 1rem 0; border-bottom: 1px solid var(--border); position: relative; display: flow-root; }
.result-item:last-child { border-bottom: none; }
/* The rank tools of a standard LIST row sit at the row's top-end as a FLOAT (kept position:relative so the
   ⋮ menu still anchors to the chips): floated, the title/summary LINE BOXES shorten beside the chips and
   wrap under them — text can NEVER render beneath the buttons, whatever rows the design template puts first
   and however far the user's text zoom grows them. (The old absolute overlay reserved only the FIRST row's
   end padding; any later row tall enough to reach the chips slid underneath — the reported overlap.) */
.result-item > .result-card-tools { position: relative; float: inline-end;
    inset-block-start: auto; inset-inline-end: auto; margin-inline-start: 0.75rem; margin-block-end: 0.25rem; }
/* "Number search results" pref (default OFF): a restrained, muted ABSOLUTE ordinal above each web result that
   continues across pages. In-flow + rem-based so it reflows and scales with OS text zoom (no fixed px); tabular
   numerals keep multi-digit numbers tidy. Decorative only (the markup marks it aria-hidden). */
.result-ordinal { font-size: 0.78rem; line-height: 1; color: var(--text-subtle); margin-bottom: 0.15rem;
    font-variant-numeric: tabular-nums; font-feature-settings: "tnum"; }
.result-ordinal::before { content: "#"; opacity: 0.6; margin-inline-end: 0.05rem; }
.result-url { font-size: 0.8rem; color: var(--success); margin-bottom: 0.15rem; word-break: break-all; }
.result-date { font-size: 0.8rem; color: var(--text-muted); margin-bottom: 0.15rem; }
.result-sitelinks { display: grid; grid-template-columns: repeat(auto-fit, minmax(7rem, 1fr)); gap: 0.1rem 1rem; margin-top: 0.35rem; min-width: 0; max-width: 30rem; }
.result-sitelink { font-size: 0.9rem; color: var(--link-color, var(--brand)); text-decoration: none; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.result-sitelink:hover { text-decoration: underline; }
/* overflow-wrap:anywhere so a long unbreakable token (a very long word, or a URL used as the title/snippet) breaks
   instead of forcing horizontal scroll at 200% text / narrow viewports — keeps the numbered web result reflow-safe. */
.result-title { font-size: 1.1rem; font-weight: 600; margin-bottom: 0.25rem; overflow-wrap: anywhere; }
.result-title a { color: var(--link-color, var(--brand)); }
.result-desc { color: var(--text-muted); font-size: 0.92rem; overflow-wrap: anywhere; }

/* ===== Result Designer: the ONLY styles a user template can apply (a fixed whitelist → the row-slot sandbox; no raw
   CSS ever). An element with no styles keeps its semantic default, so the default template = today's look. Placed
   AFTER the semantic .result-* rules so an explicit rt-* override wins by source order. ===== */
.rt-row { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.4rem; min-width: 0; margin-bottom: 0.15rem; }
.rt-row > * { margin-bottom: 0; min-width: 0; }
/* TEXT blocks sharing a row start ON the current line and grow into the remaining space (flex-basis:0 — with
   wrap enabled, an auto-basis text block whose natural width exceeds the line ALWAYS wrapped to its own flex
   line, so "favicon + excerpt in one row" never visually shared the first line). The min-width floor makes a
   genuinely-too-narrow line wrap gracefully instead of squeezing into a one-word column. Small atoms (favicon /
   date / number) keep their natural size. Designer chips mirror by content via :has(). */
.rt-row > .result-title, .rt-row > .result-desc, .rt-row > .result-url, .rt-row > .result-sitelinks,
.rt-row > .rd-chip:has(> .result-title), .rt-row > .rd-chip:has(> .result-desc),
.rt-row > .rd-chip:has(> .result-url), .rt-row > .rd-chip:has(> .result-sitelinks) {
    flex: 1 1 0; min-width: 8rem;
}
/* Small atoms beside a MULTILINE text block sit with its FIRST line (baseline through the chip wrapper resolves
   against the block's last line and sank the icon to line two). */
.rt-row > .result-favicon, .rt-row > .result-date, .rt-row > .result-ordinal,
.rt-row > .rd-chip:has(> .result-favicon), .rt-row > .rd-chip:has(> .result-date),
.rt-row > .rd-chip:has(> .result-ordinal) {
    align-self: flex-start; margin-top: 0.15em;
}
/* Favicons sit on a fixed LIGHT chip in every theme: many sites ship dark/transparent glyphs (GitHub's
   octocat, NYT's "T") that vanish on a dark surface — var(--surface-2) is near-black in dark mode, which made
   them look like MISSING icons (owner-reported via the designer preview). box-sizing keeps the box 16px. */
.result-favicon { width: 16px; height: 16px; border-radius: 3px; vertical-align: middle; margin-inline-end: 0.4rem; object-fit: contain; flex: 0 0 auto; background: #fff; padding: 2px; box-sizing: border-box; }
.rt-size-xs { font-size: 0.75rem; } .rt-size-s { font-size: 0.85rem; } .rt-size-m { font-size: 0.95rem; }
.rt-size-l { font-size: 1.15rem; } .rt-size-xl { font-size: 1.4rem; }
/* Size on the favicon = actual icon dimensions (an <img> ignores font-size; width/height CSS beats its attrs). */
.result-favicon.rt-size-xs { width: 12px; height: 12px; }
.result-favicon.rt-size-s { width: 14px; height: 14px; }
.result-favicon.rt-size-l { width: 20px; height: 20px; }
.result-favicon.rt-size-xl { width: 26px; height: 26px; }
.rt-weight-normal { font-weight: 400; } .rt-weight-medium { font-weight: 500; } .rt-weight-bold { font-weight: 700; }
.rt-color-default, .rt-color-default a { color: var(--text); }
.rt-color-muted, .rt-color-muted a { color: var(--text-muted); }
.rt-color-subtle, .rt-color-subtle a { color: var(--text-subtle); }
.rt-color-link, .rt-color-link a { color: var(--link-color, var(--brand)); }
.rt-color-success, .rt-color-success a { color: var(--success); }
.rt-color-brand, .rt-color-brand a { color: var(--brand-strong); }
.rt-color-danger, .rt-color-danger a { color: var(--danger); }
.rt-clamp-1, .rt-clamp-2, .rt-clamp-3 { display: -webkit-box; -webkit-box-orient: vertical; overflow: hidden; }
.rt-clamp-1 { -webkit-line-clamp: 1; } .rt-clamp-2 { -webkit-line-clamp: 2; } .rt-clamp-3 { -webkit-line-clamp: 3; }
.rt-caps { text-transform: uppercase; letter-spacing: 0.03em; }
.results-loading { display: flex; align-items: center; gap: 0.6rem; color: var(--text-muted); padding: 1rem 0; }
.results-empty { text-align: start; color: var(--text-muted); padding: 2.5rem 0; }
.results-count { color: var(--text-subtle); font-size: 0.85rem; margin: 0 0 1rem; }
/* The results meta row: count · malicious notice · rules summary · translate note · personalize
   toggle share ONE wrapping line (previously four stacked blocks). Children keep their identity;
   the row owns the spacing (their block margins are neutralized) and the gap is the separator. */
.results-meta { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.25rem 1.25rem;
  margin: 0 0 0.75rem; min-width: 0; }
.results-meta > * { margin: 0; min-width: 0; }

/* Numbered pager (web results). Logical properties + flex-wrap so it reflows + is RTL-ready. */
.pager { display: flex; flex-wrap: wrap; gap: 0.4rem; align-items: center; justify-content: flex-start; margin: 2.25rem 0 1rem; }
.pager-link { display: inline-flex; align-items: center; justify-content: center; min-width: 2.25rem; min-height: 2.25rem; padding-inline: 0.6rem; border: 1px solid var(--border); border-radius: var(--radius-pill, 999px); color: var(--text); text-decoration: none; font-size: 0.9rem; }
.pager-link:hover { border-color: var(--brand); color: var(--brand); }
.pager-link.active { background: var(--brand); border-color: var(--brand); color: #fff; font-weight: 600; }
.pager-edge { font-weight: 600; }
.pager-gap { color: var(--text-muted); padding-inline: 0.15rem; }

/* Slim top progress bar shown during an enhanced-nav page change (state-of-the-art transition feedback). */
.nav-progress { position: fixed; inset-block-start: 0; inset-inline-start: 0; height: 3px; width: 0; background: var(--brand); z-index: 9999; opacity: 0; pointer-events: none; }
.nav-progress.active { width: 88%; opacity: 1; transition: width 9s cubic-bezier(0.12, 0.78, 0.12, 1), opacity 0.15s ease; }
.nav-progress.done { width: 100%; opacity: 0; transition: width 0.18s ease, opacity 0.4s ease 0.12s; }

/* Subtle result fade-in (reduced-motion users get none). fill BACKWARDS, never `both`: a filled
   transform animation keeps the element a stacking context FOREVER, which made every result paint
   in DOM order — a later result's URL hit-tested ABOVE an earlier result's open Adjust panel. */
@media (prefers-reduced-motion: no-preference) {
    .result-item { animation: result-in 0.24s ease backwards; }
}
/* While a result's Adjust/kebab popup is open, that result outranks its siblings outright — no
   stacking experiment (entrance animation, future transforms) may ever paint over an open menu. */
.result-item:has(details[data-rank][open]) { z-index: 30; }
@keyframes result-in { from { opacity: 0; transform: translateY(4px); } to { opacity: 1; transform: none; } }

/* Image infinite-scroll affordances. */
.image-status { display: flex; align-items: center; justify-content: center; gap: 0.5rem; color: var(--text-muted); padding: 1.5rem 0; }
#image-sentinel { block-size: 1px; }

/* ------------------------------ Pricing --------------------------------- */
.pricing-card { max-width: 460px; margin: 0 auto 3rem; padding: clamp(1.25rem, 5vw, 2rem); text-align: center; }

/* Full-width segmented control: the two segments share the width (flex:1, min-width:0) and grow TALLER
   rather than wider when text scales — the "save" badge stacks under "Annual" (column), so it can never
   push the control past the viewport. A rounded rect (not a pill) reads cleanly when segments are tall. */
.billing-toggle { display: flex; gap: 0.25rem; width: 100%; max-width: 24rem; margin: 0 auto 1.5rem; padding: 0.3rem; background: var(--surface-2); border: 1px solid var(--border); border-radius: var(--radius-lg); }
.billing-radio { position: absolute; opacity: 0; pointer-events: none; width: 0; height: 0; }
.billing-toggle label { flex: 1 1 0; min-width: 0; cursor: pointer; text-align: center; line-height: 1.25;
    display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 0.2rem;
    padding: 0.5rem 0.4rem; border-radius: var(--radius); font-weight: 600; font-size: 0.95rem; color: var(--text-muted); }
/* At large text (em → font-aware) the two segments can't sit side by side; stack them so each gets the
   full width. The threshold is low enough that normal-font phones keep the horizontal pill. */
@media (max-width: 18em) { .billing-toggle { flex-direction: column; } }
/* Radios are direct children of .pricing-card; the toggle/price/cta are later siblings (~). The active
   segment gets an accent-tinted fill + a 1px inset accent ring so the selection is unmistakable, including
   in dark mode (the previous surface-only highlight was too subtle). */
#p-month:checked ~ .billing-toggle label[for="p-month"],
#p-year:checked ~ .billing-toggle label[for="p-year"] { background: color-mix(in srgb, var(--accent) 14%, var(--surface)); color: var(--text); box-shadow: inset 0 0 0 1px var(--accent), var(--shadow-sm); }
#p-month:focus-visible ~ .billing-toggle label[for="p-month"],
#p-year:focus-visible ~ .billing-toggle label[for="p-year"] { outline: 2px solid var(--ring); outline-offset: 2px; }
.save-badge { font-size: 0.7rem; font-weight: 700; color: var(--brand-contrast); background: var(--accent); padding: 0.05rem 0.45rem; border-radius: var(--radius-pill); white-space: nowrap; }

.price-display { margin-bottom: 1.5rem; }
/* Flex + wrap so the amount and "/month" can break onto separate lines under large text. There is no
   whitespace between the .amount and .per spans, so without flex-wrap they form one unbreakable token
   ("$12/month") that overflows the viewport when the font is scaled up. */
.price { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: center; column-gap: 0.25rem; }
/* The amount is a single unbreakable token (e.g. "$8.25"); clamp keeps it from overrunning a narrow
   viewport when scaled. The rem bounds still grow with the user's font, so text scaling is preserved —
   only the vw term limits it on small screens (it never falls below the 2rem floor). */
.price .amount { font-size: clamp(2rem, 13vw, 3rem); font-weight: 800; letter-spacing: -0.03em; line-height: 1.1; }
.price .per { color: var(--text-muted); font-size: 1rem; }
.price-note { color: var(--text-muted); font-size: 0.85rem; margin-top: 0.25rem; }

/* Toggle visibility driven purely by the radios (no JS). */
.price-year, .cta-year { display: none; }
#p-year:checked ~ .price-display .price-month { display: none; }
#p-year:checked ~ .price-display .price-year { display: flex; }
#p-month:checked ~ .price-display .price-year { display: none; }
#p-year:checked ~ .cta-month { display: none; }
#p-year:checked ~ .cta-year { display: block; }
.cta { margin: 0; }

.feature-list { list-style: none; text-align: start; margin: 0 auto 1.75rem; max-width: 330px; display: flex; flex-direction: column; gap: 0.6rem; }
.feature-list li { display: flex; gap: 0.6rem; align-items: flex-start; }
.feature-list .check { color: var(--brand); font-weight: 800; }

/* ------------------------------ Auth forms ------------------------------ */
.auth-wrap { display: flex; justify-content: center; padding: clamp(2rem, 6vw, 4rem) 1.25rem; }
.auth-card { width: 100%; max-width: 420px; padding: 2rem; }
.auth-card h1 { font-size: 1.5rem; margin-bottom: 0.25rem; }
.auth-card .sub { color: var(--text-muted); margin-bottom: 1.5rem; font-size: 0.9375rem; }
.auth-card form { display: flex; flex-direction: column; gap: 0.25rem; }
.auth-alt { margin-top: 1.25rem; font-size: 0.9375rem; color: var(--text-muted); text-align: center; }

/* Signup's "you're already signed in" panel (SSO-aware signup) */
.signedin-actions { display: flex; flex-wrap: wrap; gap: 0.5rem; margin-top: 1rem; min-width: 0; }
.signedin-actions .btn { flex: 1 1 0; min-width: 8rem; }   /* the pair shares the panel's full width */
.signedin-switch .btn { width: 100%; }
.signedin-switch { margin-top: 0.9rem; }

/* ---- Plan picker (signup) — selectable plan cards ---- */
/* gap leaves clearance for the featured card's floating ribbon so it never touches the card above it */
.plan-picker { border: 0; padding: 0; margin: 0.85rem 0 0.35rem; min-width: 0; display: flex; flex-direction: column; gap: 1.15rem; }
.plan-picker-legend { padding: 0; margin-bottom: 0.55rem; font-size: 0.75rem; font-weight: 700; letter-spacing: 0.05em; text-transform: uppercase; color: var(--text-muted); }

.plan-card {
    position: relative; display: flex; align-items: center; gap: 0.8rem;
    padding: 0.85rem 1rem; background: var(--surface);
    border: 1.5px solid var(--border); border-radius: var(--radius-lg);
    cursor: pointer; transition: border-color 0.15s ease, background 0.15s ease, box-shadow 0.15s ease, transform 0.15s ease;
}
.plan-card:hover { border-color: var(--border-strong); }
.plan-card:active { transform: scale(0.995); }
/* The real radio stays in the DOM for a11y + form posting, but is visually replaced by .plan-card-check. */
.plan-card input { position: absolute; width: 1px; height: 1px; opacity: 0; pointer-events: none; }

/* Selected state — accent ring + tint + filled check. */
.plan-card:has(input:checked) {
    border-color: var(--accent);
    background: color-mix(in srgb, var(--accent) 7%, var(--surface));
    box-shadow: 0 0 0 1px var(--accent);
}
/* Keyboard focus (the hidden radio receives focus). */
.plan-card:has(input:focus-visible) { outline: 2px solid var(--ring); outline-offset: 2px; }

.plan-card-check {
    flex: none; width: 1.3rem; height: 1.3rem; border-radius: 50%;
    border: 2px solid var(--border-strong); position: relative;
    transition: border-color 0.15s ease, background 0.15s ease;
}
.plan-card:has(input:checked) .plan-card-check { border-color: var(--accent); background: var(--accent); }
.plan-card:has(input:checked) .plan-card-check::after {
    content: ""; position: absolute; inset-inline-start: 0.34rem; top: 0.14rem; width: 0.32rem; height: 0.6rem;
    border: solid var(--brand-contrast); border-width: 0 2px 2px 0; transform: rotate(45deg);
}

/* Body holds the name/sub + price; it WRAPS so the price drops below the name (rather than overlapping it)
   when the text is scaled up — flex items never overlap, so reflow replaces the previous collision. */
.plan-card-body { flex: 1 1 auto; min-width: 0; display: flex; flex-wrap: wrap; align-items: center; gap: 0.4rem 0.85rem; }
.plan-card-main { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 0.1rem; }
.plan-card-name { font-weight: 700; font-size: 1rem; color: var(--text); line-height: 1.2; }
.plan-card-sub { font-size: 0.8125rem; color: var(--text-muted); }

/* flex-wrap so the amount + "/mo" (no whitespace between the spans → one unbreakable token) can break onto
   two lines under large text instead of overflowing — same guard as .price above. */
.plan-card-price { flex: none; margin-inline-start: auto; display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.1rem; }
.plan-card-amount { font-weight: 800; font-size: 1.3rem; letter-spacing: -0.02em; color: var(--text); }
.plan-card-per { font-size: 0.8125rem; font-weight: 600; color: var(--text-muted); }

/* Featured (annual) — a touch of accent at rest, plus the savings ribbon. */
.plan-card--featured { border-color: color-mix(in srgb, var(--accent) 40%, var(--border)); }
/* In-flow pill above the plan name (was absolute → overlapped content when the text grew). Sits at the
   top of the card body and pushes the name down; wraps cleanly at large font instead of colliding. */
.plan-card-ribbon {
    align-self: flex-start; margin-bottom: 0.1rem; line-height: 1.3;
    background: var(--accent); color: var(--brand-contrast);
    font-size: 0.6875rem; font-weight: 800; letter-spacing: 0.02em; text-transform: uppercase;
    padding: 0.16rem 0.55rem; border-radius: var(--radius);
}
@media (prefers-reduced-motion: reduce) { .plan-card { transition: none; } .plan-card:active { transform: none; } }

/* ------------------------------ Account --------------------------------- */
.account-grid { display: grid; gap: 1.25rem; }
.account-row { display: flex; justify-content: space-between; gap: 1rem; padding: 0.85rem 0; border-bottom: 1px solid var(--border); }
.account-row:last-child { border-bottom: none; }
.account-row .k { color: var(--text-muted); }
.account-row .v { font-weight: 600; }
.page-head { padding: clamp(1.5rem, 4vw, 2.5rem) 0 0.5rem; }
.page-head h1 { font-size: clamp(1.6rem, 4vw, 2.1rem); }

/* ------------------------------ Credits --------------------------------- */
.credit-balance { display: flex; flex-direction: column; gap: 0.15rem; margin-bottom: 1rem; }
.credit-amount { font-size: clamp(2rem, 6vw, 2.6rem); font-weight: 800; line-height: 1.1; letter-spacing: -0.02em; }
.credit-presets { display: grid; grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); gap: 0.6rem; }
.credit-preset {
    position: relative; display: flex; flex-direction: column; gap: 0.1rem; cursor: pointer; text-align: center;
    padding: 0.7rem 0.5rem; border: 1px solid var(--border-strong); border-radius: var(--radius);
    background: var(--input-bg); transition: border-color 0.12s ease, background 0.12s ease;
}
.credit-preset:hover { border-color: var(--brand); }
.credit-preset input { position: absolute; opacity: 0; width: 0; height: 0; }
/* Selected highlight via :has() in modern browsers; the input stays visually hidden regardless. */
.credit-preset:has(input:checked) { border-color: var(--brand); background: var(--brand-soft); }
.credit-preset:focus-within { outline: 2px solid var(--ring); outline-offset: 2px; }
.credit-preset-amt { font-weight: 700; }
.credit-preset-req { font-size: 0.8rem; color: var(--text-muted); }
/* The custom-amount entry is a single dollar figure — don't let it stretch full-width like a normal field. */
.credit-custom .field-input { max-width: 12rem; }

/* "We ❤️ Ukraine" — a subtle landing-page ribbon. It holds hidden, then gently rises + fades in ~0.8s after
   paint. STICKY, not fixed (deliberately): a sticky element stays in normal flow, so it reserves its own height
   at the end of <main> and DOCKS just above the footer at the very bottom of the page instead of floating over
   the footer copy — clearing it with zero JavaScript and zero magic numbers (the reserved space is always
   exactly the panel's height, at any OS text size / however the sub-text wraps). While you scroll the page it
   stays pinned to the viewport bottom (bottom: 1.25rem); on reaching the end it settles into flow above the
   footer. If `position: sticky` is ever unsupported it degrades to `static` — still in flow, still no overlap.
   On desktop it right-aligns to the content area's inline-END: margin-inline-start:auto pushes it to the end and
   margin-inline-end matches the centred .container's inline-end edge (max-width 1120px + 1.25rem) so it lines up
   under the footer's Contact link; logical margins keep it tracking the footer in RTL. `100%` (not 100vw) is the
   scrollbar-excluded ICB, matching how .container centres; the max() clamps to a 1.25rem inset below 1120px. */
.ua-ribbon {
    position: sticky; bottom: 1.25rem; z-index: var(--z-fixed);
    margin-inline-start: auto; margin-inline-end: max(1.25rem, calc((100% - 1120px) / 2 + 1.25rem));
    display: flex; width: fit-content; align-items: center; gap: 0.7rem;
    max-width: min(20rem, calc(100vw - 2.5rem));
    padding: 0.6rem 0.9rem; background: var(--surface); color: var(--text); text-decoration: none;
    border: 1px solid var(--border); border-radius: var(--radius); box-shadow: var(--shadow);
    animation: ua-ribbon-in 0.6s cubic-bezier(0.2, 0.7, 0.2, 1) 0.8s both;
    transition: transform 0.15s ease, box-shadow 0.15s ease;
}
.ua-ribbon:hover { transform: translateY(-2px); box-shadow: var(--shadow-lg); text-decoration: none; }
.ua-ribbon-flag { flex: none; height: 1.5rem; width: auto; border-radius: 3px; box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.08); }
/* min-width:0 lets the text column shrink/wrap inside the flex row instead of forcing overflow. */
.ua-ribbon-text { display: flex; flex-direction: column; line-height: 1.25; min-width: 0; }
.ua-ribbon-text strong { font-size: 0.95rem; font-weight: 700; }
.ua-ribbon-sub { font-size: 0.8rem; color: var(--text-muted); }

@keyframes ua-ribbon-in {
    from { opacity: 0; transform: translateY(12px); }
    to   { opacity: 1; transform: translateY(0); }
}
@media (prefers-reduced-motion: reduce) {
    .ua-ribbon { animation: none; }            /* present immediately, no motion */
    .ua-ribbon:hover { transform: none; }
}
/* Narrow viewports (em-based so the switch fires earlier under OS text-zoom): centre the panel rather than
   tuck it right, and KEEP the sub-text — margin-inline:auto (overriding the base's start:auto/end:inset) centres
   the in-flow sticky panel without a transform, so it doesn't fight the entrance/hover translate. */
@media (max-width: 35em) {
    .ua-ribbon { margin-inline: auto; bottom: 0.75rem; }
}

/* UK site only: a quiet "Hosted in the UK" pill in the hero (reuses the gentle ua-ribbon-in entrance). */
.uk-hosted {
    display: flex; width: fit-content; margin: 0.6rem auto 0; align-items: center; gap: 0.45rem;
    padding: 0.3rem 0.75rem; font-size: 0.85rem; color: var(--text-muted);
    background: var(--surface-2); border: 1px solid var(--border); border-radius: var(--radius-pill);
    animation: ua-ribbon-in 0.6s cubic-bezier(0.2, 0.7, 0.2, 1) 0.4s both;
}
.uk-hosted-flag { height: 0.95rem; width: auto; border-radius: 2px; box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.08); }
@media (prefers-reduced-motion: reduce) { .uk-hosted { animation: none; } }
.credit-neg { font-variant-numeric: tabular-nums; }
.credit-pos { color: var(--success); font-weight: 600; font-variant-numeric: tabular-nums; }

/* ===================== Settings hub ===================== */
.settings {
    /* ONE source of truth for the gap between the header and the top of both columns: the page's own padding-top
       AND the sidebar's sticky offset read this var. When they differed (padding up to 2rem vs a fixed 1.25rem
       sticky top), the sidebar visibly slid UP by the difference the moment it pinned — the owner-reported
       "master scrolls slightly when the detail scrolls". Same var ⇒ resting position == pinned position. */
    --settings-gap-top: clamp(1.25rem, 3vw, 2rem);
    display: grid;
    grid-template-columns: 240px minmax(0, 1fr);
    gap: 2rem;
    align-items: start;
    width: 100%;
    max-width: 1080px;
    margin-inline: auto;
    padding: var(--settings-gap-top) 1.25rem 3rem;
}
.settings-sidebar {
    /* Sticky on the WHOLE panel (the "Search settings" input AND the nav links). It sits BELOW the sticky
       .app-header so the input doesn't tuck up behind it; align-self:start keeps it from stretching to the grid
       row's height (so sticky has somewhere to travel); max-height + overflow-y let the panel scroll WITHIN
       itself when it genuinely exceeds the viewport (e.g. high text zoom) so every link stays reachable.
       The clip is EXACTLY the space below the pinned top (one shared var, so top and max-height can't drift):
       an extra reserved bottom gap here made the panel internally scrollable by that gap's height even when its
       content fit the viewport (owner-reported phantom scroll — harness-reproduced at 10px). dvh so mobile
       URL-bar collapse doesn't mis-size it; vh fallback first. padding gives the search field's focus ring room
       inside the scroll container. */
    --settings-sticky-top: calc(var(--header-height) + var(--settings-gap-top));
    position: sticky; top: var(--settings-sticky-top); align-self: start;
    max-height: calc(100vh - var(--settings-sticky-top));
    max-height: calc(100dvh - var(--settings-sticky-top));
    overflow-y: auto; overscroll-behavior: contain;
    padding: 0.25rem;
    display: flex; flex-direction: column; gap: 1rem;
}

/* Search box */
.settings-search { position: relative; }
.settings-search-input {
    font: inherit; width: 100%; color: var(--text); background: var(--input-bg);
    border: 1px solid var(--border-strong); border-radius: var(--radius);
    padding: 0.6rem 2rem 0.6rem 0.75rem;
}
.settings-search-input:focus {
    outline: none; border-color: var(--brand);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--brand) 25%, transparent);
}
.settings-search-clear {
    position: absolute; inset-inline-end: 0.4rem; top: 50%; transform: translateY(-50%);
    border: none; background: transparent; color: var(--text-muted);
    cursor: pointer; font-size: 1rem; line-height: 1; padding: 0.3rem; border-radius: var(--radius-sm);
}
.settings-search-clear:hover { color: var(--text); background: var(--surface-2); }
/* Hide the clear affordance while the field is empty (placeholder showing). */
.settings-search-input:placeholder-shown + .settings-search-clear { display: none; }

/* Section navigation — a <details> disclosure: an INLINE rail on desktop, a DROPDOWN on handset (below the em
   breakpoint). Desktop keeps the rail inline by forcing the content visible regardless of the details' open
   state — with BOTH mechanisms, because Chromium ≥131 hides closed-<details> content through ::details-content
   (content-visibility:hidden) which author child-display alone can't override (see the details-content
   regression). The handset dropdown rules live in the em-breakpoint block below. */
.settings-nav-disclosure { display: block; }
.settings-nav-disclosure > summary { display: none; }                        /* desktop: no button; the rail is inline */
.settings-nav-disclosure::details-content { content-visibility: visible; }   /* Chromium 131+ (author beats UA) */
.settings-nav-disclosure > .settings-nav { display: flex; }                  /* pre-::details-content engines */

/* Sidebar nav */
.settings-nav { display: flex; flex-direction: column; gap: 0.15rem; }
.settings-nav-item {
    display: block; padding: 0.5rem 0.7rem; border-radius: var(--radius);
    color: var(--text-muted); font-weight: 600; font-size: 0.95rem; text-decoration: none;
    border-inline-start: 3px solid transparent;
}
/* The hidden attribute must always win: author display rules on .btn/.settings-nav-item/etc. otherwise
   override the UA `[hidden] { display:none }` and leave "hidden" elements visible. */
[hidden] { display: none !important; }
.settings-nav-item:hover { background: var(--surface-2); color: var(--text); text-decoration: none; }
/* Nested sections (the search verticals under "Search"): indented, slightly quieter — visual nesting only,
   the panes stay flat and always reachable. Logical inset ⇒ mirrors under RTL. */
.settings-nav-child { margin-inline-start: 1rem; font-size: 0.9rem; }
.settings-nav-item.active {
    background: var(--brand-soft); color: var(--brand-strong); border-left-color: var(--brand);
}

/* Panes */
.settings-main { min-width: 0; }
.settings-pane-title { font-size: 1.4rem; margin-bottom: 1rem; }
.settings-pane-title:focus { outline: none; }
.settings-group { margin-bottom: 2rem; }
.settings-group-title {
    font-size: 0.78rem; text-transform: uppercase; letter-spacing: 0.05em;
    color: var(--text-muted); margin: 1.25rem 0 0.25rem;
}
/* An alert/panel directly under a group title (e.g. the verify-email banner under PROFILE) shouldn't sit flush. */
.settings-group-title + .alert { margin-block-start: 0.9rem; }
.settings-actions { margin-top: 1.5rem; }
/* A pane's posted form (…ending in its Save button) never crowds the standalone rows that follow it —
   the Search pane's Filtering form is trailed by the Custom Ranking / Views / Snaps run. */
.settings-form { margin-block-end: 1.25rem; }
.settings-inline-form { display: flex; gap: 0.5rem; flex-wrap: wrap; align-items: center; }
.settings-inline-form .field-input { flex: 1 1 14rem; width: auto; }

/* A single setting row: stacks by default (works for tables/forms); simple single-control rows go inline. */
.setting-row {
    display: flex; flex-direction: column; gap: 0.6rem;
    padding: 1.5rem 0; border-bottom: 1px solid var(--border);
}
.setting-row:last-child { border-bottom: none; }
.setting-row-label { font-weight: 600; }
.setting-row-desc { font-size: 0.85rem; color: var(--text-muted); margin: 0.1rem 0 0; }
.setting-row-control { min-width: 0; }
/* A conditionally-shown row (e.g. the custom citation template, shown only for the Custom style). display:none so
   the control stays in the DOM — its value is preserved and still posts — while overriding the row's flex display. */
.setting-row.is-hidden { display: none; }
.setting-row:has(> .setting-row-control > .toggle:only-child),
.setting-row:has(> .setting-row-control > .field-select:only-child),
.setting-row:has(> .setting-row-control > .segmented:only-child),
.setting-row:has(> .setting-row-control > .v:only-child) {
    flex-direction: row; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 0.5rem 1.5rem;
}
.setting-row:has(> .setting-row-control > .toggle:only-child) .setting-row-info,
.setting-row:has(> .setting-row-control > .field-select:only-child) .setting-row-info,
.setting-row:has(> .setting-row-control > .segmented:only-child) .setting-row-info,
.setting-row:has(> .setting-row-control > .v:only-child) .setting-row-info { flex: 1 1 16rem; }
.setting-row .field-select { width: auto; min-width: 13rem; max-width: 100%; }
/* Compact variant for short numeric values (e.g. Results per page) — the full 13rem reads as empty space. */
.setting-row .field-select-narrow { min-width: 6.5rem; }

/* Display-language rotator: the ui-language row's description slot — the phrase "Display language" cycling through
   the non-current languages (LanguageNameRotator.razor + 61-ui-language-rotator.ts). Same voice as
   .setting-row-desc; items are STACKED absolutely inside a one-line-reserved box so the crossfade never reflows the
   row, and inset-inline keeps them start-aligned under RTL. Crossfade only when motion is allowed — under reduced
   motion (or no JS) exactly one phrase sits there statically. */
.lang-rotator {
    position: relative; min-height: 1.35em;
    font-size: 0.85rem; color: var(--text-muted); margin: 0.1rem 0 0;
}
.lang-rotator-item {
    position: absolute; inset-inline: 0; top: 0;
    opacity: 0; visibility: hidden;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    /* Align every phrase with the PAGE's reading direction, not the phrase's own: an RTL phrase (Arabic) keeps its
       correct internal shaping via dir="rtl" but must not drift to the far edge of an LTR page (and vice versa).
       Stated physically (match-parent renders inconsistently): LTR page → left, RTL page → right. */
    text-align: left;
}
html[dir="rtl"] .lang-rotator-item { text-align: right; }
.lang-rotator-item.is-active { opacity: 1; visibility: visible; }
.lang-rotator-item.is-current { display: none; }   /* the selected language never shows its own phrase */
@media (prefers-reduced-motion: no-preference) {
    .lang-rotator-item { transition: opacity 0.55s ease, visibility 0.55s; }
}

/* Citations: custom-template editor + token help. Full-width control that reflows; the help is muted and the
   token list / worked example are monospace and allowed to wrap. The whole row is shown only for the Custom style —
   server-rendered (SettingRow Hidden) and toggled live by 62-citations-settings.ts via .setting-row.is-hidden. */
.citation-template { display: flex; flex-direction: column; gap: 0.6rem; width: 100%; min-width: 0; }
.field-textarea {
    width: 100%; min-width: 0; box-sizing: border-box; min-height: 4.5rem; resize: vertical;
    padding: 0.55rem 0.7rem; border: 1px solid var(--border); border-radius: var(--radius);
    background: var(--surface); color: var(--text);
    font-family: ui-monospace, "SF Mono", "Cascadia Code", Menlo, Consolas, monospace; font-size: 0.9rem; line-height: 1.5;
}
.field-textarea:focus { outline: none; border-color: var(--brand); box-shadow: 0 0 0 2px var(--brand-soft); }
.citation-template-help { font-size: 0.82rem; color: var(--text-muted); line-height: 1.55; }
.citation-template-help p { margin: 0 0 0.35rem; }
.citation-template-example { display: flex; flex-wrap: wrap; gap: 0.4rem; align-items: baseline; }
.citation-template-help code {
    font-family: ui-monospace, "SF Mono", "Cascadia Code", Menlo, Consolas, monospace; font-size: 0.82rem;
    background: var(--surface-2, var(--brand-soft)); padding: 0.05rem 0.35rem; border-radius: var(--radius);
    overflow-wrap: anywhere; word-break: break-word;
}

/* Brief highlight when a deep link / search result lands on a row. */
@keyframes setting-flash { from { background: var(--brand-soft); } to { background: transparent; } }
.setting-row-flash { animation: setting-flash 1.4s ease-out; border-radius: var(--radius); }

/* Auto-reload: a card-on-file row (with divider) above a clean, evenly-spaced vertical form. */
.autoreload { display: flex; flex-direction: column; gap: 1.25rem; }
.autoreload-card {
    display: flex; align-items: center; justify-content: space-between;
    gap: 1rem; flex-wrap: wrap; padding-bottom: 1.1rem; border-bottom: 1px solid var(--border);
}
.autoreload-form { display: flex; flex-direction: column; align-items: flex-start; gap: 1.1rem; }
.autoreload-form .toggle { margin: 0; }
.autoreload-form .field { margin: 0; width: 100%; max-width: 22rem; }
.autoreload-form .field-select { width: 100%; min-width: 0; }

/* Developer-access pin (Billing): toggle + Save inline, with an active-state note below. */
.developer-access { display: flex; flex-direction: column; gap: 0.75rem; align-items: flex-start; }
.developer-toggle-form { display: flex; align-items: center; gap: 1rem; flex-wrap: wrap; }

/* Search results (flat, grouped, highlighted) */
.settings-results { margin-bottom: 1.5rem; }
.settings-results-count { font-size: 0.85rem; color: var(--text-muted); margin: 0 0 0.75rem; }
.settings-result {
    display: block; padding: 0.6rem 0.75rem; border: 1px solid var(--border); border-radius: var(--radius);
    margin-bottom: 0.5rem; text-decoration: none; color: var(--text); background: var(--surface);
}
.settings-result:hover { border-color: var(--brand); text-decoration: none; }
.settings-result-breadcrumb { display: block; font-size: 0.75rem; color: var(--text-muted); }
.settings-result-label { display: block; font-weight: 600; }
.settings-results mark { background: var(--brand-soft); color: inherit; border-radius: 2px; padding: 0 1px; }

/* em breakpoint (≈760px at the default 16px root) per the OS-font reflow mandate: under Firefox-Android text-zoom
   the em threshold grows with the font, so the settings hub collapses to a single column + horizontal nav exactly
   when the enlarged text would otherwise need it (harmless on Chrome, which doesn't shift em breakpoints). */
@media (max-width: 47.5em) {
    .settings { grid-template-columns: 1fr; gap: 1rem; }
    /* Stacked single-column layout: drop the sticky pin + the viewport cap so the panel flows normally. */
    .settings-sidebar { position: static; max-height: none; overflow: visible; padding: 0; }

    /* The section rail becomes a DROPDOWN. The summary is the select-like button showing the current section;
       the nav collapses (both mechanisms) until opened, then drops down as a full-width, tappable list. This
       replaces the wrapping tab pile, which was unusable at large OS-font sizes on handset. */
    .settings-nav-disclosure > summary {
        display: flex; align-items: center; justify-content: space-between; gap: 0.5rem; cursor: pointer;
        list-style: none; padding: 0.6rem 0.85rem; border: 1px solid var(--border-strong);
        border-radius: var(--radius); background: var(--input-bg); color: var(--text);
        font-weight: 600; font-size: 0.95rem;
    }
    .settings-nav-disclosure > summary::-webkit-details-marker { display: none; }
    .settings-nav-disclosure > summary::after { content: "▾"; color: var(--text-muted); font-size: 0.8em; flex: none; }
    .settings-nav-disclosure[open] > summary::after { content: "▴"; }
    .settings-nav-disclosure > summary:focus-visible { outline: 2px solid var(--brand-strong); outline-offset: 1px; }
    .settings-nav-summary-label { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

    /* Closed ⇒ collapse. Open ⇒ the dropdown panel. */
    .settings-nav-disclosure:not([open])::details-content { content-visibility: hidden; }
    .settings-nav-disclosure:not([open]) > .settings-nav { display: none; }
    .settings-nav-disclosure[open] > .settings-nav {
        display: flex; flex-direction: column; gap: 0.1rem; margin-block-start: 0.35rem;
        padding: 0.35rem; border: 1px solid var(--border); border-radius: var(--radius);
        background: var(--surface); box-shadow: var(--shadow-lg);
    }
    /* Full-width tappable rows; the active-state uses the fill (the inset border reads oddly in a menu). */
    .settings-nav-disclosure[open] > .settings-nav .settings-nav-item { border-inline-start: 0; padding: 0.65rem 0.7rem; }
    .settings-nav-disclosure[open] > .settings-nav .settings-nav-item.active { border-inline-start: 0; }
    .settings-nav-disclosure[open] > .settings-nav .settings-nav-child { margin-inline-start: 1.25rem; }

    /* Pane-content reflow at large OS-font: the select's desktop 13rem floor (= 390px at a 30px root) overflows
       a handset viewport — let selects fill the column instead. And let long-labeled action buttons wrap rather
       than force horizontal scroll (the reflow mandate). */
    .setting-row .field-select, .setting-row .field-select-narrow { min-width: 0; }
    .settings .btn { white-space: normal; max-inline-size: 100%; }

    /* A segmented control (theme / text-size) can't shrink its worded options, so at large OS-font its row
       STACKS (label above a full-width control) and the control scrolls horizontally within its OWN box rather
       than wrapping "System" off "Light/Dark" (owner-reported) or pushing the page. The options stay one line,
       together. */
    .setting-row:has(> .setting-row-control > .segmented:only-child) { flex-direction: column; align-items: stretch; }
    .setting-row .setting-row-control:has(> .segmented) { inline-size: 100%; }
    .setting-row .segmented { max-inline-size: 100%; overflow-x: auto; }
}
@media (prefers-reduced-motion: reduce) {
    .setting-row-flash { animation: none; }
}

/* Results-page time-range filter chips (wrap freely per the responsive/text-scaling guidance). */
.search-tools { display: flex; flex-wrap: wrap; gap: 0.4rem; margin: 0; }   /* spacing owned by .results-controls */
.search-tool {
    font-size: 0.8125rem; color: var(--text-muted); text-decoration: none; white-space: nowrap;
    padding: 0.3rem 0.7rem; border-radius: var(--radius-pill); border: 1px solid transparent;
}
.search-tool:hover { background: var(--surface-2); color: var(--text); }
.search-tool.active { background: var(--brand-soft); color: var(--brand-strong); font-weight: 600; }
/* Handset: the time pills collapse into ONE dropdown (pills⇄menu swap at the same 34em breakpoint as
   the nav/anchored takeover). The items are the same links as the pills; the "N filters" pushbutton is
   NOT a time chip and stays in the row at every width. Hidden by default — desktop keeps the pills. */
.time-menu { display: none; position: relative; }
.time-menu-btn {
    display: inline-flex; align-items: center; gap: 0.3rem; cursor: pointer; list-style: none;
    background: var(--surface-2); color: var(--text);
}
.time-menu-btn::-webkit-details-marker { display: none; }
.time-menu-btn::marker { content: ""; }
.time-menu[open] > .time-menu-btn { background: var(--brand-soft); color: var(--brand-strong); }
.time-menu-btn:focus-visible { outline: 2px solid var(--brand-strong); outline-offset: 1px; }
.time-menu-caret { font-size: 0.7em; }
.time-menu-panel {
    position: absolute; inset-block-start: calc(100% + 0.35rem); inset-inline-start: 0; z-index: 45;
    min-inline-size: min(11rem, calc(100vw - 1.5rem));   /* viewport-capped — see .search-plus-menu */
    background: var(--surface, #fff); color: var(--text, #19172a);
    border: 1px solid var(--border, #ddd); border-radius: var(--radius);
    box-shadow: var(--shadow-lg, 0 16px 48px rgba(16,12,40,.16));
    padding: 0.35rem; display: flex; flex-direction: column; gap: 0.05rem;
}
.time-menu-item { padding: 0.45rem 0.55rem; border-radius: var(--radius-sm, 6px); color: var(--text); text-decoration: none; }
.time-menu-item:hover, .time-menu-item:focus { background: var(--surface-2); outline: none; }
.time-menu-item:focus-visible { outline: 2px solid var(--brand-strong); outline-offset: -2px; }
.time-menu-item[aria-current="true"] { font-weight: 600; color: var(--brand-strong); }
@media (max-width: 34em) {
    .search-tools > .search-tool:not(.search-tool-filters) { display: none; }
    .time-menu { display: inline-flex; }
    .search-tool-filters { margin-inline-start: 0.85rem; }   /* the wide set-off reads odd next to one pill */
    /* The presentation seg drops its labels (icons + title/aria stay) so the whole controls row —
       time menu, filters chip, seg — fits one line at phone widths and large text. */
    .results-controls .view-opt > span { display: none; }
    .results-controls .view-opt { padding-inline: 0.45rem; }
    /* Inside the controls row the tools nav is a shrink-wrapped flex item, so it can no longer serve
       as the panel-spanning context — hoist that role one level: the CONTROLS ROW becomes the
       positioning context and the time-menu panel (inset-inline: 0, the trick above) spans the full
       row width whatever the flex line composition. */
    .results-controls { position: relative; }
    .results-controls > .search-tools { position: static; }
    /* Handset: dropdown panels SPAN their container instead of hugging their button — a left-anchored
       compact panel protrudes past the viewport at large text (and Chromium keeps a CLOSED details'
       content box in layout, so it phantom-overflows even shut). The row/pill is the positioning
       context; the panel inherits its width, which fits the viewport by construction at any zoom. */
    .search-tools { position: relative; }
    .time-menu { position: static; }
    .search-pill { position: relative; }
    .search-plus { position: static; }
    /* min-inline-size: 0 — the container span IS the size here; a min floor would override the
       pinned inset-inline edges and push the panel past the viewport at large text. */
    .time-menu-panel, .search-plus-menu { inset-inline: 0; min-inline-size: 0; }
}

/* Per-search vertical filter bar (Images/News/Videos results) — mirrors .search-tools; compact labelled
   `field-select` dropdowns + a "More filters" disclosure for the image long-tail. Reflows freely (text-scaling). */
.search-filters { display: flex; flex-wrap: wrap; align-items: center; gap: 0.4rem; margin: 0; }   /* spacing owned by .results-controls */
.search-filter-field { display: inline-flex; min-width: 0; }
.search-filters .field-select { font-size: 0.8125rem; padding: 0.3rem 1.9rem 0.3rem 0.65rem; min-width: 0; }
.search-filters-more { display: inline-block; min-width: 0; }
.search-filters-more > summary {
    list-style: none; cursor: pointer; display: inline-flex; align-items: center; gap: 0.3rem;
    font-size: 0.8125rem; color: var(--text-muted); white-space: nowrap;
    padding: 0.3rem 0.7rem; border-radius: var(--radius-pill); border: 1px solid var(--border-strong);
}
.search-filters-more > summary::-webkit-details-marker { display: none; }
.search-filters-more > summary::after { content: "▾"; font-size: 0.7em; }
.search-filters-more[open] > summary { color: var(--text); background: var(--surface-2); }
.search-filters-more-row { display: flex; flex-wrap: wrap; gap: 0.4rem; margin-top: 0.45rem; }
.search-filters-apply {
    font-size: 0.8125rem; white-space: nowrap; cursor: pointer; color: var(--text);
    padding: 0.3rem 0.8rem; border-radius: var(--radius-pill); border: 1px solid var(--border-strong); background: var(--surface-2);
}
.search-filters-clear { font-size: 0.8125rem; color: var(--text-muted); text-decoration: none; white-space: nowrap; padding: 0.3rem 0.5rem; }
.search-filters-clear:hover { color: var(--text); text-decoration: underline; }

/* ===== Search Control (domain ranking): per-result chip + popover, transparency bar, settings rules ===== */
.rank-control, .rank-adjust { position: relative; display: inline-block; margin-block-start: 0.35rem; }
.rank-control > summary, .rank-adjust > summary { list-style: none; }
.rank-control > summary::-webkit-details-marker, .rank-adjust > summary::-webkit-details-marker { display: none; }
.rank-chip {
    display: inline-flex; align-items: center; justify-content: center; font-size: 0.75rem; cursor: pointer;
    color: var(--text); background: transparent; border: 1px solid var(--border-strong); border-radius: var(--radius-pill);
    padding: 0.2rem 0.5rem; line-height: 1.4; min-inline-size: 1.9rem; min-block-size: 1.7rem;
}
.rank-chip:hover, .rank-adjust[open] > .rank-chip, .rank-control[open] > .rank-chip { background: var(--surface-2); }
.rank-chip-neutral:hover, .rank-kebab-chip:hover { color: var(--text); }
.rank-chip:focus-visible { outline: 2px solid var(--brand-strong); outline-offset: 1px; }
.rank-chip-kebab::before { content: "⋮"; font-weight: 900; font-size: 1.05rem; line-height: 1; }

/* Windows High Contrast / forced-colors: the mask-image state icons (background-color:currentColor) and the color-mix
   "active"/magnitude tints are neutralized by the forced palette — restore a visible marker (WCAG 1.4.11). */
@media (forced-colors: active) {
    .rank-state-ic { background-color: CanvasText; }
    .view-opt.active, .rd-seg-opt.active, .rd-toggle.active { outline: 2px solid Highlight; outline-offset: -2px; }
    .rd-toggle.mixed { outline: 2px dashed Highlight; outline-offset: -2px; }
}
/* Coarse pointers (touch): keep the compact chips + segmented controls ≥24px hittable (WCAG 2.5.8 AA), while staying
   visually tight on a fine pointer (mouse). */
@media (pointer: coarse) {
    .rank-chip { min-block-size: 1.55rem; padding-block: 0.3rem; }
    .rd-seg-opt, .rd-move, .rd-toggle { min-block-size: 1.55rem; }
    .result-sitelink { padding-block: 0.15rem; }
}

/* The rank-adjust INDICATOR (left of the ⋮ kebab) = "where you initiate ranking changes for this site". Its icon is a
   monochrome SVG mask tinted by the chip's `color`; each state sets the icon + colour, and for raised/lowered the
   colour interpolates faint→vivid across the stored weight magnitude (--w = 0..100, set inline from the rule weight). */
.rank-state-ic { display: inline-block; width: 1.05em; height: 1.05em; background-color: currentColor;
    -webkit-mask: var(--ic) center / contain no-repeat; mask: var(--ic) center / contain no-repeat; }
.rank-adjust-chip { color: var(--text-muted);   /* neutral: the tune-sliders "adjust" affordance */
    --ic: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cline x1='4' y1='7' x2='20' y2='7'/%3E%3Ccircle cx='10' cy='7' r='2.4' fill='%23000' stroke='none'/%3E%3Cline x1='4' y1='16' x2='20' y2='16'/%3E%3Ccircle cx='15' cy='16' r='2.4' fill='%23000' stroke='none'/%3E%3C/svg%3E"); }
.rank-adjust-chip.rank-chip-raised { border-color: currentColor;
    color: color-mix(in oklab, #7be3a6, #047857 calc(var(--w) * 1%));
    --ic: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cline x1='12' y1='19' x2='12' y2='5'/%3E%3Cpolyline points='6 11 12 5 18 11'/%3E%3C/svg%3E"); }
.rank-adjust-chip.rank-chip-lowered { border-color: currentColor;
    color: color-mix(in oklab, #fca5a5, #b91c1c calc(var(--w) * 1%));
    --ic: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cline x1='12' y1='5' x2='12' y2='19'/%3E%3Cpolyline points='6 13 12 19 18 13'/%3E%3C/svg%3E"); }
/* Pinned: the 📌 stands ALONE — no oval drawn around it at all: border transparent (not none, so
   the geometry and the ≥24px hit target stay identical) AND no resting background plate, including
   the tools-row surface plate below. Hover/open/focus affordances remain: the hover background and
   the focus-visible ring still show it's the Adjust control. */
.rank-adjust-chip.rank-chip-pinned,
.result-card-tools .rank-chip.rank-chip-pinned { border-color: transparent; background: transparent; }
.rank-adjust-chip.rank-chip-pinned:hover,
.rank-adjust[open] > .rank-adjust-chip.rank-chip-pinned { background: var(--surface-2); }
.rank-adjust-chip.rank-chip-pinned .rank-state-ic { -webkit-mask: none; mask: none; background: none; width: auto; height: auto; }
.rank-adjust-chip.rank-chip-pinned .rank-state-ic::before { content: "📌"; font-size: 0.92em; line-height: 1; }
.rank-adjust-chip.rank-chip-blocked { color: var(--text-muted);   /* eye-off — shown when viewing hidden items */
    --ic: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M9.9 4.24A9.12 9.12 0 0 1 12 4c7 0 10 8 10 8a18.5 18.5 0 0 1-2.16 3.19m-6.72-1.07a3 3 0 1 1-4.24-4.24'/%3E%3Cpath d='M6.61 6.61A18.5 18.5 0 0 0 2 12s3 8 10 8a9.12 9.12 0 0 0 5.06-1.44'/%3E%3Cline x1='2' y1='2' x2='22' y2='22'/%3E%3C/svg%3E"); }
.rank-menu {
    position: absolute; inset-block-start: calc(100% + 0.25rem); inset-inline-end: 0; z-index: 40; min-width: min(14rem, calc(100vw - 1.5rem)); max-inline-size: min(14rem, calc(100vw - 1.5rem));
    background: var(--surface, #fff); color: var(--text, #19172a); border: 1px solid var(--border, #ddd); border-radius: var(--radius);
    box-shadow: var(--shadow-lg, 0 8px 28px rgba(0,0,0,.18)); padding: 0.35rem; display: flex; flex-direction: column;
}
.rank-menu-host { font-size: 0.75rem; color: var(--text-muted); padding: 0.25rem 0.5rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rank-act { margin: 0; }
.rank-menu-item {
    display: flex; align-items: center; gap: 0.45rem; inline-size: 100%; text-align: start; background: transparent;
    border: 0; cursor: pointer; padding: 0.4rem 0.5rem; border-radius: var(--radius-sm, 6px); color: var(--text);
    font-size: 0.875rem; text-decoration: none;
}
.rank-menu-item:hover, .rank-menu-item:focus { background: var(--surface-2); outline: none; }
.rank-menu-item:focus-visible { outline: 2px solid var(--brand-strong); outline-offset: -2px; }
.rank-item[aria-checked="true"] { font-weight: 600; color: var(--brand-strong); }
.rank-link::before { content: ""; inline-size: 0.95rem; flex: none; text-align: center; color: var(--text-muted); }
.rank-link[href*="archive.org"]::before { content: "🏛"; }
.rank-link:not([href*="archive.org"])::before { content: "⌕"; font-weight: 700; }
.rank-sep { block-size: 1px; background: var(--border); margin: 0.35rem 0.25rem; }
.rank-group-label { font-size: 0.68rem; text-transform: uppercase; letter-spacing: 0.04em; color: var(--text-muted); padding: 0.25rem 0.5rem 0.15rem; }
.rank-more { font-size: 0.75rem; color: var(--text-muted); border-block-start: 1px solid var(--border); margin-block-start: 0.25rem; }
.rank-more:hover { color: var(--text); }
/* Translate affordance — shown only when a result's detected language differs from the user's UI language. */
.result-translate {
    display: inline-flex; align-items: center; gap: 0.3rem; font-size: 0.7rem; color: var(--text-muted); cursor: pointer;
    text-decoration: none; margin-inline-start: 0.4rem; border: 1px solid var(--border); border-radius: var(--radius-pill); padding: 0.03rem 0.45rem;
}
.result-translate:hover { color: var(--text); background: var(--surface-2); }
.result-translate::before { content: "🌐"; font-size: 0.85em; display: inline-block; }
/* In-flight: the icon pulses and stops taking clicks; the text about to change shimmers gently (33-result-translate.ts). */
.result-translate.xlate-busy { pointer-events: none; }
.result-translate.xlate-busy::before { animation: xlate-pulse 0.9s ease-in-out infinite; }
.xlate-pending { animation: xlate-pulse 0.9s ease-in-out infinite; }
@keyframes xlate-pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.45; } }
/* The swapped text lands with a soft fade. */
.xlate-swap { animation: xlate-in 0.3s ease; }
@keyframes xlate-in { from { opacity: 0.25; } to { opacity: 1; } }
/* Post-translate attribution + reversible toggle (replaces the icon after an in-place translation). */
.result-translated { display: inline-flex; align-items: center; gap: 0.45rem; font-size: 0.7rem; color: var(--text-muted); margin-inline-start: 0.4rem; }
.result-translate-toggle {
    display: inline-flex; align-items: center; font: inherit; font-size: 0.7rem; color: var(--text-muted); cursor: pointer;
    background: none; border: 1px solid var(--border); border-radius: var(--radius-pill); padding: 0.03rem 0.45rem;
}
.result-translate-toggle:hover { color: var(--text); background: var(--surface-2); }
/* Designer strip in-place feedback: a saved/new card pulses; a deleted card collapses out. */
.rd-card-flash { animation: rd-card-flash 1.5s ease; }
@keyframes rd-card-flash {
    0% { outline: 2px solid var(--brand); outline-offset: 2px; }
    70% { outline: 2px solid var(--brand); outline-offset: 2px; }
    100% { outline: 2px solid transparent; outline-offset: 2px; }
}
.rd-card-removing { animation: rd-card-out 0.22s ease forwards; pointer-events: none; }
@keyframes rd-card-out { to { opacity: 0; transform: scale(0.96); } }
@media (prefers-reduced-motion: reduce) {
    .result-translate.xlate-busy::before, .xlate-pending, .xlate-swap { animation: none; }
    .rd-card-flash, .rd-card-removing { animation: none; }
}
/* Overlay container — lets a kebab sit on an <a>-wrapped vertical card without nesting interactive elements. */
.result-card { position: relative; }
.result-card-tools { position: absolute; inset-block-start: 0.35rem; inset-inline-end: 0.35rem; z-index: 5; margin: 0; display: inline-flex; align-items: center; gap: 0.2rem; }
.result-card-tools .rank-control, .result-card-tools .rank-adjust { margin: 0; }
.result-card-tools .rank-chip { background: var(--surface); }
/* On dense image cells the kebab is revealed on hover/focus (keyboard-reachable), to avoid grid clutter. */
.image-cell-wrap { position: relative; display: block; }
.image-cell-wrap .result-card-tools { opacity: 0; transition: opacity 0.12s ease; }
.image-cell-wrap:hover .result-card-tools,
.image-cell-wrap:focus-within .result-card-tools,
.image-cell-wrap .rank-control[open] { opacity: 1; }
/* A ranked image (pinned/raised/lowered/blocked) always shows its kebab, so its state indicator is visible without
   hover — the hover-reveal governs only neutral cells (keeps the dense grid clean). */
.image-cell-wrap:has(.rank-chip-pinned, .rank-chip-raised, .rank-chip-lowered, .rank-chip-blocked) .result-card-tools { opacity: 1; }
@media (hover: none) { .image-cell-wrap .result-card-tools { opacity: 1; } }
/* Raise the result whose kebab menu is OPEN above the following results, so its popup is never overlapped by
   later result text (each .result-item/.result-card is position:relative, so without this the open menu — capped
   inside its own stacking context — is painted under subsequent siblings). */
.result-item:has(.rank-control[open]),
.result-card:has(.rank-control[open]),
.image-cell-wrap:has(.rank-control[open]) { z-index: 50; }
/* Active search-scope filter chips (e.g. a site: restriction) — one-tap removable. */
.active-filters { display: flex; flex-wrap: wrap; gap: 0.4rem; margin: 0 0 0.85rem; }
.filter-chip {
    display: inline-flex; align-items: center; gap: 0.4rem; font-size: 0.8125rem; text-decoration: none; color: var(--text);
    background: var(--surface-2, #f3efe4); border: 1px solid var(--border); border-radius: var(--radius-pill); padding: 0.2rem 0.65rem;
}
.filter-chip:hover { background: var(--surface, #fff); border-color: var(--brand); }
.filter-chip-x { font-weight: 700; color: var(--text-muted); line-height: 1; }
.filter-chip:hover .filter-chip-x { color: var(--brand); }
.rank-summary { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem; font-size: 0.8125rem; margin: 0.25rem 0 0.75rem; }
.rank-summary-part { white-space: nowrap; }
.rank-summary-part + .rank-summary-part::before { content: "·"; margin-inline: 0.5rem 0.5rem; color: var(--text-muted); }   /* both sides — Razor strips inter-part whitespace (the mirror of the .rank-summary-by fix) */
/* "by your rules" trails the count parts inside the (inline) .rank-summary-text. Razor strips the source
   whitespace after the final conditional part block, so without this the words collide ("…raisedby your
   rules"). A logical-start margin restores the space deterministically and stays correct in RTL —
   0.35em (not rem): a hair wider than the font's own word space, so it always READS as one. */
.rank-summary-by { margin-inline-start: 0.35em; }
.rank-reveal summary { cursor: pointer; color: var(--brand-strong); }
.rank-blocked-list { list-style: none; margin: 0.35rem 0 0; padding: 0; display: flex; flex-direction: column; gap: 0.25rem; }
.rank-blocked-row { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem; font-size: 0.8125rem; }
.rank-blocked-host { font-weight: 500; min-width: 0; overflow-wrap: anywhere; }
.rank-unblock { background: transparent; border: 1px solid var(--border); border-radius: var(--radius-pill); padding: 0.1rem 0.5rem; cursor: pointer; color: var(--text-muted); font-size: 0.75rem; }
.rank-unblock:hover { color: var(--text); background: var(--surface-2); }
.rank-why { font-size: 0.7rem; color: var(--text-muted); margin-inline-start: 0.4rem; }
.rank-why-pinned { color: var(--brand-strong); }
/* Malicious-domain consumer (highlight mode): a restrained in-flow "Flagged" affordance on a result, and the
   "N results removed" notice in remove mode. Danger accent, but understated; reflow-friendly (rem, flex-wrap,
   min-width:0). NEVER names a feed/source. */
.malicious-flagged { border-inline-start: 3px solid var(--danger, #b42318); padding-inline-start: 0.6rem; }
.malicious-warning { display: flex; flex-wrap: wrap; align-items: center; gap: 0.35rem; margin: 0.1rem 0 0.15rem; font-size: 0.75rem; color: var(--danger, #b42318); }
.malicious-warning-badge { font-size: 0.85rem; line-height: 1; }
.malicious-warning-text { font-weight: 600; min-width: 0; cursor: help; }
.malicious-removed { display: flex; flex-wrap: wrap; align-items: center; gap: 0.4rem; font-size: 0.8125rem; color: var(--text-muted); margin: 0.25rem 0 0.75rem; }
.malicious-removed-icon { color: var(--danger, #b42318); }
.malicious-removed-count { font-weight: 600; color: var(--text); }
/* Inline (vertical) flag variant: sits in a card meta row without the block's vertical margins; flex-wraps so the card still reflows at large text. */
.malicious-warning-inline { display: inline-flex; margin: 0; }
/* Image grid flag: no left bar/padding (would shift the cell) — a red ring on the thumbnail + a corner ⚠ badge. */
.image-cell-wrap.malicious-flagged { border-inline-start: 0; padding-inline-start: 0; }
.image-cell-wrap.malicious-flagged .image-cell { outline: 3px solid var(--danger, #b42318); outline-offset: -3px; }
.malicious-flag-corner { position: absolute; inset-block-start: 0.3rem; inset-inline-start: 0.3rem; z-index: 4; background: var(--danger, #b42318); color: #fff; border-radius: 4px; padding: 0 0.25rem; font-size: 0.8rem; line-height: 1.35; }
.rank-toggle { font-size: 0.8125rem; margin: 0 0 0.5rem; }
.rank-toggle-link { color: var(--text-muted); text-decoration: none; }
.rank-toggle-link:hover { color: var(--text); text-decoration: underline; }
/* The "N filters" pushbutton — rides the time-chips row, set off from the chips by a wider gap.
   Pressed (aria-pressed=true) = your rules apply (the default); unpressed = this search unfiltered. */
.search-tool-filters { margin-inline-start: 1.25rem; }
.search-tool-filters[aria-pressed="true"] { background: var(--brand-soft); color: var(--brand-strong);
    border-color: var(--brand-strong); }
.search-tool-filters[aria-pressed="false"] { border-style: dashed; }

/* ---- Live rank preview: the ghost while the Adjust slider drags ---- */
/* The initiating result keeps its place under a dashed outline; a caret + translucent chip mark the
   predicted slot (overlay-positioned — nothing reflows under a held slider). Block previews as the
   fade the collapse will deliver. */
.rank-preview-source { outline: 2px dashed var(--brand-strong); outline-offset: 3px; border-radius: var(--radius-sm); }
.rank-preview-source-hidden { opacity: 0.45; }
.rank-preview-caret {
    position: absolute; inset-inline: 0.25rem; height: 2px; border-radius: 1px;
    background: var(--brand-strong); z-index: 24; pointer-events: none;
    transition: top 0.16s ease;
}
.rank-preview-caret::before {
    content: ""; position: absolute; inset-inline-start: -0.25rem; top: -3px;
    width: 8px; height: 8px; border-radius: 50%; background: var(--brand-strong);
}
.rank-preview-ghost {
    position: absolute; inset-inline-start: 1rem; transform: translateY(-50%);
    z-index: 25; pointer-events: none;
    display: flex; align-items: center; gap: 0.45rem; max-width: min(30rem, 85%);
    padding: 0.25rem 0.7rem; border: 1px dashed var(--brand-strong); border-radius: var(--radius-pill);
    background: color-mix(in srgb, var(--brand-soft) 60%, var(--surface));
    font-size: 0.8rem; color: var(--text); opacity: 0.94; box-shadow: var(--shadow-md, 0 4px 14px rgb(0 0 0 / 0.18));
    transition: top 0.16s ease;
}
.rank-preview-favicon { width: 14px; height: 14px; border-radius: 3px; flex: none; }
.rank-preview-title { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rank-preview-count { flex: none; font-weight: 700; color: var(--brand-strong); white-space: nowrap; }
/* Predicted slot outside the viewport → a fixed edge chip points the way (no auto-scroll mid-drag). */
.rank-preview-edge {
    position: fixed; inset-inline-start: 50%; transform: translateX(-50%); z-index: 70;
    padding: 0.3rem 0.85rem; border: 1px solid var(--brand-strong); border-radius: var(--radius-pill);
    background: var(--surface); color: var(--brand-strong); font-size: 0.8rem; font-weight: 700;
    box-shadow: var(--shadow-md, 0 4px 14px rgb(0 0 0 / 0.18)); pointer-events: none;
}
[dir="rtl"] .rank-preview-edge { transform: translateX(50%); }
@media (prefers-reduced-motion: reduce) {
    .rank-preview-caret, .rank-preview-ghost { transition: none; }
}
/* A result blocked IN THIS VIEW collapses to a compact, recoverable stub — the content hides, a one-line
   "host — blocked · Undo" row remains (30-searchcontrol.ts injects it and reconciles the block client-side; no
   postback, no re-render). The stub is the only visible child, so the item's height shrinks to the stub's. */
.rank-blocked-collapsed > :not(.rank-blocked-stub) { display: none; }
.rank-blocked-stub {
    display: flex; align-items: center; gap: 0.6rem; min-width: 0;
    padding: 0.45rem 0.7rem; border: 1px dashed var(--border); border-radius: 0.55rem;
    color: var(--text-muted); font-size: 0.8125rem; background: var(--surface-2, transparent);
}
.rank-blocked-stub-ic::before { content: "🚫"; font-size: 0.85em; line-height: 1; opacity: 0.7; }
.rank-blocked-stub-host { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rank-stub-undo { background: transparent; border: 0; color: var(--brand-strong); cursor: pointer; font-weight: 600; font-size: 0.8125rem; padding: 0; margin-inline-start: auto; white-space: nowrap; }
.rank-stub-undo:hover { text-decoration: underline; }
.rank-stub-undo:focus-visible { outline: 2px solid var(--brand-strong); outline-offset: 2px; }
/* Blocked image cells drop their aspect-ratio sizing so the stub tile stays compact in every view mode. */
.image-cell-wrap.rank-blocked-collapsed { aspect-ratio: auto !important; height: auto !important; }
@media (forced-colors: active) { .rank-blocked-stub { border-style: solid; } }
/* A just-pinned result pulses briefly after the FLIP hoist so the eye follows where it landed. */
.rank-pin-hoisted { animation: rank-pin-glow 1.1s ease-out; }
@keyframes rank-pin-glow {
    from { background-color: color-mix(in srgb, var(--brand, #6ea8fe) 16%, transparent); }
    to { background-color: transparent; }
}
@media (prefers-reduced-motion: reduce) { .rank-pin-hoisted { animation: none; } }
.rank-toast {
    position: fixed; inset-block-end: 1.25rem; inset-inline-start: 50%; transform: translateX(-50%); z-index: 100;
    background: var(--text); color: var(--surface); border-radius: var(--radius-pill); padding: 0.5rem 1rem;
    display: flex; align-items: center; gap: 0.75rem; box-shadow: var(--shadow-lg, 0 8px 28px rgba(0,0,0,.25)); font-size: 0.875rem; max-inline-size: 90vw;
}
.rank-toast-undo { background: transparent; border: 0; color: var(--brand, #6ea8fe); cursor: pointer; font-weight: 600; }
/* Failed ranking change (didn't persist) — a warm/danger background so it reads as an error, not a confirmation. */
.rank-toast-error { background: var(--danger, #b42318); color: #fff; }
.rule-group { margin-block-end: 1rem; }
.rule-group-title { font-size: 0.875rem; margin: 0 0 0.4rem; }
.rule-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0.3rem; }
.rule-row { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem; }
.rule-pattern { font-weight: 500; min-width: 0; overflow-wrap: anywhere; }
/* A built-in view's one-line description under its name in the Settings opt-in list. */
.sc-view-desc { display: block; font-weight: 400; font-size: 0.85rem; margin-block-start: 0.1rem; max-width: 38rem; }
.rule-match { font-size: 0.75rem; }
.rule-add { display: flex; flex-wrap: wrap; gap: 0.5rem; margin-block-start: 1rem; }
/* Handset (incl. large-font text-zoom, which shrinks the em-measured viewport): the popovers become a fixed
   BOTTOM SHEET. A right-anchored absolute panel overflowed the inline-start viewport edge as soon as its
   clamped width exceeded the anchor's distance to that edge; fixed viewport insets make overflow impossible at
   any text size. Same <details> element — the existing outside-click/Escape close handling applies unchanged. */
@media (max-width: 32em) {
    .rank-menu {
        position: fixed; inset-inline: 0.75rem; inset-block-start: auto; inset-block-end: 0.75rem;
        min-width: 0; max-inline-size: none;
        max-block-size: min(75vh, calc(100dvh - 1.5rem)); overflow: auto;
        z-index: var(--z-modal, 1000);
    }
}

/* --- Search Control landing showcase ("Your results, your rules") --- */
.sc-showcase-grid{display:flex;flex-wrap:wrap;gap:2rem;align-items:center;justify-content:center;margin-top:1.5rem}
.sc-points{flex:1 1 22rem;min-width:0;list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:1rem}
.sc-points li{display:flex;gap:.75rem;align-items:flex-start}
.sc-point-ico{flex:0 0 1.75rem;text-align:center;font-size:1.25rem;line-height:1.5}
/* Raise / lower / pin: circular filled badges (1.5rem disc inside the 1.75rem column so text
   left-edges stay aligned). Saturated discs + white marks for clear contrast; hue carries the
   meaning — raise = green, lower = recessed warm-grey, pin = on-brand ink-blue (positive — NOT
   the "stop"-red of Block). The up-triangle glyph sits a hair low in its em box, so the raise
   mark is nudged up ~1px (expressed in em, so it tracks OS/browser text scaling). */
.sc-rank-badge{
  display:inline-flex;align-items:center;justify-content:center;
  width:1.5rem;height:1.5rem;border-radius:50%;
  font-size:.9rem;line-height:1;color:#fff;
}
.sc-rank-tri{display:block;line-height:1}
.sc-rank-badge--raise{background:#1c7a45}
.sc-rank-badge--raise .sc-rank-tri{transform:translateY(-0.07em)}
.sc-rank-badge--lower{background:#6b6253}
.sc-rank-badge--pin{background:#2a5d9f}
.sc-rank-pin{display:block;width:.95rem;height:.95rem;fill:#fff}
.sc-points p{margin:0}
.sc-points span{color:var(--text-muted)}
/* Decorative demo: cap to the available width (max-width:100%) and allow it to shrink (flex shrink + min-width:0)
   so the 16rem box can't force horizontal scroll at large text / narrow viewports. */
.sc-demo{flex:1 1 16rem;max-width:100%;min-width:0;display:flex;flex-direction:column;gap:.6rem;padding:1rem;border:1px solid rgba(127,127,127,.25);border-radius:.75rem}
.sc-demo-row{display:flex;align-items:center;gap:.6rem;padding:.5rem;border-radius:.5rem;background:rgba(127,127,127,.08)}
.sc-demo-dot{flex:0 0 auto;width:.7rem;height:.7rem;border-radius:50%;background:rgba(127,127,127,.4)}
.sc-demo-bar{flex:1 1 auto;height:.55rem;border-radius:.3rem;background:rgba(127,127,127,.35)}
.sc-demo-raise .sc-demo-dot{background:#2e9e5b}
.sc-demo-block .sc-demo-dot{background:#d05a4e}
@media (prefers-reduced-motion:no-preference){
  .sc-demo-block{animation:sc-fade 6s ease-in-out infinite}
  .sc-demo-raise{animation:sc-rise 6s ease-in-out infinite}
}
@keyframes sc-fade{0%,18%{opacity:1}32%,72%{opacity:.18}100%{opacity:1}}
@keyframes sc-rise{0%,18%{transform:translateY(0)}32%,72%{transform:translateY(-3.1rem)}100%{transform:translateY(0)}}
.sc-showcase-foot{text-align:center;color:var(--text-muted);max-width:52ch;margin:1.5rem auto 0}

/* ------------------------- Landing: demo theater ------------------------- */
/* Five self-playing scenes driven by 78-demo-theater.ts through [data-scene="0..4"] +
   [data-phase="type|react|hold"] on .theater — ALL choreography lives here. The rail's caption
   cards are the accessible content (real text, real buttons); the stage is aria-hidden. Sizing is
   rem/em only, rows collapse via a generous max-height cap (9rem — roomy even at 200% root font),
   the layout stacks on an em breakpoint, and BOTH reduced-motion channels (the OS media query and
   the site's html[data-motion="reduce"] toggle) drop every animation/transition — the JS holds the
   end-state, so static mode is complete, not broken. The stage forces dir="ltr" (query grammar is
   LTR, like the real box); the rail stays logical for RTL. */
.theater{display:grid;grid-template-columns:minmax(16rem,22rem) minmax(0,1fr);gap:1.25rem;max-width:64rem;margin:1.5rem auto 0;align-items:stretch}
@media (max-width:56em){
  .theater{grid-template-columns:minmax(0,1fr)}
  .theater .stage{order:-1}  /* show first, captions below — the rail reads as controls there */
}
.theater-rail{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:.5rem}
/* Spotlight model (owner, 2026-07-18 — replaced the per-step progress underline): the playing card
   sits proud — full opacity, slight scale, brand-tinted border and a soft glow — while its siblings
   recede to ~55%. The only motion is a slow halo breath on the active glyph chip: a "this one is
   alive" cue, never a countdown. Reduced motion (either channel) stills the breath; the static
   opacity/border/scale contrast still marks the active card unambiguously. */
.theater-step{position:relative;display:flex;gap:.7rem;align-items:flex-start;width:100%;text-align:start;
  padding:.7rem .85rem;border:1px solid var(--border);border-radius:var(--radius);background:var(--surface);
  cursor:pointer;color:var(--text-muted);overflow:visible;font:inherit;opacity:.55;
  transition:opacity .35s ease,transform .35s ease,border-color .35s ease,background .35s ease,box-shadow .35s ease}
.theater-step:hover{border-color:var(--border-strong);opacity:.85}
.theater-step:focus-visible{outline:2px solid var(--brand);outline-offset:2px;opacity:1}
.theater-step[aria-current="step"]{opacity:1;transform:scale(1.02);
  border-color:color-mix(in srgb,var(--brand) 45%,var(--border));background:var(--bg-elevated);color:var(--text);
  box-shadow:0 .4rem 1.5rem color-mix(in srgb,var(--brand) 16%,transparent)}
.theater-glyph{flex:none;width:1.9rem;height:1.9rem;display:flex;align-items:center;justify-content:center;
  border-radius:.55rem;background:var(--brand-soft);color:var(--brand-strong);font-weight:700;font-size:.95rem;font-family:var(--font-mono)}
.theater-step[aria-current="step"] .theater-glyph{animation:glyph-breathe 2.6s ease-in-out infinite}
@keyframes glyph-breathe{50%{box-shadow:0 0 0 .4rem color-mix(in srgb,var(--brand) 20%,transparent)}}
.theater-glyph svg{width:1.05rem;height:1.05rem}
.theater-copy{display:block;min-width:0;overflow-wrap:anywhere}  /* "@docs+week:" is one unbreakable token at 200% */
.theater-copy strong{display:block;font-size:.95rem;color:var(--text);margin-bottom:.15rem}
.theater-copy span{font-size:.85rem;line-height:1.45}

.stage{border:1px solid var(--border);border-radius:var(--radius);background:var(--surface);padding:1rem;
  display:flex;flex-direction:column;gap:.7rem;min-height:20rem;contain:content}
.stage-pill{display:flex;align-items:center;gap:.6rem;border:1px solid var(--border-strong);border-radius:var(--radius-pill);
  padding:.6rem 1rem;background:var(--bg);min-width:0}
.stage-lens{flex:none;width:1.05em;height:1.05em;color:var(--text-muted)}
.stage-q{display:flex;align-items:center;min-width:0;min-height:1.35em;font-family:var(--font-mono);font-size:.95rem;white-space:pre;overflow:hidden}
.stage-caret{flex:none;width:2px;height:1.15em;margin-inline-start:1px;background:var(--brand);animation:stage-caret 1.05s steps(1) infinite}
@keyframes stage-caret{50%{opacity:0}}

/* Context chips (snap / past-week / view) land during react and stay through hold. */
.stage-chips{display:flex;flex-wrap:wrap;gap:.4rem;min-height:2rem}
.chip{display:inline-flex;flex-wrap:wrap;align-items:center;gap:.15rem .4rem;font-size:.8rem;padding:.25rem .65rem;
  border-radius:var(--radius-pill);max-width:100%;min-width:0;
  opacity:0;transform:translateY(-.35rem);transition:opacity .3s ease,transform .3s ease}
.chip-snap em{overflow-wrap:anywhere}
.chip svg{width:.85em;height:.85em}
.chip-snap{background:var(--brand-soft);color:var(--brand-strong)}
.chip-snap b{font-weight:650}
.chip-snap em{font-style:normal;opacity:.75;font-size:.72rem}
.chip-week{background:var(--surface-2);color:var(--text);border:1px solid var(--border)}
.chip-view{background:color-mix(in srgb,#0E7C7B 15%,transparent);color:#0E7C7B}
:root[data-theme="dark"] .chip-view{color:#35A19B}
@media (prefers-color-scheme:dark){:root:not([data-theme="light"]) .chip-view{color:#35A19B}}
.theater[data-scene="1"]:is([data-phase="react"],[data-phase="hold"]) .chip-snap,
.theater[data-scene="2"]:is([data-phase="react"],[data-phase="hold"]) .chip-snap,
.theater[data-scene="2"]:is([data-phase="react"],[data-phase="hold"]) .chip-week,
.theater[data-scene="3"]:is([data-phase="react"],[data-phase="hold"]) .chip-view{opacity:1;transform:none}
.theater[data-scene="2"] .chip-week{transition-delay:.18s}

/* Mock results. Rows are skeleton bars with REAL domain lines (the honest anchor). */
.stage-body{position:relative;display:flex;flex-direction:column;gap:.55rem;flex:1}
.srow{display:grid;grid-template-columns:auto minmax(0,1fr) auto auto;align-items:center;gap:.6rem;
  border:1px solid var(--border);border-radius:.6rem;padding:.55rem .7rem;background:var(--bg-elevated);
  max-height:9rem;overflow:hidden;
  transition:opacity .45s ease,transform .5s ease,filter .45s ease,max-height .5s ease,padding .5s ease,margin .5s ease,border-color .4s ease}
.sfav{width:.9rem;height:.9rem;border-radius:.28rem;border:1px solid var(--border)}
.srow-a .sfav{background:#F57C00}
.srow-b .sfav{background:var(--surface-2)}
.srow-c .sfav{background:#0E7C7B}
.srow-d .sfav{background:#FFB25C}
.sbars{display:flex;flex-direction:column;gap:.32rem;min-width:0}
.st{height:.55rem;border-radius:var(--radius-pill);background:var(--border-strong)}
.st-a{width:62%}.st-b{width:78%}.st-c{width:55%}.st-d{width:70%}
.su{font-size:.75rem;color:var(--text-muted);font-family:var(--font-mono);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;transition:color .35s ease}
.sdate{font-size:.7rem;color:var(--text-muted);border:1px solid var(--border);border-radius:var(--radius-pill);padding:.1rem .45rem;opacity:0;transition:opacity .35s ease}
.smark{width:1.15rem;height:1.15rem;display:none;align-items:center;justify-content:center}
.smark svg{width:100%;height:100%}
.smark-up{color:#2e9e5b}
.smark-block{color:var(--danger)}
.smark-pin{color:#0E7C7B}
:root[data-theme="dark"] .smark-pin{color:#35A19B}
@media (prefers-color-scheme:dark){:root:not([data-theme="light"]) .smark-pin{color:#35A19B}}

/* Scene 1 — @docs: non-member row leaves; members' domains warm up. */
.theater[data-scene="1"]:is([data-phase="react"],[data-phase="hold"]) .srow-b,
.theater[data-scene="2"]:is([data-phase="react"],[data-phase="hold"]) .srow-b{
  opacity:0;max-height:0;padding-block:0;margin-block:-.28rem;border-color:transparent}
.theater:is([data-scene="1"],[data-scene="2"]):is([data-phase="react"],[data-phase="hold"]) :is(.srow-a,.srow-c,.srow-d) .su{color:var(--brand-strong)}

/* Scene 2 — @docs+week: dates surface, then the too-old member drops out too (the AND landing). */
.theater[data-scene="2"]:is([data-phase="react"],[data-phase="hold"]) .sdate{opacity:1}
.theater[data-scene="2"]:is([data-phase="react"],[data-phase="hold"]) .srow-d{
  opacity:0;max-height:0;padding-block:0;margin-block:-.28rem;border-color:transparent;transition-delay:.5s}

/* Scene 3 — a view re-ranks: pin to top, lift, drop the junk (order swap is FLIPped by the JS). */
.theater[data-scene="3"] .srow-c{order:-1}
.theater[data-scene="3"] .srow-b{order:5}
.theater[data-scene="3"]:is([data-phase="react"],[data-phase="hold"]) .srow-c{border-color:color-mix(in srgb,#0E7C7B 55%,var(--border))}
.theater[data-scene="3"]:is([data-phase="react"],[data-phase="hold"]) .srow-b{opacity:.35;filter:grayscale(1)}
.theater[data-scene="3"]:is([data-phase="react"],[data-phase="hold"]) .srow-c .smark-pin,
.theater[data-scene="3"]:is([data-phase="react"],[data-phase="hold"]) .srow-a .smark-up,
.theater[data-scene="3"]:is([data-phase="react"],[data-phase="hold"]) .srow-b .smark-block{display:flex;animation:smark-pop .35s ease both}
@keyframes smark-pop{from{transform:scale(.4);opacity:0}}

/* Scenes 0 and 4 — overlays that slide over the results: the bang's destination, the front-end swap. */
.soverlay{position:absolute;inset:0;border-radius:.75rem;border:1px solid var(--border);background:var(--surface);
  padding:.85rem;display:flex;flex-direction:column;gap:.6rem;opacity:0;transform:translateY(.75rem);
  transition:opacity .4s ease,transform .45s ease;pointer-events:none}
.theater[data-scene="0"]:is([data-phase="react"],[data-phase="hold"]) .soverlay-gh,
.theater[data-scene="4"]:is([data-phase="react"],[data-phase="hold"]) .soverlay-fe{opacity:1;transform:none}
.sgh-head{display:flex;align-items:center;gap:.55rem;font-family:var(--font-mono);font-size:.8rem;color:var(--text)}
.sgh-head b{font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.sgh-mono{flex:none;width:1.5rem;height:1.5rem;border-radius:50%;background:var(--text);color:var(--bg);
  display:flex;align-items:center;justify-content:center;font-weight:700;font-size:.68rem}
.sgh-row{display:flex;flex-direction:column;gap:.3rem;border:1px solid var(--border);border-radius:.55rem;padding:.55rem .7rem;background:var(--bg-elevated)}
.sgh-row b{height:.55rem;width:52%;border-radius:var(--radius-pill);background:var(--border-strong)}
.sgh-row i{height:.45rem;width:78%;border-radius:var(--radius-pill);background:var(--border)}
.sgh-row-dim{opacity:.55}
.sfe-card{position:relative;display:flex;align-items:center;gap:.7rem;border:1px solid var(--border);border-radius:.6rem;
  padding:.7rem .8rem;background:var(--bg-elevated);margin-top:auto;margin-bottom:auto}
.sfe-play{flex:none;width:2.1rem;height:2.1rem;border-radius:.5rem;background:var(--surface-2);color:var(--text);
  display:flex;align-items:center;justify-content:center}
.sfe-play svg{width:1.1rem;height:1.1rem}
.sfe-urls{position:relative;display:block;min-width:0;flex:1;min-height:1.4em}
.sfe-urls b{position:absolute;inset-inline-start:0;top:0;max-width:100%;display:inline-flex;align-items:center;gap:.4rem;
  font-family:var(--font-mono);font-size:.8rem;font-weight:500;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
  transition:opacity .4s ease,transform .4s ease}
.sfe-url-yt{color:var(--text)}
.sfe-url-fe{color:#0E7C7B;opacity:0;transform:translateY(.45rem)}
:root[data-theme="dark"] .sfe-url-fe{color:#35A19B}
@media (prefers-color-scheme:dark){:root:not([data-theme="light"]) .sfe-url-fe{color:#35A19B}}
.sfe-url-fe svg{width:.9em;height:.9em;flex:none}
.sfe-url-fe i{font-style:normal;opacity:.7}
.theater[data-scene="4"][data-phase="hold"] .sfe-url-yt{opacity:0;transform:translateY(-.45rem)}
.theater[data-scene="4"][data-phase="hold"] .sfe-url-fe{opacity:1;transform:none}
/* The click that triggers the rewrite: a small cursor ring glides to the link and pulses. */
.sfe-cursor{position:absolute;inset-inline-end:1rem;bottom:-1.4rem;width:.85rem;height:.85rem;border:2px solid var(--text);
  border-radius:50%;opacity:0}
.theater[data-scene="4"][data-phase="react"] .sfe-cursor{animation:sfe-cursor 1s ease-out forwards}
@keyframes sfe-cursor{
  0%{opacity:0;transform:translate(0,0)}
  25%{opacity:.9}
  70%{opacity:.9;transform:translate(-38%,-2.6rem) scale(1)}
  100%{opacity:0;transform:translate(-38%,-2.6rem) scale(1.7)}}
.theater-hint{text-align:center;color:var(--text-muted);max-width:54ch;margin:1.25rem auto 0}

/* ------------------------------- Ori poses ------------------------------- */
/* The brand crane as a refoldable character (OriPose.razor) — stage 1: dead ends and quiet moments.
   Decorative always (aria-hidden in the component); accessory outlines (letter/lens/creases) ride
   currentColor, so coloring the wrapper with --text-muted themes them on both grounds. */
.ori-pose{display:block;inline-size:100%;block-size:auto}
.moment-ori{inline-size:clamp(4.25rem,10vw,5.5rem);margin:0 auto 1rem;color:var(--text-muted)}
.empty-ori{display:block;inline-size:3rem;margin:0 auto .6rem;color:var(--text-muted)}
.empty-ori-start{margin-inline:0;inline-size:3.75rem;margin-block:1rem .6rem}
.settings-empty{text-align:center;padding:1.25rem 0 .5rem}
.settings-empty .muted{margin-block:0}
.results-empty-state{text-align:center;padding-block:1.5rem}
.results-empty-hint{color:var(--text-muted);font-size:.9375rem;margin-top:.35rem}

/* Sigil chip beside the Bangs (!) and Snaps (@) manage-page titles — the grammar's two characters
   as their pages' marks (same visual family as the landing theater's rail glyphs). Decorative. */
.sigil-chip{display:inline-flex;align-items:center;justify-content:center;width:1.5em;height:1.5em;
  margin-inline-end:.45em;vertical-align:-.28em;border-radius:.4em;background:var(--brand-soft);
  color:var(--brand-strong);font-family:var(--font-mono);font-weight:700;font-size:.72em}

/* Commons program page (visual pass, owner 2026-07-18): terms as check-cards, steps as a real
   numbered sequence (the numbers carry meaning — it IS a sequence), the form and sponsor blocks
   as panels so the page reads in rooms rather than one long scroll. Reflow-safe: rem paddings,
   grid gaps, logical insets (RTL), no fixed heights. */
.commons h2{margin-top:2.75rem}
.commons .page-head + h2{margin-top:1.5rem}
.commons-terms{list-style:none;padding:0;margin:1.1rem 0 0;display:grid;gap:.7rem}
.commons-terms li{position:relative;border:1px solid var(--border);border-radius:.8rem;background:var(--surface);
  padding:.85rem 1.1rem .85rem 2.7rem}
.commons-terms li::before{content:"✓";position:absolute;inset-inline-start:1.05rem;top:.82rem;
  color:#2e9e5b;font-weight:800}
[dir="rtl"] .commons-terms li{padding:.85rem 2.7rem .85rem 1.1rem}
.commons-steps{list-style:none;counter-reset:cstep;padding:0;margin:1.1rem 0 0;display:grid;gap:.7rem}
.commons-steps li{counter-increment:cstep;position:relative;border:1px solid var(--border);border-radius:.8rem;
  background:var(--surface);padding:.85rem 1.1rem .85rem 3.1rem}
.commons-steps li::before{content:counter(cstep);position:absolute;inset-inline-start:.95rem;top:.78rem;
  width:1.55rem;height:1.55rem;border-radius:50%;background:var(--brand-soft);color:var(--brand-strong);
  display:flex;align-items:center;justify-content:center;font-weight:700;font-size:.85rem}
[dir="rtl"] .commons-steps li{padding:.85rem 3.1rem .85rem 1.1rem}
.commons-form{display:flex;flex-direction:column;gap:.35rem;max-width:36rem;margin-top:1.25rem;
  border:1px solid var(--border);border-radius:1rem;background:var(--surface);padding:1.5rem}
.commons-form label{font-weight:600;margin-top:.85rem}
.commons-form label:first-child{margin-top:0}
.commons-form input,.commons-form select,.commons-form textarea{
  font:inherit;padding:.55rem .7rem;border:1px solid var(--border-strong);border-radius:.5rem;
  background:var(--bg);color:var(--text);min-width:0}
.commons-form input:focus-visible,.commons-form select:focus-visible,.commons-form textarea:focus-visible{outline:2px solid var(--brand);outline-offset:1px}
.commons-form button{margin-top:1.25rem;align-self:flex-start}
.commons-fineprint{font-size:.875rem;margin-bottom:0}
.commons-sponsor{border:1px solid var(--border);border-radius:1rem;background:var(--surface);
  padding:1.5rem;margin-top:2.75rem}
.commons-sponsor h2{margin-top:0}
.commons-sponsor .btn{margin-top:1.1rem}

/* Settings › Account service-status row (79-status-probe.ts fills latency, may set degraded). */
.status-row{display:inline-flex;align-items:center;gap:.5rem;flex-wrap:wrap;min-width:0}
.status-dot{flex:none;width:.55rem;height:.55rem;border-radius:50%;background:#2e9e5b}
.status-row[data-state="degraded"] .status-dot{background:var(--danger)}
.status-detail{font-size:.875rem;font-variant-numeric:tabular-nums}

/* Static mode: either reduced-motion channel drops every animation and transition — the JS parks
   each scene at data-phase="hold", so what remains is a complete, legible end-state per step. */
@media (prefers-reduced-motion:reduce){
  .theater *,.theater{animation:none !important;transition:none !important}
  .theater-progress{display:none}
}
:root[data-motion="reduce"] .theater,
:root[data-motion="reduce"] .theater *{animation:none !important;transition:none !important}
:root[data-motion="reduce"] .theater-progress{display:none}

/* --- Search Control Phase 2: view picker, !/@ suggest, redirect tag, settings sub-lists --- */
.search-view{min-width:0;max-width:11rem;flex:0 0 auto}
/* .sc-suggest* (the bang/snap autocomplete dropdown) now lives in the shared app.css — it is used by BOTH the public
   web app and the admin Search Diagnostics box. The one web-only positioning override stays below. */
.search-form:not(.compact) .sc-suggest{inset-inline-end:0;max-width:none}
.rank-why-redirected{opacity:.85}
.rule-row-actions{display:inline-flex;gap:.5rem;flex-wrap:wrap}
.rule-builtins{margin:.5rem 0}
.rule-builtins summary{cursor:pointer;color:var(--text-muted)}
.rule-hint{margin-top:.4rem;font-size:.9em}

/* Landing store chips — the distribution channels as uniform, NON-interactive list items (nothing
   is live yet; "Coming soon" is the honest state). Our chrome, the channels' monochrome marks;
   flex-wrap + rem basis keeps the row reflow-safe at 200% text on narrow viewports. */
.stores{list-style:none;margin:1.5rem auto 0;padding:0;display:flex;flex-wrap:wrap;gap:.75rem;justify-content:center;max-width:52rem}
.store-chip{display:inline-flex;align-items:center;gap:.7rem;padding:.65rem 1.1rem;min-width:0;
  border:1px solid var(--border);border-radius:.75rem;background:var(--surface)}
.store-glyph{flex:none;width:1.5rem;height:1.5rem;color:var(--text)}
.store-lines{display:flex;flex-direction:column;min-width:0;text-align:start}
.store-lines em{font-style:normal;font-size:.7rem;text-transform:uppercase;letter-spacing:.07em;color:var(--text-muted)}
/* Channel names may wrap ("Chrome Web Store" at 200% text on a phone) — reflow, never overflow. */
.store-lines strong{font-size:.95rem;color:var(--text)}
.store-chip{max-width:100%}

/* No horizontal scroll at ~200% text (WCAG 1.4.4 / 1.4.10): break over-long words in landing headings, card/section
   copy, and the FAQ so they wrap within their column instead of forcing a scrollbar. `anywhere` (not break-word) is
   required because the FAQ <summary> is a flex item — only `anywhere` reduces its min-content so the flex line can
   shrink. It only breaks a word that would otherwise overflow, so normal-width text is unaffected. */
.hero h1, .hero .lede,
.section-title, .section-sub,
.value-card h3, .value-card p,
.reach-item h3, .reach-item p,
.sc-points p, .sc-showcase-more, .sc-showcase-foot,
.faq summary, .faq p {
    overflow-wrap: anywhere;
}

/* --- Phase 5: LibRedirect privacy redirects (settings multi-select + result indicator). Reflow-safe:
   flex-wrap + min-width:0 + rem + bounded selects, so it stays readable at 200% text / a 360px viewport. --- */
.redirect-toolbar{display:flex;flex-wrap:wrap;gap:.5rem;margin-block:.5rem 1rem}
/* Category heading + its restrained "N on" count badge (scannability for the long service list). Reflow-safe. */
.redirect-group-title{display:flex;flex-wrap:wrap;align-items:baseline;gap:.5rem;min-width:0}
.redirect-group-count{font-size:.7rem;font-weight:700;letter-spacing:.02em;color:var(--text-muted);
  background:rgba(46,158,91,.16);border-radius:var(--radius-pill,999px);padding:.05rem .5rem;white-space:nowrap}
.redirect-list{list-style:none;margin:0 0 1rem;padding:0;display:flex;flex-direction:column;gap:.5rem}
.redirect-row{display:flex;flex-wrap:wrap;align-items:flex-start;gap:.5rem 1rem;justify-content:space-between;
  padding:.6rem .75rem;border:1px solid rgba(127,127,127,.2);border-radius:.6rem;min-width:0}
.redirect-row.is-on{border-color:rgba(46,158,91,.45);background:rgba(46,158,91,.05)}
.redirect-info{display:flex;flex-wrap:wrap;align-items:baseline;gap:.35rem .6rem;min-width:0;flex:1 1 13rem}
.redirect-name{font-weight:600}
.redirect-targets{font-size:.85em;color:var(--text-muted);overflow-wrap:anywhere}
.redirect-on{background:rgba(46,158,91,.18)}
.redirect-controls{display:flex;flex-wrap:wrap;align-items:flex-end;gap:.5rem;min-width:0;flex:1 1 18rem;justify-content:flex-end}
.redirect-config{display:flex;flex-wrap:wrap;align-items:flex-end;gap:.5rem;min-width:0}
.redirect-field{display:flex;flex-direction:column;gap:.2rem;min-width:0}
.redirect-field-label{font-size:.75rem;color:var(--text-muted)}
.redirect-field .field-select{max-width:13rem}
.redirect-resolved{flex-basis:100%;margin:.15rem 0 0;font-size:.85em}
.redirect-resolved code{overflow-wrap:anywhere}
/* The seamless layer (63-redirects.ts): Apply is redundant under JS (selects self-apply on change). */
.redirects-js [data-redirect-apply]{display:none}
/* Per-row + toolbar write status: quiet until shown; errors persist until the next attempt on that row. */
.redirect-status{font-size:.85rem;color:var(--success);opacity:0}
.redirect-status.redirect-status-show{opacity:1}
.redirect-status.is-error{color:var(--danger)}
@media (prefers-reduced-motion: no-preference){ .redirect-status{transition:opacity .2s} }
/* In-flight cue: the row dims its resolved line slightly while a write is outstanding. */
.redirect-row.is-saving .redirect-resolved{opacity:.55}

/* The privacy-redirects MODE cards: two large selectable options; the active one carries the brand ring. */
.redirect-modes, .redirect-coverage { display: grid; grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr)); gap: 0.9rem; margin: 0.75rem 0 1.4rem; }
.redirect-modes form, .redirect-coverage form { display: contents; }
a.redirect-mode-card { text-decoration: none; }
a.redirect-mode-card:hover { text-decoration: none; }
.redirect-customize { align-self: flex-start; margin-top: 0.4rem; }
div.redirect-mode-card[data-custom-selected] { cursor: default; }
.coverage-dialog { max-width: 30rem; border: 1px solid var(--border-strong); border-radius: var(--radius);
    background: var(--surface); color: var(--text); padding: 1.4rem 1.5rem;
    margin: auto; }   /* the global reset zeroes margins — restore the UA's dialog centering */
.coverage-dialog::backdrop { background: rgba(0, 0, 0, 0.55); }
.coverage-dialog h3 { margin: 0 0 0.4rem; }
.coverage-dialog-list { margin: 0.7rem 0 1rem; padding-inline-start: 1.2rem; max-height: 14rem; overflow-y: auto; }
.coverage-dialog-list li { margin: 0.25rem 0; }
.coverage-dialog-actions { display: flex; gap: 0.6rem; justify-content: flex-end; }
.redirect-mode-card { display: flex; flex-direction: column; gap: 0.3rem; text-align: start; padding: 0.9rem 1.1rem;
    background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); cursor: pointer;
    color: var(--text); font: inherit; }
.redirect-mode-card:hover { border-color: var(--border-strong); }
.redirect-mode-card.is-active { border-color: var(--brand); box-shadow: 0 0 0 1px var(--brand) inset; }
.redirect-mode-card.is-active strong::after { content: " ✓"; color: var(--brand); }
.redirect-mode-card:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }
.redirect-exceptions-title { font-size: 1.05rem; margin: 1.4rem 0 0.2rem; }
.redirect-exceptions-hint { margin: 0 0 0.8rem; font-size: 0.9rem; }

/* Tabular alignment (owner-requested): FIXED rem tracks so the Front-end / Instance / switch columns align ACROSS
   rows (content-sized flex scattered them). Only under .redirects-js (the no-JS layout keeps the proven flex flow
   with its visible Apply button) and only at desktop widths (em gate ⇒ collapses to stacking at 200% text / narrow).
   display:contents dissolves the form boxes into the row grid — forms stay fully functional (purely visual).
   Explicit column assignments ⇒ a hidden Instance field leaves its track EMPTY, so alignment holds. */
@media (min-width: 56em) {
    .redirects-js .redirect-row { display: grid; grid-template-columns: minmax(0,1fr) 13rem 15rem auto;
                                  grid-auto-rows: auto; gap: 0.4rem 1rem; align-items: center; }
    .redirects-js .redirect-controls, .redirects-js .redirect-config,
    .redirects-js .redirect-toggle { display: contents; }
    .redirects-js .redirect-info { grid-column: 1; grid-row: 1; }
    .redirects-js .redirect-config .redirect-field:first-of-type { grid-column: 2; grid-row: 1; }
    .redirects-js [data-redirect-instance-field] { grid-column: 3; grid-row: 1; }
    .redirects-js .redirect-row .switch { grid-column: 4; grid-row: 1; justify-self: end; }
    .redirects-js .redirect-resolved { grid-column: 1 / 4; grid-row: 2; margin: 0; }
    .redirects-js .redirect-status { grid-column: 4; grid-row: 2; justify-self: end; white-space: nowrap; }
    .redirects-js .redirect-field .field-select { width: 100%; max-width: none; }
}
/* the restrained inline "↪ via Invidious" indicator on a redirected result */
.result-redirect{display:inline-flex;align-items:center;gap:.25rem;font-size:.8rem;color:var(--text-muted)}
.result-redirect .result-redirect-ico{font-style:normal}

/* --- Search Control Phase 3c: compute-on-view rule suggestions (understated standing panel) --- */
.rule-suggestions-block{margin-block-start:1.25rem}
.rule-suggestions{list-style:none;margin:.4rem 0 0;padding:0;display:flex;flex-direction:column;gap:.4rem}
.rule-suggestion{display:flex;flex-wrap:wrap;align-items:center;gap:.5rem 1rem;justify-content:space-between;
  padding:.5rem .75rem;border:1px solid rgba(127,127,127,.2);border-radius:.5rem;background:rgba(127,127,127,.05)}
.rule-suggestion-body{display:flex;flex-direction:column;gap:.1rem;min-width:0;flex:1 1 16rem}
.rule-suggestion-reason{font-size:.875rem}
.rule-suggestion-proposal{font-size:.8rem}
.rule-suggestion-pattern{overflow-wrap:anywhere}
.rule-suggestion-accept{margin:0;flex:0 0 auto}
.rank-why-suggested{font-style:italic;opacity:.8}

/* ============================ Documentation platform ============================
   The docs reader as a first-class product surface. It inherits the app design system VERBATIM — global tokens
   only, no local palette — so light/dark/high-contrast/forced-colors all follow the site-wide controls with zero
   docs-specific cases. Three-column shell (nav rail · article · "On this page"), plus the modern reader kit:
   sticky self-scrolling rails, a card directory with section glyphs, scroll-spy TOC, heading copy-links, prev/next
   pagination, code blocks with copy + language tabs, tinted callouts, and a ⌘K palette with live full-text
   results. Native <details> drawers take over below the em breakpoints (reflow, never suppress, at 200% text —
   WCAG 1.4.4/1.4.10). All sizing in rem; logical properties throughout (RTL-correct). Print block at the end. */

.docs-shell{
  display:grid;
  grid-template-columns:16rem minmax(0,1fr) 13.5rem;
  gap:clamp(1.5rem,3vw,3rem);
  align-items:start;
  max-width:88rem;
  margin:0 auto;
  padding:1.75rem clamp(1rem,3vw,2rem) 4.5rem;
}
.docs-main{min-width:0}   /* lets the center column shrink instead of overflowing (min-width:auto trap) */
.docs-main h1{min-width:0}

/* The article container is a programmatic skip target (tabindex="-1" + the "Skip to article" link). Suppress the
   focus ring when it's focused that way; interactive controls inside keep their own visible rings. */
.docs-main:focus{outline:none}

/* --- Left rail: the docs nav. Sticky + self-scrolling on wide viewports (the article list outgrows a screen);
   a "Browse the docs" <details> drawer below 48em. --- */
.docs-sidebar{
  position:sticky;top:1.5rem;min-width:0;
  max-height:calc(100vh - 3rem);overflow-y:auto;overscroll-behavior:contain;
  padding-block-end:.5rem;
  scrollbar-width:thin;scrollbar-color:var(--border-strong) transparent;
}
.docs-nav-drawer > summary{list-style:none}
.docs-nav-drawer > summary::-webkit-details-marker{display:none}
.docs-nav-toggle{
  display:none;align-items:center;gap:.55rem;
  padding:.6rem .8rem;border:1px solid var(--border);border-radius:var(--radius);
  background:var(--surface);color:var(--text);cursor:pointer;font-weight:600;font-size:.9rem;
}
.docs-nav-toggle:focus-visible{outline:2px solid var(--ring);outline-offset:2px}
.docs-nav-toggle-ico{color:var(--text-muted);flex:none;font-size:1.05em}
.docs-drawer-chevron{margin-inline-start:auto;color:var(--text-subtle);flex:none;transition:transform .2s ease}
details[open] > summary .docs-drawer-chevron{transform:rotate(180deg)}
/* Wide: the drawer is inert — the summary is hidden and the nav stays visible. Two mechanisms, one per engine
   generation: author `display` on the child (pre-::details-content engines) AND an explicit
   ::details-content{content-visibility:visible} (Chromium 131+, where the closed-details hiding moved to the
   slot pseudo and child display no longer overrides it). The narrow state re-asserts the hiding below. */
.docs-nav-drawer::details-content{content-visibility:visible}
.docs-nav-drawer > .docs-nav{display:flex}

.docs-nav{flex-direction:column;gap:1.35rem;font-size:.9rem}
.docs-nav-home{
  display:block;padding:.35rem .6rem;border-radius:var(--radius-sm);
  color:var(--text-muted);text-decoration:none;font-weight:600;line-height:1.45;
}
.docs-nav-home:hover{background:var(--surface-2);color:var(--text);text-decoration:none}
.docs-nav-home.active{background:var(--brand-soft);color:var(--brand-strong)}
.docs-nav-section{display:flex;flex-direction:column;gap:.35rem}
.docs-nav-section-title{
  font-size:.68rem;text-transform:uppercase;letter-spacing:.07em;color:var(--text-subtle);
  font-weight:700;margin:0;padding-inline:.6rem;
}
.docs-nav-list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:.1rem}
.docs-nav-link{
  display:block;padding:.32rem .6rem;border-radius:var(--radius-sm);
  color:var(--text-muted);text-decoration:none;line-height:1.45;
}
.docs-nav-link:hover{background:var(--surface-2);color:var(--text);text-decoration:none}
.docs-nav-link.active{background:var(--brand-soft);color:var(--brand-strong);font-weight:600}

/* --- Index: a search-first hero (Neuji's own gesture — the docs front door IS a search box), then the section
   directory as quiet cards with glyphs. --- */
.docs-hero{
  position:relative;isolation:isolate;text-align:center;
  padding:clamp(2rem,5vw,3.25rem) 1rem clamp(1.5rem,3.5vw,2.25rem);
}
.docs-hero::before{
  content:"";position:absolute;inset:-1rem -.5rem 0;z-index:-1;border-radius:var(--radius-lg);
  background:radial-gradient(46rem 20rem at 50% -4rem,var(--brand-soft),transparent 72%);
  pointer-events:none;
}
.docs-hero h1{font-size:clamp(1.9rem,4.5vw,2.6rem);font-weight:750;letter-spacing:-.02em;line-height:1.1;margin:0 0 .6rem}
.docs-lede{color:var(--text-muted);font-size:1.05rem;line-height:1.55;max-inline-size:44ch;margin:0 auto}
.docs-empty{color:var(--text-muted);padding:2rem 0}

/* Multi-column pack, not a grid: grid rows stretch every card in a row to the tallest one, so a two-article
   section inherits a sixteen-article neighbor's height as dead space. CSS columns pack each card at its natural
   height (masonry-style, zero JS), balance column heights, and stay responsive through the same 17rem minimum
   the old minmax carried. Reading order flows down each column — the natural direction for a directory. */
.docs-card-grid{
  columns:17rem;
  column-gap:1rem;
  margin-block-start:1.5rem;
}
.docs-section-card{
  display:flex;flex-direction:column;gap:.7rem;min-width:0;
  break-inside:avoid;                             /* a card never splits across columns */
  margin:0 0 1rem;                                /* the vertical gap (column-gap covers the horizontal) */
  padding:1.15rem 1.25rem 1.25rem;
  border:1px solid var(--border);border-radius:var(--radius-lg);
  background:var(--surface);box-shadow:var(--shadow-sm);
  scroll-margin-top:1.5rem;                       /* breadcrumb #s-{section} deep links land comfortably */
  transition:border-color .15s ease;
}
.docs-section-card:hover{border-color:var(--border-strong)}
.docs-section-card-title{display:flex;align-items:center;gap:.6rem;font-size:1.02rem;font-weight:650;margin:0;min-width:0}
.docs-section-ico{
  display:grid;place-items:center;inline-size:2rem;block-size:2rem;flex:none;
  border-radius:var(--radius);background:var(--brand-soft);color:var(--brand-strong);
}
.docs-section-ico-svg{font-size:1.1rem}
.docs-section-card-list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:.15rem}
.docs-section-card-list a{
  display:block;padding:.28rem .5rem;margin-inline:-.5rem;border-radius:var(--radius-sm);
  color:var(--text-muted);text-decoration:none;line-height:1.45;
}
.docs-section-card-list a:hover{background:var(--surface-2);color:var(--brand-strong);text-decoration:none}

/* --- Docs search box: the product search pill, verbatim gesture (rounded field, brand focus glow, ⌘K keycap
   inside). The hero variant grows it to the front-door stature. --- */
.docs-search{display:flex;gap:.5rem;flex-wrap:wrap;margin:1.5rem 0;min-width:0}
.docs-search-field{
  flex:1 1 16rem;min-width:0;display:flex;align-items:center;gap:.5rem;
  background:var(--input-bg);border:1px solid var(--border-strong);border-radius:var(--radius-pill);
  padding:.25rem .4rem .25rem .85rem;
  transition:border-color .15s ease,box-shadow .15s ease;
}
.docs-search-field:focus-within{border-color:var(--brand);box-shadow:0 0 0 3px color-mix(in srgb,var(--brand) 22%,transparent)}
.docs-search-ico{color:var(--text-subtle);flex:none}
.docs-search-input{
  flex:1;min-width:0;border:0;outline:none;background:transparent;color:var(--text);
  font:inherit;padding:.45rem 0;
}
.docs-search-input::placeholder{color:var(--text-subtle)}
.docs-search-go{flex:0 0 auto;white-space:nowrap}
.docs-search--hero{max-width:42rem;margin:1.6rem auto 0;justify-content:center}
.docs-search--hero .docs-search-input{font-size:1.05rem;padding:.6rem 0}

/* ⌘K trigger (inside the search field + at the end of the article breadcrumb): a quiet keycap. */
.docs-cmdk-trigger{
  flex:0 0 auto;display:inline-flex;align-items:center;border:0;background:none;
  padding:.3rem;cursor:pointer;border-radius:var(--radius-sm);
}
.docs-cmdk-trigger:focus-visible{outline:2px solid var(--ring);outline-offset:1px}
.docs-cmdk-kbd{
  font-family:var(--font-mono);font-size:.72rem;line-height:1;color:var(--text-muted);
  border:1px solid var(--border);border-radius:var(--radius-sm);padding:.28em .5em;background:var(--surface-2);
}
.docs-cmdk-trigger:hover .docs-cmdk-kbd{color:var(--text);border-color:var(--border-strong)}
.docs-cmdk-trigger-crumb{margin-inline-start:auto;padding:.15rem .3rem}

/* --- Docs search results page --- */
.docs-search-results>h1{font-size:clamp(1.5rem,4vw,1.9rem);font-weight:700;letter-spacing:-.015em;margin:0 0 .5rem}
.docs-search-count{color:var(--text-muted);font-size:.9rem;margin:1rem 0 1.25rem}
.docs-hit-list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:.6rem}
.docs-hit{
  display:flex;flex-direction:column;gap:.3rem;min-width:0;
  padding:1rem 1.15rem;border:1px solid var(--border);border-radius:var(--radius-lg);background:var(--surface);
}
.docs-hit-title{font-size:1.05rem;font-weight:650;color:var(--brand-strong);text-decoration:none;overflow-wrap:anywhere}
.docs-hit-title:hover{text-decoration:underline}
.docs-hit-section{
  order:-1;font-size:.68rem;text-transform:uppercase;letter-spacing:.07em;font-weight:700;color:var(--text-subtle);
}
.docs-hit-snippet{color:var(--text-muted);margin:0;line-height:1.6;font-size:.92rem;overflow-wrap:anywhere}
.docs-hit-snippet mark,.docs-cmdk-item-snippet mark{
  background:var(--brand-soft);color:var(--brand-stronger);padding:0 .15em;border-radius:2px;font-weight:600;
}

/* --- Breadcrumb + fallback notice + article meta row --- */
.docs-breadcrumb{
  display:flex;gap:.45rem;flex-wrap:wrap;align-items:center;
  font-size:.82rem;color:var(--text-subtle);margin-block-end:1rem;
}
.docs-breadcrumb a{color:var(--text-muted);text-decoration:none}
.docs-breadcrumb a:hover{color:var(--brand-strong);text-decoration:underline}
.docs-breadcrumb-sep{color:var(--text-subtle);opacity:.7}
[dir="rtl"] .docs-breadcrumb-sep{display:inline-block;transform:scaleX(-1)}   /* › points along reading flow */
.docs-fallback-notice{margin-block:0 1.5rem}   /* reuses .legal-lang-notice styling */

.docs-article-meta{
  display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:.5rem 1rem;
  margin:0 0 1.75rem;padding-block-end:1rem;border-block-end:1px solid var(--border);
}
.docs-updated{font-size:.85rem;color:var(--text-subtle);margin:0}
.docs-article-actions{display:flex;flex-wrap:wrap;gap:.4rem;min-width:0}
.docs-action{
  display:inline-flex;align-items:center;gap:.4em;font-size:.8rem;font-weight:500;
  padding:.32rem .7rem;border:1px solid var(--border);border-radius:var(--radius-pill);
  background:var(--surface);color:var(--text-muted);cursor:pointer;text-decoration:none;white-space:nowrap;
  transition:border-color .15s ease,color .15s ease;
}
.docs-action:hover{border-color:var(--border-strong);color:var(--text);text-decoration:none}
.docs-action:focus-visible{outline:2px solid var(--ring);outline-offset:1px}
.docs-action.is-copied{color:var(--success);border-color:var(--success)}
.docs-action-ico{flex:0 0 auto}

/* --- Article prose: the app's sans at a comfortable measure (~72ch), clear weight-led hierarchy (no counters —
   structure reads from type, not numbering). --- */
.docs-article-body{
  max-inline-size:72ch;
  font-size:1rem;line-height:1.7;color:var(--text);
  text-rendering:optimizeLegibility;
}
.docs-article-body h1{
  font-size:clamp(1.75rem,1.3rem + 1.8vw,2.35rem);font-weight:750;letter-spacing:-.02em;line-height:1.15;
  margin:0 0 .5rem;
}
.docs-article-body h2{
  font-size:1.45rem;font-weight:700;letter-spacing:-.01em;line-height:1.25;
  margin:2.5rem 0 .8rem;scroll-margin-top:2rem;
}
.docs-article-body h3{font-size:1.15rem;font-weight:650;line-height:1.3;margin:1.9rem 0 .55rem;scroll-margin-top:2rem}
.docs-article-body h4{font-size:1rem;font-weight:650;margin:1.5rem 0 .4rem;scroll-margin-top:2rem}
.docs-article-body p{line-height:1.7;margin:0 0 1.1rem;color:var(--text)}
.docs-article-body ul,.docs-article-body ol{margin:0 0 1.1rem;padding-inline-start:1.6rem;line-height:1.7}
.docs-article-body li{margin:.35rem 0}
.docs-article-body li>ul,.docs-article-body li>ol{margin:.35rem 0}
.docs-article-body a{
  color:var(--brand-strong);text-decoration:underline;text-decoration-thickness:1px;text-underline-offset:2px;
}
.docs-article-body a:hover{text-decoration-thickness:2px}
.docs-article-body strong{font-weight:650}
.docs-article-body blockquote{
  margin:1.5rem 0;padding:.5rem 1.1rem;border-inline-start:3px solid var(--border-strong);
  color:var(--text-muted);background:transparent;border-radius:0 var(--radius-sm) var(--radius-sm) 0;
}
.docs-article-body blockquote p:last-child{margin-bottom:0}
.docs-article-body hr{border:0;border-block-start:1px solid var(--border);margin:2.25rem 0}
.docs-article-body :not(pre)>code{
  font-family:var(--font-mono);font-size:.86em;background:var(--surface-3);
  padding:.12em .38em;border-radius:var(--radius-sm);color:var(--text);
}
.docs-article-body img{
  display:block;max-width:100%;height:auto;margin:1.5rem auto;
  border:1px solid var(--border);border-radius:var(--radius);background:var(--surface);
}

/* Heading copy-link anchors (SSR by DocMarkdown; TS adds copy-to-clipboard). Revealed on heading hover/focus;
   faintly visible on touch (no hover to reveal them). */
.doc-anchor{
  display:inline-flex;vertical-align:baseline;margin-inline-start:.4em;
  color:var(--text-subtle);opacity:0;text-decoration:none;
  transition:opacity .12s ease,color .12s ease;
}
.docs-article-body :is(h2,h3,h4):hover .doc-anchor,.doc-anchor:focus-visible,.doc-anchor.is-copied{opacity:1}
.doc-anchor:hover{color:var(--brand-strong)}
.doc-anchor:focus-visible{outline:2px solid var(--ring);outline-offset:2px;border-radius:2px}
.doc-anchor-ico{font-size:.72em}
.doc-anchor-ico-check{display:none;color:var(--success)}
.doc-anchor.is-copied .doc-anchor-ico-link{display:none}
.doc-anchor.is-copied .doc-anchor-ico-check{display:inline}
@media (hover:none){.doc-anchor{opacity:.5}}

/* Tables: clean horizontal rules, a quiet labeled head, rounded scroll container (Markdown emits bare tables, so
   the table itself is the scroll region — no wrapper available). */
.docs-article-body table{
  border-collapse:collapse;margin:1.5rem 0;font-size:.9rem;
  display:block;max-inline-size:100%;inline-size:fit-content;overflow-x:auto;
  border:1px solid var(--border);border-radius:var(--radius);
}
.docs-article-body table caption{
  caption-side:top;text-align:start;color:var(--text-muted);padding:.5rem .8rem 0;font-size:.85rem;
}
.docs-article-body th,.docs-article-body td{
  text-align:start;padding:.55rem .8rem;border-block-start:1px solid var(--border);vertical-align:top;
}
.docs-article-body thead th{
  border-block-start:0;background:var(--surface-2);font-weight:650;font-size:.78rem;
  text-transform:uppercase;letter-spacing:.04em;color:var(--text-muted);white-space:nowrap;
}
.docs-article-body th{font-weight:650}

/* --- Fenced code blocks: a rounded panel with a header (language label + copy) and themed token colors. --- */
.doc-code{
  margin:1.5rem 0;border:1px solid var(--border);border-radius:var(--radius-lg);overflow:hidden;
  background:var(--surface-2);
}
.doc-code-head{
  display:flex;align-items:center;justify-content:space-between;gap:.5rem;
  padding:.45rem .6rem .45rem .95rem;background:var(--surface-3);border-block-end:1px solid var(--border);
}
.doc-code-lang{
  font-family:var(--font-mono);font-size:.7rem;text-transform:uppercase;letter-spacing:.06em;
  color:var(--text-muted);font-weight:600;
}
.doc-code-copy{
  display:inline-flex;align-items:center;gap:.3rem;font-size:.75rem;font-weight:500;
  padding:.25rem .65rem;border:1px solid var(--border);border-radius:var(--radius-pill);
  background:var(--surface);color:var(--text-muted);cursor:pointer;
  transition:color .15s ease,border-color .15s ease;
}
.doc-code-copy:hover{color:var(--text);border-color:var(--border-strong)}
.doc-code-copy:focus-visible{outline:2px solid var(--ring);outline-offset:1px}
.doc-code-copy.is-copied{color:var(--success);border-color:var(--success)}
.doc-code-pre{
  margin:0;padding:.95rem 1.1rem;overflow-x:auto;
  font-family:var(--font-mono);font-size:.85rem;line-height:1.6;color:var(--text);
  tab-size:4;-moz-tab-size:4;
}
.doc-code-pre code{font-family:inherit}

/* ColorCode token classes — themed from the design tokens so light/dark/contrast all follow. */
.doc-code-pre .keyword,.doc-code-pre .Keyword{color:var(--brand-strong);font-weight:600}
.doc-code-pre .string,.doc-code-pre .String{color:var(--success)}
.doc-code-pre .comment,.doc-code-pre .Comment{color:var(--text-subtle);font-style:italic}
.doc-code-pre .number,.doc-code-pre .Number{color:var(--warning)}
.doc-code-pre .preprocessor-keyword,.doc-code-pre .preprocessorKeyword{color:var(--accent)}
.doc-code-pre .html-element-name,.doc-code-pre .htmlElementName,
.doc-code-pre .xml-attribute,.doc-code-pre .xmlAttribute,
.doc-code-pre .xml-attribute-quotes,.doc-code-pre .xmlAttributeQuotes{color:var(--brand-strong)}
.doc-code-pre .xml-attribute-value,.doc-code-pre .xmlAttributeValue{color:var(--success)}
.doc-code-pre .type,.doc-code-pre .Type{color:var(--info)}

/* --- Language tabs (curl / C# / JS): a segmented tray docked onto the code panel. --- */
.doc-tabs{margin:1.5rem 0}
.doc-tabs-strip{
  display:flex;gap:.25rem;flex-wrap:wrap;align-items:center;
  border:1px solid var(--border);border-block-end:0;
  border-start-start-radius:var(--radius-lg);border-start-end-radius:var(--radius-lg);
  background:var(--surface-3);padding:.35rem .45rem;
}
.doc-tab{
  font-size:.78rem;font-weight:550;padding:.3rem .75rem;background:none;border:0;
  border-radius:var(--radius-pill);color:var(--text-muted);cursor:pointer;
}
.doc-tab:hover{color:var(--text)}
.doc-tab.active{background:var(--surface);color:var(--brand-strong);font-weight:650;box-shadow:var(--shadow-sm)}
.doc-tab:focus-visible{outline:2px solid var(--ring);outline-offset:-2px}
.doc-tabs .doc-code{margin:0;border-start-start-radius:0;border-start-end-radius:0}

/* --- In-page TOC: the scroll-spy rail. --- */
.docs-toc{
  position:sticky;top:1.5rem;min-width:0;font-size:.85rem;
  max-height:calc(100vh - 3rem);overflow-y:auto;overscroll-behavior:contain;
  scrollbar-width:thin;scrollbar-color:var(--border-strong) transparent;
}
.docs-toc-title{
  font-size:.68rem;text-transform:uppercase;letter-spacing:.07em;color:var(--text-subtle);
  font-weight:700;margin:0 0 .6rem;padding-inline-start:.95rem;
}
.docs-toc-list{
  list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:.15rem;
  border-inline-start:1px solid var(--border);
}
.docs-toc-list a{
  display:block;color:var(--text-muted);text-decoration:none;line-height:1.45;
  padding:.15rem .5rem .15rem .85rem;
  margin-inline-start:-1px;border-inline-start:2px solid transparent;
}
.docs-toc-list a:hover{color:var(--text)}
.docs-toc-list a.active{color:var(--brand-strong);border-inline-start-color:var(--brand);font-weight:600}
.docs-toc-l3 a{padding-inline-start:1.7rem;font-size:.95em;color:var(--text-subtle)}

/* Narrow-viewport "On this page": a <details> disclosure above the article (shown only when the rail hides). */
.docs-toc-drawer{display:none;margin:0 0 1.5rem;border:1px solid var(--border);border-radius:var(--radius);background:var(--surface)}
.docs-toc-drawer-btn{
  list-style:none;display:flex;align-items:center;gap:.5rem;
  padding:.6rem .8rem;cursor:pointer;font-weight:600;font-size:.9rem;color:var(--text);
}
.docs-toc-drawer-btn::-webkit-details-marker{display:none}
.docs-toc-drawer-btn:focus-visible{outline:2px solid var(--ring);outline-offset:2px}
.docs-toc-drawer .docs-toc-list{border-inline-start:0;padding:.15rem .8rem .75rem}
.docs-toc-drawer .docs-toc-list a{border-inline-start:0;margin-inline-start:0;padding:.25rem .2rem;border-radius:var(--radius-sm)}
.docs-toc-drawer .docs-toc-list a:hover{background:var(--surface-2)}
.docs-toc-drawer .docs-toc-l3 a{padding-inline-start:1rem}

/* --- Previous / next article pagination --- */
.docs-pager{display:grid;grid-template-columns:1fr 1fr;gap:.75rem;margin-block-start:2.5rem}
.docs-pager-link{
  display:flex;flex-direction:column;gap:.25rem;min-width:0;
  padding:.85rem 1rem;border:1px solid var(--border);border-radius:var(--radius-lg);
  background:var(--surface);text-decoration:none;transition:border-color .15s ease;
}
.docs-pager-link:hover{border-color:var(--brand);text-decoration:none}
.docs-pager-next{text-align:end;align-items:flex-end}
.docs-pager-eyebrow{
  display:inline-flex;align-items:center;gap:.3rem;
  font-size:.68rem;font-weight:700;text-transform:uppercase;letter-spacing:.07em;color:var(--text-subtle);
}
.docs-pager-arrow{flex:none}
[dir="rtl"] .docs-pager-arrow{transform:scaleX(-1)}
.docs-pager-title{font-weight:600;font-size:.95rem;color:var(--text);overflow-wrap:anywhere}
.docs-pager-link:hover .docs-pager-title{color:var(--brand-strong)}
.docs-pager-spacer{min-width:0}

/* --- "Was this helpful?" --- */
.docs-feedback{
  display:flex;flex-wrap:wrap;align-items:center;gap:.6rem 1rem;
  margin-block-start:2.5rem;padding:.9rem 1.15rem;max-inline-size:72ch;
  border:1px solid var(--border);border-radius:var(--radius-lg);background:var(--surface-2);
  font-size:.9rem;color:var(--text-muted);
}
.docs-feedback-actions{display:inline-flex;gap:.5rem}
.docs-feedback-btn{
  font-size:.85rem;font-weight:500;padding:.3rem .95rem;
  border:1px solid var(--border);border-radius:var(--radius-pill);
  background:var(--surface);color:var(--text-muted);cursor:pointer;
  transition:border-color .15s ease,color .15s ease;
}
.docs-feedback-btn:hover{border-color:var(--brand);color:var(--brand-strong)}
.docs-feedback-btn:focus-visible{outline:2px solid var(--ring);outline-offset:1px}
.docs-feedback-thanks{color:var(--success);font-weight:500}

/* --- "See also" --- */
.docs-related{margin-block-start:2.25rem;max-inline-size:72ch}
.docs-related-title{
  font-size:.78rem;font-weight:700;text-transform:uppercase;letter-spacing:.06em;
  color:var(--text-subtle);margin:0 0 .6rem;
}
.docs-related-list{list-style:none;margin:0;padding:0;columns:2 14rem;column-gap:2.5rem}
.docs-related-list li{break-inside:avoid;margin:0 0 .35rem}
.docs-related-list a{color:var(--brand-strong);text-decoration:none;font-size:.95rem}
.docs-related-list a:hover{text-decoration:underline}

/* --- ⌘K command palette --- */
.docs-cmdk[hidden]{display:none}
.docs-cmdk{position:fixed;inset:0;z-index:var(--z-modal);display:flex;align-items:flex-start;justify-content:center}
html.docs-cmdk-open{overflow:hidden}   /* lock background scroll while open */
.docs-cmdk-backdrop{position:absolute;inset:0;background:rgba(10,8,20,.5);backdrop-filter:blur(2px)}
.docs-cmdk-panel{
  position:relative;margin-block-start:12vh;inline-size:min(40rem,92vw);max-block-size:70vh;
  display:flex;flex-direction:column;overflow:hidden;
  background:var(--surface);color:var(--text);
  border:1px solid var(--border);border-radius:var(--radius-lg);box-shadow:var(--shadow-lg);
}
.docs-cmdk-search{display:flex;align-items:center;gap:.6rem;padding:.75rem .95rem;border-block-end:1px solid var(--border)}
.docs-cmdk-ico{flex:0 0 auto;color:var(--text-subtle)}
.docs-cmdk-input{
  flex:1 1 auto;min-width:0;border:0;background:none;color:var(--text);
  font:inherit;font-size:1.02rem;outline:none;
}
.docs-cmdk-input::placeholder{color:var(--text-subtle)}
.docs-cmdk-esc{
  flex:0 0 auto;font-family:var(--font-mono);font-size:.68rem;color:var(--text-subtle);
  border:1px solid var(--border);border-radius:var(--radius-sm);padding:.15em .45em;background:var(--surface-2);
}
.docs-cmdk-list{list-style:none;margin:0;padding:.4rem;overflow-y:auto;min-block-size:0;overscroll-behavior:contain}
.docs-cmdk-item{
  display:flex;flex-direction:column;gap:.15rem;min-width:0;
  padding:.55rem .7rem;border-radius:var(--radius);cursor:pointer;
}
.docs-cmdk-item-row{display:flex;align-items:baseline;justify-content:space-between;gap:1rem;min-width:0}
.docs-cmdk-item-title{color:var(--text);font-weight:500;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.docs-cmdk-item-section{
  flex:0 0 auto;font-size:.66rem;font-weight:700;text-transform:uppercase;letter-spacing:.07em;color:var(--text-subtle);
}
.docs-cmdk-item-snippet{
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;
  font-size:.8rem;line-height:1.5;color:var(--text-muted);overflow-wrap:anywhere;
}
.docs-cmdk-item.active,.docs-cmdk-item[aria-selected="true"]{background:var(--brand-soft)}
.docs-cmdk-item.active .docs-cmdk-item-title{color:var(--brand-stronger)}
.docs-cmdk-empty{margin:0;padding:1rem;color:var(--text-subtle)}
.docs-cmdk-search-all{
  display:flex;align-items:baseline;gap:.4rem;inline-size:100%;text-align:start;
  padding:.65rem .95rem;border:0;border-block-start:1px solid var(--border);
  background:none;color:var(--text-muted);font:inherit;font-size:.88rem;cursor:pointer;
}
.docs-cmdk-search-all:hover{background:var(--surface-2);color:var(--text)}
.docs-cmdk-search-all:focus-visible{outline:2px solid var(--ring);outline-offset:-2px}
.docs-cmdk-search-q{color:var(--brand-strong);font-weight:600;overflow-wrap:anywhere}

/* --- Header theme toggle (global, near the contrast toggle): icon-only keycap button --- */
.theme-toggle .theme-toggle-ico{font-size:1.05em;line-height:1}

/* --- Reflow: collapse the TOC rail (→ the drawer), then the left nav (→ the drawer), as the viewport narrows
   or text scales up. Em breakpoints fire earlier under text-zoom — exactly when the columns would overflow. --- */
@media (max-width:64em){
  .docs-shell{grid-template-columns:15rem minmax(0,1fr)}
  .docs-toc{display:none}          /* the drawer + the body's own headings take over */
  .docs-toc-drawer{display:block}
}
@media (max-width:48em){
  .docs-shell{grid-template-columns:1fr;gap:1.25rem;padding-block-start:1rem}
  .docs-sidebar{position:static;max-height:none;overflow:visible;padding-block-end:0}
  .docs-nav-toggle{display:flex}
  .docs-nav-drawer:not([open])::details-content{content-visibility:hidden}
  .docs-nav-drawer:not([open]) > .docs-nav{display:none}
  .docs-nav-drawer[open] > .docs-nav{
    margin-block-start:.6rem;padding:.85rem;
    border:1px solid var(--border);border-radius:var(--radius);background:var(--surface);
  }
  .docs-article-body{max-inline-size:none}
  .docs-hero{padding-block-start:1.25rem}
}
@media (max-width:34em){
  .docs-pager{grid-template-columns:1fr}
  .docs-pager-spacer{display:none}
  .docs-pager-next{text-align:start;align-items:flex-start}
}

@media (prefers-reduced-motion:reduce){
  .doc-code-copy,.docs-action,.docs-pager-link,.docs-search-field,.docs-section-card,.doc-anchor,
  .docs-drawer-chevron,.docs-feedback-btn{transition:none}
}

/* Forced colors: keep the selected/active states visible where background tints vanish. */
@media (forced-colors:active){
  .docs-nav-link.active,.docs-nav-home.active,
  .docs-cmdk-item.active,.docs-cmdk-item[aria-selected="true"]{outline:2px solid CanvasText;outline-offset:-2px}
  .doc-callout{border-inline-start-width:4px}
}

/* ============================ Callouts / admonitions ============================
   GitHub-style alerts authored as `> [!NOTE] / [!TIP] / [!WARNING] / [!IMPORTANT] / [!HISTORY]` render as a
   semantic <aside class="doc-callout doc-callout-{type}" role="note"> (see DocMarkdown.cs CalloutRenderer). Each
   type sets one accent (--callout) from a design token; the tint + border derive via color-mix, so light/dark/
   high-contrast follow automatically and RTL is correct (logical properties only). The em-sized currentColor icon
   tracks text scaling. HISTORY is Neuji's own kind — background asides "from the record" — and reads as a quiet
   accent-tinted note (same shape as the others; the violet accent + muted body set it apart). */
.doc-callout{
  --callout:var(--info);
  margin:1.5rem 0;
  padding:.9rem 1.1rem;
  border:1px solid color-mix(in srgb,var(--callout) 28%,var(--border));
  border-inline-start:3px solid var(--callout);
  border-radius:var(--radius);
  background:color-mix(in srgb,var(--callout) 7%,var(--surface));
  color:var(--text);
}
.doc-callout > :first-child{margin-block-start:0}
.doc-callout > :last-child{margin-block-end:0}
.doc-callout-head{
  display:flex;align-items:center;gap:.45rem;
  margin:0 0 .4rem;
  color:var(--callout);
  font-weight:700;
}
.doc-callout-icon{flex:none;inline-size:1.1em;block-size:1.1em}   /* em-sized → scales with OS/text-zoom font */
.doc-callout-label{font-size:.72rem;text-transform:uppercase;letter-spacing:.08em;line-height:1.2}
.doc-callout-body > :first-child{margin-block-start:0}
.doc-callout-body > :last-child{margin-block-end:0}
.doc-callout-body p{line-height:1.6;margin:0 0 .6rem}
.doc-callout-body ul,.doc-callout-body ol{margin:0 0 .6rem;padding-inline-start:1.3rem}

/* Per-type accents (each maps to a design token so dark mode / contrast follow automatically). */
.doc-callout-note{--callout:var(--info)}
.doc-callout-tip{--callout:var(--success)}
.doc-callout-warning{--callout:var(--warning)}
.doc-callout-important{--callout:var(--danger)}
.doc-callout-history{--callout:var(--accent)}
.doc-callout-history .doc-callout-body{color:var(--text-muted)}

/* ===================== Community views (sharing + directory) =====================
   Public view page (/v/{token}), the directory (/views), and the Settings share/subscription controls. All
   rem-based, flex-wrap rows + min-width:0 children, so it reflows with no horizontal scroll at 200% text. */

/* --- Public view page --- */
.view-public { padding-block: clamp(1rem, 4vw, 2rem); }
.view-public-crumb { font-size: 0.9rem; margin-bottom: 0.75rem; }
.view-public-crumb a { color: var(--accent); }
.view-public-head h1 { font-size: clamp(1.5rem, 4vw, 2rem); margin: 0 0 0.5rem; }
.view-public-desc { color: var(--text-muted); font-size: 1.05rem; margin: 0 0 0.75rem; max-width: 60ch; }
.view-public-meta { display: flex; flex-wrap: wrap; gap: 0.4rem 1.25rem; font-size: 0.9rem; }
.view-public-stat { display: inline-flex; gap: 0.3rem; min-width: 0; }
.view-public-actions {
    display: flex; flex-wrap: wrap; align-items: center; gap: 0.6rem;
    margin: 1.25rem 0 0.5rem;
}
.view-public-actions form { margin: 0; }
.view-public-actions .alert { flex: 1 1 100%; }
.view-public-hint { font-size: 0.85rem; margin: 0 0 1.5rem; max-width: 60ch; }
.view-public-rules { margin-top: 1.5rem; border-block-start: 1px solid var(--border); padding-block-start: 1.5rem; }
.view-public-rules h2 { font-size: 1.2rem; margin: 0 0 0.25rem; }
.view-public-signin { margin: 0; }

/* --- Inspectable rules table (shared: public page + admin) --- */
.view-rules { display: flex; flex-direction: column; gap: 1.25rem; margin-top: 1rem; }
.view-rules-group-title {
    display: flex; align-items: center; gap: 0.5rem; font-size: 0.95rem; font-weight: 600;
    margin: 0 0 0.5rem; color: var(--text);
}
.view-rules-count {
    font-size: 0.75rem; font-weight: 600; color: var(--text-muted);
    background: var(--surface-2); border: 1px solid var(--border); border-radius: var(--radius-pill);
    padding: 0.05rem 0.45rem;
}
.view-rules-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0.4rem; }
.view-rules-row { display: flex; flex-wrap: wrap; align-items: center; gap: 0.4rem 0.6rem; min-width: 0; }
.view-rules-pattern {
    font-family: var(--font-mono); font-size: 0.9rem;
    background: var(--surface-2); border: 1px solid var(--border); border-radius: var(--radius-sm);
    padding: 0.1rem 0.4rem; word-break: break-word; min-width: 0;
}
.view-rules-arrow { color: var(--text-muted); }
.view-rules-match { font-size: 0.8rem; }
.view-rules-scope { font-size: 0.7rem; }

/* --- Directory (/views) --- */
.view-directory { padding-block: clamp(1rem, 4vw, 2rem); }
.view-directory-search {
    display: flex; flex-wrap: wrap; gap: 0.5rem; margin: 1.25rem 0 1.5rem; max-width: 36rem;
}
.view-directory-search .field-input { flex: 1 1 12rem; min-width: 0; }
.view-directory-grid {
    list-style: none; margin: 0; padding: 0;
    display: grid; grid-template-columns: repeat(auto-fill, minmax(17rem, 1fr)); gap: 1rem;
}
.view-directory-card { display: flex; flex-direction: column; gap: 0.6rem; min-width: 0; }
.view-directory-card-head { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem; min-width: 0; }
.view-directory-card-title { font-size: 1.1rem; margin: 0; min-width: 0; }
.view-directory-card-title a { color: var(--text); }
.view-directory-card-title a:hover { color: var(--accent); }
.view-directory-card-desc { color: var(--text-muted); font-size: 0.9rem; margin: 0; flex: 1 1 auto; }
.view-directory-card-foot {
    display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem; margin-top: auto;
}
.view-directory-card-foot form { margin: 0; }
.view-directory-subs { font-size: 0.85rem; margin-inline-end: auto; }
.view-directory-signin { margin-top: 1.5rem; font-size: 0.9rem; }
.view-directory-signin a { color: var(--accent); }

/* ==================== Search Control: Adjust slider · modal · rules page · view switches ==================== */

/* --- Adjust slider (RankSlider) — replaces the old per-result action buttons; reused on the rules-page editor --- */
.rank-slider-wrap { padding: 0.15rem 0.1rem 0; }
.rank-slider-form { display: flex; flex-direction: column; gap: 0.4rem; min-width: 0; }
.rank-slider-head { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: 0.25rem 0.5rem; min-width: 0; }
.rank-slider-caption { font-size: 0.68rem; text-transform: uppercase; letter-spacing: 0.04em; color: var(--text-muted); }
.rank-slider-value { font-size: 0.8rem; font-weight: 600; color: var(--text); }
.rank-slider { inline-size: 100%; accent-color: var(--brand); margin: 0; min-width: 0; }
.rank-slider-marks { display: flex; justify-content: space-between; gap: 0.2rem; font-size: 0.6rem; color: var(--text-muted); }
.rank-slider-marks span { min-width: 0; text-align: center; overflow-wrap: anywhere; }
.rank-slider-apply { align-self: flex-start; }

/* --- Reusable modal (Modal.razor) — cloned from .docs-cmdk --- */
.modal[hidden] { display: none; }
.modal { position: fixed; inset: 0; z-index: 1000; display: flex; align-items: flex-start; justify-content: center; }
html.modal-open { overflow: hidden; }   /* lock background scroll while open */
.modal-backdrop { position: absolute; inset: 0; background: rgba(15, 12, 8, 0.45); }
.modal-panel {
    position: relative; margin-block-start: 10vh; inline-size: min(34rem, 92vw); max-block-size: 84vh;
    display: flex; flex-direction: column; overflow: hidden;
    background: var(--surface); color: var(--text);
    border: 1px solid var(--border-strong); border-radius: var(--radius); box-shadow: var(--shadow-lg);
}
.modal-head { display: flex; align-items: center; justify-content: space-between; gap: 0.75rem; padding: 0.8rem 1rem; border-block-end: 1px solid var(--border); }
.modal-title { margin: 0; font-size: 1.05rem; }
.modal-close { flex: 0 0 auto; border: 0; background: none; color: var(--text-muted); font-size: 1.1rem; line-height: 1; cursor: pointer; padding: 0.2rem 0.45rem; border-radius: var(--radius-sm); }
.modal-close:hover { color: var(--text); background: var(--surface-2); }
.modal-close:focus-visible { outline: 2px solid var(--ring); outline-offset: -2px; }
.modal-body { padding: 1rem; overflow-y: auto; min-block-size: 0; }
.modal-error { margin: 0 0 0.75rem; color: var(--danger, #b42318); font-size: 0.85rem; }
.rule-add .modal-error { flex-basis: 100%; }

/* --- Search-Control sub-pages (rules list / add / view add) --- */
.sc-page { padding-block-end: 3rem; }
.sc-back { display: inline-block; font-size: 0.85rem; color: var(--text-muted); text-decoration: none; margin-block-end: 0.25rem; }
.sc-back::before { content: "← "; }
[dir="rtl"] .sc-back::before { content: "→ "; }   /* back points the other way in RTL */
.sc-back:hover { color: var(--text); }
.sc-rules-toolbar { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 0.75rem; margin: 1rem 0; }
.sc-rules-sort { display: flex; flex-wrap: wrap; align-items: center; gap: 0.4rem; font-size: 0.8125rem; }
.sc-sort-link { color: var(--text-muted); text-decoration: none; padding: 0.15rem 0.55rem; border-radius: var(--radius-pill); border: 1px solid transparent; cursor: pointer; }
.sc-sort-link:hover { color: var(--text); }
.sc-sort-link.is-active { color: var(--brand-strong); border-color: var(--border); background: var(--surface-2); }
/* "Your rules" — icon-led cards. One row per rule; the leading action icon + its colour is the at-a-glance
   signature (block = red ⊘, lower = amber ↓, raise = green ↑, pin = brand ⤒), the pattern is the headline,
   match-type/scope sit muted beneath. Flex row reflows on its own (no grid breakpoint needed). */
.sc-rules { display: flex; flex-direction: column; gap: 0.4rem; }
.sc-rule-row { border: 1px solid var(--border); border-radius: var(--radius); background: var(--surface);
    transition: border-color 0.15s ease; }
.sc-rule-row:hover { border-color: var(--border-strong); }
.sc-rule-row[open] { border-color: var(--brand); }
.sc-rule-summary { display: flex; align-items: center; gap: 0.85rem; padding: 0.65rem 0.8rem; cursor: pointer; list-style: none; }
.sc-rule-summary::-webkit-details-marker { display: none; }
.sc-rule-icon { flex: none; display: grid; place-items: center; inline-size: 2.1rem; block-size: 2.1rem; border-radius: 50%; }
.sc-rule-icon svg { inline-size: 1.05rem; block-size: 1.05rem; }
.sc-rule-main { min-inline-size: 0; flex: 1 1 auto; display: flex; flex-direction: column; gap: 0.1rem; }
.sc-rule-pattern { font-weight: 600; font-size: 0.92rem; overflow-wrap: anywhere; line-height: 1.25; }
.sc-rule-meta { display: flex; flex-wrap: wrap; align-items: center; gap: 0.3rem; font-size: 0.75rem; color: var(--text-muted); }
.sc-rule-act { font-weight: 600; }
.sc-rule-sep { opacity: 0.45; }
/* view-scoped rule: the owning view named in the summary meta, accent-tinted so it reads as a scope
   condition ("only while this view is active"), not another attribute */
.sc-rule-viewchip { color: var(--brand-strong); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-inline-size: 14rem; }
.sc-rule-weight { flex: none; font-variant-numeric: tabular-nums; font-weight: 700; font-size: 0.8rem; padding: 0.08rem 0.5rem; border-radius: var(--radius-pill); }
.sc-rule-chevron { flex: none; display: grid; place-items: center; color: var(--text-muted); transition: transform 0.2s ease; }
.sc-rule-chevron svg { inline-size: 1.05rem; block-size: 1.05rem; }
.sc-rule-row[open] .sc-rule-chevron { transform: rotate(90deg); }
/* per-action colour (matches the result-kebab chips; tokens are theme-aware) */
.sc-rule-icon-block { background: var(--danger-soft); color: var(--danger); }
.sc-rule-icon-lower { background: var(--warning-soft); color: var(--warning); }
.sc-rule-icon-raise { background: var(--success-soft); color: var(--success); }
.sc-rule-icon-pin   { background: var(--brand-soft); color: var(--brand-strong); }
.sc-rule-icon-normal { background: var(--surface-2); color: var(--text-muted); }
.sc-rule-act-block { color: var(--danger); }
.sc-rule-act-lower { color: var(--warning); }
.sc-rule-act-raise { color: var(--success); }
.sc-rule-act-pin   { color: var(--brand-strong); }
.sc-rule-weight-lower { background: var(--warning-soft); color: var(--warning); }
.sc-rule-weight-raise { background: var(--success-soft); color: var(--success); }
/* expanded editor (the Adjust slider + delete) */
.sc-rule-edit { padding: 0.65rem 0.8rem 0.8rem; border-block-start: 1px solid var(--border);
    display: flex; flex-wrap: wrap; align-items: flex-end; gap: 0.75rem 1.25rem; }
.sc-rule-edit .rank-slider-form { flex: 1 1 16rem; max-inline-size: 24rem; border: 1px solid var(--border); border-radius: var(--radius); padding: 0.5rem 0.65rem; }
.sc-rule-fromview { flex: 1 1 16rem; margin: 0; }
.sc-rule-delete { margin: 0; }

/* --- Settings › Search Control: rules-count summary + view switches + always-shown built-ins --- */
.rule-summary-counts { margin: 0 0 0.5rem; }
/* Colour-coded count chips (the pane "Your rules" summary) — icon + count + label, tinted per action via the
   shared .sc-rule-icon-{action} tokens. */
.rank-stat-row { display: flex; flex-wrap: wrap; gap: 0.5rem; margin: 0.25rem 0 0.7rem; }
.rank-stat { display: inline-flex; align-items: center; gap: 0.35rem; padding: 0.28rem 0.65rem;
    border-radius: var(--radius-pill); font-size: 0.82rem; font-weight: 500; }
.rank-stat svg { inline-size: 0.95rem; block-size: 0.95rem; flex: none; }
.rank-stat strong { font-weight: 700; font-variant-numeric: tabular-nums; }
.rule-manage-row { margin: 0.5rem 0 0; }

/* --- Settings › Views: import dropzone + one-form export (io-*) ---------------------------------
   The file input COVERS the dropzone (opacity 0, inset 0): click-anywhere browses, native drag-drop
   lands on the input with no JS; 67-views-io.ts only decorates (drag-over, filename, arming). The
   whole import/export block nests INSIDE the Views row behind a left rail — the "belongs to Views"
   grouping the flat run can't communicate on its own. */
.io-subsection { margin-block-start: 1.2rem; padding-inline-start: 1rem;
    border-inline-start: 2px solid var(--border-strong);
    display: flex; flex-direction: column; gap: 1.1rem; }
.io-subsection .rule-group-title { margin: 0; }
.io-import { margin: 0; }
.io-dropzone { position: relative; display: flex; flex-direction: column; align-items: center; gap: 0.2rem;
    padding: 1rem 1rem 1.1rem; border: 1.5px dashed var(--border-strong);
    border-radius: var(--radius); text-align: center; cursor: pointer;
    transition: border-color 120ms ease, background-color 120ms ease; }
.io-dropzone.is-dragover, .io-dropzone:hover { border-color: var(--brand); background: var(--brand-soft); }
.io-dropzone:focus-within { outline: 2px solid var(--brand); outline-offset: 2px; }
.io-dropzone .io-file { position: absolute; inset: 0; opacity: 0; cursor: pointer; inline-size: 100%; block-size: 100%; }
.io-drop-glyph { inline-size: 1.5rem; block-size: 1.5rem; color: var(--text-muted); }
.io-drop-title { font-weight: 600; font-size: 0.9rem; }
.io-drop-hint { font-size: 0.8rem; max-inline-size: 34rem; }
.io-drop-file { font-size: 0.82rem; font-weight: 600; font-variant-numeric: tabular-nums; word-break: break-all;
    padding: 0.15rem 0.6rem; border-radius: var(--radius-pill); background: var(--brand-soft); }
.io-dropzone.has-file { border-style: solid; }
.io-import-actions { display: flex; flex-wrap: wrap; gap: 0.5rem; align-items: center; margin-block-start: 0.55rem; }
.io-export .field-label { display: block; margin-block-end: 0.3rem; }
.io-export-row { display: flex; flex-wrap: wrap; gap: 0.5rem; align-items: center; }
.io-export-row .field-select { min-inline-size: 0; flex: 0 1 16rem; }

.view-row-head { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem; min-width: 0; }
.view-row-head .rule-pattern { flex: 1 1 auto; }
.view-row-head .rule-row-actions { margin-inline-start: auto; }
.view-switch-form { margin: 0; flex: 0 0 auto; }
.view-builtins { margin-block-start: 1rem; }
.view-bulk { display: flex; flex-wrap: wrap; gap: 0.5rem; margin: 0.35rem 0 0.6rem; }
.view-mode-help { list-style: none; margin: 0.6rem 0 0; padding: 0; display: flex; flex-direction: column; gap: 0.3rem; font-size: 0.8rem; flex-basis: 100%; }

/* --- Settings: per-view share controls + subscriptions --- */
.rule-row-view { flex-direction: column; align-items: stretch; }
.view-share {
    flex-basis: 100%; display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem 1rem;
    margin-top: 0.4rem; padding-top: 0.4rem; border-block-start: 1px dashed var(--border);
}
.view-share-link { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.3rem; min-width: 0; font-size: 0.85rem; }
.view-share-url { word-break: break-all; min-width: 0; }
.view-share-url a { color: var(--accent); }
.view-share-actions { display: inline-flex; flex-wrap: wrap; gap: 0.5rem; }

/* ============================ Print ============================
   A clean, chrome-free article on paper: hide navigation/controls, black on white, expand external link URLs,
   and keep code/tables/callouts from splitting badly. (The browser's own header/footer supplies page numbers.) */
@media print{
  @page{margin:16mm}

  /* App chrome + interactive-only bits */
  .app-bar,.app-header,.header-nav,.skip-link,
  .docs-sidebar,.docs-toc,.docs-toc-drawer,.docs-search,.doc-code-copy,.doc-tabs-strip,.docs-breadcrumb,
  .doc-anchor,.docs-article-actions,.docs-feedback,.docs-pager,.docs-cmdk,.docs-cmdk-trigger{display:none !important}

  html,body{background:#fff !important}
  .docs-shell{display:block;max-width:none;margin:0;padding:0;background:#fff !important;color:#000 !important}
  .docs-main,.docs-article-body{max-inline-size:none}
  .docs-article-body{font-size:11pt;line-height:1.55}
  .docs-article-body h1{font-size:20pt}
  .docs-article-meta{display:block;border-block-end:1pt solid #000}

  /* Black on white, no tints */
  body,.docs-article-body,.docs-article-body p,.docs-article-body li,
  .docs-article-body h1,.docs-article-body h2,.docs-article-body h3,.docs-article-body h4{color:#000 !important}
  .doc-code,.doc-code-pre,.doc-code-head,.docs-article-body :not(pre)>code,
  .docs-article-body th,.docs-article-body blockquote,
  .doc-callout,.doc-callout-head{background:#fff !important;color:#000 !important}
  .doc-code,.doc-code-head,.doc-code-pre,.docs-article-body table,
  .docs-article-body th,.docs-article-body td,.docs-article-body img{border-color:#999 !important}
  .doc-callout{border:1px solid #999 !important;border-inline-start:3px solid #000 !important}
  .docs-article-body a{color:#000 !important;text-decoration:underline}
  .docs-article-body blockquote{border-inline-start:2pt solid #000 !important}
  .doc-code-pre .keyword,.doc-code-pre .string,.doc-code-pre .comment,.doc-code-pre .number,
  .doc-code-pre .type,.doc-code-pre .preprocessor-keyword{color:#000 !important;font-style:normal}

  /* Language tab groups: print EVERY panel (each is labeled by its own header), not just the active one. */
  .doc-tabs [data-doc-panel][hidden]{display:block !important}
  .doc-tabs .doc-code{margin:0 0 .75rem;border-radius:0}

  /* Expand hyperlink targets so a printed page keeps the URLs (skip in-page anchors + relative links) */
  .docs-article-body a[href^="http"]::after{content:" (" attr(href) ")";font-size:.85em;color:#000;word-break:break-all}

  /* Don't split code / tables / callouts / figures awkwardly; keep headings with their text. */
  .doc-code,.doc-tabs,.docs-article-body pre,.docs-article-body table,.docs-article-body blockquote,
  .docs-article-body img,.doc-callout{break-inside:avoid;page-break-inside:avoid}
  .docs-article-body h1,.docs-article-body h2,.docs-article-body h3,.docs-article-body h4,
  .doc-code-head{break-after:avoid;page-break-after:avoid}
  .docs-article-body p,.docs-article-body li{orphans:3;widows:3}
  .doc-code-pre{white-space:pre-wrap;word-break:break-word}   /* wrap long lines so nothing is clipped on paper */
}

/* ── Advanced Search (/advanced) ───────────────────────────────────────────────────────────────────────────────
   A composable boolean query builder. Two columns on desktop (build + sticky filter rail); the JS canvas (38-
   advanced-search.ts) replaces the flat word rows with a nestable AND/OR/NOT tree and drives the live preview. */
.adv { max-width: 64rem; margin: 0 auto; padding: 1.5rem 1rem 4rem; }
.adv-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 1rem; flex-wrap: wrap; margin-bottom: 1.5rem; }
.adv-head h1 { margin: 0 0 .25rem; font-size: clamp(1.4rem, 1rem + 1.6vw, 1.75rem); }
.adv-sub { margin: 0; font-size: .9rem; max-width: 44rem; }
.adv-x { font-size: 1.9rem; line-height: 1; color: var(--text-subtle); text-decoration: none; padding: 0 .4rem; border-radius: var(--radius-sm); }
.adv-x:hover { color: var(--text); background: var(--bg-elevated); }

.adv-cols { display: grid; grid-template-columns: 1fr; gap: 1.25rem; }
@media (min-width: 56em) { .adv-cols { grid-template-columns: 1.45fr 1fr; align-items: start; } }

.adv-card { border: 1px solid var(--border); border-radius: var(--radius-lg); background: var(--surface); padding: 1.1rem 1.2rem; margin: 0 0 1.1rem; }
.adv-build { min-width: 0; }
.adv-build .adv-card:last-child { margin-bottom: 0; }
.adv-card > legend, .adv-rail > legend { display: block; width: 100%; font-weight: 650; font-size: .72rem; letter-spacing: .05em; text-transform: uppercase; color: var(--text-muted); padding: 0; margin-bottom: .9rem; }
@media (min-width: 56em) { .adv-rail { position: sticky; top: calc(var(--header-height) + 1rem); } }

.adv-row { display: flex; flex-direction: column; gap: .35rem; min-width: 0; margin-bottom: .9rem; }
.adv-row:last-child { margin-bottom: 0; }
.adv-row > label, .adv-row-label { font-size: .85rem; font-weight: 550; color: var(--text); }
.adv-hint { margin: .05rem 0 0; font-size: .78rem; color: var(--text-subtle); }
.adv-grid2 { display: grid; grid-template-columns: 1fr; gap: 0 1rem; }
@media (min-width: 30em) { .adv-grid2 { grid-template-columns: 1fr 1fr; } .adv-grid2 .adv-row:last-child { grid-column: 1 / -1; } }

.adv-chips { display: flex; flex-wrap: wrap; gap: .35rem; margin-top: .15rem; }
.adv-chip { font: inherit; font-size: .78rem; padding: .2rem .6rem; border: 1px solid var(--border); border-radius: var(--radius-pill); background: var(--bg); color: var(--text-muted); cursor: pointer; }
.adv-chip:hover { border-color: var(--brand); color: var(--brand); }
.adv-chip.is-on { background: var(--brand-soft); border-color: var(--brand); color: var(--brand-strong); }

.adv-daterow { display: flex; flex-wrap: wrap; gap: .6rem; }
.adv-date { display: flex; flex-direction: column; gap: .2rem; flex: 1 1 8rem; min-width: 0; font-size: .78rem; color: var(--text-subtle); }

.adv-toggles { display: flex; flex-direction: column; gap: .6rem; }
.adv-check { display: flex; align-items: center; gap: .55rem; font-size: .88rem; cursor: pointer; }
.adv-check input { width: 1.05rem; height: 1.05rem; accent-color: var(--brand); flex: none; }

.adv-preview { display: flex; align-items: baseline; gap: .7rem; flex-wrap: wrap; margin-top: 1.25rem; padding: .8rem 1rem; border: 1px solid var(--border); border-left: 3px solid var(--brand); border-radius: var(--radius); background: var(--bg-elevated); }
.adv-preview-label { font-size: .7rem; text-transform: uppercase; letter-spacing: .06em; color: var(--text-subtle); white-space: nowrap; }
.adv-preview-q { font-family: var(--font-mono); font-size: .9rem; line-height: 1.5; color: var(--text); word-break: break-word; min-width: 0; }
.adv-preview-q:empty::before { content: attr(data-empty); color: var(--text-subtle); }

.adv-actions { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: .75rem; margin-top: 1.5rem; }
.adv-actions .btn { min-width: 8rem; justify-content: center; }

/* The boolean canvas (mounted by JS; flat rows hidden via [data-adv-words][hidden]). */
.adv-canvas[hidden], .adv-words[hidden] { display: none; }
.adv-canvas { display: flex; flex-direction: column; gap: .6rem; }
.adv-group { border: 1px solid var(--border); border-radius: var(--radius); padding: .65rem .7rem; background: var(--bg); }
.adv-group .adv-group { background: var(--bg-elevated); }
.adv-group-head { display: flex; align-items: center; gap: .4rem; flex-wrap: wrap; margin-bottom: .55rem; }
.adv-conn { display: inline-flex; border: 1px solid var(--border); border-radius: var(--radius-pill); overflow: hidden; flex: none; }
.adv-conn button { font: inherit; font-size: .76rem; font-weight: 600; padding: .18rem .65rem; border: 0; background: transparent; color: var(--text-muted); cursor: pointer; }
.adv-conn button.is-on { background: var(--brand); color: var(--brand-contrast); }
.adv-spacer { flex: 1 1 auto; }
.adv-iconbtn { font: inherit; font-size: .76rem; padding: .18rem .5rem; border: 1px solid var(--border); border-radius: var(--radius-sm); background: var(--surface); color: var(--text-muted); cursor: pointer; white-space: nowrap; }
.adv-iconbtn:hover { border-color: var(--brand); color: var(--brand); }
.adv-iconbtn.adv-rm { padding: .18rem .45rem; line-height: 1; }
.adv-nodes { display: flex; flex-direction: column; gap: .45rem; }
.adv-node { display: flex; align-items: center; gap: .45rem; flex-wrap: wrap; min-width: 0; }
.adv-cond { display: flex; align-items: center; gap: .4rem; flex: 1 1 16rem; min-width: 0; }
.adv-cond .field-input { flex: 1 1 8rem; width: auto; min-width: 0; }
.adv-cond .field-select { flex: 0 0 auto; width: auto; min-width: 0; font-size: .82rem; }
.adv-not { display: inline-flex; align-items: center; gap: .25rem; font-size: .76rem; color: var(--text-subtle); white-space: nowrap; }
.adv-canvas-hint { font-size: .78rem; color: var(--text-subtle); margin: .1rem 0 0; }

/* Global safe search: a per-type safe-search toggle locked ON by the master toggle (General pane). The server
   renders it disabled; .is-disabled (set live by 65-global-safe-search.ts) dims it to read as locked. */
.toggle.is-disabled { opacity: .55; }
.toggle.is-disabled, .toggle input:disabled { cursor: not-allowed; }
.settings-group-note { margin: .5rem 0 0; font-size: .82rem; }

/* ── Search-Control dedicated pages: icon-led cards (bangs/snaps/redirects/views) ──────────────────────────────── */
.sc-cards { display: flex; flex-direction: column; gap: .5rem; margin: 0 0 1.5rem; }
.sc-card { display: flex; align-items: center; gap: .75rem; padding: .7rem .9rem; border: 1px solid var(--border); border-radius: var(--radius); background: var(--surface); }
.sc-card.sc-card-off { opacity: .55; }
.sc-card-icon { flex: none; width: 2rem; height: 2rem; display: grid; place-items: center; border-radius: var(--radius-sm); }
.sc-card-icon svg { width: 1.2rem; height: 1.2rem; }
.sc-card-icon-bang { background: var(--brand-soft); color: var(--brand); }
.sc-card-icon-snap { background: var(--info-soft); color: var(--info); }
.sc-card-icon-redirect { background: var(--warning-soft); color: var(--warning); }
.sc-card-icon-view { background: var(--success-soft); color: var(--success); }
/* View cards carry a mode class too — match the icon stroke to its tinted box (boost=green, restrict=brand, filter=amber). */
.sc-card-icon-view.sc-rule-icon-raise { background: var(--success-soft); color: var(--success); }
.sc-card-icon-view.sc-rule-icon-pin   { background: var(--brand-soft); color: var(--brand-strong); }
.sc-card-icon-view.sc-rule-icon-lower { background: var(--warning-soft); color: var(--warning); }
.sc-card-main { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: .1rem; }
.sc-card-title { font-weight: 600; font-family: var(--font-mono); word-break: break-word; }
.sc-card-sub { font-size: .82rem; color: var(--text-muted); word-break: break-word; }
.sc-card-actions { flex: none; display: flex; align-items: center; gap: .5rem; flex-wrap: wrap; justify-content: flex-end; }
.sc-add-title { font-size: 1.05rem; margin: 1.75rem 0 .85rem; }
.sc-form { display: flex; flex-direction: column; gap: 1rem; max-width: 34rem; }
.sc-form .field { display: flex; flex-direction: column; gap: .3rem; }
.sc-form .field-label { font-weight: 550; font-size: .9rem; }
.sc-form .field-hint { margin: 0; font-size: .8rem; color: var(--text-subtle); }
.sc-builtins { margin-top: 1.75rem; }

/* ── Account › Email address (/account/settings/email) + the Account email-row Change button ─────────────────────── */
.email-page { max-width: 40rem; }
.account-email-value { display: flex; align-items: center; gap: 0.55rem; flex-wrap: wrap; justify-content: flex-end; }
.account-email-addr { word-break: break-all; min-width: 0; }
.account-email-change { flex: none; }
.email-badge-warn { background: var(--warning-soft); color: var(--warning); }

.email-current { display: flex; flex-direction: column; gap: 0.35rem; margin: 1.25rem 0;
    border: 1px solid var(--border); border-radius: var(--radius-lg); background: var(--surface); padding: 1rem 1.2rem; }
.email-current-label { font-size: 0.7rem; text-transform: uppercase; letter-spacing: 0.05em; color: var(--text-muted); }
.email-current-value { display: flex; align-items: center; gap: 0.6rem; flex-wrap: wrap; min-width: 0; }
.email-current-addr { font-size: 1.1rem; font-weight: 600; word-break: break-all; min-width: 0; }

.email-form { display: flex; flex-direction: column; gap: 1.15rem; margin-top: 0.4rem;
    border: 1px solid var(--border); border-radius: var(--radius-lg); background: var(--surface); padding: 1.4rem; }
.email-form .field { display: flex; flex-direction: column; gap: 0.4rem; }
.email-form .field-label { font-weight: 600; font-size: 0.9rem; }
.email-form .field-hint { font-size: 0.8rem; color: var(--text-subtle); line-height: 1.45; }
.email-form-submit { align-self: flex-start; min-width: 12rem; justify-content: center; margin-top: 0.2rem; }

.email-pending { display: flex; gap: 0.9rem; margin-top: 0.4rem;
    border: 1px solid color-mix(in srgb, var(--warning) 40%, var(--border)); border-radius: var(--radius-lg);
    background: var(--warning-soft); padding: 1.3rem; }
.email-pending-icon { flex: none; color: var(--warning); margin-top: 0.1rem; }
.email-pending-body { display: flex; flex-direction: column; gap: 0.45rem; min-width: 0; }
.email-pending-title { margin: 0; font-size: 1.05rem; }
.email-pending-text { margin: 0; color: var(--text); line-height: 1.5; }
.email-pending-addr { word-break: break-all; }
.email-pending-actions { display: flex; gap: 0.6rem; flex-wrap: wrap; margin-top: 0.35rem; }
.email-pending-actions form { margin: 0; }
@media (max-width: 30em) { .email-form-submit { width: 100%; align-self: stretch; } .account-email-value { justify-content: flex-start; } }

/* ===== Result Designer (WYSIWYG result-template editor) ===== */
.rd { margin-top: 0.5rem; }
.rd-nojs { padding: 1.5rem; text-align: center; }
.rd-stage { display: flex; flex-wrap: wrap; gap: 1.5rem; align-items: flex-start; }
.rd-stage-main { flex: 1 1 20rem; min-width: 0; }
.rd-panel { flex: 0 0 15rem; min-width: 0; display: flex; flex-direction: column; gap: 0.7rem; padding: 0.9rem; border: 1px solid var(--border); border-radius: var(--radius); background: var(--surface-2); position: sticky; top: 1rem; }
@media (max-width: 44em) { .rd-stage { flex-direction: column; } .rd-panel { position: static; flex-basis: auto; width: 100%; } }

.rd-canvas { border: 1px solid var(--border); border-radius: var(--radius); padding: 0.5rem 1rem; background: var(--surface); }
/* Square designer: the editable card wears the REAL tile chrome (media + foot meta) at grid-tile width, so
   what you design is what the results grid renders; context samples sit beside each other like a grid row. */
.rd-canvas .sq-card { max-inline-size: 16rem; }
.rd-ctx-row { display: flex; flex-wrap: wrap; gap: 1rem; align-items: flex-start; }
.rd-ctx-row .sq-card { flex: 0 1 14rem; min-width: 0; }
.rd-sample { animation: none; }
.rd-rowsolo { min-width: 0; }
.rd-context { margin-top: 0.5rem; border-top: 1px dashed var(--border); padding-top: 0.5rem; opacity: 0.85; }
/* closed-details hiding is overridable by author display on children (the nav pattern exploits this;
   here it backfires — the result cards carry their own display) — hide explicitly. */
details.rd-context:not([open]) > :not(summary) { display: none !important; }
.rd-context-label { margin: 1rem 0 0.4rem; font-size: 0.78rem; text-transform: uppercase; letter-spacing: 0.06em;
    cursor: pointer; list-style: none; display: inline-flex; align-items: center; gap: 0.4rem; border-radius: var(--radius-sm); padding: 0.15rem 0.3rem; }
.rd-context-label::-webkit-details-marker { display: none; }
.rd-context-label::before { content: "▸"; font-size: 0.7rem; transition: transform 0.15s ease; }
details.rd-context[open] > .rd-context-label::before { transform: rotate(90deg); }
.rd-context-label:hover { background: var(--surface-2); color: var(--text); }
.rd-context-label:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }
@media (prefers-reduced-motion: reduce) { .rd-context-label::before { transition: none; } }
.rd-empty { padding: 1rem 0; }

.rd-editable .rd-chip { display: block; position: relative; border-radius: var(--radius-sm); cursor: grab; outline: 1px dashed transparent; outline-offset: 2px; touch-action: none; user-select: none; -webkit-user-select: none; }
/* The favicon is an <img> — natively draggable, which hijacks pointermove and killed the chip drag (owner: "only
   the favicon won't drop"). draggable=false is set in JS; these are the CSS belts for WebKit + selection drags. */
.rd-editable .rd-chip img { -webkit-user-drag: none; user-drag: none; }
.rd-editable .rt-row { align-items: center; }
.rd-editable .rd-chip:hover { outline-color: var(--border-strong); }
.rd-editable .rd-chip:focus-visible { outline: 2px solid var(--brand-strong); }
.rd-editable .rd-chip.rd-selected { outline: 2px solid var(--brand); background: var(--brand-soft); }
body.rd-dragging { cursor: grabbing; user-select: none; }

.rd-slot { background: transparent; border-radius: 2px; transition: background 0.1s; }
.rd-slot-row { min-height: 4px; margin: 1px 0; }
.rd-slot-col { align-self: stretch; min-width: 4px; }
body.rd-dragging .rd-slot-row { min-height: 16px; background: var(--surface-2); }
body.rd-dragging .rd-slot-col { min-width: 16px; background: var(--surface-2); }
/* EDITABLE solo rows are flex like multi-element rows: (a) chips hug their content — a block .rd-rowsolo
   stretched a lone favicon's chip (and its cloned drag GHOST) to the full card width, burying the drop bands
   under a giant slab and making the selection outline read as full-width; (b) col slots get real height — as
   block children they were 0-tall and UNHITTABLE, so "drop beside a lone element" was silently impossible.
   Context cards keep the true block rendering (fidelity); the editable card trades exact solo-row geometry for
   a manipulable surface. */
.rd-editable .rd-rowsolo { display: flex; flex-wrap: wrap; align-items: baseline; }
body.rd-dragging .rd-rowsolo { display: flex; align-items: center; }
/* During a drag, SOLO text chips flex from basis 0 so the row's start/end col slots share their line — with the
   natural (max-content) basis, flex line-breaking exiled those slots to their own wrapped lines as invisible
   slivers (owner: "the excerpt's start/end dropzones don't appear unless the favicon is already there"). Atoms
   (favicon/date/number) stay content-sized. */
body.rd-dragging .rd-rowsolo > .rd-chip:has(> .result-title), body.rd-dragging .rd-rowsolo > .rd-chip:has(> .result-desc),
body.rd-dragging .rd-rowsolo > .rd-chip:has(> .result-url), body.rd-dragging .rd-rowsolo > .rd-chip:has(> .result-sitelinks) {
    flex: 1 1 0; min-width: 0;
}
.rd-slot.rd-slot-active { background: var(--brand) !important; }
.rd-ghost { position: fixed; z-index: 1000; pointer-events: none; opacity: 0.85; transform: translate(-50%, -50%); box-shadow: var(--shadow); background: var(--surface); border: 1px solid var(--brand); border-radius: var(--radius-sm); padding: 0.15rem 0.35rem; }
/* Multi-select: the drag ghost's count badge, dimmed origin chips, and the panel's mixed-value affordances. */
.rd-ghost-count { position: absolute; top: -0.5rem; inset-inline-end: -0.5rem; min-width: 1.1rem; text-align: center;
    background: var(--brand); color: var(--brand-contrast, #fff); border-radius: var(--radius-pill, 999px);
    font-size: 0.7rem; font-weight: 600; padding: 0 0.35rem; }
.rd-chip.rd-drag-src { opacity: 0.35; }
.rd-mixed-tag { font-size: 0.68rem; color: var(--text-muted); border: 1px dashed var(--border-strong);
    border-radius: var(--radius-pill, 999px); padding: 0 0.3rem; margin-inline-start: 0.3rem; }
.rd-toggle.mixed { border-style: dashed; color: var(--text); }
.rd-panel-sub { margin: -0.3rem 0 0.5rem; font-size: 0.8rem; }

.rd-tray-head { font-size: 0.72rem; margin: 0.9rem 0 0.35rem; }
.rd-tray { display: flex; flex-wrap: wrap; gap: 0.4rem; }
.rd-tray-chip { font-size: 0.8rem; cursor: grab; touch-action: none; color: var(--text); background: var(--surface-2); border: 1px dashed var(--border-strong); border-radius: var(--radius-pill); padding: 0.25rem 0.7rem; }
.rd-tray-chip:hover { border-color: var(--brand); color: var(--brand-strong); }
.rd-tray-chip:focus-visible { outline: 2px solid var(--brand-strong); outline-offset: 1px; }

.rd-panel-hint { margin: 0; font-size: 0.82rem; }
.rd-panel-head { display: flex; align-items: center; justify-content: space-between; gap: 0.5rem;
    font-weight: 600; font-size: 0.95rem; }
.rd-panel-head-label { min-width: 0; overflow-wrap: anywhere; }
/* The familiar top-right ✕ — hides the selected element(s); the accessible name carries the verb. */
.rd-close { flex: none; width: 1.5rem; height: 1.5rem; display: inline-flex; align-items: center;
    justify-content: center; cursor: pointer; color: var(--text-muted); background: transparent;
    border: 1px solid transparent; border-radius: var(--radius-pill); font-size: 0.8rem; line-height: 1; }
.rd-close:hover { color: var(--text); background: var(--surface-2); }
.rd-close:focus-visible { outline: 2px solid var(--brand-strong); outline-offset: 1px; }
.rd-field { display: flex; flex-direction: column; gap: 0.25rem; }
.rd-field-label { font-size: 0.72rem; color: var(--text-muted); }
.rd-seg { display: inline-flex; flex-wrap: wrap; gap: 0.15rem; padding: 0.2rem; background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-pill); }
.rd-seg-opt { min-width: 0; cursor: pointer; font-size: 0.78rem; color: var(--text-muted); background: transparent; border: 0; border-radius: var(--radius-pill); padding: 0.2rem 0.55rem; }
.rd-seg-opt:hover { color: var(--text); }
.rd-seg-opt.active { background: color-mix(in srgb, var(--accent) 16%, var(--surface)); color: var(--text); box-shadow: inset 0 0 0 1px var(--accent); }
.rd-seg-opt:focus-visible { outline: 2px solid var(--brand-strong); outline-offset: 1px; }
.rd-toggle { align-self: flex-start; font-size: 0.78rem; cursor: pointer; color: var(--text-muted); background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-pill); padding: 0.25rem 0.7rem; }
.rd-toggle.active { color: var(--text); border-color: var(--accent); box-shadow: inset 0 0 0 1px var(--accent); }
.rd-moves { display: flex; gap: 0.25rem; }
.rd-move { flex: 1 1 0; cursor: pointer; color: var(--text-muted); background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-sm); padding: 0.25rem 0; }
.rd-move:hover { color: var(--text); border-color: var(--border-strong); }

.rd-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 0.6rem; margin-top: 1.25rem; }
.rd-status { font-size: 0.85rem; color: var(--success); opacity: 0; transition: opacity 0.2s; }
.rd-status.rd-status-show { opacity: 1; }

/* Saved designs + built-in gallery strips (server-rendered, below the editor; work without JS). */
.rd-designs, .rd-gallery { margin-top: 2rem; }
.rd-strip-head { font-size: 1rem; margin: 0 0 0.75rem; }
.rd-embed { min-width: 0; }
.rd-design-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(14rem, 100%), 1fr)); gap: 1rem; }
.rd-design-card { display: flex; flex-direction: column; gap: 0.5rem; min-width: 0; padding: 0.75rem; border: 1px solid var(--border); border-radius: 0.6rem; background: var(--surface, var(--bg)); }
.rd-design-card.is-active { border-color: var(--brand); box-shadow: inset 0 0 0 1px var(--brand); }
.rd-mini { max-height: 8rem; overflow: hidden; padding: 0.5rem 0.6rem; border: 1px solid var(--border); border-radius: 0.4rem; background: var(--bg); font-size: 0.72rem; line-height: 1.3; pointer-events: none; }
.rd-mini .result-item { margin: 0; }
.rd-mini .result-card-tools { display: none; }   /* the ⋮ kebab isn't part of a design preview */
.rd-mini .result-favicon { width: 14px; height: 14px; }
/* Square minis: a full 4:3 media block would eat the whole preview box — a slim banner keeps the
   tile anatomy (media → rows → foot meta) recognizable inside the strip card. */
.rd-mini .sq-media { block-size: 3.2rem; aspect-ratio: auto; }
.rd-mini .sq-card .result-title:not([class*="rt-clamp"]),
.rd-mini .sq-card .result-desc:not([class*="rt-clamp"]) { -webkit-line-clamp: 2; }
.rd-design-name { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.4rem; min-width: 0; font-weight: 600; color: var(--text); }
.rd-design-name > span:first-child { overflow: hidden; text-overflow: ellipsis; }
.rd-active-badge { padding: 0 0.3rem; border: 1px solid var(--brand); border-radius: 0.3rem; font-size: 0.7rem; font-weight: 500; color: var(--brand); }
.rd-design-actions { display: flex; flex-wrap: wrap; gap: 0.4rem; margin-top: auto; }
/* Gallery cards: the single Use button sits at the card's end corner (owner-directed); the My-designs
   strip keeps its start-aligned multi-action row. flex-end is direction-aware, so RTL mirrors. */
.rd-gallery .rd-design-actions { justify-content: flex-end; }
.rd-design-actions form { display: inline; margin: 0; }

/* header theme cycle (marketing chrome; anonymous-visible) */
.app-header .theme-cycle { margin-inline-start: auto; font-size: 1rem; line-height: 1; padding: 0.35rem 0.55rem; }
.app-header .theme-cycle + .nav-disclosure { margin-inline-start: 0.25rem; }

/* ═══ Signup — the membership desk ═══
   Two columns at ≥56em (the form does the work; a quiet value rail says why), single column below.
   Signature: a slim aurora edge across the card's top — the landing pulse's colors, whispered. */
.signup-shell { align-items: flex-start; gap: clamp(2rem, 5vw, 3.5rem); }
/* The GREET state (no value rail): one card, vertically centered in the viewport on every form factor,
   with a roomier internal rhythm than the working signup form. */
.signup-shell:not(.has-aside) { min-height: 72dvh; align-items: center; }
.signup-shell:not(.has-aside) .auth-card--signup { padding: 2.5rem 2.25rem; }
.signup-shell:not(.has-aside) h1 { margin: 0 0 0.75rem; }
.signedin-as { margin-bottom: 1.75rem; }
.signedin-avatar { margin-bottom: 1.4rem; }
.signedin-actions { gap: 0.75rem; }
.signedin-switch { margin-top: 1.25rem; }
.signup-shell.has-aside { display: flex; flex-wrap: wrap; justify-content: center; }
.auth-card--signup { position: relative; overflow: hidden; }
.auth-card--signup::before { content: ""; position: absolute; inset-block-start: 0; inset-inline: 0; height: 3px;
    background: linear-gradient(90deg, var(--brand), #7ad0ff 35%, #b48bff 70%, var(--brand));
    background-size: 220% 100%; animation: signup-aurora 9s linear infinite; }
@keyframes signup-aurora { from { background-position: 0% 0; } to { background-position: 220% 0; } }
.signup-step { display: flex; align-items: baseline; gap: 0.5rem; margin: 0 0 0.9rem; font-size: 0.8125rem; color: var(--text-muted); }
.signup-step-badge { flex: none; font-weight: 700; font-size: 0.7rem; letter-spacing: 0.06em; text-transform: uppercase;
    color: var(--brand); border: 1px solid color-mix(in srgb, var(--brand) 45%, transparent);
    border-radius: var(--radius-pill, 999px); padding: 0.1rem 0.55rem;
    background: color-mix(in srgb, var(--brand) 8%, transparent); white-space: nowrap; }
.signup-cta { display: inline-flex; align-items: center; justify-content: center; gap: 0.5rem; margin-top: 0.75rem; }
.signup-cta-lock { width: 1.05em; height: 1.05em; flex: none; }
.signup-trust { display: flex; flex-direction: column; gap: 0.2rem; text-align: center; margin-top: 0.8rem;
    font-size: 0.8125rem; color: var(--text-muted); }
.signup-stripe { font-size: 0.75rem; color: var(--text-subtle); }
.signup-aside { flex: 0 1 19rem; min-width: 15rem; padding-block-start: 0.5rem; }
.signup-aside-title { font-size: 0.75rem; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase;
    color: var(--text-muted); margin: 0 0 0.7rem; }
.signup-aside-title + .signup-aside-title, .signup-how { margin-top: 0; }
.signup-value-list { list-style: none; margin: 0 0 1.6rem; padding: 0; display: flex; flex-direction: column; gap: 0.55rem; }
.signup-value-list li { display: flex; gap: 0.55rem; align-items: flex-start; font-size: 0.9rem; color: var(--text); }
.signup-value-list .check { color: var(--success); flex: none; }
.signup-how { margin: 0; padding-inline-start: 1.2rem; display: flex; flex-direction: column; gap: 0.45rem;
    font-size: 0.9rem; color: var(--text-muted); }
.signup-how li::marker { color: var(--brand); font-weight: 700; }
.signedin-avatar { width: 3rem; height: 3rem; margin-inline: auto; border-radius: 50%; display: flex; align-items: center; justify-content: center;
    font-weight: 800; font-size: 1.2rem; color: var(--brand-strong, var(--brand));
    background: color-mix(in srgb, var(--brand) 14%, transparent);
    border: 1px solid color-mix(in srgb, var(--brand) 40%, transparent); margin-bottom: 0.9rem; }
.signedin-as { overflow-wrap: anywhere; }
@media (max-width: 56em) { .signup-aside { flex-basis: 100%; max-width: 420px; } }
@media (prefers-reduced-motion: reduce) { .auth-card--signup::before { animation: none; } }

/* Settings > Search — the Default display mode pushbuttons (the results toolbar's language, radio-backed
   so the plain form post works without JS; the check state mirrors .view-opt.active). */
.vm-seg { justify-content: flex-start; }
.vm-opt { cursor: pointer; }
.vm-opt input { position: absolute; width: 1px; height: 1px; opacity: 0; pointer-events: none; }
.vm-opt:has(input:checked) { background: color-mix(in srgb, var(--brand) 16%, transparent); color: var(--text); border-color: var(--brand); }
.vm-opt:has(input:focus-visible) { outline: 2px solid var(--ring); outline-offset: 2px; }

/* ---------- Support portal (/support) ---------- */
/* Reflow-first: rem spacing, flex-wrap, min-width:0 — readable at 200% text with no horizontal scroll. */
.support-page .page-head { padding-block-end: 1rem; }
.support-actions { display: flex; flex-wrap: wrap; gap: 0.6rem; margin-block: 0.5rem 1.5rem; }
.support-list-title { font-size: 1.1rem; margin-block: 1.25rem 0.6rem; }
.support-ticket-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0.5rem; }
.support-ticket-row { border: 1px solid var(--border); border-radius: var(--radius); background: var(--surface); }
.support-ticket-link { display: flex; flex-wrap: wrap; gap: 0.5rem 1rem; align-items: baseline; justify-content: space-between;
    padding: 0.7rem 0.9rem; color: inherit; }
.support-ticket-link:hover { text-decoration: none; background: var(--surface-2); border-radius: var(--radius); }
.support-ticket-subject { flex: 1 1 16rem; min-width: 0; overflow-wrap: anywhere; font-weight: 600; }
.support-ticket-num { color: var(--text-muted); font-weight: 600; font-variant-numeric: tabular-nums; }
.support-ticket-meta { display: flex; flex-wrap: wrap; gap: 0.6rem; align-items: baseline; }
.support-newreply { display: inline-block; margin-inline-start: 0.4rem; padding: 0.05rem 0.5rem; border-radius: 999px;
    background: var(--brand); color: var(--brand-contrast); font-size: 0.72rem; font-weight: 700; }
.support-status { display: inline-block; padding: 0.1rem 0.55rem; border-radius: 999px; font-size: 0.78rem; font-weight: 700;
    border: 1px solid var(--border); }
.support-status-new, .support-status-open { background: var(--success-soft); color: var(--success); border-color: transparent; }
.support-status-pending { background: var(--warning-soft); color: var(--warning); border-color: transparent; }
.support-status-on_hold { color: var(--text-muted); }
.support-status-solved { color: var(--success); }
.support-status-closed { color: var(--text-muted); }

.support-new-layout { display: flex; flex-wrap: wrap; gap: 2rem; align-items: flex-start; }
.support-new-form { flex: 1 1 24rem; min-width: 0; }
.support-new-aside { flex: 1 1 14rem; min-width: min(14rem, 100%); max-width: 22rem; }
.support-impact { border: 0; padding: 0; margin: 0 0 1.1rem; }
.support-impact-opt { display: flex; gap: 0.5rem; align-items: baseline; padding-block: 0.25rem; }
.support-diag-label { display: flex; gap: 0.5rem; align-items: baseline; font-weight: 600; font-size: 0.9375rem; }
.support-file-input { font-size: 0.9rem; max-width: 100%; }
.support-suggest { border: 1px solid var(--border); border-radius: var(--radius); background: var(--surface-2);
    padding: 0.75rem 0.9rem; margin-block-end: 1.1rem; }
.support-suggest-title { margin: 0 0 0.4rem; font-weight: 600; font-size: 0.9rem; }
.support-suggest-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0.3rem; font-size: 0.92rem; }

.support-ticket-title { overflow-wrap: anywhere; }
.support-ticket-headline { display: flex; flex-wrap: wrap; gap: 0.6rem; align-items: baseline; margin-block-start: 0.4rem; }
.support-transcript { font-size: 0.85rem; }
.support-sla-line { display: block; margin-block-start: 0.25rem; }
.support-newreply-note[hidden] { display: none; }

.support-thread { list-style: none; margin: 1rem 0; padding: 0; display: flex; flex-direction: column; gap: 0.75rem; }
.support-msg { border: 1px solid var(--border); border-radius: var(--radius); background: var(--surface); padding: 0.8rem 1rem; }
.support-msg-staff { border-inline-start: 0.2rem solid var(--brand); }
.support-msg-you { background: var(--surface-2); }
.support-msg-head { display: flex; flex-wrap: wrap; gap: 0.5rem 0.75rem; align-items: baseline; margin-block-end: 0.4rem; font-size: 0.875rem; }
.support-msg-body { white-space: pre-wrap; overflow-wrap: anywhere; }
.support-msg-attachments { list-style: none; margin: 0.5rem 0 0; padding: 0; display: flex; flex-wrap: wrap; gap: 0.6rem; font-size: 0.85rem; }
.support-event { color: var(--text-muted); font-size: 0.85rem; padding-inline-start: 0.5rem; }
.support-event-time { white-space: nowrap; }

.support-composer-wrap { margin-block: 1.25rem 2rem; }
.support-composer { display: flex; flex-direction: column; gap: 0.6rem; }
.support-composer-foot { display: flex; flex-wrap: wrap; gap: 0.75rem; align-items: center; }
.support-composer-foot .btn-primary { margin-inline-start: auto; }
.support-file-label { display: inline-flex; flex-wrap: wrap; gap: 0.4rem; align-items: center; font-size: 0.9rem; color: var(--text-muted); min-width: 0; }
.support-self-actions { display: flex; flex-wrap: wrap; gap: 0.5rem; margin-block-start: 0.75rem; }

.support-csat { margin-block: 1.25rem; }
.support-csat-title { font-size: 1.05rem; margin: 0 0 0.6rem; }
.support-csat-form { display: flex; flex-direction: column; gap: 0.6rem; }
.support-csat-choices { display: flex; flex-wrap: wrap; gap: 1rem; }
.support-csat-opt { display: inline-flex; gap: 0.4rem; align-items: baseline; font-weight: 600; }
.support-csat-form .btn { align-self: flex-start; }
/* Reflow: every support-page button wraps its label at large text sizes rather than forcing h-scroll. */
.support-page .btn { white-space: normal; line-height: 1.25; }
.support-self-actions form { min-width: 0; max-width: 100%; }

/* ── Instant answers ─────────────────────────────────────────────────────────────────────────────
   The answer card sits between the rank summary and the results. Fully SSR; 22-instant-answers.ts
   reveals the copy button and upgrades live widgets. rem-based throughout (reflows at 200% text);
   direction-neutral (logical properties) so RTL mirrors for free. */
.ia-card { border: 1px solid var(--border); border-radius: var(--radius); background: var(--surface);
  padding: 1rem 1.125rem; margin: 0.25rem 0 1rem; max-width: 42rem; }
.ia-card.ia-error { border-color: var(--border-strong); }
.ia-label { font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.06em; margin: 0 0 0.25rem; }
.ia-primary { font-size: 1.75rem; font-weight: 650; line-height: 1.2; margin: 0;
  font-variant-numeric: tabular-nums; overflow-wrap: anywhere; }
.ia-error .ia-primary { color: var(--text-muted); }
.ia-expression { font-size: 0.875rem; margin: 0.25rem 0 0; overflow-wrap: anywhere; }
.ia-secondary { font-size: 0.9375rem; margin: 0.375rem 0 0; color: var(--text); overflow-wrap: anywhere; }
.ia-items { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(11rem, 100%), 1fr));
  gap: 0.375rem 1rem; margin: 0.625rem 0 0; }
.ia-item dt { font-size: 0.75rem; color: var(--text-muted); }
.ia-item dd { margin: 0; font-size: 0.9375rem; font-variant-numeric: tabular-nums; overflow-wrap: anywhere; }
.ia-svg svg { width: min(11rem, 60vw); height: auto; display: block; margin: 0.375rem 0; border-radius: 0.5rem; }
.ia-foot { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem 0.75rem; margin-top: 0.625rem; }
.ia-foot:empty { display: none; }
.ia-copy { font-size: 0.8125rem; padding: 0.25rem 0.75rem; border: 1px solid var(--border);
  border-radius: var(--radius-pill); background: none; color: var(--text); cursor: pointer; }
.ia-copy:hover { border-color: var(--border-strong); }
.ia-requeries { display: flex; flex-wrap: wrap; gap: 0.375rem; min-width: 0; }
.ia-requery { font-size: 0.8125rem; padding: 0.25rem 0.75rem; border: 1px solid var(--border);
  border-radius: var(--radius-pill); text-decoration: none; color: var(--text-muted); white-space: nowrap; }
.ia-requery:hover { color: var(--text); border-color: var(--border-strong); }
.ia-disclosure { font-size: 0.75rem; margin: 0.625rem 0 0; }

/* Flagship timezone card: ONE shared content width for everything that reads as a timeline —
   the city matrix, the hour axis, the slider, and the map — so their right edges line up as a
   single column instead of each element picking its own stopping point. */
.ia-tz { --tz-content: 46rem; --tz-label-col: clamp(9rem, 32%, 15rem); }

/* The city matrix. Every row (and the axis) uses the SAME grid template — city block | timeline —
   which is what actually aligns the strips into one comparable band. Collapses to stacked
   label-over-strip below the em breakpoint (strips stay full-width ⇒ still aligned). */
.ia-tz-axis { display: grid; grid-template-columns: var(--tz-label-col) minmax(0, 1fr);
  column-gap: 1rem; align-items: end; max-width: var(--tz-content); margin: 0.75rem 0 0; }
.ia-tz-axis-label { font-size: 0.6875rem; }
.ia-tz-axis-scale { position: relative; display: block; height: 1rem; font-size: 0.6875rem;
  font-variant-numeric: tabular-nums; }
.ia-tz-axis-scale i { position: absolute; bottom: 0; font-style: normal; transform: translateX(-50%); }
.ia-tz-axis-scale i:nth-child(1) { left: 0; transform: none; }
.ia-tz-axis-scale i:nth-child(2) { left: 25%; }
.ia-tz-axis-scale i:nth-child(3) { left: 50%; }
.ia-tz-axis-scale i:nth-child(4) { left: 75%; }
.ia-tz-axis-scale i:nth-child(5) { left: 100%; transform: translateX(-100%); }
.ia-tz-rows { list-style: none; margin: 0.25rem 0 0; padding: 0; display: grid; gap: 0.625rem;
  max-width: var(--tz-content); }
.ia-tz-row { display: grid; grid-template-columns: var(--tz-label-col) minmax(0, 1fr);
  column-gap: 1rem; align-items: center; min-width: 0; }
.ia-tz-rowhead { display: grid; gap: 0.125rem; min-width: 0; }
.ia-tz-headline { display: flex; align-items: center; gap: 0.375rem; min-width: 0; }
.ia-tz-meta { display: flex; flex-wrap: wrap; align-items: center; gap: 0.25rem 0.5rem; }
.ia-tz-glyph { width: 1.25rem; text-align: center; flex: none; }
.ia-tz-city { font-weight: 550; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ia-tz-remove { flex: none; margin-inline-start: auto; width: 1.25rem; height: 1.25rem;
  display: inline-flex; align-items: center; justify-content: center; border-radius: var(--radius-pill);
  color: var(--text-muted); text-decoration: none; font-size: 0.75rem; line-height: 1;
  opacity: 0; transition: opacity 120ms ease; }
.ia-tz-row:hover .ia-tz-remove, .ia-tz-row:focus-within .ia-tz-remove { opacity: 1; }
.ia-tz-remove:hover, .ia-tz-remove:focus-visible { color: var(--text); background: var(--border); opacity: 1; }
@media (prefers-reduced-motion: reduce) { .ia-tz-remove { transition: none; } }
@media (hover: none) { .ia-tz-remove { opacity: 1; } }   /* touch: no hover to reveal — always visible */
.ia-tz-time { font-variant-numeric: tabular-nums; font-size: 1.0625rem; }
.ia-tz-chip { font-size: 0.6875rem; border: 1px solid var(--border); border-radius: var(--radius-pill);
  padding: 0.0625rem 0.5rem; color: var(--text-muted); white-space: nowrap; }
.ia-tz-dst { border-style: dashed; }
.ia-tz-strip { display: flex; gap: 1px; height: 0.875rem; min-width: 0; }
.ia-tz-slot { flex: 1 1 0; border-radius: 1px; background: var(--border); }
.ia-tz-b { background: var(--brand); }
.ia-tz-d { background: var(--border-strong); }
.ia-tz-next { font-size: 0.75rem; }
.ia-tz-unix { font-size: 0.8125rem; font-variant-numeric: tabular-nums; }
/* The card mid-swap (add/remove/knobs fetch the fresh server render): calm, no layout shift. */
.ia-tz[aria-busy="true"] { opacity: 0.6; transition: opacity 120ms ease; }
@media (prefers-reduced-motion: reduce) { .ia-tz[aria-busy="true"] { transition: none; } }
@media (max-width: 38em) {
  .ia-tz-row, .ia-tz-axis { grid-template-columns: minmax(0, 1fr); }
  .ia-tz-axis-label { display: none; }
  .ia-tz-remove { opacity: 1; }
}

/* Timer state: a static (reduced-motion-safe) accent when the countdown completes; the SR live
   region announces regardless of audio. */
.ia-timer-done .ia-primary { color: var(--brand-strong); }
.ia-card .visually-hidden { position: absolute; width: 1px; height: 1px; margin: -1px;
  clip-path: inset(50%); overflow: hidden; white-space: nowrap; }
.ia-tz-legend { display: flex; align-items: center; gap: 0.375rem; font-size: 0.75rem; margin: 0.375rem 0 0; }
.ia-tz-legend .ia-tz-slot { flex: 0 0 auto; width: 0.75rem; height: 0.5rem; }

/* The flagship world map: theme-aware sea/land, computed night + twilight overlays, city markers.
   Night stays darker than day in EVERY mode. The overlay is a component token because one literal
   can't serve both grounds: over the light sea a soft navy veil reads clearly, but over the dark
   theme's #14121f sea the same veil was near-invisible — dark themes deepen the fill to black and
   raise the opacity (the app.css dual pattern, scoped: media query for system dark, [data-theme]
   for the explicit toggle, both directions). High-contrast adds a STROKED terminator edge — over a
   solid-black (light-HC) or solid-white (dark-HC) landmass a fill difference alone can't carry the
   boundary. forced-colors keeps geometry, drops the tints. */
.ia-tz-map { margin: 0.625rem 0 0; max-width: var(--tz-content, 46rem);
  --ia-map-night: #0b1026; --ia-map-night-op: 0.30; --ia-map-twilight-op: 0.15; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .ia-tz-map {
    --ia-map-night: #000000; --ia-map-night-op: 0.50; --ia-map-twilight-op: 0.25; }
}
:root[data-theme="dark"] .ia-tz-map {
  --ia-map-night: #000000; --ia-map-night-op: 0.50; --ia-map-twilight-op: 0.25; }
.ia-tz-map svg { width: 100%; height: auto; display: block; }
.ia-map-sea { fill: var(--surface); stroke: var(--border); stroke-width: 1; }
.ia-map-land { fill: var(--border-strong); }
.ia-map-twilight { fill: var(--ia-map-night); opacity: var(--ia-map-twilight-op); }
.ia-map-night { fill: var(--ia-map-night); opacity: var(--ia-map-night-op); }
.ia-map-halo { fill: var(--brand); opacity: 0.25; }
.ia-map-dot { fill: var(--text-muted); }
.ia-map-dot--primary { fill: var(--brand); }
.ia-map-line { stroke: var(--brand); stroke-width: 1.5; fill: none; stroke-dasharray: 4 3; opacity: 0.7; }
[data-contrast="high"] .ia-map-night,
[data-contrast="high"] .ia-map-twilight { stroke: var(--text); stroke-width: 1; }
[data-contrast="high"] .ia-map-night { opacity: 0.40; }
@media (prefers-contrast: more) {
  .ia-map-night, .ia-map-twilight { stroke: var(--text); stroke-width: 0.75; }
}
@media (forced-colors: active) {
  .ia-map-sea { fill: Canvas; stroke: CanvasText; }
  .ia-map-land { fill: CanvasText; }
  .ia-map-twilight, .ia-map-night { fill: none; }
  .ia-map-halo { fill: none; }
  .ia-map-dot, .ia-map-dot--primary { fill: Highlight; }
}

/* The time slider — the flagship's central lever. A GET form; the range sweeps the reference zone's
   chosen day in quarter-hours; Apply submits no-JS and the client module hides it once live. The
   axis is pinned ltr (a day axis never mirrors in RTL — it must stay aligned with the strips and
   the map); labels around it stay logical. The strip cursor uses physical `left` deliberately: its
   container is dir=ltr. */
.ia-tz-slider { display: grid; grid-template-columns: var(--tz-label-col) minmax(0, 1fr);
  column-gap: 1rem; align-items: center; margin-top: 0.625rem; min-width: 0;
  max-width: var(--tz-content, 46rem); }
.ia-tz-slider-head { display: flex; flex-wrap: wrap; align-items: center; gap: 0.375rem; min-width: 0; }
.ia-tz-range { width: 100%; min-width: 0; accent-color: var(--brand); margin: 0; }
@media (max-width: 38em) {
  .ia-tz-slider { grid-template-columns: minmax(0, 1fr); row-gap: 0.375rem; }
}
.ia-tz-date input { font: inherit; font-size: 0.8125rem; padding: 0.2rem 0.5rem;
  border: 1px solid var(--border); border-radius: var(--radius);
  background: var(--input-bg); color: var(--text); }
.ia-tz-strip { position: relative; }
.ia-tz-cursor { position: absolute; inset-block: -2px; left: var(--tz-cursor, 50%); width: 2px;
  margin-left: -1px; border-radius: 1px; background: var(--brand-strong); }
@media (forced-colors: active) { .ia-tz-cursor { background: Highlight; } }

.ia-tz-knobs { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem 1rem; margin-top: 0.625rem; }
.ia-tz-add { display: flex; flex-wrap: wrap; align-items: center; gap: 0.375rem; min-width: 0; position: relative; }
.ia-tz-add-input[aria-invalid="true"] { border-color: var(--danger); }
.ia-tz-add-error { font-size: 0.75rem; color: var(--danger); flex-basis: 100%; }
.ia-tz-add-input { font-size: 0.8125rem; padding: 0.25rem 0.625rem; border: 1px solid var(--border);
  border-radius: var(--radius-pill); background: none; color: var(--text); width: 11rem; max-width: 100%; }
.ia-tz-suggest { position: absolute; top: calc(100% + 0.25rem); inset-inline-start: 0; z-index: 30;
  background: var(--surface); border: 1px solid var(--border-strong); border-radius: var(--radius);
  min-width: 14rem; max-width: 90vw; padding: 0.25rem; display: grid; }
.ia-tz-suggest button { text-align: start; padding: 0.375rem 0.625rem; border: 0; background: none;
  color: var(--text); border-radius: 0.375rem; cursor: pointer; font-size: 0.875rem; }
.ia-tz-suggest button:hover, .ia-tz-suggest button[aria-selected="true"] { background: var(--border); }
.ia-tz-suggest .muted { font-size: 0.75rem; }
.ia-live { display: flex; flex-wrap: wrap; gap: 0.5rem 1rem; margin: 0.625rem 0 0; }
.ia-live-field { display: grid; gap: 0.125rem; font-size: 0.75rem; color: var(--text-muted); min-width: 0; }
.ia-live-field input { width: 6.5rem; max-width: 100%; font-size: 0.875rem; padding: 0.25rem 0.5rem;
  border: 1px solid var(--border); border-radius: 0.5rem; background: none; color: var(--text);
  font-variant-numeric: tabular-nums; }

/* Definitions (the dictionary card). The day-to-day shape is: headword row (word + IPA + play),
   POS sections with numbered senses, linked Wiktionary attribution. Mixed-direction: under an RTL
   page, English content (the labeled EN-gloss fallback) renders as proper LTR islands. */
.ia-def-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.25rem 0.625rem; }
.ia-def-head .ia-primary { margin: 0; }
.ia-def-ipa { font-size: 0.875rem; unicode-bidi: isolate; }
.ia-def-play { border: 1px solid var(--border); border-radius: var(--radius-pill); background: none;
  color: var(--text-muted); width: 1.75rem; height: 1.75rem; display: inline-flex; align-items: center;
  justify-content: center; cursor: pointer; align-self: center; flex: none; }
.ia-def-play:hover { color: var(--text); border-color: var(--border-strong); }
.ia-def-play[data-state="playing"] { color: var(--brand-strong); border-color: var(--brand-strong); }
.ia-def-play[data-state="loading"] .ia-def-play-wave,
.ia-def-play[data-state="playing"] .ia-def-play-wave { animation: ia-def-wave 1s ease-in-out infinite; }
@keyframes ia-def-wave { 0%, 100% { opacity: 1; } 50% { opacity: 0.25; } }
@media (prefers-reduced-motion: reduce) { .ia-def-play .ia-def-play-wave { animation: none !important; } }
@media (forced-colors: active) { .ia-def-play[data-state="playing"] { color: Highlight; border-color: Highlight; } }
.ia-def-glossnote { font-size: 0.75rem; margin: 0.375rem 0 0; }
.ia-def-pos { margin-top: 0.625rem; }
.ia-def-posname { font-size: 0.6875rem; font-weight: 600; letter-spacing: 0.06em; text-transform: uppercase;
  margin: 0 0 0.25rem; }
.ia-def-senses { margin: 0; padding-inline-start: 1.375rem; display: grid; gap: 0.375rem;
  font-size: 0.9375rem; line-height: 1.5; }
.ia-def-senses li::marker { color: var(--text-muted); font-size: 0.8125rem; }
.ia-def-example { font-size: 0.8125rem; margin: 0.125rem 0 0; font-style: italic; }
.ia-def-more { margin-top: 0.375rem; }
.ia-def-more > summary { cursor: pointer; font-size: 0.8125rem; color: var(--link);
  width: fit-content; }
.ia-def-more[open] > summary { margin-bottom: 0.375rem; }
.ia-def-more > .ia-def-senses { margin-top: 0.25rem; }
.ia-disclosure a { color: inherit; text-decoration: underline; text-underline-offset: 2px; }
.ia-def-credit { display: inline-block; margin-inline-start: 0.625rem; }
.ia-def-credit > summary { cursor: pointer; display: inline; color: var(--link); }
.ia-def-credit > span { display: block; margin-top: 0.25rem; }
/* LTR islands under an RTL page: the labeled English-gloss fallback (and any en-tagged content). */
[dir="rtl"] .ia-def [lang="en"], [dir="rtl"] .ia-def[data-ia-kind] .ia-def-senses[lang="en"] {
  direction: ltr; text-align: start; }
[dir="rtl"] .ia-def .ia-def-senses[lang="en"] { padding-inline-start: 1.375rem; }

/* The Search button lives INSIDE the pill (its far end), so the autosuggest dropdown — which opens
   below the form stack — can never occupy the same space as the button. The old z-stacking
   mitigation (z 45 over the panel) is retired with the collision itself; the BAR row (the form is
   a column stack now) still never wraps. */
.search-bar { flex-wrap: nowrap; }

/* --- /bot — Neuji-HealthMonitor documentation (reuses the .legal typography; adds the ranges table).
   The table wrapper scrolls on its own axis so enlarged text reflows without page-level horizontal
   scroll (WCAG 1.4.10); code spans stay LTR islands under the RTL UI languages. --- */
.botdoc .tbl { overflow-x: auto; margin: 0.5rem 0 1rem; }
.botdoc table { border-collapse: collapse; min-width: 100%; }
.botdoc th, .botdoc td { text-align: start; padding: 0.4rem 1.1rem 0.4rem 0; border-bottom: 1px solid var(--border); white-space: nowrap; }
.botdoc th { font-size: 0.85rem; color: var(--muted, inherit); font-weight: 600; }
.botdoc code { direction: ltr; unicode-bidi: isolate; }

/* ── Views collection (settings): the unified user-orderable list ─────────────────────────────────
   Rows carry a ⠿ drag handle (revealed only when JS wires the list — .view-list--drag) and always-on
   accessible ↑/↓ buttons (the no-JS / keyboard path). Built-in rows are badged; the handle column keeps
   the cards aligned whether or not the row is draggable. */
.view-collection-row { align-items: center; flex-wrap: wrap; }
.view-collection-row .sc-card-main { min-width: 0; flex: 1 1 12rem; }
/* System (built-in) rows: the layers glyph in a muted brand tone — the icon alone marks a system view. */
.sc-card-icon-builtin { color: var(--text-muted); background: var(--surface-2); }
/* The enable switch is the LAST action in every row; pinning it to the row's end aligns the toggles in one
   column regardless of what other actions a row carries. */
.view-collection-row .sc-card-actions .view-switch-form { margin-inline-start: auto; }

/* flex 0 1 auto (base is flex:none): the actions block must be SHRINKABLE for its internal wrap to
   engage at large text — flex:none lets it overflow the row instead. */
.view-collection-row .sc-card-actions { flex: 0 1 auto; flex-wrap: wrap; min-width: 0; }
.view-collection-row .view-share { min-width: 0; }
.view-collection-row .view-share-actions { flex-wrap: wrap; }
.view-collection-row .btn, .view-collection-row .rank-unblock { white-space: normal; max-inline-size: 100%; }
.view-drag { display: none; cursor: grab; color: var(--text-subtle); font-size: 1rem; padding: 0.25rem; user-select: none; }
.view-list--drag .view-drag { display: inline-block; }
.view-list--drag [data-view-slug].is-dragging { opacity: 0.5; }
.view-updown { display: inline-flex; flex-direction: column; gap: 0.1rem; }
.view-updown form { margin: 0; }
.view-move {
    display: inline-flex; align-items: center; justify-content: center; inline-size: 1.5rem; block-size: 1.15rem;
    font: inherit; font-size: 0.75rem; line-height: 1; cursor: pointer; color: var(--text-muted);
    background: var(--surface-2); border: 1px solid var(--border); border-radius: var(--radius-sm);
}
.view-move:hover:not(:disabled) { color: var(--text); border-color: var(--border-strong); }
.view-move:disabled { opacity: 0.35; cursor: default; }

/* ── The per-view EDITOR (identity header · sites-first card · grouped form · danger zone) ── */
.vw-page { max-inline-size: 52rem; }
.vw-identity { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.35rem 0.8rem; min-width: 0; }
.vw-identity h1 { margin: 0; overflow-wrap: anywhere; }
.vw-identity-meta { display: inline-flex; flex-wrap: wrap; align-items: center; gap: 0.45rem; }
.vw-slug-chip { font-size: 0.85rem; padding: 0.1rem 0.5rem; background: var(--surface-2); border: 1px solid var(--border); border-radius: var(--radius-pill); color: var(--text-muted); }
.vw-mode-chip { text-transform: none; }
.vw-mode-boost { color: var(--success); border-color: currentColor; }
.vw-mode-restrict { color: var(--brand-strong); border-color: currentColor; }
.vw-mode-filter { color: var(--warning); border-color: currentColor; }

.vw-card { padding: 1.15rem 1.3rem; margin-block-end: 1.1rem; }
.vw-card-head { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: 0.3rem 1rem; margin-block-end: 0.85rem; }
.vw-card-head h2 { font-size: 1.02rem; margin: 0; }
.vw-card-head .muted { margin: 0; font-size: 0.85rem; flex-basis: 100%; }

/* Sites & keywords */
.vw-restrict-meter { font-variant-numeric: tabular-nums; font-size: 0.8rem; font-weight: 700; color: var(--text-muted); padding: 0.1rem 0.55rem; border: 1px solid var(--border); border-radius: var(--radius-pill); }
.vw-restrict-meter-hot { color: var(--warning); border-color: currentColor; }
.vw-empty { padding: 1rem 0.2rem; color: var(--text-muted); }
.vw-empty p { margin: 0; }
.vw-rule-list { margin: 0 0 0.9rem; padding: 0; list-style: none; }
.vw-rule-row { display: flex; flex-wrap: wrap; align-items: center; gap: 0.4rem 0.75rem; padding: 0.5rem 0.15rem; border-block-end: 1px solid var(--border); }
.vw-rule-row:last-child { border-block-end: 0; }
.vw-rule-kind-ic { display: inline-flex; inline-size: 1.05rem; block-size: 1.05rem; color: var(--text-subtle); flex: none; }
.vw-rule-kind-ic svg { inline-size: 100%; block-size: 100%; }
.vw-rule-row .rule-pattern { display: flex; flex-wrap: wrap; align-items: center; gap: 0.4rem; min-width: 0; overflow-wrap: anywhere; flex: 1 1 12rem; }
.vw-rule-row .rule-del { margin-inline-start: auto; }
/* Included/Excluded group scaffolding — the group heading carries the include/exclude meaning
   (rows stay clean: no strikethrough, no per-row Excluded badge). */
.vw-group-head { margin: 0.7rem 0 0.15rem; font-size: 0.72rem; font-weight: 700; letter-spacing: 0.05em;
    text-transform: uppercase; color: var(--text-muted); }
.vw-group-hint { margin: 0 0 0.25rem; font-size: 0.78rem; color: var(--text-subtle); }
.vw-sites-context { margin: -0.35rem 0 0.75rem; font-size: 0.85rem; }
.vw-sites-warn { margin-block-end: 0.9rem; }
.vw-site-add { display: flex; flex-wrap: wrap; gap: 0.5rem; align-items: center; }
.vw-site-add .field-input { flex: 1 1 14rem; min-width: 0; }
.vw-site-add .field-select { width: auto; flex: 0 1 auto; }
.vw-site-add .btn { flex: none; }
.vw-grammar { margin: 0.6rem 0 0; font-size: 0.8rem; display: flex; flex-wrap: wrap; align-items: center; gap: 0.25rem 0.45rem; }
.vw-grammar code { font-size: 0.78rem; background: var(--surface-2); border: 1px solid var(--border); border-radius: var(--radius-sm); padding: 0.05rem 0.35rem; overflow-wrap: anywhere; }

/* Field groups */
.vw-field-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(14rem, 100%), 1fr)); gap: 0.85rem 1.1rem; }
.vw-field { display: flex; flex-direction: column; gap: 0.3rem; min-width: 0; }
.vw-field > span { font-size: 0.8rem; font-weight: 600; color: var(--text-muted); }
.vw-field-hint { font-size: 0.76rem; color: var(--text-subtle); line-height: 1.35; }
.vw-field-wide { grid-column: 1 / -1; }
.vw-field-check { flex-direction: row; align-items: center; gap: 0.5rem; }
.vw-field-check > span { font-size: inherit; font-weight: 500; color: var(--text); }

/* Activation bang adornment */
.vw-bang-wrap { display: flex; align-items: stretch; min-width: 0; }
.vw-bang-prefix { display: inline-flex; align-items: center; padding: 0 0.6rem; font-weight: 700; color: var(--text-muted); background: var(--surface-2); border: 1px solid var(--border); border-inline-end: 0; border-start-start-radius: var(--radius-sm); border-end-start-radius: var(--radius-sm); }
.vw-bang-input { border-start-start-radius: 0; border-end-start-radius: 0; min-width: 0; }

/* Sticky save — always reachable while editing a long form. */
.vw-savebar { position: sticky; inset-block-end: 0; z-index: 5; display: flex; justify-content: flex-end; padding: 0.6rem 0.2rem; background: linear-gradient(to top, var(--bg) 65%, transparent); }

/* Destructive button (confirm dialog). */
.btn-danger { background: transparent; color: var(--danger); border: 1px solid currentColor; }
.btn-danger:hover { background: color-mix(in srgb, var(--danger) 12%, transparent); }

/* The time-scope group: three UNIFORM label-above fields (preset select + the custom date pair) on one
   row — bottom-aligned so the inputs sit on one line (and single-line labels on another), wrapping on
   narrow screens. The dates wrapper is display:contents so its two fields are laid out as direct row
   items; author display beats the UA's [hidden] rule, so hiding needs the explicit [hidden] override. */
.vw-time-group { border: 0; padding: 0; margin: 0; min-width: 0; }
/* Top-aligned: single-line labels sit on one line and the input TOPS on another (a native date input
   renders ~2px taller than a select, so bottom-alignment would nudge the select's label down). */
.vw-time-row { display: flex; flex-wrap: wrap; align-items: flex-start; gap: 0.75rem 1.1rem; }
.vw-time-row .vw-field { flex: 0 1 auto; min-width: 0; }
.vw-time-row .field-select { width: auto; }
.vw-time-dates { display: contents; }
.vw-time-dates[hidden] { display: none; }

/* Destructive list action: same ghost chrome as its neighbors, red text on hover/focus only. */
.sc-action-danger:hover, .sc-action-danger:focus-visible { color: var(--danger); border-color: currentColor; }

/* Result-layouts group (Settings > Search): the segmented switcher + per-layout designer sections. */
.rl-switch { margin-block-end: 0.9rem; }
.rl-title { margin: 0 0 0.5rem; font-size: 0.95rem; }

/* Public view page: the restrict list's Sites inspection block. */
.view-public-sites { margin: 0; padding: 0; list-style: none; display: flex; flex-wrap: wrap; gap: 0.4rem; }
.view-public-sites code { background: var(--surface-2); border: 1px solid var(--border); border-radius: var(--radius-sm); padding: 0.1rem 0.45rem; overflow-wrap: anywhere; }

/* ── App-wide feedback: the flash strip (no-JS face of the toast) + the confirm dialog ── */
.flash-toast { display: flex; flex-wrap: wrap; align-items: center; gap: 0.4rem 0.9rem; }
.flash-undo-form { margin: 0; display: inline-flex; }
.flash-undo { background: transparent; border: 0; padding: 0; font: inherit; font-weight: 700;
    color: var(--brand-strong); cursor: pointer; text-decoration: underline; }

.confirm-dialog { max-width: 26rem; border: 1px solid var(--border-strong); border-radius: var(--radius);
    background: var(--surface); color: var(--text); padding: 1.4rem 1.5rem;
    /* The global reset zeroes margins, killing the UA's dialog centering — restore it. */
    margin: auto; box-shadow: var(--shadow-lg); }
.confirm-dialog::backdrop { background: rgba(0, 0, 0, 0.55); }
.confirm-dialog h2 { margin: 0 0 0.6rem; font-size: 1.1rem; }
.confirm-dialog-name { margin: 0 0 0.35rem; overflow-wrap: anywhere; }
.confirm-dialog-body { margin: 0 0 1.1rem; font-size: 0.9rem; }
.confirm-dialog-list { margin: -0.6rem 0 1.1rem; padding-inline-start: 1.2rem; max-height: 10rem; overflow-y: auto; font-size: 0.88rem; }
.confirm-dialog-list li { margin: 0.2rem 0; overflow-wrap: anywhere; }
.confirm-dialog-actions { display: flex; flex-wrap: wrap; gap: 0.6rem; justify-content: flex-end; }

/* Mode hints: JS reveals only the selected mode's line (all three render for no-JS). */
.vw-mode-hints-live .vw-field-hint[data-vw-mode-hint] { display: none; }
.vw-mode-hints-live .vw-field-hint[data-vw-mode-hint].is-active { display: block; }

/* ── Results page: the "Add site to a view" inline picker (cloned from the page template) ── */
.view-add-panel { border-block-start: 1px solid var(--border); margin-block-start: 0.25rem; padding-block-start: 0.25rem; }
.view-add-list { display: flex; flex-direction: column; max-block-size: 14rem; overflow-y: auto; }
.view-add-list form { margin: 0; }
.view-add-item { inline-size: 100%; text-align: start; }
.view-add-new { font-weight: 600; }
