/* Pshtiwani app styles.
   Base: index.html <style> (prototype lines 100-860).
   Plus creators.html-only rules, and direction handling for the LTR (en) locale. */

@font-face {
    font-family: 'BFA';
    src: url('/fonts/bfa.ttf') format('truetype');
    font-weight: 400;
    font-style: normal;
    font-display: swap;
}

body {
    font-synthesis: weight style;
}

*,
*::before,
*::after {
    letter-spacing: normal !important;
}

.ls-phone {
    letter-spacing: 0.06em !important;
}

[x-cloak] {
    display: none !important;
}

/* Sticker artwork drifts at rest and springs on hover, so the catalogue feels
   alive rather than like a spreadsheet of emoji. */
@keyframes stickerFloat {
    0%, 100% { transform: translateY(0) rotate(0deg); }
    50% { transform: translateY(-7px) rotate(-3deg); }
}

@keyframes stickerIn {
    from { opacity: 0; transform: translateY(16px) scale(0.84); }
    to { opacity: 1; transform: none; }
}

.sticker-card {
    animation: stickerIn 560ms cubic-bezier(0.22, 1, 0.36, 1) both;
    animation-delay: calc(var(--i, 0) * 45ms);
}

.sticker-art {
    animation: stickerFloat 4.5s ease-in-out infinite;
    animation-delay: calc(var(--i, 0) * -370ms);
    transition: transform 420ms cubic-bezier(0.34, 1.56, 0.64, 1);
    will-change: transform;
}

.group:hover .sticker-art,
.group:focus-within .sticker-art {
    animation-play-state: paused;
    transform: translateY(-9px) scale(1.18) rotate(5deg);
}

/* A light sweeps across the tile on hover. */
.sticker-shine::after {
    content: '';
    position: absolute;
    inset: 0;
    background: linear-gradient(100deg, transparent 22%, rgb(255 255 255 / 0.22) 48%, transparent 72%);
    background-size: 240% 100%;
    background-position: 100% 0;
    opacity: 0;
    pointer-events: none;
    transition: background-position 700ms cubic-bezier(0.22, 1, 0.36, 1), opacity 200ms ease;
}

.group:hover .sticker-shine::after {
    background-position: -60% 0;
    opacity: 1;
}

/* Video stickers animate themselves, so they only get the hover spring —
   layering the idle float on top would read as jittery. */
.sticker-video {
    transition: transform 420ms cubic-bezier(0.34, 1.56, 0.64, 1);
    will-change: transform;
}

.group:hover .sticker-video,
.group:focus-within .sticker-video {
    transform: scale(1.09);
}

@media (prefers-reduced-motion: reduce) {
    .sticker-video { transition: none; }

    .group:hover .sticker-video { transform: none; }
}

.sticker-row-art {
    transition: transform 380ms cubic-bezier(0.34, 1.56, 0.64, 1);
}

.group:hover .sticker-row-art {
    transform: scale(1.16) rotate(-6deg);
}

@media (prefers-reduced-motion: reduce) {
    .sticker-card,
    .sticker-art { animation: none; }

    .sticker-art,
    .sticker-row-art,
    .sticker-shine::after { transition: none; }

    .group:hover .sticker-art { transform: none; }
}

/* Desktop rail tooltips open into the page, away from the screen edge. */
.desktop-nav-link {
    position: relative;
}

/* The rail is icons only, so this hover label is the only thing naming them.
   It has to open away from the rail and into the page, which is inset-inline-
   START of 100%: that puts the label's leading edge just past the link's
   trailing edge. `inset-inline-end` looks like the natural choice and is the
   trap — it pushes the label back past the rail and off the screen, in both
   directions, which is why these labels stopped appearing at all. */
.desktop-nav-link::after {
    content: attr(aria-label);
    position: absolute;
    top: 50%;
    inset-inline-start: calc(100% + 12px);
    z-index: 60;
    padding: 7px 11px;
    border-radius: 10px;
    background: #0F1114;
    color: #FFFFFF;
    box-shadow: 0 8px 24px -10px rgb(15 17 20 / 0.48);
    font-size: 12px;
    font-weight: 600;
    line-height: 1;
    white-space: nowrap;
    pointer-events: none;
    opacity: 0;
    visibility: hidden;
    transform: translate(calc(var(--dir) * 7px), -50%) scale(0.96);
    transform-origin: var(--tip-origin, 100%) center;
    transition: opacity 160ms ease, transform 220ms cubic-bezier(0.22, 1, 0.36, 1), visibility 160ms;
}

.dark .desktop-nav-link::after {
    background: #2E343D;
}

.desktop-nav-link:hover::after,
.desktop-nav-link:focus-visible::after {
    opacity: 1;
    visibility: visible;
    transform: translate(0, -50%) scale(1);
}

/* Opt back in only where the text is Latin. */
.ls-card {
    letter-spacing: 0.2em !important;
}

/* Atmospheric card art: soft glass orbs replace the repeated flat circles. */
.balance-card,
.stat-card { isolation: isolate; }
.balance-card > *,
.stat-card > * { position: relative; z-index: 1; }
.balance-card::before {
  content: '';
  position: absolute;
  z-index: 0;
  width: 280px;
  height: 280px;
  inset-inline-start: -94px;
  top: -142px;
  border: 1px solid rgb(var(--brand-rgb) / 0.14);
  border-radius: 46% 54% 58% 42% / 42% 40% 60% 58%;
  background:
    radial-gradient(circle at 32% 28%, rgb(255 255 255 / 0.72) 0 2%, transparent 9%),
    linear-gradient(145deg, rgb(var(--brand-rgb) / 0.20), rgb(var(--brand-rgb) / 0.025) 72%);
  box-shadow:
    inset 0 0 48px rgb(255 255 255 / 0.12),
    0 24px 70px rgb(var(--brand-rgb) / 0.08);
  transform: rotate(-12deg);
  animation: balanceOrb 9s ease-in-out infinite alternate;
}
.balance-card::after {
  content: '';
  position: absolute;
  z-index: 0;
  width: 112px;
  height: 112px;
  inset-inline-end: -42px;
  bottom: -52px;
  border: 1px solid rgb(15 17 20 / 0.08);
  border-radius: 50%;
  background: radial-gradient(circle at 34% 30%, rgb(255 255 255 / 0.7) 0 4%, rgb(var(--brand-rgb) / 0.07) 18%, transparent 70%);
  box-shadow:
    34px -68px 0 -39px rgb(var(--brand-rgb) / 0.18),
    72px -28px 0 -45px rgb(var(--brand-rgb) / 0.14);
}
.dark .balance-card::before { opacity: 0.72; border-color: rgb(var(--brand-rgb) / 0.18); }
.dark .balance-card::after { opacity: 0.62; border-color: rgb(243 245 247 / 0.08); }

.stat-card { --card-accent: 240 83 43; }
.stat-card-info { --card-accent: 46 125 246; }
.stat-card-danger { --card-accent: 239 75 63; }
.stat-card-purple { --card-accent: 139 92 246; }
.stat-card-success { --card-accent: 36 164 85; }
.stat-card-warn { --card-accent: 245 158 11; }
/*
 * Lighting, not decoration. The prototype put a second orb at top:39px with a
 * near-white core, which landed in the middle of the card — with the content
 * centred it read as a smudge on the glass rather than as depth. There is now
 * one soft accent glow behind the icon, where the eye enters the card, and a
 * hairline of the same accent along the top edge to tie the card to its tone.
 */
.stat-card::before {
  content: '';
  position: absolute;
  z-index: 0;
  inset-inline: 0;
  top: -3.25rem;
  height: 7.5rem;
  background: radial-gradient(50% 50% at 50% 50%, rgb(var(--card-accent) / 0.22), transparent 70%);
  pointer-events: none;
  transition: opacity 400ms ease, transform 650ms cubic-bezier(0.22, 1, 0.36, 1);
}
.stat-card::after {
  content: '';
  position: absolute;
  z-index: 0;
  inset-inline: 20%;
  top: 0;
  height: 1px;
  background: linear-gradient(90deg, transparent, rgb(var(--card-accent) / 0.55), transparent);
  pointer-events: none;
  transition: opacity 400ms ease;
}
/* `.stat-card > *` forces position:relative on every child and ties with
   Tailwind's `.absolute` on specificity, so the badge's placement would hang on
   stylesheet order. Two classes beat one, and this settles it. */
.stat-card > .stat-badge {
  position: absolute;
  z-index: 2;
  top: 0.5rem;
  inset-inline-end: 0.5rem;
}

.stat-card:hover::before { transform: translateY(3px) scale(1.06); }
.stat-card:hover::after { opacity: 0.75; }
.dark .stat-card::before { opacity: 0.85; }
@keyframes balanceOrb {
  from { transform: rotate(-12deg) translate3d(0, 0, 0); }
  to { transform: rotate(-5deg) translate3d(-7px, 8px, 0); }
}
@media (prefers-reduced-motion: reduce) {
  .balance-card::before { animation: none; }
  .stat-card::before,
  .stat-card::after { transition: none; }
}

/* Notifications */
@keyframes bellRing {
  0%, 100% { transform: rotate(0); }
  20%, 60% { transform: rotate(12deg); }
  40%, 80% { transform: rotate(-12deg); }
}
.animate-bell-ring {
  animation: bellRing 0.75s cubic-bezier(0.36, 0.07, 0.19, 0.97) both;
}


