/* ================================================================
   RATE MODAL — animeoshi.com's QuickRating + its post-submit celebration.
   Shared: rate.js and this markup ship on BOTH the episode page and the
   anime detail page (EpRatingPill / the bottom sticky bar open the same
   modal), so the CSS cannot live in one page's stylesheet — without it the
   modal renders inline and unstyled instead of hidden until opened.
   Consumes the page's scoped token map, which both pages extend to
   #ao-rate-modal / .ao-cel-overlay.
   ================================================================ */
/* ── Rate modal — mirrors animeoshi.com's QuickRating ─────────────── */
/* Backdrop mirrors animeoshi's Base modal .overlay: 80% black + blur (not the
   sitewide 60% --color-overlay), so the page behind the QuickRating dims fully. */
#ao-rate-modal { display: none; position: fixed; inset: 0; background: rgba(0, 0, 0, 0.8); backdrop-filter: blur(5px); -webkit-backdrop-filter: blur(5px); z-index: 210; align-items: center; justify-content: center; padding: var(--spacing-md); overflow-y: auto; }
/* Open animation mirrors AO BaseModal: overlay fade + box slide up from bottom.
   Keyframes (ao-modal-fade / ao-modal-rise) are defined once in site-chrome.css. */
#ao-rate-modal.open { display: flex; animation: ao-modal-fade 0.2s ease; }
/* ─────────────────────────────────────────────────────────────────────────
   Precise sync map → animeoshi-web QuickRating (src/components/Modal/…).
   When those .module.css files change, re-diff against this block.
     .ao-rate-box      → Base/base.module.css .modal.quickRating + Rating .container
     .ao-rate-header   → QuickRating/quickRatingHeader.module.css .modalHeaderOverride
     .ao-rate-scroll   → Rating .contentArea + quickRating .quickContent
     .ao-rate-footer   → quickRating .footer
     .ao-rate-section* → quickRating .sectionHeader/.sectionTitle/.pointsBadge
     .ao-rate-stars    → starRatingStep.module.css
     .ao-rate-review*  → quickReviewStep.module.css .card/.textarea/.cardFooter
     .ao-rate-more     → quickRating .moreOptions + .moreDetails rules
     .ao-rate-attr*    → quickAttributeRatingStep.module.css
     .ao-rate-progress → quickRatingHeader .progressBar/.track/.marker
     .ao-rate-ep-pill  → quickEpisodePicker.module.css .trigger
   Token scale (animeoshi src/styles/variables.css): sm8 md16 lg24 xl32 · xs12 sm14
   md16 lg18 · radius md8 lg12 xl16 2xl21 4xl32 · weight medium500 semibold600.
   ───────────────────────────────────────────────────────────────────────── */
.ao-rate-box { display: flex; flex-direction: column; background: hsl(271, 42%, 8%); border: var(--border-normal) solid var(--color-border); border-radius: var(--radius-4xl); width: 100%; max-width: 440px; min-height: 420px; position: relative; box-shadow: var(--shadow-lg); box-sizing: border-box; max-height: 95vh; max-height: 95dvh; overflow: hidden; animation: ao-modal-rise 0.4s cubic-bezier(0.16, 1, 0.3, 1); }

/* Header (compact, fixed) — lighter surface, distinct from the darker body
   (mirrors animeoshi: header = --color-surface, body = --color-bg). */
/* Close is absolute (out of flow) like animeoshi's BaseModal closeWrapper, so the
   header height is driven by the title alone (~49px), not the 32px close button.
   padding-right = close clearance (--modal-close-inset 12 * 2 + 32 = 56px).
   Vertical padding is 20px (a touch taller than animeoshi's 16px spec, per request). */
.ao-rate-header { flex-shrink: 0; display: flex; align-items: center; padding: var(--spacing-mlg) 56px var(--spacing-mlg) var(--spacing-mlg); background: hsl(271, 35%, 13%); border-bottom: var(--border-normal) solid var(--color-border); }
.ao-rate-title { margin: 0; font-size: var(--font-size-sm); line-height: normal; font-weight: var(--font-weight-normal); color: var(--pebble); }
.ao-rate-close { position: absolute; top: var(--spacing-smd); right: var(--spacing-smd); display: inline-flex; align-items: center; justify-content: center; width: 32px; height: 32px; border-radius: var(--radius-full); border: none; background: rgba(237, 237, 237, 0.08); color: var(--pebble); cursor: pointer; flex-shrink: 0; z-index: 3; }
.ao-rate-close:hover { background: rgba(237, 237, 237, 0.16); }

/* Step = scrollable body + pinned footer, so the CTA is always visible. */
.ao-rate-step { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; }
.ao-rate-step[hidden] { display: none; }
.ao-rate-scroll { flex: 1 1 auto; min-height: 0; overflow-y: auto; overscroll-behavior: contain; display: flex; flex-direction: column; gap: var(--spacing-md); padding: var(--spacing-mlg) var(--spacing-mlg) var(--spacing-md); }
.ao-rate-footer { position: relative; flex-shrink: 0; display: flex; flex-direction: column; gap: var(--spacing-md); padding: var(--spacing-md) var(--spacing-mlg) var(--spacing-mlg); background: hsl(271, 42%, 8%); }
/* Fade scrolling content into the footer's top edge (mirrors animeoshi's .footer::before). */
.ao-rate-footer::before { content: ""; position: absolute; left: 0; right: 0; bottom: 100%; height: 28px; pointer-events: none; background: linear-gradient(to bottom, transparent, hsl(271, 42%, 8%)); }
/* Mobile: the rating modal is a bottom sheet — full-width, pinned to the bottom,
   90dvh tall, rounded top corners only (mirrors AO's BaseModal .modal.quickRating
   ≤640: overlay align-items:flex-end + sheet). The header/scroll/footer flex is
   already in place, so the content fills the sheet and scrolls internally. */
