/* ════════════════════════════════════════════════════════════════════════════
   profile-border/style.css — FLAT (vanilla) Profile Border overlay.

   Ported from the React widget's styles (src/assets/css/profile-border.css):
   the OVERLAY rules (.pbw-* / .orbit-text-*) plus a handful of inert Console
   (.pb-*) rules that sit interleaved in the shared style-variant block — they
   match no element here, and keeping the block whole avoids dropping a
   .pbw-style-* variant by accident. The app theme vars those rules reference are
   inlined below so this file stands alone (the relay serves it with no app CSS).

   Transparent by design (CLAUDE.md "กฎ overlay โปร่งใส"): OBS composites this
   over the stream, so NOTHING here sets an opaque page background.
   ════════════════════════════════════════════════════════════════════════════ */

:root {
    --app-bg: #06070A;
    --app-border-strong: rgba(255, 255, 255, 0.14);
    --app-text: #e2e8f0;
    --app-text-muted: rgba(255, 255, 255, 0.6);
    --black-rgb: 0, 0, 0;
    --brand: #e1196e;
    --brand-rgb: 225, 25, 110;
    --mek-pink: var(--brand);
    --font-body: 'Montserrat', system-ui, -apple-system, 'Segoe UI', sans-serif;
}

/* ทุก overlay ต้องไม่แสดง scrollbar ใน OBS/CEF — ซ่อน scrollbar ทุก browser (ไม่แตะ overflow/layout) */
html, body { scrollbar-width: none; -ms-overflow-style: none; }
::-webkit-scrollbar { display: none; }

/* Transparent stage — never paint the page background. */
html, body {
    margin: 0;
    padding: 0;
    background: transparent !important;
    overflow: hidden;
    font-family: var(--font-body);
}

/* ── orbit-text (ported verbatim) ─────────────────────────────────────── */
.orbit-text {
  position: absolute;
  top: 50%;
  left: 50%;
  /* transform (centre + size-scaled downward offset) is set inline by the
     component so the orbit sits at the same RELATIVE position in the preview and
     the overlay regardless of frame size. */
  z-index: 4;
  pointer-events: none;
}

/* The ring just holds the glyphs centred; JS (requestAnimationFrame) drives each
   glyph's position, scale and opacity every frame for the orbit. */
.orbit-text-ring {
  position: absolute;
  inset: 0;
}

/* Each glyph is billboarded (always facing the viewer) and centred at the ring
   middle; JS sets its per-frame transform/opacity. The dark stroke keeps it
   legible over any frame art. */
.orbit-text-char {
  position: absolute;
  top: 50%;
  left: 50%;
  display: inline-block;
  white-space: pre;
  font-weight: 800;
  color: #fff;
  text-shadow:
    0 0 2px rgba(0, 0, 0, 0.9),
    0 1px 4px rgba(0, 0, 0, 0.8);
  /* Smooth the per-frame opacity/scale steps so the fade in/out at the sides
     looks natural rather than snapping. */
  will-change: transform, opacity;
}

/* ── .pbw-* overlay (ported verbatim) ─────────────────────────────────── */
.pbw-stage {
  position: fixed;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: transparent;
}

/* OBS captures the whole page — keep it transparent, no scrollbars. */
.pbw-root,
.pbw-waiting {
  background: transparent;
}

.pbw-waiting {
  /* Hidden in OBS (transparent text) but visible in a browser tab for debugging. */
  color: rgba(255, 255, 255, 0.5);
  font-family: var(--font-body, sans-serif);
  font-size: 14px;
  padding: 16px;
}

/* Spacing mirrors the editor's .pb-preview so Console and overlay read the
   same. The frame art has transparent padding (wings/crown), so the text tucks
   in under it via a small negative margin — same intent both modes. */
.pbw-root {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px;
  font-family: var(--font-body, 'Montserrat', system-ui, sans-serif);
}

/* The frame must paint ON TOP of the title/message plates, so the chips appear
   to slide UNDER the skin. Both children share this root as their stacking
   context; the avatar-wrap is lifted above the text. */
.pbw-root .pbw-avatar-wrap {
  position: relative;
  z-index: 2;
}
.pbw-root .pbw-text {
  position: relative;
  z-index: 1;
}