/* Earnings chart: quiet depth at rest, vivid focus only on interaction. */
.earnings-card {
  --chart-rgb: 240 83 43;
  --chart-top: 255 154 98;
  --chart-bottom: 217 61 28;
  position: relative;
  isolation: isolate;
  overflow: hidden;
}
.earnings-card.earnings-withdrawal {
  --chart-rgb: 46 125 246;
  --chart-top: 111 169 250;
  --chart-bottom: 30 78 184;
}
.earnings-card::before {
  content: '';
  position: absolute;
  z-index: 0;
  width: 260px;
  height: 180px;
  inset-inline-end: -92px;
  top: -118px;
  border-radius: 50%;
  background: radial-gradient(circle, rgb(var(--chart-rgb) / 0.11), transparent 68%);
  pointer-events: none;
}
.earnings-card > * { position: relative; z-index: 1; }
.earnings-header { z-index: 40 !important; }
.range-trigger {
  border-color: transparent;
  background: #F4F5F7;
  box-shadow: inset 0 0 0 1px transparent;
}
.range-trigger:hover { background: #E9EBEF; }
.range-trigger[aria-expanded='true'] {
  border-color: rgb(var(--brand-rgb) / 0.24);
  background: #FDECE5;
  color: #F0532B;
  box-shadow: 0 7px 20px -12px rgb(var(--brand-rgb) / 0.52), inset 0 0 0 1px rgb(var(--brand-rgb) / 0.04);
}
.dark .range-trigger { background: #1D2026; }
.dark .range-trigger:hover { background: #22262D; }
.dark .range-trigger[aria-expanded='true'] {
  border-color: rgb(var(--brand-rgb) / 0.28);
  background: #2A1A13;
  color: #FF8A4B;
}
.range-menu {
  border: 1px solid #E9EAED;
  background: linear-gradient(145deg, rgb(255 255 255 / 0.98), rgb(249 250 251 / 0.96));
  box-shadow: 0 24px 60px -22px rgb(15 17 20 / 0.42), 0 8px 24px -16px rgb(15 17 20 / 0.20);
  backdrop-filter: blur(20px);
}
.range-menu::before {
  content: '';
  position: absolute;
  width: 10px;
  height: 10px;
  inset-inline-end: 20px;
  top: -6px;
  border-top: 1px solid #E9EAED;
  border-inline-start: 1px solid #E9EAED;
  background: #FFFFFF;
  transform: rotate(45deg);
}
.dark .range-menu {
  border-color: #2E333B;
  background: linear-gradient(145deg, rgb(29 32 38 / 0.98), rgb(22 24 29 / 0.97));
  box-shadow: 0 28px 68px -24px rgb(0 0 0 / 0.72), 0 8px 24px -16px rgb(0 0 0 / 0.52);
}
.dark .range-menu::before { border-color: #2E333B; background: #1D2026; }
.range-option {
  border: 1px solid transparent;
  transition: transform 220ms cubic-bezier(0.22, 1, 0.36, 1), background-color 180ms ease, border-color 180ms ease;
}
.range-option:hover { background: #F4F5F7; transform: translateX(-2px); }
.range-option.is-selected { border-color: rgb(var(--brand-rgb) / 0.14); background: #FEF3EE; }
.dark .range-option:hover { background: #22262D; }
.dark .range-option.is-selected { border-color: rgb(var(--brand-rgb) / 0.20); background: #2A1A13; }

/* Right-column utilities share the same soft depth and interaction language. */
.side-card {
  box-shadow: 0 12px 34px -28px rgb(15 17 20 / 0.34);
  transition: border-color 220ms ease, box-shadow 260ms ease, transform 260ms cubic-bezier(0.22, 1, 0.36, 1);
}
.side-card:hover {
  border-color: rgb(var(--brand-rgb) / 0.18);
  box-shadow: 0 18px 42px -28px rgb(15 17 20 / 0.42);
}
.quick-person {
  opacity: 0.66;
  transition: opacity 180ms ease, transform 240ms cubic-bezier(0.22, 1, 0.36, 1);
}
.quick-person:hover { opacity: 1; transform: translateY(-2px); }
.quick-person.is-selected { opacity: 1; transform: translateY(-2px); }
.quick-person .quick-avatar {
  transition: box-shadow 220ms ease, scale 240ms cubic-bezier(0.22, 1, 0.36, 1);
}
.quick-person.is-selected .quick-avatar {
  box-shadow: 0 0 0 2px #FFFFFF, 0 0 0 4px #F0532B, 0 8px 18px -8px rgb(var(--brand-rgb) / 0.65);
  scale: 1.04;
}
.dark .quick-person.is-selected .quick-avatar { box-shadow: 0 0 0 2px #16181D, 0 0 0 4px #F0532B, 0 8px 18px -8px rgb(var(--brand-rgb) / 0.72); }
.quick-amount {
  border: 1px solid transparent;
  background: #F4F5F7;
  transition: border-color 180ms ease, background-color 180ms ease, box-shadow 180ms ease;
}
.quick-amount:focus-within {
  border-color: rgb(var(--brand-rgb) / 0.28);
  background: #FFFFFF;
  box-shadow: 0 0 0 3px rgb(var(--brand-rgb) / 0.08);
}
.dark .quick-amount { background: #1D2026; }
.dark .quick-amount:focus-within { background: #16181D; }
.payment-account {
  isolation: isolate;
  box-shadow: 0 20px 38px -24px rgb(15 17 20 / 0.48);
}
.payment-account::before {
  content: '';
  position: absolute;
  z-index: 0;
  width: 190px;
  height: 190px;
  inset-inline-start: -72px;
  top: -106px;
  border: 1px solid rgb(255 255 255 / 0.18);
  border-radius: 45% 55% 48% 52% / 56% 42% 58% 44%;
  background: linear-gradient(145deg, rgb(255 255 255 / 0.18), rgb(255 255 255 / 0.025));
  transform: rotate(-14deg);
  transition: transform 700ms cubic-bezier(0.22, 1, 0.36, 1);
}
.payment-account::after {
  content: '';
  position: absolute;
  z-index: 0;
  width: 78px;
  height: 78px;
  inset-inline-end: -24px;
  bottom: -31px;
  border: 1px solid rgb(255 255 255 / 0.16);
  border-radius: 50%;
  background: radial-gradient(circle at 32% 28%, rgb(255 255 255 / 0.32) 0 5%, transparent 68%);
}
.payment-account:hover::before { transform: translate(-5px, 6px) rotate(-7deg) scale(1.04); }
.payment-account > * { position: relative; z-index: 1; }
.plan-card {
  border: 1px solid rgb(255 255 255 / 0.08);
  background:
    radial-gradient(circle at 84% 8%, rgb(var(--brand-rgb) / 0.50), transparent 38%),
    radial-gradient(circle at 8% 100%, rgb(139 92 246 / 0.22), transparent 40%),
    linear-gradient(145deg, #202329 0%, #101216 68%);
  box-shadow: 0 22px 46px -28px rgb(0 0 0 / 0.72);
}
.plan-card::before {
  content: '';
  position: absolute;
  width: 150px;
  height: 150px;
  inset-inline-start: -76px;
  top: -82px;
  border: 1px solid rgb(255 255 255 / 0.10);
  border-radius: 50%;
  box-shadow: 0 0 0 28px rgb(255 255 255 / 0.025), 0 0 0 56px rgb(255 255 255 / 0.018);
}
.plan-card-button {
  box-shadow: 0 12px 24px -14px rgb(0 0 0 / 0.65);
  transition: transform 240ms cubic-bezier(0.22, 1, 0.36, 1), box-shadow 220ms ease, background-color 180ms ease;
}
.plan-card-button:hover { transform: translateY(-2px); box-shadow: 0 16px 28px -14px rgb(0 0 0 / 0.72); }
.earnings-plot {
  background: linear-gradient(180deg, rgb(244 245 247 / 0.72), rgb(255 255 255 / 0.42));
  box-shadow: inset 0 1px 0 rgb(255 255 255 / 0.72);
}
.dark .earnings-plot {
  background: linear-gradient(180deg, rgb(29 32 38 / 0.78), rgb(22 24 29 / 0.38));
  box-shadow: inset 0 1px 0 rgb(255 255 255 / 0.025);
}
.earnings-bar {
  /* Without a cap, a 7-day range spreads seven bars across the whole card. */
  max-width: 3.5rem;
  margin-inline: auto;
  border: 1px solid rgb(var(--chart-rgb) / 0.10);
  border-bottom: 0;
  background: linear-gradient(180deg, rgb(var(--chart-rgb) / 0.34), rgb(var(--chart-rgb) / 0.10));
  box-shadow: inset 0 1px 0 rgb(255 255 255 / 0.26);
  transform-origin: bottom;
  transition: height 650ms cubic-bezier(0.22, 1, 0.36, 1), opacity 220ms ease, transform 300ms cubic-bezier(0.22, 1, 0.36, 1), background 260ms ease, box-shadow 260ms ease;
}
.earnings-bar::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: linear-gradient(100deg, transparent 18%, rgb(255 255 255 / 0.18) 48%, transparent 74%);
  background-position: 100% 0;
  background-size: 240% 100%;
  opacity: 0;
  pointer-events: none;
  transition: background-position 620ms cubic-bezier(0.22, 1, 0.36, 1), opacity 180ms ease;
}
.earnings-bar.is-peak {
  border-color: rgb(var(--chart-rgb) / 0.22);
  background: linear-gradient(180deg, rgb(var(--chart-top) / 0.72), rgb(var(--chart-rgb) / 0.28));
  box-shadow: 0 8px 20px -12px rgb(var(--chart-rgb) / 0.52), inset 0 1px 0 rgb(255 255 255 / 0.36);
}
.earnings-bar.is-active {
  z-index: 2;
  border-color: rgb(255 255 255 / 0.26);
  background: linear-gradient(180deg, rgb(var(--chart-top)) 0%, rgb(var(--chart-rgb)) 52%, rgb(var(--chart-bottom)) 100%);
  box-shadow: 0 14px 26px -12px rgb(var(--chart-rgb) / 0.72), inset 0 1px 0 rgb(255 255 255 / 0.5);
  transform: scaleX(1.06);
}
.earnings-bar.is-active::after { background-position: -100% 0; opacity: 1; }
.earnings-bar.is-dimmed { opacity: 0.43; }
.dark .earnings-bar {
  border-color: rgb(var(--chart-rgb) / 0.13);
  background: linear-gradient(180deg, rgb(var(--chart-rgb) / 0.30), rgb(var(--chart-rgb) / 0.09));
  box-shadow: inset 0 1px 0 rgb(255 255 255 / 0.08);
}
.dark .earnings-bar.is-peak {
  background: linear-gradient(180deg, rgb(var(--chart-top) / 0.62), rgb(var(--chart-rgb) / 0.22));
}
.dark .earnings-bar.is-active {
  border-color: rgb(255 255 255 / 0.18);
  background: linear-gradient(180deg, rgb(var(--chart-top)) 0%, rgb(var(--chart-rgb)) 58%, rgb(var(--chart-bottom)) 100%);
}
.earnings-tab-indicator {
  background: rgb(var(--chart-rgb));
  box-shadow: 0 5px 14px -7px rgb(var(--chart-rgb) / 0.85);
}
@media (prefers-reduced-motion: reduce) {
  .earnings-bar,
  .earnings-bar::after { transition: none; }
}

/* Live chart uses a lighter plot treatment so changing data stays legible. */
.live-card { position: relative; isolation: isolate; overflow: hidden; }
.live-card::before {
  content: '';
  position: absolute;
  z-index: 0;
  width: 210px;
  height: 150px;
  inset-inline-start: -82px;
  top: -100px;
  border-radius: 50%;
  background: radial-gradient(circle, rgb(36 164 85 / 0.10), transparent 70%);
  pointer-events: none;
}
.live-card > * { position: relative; z-index: 1; }
.live-plot {
  background:
    linear-gradient(180deg, rgb(244 245 247 / 0.76), rgb(255 255 255 / 0.38)),
    repeating-linear-gradient(90deg, transparent 0, transparent calc(25% - 1px), rgb(15 17 20 / 0.035) 25%);
  box-shadow: inset 0 1px 0 rgb(255 255 255 / 0.76);
}
.dark .live-plot {
  background:
    linear-gradient(180deg, rgb(29 32 38 / 0.80), rgb(22 24 29 / 0.36)),
    repeating-linear-gradient(90deg, transparent 0, transparent calc(25% - 1px), rgb(255 255 255 / 0.025) 25%);
  box-shadow: inset 0 1px 0 rgb(255 255 255 / 0.025);
}
.live-area,
.live-glow,
.live-line {
  transition: d 900ms cubic-bezier(0.22, 1, 0.36, 1);
}
.live-area { opacity: 0.72; }
.live-glow { filter: blur(1.5px); }
.live-line {
  filter: drop-shadow(0 5px 5px rgb(var(--brand-rgb) / 0.22));
  stroke-dasharray: 1;
  stroke-dashoffset: 1;
  animation: liveLineDraw 1100ms cubic-bezier(0.22, 1, 0.36, 1) 650ms both;
}
.live-endpoint {
  transition: top 900ms cubic-bezier(0.22, 1, 0.36, 1);
}
@keyframes liveLineDraw { to { stroke-dashoffset: 0; } }
@media (prefers-reduced-motion: reduce) {
  .live-line { animation: none; stroke-dashoffset: 0; }
  .live-area,
  .live-glow,
  .live-line,
  .live-endpoint { transition: none; }
}

/* Load choreography: a short, staggered soft landing for visual hierarchy. */
.motion-enter {
  --motion-x: 0px;
  --motion-y: 18px;
  opacity: 0;
  animation: motionEnter 760ms cubic-bezier(0.16, 1, 0.3, 1) both;
  animation-delay: var(--motion-delay, 0ms);
  will-change: opacity, translate, scale, filter;
}
.motion-from-start { --motion-x: 18px; --motion-y: 0px; }
.motion-from-top { --motion-x: 0px; --motion-y: -12px; }
.motion-soft { --motion-y: 10px; }
@keyframes motionEnter {
  0% {
    opacity: 0;
    translate: var(--motion-x) var(--motion-y);
    scale: 0.978;
    filter: blur(7px);
  }
  68% {
    opacity: 1;
    translate: 0 -1px;
    scale: 1.004;
    filter: blur(0);
  }
  100% {
    opacity: 1;
    translate: 0 0;
    scale: 1;
    filter: none;
  }
}
.chart-column {
  position: relative;
  z-index: 0;
  transform-origin: center bottom;
  animation: chartColumnIn 720ms cubic-bezier(0.16, 1, 0.3, 1) both;
}
.chart-column:hover { z-index: 30; }
@keyframes chartColumnIn {
  from { opacity: 0; transform: scaleY(0.08); }
  to { opacity: 1; transform: scaleY(1); }
}
@media (prefers-reduced-motion: reduce) {
  .motion-enter {
    opacity: 1;
    animation: none;
    translate: none;
    scale: 1;
    filter: none;
  }
  .chart-column { animation: none; }
}

:root {
    --brand-l: 240 83 43;
    --brand-l-dark: 206 71 37;
    --brand-l-soft: 245 138 111;
    --brand-d: 240 83 43;
    --brand-d-dark: 206 71 37;
    --brand-d-soft: 245 138 111;
    --brand-rgb: var(--brand-l);
    --brand-dark-rgb: var(--brand-l-dark);
    --brand-soft-rgb: var(--brand-l-soft);
    --glow-a: 0.42;
}

.dark {
    --brand-rgb: var(--brand-d);
    --brand-dark-rgb: var(--brand-d-dark);
    --brand-soft-rgb: var(--brand-d-soft);
    --glow-a: 0.20;
    color-scheme: dark;
}

html {
    background-color: #F4F5F7;
    overflow-x: hidden;
    -webkit-tap-highlight-color: transparent;
}

html.dark {
    background-color: #0D0F12;
}

html.lock {
    overflow: hidden;
}

body {
    transition: background-color .35s ease, color .35s ease;
}

:where(a, button, [tabindex]):focus-visible {
    outline: 2px solid rgb(var(--brand-rgb) / 0.55);
    outline-offset: 3px;
}

input[type=search]::-webkit-search-cancel-button,
input[type=search]::-webkit-search-decoration {
    -webkit-appearance: none;
    appearance: none;
}

input[type=number]::-webkit-inner-spin-button,
input[type=number]::-webkit-outer-spin-button {
    -webkit-appearance: none;
    margin: 0;
}

input[type=number] {
    -moz-appearance: textfield;
    appearance: textfield;
}

input[type=range] {
    -webkit-appearance: none;
    appearance: none;
    height: 6px;
    border-radius: 9999px;
    background: rgb(var(--brand-rgb) / 0.18);
    outline: none;
    cursor: pointer;
}

input[type=range]::-webkit-slider-thumb {
    -webkit-appearance: none;
    appearance: none;
    height: 22px;
    width: 22px;
    border-radius: 9999px;
    background: #fff;
    border: 3px solid rgb(var(--brand-rgb));
    box-shadow: 0 2px 8px rgba(15, 23, 42, 0.25);
    transition: transform .2s ease;
}

input[type=range]::-webkit-slider-thumb:active {
    transform: scale(1.15);
}

input[type=range]::-moz-range-thumb {
    height: 16px;
    width: 16px;
    border-radius: 9999px;
    background: #fff;
    border: 3px solid rgb(var(--brand-rgb));
    box-shadow: 0 2px 8px rgba(15, 23, 42, 0.25);
}

input[type=range].hue {
    background: linear-gradient(to right, #f00 0%, #ff0 17%, #0f0 33%, #0ff 50%, #00f 67%, #f0f 83%, #f00 100%);
}

/* Scrollbars are hidden app-wide; scrolling behaviour itself is untouched. */
* {
    scrollbar-width: none;
    -ms-overflow-style: none;
}

::-webkit-scrollbar {
    width: 0;
    height: 0;
    display: none;
}

@property --vt-r {
    syntax: '<length>';
    inherits: true;
    initial-value: 99999px;
}

::view-transition-old(root),
::view-transition-new(root) {
    animation: none;
    mix-blend-mode: normal;
}

::view-transition-old(root) {
    z-index: 1;
}

::view-transition-new(root) {
    z-index: 2;
    -webkit-mask-image: radial-gradient(circle at var(--vt-x, 50%) var(--vt-y, 50%), #000 calc(var(--vt-r) - 160px), transparent var(--vt-r));
    mask-image: radial-gradient(circle at var(--vt-x, 50%) var(--vt-y, 50%), #000 calc(var(--vt-r) - 160px), transparent var(--vt-r));
}

@media (prefers-reduced-motion: reduce) {

    ::view-transition-group(*),
    ::view-transition-old(*),
    ::view-transition-new(*) {
        animation: none !important;
    }
}

body::before {
    content: '';
    position: fixed;
    inset: 0;
    z-index: 0;
    pointer-events: none;
    background:
        radial-gradient(68rem 46rem at calc(100% + 7rem) -13rem,
            rgb(var(--brand-rgb) / var(--glow-a)) 0%,
            rgb(var(--brand-rgb) / calc(var(--glow-a) * 0.52)) 26%,
            rgb(var(--brand-rgb) / calc(var(--glow-a) * 0.20)) 46%,
            rgb(var(--brand-rgb) / calc(var(--glow-a) * 0.06)) 62%,
            rgb(var(--brand-rgb) / 0) 76%);
}

/* ═══════════════════════════════════════════════════════════════════════
   From creators.html — the public hub: card entrance, live hearts,
   gift confirmation burst.
   ═══════════════════════════════════════════════════════════════════════ */

@keyframes cardIn {
    from { opacity: 0; transform: translateY(18px) scale(0.97); }
    to   { opacity: 1; transform: none; }
}

.card-in {
    animation: cardIn 620ms cubic-bezier(0.22, 1, 0.36, 1) both;
    animation-delay: calc(var(--i, 0) * 55ms);
}

/* Hearts drift up out of the live badge, TikTok style. */
@keyframes heartRise {
    0%   { opacity: 0; transform: translate(0, 0) scale(0.4) rotate(0deg); }
    15%  { opacity: 1; }
    75%  { opacity: 1; }
    100% { opacity: 0; transform: translate(var(--dx, 0px), var(--rise, -150px)) scale(1.2) rotate(var(--rot, 14deg)); }
}

.heart {
    animation: heartRise var(--dur, 3.4s) ease-out infinite;
    animation-delay: var(--delay, 0s);
    will-change: transform, opacity;
}

@keyframes livePulse {
    0%   { opacity: 0.55; transform: scale(0.85); }
    100% { opacity: 0;    transform: scale(1.35); }
}

.live-pulse { animation: livePulse 1900ms ease-out infinite; }

@keyframes giftPop {
    0%   { opacity: 0; transform: translateY(26px) scale(0.5) rotate(-14deg); }
    55%  { opacity: 1; transform: translateY(-10px) scale(1.14) rotate(5deg); }
    100% { opacity: 1; transform: none; }
}

.gift-pop { animation: giftPop 780ms cubic-bezier(0.22, 1, 0.36, 1) both; }

@keyframes ringOut {
    from { opacity: 0.55; transform: scale(0.6); }
    to   { opacity: 0;    transform: scale(2.1); }
}

.ring-out   { animation: ringOut 1100ms ease-out infinite; }
.ring-out-2 { animation-delay: 380ms; }

@media (prefers-reduced-motion: reduce) {
    .card-in, .gift-pop, .ring-out, .heart, .live-pulse { animation: none; }
}

/* ═══════════════════════════════════════════════════════════════════════
   Direction. The prototype was RTL-only; English renders LTR, so any
   hard-coded horizontal offset is mirrored through --dir instead.
   ═══════════════════════════════════════════════════════════════════════ */

:root      { --dir:  1; --tip-origin: 100%; }
[dir="ltr"]{ --dir: -1; --tip-origin: 0%; }

.range-option:hover { transform: translateX(calc(var(--dir) * -2px)); }

[dir="ltr"] .range-menu::before { inset-inline-start: auto; inset-inline-end: 1.25rem; }

/* Icons that point along the reading direction. */
.dir-flip { transform: scaleX(var(--dir)); }

/* ═══════════════════════════════════════════════════════════════════════
   App additions: forms, tables, badges shared by the panels.
   ═══════════════════════════════════════════════════════════════════════ */

.field {
    width: 100%;
    border-radius: 0.875rem;
    border: 1px solid #E9EAED;
    background: #F4F5F7;
    padding: 0.625rem 0.875rem;
    font-size: 0.8125rem;
    font-weight: 600;
    color: #0F1114;
    transition: border-color .2s ease, background .2s ease, box-shadow .2s ease;
}
.field::placeholder { color: #9CA2AC; font-weight: 500; }
.field:focus {
    outline: none;
    background: #FFFFFF;
    border-color: rgb(var(--brand-rgb) / 0.55);
    box-shadow: 0 0 0 3px rgb(var(--brand-rgb) / 0.12);
}
.dark .field { background: #1D2026; border-color: #262A31; color: #F3F5F7; }
.dark .field:focus { background: #16181D; }
.field-error { border-color: #EF4B3F !important; }

.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    border-radius: 0.875rem;
    padding: 0.625rem 1.125rem;
    font-size: 0.8125rem;
    font-weight: 700;
    transition: transform .2s ease, background .2s ease, opacity .2s ease, box-shadow .2s ease;
    cursor: pointer;
}
.btn:disabled { opacity: 0.5; cursor: not-allowed; }
.btn:not(:disabled):hover { transform: translateY(-1px); }
.btn-brand { background: rgb(var(--brand-rgb)); color: #fff; box-shadow: 0 8px 18px -10px rgb(var(--brand-rgb) / 0.8); }
.btn-ghost { background: #F4F5F7; color: #0F1114; }
.dark .btn-ghost { background: #1D2026; color: #F3F5F7; }
.btn-danger { background: #EF4B3F; color: #fff; }
.btn-outline { border: 1px solid #E9EAED; background: transparent; color: #0F1114; }
.dark .btn-outline { border-color: #262A31; color: #F3F5F7; }

@media (prefers-reduced-motion: reduce) {
    .btn:not(:disabled):hover { transform: none; }
}

/* Tables share one skin across every panel page. */
.tbl { width: 100%; border-collapse: separate; border-spacing: 0; }
.tbl th {
    text-align: start;
    font-size: 0.6875rem;
    font-weight: 700;
    color: #6E747E;
    padding: 0.75rem 0.875rem;
    white-space: nowrap;
}
.dark .tbl th { color: #99A0AB; }

/* `.tbl th` sets text-align at (0,1,1) — an element plus a class — which beats
   a bare `.text-end` utility at (0,1,0). Numeric headers therefore stayed
   start-aligned over end-aligned figures. Two classes and the element settle
   it in the utility's favour. */
.tbl th.text-end { text-align: end; }
.tbl th.text-center { text-align: center; }

/* A filled header band, so the column names read as a header rather than as a
   first row. The dividers under it come from each cell's own border-top, which
   is why there is no border-bottom here — it would double up. */
.tbl thead th { background: #F9FAFB; }
.dark .tbl thead th { background: #1A1D22; }

/* Wrapper for a table that lives in its own card: keeps the rounded corners
   from being squared off by the header band, and gives wide tables somewhere
   to scroll that is not the page body. */
.tbl-card {
    overflow-x: auto;
    border-radius: 1.5rem;
    border: 1px solid #E9EAED;
    background: #FFFFFF;
}
.dark .tbl-card { border-color: #262A31; background: #16181D; }

/* The expanded detail under a row. It is a cell spanning every column, so it
   needs to shed the padding a normal cell carries. */
.tbl td.tbl-detail { padding: 0; background: #F9FAFB; }
.dark .tbl td.tbl-detail { background: #1A1D22; }
.tbl td { padding: 0.875rem; font-size: 0.8125rem; border-top: 1px solid #E9EAED; }
.dark .tbl td { border-color: #262A31; }
.tbl tbody tr { transition: background .18s ease; }
.tbl tbody tr:hover { background: #F4F5F7; }
.dark .tbl tbody tr:hover { background: #1D2026; }

.badge {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    border-radius: 9999px;
    padding: 0.25rem 0.625rem;
    font-size: 0.6875rem;
    font-weight: 700;
    white-space: nowrap;
}

/* The overlay preview iframe paints its own transparent ground. */
.overlay-frame {
    background-image:
        linear-gradient(45deg, #e5e7eb 25%, transparent 25%),
        linear-gradient(-45deg, #e5e7eb 25%, transparent 25%),
        linear-gradient(45deg, transparent 75%, #e5e7eb 75%),
        linear-gradient(-45deg, transparent 75%, #e5e7eb 75%);
    background-size: 16px 16px;
    background-position: 0 0, 0 8px, 8px -8px, -8px 0;
}
.dark .overlay-frame {
    background-image:
        linear-gradient(45deg, #262A31 25%, transparent 25%),
        linear-gradient(-45deg, #262A31 25%, transparent 25%),
        linear-gradient(45deg, transparent 75%, #262A31 75%),
        linear-gradient(-45deg, transparent 75%, #262A31 75%);
}

@media print {
    .no-print { display: none !important; }
    body { background: #fff !important; }
}

/* ═══════════════════════════════════════════════════════════════════════
   Wide screens. On an ultrawide the panel is full-bleed, so tables would
   otherwise spread six columns across 1900px with huge gaps between a
   name and its amount. Columns hug their content instead, and the first
   (identity) column absorbs the slack.
   ═══════════════════════════════════════════════════════════════════════ */

@media (min-width: 1280px) {
    /* Values stay on one line; the container cap below keeps the table readable. */
    .tbl th,
    .tbl td { white-space: nowrap; }

    /* Opt-out for cells that genuinely need to wrap (gift messages). */
    .tbl .cell-wrap {
        white-space: normal;
        max-width: 32rem;
    }
}

/* The bar chart stretches with the page; keep bars from becoming slabs. */

/* ═══════════════════════════════════════════════════════════════════════
   Sign-in (/login only — every other auth screen keeps the plain shell).

   One continuous field runs behind BOTH columns: the rail paints no
   background of its own, so there is no seam down the middle where the
   two halves meet. Everything is driven off --brand-rgb, so a workspace
   that repaints its accent in Site Settings repaints this page too; no
   accent is written as a literal.
   ═══════════════════════════════════════════════════════════════════════ */

.auth-shell { min-height: 100svh; }

/* ── The field ────────────────────────────────────────────────────────
   Fixed and full-viewport, so it spans the rail and the form column as a
   single surface and never joins the scroll or catches a pointer.
   Three layers: a base wash, a fine grid, two drifting brand pools. */
.auth-bg {
    position: fixed;
    inset: 0;
    z-index: 0;
    pointer-events: none;
    overflow: hidden;
    background:
        radial-gradient(115% 80% at 8% 0%, rgb(var(--brand-rgb) / 0.14), transparent 56%),
        radial-gradient(90% 70% at 100% 100%, rgb(var(--brand-soft-rgb) / 0.13), transparent 60%),
        linear-gradient(165deg, #FFFFFF 0%, #F4F5F7 52%, #EFF1F4 100%);
}
.dark .auth-bg {
    background:
        radial-gradient(115% 80% at 8% 0%, rgb(var(--brand-rgb) / 0.20), transparent 56%),
        radial-gradient(90% 70% at 100% 100%, rgb(var(--brand-soft-rgb) / 0.12), transparent 62%),
        linear-gradient(165deg, #16181D 0%, #101318 55%, #0D0F12 100%);
}

/* A 34px grid, faded out downward so it never fights the copy. */
.auth-bg::before {
    content: '';
    position: absolute;
    inset: 0;
    background-image:
        linear-gradient(to right, rgb(15 17 20 / 0.045) 1px, transparent 1px),
        linear-gradient(to bottom, rgb(15 17 20 / 0.045) 1px, transparent 1px);
    background-size: 34px 34px;
    -webkit-mask-image: linear-gradient(to bottom, #000 0%, transparent 82%);
    mask-image: linear-gradient(to bottom, #000 0%, transparent 82%);
}
.dark .auth-bg::before {
    background-image:
        linear-gradient(to right, rgb(243 245 247 / 0.05) 1px, transparent 1px),
        linear-gradient(to bottom, rgb(243 245 247 / 0.05) 1px, transparent 1px);
}

/* The moving half: one slow pool, so the page breathes without drawing
   attention away from the form. */
.auth-bg::after {
    content: '';
    position: absolute;
    inset-inline-start: -12%;
    top: -20%;
    width: 44rem;
    height: 44rem;
    border-radius: 50%;
    filter: blur(80px);
    opacity: 0.5;
    background: radial-gradient(circle, rgb(var(--brand-rgb) / 0.30), transparent 66%);
    animation: authDrift 28s ease-in-out infinite alternate;
}
.dark .auth-bg::after { opacity: 0.32; }

@keyframes authDrift {
    from { transform: translate3d(0, 0, 0) scale(1); }
    to   { transform: translate3d(5%, 7%, 0) scale(1.14); }
}

/* ── The brand rail ───────────────────────────────────────────────────
   Desktop only, and deliberately background-free: it sits on the shared
   field. The only division is a hairline that fades out at both ends, so
   the two halves read as one surface with a fold, not two panels. */
.auth-rail { position: relative; }
.auth-rail::after {
    content: '';
    position: absolute;
    inset-block: 8%;
    inset-inline-end: 0;
    width: 1px;
    background: linear-gradient(to bottom, transparent, rgb(15 17 20 / 0.10) 22%, rgb(15 17 20 / 0.10) 78%, transparent);
}
.dark .auth-rail::after {
    background: linear-gradient(to bottom, transparent, rgb(243 245 247 / 0.10) 22%, rgb(243 245 247 / 0.10) 78%, transparent);
}

/* ── The form card ────────────────────────────────────────────────────
   Glass, so the field shows through and the card belongs to the page
   rather than sitting on it. The solid colour underneath is the fallback
   wherever backdrop-filter is unavailable. */
.auth-card {
    background: rgb(255 255 255 / 0.82);
    border: 1px solid rgb(233 234 237 / 0.9);
    box-shadow:
        0 1px 2px rgb(15 23 42 / 0.04),
        0 18px 44px -28px rgb(15 23 42 / 0.30);
}
.dark .auth-card {
    background: rgb(22 24 29 / 0.80);
    border-color: rgb(38 42 49 / 0.9);
    box-shadow:
        0 1px 2px rgb(0 0 0 / 0.30),
        0 18px 44px -26px rgb(0 0 0 / 0.60);
}
@supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) {
    .auth-card {
        -webkit-backdrop-filter: blur(20px) saturate(1.4);
        backdrop-filter: blur(20px) saturate(1.4);
    }
}

/* ── The demo alerts ──────────────────────────────────────────────────
   Three cards standing in for what OBS actually renders. They ride --d
   for their stagger, the same rhythm the panels use. */
.auth-alert {
    animation: authAlertIn 900ms cubic-bezier(0.22, 1, 0.36, 1) backwards;
    animation-delay: var(--d, 0ms);
}
@keyframes authAlertIn {
    0%   { opacity: 0; transform: translateY(18px) scale(0.96); }
    100% { opacity: 1; transform: none; }
}

/* The lead card keeps breathing, so the rail is never quite still. */
.auth-alert-live {
    animation:
        authAlertIn 900ms cubic-bezier(0.22, 1, 0.36, 1) backwards,
        authFloat 6s ease-in-out 1.2s infinite;
}
@keyframes authFloat {
    0%, 100% { transform: none; }
    50%      { transform: translateY(-7px); }
}

/* Live dot — the same idea as the presence dot in the panels. */
.auth-pulse { position: relative; }
.auth-pulse::after {
    content: '';
    position: absolute;
    inset: 0;
    border-radius: 999px;
    background: inherit;
    animation: authPulse 2s cubic-bezier(0.22, 1, 0.36, 1) infinite;
}
@keyframes authPulse {
    0%        { transform: scale(1); opacity: 0.7; }
    70%, 100% { transform: scale(2.6); opacity: 0; }
}

/* ── Fields ───────────────────────────────────────────────────────────
   A wrapper, so the leading icon can answer the input's focus. Focus is
   an accent border plus a thin ring, matching .field everywhere else. */
.auth-field { position: relative; display: flex; align-items: center; }
.auth-field > .field { padding-inline-start: 2.5rem; }
.auth-field-icon {
    position: absolute;
    inset-inline-start: 0.875rem;
    display: flex;
    color: #9CA2AC;
    pointer-events: none;
    transition: color .2s ease;
}
.dark .auth-field-icon { color: #6E747E; }
.auth-field:focus-within .auth-field-icon { color: rgb(var(--brand-rgb)); }

/* Trailing control (the reveal toggle) sits opposite the icon. */
.auth-field-btn {
    position: absolute;
    inset-inline-end: 0.25rem;
    display: flex;
    height: 2.25rem;
    width: 2.25rem;
    align-items: center;
    justify-content: center;
    border-radius: 0.75rem;
    color: #9CA2AC;
    transition: color .2s ease, background .2s ease;
}
.auth-field-btn:hover { color: #0F1114; background: #E9EBEF; }
.dark .auth-field-btn:hover { color: #F3F5F7; background: #22262D; }

/* The "this parses" tick, opposite the icon. Absolutely positioned, so the
   wrapper's align-items does not reach it and it centres itself. */
.auth-field-tick {
    position: absolute;
    inset-inline-end: 0.875rem;
    top: 50%;
    transform: translateY(-50%);
    display: flex;
    color: #24A455;
    pointer-events: none;
}

/* A select drops its native arrow so the drawn chevron is not doubled up.
   Scoped, never global: other screens use a bare `select.field` and must keep
   the arrow the platform gives them. */
.auth-field > select.field,
select.field.select-pill {
    -webkit-appearance: none;
    -moz-appearance: none;
    appearance: none;
}
.auth-field-chevron {
    position: absolute;
    inset-inline-end: 0.875rem;
    top: 50%;
    transform: translateY(-50%);
    display: flex;
    color: #9CA2AC;
    pointer-events: none;
}
.dark .auth-field-chevron { color: #6E747E; }

/* ── Language pills ───────────────────────────────────────────────────
   Three languages, so all three are one tap rather than two. One
   highlight crosses the track: --lang (0-2) is set on the track by PHP,
   which is why there is no JS measuring anything. --dir flips the travel
   for RTL, where the second chip sits to the LEFT of the first. */
.auth-langs {
    position: relative;
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 0.125rem;
    border-radius: 999px;
    padding: 0.1875rem;
    background: rgb(244 245 247 / 0.8);
    border: 1px solid rgb(233 234 237 / 0.9);
}
.dark .auth-langs {
    background: rgb(29 32 38 / 0.8);
    border-color: rgb(38 42 49 / 0.9);
}
.auth-langs::before {
    content: '';
    position: absolute;
    z-index: 0;
    top: 0.1875rem;
    bottom: 0.1875rem;
    inset-inline-start: 0.1875rem;
    width: calc((100% - 0.625rem) / 3);
    border-radius: 999px;
    background: #FFFFFF;
    box-shadow: 0 2px 8px -4px rgb(15 23 42 / 0.35);
    transform: translateX(calc(var(--dir) * -1 * var(--lang, 0) * (100% + 0.125rem)));
    transition: transform 460ms cubic-bezier(0.34, 1.36, 0.5, 1);
}
.dark .auth-langs::before {
    background: #262A31;
    box-shadow: 0 2px 8px -4px rgb(0 0 0 / 0.7);
}
.auth-lang {
    position: relative;
    z-index: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.375rem;
    min-width: 0;
    height: 2rem;
    border-radius: 999px;
    padding-inline: 0.5rem;
    font-size: 0.6875rem;
    font-weight: 700;
    color: #6E747E;
    white-space: nowrap;
    transition: color .2s ease;
}

/* The flag is a drawn SVG from the sprite, never an emoji: emoji render
   differently on every platform and ignore the type ramp. Clipped to a
   rounded corner here, with a hairline so a white-heavy flag still has an
   edge against the track. */
.auth-lang-flag {
    display: block;
    flex: none;
    width: 1.125rem;
    height: 0.75rem;
    border-radius: 0.1875rem;
    overflow: hidden;
    box-shadow: inset 0 0 0 1px rgb(15 17 20 / 0.14);
    filter: saturate(0.9);
    transition: filter .2s ease, opacity .2s ease;
    opacity: 0.72;
}
.dark .auth-lang-flag { box-shadow: inset 0 0 0 1px rgb(243 245 247 / 0.16); }
.auth-lang:hover .auth-lang-flag,
.auth-lang[aria-current='true'] .auth-lang-flag { filter: none; opacity: 1; }
.dark .auth-lang { color: #99A0AB; }
.auth-lang:hover { color: #0F1114; }
.dark .auth-lang:hover { color: #F3F5F7; }
.auth-lang[aria-current='true'] { color: #0F1114; }
.dark .auth-lang[aria-current='true'] { color: #F3F5F7; }

/* ── Role switch (sign-up) ────────────────────────────────────────────
   Supporter or creator. Same idea as the language track — one highlight
   travels rather than two backgrounds swapping — but over two slots, and
   these are links, so --seg comes from PHP and no JS measures anything. */
.auth-seg {
    position: relative;
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 0.125rem;
    border-radius: 999px;
    padding: 0.25rem;
    background: rgb(244 245 247 / 0.8);
    border: 1px solid rgb(233 234 237 / 0.9);
}
.dark .auth-seg {
    background: rgb(29 32 38 / 0.8);
    border-color: rgb(38 42 49 / 0.9);
}
.auth-seg::before {
    content: '';
    position: absolute;
    z-index: 0;
    top: 0.25rem;
    bottom: 0.25rem;
    inset-inline-start: 0.25rem;
    width: calc((100% - 0.625rem) / 2);
    border-radius: 999px;
    background: #FFFFFF;
    box-shadow: 0 2px 10px -5px rgb(15 23 42 / 0.4);
    transform: translateX(calc(var(--dir) * -1 * var(--seg, 0) * (100% + 0.125rem)));
    transition: transform 460ms cubic-bezier(0.34, 1.36, 0.5, 1);
}
.dark .auth-seg::before {
    background: #262A31;
    box-shadow: 0 2px 10px -5px rgb(0 0 0 / 0.7);
}
.auth-seg-item {
    position: relative;
    z-index: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.375rem;
    height: 2.125rem;
    border-radius: 999px;
    padding-inline: 0.625rem;
    font-size: 0.75rem;
    font-weight: 700;
    color: #6E747E;
    white-space: nowrap;
    transition: color .2s ease;
}
.dark .auth-seg-item { color: #99A0AB; }
.auth-seg-item:hover { color: #0F1114; }
.dark .auth-seg-item:hover { color: #F3F5F7; }
.auth-seg-item[aria-current='true'] { color: #0F1114; }
.dark .auth-seg-item[aria-current='true'] { color: #F3F5F7; }

/* ── Trust row ────────────────────────────────────────────────────────
   Quiet by design: it reassures, it does not sell. */
.auth-point {
    animation: authAlertIn 700ms cubic-bezier(0.22, 1, 0.36, 1) backwards;
    animation-delay: var(--d, 0ms);
}

@media (prefers-reduced-motion: reduce) {
    .auth-bg::after,
    .auth-alert,
    .auth-alert-live,
    .auth-point { animation: none; }
    /* Still a live indicator, just not a moving one. */
    .auth-pulse::after { animation: none; opacity: 0.35; transform: scale(1.8); }
    .auth-langs::before,
    .auth-seg::before { transition: none; }
}

/* ═══════════════════════════════════════════════════════════════════════
   Landing page.

   The hero states the promise, the three steps show the mechanism, and the
   grid is the product. Everything reads off --brand-rgb so a workspace
   that repaints its accent repaints this too.
   ═══════════════════════════════════════════════════════════════════════ */

/* ── Hero ─────────────────────────────────────────────────────────────
   A single brand pool behind the headline, masked so it fades before it
   reaches the grid below. */
.hero {
    position: relative;
    isolation: isolate;
}
.hero::before {
    content: '';
    position: absolute;
    z-index: -1;
    inset-inline: -20%;
    top: -8rem;
    height: 34rem;
    border-radius: 50%;
    filter: blur(90px);
    opacity: 0.5;
    background: radial-gradient(closest-side, rgb(var(--brand-rgb) / 0.30), transparent 72%);
    pointer-events: none;
}
.dark .hero::before { opacity: 0.34; }

/* Entrance: the hero assembles top-down on the house 70ms rhythm. */
.hero-in {
    animation: heroIn 780ms cubic-bezier(0.22, 1, 0.36, 1) backwards;
    animation-delay: var(--d, 0ms);
}
@keyframes heroIn {
    0%   { opacity: 0; transform: translateY(16px); }
    100% { opacity: 1; transform: none; }
}

/* ── The three steps ──────────────────────────────────────────────────
   Find → send → see. The connector is a flex child rather than a border,
   so it disappears cleanly when the row wraps on a phone. */
.step-icon {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 2.75rem;
    height: 2.75rem;
    border-radius: 1rem;
    color: rgb(var(--brand-rgb));
    background: rgb(var(--brand-rgb) / 0.12);
    transition: transform .3s cubic-bezier(0.22, 1, 0.36, 1), background .2s ease;
}
.step:hover .step-icon {
    transform: translateY(-3px);
    background: rgb(var(--brand-rgb) / 0.2);
}

/* The arrow points along the reading direction. */
.step-link { color: #9CA2AC; transform: scaleX(calc(var(--dir) * -1)); }
.dark .step-link { color: #6E747E; }

/* ── Creator card ─────────────────────────────────────────────────────
   The cover is the only image, so it carries the hover. Everything else
   stays still, which keeps a wall of twelve cards calm. */
.creator-card {
    transition:
        transform .3s cubic-bezier(0.22, 1, 0.36, 1),
        border-color .2s ease,
        box-shadow .3s ease;
}
.creator-card:hover {
    transform: translateY(-4px);
    border-color: rgb(var(--brand-rgb) / 0.35);
    box-shadow: 0 18px 40px -24px rgb(15 23 42 / 0.42);
}
.dark .creator-card:hover { box-shadow: 0 18px 40px -22px rgb(0 0 0 / 0.7); }

.creator-cover img {
    transition: transform .5s cubic-bezier(0.22, 1, 0.36, 1);
}
.creator-card:hover .creator-cover img { transform: scale(1.06); }

/* Staggered landing, capped so the twelfth card is not left waiting. */
.creator-card {
    animation: cardIn 620ms cubic-bezier(0.22, 1, 0.36, 1) backwards;
    animation-delay: calc(var(--i, 0) * 45ms);
}
@keyframes cardIn {
    0%   { opacity: 0; transform: translateY(18px) scale(0.985); }
    100% { opacity: 1; transform: none; }
}

/* The live chip's halo, same idea as the presence dot elsewhere. */
.live-dot { position: relative; }
.live-dot::after {
    content: '';
    position: absolute;
    inset: 0;
    border-radius: 999px;
    background: inherit;
    animation: livePulse 2s cubic-bezier(0.22, 1, 0.36, 1) infinite;
}
@keyframes livePulse {
    0%        { transform: scale(1); opacity: 0.75; }
    70%, 100% { transform: scale(2.8); opacity: 0; }
}

/* ── Filter pills ─────────────────────────────────────────────────────
   Plain links, so the active one is styled server-side; no JS measures
   anything and the row is correct on the first paint. */
.pill {
    display: inline-flex;
    flex: none;
    align-items: center;
    gap: 0.4375rem;
    height: 2.25rem;
    border-radius: 999px;
    padding-inline: 0.9375rem;
    font-size: 0.75rem;
    font-weight: 700;
    white-space: nowrap;
    border: 1px solid #E9EAED;
    background: #FFFFFF;
    color: #6E747E;
    transition: color .2s ease, background .2s ease, border-color .2s ease;
}
.dark .pill { border-color: #262A31; background: #16181D; color: #99A0AB; }
.pill:hover { color: #0F1114; border-color: rgb(var(--brand-rgb) / 0.35); }
.dark .pill:hover { color: #F3F5F7; }
.pill.is-on {
    background: rgb(var(--brand-rgb));
    border-color: rgb(var(--brand-rgb));
    color: #FFFFFF;
    box-shadow: 0 8px 18px -10px rgb(var(--brand-rgb) / 0.85);
}
.dark .pill.is-on { color: #FFFFFF; }

/* ── Search row ───────────────────────────────────────────────────────
   A pill-shaped variant of .field. Colour and focus come from .field
   itself, including its dark half; only the shape changes here.
   `.select-pill` (above) drops the native arrow, and the drawn one is
   `.auth-field-chevron`, which positions itself and needs no wrapper class. */
.field-pill {
    border-radius: 999px;
    height: 3rem;
    padding-block: 0;
}

@media (prefers-reduced-motion: reduce) {
    .hero-in,
    .creator-card { animation: none; }
    .creator-card,
    .creator-cover img,
    .step-icon { transition: none; }
    .creator-card:hover { transform: none; }
    .creator-card:hover .creator-cover img { transform: none; }
    .step:hover .step-icon { transform: none; }
    /* Still a live indicator, just not a moving one. */
    .live-dot::after { animation: none; opacity: 0.4; transform: scale(2); }
}

/* ═══════════════════════════════════════════════════════════════════════
   Public creator profile and the gift composer.

   The composer is the only thing on this page that matters, so it gets the
   width and the preview gets the sticky column: a supporter can see what
   their gift will look like on the stream while they are still typing it.
   ═══════════════════════════════════════════════════════════════════════ */

/* ── Profile hero ─────────────────────────────────────────────────────
   The cover carries a brand-tinted scrim so white text stays legible over
   any photograph, including a blown-out one. */
.profile-cover { position: relative; overflow: hidden; }
.profile-cover::after {
    content: '';
    position: absolute;
    inset: 0;
    background:
        linear-gradient(180deg, rgb(15 17 20 / 0.10) 0%, rgb(15 17 20 / 0.72) 100%),
        radial-gradient(80% 120% at 88% 0%, rgb(var(--brand-rgb) / 0.30), transparent 62%);
    pointer-events: none;
}

/* The avatar sits on the seam between cover and card, so it needs a ring in
   the card's own colour to cut cleanly out of the photograph. */
.profile-avatar {
    box-shadow: 0 0 0 4px #FFFFFF, 0 12px 28px -14px rgb(15 23 42 / 0.5);
}
.dark .profile-avatar { box-shadow: 0 0 0 4px #16181D, 0 12px 28px -14px rgb(0 0 0 / 0.7); }
.profile-avatar.is-live { box-shadow: 0 0 0 4px #FFFFFF, 0 0 0 7px #EF4B3F; }
.dark .profile-avatar.is-live { box-shadow: 0 0 0 4px #16181D, 0 0 0 7px #EF4B3F; }

/* ── Sticker tiles ────────────────────────────────────────────────────
   The whole tile is the target. Selection is a solid accent ring rather
   than a shadow, so it survives on both themes and never blurs the art. */
.sticker-tile {
    position: relative;
    border: 1px solid #E9EAED;
    background: #FFFFFF;
    transition:
        transform .25s cubic-bezier(0.22, 1, 0.36, 1),
        border-color .2s ease,
        box-shadow .2s ease;
}
.dark .sticker-tile { border-color: #262A31; background: #16181D; }
.sticker-tile:hover {
    transform: translateY(-3px);
    border-color: rgb(var(--brand-rgb) / 0.45);
}
.sticker-tile.is-on {
    border-color: rgb(var(--brand-rgb));
    box-shadow: inset 0 0 0 1px rgb(var(--brand-rgb)), 0 10px 24px -14px rgb(var(--brand-rgb) / 0.8);
    background: rgb(var(--brand-rgb) / 0.06);
}

/* The tick that marks the chosen tile. */
.sticker-check {
    position: absolute;
    top: 0.375rem;
    inset-inline-end: 0.375rem;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 1.25rem;
    height: 1.25rem;
    border-radius: 999px;
    color: #FFFFFF;
    background: rgb(var(--brand-rgb));
    animation: stickerCheck 340ms cubic-bezier(0.34, 1.36, 0.5, 1);
}
@keyframes stickerCheck {
    0%   { transform: scale(0.4); opacity: 0; }
    100% { transform: none; opacity: 1; }
}

/* Art drifts at rest and springs when its tile is hovered, so a wall of
   stickers reads as a catalogue of things rather than a table of prices. */
.sticker-tile-art {
    transition: transform .4s cubic-bezier(0.34, 1.4, 0.64, 1);
}
.sticker-tile:hover .sticker-tile-art { transform: scale(1.1) rotate(-4deg); }

/* ── Quantity stepper ─────────────────────────────────────────────────── */
.qty-btn {
    display: flex;
    flex: none;
    align-items: center;
    justify-content: center;
    width: 2.5rem;
    height: 2.5rem;
    border-radius: 0.875rem;
    font-weight: 800;
    color: #6E747E;
    background: #F4F5F7;
    border: 1px solid #E9EAED;
    transition: color .2s ease, background .2s ease, border-color .2s ease;
}
.dark .qty-btn { color: #99A0AB; background: #1D2026; border-color: #262A31; }
.qty-btn:hover {
    color: rgb(var(--brand-rgb));
    border-color: rgb(var(--brand-rgb) / 0.45);
    background: rgb(var(--brand-rgb) / 0.08);
}
.qty-btn:disabled { opacity: 0.4; cursor: not-allowed; }
.qty-btn:disabled:hover { color: #6E747E; background: #F4F5F7; border-color: #E9EAED; }
.dark .qty-btn:disabled:hover { color: #99A0AB; background: #1D2026; border-color: #262A31; }

/* ── On-stream preview ────────────────────────────────────────────────
   Sits on `.overlay-frame`'s checkerboard, the same transparency cue the
   overlay's own preview mode uses, so what this shows reads as "over your
   video" rather than "another card on this page". */
.stream-alert {
    animation: streamAlert 620ms cubic-bezier(0.22, 1, 0.36, 1);
    background: rgb(15 17 20 / 0.86);
    border: 1px solid rgb(255 255 255 / 0.10);
    box-shadow: 0 18px 40px -20px rgb(0 0 0 / 0.75);
    -webkit-backdrop-filter: blur(12px);
    backdrop-filter: blur(12px);
}
@keyframes streamAlert {
    0%   { opacity: 0; transform: translateY(14px) scale(0.94); }
    100% { opacity: 1; transform: none; }
}

/* Re-runs whenever the sticker changes, so a new pick visibly lands. */
.stream-art {
    animation: streamArt 700ms cubic-bezier(0.34, 1.36, 0.5, 1);
}
@keyframes streamArt {
    0%   { transform: scale(0.55) rotate(-12deg); }
    100% { transform: none; }
}

/* ── Recent gift row ──────────────────────────────────────────────────── */
.gift-row {
    transition: border-color .2s ease, background .2s ease;
}
.gift-row:hover {
    border-color: rgb(var(--brand-rgb) / 0.3);
    background: rgb(var(--brand-rgb) / 0.04);
}

@media (prefers-reduced-motion: reduce) {
    .sticker-tile,
    .sticker-tile-art { transition: none; }
    .sticker-tile:hover { transform: none; }
    .sticker-tile:hover .sticker-tile-art { transform: none; }
    .sticker-check,
    .stream-alert,
    .stream-art { animation: none; }
}


/* ── Anonymity switch ─────────────────────────────────────────────────
   Turning this on rewrites the form — the name and email rows leave — so
   it is a mode, not a tickbox, and it gets a switch. The native checkbox
   is still there under `.sr-only`: it carries the value, the label keeps
   toggling it, and the keyboard still lands on it, which is why the focus
   ring below hangs off `:focus-visible` on the input rather than a div. */
.anon-card {
    position: relative;
    display: flex;
    align-items: center;
    gap: 0.75rem;
    cursor: pointer;
    border-radius: 1rem;
    padding: 0.75rem;
    border: 1px solid #E9EAED;
    background: #F4F5F7;
    transition: border-color .25s ease, background .25s ease, box-shadow .25s ease;
}
.dark .anon-card { border-color: #262A31; background: #1D2026; }
.anon-card:hover { border-color: rgb(var(--brand-rgb) / 0.4); }
.anon-card.is-on {
    border-color: rgb(var(--brand-rgb) / 0.5);
    background: rgb(var(--brand-rgb) / 0.07);
    box-shadow: 0 8px 22px -16px rgb(var(--brand-rgb) / 0.9);
}
/* The input precedes the track in the markup, so a plain sibling combinator
   reaches it — no :has() needed, and the ring lands on the switch, which is
   where a switch's focus ring belongs. Keyed to :focus-visible so a mouse
   click does not light it up. */
.anon-card > input:focus-visible ~ .anon-switch {
    box-shadow: 0 0 0 3px rgb(var(--brand-rgb) / 0.28);
}

/* The glyph swaps from a face to a struck-through eye, and turns over as it
   goes, so the change registers even out of the corner of the eye. */
.anon-icon {
    display: flex;
    flex: none;
    align-items: center;
    justify-content: center;
    width: 2.25rem;
    height: 2.25rem;
    border-radius: 0.75rem;
    color: #6E747E;
    background: #FFFFFF;
    border: 1px solid #E9EAED;
    transition: color .25s ease, background .25s ease, border-color .25s ease, transform .45s cubic-bezier(0.34, 1.36, 0.5, 1);
}
.dark .anon-icon { color: #99A0AB; background: #16181D; border-color: #262A31; }
.anon-card.is-on .anon-icon {
    color: #FFFFFF;
    background: rgb(var(--brand-rgb));
    border-color: rgb(var(--brand-rgb));
    transform: rotateY(180deg);
}

/* The track. --dir flips the knob's travel, since in RTL "on" is to the left. */
.anon-switch {
    position: relative;
    flex: none;
    width: 2.75rem;
    height: 1.5rem;
    border-radius: 999px;
    background: #E9EBEF;
    transition: background .25s ease;
}
.dark .anon-switch { background: #22262D; }
.anon-card.is-on .anon-switch { background: rgb(var(--brand-rgb)); }

.anon-knob {
    position: absolute;
    top: 0.1875rem;
    inset-inline-start: 0.1875rem;
    width: 1.125rem;
    height: 1.125rem;
    border-radius: 999px;
    background: #FFFFFF;
    box-shadow: 0 1px 3px rgb(15 23 42 / 0.32);
    transition: transform .42s cubic-bezier(0.34, 1.36, 0.5, 1);
}
.anon-card.is-on .anon-knob {
    transform: translateX(calc(var(--dir) * -1 * 1.25rem));
}

@media (prefers-reduced-motion: reduce) {
    .anon-card,
    .anon-icon,
    .anon-switch,
    .anon-knob { transition: none; }
    /* The flip is decoration; the colour change already carries the state. */
    .anon-card.is-on .anon-icon { transform: none; }
}

/* ── Supporter messages ───────────────────────────────────────────────
   The message is the reason a creator opens this list at all, so it is
   given the weight of quoted speech rather than being tucked under the
   sticker name as another grey line. */
.gift-msg {
    position: relative;
    border-radius: 0.875rem;
    border: 1px solid #E9EAED;
    background: #FFFFFF;
    transition: border-color .25s ease, transform .25s cubic-bezier(0.22, 1, 0.36, 1);
}
.dark .gift-msg { border-color: #262A31; background: #16181D; }

/* A tail toward the name above it, drawn as a rotated corner of the bubble so
   its border and fill can never drift out of step with the box. */
.gift-msg::before {
    content: '';
    position: absolute;
    top: -0.3125rem;
    inset-inline-start: 1.125rem;
    width: 0.5625rem;
    height: 0.5625rem;
    transform: rotate(45deg);
    border-top: 1px solid #E9EAED;
    border-inline-start: 1px solid #E9EAED;
    background: #FFFFFF;
}
.dark .gift-msg::before { border-color: #262A31; background: #16181D; }

.gift-row:hover .gift-msg {
    border-color: rgb(var(--brand-rgb) / 0.4);
    transform: translateY(-1px);
}
.gift-row:hover .gift-msg::before { border-color: rgb(var(--brand-rgb) / 0.4); }

/* The quote glyph sits behind the words, so it reads as texture rather than
   as a character someone typed. */
.gift-quote {
    position: absolute;
    top: 0.375rem;
    inset-inline-end: 0.5rem;
    color: rgb(var(--brand-rgb));
    opacity: 0.14;
    pointer-events: none;
}

@media (prefers-reduced-motion: reduce) {
    .gift-msg { transition: none; }
    .gift-row:hover .gift-msg { transform: none; }
}

/* ── Panel header chips ───────────────────────────────────────────────
   The prototype's treatment: a round chip on the surface colour with a
   hairline ring and a soft shadow. Loose glyphs on the page background
   read as unfinished; these read as controls. */
.hdr-chip {
    position: relative;
    display: flex;
    flex: none;
    align-items: center;
    justify-content: center;
    width: 2.25rem;
    height: 2.25rem;
    border-radius: 999px;
    color: #6E747E;
    background: #FFFFFF;
    box-shadow: 0 0 0 1px #E9EAED, 0 1px 2px rgb(15 23 42 / 0.06);
    transition: color .2s ease, box-shadow .2s ease, transform .15s ease;
}
.dark .hdr-chip {
    color: #99A0AB;
    background: #16181D;
    box-shadow: 0 0 0 1px #262A31, 0 1px 2px rgb(0 0 0 / 0.4);
}
.hdr-chip:hover { color: #0F1114; }
.dark .hdr-chip:hover { color: #F3F5F7; }
.hdr-chip:active { transform: scale(0.9); }

/* The avatar is the one chip that is filled, because it is the only one
   that stands for a person rather than an action. */
.hdr-avatar {
    position: relative;
    display: flex;
    flex: none;
    align-items: center;
    justify-content: center;
    overflow: hidden;
    width: 2.25rem;
    height: 2.25rem;
    border-radius: 999px;
    background: rgb(var(--brand-rgb));
    color: #FFFFFF;
    font-size: 0.75rem;
    font-weight: 800;
    box-shadow: 0 0 0 2px #F4F5F7, 0 0 0 4px rgb(var(--brand-rgb));
    transition: box-shadow .2s ease, transform .15s ease;
}
.dark .hdr-avatar { box-shadow: 0 0 0 2px #0D0F12, 0 0 0 4px rgb(var(--brand-rgb)); }
.hdr-avatar:hover { box-shadow: 0 0 0 2px #F4F5F7, 0 0 0 4px rgb(var(--brand-dark-rgb)); }
.dark .hdr-avatar:hover { box-shadow: 0 0 0 2px #0D0F12, 0 0 0 4px rgb(var(--brand-dark-rgb)); }
.hdr-avatar:active { transform: scale(0.95); }

@media (min-width: 640px) {
    .hdr-chip,
    .hdr-avatar { width: 2.5rem; height: 2.5rem; }
}

@media (prefers-reduced-motion: reduce) {
    .hdr-chip,
    .hdr-avatar { transition: none; }
    .hdr-chip:active,
    .hdr-avatar:active { transform: none; }
}

/* ── Desktop icon rail ────────────────────────────────────────────────
   One row style for every item in the rail, including the two utility
   links under the divider, so the whole column keeps one rhythm. */
.rail-link {
    position: relative;
    display: flex;
    flex: none;
    align-items: center;
    justify-content: center;
    width: 2.25rem;
    height: 2.25rem;
    border-radius: 0.75rem;
    color: #6E747E;
    transition: color .18s ease, background .18s ease;
}
.dark .rail-link { color: #99A0AB; }
.rail-link:hover { color: #0F1114; background: #F4F5F7; }
.dark .rail-link:hover { color: #F3F5F7; background: #22262D; }

/* Active: a tinted tile plus a marker on the leading edge. The marker is what
   survives at a glance — colour alone is a weak signal at this size. */
.rail-link.is-on {
    color: rgb(var(--brand-rgb));
    background: rgb(var(--brand-rgb) / 0.1);
}
.rail-link.is-on:hover { background: rgb(var(--brand-rgb) / 0.14); }
.rail-link.is-on::before {
    content: '';
    position: absolute;
    inset-block: 0.5rem;
    inset-inline-start: -0.5rem;
    width: 3px;
    border-radius: 999px;
    background: rgb(var(--brand-rgb));
}

.rail-link.is-danger:hover { color: #EF4B3F; background: #FDECEA; }
.dark .rail-link.is-danger:hover { color: #EF4B3F; background: #2B1715; }

/* Section break. Short and centred rather than full width — it should read as
   a breath between runs of icons, not as a line ruled across the column. */
.rail-rule {
    width: 1.25rem;
    height: 1px;
    margin-block: 0.25rem;
    border-radius: 999px;
    background: #E9EAED;
}
.dark .rail-rule { background: #262A31; }

/* The count of things waiting. Ringed in the island's own colour so it cuts
   cleanly out of the icon it overlaps. */
.rail-badge {
    position: absolute;
    top: -0.125rem;
    inset-inline-end: -0.125rem;
    display: flex;
    align-items: center;
    justify-content: center;
    min-width: 1rem;
    height: 1rem;
    padding-inline: 0.25rem;
    border-radius: 999px;
    background: #EF4B3F;
    color: #FFFFFF;
    font-size: 0.5625rem;
    font-weight: 800;
    font-variant-numeric: tabular-nums;
    box-shadow: 0 0 0 2px #FFFFFF;
}
.dark .rail-badge { box-shadow: 0 0 0 2px #16181D; }

@media (prefers-reduced-motion: reduce) {
    .rail-link { transition: none; }
}

/* ── Panel language switcher ──────────────────────────────────────────
   Sits in the header chip row, so it borrows the chip's surface, ring and
   press. It is wider than the round chips because it carries a flag and,
   from `sm` up, the language's own name. */
.lang-chip {
    display: flex;
    flex: none;
    align-items: center;
    gap: 0.5rem;
    height: 2.25rem;
    padding-inline: 0.625rem;
    border-radius: 999px;
    font-size: 0.75rem;
    font-weight: 700;
    color: #6E747E;
    background: #FFFFFF;
    box-shadow: 0 0 0 1px #E9EAED, 0 1px 2px rgb(15 23 42 / 0.06);
    transition: color .2s ease, box-shadow .2s ease, transform .15s ease;
}
.dark .lang-chip {
    color: #99A0AB;
    background: #16181D;
    box-shadow: 0 0 0 1px #262A31, 0 1px 2px rgb(0 0 0 / 0.4);
}
.lang-chip:hover { color: #0F1114; }
.dark .lang-chip:hover { color: #F3F5F7; }
.lang-chip:active { transform: scale(0.95); }

.lang-option {
    display: flex;
    align-items: center;
    gap: 0.625rem;
    border-radius: 0.75rem;
    padding: 0.5rem 0.75rem;
    font-size: 0.75rem;
    font-weight: 700;
    transition: background .18s ease, color .18s ease;
}
.lang-option:hover { background: #F4F5F7; }
.dark .lang-option:hover { background: #22262D; }
.lang-option.is-on { color: rgb(var(--brand-rgb)); }

@media (min-width: 640px) {
    .lang-chip { height: 2.5rem; padding-inline: 0.75rem; }
}

@media (prefers-reduced-motion: reduce) {
    .lang-chip { transition: none; }
    .lang-chip:active { transform: none; }
}

/* ── Mobile navigation rows ───────────────────────────────────────────
   Full-width and 48px tall: this is the one place the navigation has
   room to be comfortable, so it takes it. */
.m-nav {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    min-height: 3rem;
    border-radius: 1rem;
    padding-inline: 0.75rem;
    font-size: 0.875rem;
    font-weight: 700;
    color: #0F1114;
    transition: background .18s ease, color .18s ease, transform .15s ease;
}
.dark .m-nav { color: #F3F5F7; }
.m-nav:active { transform: scale(0.985); }

.m-nav-icon {
    display: flex;
    flex: none;
    align-items: center;
    justify-content: center;
    width: 2.25rem;
    height: 2.25rem;
    border-radius: 0.75rem;
    color: #6E747E;
    background: #FFFFFF;
    box-shadow: inset 0 0 0 1px #E9EAED;
    transition: color .18s ease, background .18s ease, box-shadow .18s ease;
}
.dark .m-nav-icon { color: #99A0AB; background: #16181D; box-shadow: inset 0 0 0 1px #262A31; }

.m-nav.is-on { color: rgb(var(--brand-rgb)); background: rgb(var(--brand-rgb) / 0.1); }
.m-nav.is-on .m-nav-icon {
    color: #FFFFFF;
    background: rgb(var(--brand-rgb));
    box-shadow: none;
}

.m-nav.is-danger { color: #EF4B3F; }
.m-nav.is-danger .m-nav-icon { color: #EF4B3F; }
.m-nav.is-danger:active { background: #FDECEA; }
.dark .m-nav.is-danger:active { background: #2B1715; }

@media (prefers-reduced-motion: reduce) {
    .m-nav,
    .m-nav-icon { transition: none; }
    .m-nav:active { transform: none; }
}

/* The icon tile picks up a ring in its own tone, so the accent reads on the
   tile itself and not only in the glow behind it. */
.stat-icon { box-shadow: 0 0 0 1px rgb(var(--card-accent) / 0.18); }
.stat-card:hover .stat-icon { box-shadow: 0 0 0 1px rgb(var(--card-accent) / 0.34); }

/* ── Filter chips ─────────────────────────────────────────────────────
   A native <select> cannot be styled to match the toolbar around it and
   renders as a different application in dark mode, so these replace it. */
.filter-chip {
    display: flex;
    align-items: center;
    gap: 0.4375rem;
    height: 2.5rem;
    padding-inline: 0.75rem;
    border-radius: 0.875rem;
    font-size: 0.75rem;
    color: #0F1114;
    background: #FFFFFF;
    border: 1px solid #E9EAED;
    transition: border-color .2s ease, background .2s ease, color .2s ease;
}
.dark .filter-chip { color: #F3F5F7; background: #16181D; border-color: #262A31; }
.filter-chip:hover { border-color: rgb(var(--brand-rgb) / 0.4); }

/* Narrowed by this filter — worth seeing at a glance, since a filter you
   forgot you set is the usual reason a table looks empty. */
.filter-chip.is-on {
    color: rgb(var(--brand-rgb));
    border-color: rgb(var(--brand-rgb) / 0.5);
    background: rgb(var(--brand-rgb) / 0.08);
}
.filter-chip.is-on .text-muted { color: rgb(var(--brand-rgb) / 0.7); }

.filter-menu {
    overflow: hidden;
    border-radius: 1rem;
    padding: 0.25rem;
    background: #FFFFFF;
    border: 1px solid #E9EAED;
    box-shadow: 0 18px 44px rgb(16 24 40 / 0.18);
}
.dark .filter-menu { background: #16181D; border-color: #262A31; box-shadow: 0 18px 44px rgb(0 0 0 / 0.5); }

.filter-option {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    width: 100%;
    border-radius: 0.625rem;
    padding: 0.5rem 0.625rem;
    font-size: 0.75rem;
    font-weight: 700;
    white-space: nowrap;
    color: #0F1114;
    transition: background .16s ease, color .16s ease;
}
.dark .filter-option { color: #F3F5F7; }
.filter-option:hover { background: #F4F5F7; }
.dark .filter-option:hover { background: #22262D; }
.filter-option.is-on { color: rgb(var(--brand-rgb)); }

@media (prefers-reduced-motion: reduce) {
    .filter-chip,
    .filter-option { transition: none; }
}

/* Trigger for `select-menu` — matches `.field` so a styled dropdown and a text
   input sit on the same line without looking like different controls. */
.select-trigger {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    width: 100%;
    height: 2.625rem;
    padding-inline: 0.875rem;
    border-radius: 0.875rem;
    font-size: 0.8125rem;
    font-weight: 600;
    color: #0F1114;
    background: #FFFFFF;
    border: 1px solid #E9EAED;
    transition: border-color .2s ease, box-shadow .2s ease;
}
.dark .select-trigger { color: #F3F5F7; background: #16181D; border-color: #262A31; }
.select-trigger:hover { border-color: rgb(var(--brand-rgb) / 0.4); }
.select-trigger:focus-visible {
    outline: none;
    border-color: rgb(var(--brand-rgb));
    box-shadow: 0 0 0 3px rgb(var(--brand-rgb) / 0.16);
}

@media (prefers-reduced-motion: reduce) {
    .select-trigger { transition: none; }
}

/* ── Confirmation dialog ──────────────────────────────────────────────
   The tone's wash sits behind the icon at the head of the card, so the
   question reads before the words do. */
.confirm-card { box-shadow: 0 28px 70px rgb(16 24 40 / 0.32); }
.dark .confirm-card { box-shadow: 0 28px 70px rgb(0 0 0 / 0.6); }

.confirm-glow {
    position: absolute;
    inset-inline: 0;
    top: 0;
    height: 9rem;
    pointer-events: none;
}
.confirm-glow.is-danger { background: radial-gradient(50% 60% at 50% 0%, rgb(239 75 63 / 0.16), transparent 70%); }
.confirm-glow.is-ok     { background: radial-gradient(50% 60% at 50% 0%, rgb(36 164 85 / 0.16), transparent 70%); }
.confirm-glow.is-brand  { background: radial-gradient(50% 60% at 50% 0%, rgb(var(--brand-rgb) / 0.16), transparent 70%); }

.confirm-icon {
    display: flex;
    flex: none;
    align-items: center;
    justify-content: center;
    width: 3.5rem;
    height: 3.5rem;
    border-radius: 1.25rem;
    animation: confirmIcon 420ms cubic-bezier(0.34, 1.36, 0.5, 1);
}
@keyframes confirmIcon {
    0%   { transform: scale(0.6); opacity: 0; }
    100% { transform: none; opacity: 1; }
}

@media (prefers-reduced-motion: reduce) {
    .confirm-icon { animation: none; }
}

/* ── Settings ─────────────────────────────────────────────────────────
   A settings page is a list of decisions, so each one gets a row: what
   it does on the reading side, the control on the other. Stacking a
   label above every input made five sections read as one long form. */
.set-nav-item {
    display: flex;
    align-items: center;
    gap: 0.625rem;
    width: 100%;
    border-radius: 0.875rem;
    padding: 0.625rem 0.75rem;
    font-size: 0.8125rem;
    font-weight: 700;
    color: #6E747E;
    transition: color .18s ease, background .18s ease;
}
.dark .set-nav-item { color: #99A0AB; }
.set-nav-item:hover { color: #0F1114; background: #F4F5F7; }
.dark .set-nav-item:hover { color: #F3F5F7; background: #22262D; }
.set-nav-item.is-on { color: rgb(var(--brand-rgb)); background: rgb(var(--brand-rgb) / 0.1); }

.set-nav-icon {
    display: flex;
    flex: none;
    align-items: center;
    justify-content: center;
    width: 1.75rem;
    height: 1.75rem;
    border-radius: 0.5rem;
    background: #FFFFFF;
    box-shadow: inset 0 0 0 1px #E9EAED;
}
.dark .set-nav-icon { background: #16181D; box-shadow: inset 0 0 0 1px #262A31; }
.set-nav-item.is-on .set-nav-icon {
    color: #FFFFFF;
    background: rgb(var(--brand-rgb));
    box-shadow: none;
}

/* One decision. Wraps to a stack when there is not room for two columns. */
.set-row {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem 1rem;
    padding: 0.875rem 0;
    border-top: 1px solid #EFF0F2;
}
.dark .set-row { border-color: #23262C; }
.set-row:first-child { border-top: 0; }
.set-row-text { min-width: 12rem; flex: 1 1 12rem; }
.set-row-control { flex: 0 0 auto; min-width: 0; }

/* ── Switch ───────────────────────────────────────────────────────────
   Generalised from the gift composer's anonymity toggle, so a boolean
   setting reads the same wherever it appears. The native checkbox stays
   under `.sr-only` and does the submitting. */
.switch {
    position: relative;
    flex: none;
    width: 2.75rem;
    height: 1.5rem;
    border-radius: 999px;
    background: #E9EBEF;
    transition: background .25s ease;
}
.dark .switch { background: #22262D; }
.switch-knob {
    position: absolute;
    top: 0.1875rem;
    inset-inline-start: 0.1875rem;
    width: 1.125rem;
    height: 1.125rem;
    border-radius: 999px;
    background: #FFFFFF;
    box-shadow: 0 1px 3px rgb(15 23 42 / 0.32);
    transition: transform .42s cubic-bezier(0.34, 1.36, 0.5, 1);
}
/* --dir flips the travel: "on" is to the left in RTL. */
.switch-wrap input:checked ~ .switch { background: rgb(var(--brand-rgb)); }
.switch-wrap input:checked ~ .switch .switch-knob { transform: translateX(calc(var(--dir) * -1 * 1.25rem)); }
.switch-wrap input:focus-visible ~ .switch { box-shadow: 0 0 0 3px rgb(var(--brand-rgb) / 0.28); }

@media (prefers-reduced-motion: reduce) {
    .set-nav-item, .switch, .switch-knob { transition: none; }
}