@media (max-width: 640px) {
  #ao-rate-modal { align-items: flex-end; padding: 0; }
  .ao-rate-box {
    max-width: none;
    width: 100%;
    min-height: 0;
    height: 90vh;
    height: 90dvh;
    max-height: 90vh;
    max-height: 90dvh;
    border-radius: var(--radius-4xl) var(--radius-4xl) 0 0;
    border-bottom: none;
  }
}

/* Mode toggle (Anime/Episode radios + episode pill) */
.ao-rate-modes { display: flex; align-items: center; justify-content: center; gap: var(--spacing-md); }
/* AO's `episodeHoverWrap` — the hover target that raises the help overlay. */
.ao-rate-mode-wrap { display: inline-flex; align-items: center; }
/* AO's `helpOverlay` / `helpCard` / `modeHelpDimmed`: hovering a mode option
   blurs the form below the row and floats the explainer over it. */
.ao-rate-help {
  position: absolute; left: 0; right: 0; bottom: 0;
  display: flex; align-items: center; justify-content: center;
  padding: var(--spacing-xl) var(--spacing-2xl);
  background: rgba(24, 13, 34, 0.5);
  backdrop-filter: blur(5px); -webkit-backdrop-filter: blur(5px);
  border-radius: 0 0 var(--radius-4xl) var(--radius-4xl);
  z-index: 6; pointer-events: none;
}
.ao-rate-help[hidden] { display: none; }
.ao-rate-help-card {
  max-width: 320px; padding: 14px 18px;
  background: rgba(237, 237, 237, 0.05);
  border: 1px solid rgba(237, 237, 237, 0.2);
  border-radius: var(--radius-md);
  backdrop-filter: blur(15px); -webkit-backdrop-filter: blur(15px);
}
.ao-rate-help-text {
  margin: 0; color: var(--ivory);
  font-size: var(--font-size-md); line-height: 1.55; font-weight: 500; text-align: center;
}
/* AO blurs `.quickContent` + `.footer`, which are siblings of the mode row.
   Here the row lives inside `.ao-rate-scroll`, so the row itself is excluded —
   blurring it would also take `pointer-events: none` with it and cancel the very
   hover that opened the overlay. */
