/* GENERATED COPY - do not edit here.
   Source of truth: seep-extension/seep.css
   Refresh with: .venv/bin/python -m scripts.sync_sim_extension */
/* ===========================================================================
 * Loading mask + soft "alive and loading" glow — FLAVOR C: opacity breathe
 * ===========================================================================
 * The whole mask gently fades between fully opaque and noticeably
 * translucent, letting some of the page background peek through at the
 * dim points. Reads more as "breathing" than as "glowing" — the mask
 * appears to recede and return rather than emit light.
 *
 *   loading-glow-C: 2.4s infinite, opacity 0.55 ↔ 1.00
 *
 * (Previous version of this file used 0.85 ↔ 1.00, which read as
 * essentially static — a 15% swing at a 2.4s cycle is below the
 * threshold of comfortable perception. 0.55 ↔ 1.00 is a 45% swing
 * and reads as clear breathing.)
 *
 * Why this is safe (no text leakage):
 *   The .seep-loading rule sets `color: transparent !important` on the
 *   span AND on every descendant via the `.seep-loading *` selector below.
 *   Opacity scales ALL paint output of the element, but transparent text
 *   stays transparent at any opacity. The user can never glimpse the
 *   original English through the dim points of the breathe cycle.
 *
 * What does fade: only the mask's background-color. At opacity 0.55, the
 * user sees a blend of 55% mask color + 45% whatever's painted behind
 * (page background). Since the mask is already similar to the page bg
 * (only ±24-28 brightness shift; see makeVisibleDesaturatedMaskColor),
 * the dim point looks like the mask softly receding toward the page.
 * --------------------------------------------------------------------------- */
.seep-loading {
  background-color: var(--seep-loading-bg, rgba(128, 128, 128, 0.35)) !important;
  color: transparent !important;
  border-radius: 6px !important;
  user-select: none !important;
  /* The masked block is inert except for the double-click-to-skip gesture
   * handled in JS — never a text field or a link. Force a plain arrow
   * cursor so it doesn't show an I-beam (or, over a masked link, the link
   * "hand") and imply something is clickable underneath. */
  cursor: default !important;
  box-decoration-break: clone !important;
  -webkit-box-decoration-break: clone !important;
  animation: seep-loading-glow-breathe 1.0s ease-in-out infinite both;
}

@keyframes seep-loading-glow-breathe {
  0%, 100% { opacity: 1.00; }
  50%      { opacity: 0.75; }
}

/* Infinite-loop motion can fatigue motion-sensitive users; respect the
 * OS-level reduced-motion preference. The mask color stays visible —
 * only the pulse stops. */
@media (prefers-reduced-motion: reduce) {
  .seep-loading {
    animation: none;
  }
}

/* Every descendant is neutralised while the sentence is masked:
 *   color / background → transparent: no text or link styling leaks through.
 *   pointer-events: none: masked links (and any other inline control) are
 *     made fully inert. Without this the <a> under the mask stays live even
 *     though its text is hidden — hovering it flips the cursor to the link
 *     "hand" (revealing a link the mask is meant to hide) and clicking it
 *     navigates. On link-dense pages (Wikipedia) that also broke the
 *     double-click-to-skip gesture: the first click navigated before the
 *     span's `dblclick` could fire. With pointer-events off, the descendant
 *     is transparent to the mouse, so clicks fall through to the masked
 *     span itself, where the dblclick-to-skip handler lives — making skip
 *     reliable as a side effect. Everything reverts automatically when
 *     `.seep-loading` is removed on translate/skip, re-enabling the links. */
.seep-loading * {
  color: transparent !important;
  background-color: transparent !important;
  pointer-events: none !important;
}

/* A DEFERRED (click-to-load) native-Chinese sentence shares the resting look of a
   seepified-but-not-selected sentence: the same faint wash, rounded chip, pointer
   cursor, and hover brighten. It carries no tokens yet, so there are simply no
   unknown-word highlights - which is exactly "looks seepified, minus the highlights"
   until a click loads it. */
