/* ============================================================
   Pawtalk - tokens and shared furniture
   ============================================================ */

:root {
  /* ----------------------------------------------------------
     Read off the reference render, rather than invented:

       fur          #e5813a      hair highlight  #f0a165
       ear / shade  #c96a2a      boot brown      #2e231e
       chest cream  #f2e8d7      cardigan        #e8e0ce
       skirt        #8ca0b8      blush           #e9a0a8

     Orange remains the PAW identity, while reading surfaces use a neutral
     near-black ramp. Brown behind warm grey reduced character separation
     for low-vision and dyslexic readers, especially at small sizes.
     ---------------------------------------------------------- */

  --bg-00: #07080a;   /* server rail - sits behind everything else */
  --bg-0:  #0c0e11;
  --bg-1:  #111419;
  --bg-2:  #181c22;
  --bg-3:  #202630;
  --bg-4:  #29313b;

  /* Reusable translucent surfaces. They keep the interface layered without
     introducing cold grey cards into the fox palette. */
  --surface:        rgba(24, 28, 34, 0.94);
  --surface-raised: rgba(32, 38, 48, 0.96);
  --surface-glass:  rgba(17, 20, 25, 0.84);
  --surface-hover:  rgba(255, 255, 255, 0.065);

  /* Text stays neutral and high-contrast; cream is decorative, not body ink. */
  --fg:      #ffffff;
  --fg-mid:  #eef2f7;
  --fg-dim:  #c8d0da;

  /* Accent - the fur */
  --accent:      #e5813a;
  --accent-soft: #ffad70;
  --accent-deep: #c95f24;
  --accent-ink:  #24130a;
  --accent-rgb: 229, 129, 58;

  /* A wash of the fur, for selected rows and highlights */
  --accent-wash: rgba(var(--accent-rgb), 0.15);
  --accent-edge: rgba(var(--accent-rgb), 0.44);

  /* The skirt, for quiet informational bits */
  --cool:  #8ca0b8;
  /* The blush */
  --blush: #e9a0a8;

  /* Presence + state */
  --ok:    #6cc98b;
  --warn:  #f0a165;
  --busy:  #e07a6a;
  --off:   #7d6a5c;

  /* Destructive actions, errors, and the mention badge. Nine rules across
     the stylesheets already asked for this and were getting nothing back,
     so a red badge has never actually been red. Kept clearly apart from
     --accent, which is orange, and from --busy, which means a person. */
  --danger: #d64b4b;

  --line:   rgba(255, 255, 255, 0.14);
  --line-2: rgba(255, 255, 255, 0.24);

  --radius:    13px;
  --radius-sm: 10px;
  --radius-lg: 20px;
  --radius-xl: 28px;

  --shadow:    0 24px 70px rgba(0, 0, 0, 0.50), 0 2px 10px rgba(0, 0, 0, 0.24);
  --shadow-sm: 0 10px 30px rgba(0, 0, 0, 0.30);
  --shadow-glow: 0 12px 34px rgba(var(--accent-rgb), 0.22);

  --font: "Segoe UI Variable Text", "Segoe UI", Inter, -apple-system, BlinkMacSystemFont, Roboto, Arial, sans-serif;
  --mono: "Cascadia Mono", Consolas, "SF Mono", Menlo, monospace;

  --srail-w:  72px;
  --rail-w:   272px;
  --member-w: 264px;
  --head-h:   64px;

  /* Compatibility names used by a few older components. */
  --text: var(--fg);
  --bg: var(--bg-0);
  --green: var(--ok);
}

* { box-sizing: border-box; }

/* The UA rule for [hidden] is only `display: none`, so any author rule that
   sets display - and most of the components below do - silently defeats it.
   Anything toggled with the hidden attribute needs this to hold. */
[hidden] { display: none !important; }

html, body {
  height: 100%;
  margin: 0;
}

