/* ============================================================
   ui.css — design foundation + shared components
   Loaded AFTER app.css on every page. app.css stays the base;
   this file only adds tokens, global fixes and reusable components.
   ============================================================ */

/* ---------- 1. Tokens ---------- */
:root {
  /* readable secondary text (was #5C7773 ≈ 2.9:1, now ≈ 5.3:1 on --bg-primary) */
  --hint-color: #5C7773;

  /* type scale — never go below --fs-12 for readable text */
  --fs-12: 12px;
  --fs-13: 13px;
  --fs-15: 15px;
  --fs-18: 18px;
  --fs-22: 22px;

  /* spacing scale (4/8 rhythm) */
  --sp-4: 4px;
  --sp-8: 8px;
  --sp-12: 12px;
  --sp-16: 16px;
  --sp-24: 24px;
  --sp-32: 32px;

  --radius-xl: 32px;
  --tap: 44px;
  --on-primary: #fff;

  /* gradient for surfaces that carry white text (≥4.5:1 everywhere) */
  --cta-gradient: linear-gradient(135deg, #1F7A74 0%, #155E59 100%);
  --vip-gradient: linear-gradient(135deg, #F59E0B 0%, #D97706 100%);
  --warn-fg: #B45309;

  --safe-top: env(safe-area-inset-top, 0px);
  --safe-bottom: env(safe-area-inset-bottom, 0px);

  --ease-out: cubic-bezier(.2, .8, .2, 1);
  --dur-fast: 150ms;
  --dur-base: 220ms;
}

[data-theme="dark"] {
  --hint-color: #9DBDB8;
  --cta-gradient: linear-gradient(135deg, #1F7A74 0%, #125550 100%);
  --warn-fg: #FBBF24;
}

/* ---------- 2. Global fixes ---------- */

/* iOS zooms into any field under 16px on focus */
@media (max-width: 576px) {
  input:not([type="checkbox"]):not([type="radio"]):not([type="range"]),
  select,
  textarea,
  .form-control {
    font-size: 16px !important;
  }
}

/* toolbar-safe full height */
.aw {
  min-height: 100vh;
  min-height: 100dvh;
}

/* keep the notification stack clear of the notch */
.notification {
  top: calc(12px + var(--safe-top));
}

/* touch: no 300ms delay, no grey flash */
a, button, [role="button"], .pointer, .btn {
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
}

/* respect the OS "reduce motion" setting everywhere */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
    scroll-behavior: auto !important;
  }
}

/* icofont duotone icons are two glyph layers: ::after sits in normal flow, ::before is pinned
   absolutely to the top-left corner. Whenever the <i> is a tap box larger than the glyph (nav pills,
   round 44px buttons, the send button) the two halves drift apart; centring the pinned layer in the
   box keeps both halves on top of each other for every host size. */
i[class*="icofont-"].icofont-duotone::before {
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
}
/* spin helper used by the route loader and the username check (not shipped in icofont.min.css) */
.icofont-spin {
  display: inline-block;
  animation: icofontSpin 1s linear infinite;
}
@keyframes icofontSpin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .icofont-spin { animation-duration: 2.4s; } }

/* ---------- 3. Header / back button (shared by every page) ---------- */
header {
  background: var(--cta-gradient);
  height: calc(56px + var(--safe-top));
  padding-top: var(--safe-top);
}
header .title {
  font-size: var(--fs-15);
}
header .back-btn,
header .add,
header .refresh,
header > .icon {
  min-width: var(--tap);
  min-height: var(--tap);
  width: var(--tap);
  height: var(--tap);
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  border: 0;
  color: inherit;
  padding: 0;
}
header .back-btn:active,
header .add:active,
header .refresh:active,
header > .icon:active {
  background: rgba(255, 255, 255, .18);
}
/* the back button always sits at the start of the header (right side in RTL) whatever the markup order;
   a header that has to keep it on the left adds .is-left so the arrow points left */