.ao-rate-help-dimmed .ao-rate-scroll > *:not(#ao-rate-modes),
.ao-rate-help-dimmed .ao-rate-footer {
  filter: blur(3px); pointer-events: none; transition: filter 0.2s ease;
}
.ao-rate-mode { display: inline-flex; align-items: center; gap: 10px; border: none; background: none; color: rgba(237, 237, 237, 0.75); font: inherit; font-size: var(--font-size-sm); line-height: 18px; font-weight: var(--font-weight-medium); cursor: pointer; }
.ao-rate-radio { width: 20px; height: 20px; border-radius: 50%; border: 1.5px solid rgba(237, 237, 237, 0.3); box-sizing: border-box; flex-shrink: 0; position: relative; }
.ao-rate-mode-active { color: var(--pebble); }
.ao-rate-mode-active .ao-rate-radio { background: var(--ivory); border-color: var(--ivory); }
.ao-rate-mode-active .ao-rate-radio::after { content: ""; position: absolute; inset: 0; background: no-repeat center / 70% url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23170D21' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6L9 17l-5-5'/%3E%3C/svg%3E"); }
.ao-rate-ep-pill { display: inline-flex; align-items: center; justify-content: center; gap: 6px; height: 30px; padding: 5px 10px; min-width: 44px; border-radius: var(--radius-full); background: rgba(237, 237, 237, 0.06); color: var(--pebble); font-size: var(--font-size-sm); font-weight: var(--font-weight-medium); line-height: 18px; }

/* Section head (label + points pill) */
.ao-rate-section-head { display: flex; align-items: center; justify-content: space-between; gap: var(--spacing-smd); }
.ao-rate-section-title { font-size: var(--font-size-md); font-weight: var(--font-weight-medium); color: var(--pebble); }
.ao-rate-aspects-title { font-size: var(--font-size-md); font-weight: var(--font-weight-medium); color: var(--pebble); }
.ao-rate-pts-pill { display: inline-flex; align-items: center; gap: 5px; padding: 3px 10px; border-radius: var(--radius-max); background: rgba(237, 237, 237, 0.06); color: var(--pebble); font-size: var(--font-size-xs); font-weight: var(--font-weight-semibold); }
.ao-rate-pts-star { width: 16px; height: 16px; flex-shrink: 0; display: block; object-fit: contain; }

/* Large star picker (centered) */
.ao-rate-stars { --rate-pick: 44px; display: inline-flex; justify-content: center; gap: 10px; color: var(--pebble); align-self: center; }
.ao-rate-slot { position: relative; width: var(--rate-pick); height: var(--rate-pick); flex-shrink: 0; }
.ao-rate-slot .ao-rate-star { width: var(--rate-pick); height: var(--rate-pick); display: block; }
.ao-rate-slot .ao-rate-star[fill="none"] { stroke: rgba(237, 237, 237, 0.4); }
.ao-rate-fill { position: absolute; top: 0; left: 0; height: 100%; width: 0; overflow: hidden; transition: width 0.08s ease; }
.ao-rate-fill .ao-rate-star { width: var(--rate-pick); }
.ao-rate-half { position: absolute; top: 0; height: 100%; width: 50%; z-index: 2; cursor: pointer; }
.ao-rate-half-l { left: 0; }
.ao-rate-half-r { left: 50%; }
.ao-rate-score { text-align: center; font-size: var(--font-size-xs); color: var(--color-text-secondary); min-height: 16px; margin-top: calc(-1 * var(--spacing-sm)); }
/* Click blink on the star row (mirrors animeoshi's starBlink). */
@keyframes ao-rate-star-blink { 0% { opacity: 1; } 20% { opacity: 0.3; } 40% { opacity: 1; } 60% { opacity: 0.3; } 100% { opacity: 1; } }
.ao-rate-blink { animation: ao-rate-star-blink 500ms ease-in-out; }

/* Review box + icon toolbar */
.ao-rate-review-box { border: var(--border-normal) solid rgba(237, 237, 237, 0.08); border-radius: var(--radius-xl); padding: 14px 14px 10px; background: rgba(237, 237, 237, 0.04); }
.ao-rate-review { width: 100%; box-sizing: border-box; resize: none; min-height: 96px; border: none; background: none; color: var(--color-text-primary); font: inherit; font-size: var(--font-size-md); line-height: 1.5; }
.ao-rate-review::placeholder { color: var(--color-text-secondary); }
.ao-rate-review:focus { outline: none; }
/* Toolbar items evenly distributed (mirrors animeoshi's space-around cardFooter). */
.ao-rate-review-toolbar { display: flex; align-items: center; justify-content: space-around; gap: var(--spacing-smd); margin-top: var(--spacing-sm); color: var(--color-text-secondary); }
.ao-rate-tool { display: inline-flex; align-items: center; gap: 6px; border: none; background: none; color: inherit; font: inherit; font-size: var(--font-size-sm); cursor: pointer; padding: 0; }
.ao-rate-tool:hover { color: var(--pebble); }
.ao-rate-tool-aa { font-weight: var(--font-weight-semibold); font-size: var(--font-size-md); }
.ao-rate-spoiler-dot { width: 16px; height: 16px; border-radius: 50%; border: 1.5px solid rgba(237, 237, 237, 0.45); box-sizing: border-box; }
/* Active spoiler: only the dot turns accent; the label keeps its default color. */
.ao-rate-spoiler[aria-pressed="true"] .ao-rate-spoiler-dot { background: var(--color-accent); border-color: var(--color-accent); }
.ao-rate-media-list { display: flex; flex-wrap: wrap; gap: var(--spacing-sm); margin-top: var(--spacing-sm); }
.ao-rate-media-thumb { width: 56px; height: 56px; border-radius: var(--radius-md); overflow: hidden; background: rgba(237, 237, 237, 0.05); }
.ao-rate-media-thumb img, .ao-rate-media-thumb video { width: 100%; height: 100%; object-fit: cover; display: block; }

/* Animated triple-caret scroll hint (mirrors animeoshi's scrollHintRow) */
.ao-rate-scrollhint { display: flex; flex-direction: column; align-items: center; padding: var(--spacing-xs) 0; pointer-events: none; }
.ao-rate-hint-caret { width: 16px; height: 16px; color: rgba(237, 237, 237, 0.55); animation: ao-rate-hint-cascade 1.4s ease-in-out infinite; transform: rotate(180deg); }
.ao-rate-hint-caret + .ao-rate-hint-caret { margin-top: -7px; }
.ao-rate-hint-1 { animation-delay: 0s; }
.ao-rate-hint-2 { animation-delay: 0.2s; }
.ao-rate-hint-3 { animation-delay: 0.4s; }
.ao-rate-hint-up .ao-rate-hint-caret { transform: rotate(180deg); }
.ao-rate-hint-up .ao-rate-hint-1 { animation-delay: 0.4s; }
.ao-rate-hint-up .ao-rate-hint-3 { animation-delay: 0s; }
@keyframes ao-rate-hint-cascade { 0%, 60%, 100% { opacity: 0.2; } 30% { opacity: 1; } }

/* More Details (collapsible; holds watch date + radar + aspect stars) */
.ao-rate-more { border: var(--border-normal) solid var(--color-border); border-radius: var(--radius-lg); background: rgba(237, 237, 237, 0.05); }
.ao-rate-more-summary { display: flex; align-items: center; justify-content: space-between; gap: var(--spacing-smd); min-height: 50px; padding: var(--spacing-sm) var(--spacing-mlg) var(--spacing-sm) 15px; cursor: pointer; list-style: none; }
.ao-rate-more-summary::-webkit-details-marker { display: none; }
.ao-rate-more-heads { display: flex; flex-direction: column; line-height: 1.25; }
.ao-rate-more-title { font-size: var(--font-size-sm); line-height: 18px; font-weight: var(--font-weight-medium); color: var(--pebble); }
.ao-rate-more-sub { font-size: var(--font-size-xs); line-height: 16px; color: rgba(237, 237, 237, 0.55); }
.ao-rate-more-right { display: inline-flex; align-items: center; gap: var(--spacing-sm); color: var(--color-text-secondary); }
/* Chevron points DOWN when collapsed, flips up when open (base path is right-facing). */
.ao-rate-more-chevron { transition: transform 0.15s ease; transform: rotate(90deg); }
.ao-rate-more[open] .ao-rate-more-chevron { transform: rotate(-90deg); }
.ao-rate-more-body { display: flex; flex-direction: column; gap: var(--spacing-md); padding: 0 var(--spacing-mlg) 15px 15px; }
.ao-rate-field { display: flex; align-items: center; justify-content: space-between; gap: var(--spacing-smd); min-height: 36px; padding: var(--spacing-sm) 0; font-size: var(--font-size-md); font-weight: var(--font-weight-medium); color: var(--pebble); }
.ao-rate-field input[type="date"] { padding: 6px var(--spacing-smd); border-radius: var(--radius-max); border: 0; background: rgba(237, 237, 237, 0.06); color: var(--pebble); font: inherit; font-size: var(--font-size-sm); font-weight: var(--font-weight-medium); cursor: pointer; color-scheme: dark; }

/* Aspects: radar + per-aspect half-star rows */
.ao-rate-radar { display: flex; justify-content: center; }
.ao-rate-radar-svg { width: 140px; height: 140px; }
.ao-rate-radar-grid { fill: none; stroke: rgba(237, 237, 237, 0.15); stroke-width: 0.5; }
.ao-rate-radar-axis { stroke: rgba(237, 237, 237, 0.15); stroke-width: 0.5; }
.ao-rate-radar-data { fill: var(--color-accent); fill-opacity: 0.18; stroke: var(--color-accent); stroke-width: 1.5; }
.ao-rate-radar-label { font-size: 8px; fill: var(--color-text-secondary); }
.ao-rate-attr-row { display: flex; align-items: center; justify-content: space-between; gap: var(--spacing-md); padding: 3px 0; }
.ao-rate-attr-label { font-size: var(--font-size-md); font-weight: var(--font-weight-medium); color: var(--pebble); }
.ao-rate-attr-stars { --attr-star: 32px; display: inline-flex; gap: 6px; color: var(--pebble); flex-shrink: 0; }
.ao-rate-attr-slot { position: relative; width: var(--attr-star); height: var(--attr-star); }
.ao-rate-attr-slot .ao-rate-astar { width: var(--attr-star); height: var(--attr-star); display: block; stroke: rgba(237, 237, 237, 0.4); }
.ao-rate-attr-fill { position: absolute; top: 0; left: 0; height: 100%; width: 0; overflow: hidden; transition: width 0.08s ease; }
.ao-rate-attr-fill .ao-rate-astar { width: var(--attr-star); stroke: none; }
.ao-rate-attr-half { width: 50%; cursor: pointer; }

/* Points progress bar */
.ao-rate-progress { display: flex; align-items: center; gap: var(--spacing-smd); }
/* NOTE: no overflow:hidden here — unlike animeoshi (markers live in a separate
   layer), this SSG nests the 22px markers + Verified! badge inside the track, so
   clipping would hide them. The fill's own border-radius rounds its leading edge. */
.ao-rate-progress-track { position: relative; flex: 1; height: 10px; border-radius: var(--radius-max); background: rgba(255, 255, 255, 0.2); box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.18); }
.ao-rate-progress-fill { position: absolute; left: 0; top: 0; height: 100%; border-radius: var(--radius-max) 0 0 var(--radius-max); background: linear-gradient(90deg, #a1862e 0%, #fdd835 5%, #fdd835 100%); transition: width 0.35s ease; }
/* Fixed milestone markers (10/15/25/35) — reached ones light up, the highest
   reached gets the burst glow. The running total lives in the end pill only. */
.ao-rate-progress-mark { position: absolute; top: 50%; transform: translate(-50%, -50%); z-index: 1; width: 22px; height: 22px; border-radius: var(--radius-max); background: #463d4e; color: rgba(237, 237, 237, 0.55); font-size: var(--font-size-xs); line-height: 14px; font-weight: var(--font-weight-bold); display: inline-flex; align-items: center; justify-content: center; transition: background-color 0.35s ease, color 0.35s ease; }
.ao-rate-progress-mark-reached { background: #fdd835; color: var(--charcoal); }
/* Leading (highest-reached) marker: animeoshi shows pulsing sun rays above it,
   with no glow ring on the marker itself (mirrors QuickRatingProgressBar). */
.ao-rate-progress-rays { position: absolute; bottom: calc(100% - 2px); left: 50%; width: 26px; height: 10px; transform: translateX(-50%); pointer-events: none; animation: ao-rate-sunshine 1.6s ease-in-out infinite; }
@keyframes ao-rate-sunshine {
  0%, 100% { opacity: 0.75; transform: translateX(-50%) scale(0.96); }
  50% { opacity: 1; transform: translateX(-50%) scale(1.04); }
}
/* Last marker (35) sits at left:100% — anchor its right edge to the track end
   (mirrors animeoshi's .markerLast) so the bar ends exactly at 35, not past it. */
.ao-rate-progress-mark-last { transform: translate(-100%, -50%); }
/* "Verified!" badge — centered above the last milestone (35), 22px up, exactly
   like animeoshi's verifiedBadge (bottom: calc(100% + 22px); centered). It sits
   at the bar's top-right over the 35 marker; the 22px lift clears the total pill. */
.ao-rate-progress-verified { position: absolute; bottom: calc(100% + 22px); left: 50%; transform: translateX(-50%); padding: 3px 10px; border-radius: var(--radius-full); background: linear-gradient(180deg, #ffe454 0%, #fdd835 100%); color: var(--charcoal); font-size: 11px; line-height: 1.3; font-weight: 700; letter-spacing: 0.2px; white-space: nowrap; box-shadow: 0 2px 8px rgba(253, 216, 53, 0.35); pointer-events: none; animation: ao-rate-verified-pop 0.4s ease-out; }
/* [hidden] must win over the absolute-positioning rule above (rate.js toggles it). */
.ao-rate-progress-verified[hidden] { display: none; }
@keyframes ao-rate-verified-pop {
  from { opacity: 0; filter: blur(6px); transform: translateX(-50%) translateY(4px) scale(0.85); }
  to { opacity: 1; filter: blur(0); transform: translateX(-50%) translateY(0) scale(1); }
}
.ao-rate-progress-total { flex-shrink: 0; }
/* animeoshi's total is a plain label (star + number), NOT a filled pill —
   strip the pts-pill background/padding here (quickRatingHeader .totalLabel). */
.ao-rate-progress-total .ao-rate-pts-pill { background: transparent; padding: 0; gap: var(--spacing-xs); font-size: var(--font-size-sm); font-weight: var(--font-weight-bold); color: var(--pebble); }

/* Continue / Skip */
.ao-rate-continue { width: 100%; height: 50px; border-radius: var(--radius-full); background: var(--pebble); color: var(--color-button-text); border: none; font-size: var(--font-size-md); font-weight: var(--font-weight-semibold); cursor: pointer; transition: opacity 0.15s ease; }
.ao-rate-continue:hover:not(:disabled) { opacity: 0.85; }
.ao-rate-continue:disabled { opacity: 0.4; cursor: default; }

/* Captcha step */
.ao-rate-captcha-q { margin: 0; font-size: var(--font-size-lg); font-weight: var(--font-weight-semibold); color: var(--pebble); text-align: center; }
.ao-rate-captcha-opts { display: flex; flex-direction: column; gap: var(--spacing-sm); }
.ao-rate-captcha-opt { display: flex; align-items: center; gap: var(--spacing-md); text-align: left; padding: var(--spacing-md); border: var(--border-normal) solid rgba(237, 237, 237, 0.1); border-radius: var(--radius-lg); background: rgba(237, 237, 237, 0.05); color: var(--color-text-primary); font: inherit; font-size: var(--font-size-sm); cursor: pointer; }
.ao-rate-captcha-opt:hover { background: rgba(237, 237, 237, 0.1); border-color: rgba(237, 237, 237, 0.2); }
.ao-rate-captcha-opt-active { background: var(--pebble); border-color: var(--pebble); color: var(--color-button-text); }
.ao-rate-captcha-tag { display: inline-flex; align-items: center; justify-content: center; width: 32px; height: 32px; border-radius: var(--radius-md); background: rgba(0, 0, 0, 0.35); color: var(--pebble); font-weight: var(--font-weight-bold); flex-shrink: 0; }
.ao-rate-captcha-opt-active .ao-rate-captcha-tag { background: var(--charcoal); color: var(--pebble); }
/* The "Wrong answer" line — sits between the question and options (mirrors
   animeoshi's captchaStep .error: font-size sm, danger red, centered). */
.ao-rate-captcha-status { font-size: var(--font-size-sm); color: #f04141; text-align: center; margin: 0; }
.ao-rate-captcha-status:empty { display: none; }
.ao-rate-captcha-actions { display: flex; align-items: center; gap: var(--spacing-smd); }
.ao-rate-skip { border: none; background: none; color: var(--pebble); font: inherit; font-size: var(--font-size-md); font-weight: var(--font-weight-semibold); cursor: pointer; padding: 0 var(--spacing-md); flex: 3 1 0; min-width: 0; }
.ao-rate-captcha-actions .ao-rate-continue { flex: 7 1 0; min-width: 0; }

/* Episode picker (the "N ▾" dropdown → "Select Episode" panel) */
.ao-rate-picker { display: flex; flex-direction: column; background: hsl(271, 42%, 8%); border: var(--border-normal) solid rgba(237, 237, 237, 0.1); border-radius: var(--radius-2xl); width: 100%; max-width: 440px; max-height: calc(100vh - 2 * var(--spacing-md)); max-height: calc(100dvh - 2 * var(--spacing-md)); box-shadow: var(--shadow-lg); box-sizing: border-box; overflow: hidden; text-align: left; }
/* Compact header — centered title stack (close pinned top-right) + arc pills. */
.ao-rate-picker-head { position: relative; flex-shrink: 0; display: flex; flex-direction: column; gap: 10px; padding: var(--spacing-md) var(--spacing-mlg); background: hsl(271, 35%, 13%); border-bottom: var(--border-normal) solid var(--color-border); }
.ao-rate-picker-toprow { display: flex; justify-content: center; }
.ao-rate-picker-titlestack { display: flex; flex-direction: column; align-items: center; text-align: center; }
.ao-rate-picker-title { margin: 0; font-size: var(--font-size-base); line-height: 20px; font-weight: var(--font-weight-medium); color: var(--pebble); }
.ao-rate-picker-sub { margin: 0; font-size: var(--font-size-sm); line-height: 18px; font-weight: var(--font-weight-medium); color: rgba(237, 237, 237, 0.8); }
.ao-rate-picker-head .ao-rate-close { position: absolute; top: var(--spacing-sm); right: var(--spacing-md); }
/* animeoshi's .arcRow (wrapping pills). AO's header is flex-shrink:0 and its arc
   row is unbounded, which is fine for a normal season — but a long-runner like
   One Piece has 46 arcs, and this panel is height-locked to the rating modal's
   footprint, so an unbounded row would eat the whole panel and hide the episode
   list. The row is capped at ~3 pill rows and scrolls past that. */
.ao-rate-picker-pills { display: flex; flex-wrap: wrap; gap: 5px; max-height: 74px; overflow-y: auto; overscroll-behavior: contain; }
.ao-rate-picker-pill { display: inline-flex; align-items: center; height: 20px; padding: 0 var(--spacing-sm); border-radius: var(--radius-full); border: 0; background: rgba(237, 237, 237, 0.1); color: var(--pebble); font: inherit; font-size: var(--font-size-xs); font-weight: var(--font-weight-medium); line-height: 16px; white-space: nowrap; cursor: pointer; }
.ao-rate-picker-pill:hover { background: rgba(237, 237, 237, 0.12); }
.ao-rate-picker-pill-active { background: var(--pebble); border-color: var(--pebble); color: var(--color-button-text); }
.ao-rate-picker-list { flex: 1 1 auto; min-height: 0; overflow-y: auto; overscroll-behavior: contain; }
/* Infinite-scroll sentinel (animeoshi QuickEpisodePicker) — zero-height probe. */
.ao-rate-picker-sentinel { height: 1px; flex: 0 0 auto; }
.ao-rate-picker-loading { padding: var(--spacing-lg); text-align: center; color: var(--color-text-secondary); font-size: var(--font-size-sm); }
.ao-rate-picker-row { display: flex; align-items: center; gap: var(--spacing-md); width: 100%; text-align: left; padding: var(--spacing-sm) var(--spacing-lg); border: none; border-top: var(--border-normal) solid var(--color-border); background: none; color: var(--pebble); font: inherit; font-size: var(--font-size-sm); cursor: pointer; }
.ao-rate-picker-row:hover { background: rgba(237, 237, 237, 0.04); }
.ao-rate-picker-epnum { font-weight: var(--font-weight-medium); min-width: 50px; flex-shrink: 0; }
.ao-rate-picker-eptitle { color: var(--pebble); }
.ao-rate-picker-row-active .ao-rate-picker-eptitle { font-weight: var(--font-weight-bold); }
/* The ep pill is a <button> now. */
button.ao-rate-ep-pill { cursor: pointer; }

/* ── Post-submit celebration overlays (built by rate.js) ─────────── */
/* Rated state: an icon + label REPLACE the star row (stars hidden). Icon + colors
   mirror animeoshi.com's RateEpisodeButton (verifiedBadge / primary Verify CTA).
   The overlay carries its own copy of animeoshi's fixed-px token values so the
   celebration/picker render 1:1, not at fluid/fallback sizes — it mounts on
   <body>, outside the page's scoped token map. */
.ao-cel-overlay {
  --font-display: var(--font-montra), sans-serif;
  --font-size-xs: 12px; --font-size-sm: 14px; --font-size-md: 16px; --font-size-lg: 18px;
  --font-size-xl: 20px; --font-size-2xl: 24px; --font-size-3xl: 30px; --font-size-4xl: 36px;
  --spacing-xs: 5px; --spacing-sm: 8px; --spacing-smd: 12px; --spacing-md: 16px;
  --spacing-mlg: 20px; --spacing-lg: 24px; --spacing-xl: 32px; --spacing-2xl: 40px;
  --radius-2xl: 21px; --radius-new: 10px;
  --color-text-secondary: rgba(237, 237, 237, 0.8); --color-text-tertiary: rgba(237, 237, 237, 0.5);
  --color-border: rgba(237, 237, 237, 0.2); --color-surface: rgba(237, 237, 237, 0.05);
  --gold: hsl(49, 98%, 60%);
  position: fixed; inset: 0; display: flex; align-items: center; justify-content: center; padding: var(--spacing-md); background: rgba(0, 0, 0, 0.8); backdrop-filter: blur(5px); -webkit-backdrop-filter: blur(5px); z-index: 220; opacity: 0; transition: opacity 0.2s ease; overflow-y: auto;
}
.ao-cel-overlay.open { opacity: 1; }
/* padding mirrors AO's PointsSummary `.summary` (spacing-mlg / 20px), not 2xl —
   the extra 40px was what pushed the card past the viewport and forced a scroll. */
.ao-cel-box { position: relative; background: hsl(271, 40%, 11%); border: var(--border-normal) solid rgba(237, 237, 237, 0.1); border-radius: var(--radius-2xl); padding: var(--spacing-mlg); width: 100%; max-width: 440px; box-shadow: var(--shadow-lg); text-align: center; box-sizing: border-box; max-height: calc(100vh - 2 * var(--spacing-md)); max-height: calc(100dvh - 2 * var(--spacing-md)); overflow-y: auto; overflow-x: hidden; overscroll-behavior: contain; }
.ao-cel-close { position: absolute; top: var(--spacing-md); right: var(--spacing-md); z-index: 2; width: 30px; height: 30px; border-radius: var(--radius-full); border: none; background: rgba(237, 237, 237, 0.08); color: var(--pebble); font-size: 15px; line-height: 1; cursor: pointer; }
.ao-cel-close:hover { background: rgba(237, 237, 237, 0.16); }
/* Hero + Oshi Points card — 1:1 with animeoshi's pointsSummary. */
.ao-cel-hero { display: flex; flex-direction: column; align-items: center; gap: var(--spacing-md); margin-bottom: var(--spacing-xl); }
.ao-cel-emoji { width: 100px; height: 100px; object-fit: contain; display: block; }
.ao-cel-title { font-family: var(--font-display); font-size: var(--font-size-3xl); line-height: 1; text-transform: uppercase; letter-spacing: 1px; margin: 0; color: var(--pebble); }
.ao-cel-oshi { display: flex; align-items: center; gap: var(--spacing-smd); min-height: 86px; padding: var(--spacing-md); border: 2px solid var(--color-border); border-radius: var(--radius-lg); box-sizing: border-box; }
.ao-cel-oshi-icon { width: 48px; height: 48px; object-fit: contain; flex-shrink: 0; }
.ao-cel-oshi-left { display: flex; flex-direction: column; align-items: flex-start; min-width: 0; }
.ao-cel-oshi-label { font-size: var(--font-size-md); line-height: 20px; font-weight: var(--font-weight-medium); color: var(--gold); }
.ao-cel-oshi-total { font-family: var(--font-display); font-size: var(--font-size-3xl); line-height: 30px; text-transform: uppercase; color: var(--pebble); }
.ao-cel-oshi-plus { margin-left: auto; padding-left: var(--spacing-sm); font-family: var(--font-display); font-size: var(--font-size-3xl); line-height: 30px; text-transform: uppercase; color: var(--gold); }
.ao-cel-bonus { font-size: var(--font-size-sm); color: var(--color-text-secondary); margin: var(--spacing-sm) 0 0; }
/* Crest card — 1:1 with animeoshi's pointsSummary crestCard (horizontal:
   image + [name + message] + progression track with 3 tier nodes/labels). */
.ao-cel-crest { display: flex; align-items: center; gap: var(--spacing-mlg); width: 100%; box-sizing: border-box; margin-top: var(--spacing-md); padding: var(--spacing-md); border: var(--border-normal) solid var(--color-border); border-radius: var(--radius-2xl); text-align: left; }
.ao-cel-crest-img { flex-shrink: 0; width: 48px; height: 56px; object-fit: contain; }
.ao-cel-crest-body { display: flex; flex-direction: column; gap: var(--spacing-smd); flex: 1 1 auto; min-width: 0; }
.ao-cel-crest-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; text-align: center; }
.ao-cel-crest-name { font-family: var(--font-display); font-size: var(--font-size-xl); line-height: 26px; color: var(--pebble); }
.ao-cel-crest-msg { font-family: var(--font-body); font-weight: var(--font-weight-medium); font-size: var(--font-size-sm); line-height: 18px; color: var(--color-text-secondary); }
.ao-cel-crest-track { position: relative; width: 100%; padding: 0 var(--spacing-sm); box-sizing: border-box; }
.ao-cel-crest-bar { position: relative; height: 6px; border-radius: var(--radius-full); background: rgba(237, 237, 237, 0.15); }
.ao-cel-crest-fill { position: absolute; left: 0; top: 0; height: 100%; border-radius: var(--radius-full); background: var(--pebble); width: 0; transition: width 1s cubic-bezier(0.16, 1, 0.3, 1); }
.ao-cel-crest-node { position: absolute; top: 50%; width: 16px; height: 16px; border-radius: 50%; box-sizing: border-box; background: var(--charcoal); border: 2px solid rgba(237, 237, 237, 0.15); transform: translate(-50%, -50%); transition: background 0.3s ease, border-color 0.3s ease; }
.ao-cel-crest-node-on { background: var(--pebble); border-color: var(--pebble); }
.ao-cel-crest-labels { display: flex; justify-content: space-between; width: 100%; margin-top: var(--spacing-sm); }
.ao-cel-crest-label { font-family: var(--font-body); font-weight: var(--font-weight-medium); font-size: var(--font-size-xs); line-height: 14px; color: var(--color-text-tertiary); }
.ao-cel-crest-label-on { color: var(--pebble); }
.ao-cel-foot { margin: var(--spacing-lg) 0 0; font-size: var(--font-size-sm); font-weight: var(--font-weight-semibold); color: var(--pebble); }
.ao-cel-continue { margin-top: var(--spacing-sm); width: 100%; height: 50px; border-radius: var(--radius-full); background: var(--pebble); color: var(--color-button-text); border: none; font-size: var(--font-size-md); font-weight: var(--font-weight-semibold); cursor: pointer; }
.ao-cel-continue:hover { opacity: 0.85; }
/* Mobile: the celebration owns the whole viewport (mirrors AO's ratingStatus
   full-screen ≤640) instead of a centered card that has to scroll. Content is
   centered in the full height, so it never needs a scrollbar. */
@media (max-width: 640px) {
  /* The overlay is position:fixed inset:0 (= viewport); align-items:stretch makes
     the box fill that height reliably — no 100dvh needed. Content is centered, so
     the celebration owns the whole screen and never scrolls (AO's ≤640 behavior). */
  .ao-cel-overlay { padding: 0; align-items: stretch; }
  .ao-cel-box {
    max-width: none;
    width: 100%;
    max-height: none;
    border: none;
    border-radius: 0;
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: var(--spacing-md);
  }
}

/* ── Celebration bonus (2x/3x) variant — mirrors animeoshi-web PointsSummary
   isBonus branch (pointsSummary.module.css). Tone set by ao-cel-tone-{n}x on the
   overlay; the card uses a gradient border (black padding-box + gradient
   border-box) and a gradient hero. Dark-pinned like the source. */
.ao-cel-tone-2x { --cel-bonus-grad: linear-gradient(129.52deg, #eb0901 -20%, #f97316 18%, #fdd835 72%); }
.ao-cel-tone-3x { --cel-bonus-grad: linear-gradient(105.98deg, #fb06f5 0%, #fdd835 145.59%); }
.ao-cel-bonusv .ao-cel-box { background: var(--black); }

.ao-cel-star-stage {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: clamp(140px, 28dvh, 260px);
  margin-bottom: var(--spacing-md);
}
.ao-cel-star-glow {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 120%;
  height: 120%;
  max-width: none;
  object-fit: contain;
  transform: translate(-50%, -50%);
  pointer-events: none;
  user-select: none;
}
.ao-cel-star-img {
  position: relative;
  width: auto;
  height: 100%;
  max-width: 100%;
  aspect-ratio: 1 / 1;
  object-fit: contain;
  pointer-events: none;
  user-select: none;
  animation: aoCelStarFloat 4.5s ease-in-out infinite;
}
@keyframes aoCelStarFloat {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(-6px); }
}

.ao-cel-bonus-card {
  container-type: inline-size;
  display: flex;
  flex-direction: column;
  width: 100%;
  box-sizing: border-box;
  overflow: hidden;
  border: 2px solid transparent;
  border-radius: var(--radius-lg);
  background:
    linear-gradient(var(--black), var(--black)) padding-box,
    var(--cel-bonus-grad) border-box;
}
.ao-cel-bonus-hero {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--spacing-xs);
  padding: var(--spacing-md) 0;
  background: var(--cel-bonus-grad);
}
.ao-cel-bonus-mult,
.ao-cel-bonus-unit {
  font-family: var(--font-body);
  font-size: clamp(52px, 26cqi, 100px);
  line-height: 1;
  letter-spacing: -0.02em;
  color: var(--charcoal);
}
.ao-cel-bonus-mult { font-weight: 800; }
.ao-cel-bonus-unit { font-weight: 200; }
.ao-cel-bonus-strip {
  display: flex;
  align-items: flex-end;
  gap: var(--spacing-mlg);
  width: 100%;
  box-sizing: border-box;
  padding: var(--spacing-smd) var(--spacing-smd) var(--spacing-md);
}
.ao-cel-bonus-delta {
  display: flex;
  align-items: center;
  gap: var(--spacing-xs);
  margin-left: auto;
  padding-left: var(--spacing-sm);
}
.ao-cel-bonus-delta-val {
  font-family: var(--font-display);
  font-size: var(--font-size-3xl);
  line-height: 30px;
  text-transform: uppercase;
  color: var(--gold);
}
.ao-cel-bonus-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: 30px;
  height: 30px;
  box-sizing: border-box;
  border-radius: var(--radius-max);
  background: var(--gold);
  font-family: var(--font-body);
  font-weight: 800;
  font-size: var(--font-size-xl);
  line-height: 1;
  color: var(--charcoal);
}

/* ── Celebration entrance timeline — mirrors animeoshi-web PointsSummary
   framer-motion reveals. Box springs up as the overlay fades; then hero (t=0) →
   points/bonus card (0.45s) → crest card (1.6s) rise in. Count-up (650ms) and
   the progress-bar fill (1800ms) are timed in rate.js. */
@keyframes aoCelBoxIn { from { transform: translateY(100%); } to { transform: translateY(0); } }
@keyframes aoCelHeroIn { from { opacity: 0; transform: translateY(12px); } to { opacity: 1; transform: translateY(0); } }
@keyframes aoCelStarIn { from { opacity: 0; transform: scale(0.86); } to { opacity: 1; transform: scale(1); } }
@keyframes aoCelRiseIn { from { opacity: 0; transform: translateY(16px); } to { opacity: 1; transform: translateY(0); } }

.ao-cel-points .ao-cel-box { animation: aoCelBoxIn 0.5s cubic-bezier(0.22, 1.12, 0.36, 1) both; }
.ao-cel-points .ao-cel-hero { animation: aoCelHeroIn 0.4s ease-out both; }
.ao-cel-points .ao-cel-star-stage { animation: aoCelStarIn 0.5s ease-out both; }
.ao-cel-points .ao-cel-oshi,
.ao-cel-points .ao-cel-bonus-card { animation: aoCelRiseIn 0.4s ease-out both; animation-delay: 0.45s; }
.ao-cel-points .ao-cel-crest { animation: aoCelRiseIn 0.4s ease-out both; animation-delay: 1.6s; }

@media (prefers-reduced-motion: reduce) {
  .ao-cel-points .ao-cel-box,
  .ao-cel-points .ao-cel-hero,
  .ao-cel-points .ao-cel-star-stage,
  .ao-cel-points .ao-cel-oshi,
  .ao-cel-points .ao-cel-bonus-card,
  .ao-cel-points .ao-cel-crest { animation: none; }
}

/* Shareable card */
.ao-share-card { position: relative; border-radius: var(--radius-lg); overflow: hidden; background: rgba(237, 237, 237, 0.05); margin-bottom: var(--spacing-lg); }
.ao-share-cover { width: 100%; height: 160px; object-fit: cover; display: block; opacity: 0.6; }
.ao-share-logo { position: absolute; top: var(--spacing-md); left: var(--spacing-md); width: 96px; height: auto; }
.ao-share-body { padding: var(--spacing-lg); text-align: left; }
.ao-share-overline { font-size: var(--font-size-xs); text-transform: uppercase; letter-spacing: 1px; color: var(--color-text-secondary); margin: 0 0 4px; }
.ao-share-titleline { font-family: var(--font-display); font-size: var(--font-size-lg); margin: 0 0 var(--spacing-sm); color: var(--pebble); }
.ao-share-review { font-size: var(--font-size-sm); color: var(--pebble); margin: 0 0 var(--spacing-md); line-height: 1.5; }
.ao-share-stars { display: inline-flex; gap: 2px; color: var(--pebble); margin-bottom: var(--spacing-md); }
.ao-share-stars .ao-rate-attr-slot { width: 24px; height: 24px; }
.ao-share-stars .ao-rate-astar { width: 24px; height: 24px; }
.ao-share-stars .ao-rate-attr-fill .ao-rate-astar { width: 24px; }
.ao-share-cta { display: inline-block; font-size: var(--font-size-sm); color: var(--color-primary, #ffc300); text-decoration: none; }
.ao-share-actions { display: flex; gap: var(--spacing-md); }
.ao-share-skip, .ao-share-btn { flex: 1; height: 44px; border-radius: var(--radius-full); font: inherit; font-size: var(--font-size-sm); font-weight: var(--font-weight-semibold); cursor: pointer; }
.ao-share-skip { background: transparent; border: var(--border-normal) solid var(--color-border); color: var(--color-text-primary); }
.ao-share-btn { background: var(--pebble); border: none; color: var(--color-button-text); }
.ao-share-snooze { display: flex; align-items: center; gap: var(--spacing-sm); justify-content: center; margin-top: var(--spacing-md); font-size: var(--font-size-xs); color: var(--color-text-secondary); cursor: pointer; }