body {
  background:
    radial-gradient(1000px 650px at 4% -12%, rgba(var(--accent-rgb), 0.13), transparent 62%),
    radial-gradient(900px 560px at 108% 108%, rgba(var(--accent-rgb), 0.08), transparent 64%),
    var(--bg-0);
  color: var(--fg);
  font-family: var(--font);
  font-size: 15px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

::selection { background: rgba(var(--accent-rgb), 0.34); color: var(--fg); }

:focus-visible {
  outline: 2px solid var(--accent-soft);
  outline-offset: 3px;
}

a {
  color: var(--accent-soft);
  text-decoration: none;
}
a:hover { text-decoration: underline; }

::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb {
  background: var(--bg-4);
  border-radius: 10px;
  border: 2px solid transparent;
  background-clip: content-box;
}
::-webkit-scrollbar-thumb:hover { background-color: #4c3a31; background-clip: content-box; }

/* ── Buttons ──────────────────────────────────────────────── */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.45rem;
  min-height: 40px;
  padding: 0.58rem 1.1rem;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--bg-3);
  color: var(--fg);
  font: inherit;
  font-weight: 600;
  font-size: 0.9rem;
  cursor: pointer;
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.035);
  transition: background 0.16s, border-color 0.16s, color 0.16s, box-shadow 0.16s, transform 0.12s;
}
.btn:hover  { border-color: var(--line-2); background: var(--bg-4); transform: translateY(-1px); }
.btn:active { transform: translateY(0); }
.btn:disabled {
  opacity: 1;
  border-color: var(--line);
  background: var(--bg-2);
  color: var(--fg-dim);
  cursor: not-allowed;
  box-shadow: none;
}

.btn-primary {
  border-color: rgba(255, 173, 112, 0.24);
  background: linear-gradient(135deg, var(--accent-soft), var(--accent));
  color: var(--accent-ink);
  box-shadow: 0 10px 24px rgba(201, 95, 36, 0.20), inset 0 1px 0 rgba(255,255,255,0.24);
}
.btn-primary:hover { border-color: var(--accent-edge); background: linear-gradient(135deg, var(--accent-soft), var(--accent)); box-shadow: var(--shadow-glow); }

.btn-ghost {
  background: transparent;
  border-color: var(--line-2);
  color: var(--fg-mid);
}
.btn-ghost:hover { background: var(--bg-2); color: var(--fg); }

.btn-danger { background: var(--busy); color: #1e0907; }
.btn-danger:hover { background: #e58878; color: #1e0907; }

.btn-block { width: 100%; }
.btn-sm { min-height: 34px; padding: 0.38rem 0.78rem; font-size: 0.83rem; }

/* ── Forms ────────────────────────────────────────────────── */

.field { margin-bottom: 1rem; }

.label {
  display: block;
  margin-bottom: 0.35rem;
  font-size: 0.74rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--fg-dim);
}

.input,
.textarea,
.select {
  width: 100%;
  min-height: 44px;
  padding: 0.68rem 0.82rem;
  background: rgba(7, 9, 12, 0.88);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  color: var(--fg);
  font: inherit;
  font-size: 0.94rem;
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.018);
  transition: border-color 0.16s, background 0.16s, box-shadow 0.16s;
}
.input:focus,
.textarea:focus,
.select:focus {
  outline: none;
  border-color: var(--accent);
  background: rgba(12, 14, 17, 0.98);
  box-shadow: 0 0 0 4px rgba(var(--accent-rgb), 0.15), inset 0 1px 0 rgba(255,255,255,0.025);
}
.input::placeholder, .textarea::placeholder { color: var(--fg-dim); }
.input:disabled,
.textarea:disabled,
.select:disabled {
  opacity: 1;
  border-color: var(--line);
  background: var(--bg-1);
  color: var(--fg-dim);
  cursor: not-allowed;
}

.textarea { resize: vertical; min-height: 88px; }

.hint {
  margin-top: 0.3rem;
  font-size: 0.79rem;
  color: var(--fg-dim);
}

/* ── Notices ──────────────────────────────────────────────── */

.notice {
  padding: 0.65rem 0.85rem;
  border-radius: var(--radius-sm);
  border-left: 3px solid var(--accent);
  background: var(--bg-2);
  font-size: 0.88rem;
  margin-bottom: 1rem;
}
.notice-error { border-left-color: var(--busy); }
.notice-ok    { border-left-color: var(--ok); }

/* ── Avatars ──────────────────────────────────────────────── */

.avatar {
  position: relative;
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 38px;
  height: 38px;
  border-radius: 50%;
  overflow: hidden;
  background: var(--bg-3);
  color: #fff;
  font-weight: 700;
  font-size: 0.9rem;
  text-transform: uppercase;
  user-select: none;
}
.avatar img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.avatar-sm { width: 28px; height: 28px; font-size: 0.72rem; }
.avatar-lg { width: 72px; height: 72px; font-size: 1.6rem; }

/* Presence pip rides on a wrapper, not the avatar, so it is not clipped
   by the circular overflow. */