/* Horizontal: stretch the Title plate's left edge in tight against the frame and
   slide it BEHIND the skin (z-index 1 < the avatar's 2), mirroring the Console
   preview. Only a hair of padding-left remains so the plate's left edge sits
   flush up against the frame's right side (≈ the preview's 4px scaled by
   360/250). Only the Title lives in .pbw-text now — the Message sits in
   .pbw-avatar-wrap and is unaffected. */
.pbw-root--horizontal .pbw-text {
  /* Pull the Title in closer to the frame's right edge. The frame art overflows
     the 360px box by ~18% (~65px) each side, so a large positive margin floated
     the Title far off to the right. A negative pull slides the Title plate in
     tight against/under the frame — mirrors the Console preview's tucked look. */
  margin-left: -72px;
  padding-left: 6px;
}

/* Vertical: avatar on top, title + message stacked below, pulled up under
   the frame's bottom edge. */
.pbw-root--vertical {
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 8px;
}

.pbw-root--vertical .pbw-text {
  /* Gentle tuck only — the title/message slip behind the frame's bottom edge
     without riding up into the wing artwork (which looks off-centre). Symmetric
     so both chips sit dead-centre under the avatar hole. */
  margin-top: -52px;
  padding-top: 36px;
}

/* Match chip widths so vertical mode stays symmetric about the frame centre. */
.pbw-root--vertical .pbw-desc,
.pbw-root--vertical .pbw-title-wrap {
  max-width: 320px;
}

/* ── Avatar nested in the skin frame ─────────────────────────────────── */
/* Overlay renders larger than the editor preview — it's the broadcast output,
   so the frame reads at ~360px on the OBS canvas (editor box is 250px). */
.pbw-avatar-wrap {
  position: relative;
  flex-shrink: 0;
  width: 360px;
  height: 360px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  line-height: 0;
  overflow: visible;
}

/* object-fit: cover fills the square box (crops the PNG's transparent padding)
   so each frame's hole scales toward the box centre uniformly — matches the
   editor's .pb-preview-skin so the centred avatar lines up across all skins. */
.pbw-skin {
  position: absolute;
  inset: -18%;
  width: 136%;
  height: 136%;
  object-fit: cover;
  pointer-events: none;
}

/* Photo sits in the frame's centre opening. Round, sized to the inner hole. */
.pbw-avatar-wrap.has-skin .pbw-avatar {
  width: 35%;
  height: 35%;
}

.pbw-avatar {
  width: 60%;
  height: 60%;
  object-fit: cover;
  border-radius: 50%;
}


/* ── Title plate + message ───────────────────────────────────────────── */
.pbw-text {
  display: flex;
  flex-direction: column;
  /* Centre the message + title plate on each other (both modes). */
  align-items: center;
  gap: 6px;
  min-width: 0;
}

/* Title sits on the name-bar artwork (skin's mvp_frame_description asset). */
.pbw-title-wrap {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 240px;
  padding: 11px 24px;
}

.pbw-namebar {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: fill;
  pointer-events: none;
  z-index: 0;
}

.pbw-title {
  position: relative;
  z-index: 1;
  color: #fff;
  font-size: 30px;
  font-weight: 800;
  letter-spacing: 0.02em;
  text-shadow: 0 2px 6px rgba(0, 0, 0, 0.7);
  white-space: nowrap;
}

/* No name-bar art → fall back to a translucent pill so the title still reads. */
.pbw-title-wrap:not(.has-namebar) {
  background: rgba(0, 0, 0, 0.45);
  border-radius: 999px;
}

/* Text Message plate — shown when "Scrolling text" is OFF. A gold pill tucked up
   under the frame with the text scrolling right→left as a seamless marquee,
   mirroring the Console preview's .pb-preview-text. */
.pbw-desc {
  position: absolute;
  top: 100%;
  left: 50%;
  /* Tuck UP under the frame's lower edge. Nudged DOWN a touch (−83px → −72px) so
     the Text Message clears the frame's bottom art instead of riding up too high
     over it — matches how the plate reads in the OBS overlay. */
  transform: translate(-50%, -72px);
  width: 180px;
  max-width: 86vw;
  overflow: hidden;
  /* Gold pill matching the preview's .pb-preview-text — deep-black fill, warm
     gold border + glow, so Console and overlay read identically. */
  background:
    linear-gradient(180deg, rgba(0, 0, 0, 0.94), rgba(0, 0, 0, 0.86));
  border: 2px solid #e9c45a;
  box-shadow:
    0 0 12px rgba(233, 196, 90, 0.45),
    0 2px 8px rgba(0, 0, 0, 0.55),
    inset 0 0 10px rgba(233, 196, 90, 0.15);
  border-radius: 999px;
  /* Taller pill so the text has breathing room top/bottom — matches the preview
     plate's proportions instead of hugging the glyphs. */
  padding: 18px 0;
  z-index: 4;
  /* No end-fade mask — the gold side borders (left/right) must stay fully solid
     and visible. The scrolling track is clipped by overflow:hidden + the pill's
     border-radius, so text still stays inside the rounded ends without the mask
     dimming the borders. */
}