.seep-translated,
[data-seep-state="enrich-deferred"] {
  background-color: rgba(100, 150, 250, 0.08);
  border-radius: 6px;
  cursor: pointer;
  box-decoration-break: clone;
  -webkit-box-decoration-break: clone;
  transition: background-color 0.15s ease;
}

/* Seep owns its own inline typography; don't let a host page's text spacing
   leak into our wrapper or its inner spans. Chinese UIs lay out short menu
   labels in a fixed-width slot and push the characters apart to fill it. The
   trap: they do this with a descendant-`span` selector (e.g. Baidu's category
   bar "全部 / 人物 / 社会" uses `.knowledges.nav span { margin-right: 42px }`),
   which matches not only the page's own label but ALSO every span Seep injects
   inside it - the wrapper, `.seep-token`, `.seep-token-underline`, and crucially
   each per-character `.seep-ruby-base`. The leaked `margin-right` on every base
   is what literally spreads the Han characters apart (confirmed against the live
   bar via getComputedStyle: a 42px right margin on each base = a 42px gap
   between characters). Other sites do the same thing with `letter-spacing`,
   `word-spacing`, `text-align: justify`, or a fixed `width`, so reset all of
   those vectors here.

   Two things make this defeat a plain reset, both learned the hard way:
   (1) the host selector out-specifies `.seep-translated`, so a non-important
   reset loses the cascade; and (2) the spacing is applied to the inner spans,
   not just the wrapper, so resetting the wrapper alone does nothing. So: reset
   across the whole Seep subtree (`.seep-translated *`) with `!important` (an
   important author declaration beats a non-important one regardless of
   specificity). `margin: 0` removes the leaked per-character gap; `width: auto`
   undoes any leaked fixed width (a no-op otherwise, and an auto-width box still
   shrinks to content so multi-token sentence wrappers keep wrapping). We leave
   `display` untouched: forcing it would risk breaking the native ruby layout
   (see the <ruby> note below), and it is not needed once margin/width are reset. */
.seep-translated,
.seep-translated *,
[data-seep-state="enrich-deferred"],
[data-seep-state="enrich-deferred"] * {
  letter-spacing: normal !important;
  word-spacing: normal !important;
  text-align: start !important;
  text-align-last: auto !important;
  width: auto !important;
  margin: 0 !important;
}

/* Subtle highlight while hovering so the user can see the sentence's
   exact boundaries among adjacent text. */
.seep-translated:hover,
[data-seep-state="enrich-deferred"]:hover {
  background-color: rgba(100, 150, 250, 0.20);
}

/* The sentence currently being inspected in the sidebar. Stays prominent
   regardless of hover so the user always sees which one the popup
   corresponds to.

   Only TEXT COLOR lives here. The chip itself - fill and rim, one merged
   rounded shape around all of the sentence's line boxes - is drawn by
   render/active-outline.js as an svg injected under the text (a
   negative-z child of the sentence's isolated block container), so a
   wrapped sentence reads as one connected chip with the leading between
   lines filled like a bucket, translucent-safe on dark surfaces. The
   background is forced transparent so the idle/hover chip tints never
   double with the drawn fill; --seep-active-fill-base NAMES each
   variant's fill color for active-outline.js to read. A custom property
   on purpose: it never animates, while background-color inherits a 0.15s
   transition (a mid-transition read once poisoned the fill color). */
.seep-translated.seep-active,
.seep-translated.seep-active:hover {
  --seep-active-fill-base: rgba(100, 150, 250, 0.38);
  background-color: transparent;
  color: #ffffff !important;
}

/* On light page backgrounds, the active sentence should look like
   black text on a white chip with a strong dark-blue rim, not a blue fill.
   (Chip and rim both come from active-outline.js, keyed off this class.) */
.seep-translated.seep-active.seep-active-on-light-bg,
.seep-translated.seep-active.seep-active-on-light-bg:hover {
  --seep-active-fill-base: #ffffff;
  background-color: transparent !important;
  color: #111111 !important;
}