.av-wrap { position: relative; flex: none; display: inline-block; }
.av-wrap .pip {
  position: absolute;
  right: -1px;
  bottom: -1px;
  width: 12px;
  height: 12px;
  border-radius: 50%;
  border: 2.5px solid var(--bg-1);
  background: var(--off);
}
.pip.is-online { background: var(--ok); }
.pip.is-idle   { background: var(--warn); }
.pip.is-busy   { background: var(--busy); }

/* ── Modal ────────────────────────────────────────────────── */

.modal {
  position: fixed;
  inset: 0;
  z-index: 90;
  display: none;
  align-items: center;
  justify-content: center;
  padding: 1.5rem;
  background: rgba(8, 5, 4, 0.72);
  backdrop-filter: blur(14px) saturate(0.85);
}
.modal.open { display: flex; }

.modal-box {
  width: 100%;
  max-width: 460px;
  background:
    radial-gradient(circle at 10% 0, rgba(229,129,58,0.08), transparent 220px),
    var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow);
  backdrop-filter: blur(22px);
  overflow: hidden;
}
.modal-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0.95rem 1.1rem;
  border-bottom: 1px solid var(--line);
  font-weight: 700;
}
.modal-body { padding: 1.1rem; }
.modal-foot {
  display: flex;
  justify-content: flex-end;
  gap: 0.55rem;
  padding: 0.85rem 1.1rem;
  border-top: 1px solid var(--line);
  background: var(--bg-1);
}
.modal-x {
  background: none;
  border: 0;
  color: var(--fg-dim);
  font-size: 1.4rem;
  line-height: 1;
  cursor: pointer;
  padding: 0 0.2rem;
}
.modal-x:hover { color: var(--fg); }

/* One recognisable, non-browser safety prompt for outside destinations and
   executable or archive downloads. The page keeps the original action in
   place until the user explicitly chooses to continue. */
.safety-modal { z-index: 120; }
.safety-modal-box { max-width: 500px; }
.safety-modal-head { display: inline-flex; align-items: center; gap: .45rem; color: var(--fg-mid); font-size: .78rem; font-weight: 800; letter-spacing: .055em; text-transform: uppercase; }
.safety-modal-dot { width: .48rem; height: .48rem; border-radius: 50%; background: var(--warn); box-shadow: 0 0 0 4px color-mix(in srgb, var(--warn) 14%, transparent); }
.safety-modal-body { padding: 1.55rem 1.55rem 1.35rem; text-align: center; }
.safety-modal-icon { position: relative; display: grid; place-items: center; width: 58px; height: 58px; margin: 0 auto 1rem; border-radius: 1rem; background: color-mix(in srgb, var(--warn) 14%, var(--bg-3)); color: var(--warn); }
.safety-modal-icon span { display: grid; place-items: center; width: 28px; height: 28px; }.safety-modal-icon [data-safety-icon="download"] { display: none; }.safety-modal[data-kind="download"] .safety-modal-icon [data-safety-icon="external"] { display: none; }.safety-modal[data-kind="download"] .safety-modal-icon [data-safety-icon="download"] { display: grid; }.safety-modal-icon .app-icon { width:100%; height:100%; object-fit:contain; }.safety-modal-icon .app-icon[data-icon-animated][data-icon-playing] { object-fit:fill; transform:scale(var(--app-icon-hover-scale,1)); transform-origin:center; }
.safety-modal-kicker { margin: 0 0 .38rem; color: var(--warn); font-size: .66rem; font-weight: 850; letter-spacing: .095em; }.safety-modal-body h2 { max-width: 370px; margin: 0 auto .65rem; color: var(--fg); font-size: 1.45rem; letter-spacing: -.035em; line-height: 1.1; }.safety-modal-body > p:not(.safety-modal-kicker):not(.safety-modal-tip) { max-width: 390px; margin: 0 auto; color: var(--fg-mid); font-size: .9rem; line-height: 1.58; }.safety-modal-destination { display: block; max-width: 100%; margin: 1rem 0 .7rem; padding: .58rem .68rem; overflow: hidden; border: 1px solid var(--line); border-radius: .58rem; background: var(--bg-1); color: var(--accent-soft); font-family: var(--mono); font-size: .72rem; text-overflow: ellipsis; white-space: nowrap; }.safety-modal-tip { margin: 0; color: var(--fg-dim); font-size: .74rem; line-height: 1.45; }.safety-modal-actions { justify-content: center; }.safety-modal-actions .btn { min-width: 132px; }

/* Long forms must remain complete on small screens.  The shell becomes a
   bottom sheet while its body scrolls, leaving the header and actions in
   reach instead of letting the page itself overflow behind the modal. */