/* The scrolling track — two text copies side by side. Sliding it by -50% (one
   copy's width incl. the gap) lands the second copy where the first started, so
   the loop is seamless. */
.pbw-desc-track {
  display: inline-flex;
  flex-wrap: nowrap;
  white-space: nowrap;
  gap: 48px;
  padding-left: 48px;
  will-change: transform;
  /* Right→left. */
  animation: pbw-marquee 12s linear infinite;
}

.pbw-desc-item {
  /* Gold text to match the preview's message plate (.pb-preview-text). */
  color: #f3d27a;
  font-size: 22px;
  font-weight: 700;
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.85);
  white-space: nowrap;
}

@keyframes pbw-marquee {
  from { transform: translateX(0); }
  to   { transform: translateX(-50%); }
}

/* Mount the message on the frame box itself so top:100% anchors to the frame's
   bottom edge (not the text column). The wrap already establishes position. */
.pbw-avatar-wrap {
  position: relative;
}

/* ── Skin "applying" loaders ────────────────────────────────────────────
   Shown while a chosen frame is committing to the cloud (set-skin call). One
   on the Console card's avatar, one on the grid tile being applied. Both reuse
   the shared `ma-spin` keyframe so the motion matches the rest of Extras. */
.pb-preview-skin-loading {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background: radial-gradient(circle at center,
    rgba(var(--black-rgb), 0.55) 0 42%, transparent 60%);
  z-index: 3;
  pointer-events: none;
}
.pb-preview-skin-spinner {
  width: 40px;
  height: 40px;
  border: 3px solid rgba(var(--brand-rgb), 0.2);
  border-top-color: var(--brand);
  border-radius: 50%;
  animation: ma-spin 0.8s linear infinite;
}

/* Grid tile loader — dim the tile and centre a spinner over it. */
.pb-skin-tile.is-loading {
  cursor: default;
}
.pb-skin-tile-loading {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: inherit;
  background: rgba(var(--black-rgb), 0.5);
  z-index: 2;
  pointer-events: none;
}
.pb-skin-tile-spinner {
  width: 30px;
  height: 30px;
  border: 3px solid rgba(var(--brand-rgb), 0.2);
  border-top-color: var(--brand);
  border-radius: 50%;
  animation: ma-spin 0.8s linear infinite;
}

/* ── Custom Slot Controls (Switch + Style Dropdown) ─────────────────── */
.pb-card-controls {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  background: rgba(var(--black-rgb), 0.15);
  border: 1px solid var(--app-border-strong);
  border-radius: 12px;
  padding: 8px 12px;
  margin-top: 4px;
}

.pb-card.is-collapsed .pb-card-controls {
  display: none;
}

.pb-control-item {
  display: flex;
  align-items: center;
  gap: 10px;
}

.pb-control-label {
  font-size: 11px;
  font-weight: 600;
  color: var(--app-text-muted);
}

/* Custom Switch Toggle (iOS/Modern style) */
.pb-switch {
  position: relative;
  display: inline-block;
  width: 36px;
  height: 20px;
}

.pb-switch input {
  opacity: 0;
  width: 0;
  height: 0;
}

.pb-switch-slider {
  position: absolute;
  cursor: pointer;
  inset: 0;
  background-color: var(--app-border-strong);
  transition: .2s ease;
  border-radius: 20px;
}

.pb-switch-slider:before {
  position: absolute;
  content: "";
  height: 14px;
  width: 14px;
  left: 3px;
  bottom: 3px;
  background-color: var(--app-bg);
  transition: .2s ease;
  border-radius: 50%;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.4);
}