/* Force the engaged sentence's text to pure white (dark surfaces) or
   near-black (light), EXCEPT links: anchors and their contents are
   excluded from the blanket (rather than re-colored after the fact,
   because there is no CSS value meaning "what the site's own stylesheet
   would have used"; leaving them unmatched lets the page's link color
   cascade through untouched), so what is and isn't a link stays
   distinguishable while a sentence is engaged. The :not() argument list
   keeps these rules BELOW the pinyin rt overrides in specificity. */
.seep-translated.seep-active *:not(a, a *),
.seep-translated.seep-active:hover *:not(a, a *) {
  color: #ffffff !important;
}

.seep-translated.seep-active.seep-active-on-light-bg *:not(a, a *),
.seep-translated.seep-active.seep-active-on-light-bg:hover *:not(a, a *) {
  color: #111111 !important;
}

/* Keep inline pinyin in its pre-selection page text color while the
   active sentence changes color. This rule must come after the blanket
   active-sentence child rules above. */
.seep-translated.seep-active rt.seep-ruby-text,
.seep-translated.seep-active:hover rt.seep-ruby-text,
.seep-translated.seep-active.seep-active-on-light-bg rt.seep-ruby-text,
.seep-translated.seep-active.seep-active-on-light-bg:hover rt.seep-ruby-text {
  color: var(--seep-active-pinyin-color, currentColor) !important;
}

/* In light-mode active sentences, visible inline pinyin needs its own
   white chip so it stays readable. This applies whenever inline pinyin
   is showing at all — i.e. in "all" or "active-token" mode but not
   "off" mode. In "active-token" mode the chip only renders on the one
   token whose rt is unhidden (the keyboard-focused one), because the
   active-token rule sets display: none on every other rt, which
   suppresses the background regardless of this rule. */
html:not([data-seep-inline-pinyin="off"])
  .seep-translated.seep-active.seep-active-on-light-bg rt.seep-ruby-text,
html:not([data-seep-inline-pinyin="off"])
  .seep-translated.seep-active.seep-active-on-light-bg:hover rt.seep-ruby-text {
  /* The chip's WHITE PLATE is painted by active-outline.js (in the chip
     layer, above the rim but below the page's inline content), not by a
     background here: an element's background cannot be separated from its
     own text in the stacking order, and the plate must sit BELOW the
     rating highlights while the pinyin GLYPHS sit above them. Only the
     plate's geometry stays here, so the drawn rect matches the box the
     browser reserves: padding widens it, the radius rounds it. */
  border-radius: 0.25em !important;
  padding: 0 0.14em !important;
  text-shadow: none !important;
}

/* Buzz animation that builds in intensity and frequency — visually
   announces that the sidebar is about to open. Applies to a deferred
   (click-to-load) frame too, so hover-to-open telegraphs the same way before it
   loads on hover. */
.seep-translated.seep-hover-buzz,
[data-seep-state="enrich-deferred"].seep-hover-buzz {
  animation: seep-hover-buzz 0.65s ease-in-out both;
}

@keyframes seep-hover-buzz {
  0%   { background-color: rgba(100, 150, 250, 0.20); }
  18%  { background-color: rgba(100, 150, 250, 0.42); }
  32%  { background-color: rgba(100, 150, 250, 0.20); }
  50%  { background-color: rgba(100, 150, 250, 0.48); }
  60%  { background-color: rgba(100, 150, 250, 0.20); }
  74%  { background-color: rgba(100, 150, 250, 0.55); }
  82%  { background-color: rgba(100, 150, 250, 0.22); }
  92%  { background-color: rgba(100, 150, 250, 0.62); }
  100% { background-color: rgba(100, 150, 250, 0.30); }
}

/* Applied only during the brief window of a multi-click sequence so the
   browser's native word/paragraph selection on click 2/3 never paints. */
.seep-suppress-selection,
.seep-suppress-selection * {
  user-select: none !important;
  -webkit-user-select: none !important;
}