header .back-btn { order: -1; }
header .back-btn.is-left { order: 1; margin-inline-start: auto; }
header .back-btn.is-left i { transform: scaleX(-1); }
.topgap {
  height: calc(56px + var(--safe-top));
}

/* ---------- 4. Buttons ---------- */
.ui-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-8);
  min-height: var(--tap);
  padding: 0 var(--sp-16);
  border-radius: var(--radius-md);
  border: 1.5px solid transparent;
  font-size: var(--fs-15);
  font-weight: 600;
  line-height: 1.2;
  cursor: pointer;
  transition: transform var(--dur-fast) var(--ease-out), opacity var(--dur-fast) ease;
}
.ui-btn:active { transform: scale(.97); }
.ui-btn[disabled],
.ui-btn.is-loading {
  opacity: .6;
  pointer-events: none;
}
.ui-btn.is-loading::after {
  content: "";
  width: 16px;
  height: 16px;
  border-radius: 50%;
  border: 2px solid currentColor;
  border-top-color: transparent;
  animation: uiSpin .7s linear infinite;
}
.ui-btn-primary { background: var(--cta-gradient); color: var(--on-primary); }
.ui-btn-ghost   { background: transparent; color: var(--font-color2); border-color: var(--border-color); }
.ui-btn-danger  { background: var(--red); color: #fff; }
.ui-btn-block   { width: 100%; }
@keyframes uiSpin { to { transform: rotate(360deg); } }

/* confirm dialog built by dialog() in app.js */
#modal_dialog .modal-body {
  font-size: var(--fs-15);
  line-height: 1.7;
  color: var(--font-color);
  padding: var(--sp-24) var(--sp-16) var(--sp-16);
  text-align: center;
}
#modal_dialog .modal-footer {
  display: flex;
  flex-direction: column;
  gap: var(--sp-8);
  border-top: 0;
  padding: 0 var(--sp-16) var(--sp-16);
}
#modal_dialog .modal-footer > * {
  width: 100%;
  margin: 0 !important;
}

/* ---------- 5. Forms ---------- */
.ui-label {
  display: block;
  font-size: var(--fs-13);
  font-weight: 600;
  color: var(--font-color);
  margin: 0 0 6px;
}
.ui-help {
  font-size: var(--fs-12);
  color: var(--font-color2);
  margin-top: 6px;
}
.sr-only-fa {
  position: absolute !important;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0, 0, 0, 0);
  white-space: nowrap; border: 0;
}