@media (max-width: 700px) {
  .modal {
    align-items: flex-end;
    padding: 0.5rem;
    padding-bottom: max(0.5rem, env(safe-area-inset-bottom));
  }
  .modal-box {
    max-width: none;
    max-height: calc(100dvh - 1rem);
    display: flex;
    flex-direction: column;
    border-radius: 1.1rem 1.1rem 0.8rem 0.8rem;
  }
  .modal-head,
  .modal-foot { flex: none; }
  .modal-body {
    min-height: 0;
    overflow-y: auto;
    overscroll-behavior: contain;
  }
  .modal-foot {
    flex-wrap: wrap;
    padding-bottom: max(0.85rem, env(safe-area-inset-bottom));
  }
  .modal-foot .btn { flex: 1 1 9rem; min-height: 2.65rem; }
  .safety-modal-body { padding: 1.35rem 1.1rem 1.2rem; }
  .safety-modal-actions .btn { min-width: 0; }
}

/* ── Utility ──────────────────────────────────────────────── */

.muted { color: var(--fg-dim); }
.row   { display: flex; align-items: center; gap: 0.6rem; }
.spacer { flex: 1; }
.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}

/* ── Loading ───────────────────────────────────────────────
   Two moods on one veil: a lively picture while you wait, and a sleeping
   one when the server cannot be reached. The paw mark and the dots are
   drawn inline, so a missing artwork file leaves a plainer loader rather
   than a broken one - and the offline screen never needs the network to
   draw itself. */

.loader-veil {
  position: fixed;
  inset: 0;
  z-index: 300;
  display: grid;
  place-items: center;
  padding: 1.5rem;
  background: var(--bg-0);
}
.loader-veil[hidden] { display: none; }

/* Fading out rather than vanishing, so a fast load does not flash. */
.loader-veil.is-going {
  animation: loaderOut 0.28s ease-in forwards;
  pointer-events: none;
}
@keyframes loaderOut { to { opacity: 0; visibility: hidden; } }

.loader-card {
  display: grid;
  justify-items: center;
  gap: 0.6rem;
  text-align: center;
}

.loader-stage {
  position: relative;
  display: grid;
  place-items: center;
  width: min(240px, 62vw);
  aspect-ratio: 1;
}

/* The mark sits behind her and turns. It is the only thing that rotates -
   spinning the character herself was what looked broken. */
.loader-mark {
  position: absolute;
  width: 58%;
  opacity: 0.16;
}
.mark-spin {
  transform-box: view-box;
  transform-origin: 30px 30px;
  animation: markRound 6s linear infinite;
}
@keyframes markRound { to { transform: rotate(360deg); } }

.loader-figure {
  position: relative;
  width: 100%;
  height: 100%;
  object-fit: contain;
  /* Artwork, not a decoration to be dragged off the page. */
  -webkit-user-drag: none;
  user-select: none;
}

/* One veil, two pictures - whichever the state calls for. */
.loader-resting { display: none; }
.loader-veil.is-resting .loader-busy { display: none; }
.loader-veil.is-resting .loader-resting { display: block; }
.loader-veil.is-resting .loader-mark { display: none; }

/* Only a still picture gets a bob from us. An animated file already has
   its own motion, and layering ours on top turns it into a wobble. */
.loader-busy.is-still    { animation: loaderBob 2.6s ease-in-out infinite; }
.loader-resting.is-still { animation: loaderBreathe 4.6s ease-in-out infinite; }

@keyframes loaderBob {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(-7px); }
}
@keyframes loaderBreathe {
  0%, 100% { transform: scale(1); }
  50%      { transform: scale(1.035); }
}

.loader-line {
  margin: 0;
  max-width: 34ch;
  color: var(--fg-mid);
  font-size: 0.92rem;
  line-height: 1.5;
}

/* ── Paw dots ─────────────────────────────────────────────── */

.loader-paws { display: flex; gap: 0.45rem; }
.loader-paws i {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--accent);
  opacity: 0.25;
  animation: pawStep 1.35s ease-in-out infinite;
}
.loader-paws i:nth-child(2) { animation-delay: 0.18s; }
.loader-paws i:nth-child(3) { animation-delay: 0.36s; }
@keyframes pawStep {
  0%, 100% { opacity: 0.22; transform: translateY(0) scale(1); }
  40%      { opacity: 1;    transform: translateY(-4px) scale(1.25); }
}

.loader-veil.is-resting .loader-paws { display: none; }