/* Inline ruby pinyin on every Han character in a translated sentence.
   Notes:
   1. We do NOT set `display` here. Setting any non-default display on
      <ruby> (including inline-block) disables the browser's native ruby
      layout — the thing that centers the <rt> over the base character.
      Without ruby layout, <rt> becomes a regular block-level child with
      default left alignment, so pinyin starts at each character's left
      edge and overflows to the right, drifting visually as more
      characters accumulate.
   2. ruby-align: center is the explicit instruction to center the
      annotation over the base when one is wider than the other.
   3. Line breaking is already handled by the CSS Ruby spec: a single
      <ruby>...<rt>...</rt></ruby> pair is never split across lines.
      Line breaks happen between adjacent ruby pairs, which is exactly
      what we want for word-wrapping a translated sentence.
   4. line-height: 1 on the ruby keeps tight vertical rhythm so
      successive ruby-annotated sentences don't blow out paragraph
      spacing. */
ruby.seep-ruby {
  ruby-position: over;
  -webkit-ruby-position: before;
  ruby-align: center;
  line-height: 1.0;
}

rt.seep-ruby-text {
  font-size: 0.55em;
  font-weight: 400;
  line-height: 1.1;
  letter-spacing: normal;
  /* A drag-select over Chinese text would otherwise sweep up the pinyin
     annotation too (the browser flattens <rt> into the selection's text
     order right after its base character), leaving the reading glued onto
     every copied character. user-select: none removes <rt> from that flow
     entirely; the Han base character (.seep-ruby-base) is untouched and
     stays selectable on its own. */
  user-select: none !important;
  -webkit-user-select: none !important;
}

/* User-chosen Chinese typeface. content/chinese-font.js sets --seep-zh-stack on
   <html>; this applies it to Seep's translated + code-switched Chinese ONLY
   (data-seep-source-lang="en"), never a site's native Chinese (="zh"). It
   targets the Han base span, so the rt pinyin keeps the page's font untouched.
   The `sans-serif` fallback (matching the default choice) covers the brief
   window before the var is hydrated. */
[data-seep-source-lang="en"] .seep-ruby-base {
  font-family: var(--seep-zh-stack, sans-serif);
}

/* Page-inline pinyin should only appear for the sentence currently
   being inspected in the sidebar/popup. The content script still renders
   ruby nodes for translated Chinese so the same sentence can reveal
   pinyin instantly when .seep-active is applied, but inactive sentences
   read as plain Chinese text. This rule does not affect the sidebar
   itself because the sidebar lives in a shadow root with its own CSS. */
.seep-translated:not(.seep-active) rt.seep-ruby-text {
  display: none;
}
.seep-translated:not(.seep-active) ruby.seep-ruby {
  display: inline;
}

/* THE PAIRING INVARIANT, stated once for every rule below that touches an rt's
   display: a rule that HIDES an annotation must also drop its <ruby> to
   `display: inline`, and a rule that REVEALS one must put the ruby back to
   `revert` (the UA's `display: ruby`). The two declarations are written as
   adjacent, same-specificity blocks at every state, and neither may appear
   without the other.

   Why the ruby box has to follow its annotation: Blink offers NO line-break
   opportunity between adjacent <ruby> elements whose annotation is
   `display: none`. We render one <ruby> per Han character, so with the pinyin
   hidden - the resting state of every sentence on the page - a whole Chinese run
   becomes ONE unbreakable box. Nothing gets wider; the run's min-content simply
   rises to equal its max-content, which is the browser saying "this cannot wrap".
   In flowing prose that is invisible. In an AUTO-LAYOUT TABLE it is not, because
   a column can never be narrower than the widest thing in it that refuses to
   wrap: every seepified cell then forces its column open and the table visibly
   changes shape. Measured on en.wikipedia Cosmology (18-char run, 16px text): the
   run's min-content 16px -> 316px, the Remarks column's floor 109px -> 332px, the
   table's min-content 409px -> 661px. Dropping the ruby to `inline` while its
   annotation is hidden makes it an ordinary inline box again and CJK line
   breaking works as it always should have.

   Rejected alternatives, both verified in Blink: removing the <rt> from the DOM
   does not help (a <ruby> with no rendered annotation is unbreakable regardless),
   and hiding the rt with `font-size: 0` keeps the run breakable but leaks the
   pinyin into copied text ("状zhuàng态tài" instead of "状态").

   Gecko breaks these runs correctly, so the pairing is inert in the Firefox fork.
   It is kept in both trees anyway: the behavior is shared, and the tables it
   protects are the same tables. Guarded by
   seep-extension-tests/ruby-line-break.test.mjs. */