.pb-switch input:checked + .pb-switch-slider {
  background-color: var(--brand, var(--mek-pink, #ff0055));
}

.pb-switch input:focus + .pb-switch-slider {
  box-shadow: 0 0 1px var(--brand, var(--mek-pink, #ff0055));
}

.pb-switch input:checked + .pb-switch-slider:before {
  transform: translateX(16px);
  background-color: #fff;
}

/* Dropdown override styling */
.pb-card-style-dropdown {
  background: var(--app-bg);
  border: 1px solid var(--app-border-strong);
  color: var(--app-text);
  border-radius: 8px;
  padding: 4px 10px;
  font-size: 11px;
  font-weight: 700;
  cursor: pointer;
  outline: none;
  transition: border-color 0.15s, box-shadow 0.15s;
}

.pb-card-style-dropdown:hover {
  border-color: var(--app-text-muted);
}

.pb-card-style-dropdown:focus {
  border-color: var(--brand, var(--mek-pink, #ff0055));
  box-shadow: 0 0 0 2px rgba(var(--brand-rgb), 0.15);
}

/* ════════════════════════════════════════════════════════════════════════
   Custom Text Styles: Classic, Neon, Retro, Cyber, Luxury (TEXT ONLY)
   ════════════════════════════════════════════════════════════════════════ */

/* ── 1. Classic Gold (Default) — no overrides needed as base is classic ── */

/* ── 2. Neon Glow (neon) ── */
/* Console Preview */
.pb-style-neon .pb-preview-type {
  color: #00f0ff !important;
  text-shadow: 0 0 5px #00f0ff, 0 0 10px #00f0ff !important;
}
.pb-style-neon .pb-preview-text:focus {
  color: #00f0ff !important;
}
.pb-style-neon .pb-preview-text-item {
  color: #00f0ff !important;
  text-shadow: 0 0 5px #00f0ff !important;
}
.pb-style-neon .orbit-text-char {
  color: #00f0ff;
  text-shadow: 0 0 4px #00f0ff, 0 0 8px #00f0ff, 0 1px 2px rgba(0,0,0,0.8);
}
/* OBS Overlay Widget */
.pbw-style-neon .pbw-title {
  color: #00f0ff !important;
  text-shadow: 0 0 6px #00f0ff, 0 0 12px #00f0ff, 0 2px 4px rgba(0, 0, 0, 0.8) !important;
}
.pbw-style-neon .pbw-desc-item {
  color: #00f0ff !important;
  text-shadow: 0 0 5px #00f0ff !important;
}
/* Orbiting text (Scrolling text ON) — mirror the neon look onto each glyph so
   the circling caption matches the Console preview. */
.pbw-style-neon .orbit-text-char {
  color: #00f0ff !important;
  text-shadow: 0 0 4px #00f0ff, 0 0 8px #00f0ff, 0 1px 2px rgba(0, 0, 0, 0.8) !important;
}

/* ── 3. Retro Arcade (retro) ── */
/* Console Preview */
.pb-style-retro .pb-preview-type,
.pb-style-retro .pb-preview-text,
.pb-style-retro .pb-preview-text-item,
.pb-style-retro .orbit-text-char {
  font-family: 'Courier New', Courier, monospace !important;
  letter-spacing: -0.05em !important;
}
.pb-style-retro .pb-preview-type {
  color: #ffff00 !important;
  text-shadow: 2px 2px 0px #000, -1px -1px 0px #ff0055 !important;
}
.pb-style-retro .pb-preview-text:focus {
  color: #ffff00 !important;
}
.pb-style-retro .pb-preview-text-item {
  color: #ffff00 !important;
  text-shadow: 1px 1px 0px #000 !important;
}
.pb-style-retro .orbit-text-char {
  color: #ffff00;
  text-shadow: 2px 2px 0px #000;
}
/* OBS Overlay Widget */
.pbw-style-retro .pbw-title,
.pbw-style-retro .pbw-desc-item,
.pbw-style-retro .orbit-text-char {
  font-family: 'Courier New', Courier, monospace !important;
  letter-spacing: -0.05em !important;
}
.pbw-style-retro .pbw-title {
  color: #ffff00 !important;
  text-shadow: 3px 3px 0px #000, -1px -1px 0px #ff0055, 0 2px 4px rgba(0, 0, 0, 0.7) !important;
}
.pbw-style-retro .pbw-desc-item {
  color: #ffff00 !important;
  text-shadow: 1px 1px 0px #000 !important;
}
/* Orbiting text (Scrolling text ON) — the block above only sets the retro font
   on the glyphs; give them the retro colour + shadow too so the circling caption
   matches the Console preview instead of staying the base white. */
.pbw-style-retro .orbit-text-char {
  color: #ffff00 !important;
  text-shadow: 2px 2px 0px #000 !important;
}

/* ── 4. Cyberpunk (cyber) ── */
/* Console Preview */
.pb-style-cyber .pb-preview-type,
.pb-style-cyber .pb-preview-text,
.pb-style-cyber .pb-preview-text-item,
.pb-style-cyber .orbit-text-char {
  font-weight: 900 !important;
  font-style: italic !important;
}
.pb-style-cyber .pb-preview-type {
  color: #fcee0a !important;
  text-shadow: 2px 2px 0px #ff0055, -2px -2px 0px #00f0ff !important;
}
.pb-style-cyber .pb-preview-text:focus {
  color: #fcee0a !important;
}
.pb-style-cyber .pb-preview-text-item {
  color: #fcee0a !important;
  text-shadow: 1px 1px 0px #ff0055 !important;
}
.pb-style-cyber .orbit-text-char {
  color: #fcee0a;
  text-shadow: 2px 2px 0px #ff0055, -1px -1px 0px #00f0ff;
}
/* OBS Overlay Widget */
.pbw-style-cyber .pbw-title,
.pbw-style-cyber .pbw-desc-item,
.pbw-style-cyber .orbit-text-char {
  font-weight: 900 !important;
  font-style: italic !important;
}
.pbw-style-cyber .pbw-title {
  color: #fcee0a !important;
  text-shadow: 3px 3px 0px #ff0055, -2px -2px 0px #00f0ff !important;
}
.pbw-style-cyber .pbw-desc-item {
  color: #fcee0a !important;
  text-shadow: 1px 1px 0px #ff0055 !important;
}
/* Orbiting text (Scrolling text ON) — the block above only sets the cyber font
   on the glyphs; give them the cyber colour + shadow too so the circling caption
   matches the Console preview instead of staying the base white. */
.pbw-style-cyber .orbit-text-char {
  color: #fcee0a !important;
  text-shadow: 2px 2px 0px #ff0055, -1px -1px 0px #00f0ff !important;
}

/* ── 5. Luxury Gold (luxury) ── */
/* Console Preview */
.pb-style-luxury .pb-preview-type {
  color: #ffe893 !important;
  text-shadow: 0 1px 0px #b5891e, 0 2px 0px #977114, 0 3px 0px #705206, 0 4px 5px rgba(0,0,0,0.8) !important;
}
.pb-style-luxury .pb-preview-text:focus {
  color: #ffd700 !important;
}
.pb-style-luxury .pb-preview-text-item {
  color: #ffd700 !important;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.9), 0 0 5px rgba(255, 215, 0, 0.4) !important;
}
.pb-style-luxury .orbit-text-char {
  color: #ffd700;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.9), 0 0 6px rgba(255, 215, 0, 0.6);
}
/* OBS Overlay Widget */
.pbw-style-luxury .pbw-title {
  color: #ffe893 !important;
  text-shadow: 0 1px 0px #b5891e, 0 2px 0px #977114, 0 3px 0px #705206, 0 4px 6px rgba(0,0,0,0.85) !important;
}
.pbw-style-luxury .pbw-desc-item {
  color: #ffd700 !important;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.9), 0 0 6px rgba(255, 215, 0, 0.5) !important;
}
/* Orbiting text (Scrolling text ON) — mirror the luxury look onto each glyph so
   the circling caption matches the Console preview. */
.pbw-style-luxury .orbit-text-char {
  color: #ffd700 !important;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.9), 0 0 6px rgba(255, 215, 0, 0.6) !important;
}

/* ── Horizontal scale down by 50% (frame is 180px instead of 360px) ── */
.pbw-root--horizontal .pbw-avatar-wrap {
  width: 180px;
  height: 180px;
}

.pbw-root--horizontal .pbw-text {
  margin-left: -36px;
  padding-left: 4px;
}

/* Note: Only the frame container is scaled. Title and message pill text sizes remain at their original proportions. */
.pbw-root--horizontal .pbw-desc {
  transform: translate(-50%, -36px);