/* ── Server identity tags ───────────────────────────────────
   Shared by chat and the server-tag studio. Color and treatment are
   controlled preset classes; user content never becomes raw CSS. */
.server-member-tag {
  --tag-main: #e5813a;
  --tag-light: #ffbe8c;
  --tag-rgb: 229, 129, 58;
  --tag-ink: #24130a;
  display: inline-flex;
  align-items: center;
  gap: 0.22rem;
  flex: none;
  margin-left: 0.35rem;
  padding: 0.16rem 0.36rem;
  border: 1px solid rgba(var(--tag-rgb), 0.38);
  border-radius: 6px;
  background: rgba(var(--tag-rgb), 0.15);
  color: var(--tag-light);
  font-size: 0.58rem;
  font-weight: 850;
  letter-spacing: 0.065em;
  line-height: 1;
  text-transform: uppercase;
  vertical-align: middle;
}
.server-member-tag-emoji {
  font-family: "Segoe UI Emoji", "Apple Color Emoji", sans-serif;
  font-size: 0.72rem;
  font-weight: 400;
  letter-spacing: 0;
  line-height: 1;
  text-transform: none;
}
.server-member-tag-emoji img {
  display: block;
  width: 0.86rem;
  height: 0.86rem;
  object-fit: contain;
}
.server-member-tag-text { line-height: 1; }

.server-tag-color-ember  { --tag-main:#e5813a; --tag-light:#ffbe8c; --tag-rgb:229,129,58;  --tag-ink:#24130a; }
.server-tag-color-gold   { --tag-main:#e5ac3a; --tag-light:#ffd783; --tag-rgb:229,172,58;  --tag-ink:#251a05; }
.server-tag-color-berry  { --tag-main:#d85b83; --tag-light:#ff9cbd; --tag-rgb:216,91,131;  --tag-ink:#290912; }
.server-tag-color-sky    { --tag-main:#559bcc; --tag-light:#a8dcff; --tag-rgb:85,155,204;  --tag-ink:#071b2b; }
.server-tag-color-mint   { --tag-main:#58b98c; --tag-light:#a5ebc9; --tag-rgb:88,185,140;  --tag-ink:#08261a; }
.server-tag-color-violet { --tag-main:#956fd0; --tag-light:#d1b5ff; --tag-rgb:149,111,208; --tag-ink:#190d2b; }
.server-tag-color-custom { --tag-main:#e5813a; --tag-light:#ffbe8c; --tag-rgb:229,129,58; --tag-ink:#24130a; }

.server-tag-style-soft {
  border-color: rgba(var(--tag-rgb), 0.38);
  background: rgba(var(--tag-rgb), 0.15);
  color: var(--tag-light);
}
.server-tag-style-outline {
  border-color: rgba(var(--tag-rgb), 0.68);
  background: transparent;
  color: var(--tag-light);
}
.server-tag-style-solid {
  border-color: rgba(255,255,255,0.18);
  background: var(--tag-main);
  color: var(--tag-ink);
  box-shadow: inset 0 1px rgba(255,255,255,0.24), inset 0 -1px rgba(0,0,0,0.13);
}
.server-tag-style-glow {
  border-color: rgba(var(--tag-rgb), 0.62);
  background: linear-gradient(135deg, rgba(var(--tag-rgb), 0.32), rgba(var(--tag-rgb), 0.13));
  color: var(--tag-light);
  box-shadow: 0 0 13px rgba(var(--tag-rgb), 0.28), inset 0 1px rgba(255,255,255,0.08);
  text-shadow: 0 0 8px rgba(var(--tag-rgb), 0.42);
}
.loader-retry { margin-top: 0.4rem; }

/* Stillness for anyone who asked for it: the pictures stay, the motion
   goes, and the dots hold at a readable opacity rather than vanishing. */
@media (prefers-reduced-motion: reduce) {
  .mark-spin, .loader-busy, .loader-resting,
  .loader-busy.is-still, .loader-resting.is-still,
  .loader-paws i, .loader-veil.is-going {
    animation: none;
  }
  .loader-paws i { opacity: 0.6; }
  .loader-veil.is-going { display: none; }
}

/* Honour the operating-system contrast preference without replacing the
   PAW accent. Text becomes pure white and boundaries stop relying on tint. */
@media (prefers-contrast: more) {
  :root {
    --fg: #ffffff;
    --fg-mid: #ffffff;
    --fg-dim: #e4e9ef;
    --line: rgba(255,255,255,0.28);
    --line-2: rgba(255,255,255,0.46);
    --accent-edge: rgba(var(--accent-rgb),0.72);
  }
}