/* User setting: three modes for page-inline pinyin, distributed via the
   data-seep-inline-pinyin attribute on <html> (written by content.js from
   the seepInlinePinyinMode storage key; allowed values "all" |
   "active-token" | "off"). The sidebar uses shadow-DOM CSS, so these rules
   only affect pinyin on the page itself; the sidebar always shows pinyin.

   FAIL-SAFE DEFAULT (Layer C of the active-word-only fix). The rules below
   are deliberately ordered so the SAFE behavior — active-token — is what you
   get when the attribute is ABSENT or unrecognized, not the noisy "all"
   behavior. Why this matters: the attribute lives on <html>, an element host
   frameworks (React/Next) reconcile and can strip on hydration / client-side
   navigation. If it is stripped, the page must NOT revert to showing pinyin
   over every word of the active sentence (the original bug). So
   "hide non-focused rt on the active sentence" is the UNGATED base, and "all"
   is the explicit opt-in that reveals everything. content.js's attribute
   guard (Layer B) still restores the user's real mode within a frame; this
   layer only makes that sub-frame gap harmless. */

/* Base = active-token behavior, ungated, so a missing/stripped attribute
   degrades to active-word-only. On the active sentence, hide every rt, then
   re-enable rt only on the token carrying .seep-token-focused. That class is
   the single CSS hook for "this is the underlined token on the page mirror"
   — token-marks.js adds it in lockstep with whichever specific state class is
   active (seep-token-selected for the auto/click-confirmed state,
   seep-token-keyboard-focus during arrow-key navigation). The blue underline
   below keys off the same class, so wherever the underline appears the pinyin
   appears too. Non-active sentences already have rt hidden by
   .seep-translated:not(.seep-active) above, so we don't touch them here. */
.seep-translated.seep-active rt.seep-ruby-text {
  display: none;
}
.seep-translated.seep-active ruby.seep-ruby {
  display: inline;
}
.seep-translated.seep-active .seep-token.seep-token-focused rt.seep-ruby-text {
  /* revert falls back to the user-agent default for rt
     (display: ruby-text), which is what shows pinyin above the base. */
  display: revert;
}
.seep-translated.seep-active .seep-token.seep-token-focused ruby.seep-ruby {
  /* ...and the ruby box comes back with it (UA default: display: ruby), or the
     revealed annotation would render beside the character instead of above it. */
  display: revert;
}

/* "all" mode: explicit opt-in that reveals pinyin over EVERY word of the
   active sentence. One extra attribute selector gives it higher specificity
   than the base hide rule, so it wins; it ties the focused-token reveal in
   specificity but both resolve to display: revert, so the result is uniformly
   visible. Inactive sentences stay hidden — page pinyin only ever appears on
   the sentence being inspected. */
html[data-seep-inline-pinyin="all"] .seep-translated.seep-active rt.seep-ruby-text {
  display: revert;
}
html[data-seep-inline-pinyin="all"] .seep-translated.seep-active ruby.seep-ruby {
  display: revert;
}

/* Clip-guard suppression: a host that cannot grow (fixed-height
   overflow-hidden box, e.g. YouTube's 28px shelf headings) clips the sentence
   when the ruby annotations open - the reveal makes the line taller, the box
   stays put, and the Han glyphs get shoved past the clip edge (selecting a
   word made the heading text vanish). lifecycle.js probes for that host at
   engage time (pinyin-clip-guard.js is the owner) and stamps
   seep-pinyin-clipped on the sentence, which must defeat BOTH reveal paths:
   the focused-token revert above (same specificity, so these rules sit AFTER
   it and win on order) and the "all"-mode revert (lower specificity than
   these). Pairing invariant honored: rt hidden, ruby dropped to inline. */