/* ---------- 6. User row (messages, viewers, blocks, favourites) ---------- */
.urow {
  display: flex;
  align-items: center;
  gap: var(--sp-12);
  min-height: 72px;
  padding: var(--sp-12) var(--sp-16);
  margin: var(--sp-8) var(--sp-12);
  background: var(--bg-primary);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
  cursor: pointer;
  transition: transform var(--dur-fast) var(--ease-out), background var(--dur-fast) ease;
}
.urow:active { transform: scale(.98); background: var(--bg-secondary); }
.urow-pic {
  position: relative;
  flex: 0 0 52px;
  width: 52px;
  height: 52px;
  border-radius: 50%;
  background-size: cover;
  background-position: center;
  background-color: var(--bg-secondary);
  /* hairline ring so white-background avatars keep an edge on light cards */
  box-shadow: 0 0 0 1px var(--border-color);
}
.urow.online .urow-pic::after {
  content: "";
  position: absolute;
  bottom: 1px;
  left: 1px;
  width: 13px;
  height: 13px;
  border-radius: 50%;
  background: var(--green);
  border: 2px solid var(--bg-primary);
}
.urow-body { flex: 1; min-width: 0; }
.urow-name {
  display: flex;
  align-items: center;
  gap: 4px;
  font-size: var(--fs-15);
  font-weight: 700;
  color: var(--font-color);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* .urow-name is flex, so the ellipsis must live on the text child */
.urow-nm {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.urow-sub {
  font-size: var(--fs-13);
  color: var(--font-color2);
  margin-top: 2px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.urow-meta {
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 6px;
  font-size: var(--fs-12);
  color: var(--font-color2);
}
.urow-badge {
  min-width: 22px;
  height: 22px;
  padding: 0 6px;
  border-radius: var(--radius-pill);
  background: var(--cta-gradient); /* white text stays ≥4.5:1 in both themes */
  color: #fff;
  font-size: var(--fs-12);
  font-weight: 700;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

/* ---------- 7. Grouped settings list (iOS style) ---------- */
.s-group-title {
  font-size: var(--fs-13);
  font-weight: 600;
  color: var(--font-color2);
  margin: var(--sp-24) var(--sp-16) var(--sp-8);
}
.s-group {
  background: var(--bg-primary);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-lg);
  margin: 0 var(--sp-12);
  overflow: hidden;
}
.s-item {
  display: flex;
  align-items: center;
  gap: var(--sp-12);
  width: 100%;
  min-height: 52px;
  padding: var(--sp-8) var(--sp-16);
  background: transparent;
  border: 0;
  color: var(--font-color);
  font-size: var(--fs-15);
  text-align: start;
  cursor: pointer;
}
.s-item + .s-item { border-top: 1px solid var(--border-color); }
.s-item:active { background: var(--bg-secondary); }
.s-item .s-ico {
  flex: 0 0 32px;
  width: 32px;
  height: 32px;
  border-radius: 9px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 17px;
  background: var(--bg-secondary);
  color: var(--primary-color);
}
.s-item .s-label { flex: 1; min-width: 0; }
.s-item .s-value { font-size: var(--fs-13); color: var(--font-color2); }
.s-item .s-chev { color: var(--font-color2); font-size: 14px; }
.s-item.is-danger { color: var(--red); }
.s-item.is-danger .s-ico { color: var(--red); background: rgba(239, 68, 68, .1); }

/* real switch control: <button class="s-switch" role="switch" aria-checked="true|false"> */
.s-switch {
  position: relative;
  flex: 0 0 51px;
  width: 51px;
  height: 31px;
  border-radius: 999px;
  border: 0;
  padding: 0;
  background: var(--border-color2);
  transition: background var(--dur-base) ease;
  cursor: pointer;
}
.s-switch::after {
  content: "";
  position: absolute;
  top: 2px;
  right: 2px;
  width: 27px;
  height: 27px;
  border-radius: 50%;
  background: #fff;
  box-shadow: 0 2px 6px rgba(0, 0, 0, .2);
  transition: transform var(--dur-base) var(--ease-out);
}
.s-switch[aria-checked="true"] { background: var(--green); }
.s-switch[aria-checked="true"]::after { transform: translateX(-20px); }

/* ---------- 8. Add-to-Home-Screen sheet (iOS) ---------- */
.a2hs-scrim {
  position: fixed;
  inset: 0;
  z-index: 2000;
  background: rgba(20, 8, 16, .45);
  opacity: 0;
  transition: opacity var(--dur-base) ease;
}
.a2hs-sheet {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 2001;
  max-width: 500px;
  margin: 0 auto;
  background: var(--bg-primary);
  color: var(--font-color);
  border-radius: 24px 24px 0 0;
  padding: 10px var(--sp-16) calc(var(--sp-16) + var(--safe-bottom));
  box-shadow: 0 -12px 40px rgba(15, 42, 40, .25);
  transform: translateY(100%);
  transition: transform 320ms var(--ease-out);
  direction: rtl;
  text-align: right;
}
.a2hs-open .a2hs-scrim { opacity: 1; }
.a2hs-open .a2hs-sheet { transform: translateY(0); }
.a2hs-grip {
  width: 40px;
  height: 5px;
  border-radius: 3px;
  background: var(--border-color2);
  margin: 0 auto var(--sp-16);
}
.a2hs-head {
  display: flex;
  align-items: center;
  gap: var(--sp-12);
  margin-bottom: var(--sp-16);
}
.a2hs-head img {
  width: 56px;
  height: 56px;
  border-radius: 14px;
  box-shadow: var(--shadow-sm);
  flex: 0 0 56px;
}
.a2hs-title { font-size: var(--fs-18); font-weight: 700; margin: 0; }
.a2hs-sub { font-size: var(--fs-13); color: var(--font-color2); margin: 2px 0 0; line-height: 1.6; }
.a2hs-steps {
  list-style: none;
  margin: 0 0 var(--sp-16);
  padding: 0;
  background: var(--bg-secondary);
  border-radius: var(--radius-md);
}
.a2hs-steps li {
  display: flex;
  align-items: center;
  gap: var(--sp-12);
  padding: var(--sp-12) var(--sp-16);
  font-size: var(--fs-15);
  line-height: 1.5;
}
.a2hs-steps li + li { border-top: 1px solid var(--border-color); }
.a2hs-num {
  flex: 0 0 24px;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  background: var(--primary-color);
  color: #fff;
  font-size: var(--fs-12);
  font-weight: 700;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.a2hs-ico {
  display: inline-flex;
  vertical-align: middle;
  color: #0A84FF;
  margin: 0 2px;
}
.a2hs-ico svg { width: 20px; height: 20px; }
.a2hs-actions { display: flex; gap: var(--sp-8); }
.a2hs-actions .ui-btn { flex: 1; }
/* pointer that sits above Safari's share button (bottom toolbar on iPhone) */
.a2hs-arrow {
  display: block;
  text-align: center;
  color: var(--primary-color);
  font-size: 22px;
  margin-top: var(--sp-8);
  animation: a2hsNudge 1.4s ease-in-out 3;
}
@keyframes a2hsNudge {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(5px); }
}


/* ---------- connection banner (main.html #connBar) ---------- */
/* a full-width strip under the status bar: red = device offline, amber = reconnecting to the
   server, green = back online (shown briefly). Slides in from the top. */
.conn-bar {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 3000;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-8);
  padding: calc(var(--safe-top) + 8px) var(--sp-16) 8px;
  background: #B91C1C;
  color: #fff;
  font-size: var(--fs-13);
  font-weight: 600;
  line-height: 1.4;
  text-align: center;
  box-shadow: 0 6px 20px rgba(0, 0, 0, .18);
  transform: translateY(-110%);
  opacity: 0;
  pointer-events: none;
  transition: transform .25s var(--ease-out, ease), opacity .25s ease, background-color .25s ease;
}
.conn-bar.is-shown { transform: translateY(0); opacity: 1; }
.conn-bar.is-offline { background: #B91C1C; }
.conn-bar.is-reconnecting { background: #B45309; }
.conn-bar.is-online { background: #15803D; }
.conn-bar .conn-ico { font-size: 16px; line-height: 1; }
.conn-bar .conn-spin { display: none; }
.conn-bar.is-reconnecting .conn-spin { display: inline-block; }
.conn-bar.is-reconnecting .conn-ico { display: none; }
.conn-spin {
  width: 14px;
  height: 14px;
  border: 2px solid rgba(255, 255, 255, .35);
  border-top-color: #fff;
  border-radius: 50%;
  animation: connSpin .8s linear infinite;
}
@keyframes connSpin { to { transform: rotate(360deg); } }

/* ---------- list skeleton rows + lazy avatars ---------- */
.urow-skel { cursor: default; box-shadow: none; }
.urow-skel .urow-body { flex: 1; display: flex; flex-direction: column; gap: var(--sp-8); }
.urow-skel .sk-line { height: 12px; width: 55%; border-radius: 6px; }
.urow-skel .sk-short { width: 32%; }
[data-bg] { background-color: var(--bg-secondary); }