.seep-translated.seep-active.seep-pinyin-clipped .seep-token rt.seep-ruby-text {
  display: none;
}
.seep-translated.seep-active.seep-pinyin-clipped .seep-token ruby.seep-ruby {
  display: inline;
}

/* "off" mode: hide every rt everywhere, including the focused token on the
   active sentence (which the base reveal rule above would otherwise show).
   The !important is what lets it beat both the base focused-token reveal and
   the "all" reveal. */
html[data-seep-inline-pinyin="off"] .seep-translated rt.seep-ruby-text,
html[data-seep-inline-pinyin="off"] .seep-translated.seep-active rt.seep-ruby-text,
html[data-seep-inline-pinyin="off"] .seep-translated.seep-active:hover rt.seep-ruby-text {
  display: none !important;
}
html[data-seep-inline-pinyin="off"] .seep-translated ruby.seep-ruby,
html[data-seep-inline-pinyin="off"] .seep-translated.seep-active ruby.seep-ruby,
html[data-seep-inline-pinyin="off"] .seep-translated.seep-active:hover ruby.seep-ruby {
  display: inline !important;
}


/* Inline token selection mirror. The sidebar owns the selected/focused
   vocabulary state; content.js mirrors that state onto the active page
   sentence so the blue underline appears in both places. */
.seep-translated .seep-token {
  border-radius: 0.22em;
  padding: 0 0.08em;
  position: relative;
  text-decoration-line: none;
  background-image: none;
  box-decoration-break: clone;
  -webkit-box-decoration-break: clone;
}
/* English-run tokens in a code-switch carry no ruby/highlight, so the padding
   above only pushes a visible gap in front of the punctuation that follows them
   in the gap text (e.g. "makes sense ,"). Drop it for non-Chinese tokens. */
.seep-translated .seep-token[data-seep-non-chinese-token] {
  padding-left: 0;
  padding-right: 0;
}

/* The focused token's cursor bar is DRAWN BY active-outline.js on its
   overlay, not here. The .seep-token-underline span remains as the bar's
   measuring stick (its rect gives the bar's horizontal extent; the parent
   token's box bottom anchors it vertically, the same edge the rim hugs, so
   English and Chinese sentences render identically). The old
   text-decoration bar anchored to the glyph RUN's font metrics instead: a
   CJK run's descent differs from the span's primary font, so on natively-
   Chinese sentences the bar floated above the rim with a fill gap under
   it. (The even older border-bottom bar grew scrollHeight and gave every
   seepified YouTube comment a spurious "Read more"; an overlay bar, like
   text-decoration, is pure ink and can affect neither.) */

/* Paint order inside an engaged sentence, stated in ONE place. The layers
   overlap because a ruby annotation renders in the leading, reaching over
   the tokens beside it and on the line above:

     chip fill + rim     (active-outline.js svg, z -1, first in that svg)
     pinyin WHITE PLATE  (same svg, drawn after the rim: above it)
     rating highlights   (green/red/amber token backgrounds, in-flow)
     cursor bar          (active-outline.js svg, z 2)
     pinyin GLYPHS       (this rule: z 3, the top layer - nothing occludes
                          a reading, not even the bar it overhangs when the
                          next line's annotation reaches into this one)

   The glyphs are lifted, not the whole annotation: a token's background is
   painted in tree order, so a later token's highlight covered the bottom of
   its neighbour's pinyin, and the focused token's (then-lifted) highlight
   covered the next line's pinyin outright. Lifting the annotation's BOX
   would drag its white plate up with it, over the highlights; the plate is
   therefore drawn in the chip layer instead (see the rt rule above), which
   is what puts it under the highlights and over the rim.

   The retired `.seep-token-focused { z-index: 2 }` lift did this job for
   the cursor bar back when the bar was a text-decoration ON the token. The
   bar is a drawn layer now, so that lift only served to hide pinyin. */
.seep-translated.seep-active rt.seep-ruby-text {
  position: relative;
  z-index: 3;
}
