/* ============================================================================
   EchoStream — single stylesheet. Plain CSS, loaded directly (no build step).
   Tailwind (via CDN) still provides generic utilities (flex, grid, spacing,
   rounded, emerald/red/yellow, white-alpha). Everything THEME-related lives
   here. To restyle the product, edit the variables in the block below.
   ============================================================================ */

:root{
  /* ===================== EDIT YOUR THEME HERE ===================== */
  --accent:#26D8B0;        /* primary green (buttons, highlights)     */
  --accent-2:#5BE3C3;       /* lighter green (text, active items)      */
  --accent-3:#18AA88;       /* darker green (gradient end)             */
  --accent-ink:#04130D;     /* text/icon color ON green buttons        */

  --bg:#0A0B0E;             /* page background (dark, neutral)         */
  --surface:#0F1115;        /* cards / inputs base                     */
  --side:#0F1115;           /* sidebar background                      */
  --ink:#E8EAF0;            /* main text                               */
  --muted:#919AA6;          /* secondary text                         */
  --faint:#5C6470;          /* hints / disabled                        */
  --line:rgba(255,255,255,.08);   /* hairline borders                 */

  --radius:.9rem;           /* default corner radius                   */

  /* green tints (kept here so the accent is changeable in one place)  */
  --accent-soft:rgba(38,216,176,.12);
  --accent-line:rgba(38,216,176,.28);
  --accent-ring:rgba(38,216,176,.45);
  --accent-strong:rgba(38,216,176,.55);
  /* =============================================================== */
}

/* ---------- base ---------- */
*{ box-sizing:border-box }
html{ scroll-behavior:smooth }
body{ margin:0; background:var(--bg); color:var(--ink);
  font-family:Inter,"Segoe UI",sans-serif; -webkit-font-smoothing:antialiased; }

.font-display{ font-family:"Space Grotesk",Inter,sans-serif }
.font-mono{ font-family:"JetBrains Mono",ui-monospace,monospace }
.text-muted{ color:var(--muted) }
.text-faint{ color:var(--faint) }
.text-ink{ color:var(--ink) }

.grid-bg{
  background-color:var(--bg);
  background-image:
    radial-gradient(75% 55% at 50% -10%, rgba(255,255,255,.035), transparent 60%),
    linear-gradient(rgba(255,255,255,.02) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255,255,255,.02) 1px, transparent 1px);
  background-size:auto, 44px 44px, 44px 44px;
}
.glow{ background:radial-gradient(55% 55% at 50% 0%, rgba(255,255,255,.04), transparent 60%); }

/* ---------- surfaces ---------- */
.glass-card{ background:rgba(255,255,255,.04); border:1px solid var(--line);
  backdrop-filter:blur(14px); -webkit-backdrop-filter:blur(14px); }
.glass{ background:rgba(255,255,255,.06); border:1px solid rgba(255,255,255,.10);
  backdrop-filter:blur(10px); -webkit-backdrop-filter:blur(10px); }
.tile,.mini-stat{ background:rgba(255,255,255,.028); border:1px solid var(--line); }

/* A dialog is not a card. .glass-card is 4% white, which reads correctly when
   it sits on the page but goes see-through the moment it floats over a scrim -
   the storage page's "Add more storage" tiles were legible straight through the
   Go live dialog. Modals get an opaque surface instead. */
/* An upload bar whose width is truthful still looks frozen while a slow chunk
   is in flight. The stripes move constantly so the bar reads as alive, without
   the width ever claiming progress that has not happened - a simulated bar
   would have hidden the Cloudflare stall that cost us a day. */
.bar-live{
  background-image:linear-gradient(90deg,
    rgba(255,255,255,.20) 25%, transparent 25%, transparent 50%,
    rgba(255,255,255,.20) 50%, rgba(255,255,255,.20) 75%, transparent 75%);
  background-size:1.15rem 1.15rem;
  animation:bar-stripes .9s linear infinite;
}
@keyframes bar-stripes{ from{ background-position:0 0 } to{ background-position:1.15rem 0 } }
@media (prefers-reduced-motion:reduce){ .bar-live{ animation:none } }

/* The upload bar's fill. It used to be an inline `background:` shorthand on the
   element, which outranks every class - so .bar-live's stripes and .bar-indet's
   sweep were both silently painted over and neither ever appeared. */
.bar-fill{ background:linear-gradient(90deg, var(--accent), var(--accent-2)); }

/* Indeterminate: a band that sweeps the track while there is genuinely nothing
   to report. The first chunk of an upload is the slowest - the connection is
   still in slow start and BBR has not found the bandwidth yet - so a bar
   stopped at 0% for twenty seconds reads as broken when it is working. This
   says "busy" without inventing a percentage. */
.bar-indet{
  width:100% !important;
  background-image:linear-gradient(90deg,
    transparent 0%, var(--accent-3) 30%, var(--accent-2) 50%, var(--accent-3) 70%, transparent 100%);
  background-size:45% 100%;
  background-repeat:no-repeat;
  animation:bar-indet 1.5s ease-in-out infinite;
}
@keyframes bar-indet{ from{ background-position:-55% 0 } to{ background-position:155% 0 } }
@media (prefers-reduced-motion:reduce){ .bar-indet{ animation:none; background-position:50% 0 } }

.modal-scrim{ background:rgba(0,0,0,.66); backdrop-filter:blur(3px); -webkit-backdrop-filter:blur(3px); }
.modal-card{ background:var(--surface); border:1px solid var(--line);
  box-shadow:0 24px 60px rgba(0,0,0,.6); }

/* ---------- accents ---------- */
.grad{ background:linear-gradient(135deg,var(--accent),var(--accent-3)); }
.text-gradient{ background:linear-gradient(120deg,var(--accent-2),var(--accent));
  -webkit-background-clip:text; background-clip:text; color:transparent; }

/* ---------- buttons ---------- */
.btn-primary{ background:linear-gradient(135deg,var(--accent),var(--accent-3)); color:var(--accent-ink);
  font-weight:600; display:inline-flex; align-items:center; gap:.5rem; justify-content:center;
  transition:.18s; border:0; cursor:pointer; }
.btn-primary:hover{ opacity:.92; transform:translateY(-1px); }
.btn-ghost{ background:rgba(255,255,255,.04); border:1px solid var(--line); color:var(--ink);
  display:inline-flex; align-items:center; gap:.5rem; justify-content:center; transition:.18s; cursor:pointer; }
.btn-ghost:hover{ background:rgba(255,255,255,.08); }

/* ---------- badges ---------- */
.badge{ display:inline-flex; align-items:center; gap:.35rem; font-size:11px; font-weight:600;
  padding:.25rem .6rem; border-radius:9999px; }
.badge-green{ background:var(--accent-soft); color:var(--accent-2); border:1px solid var(--accent-line); }
.badge-yellow{ background:rgba(245,158,11,.12); color:#FBBF24; border:1px solid rgba(245,158,11,.28); }
.badge-red{ background:rgba(239,68,68,.12); color:#F87171; border:1px solid rgba(239,68,68,.28); }
.badge-muted{ background:rgba(255,255,255,.06); color:var(--faint); border:1px solid var(--line); }

/* ---------- form fields ---------- */
input,select,textarea{ background:rgba(255,255,255,.05); border:1px solid var(--line); color:var(--ink); }
input::placeholder,textarea::placeholder{ color:var(--faint); }
input:focus,select:focus,textarea:focus{ outline:none; border-color:var(--accent-strong);
  box-shadow:0 0 0 3px var(--accent-soft); }
select option{ background:var(--surface); }

/* ---------- sidebar ---------- */
.side-bar{ background:linear-gradient(180deg,rgba(255,255,255,.02),transparent 40%),var(--side);
  border-right:1px solid var(--line); }
.side-item{ position:relative; display:flex; align-items:center; gap:.7rem; margin:.12rem .25rem;
  padding:.62rem .8rem; border-radius:.75rem; color:var(--muted); font-size:.9rem; font-weight:500;
  transition:.15s; cursor:pointer; }
.side-item i{ width:1.15rem; text-align:center; font-size:1rem; opacity:.9; }
.side-item:hover{ background:rgba(255,255,255,.05); color:var(--ink); }
.side-item.active{ background:var(--accent-soft); color:var(--accent-2); box-shadow:inset 3px 0 0 var(--accent); }
.side-item.active i{ opacity:1; }
.nav-sep{ font-size:.66rem; letter-spacing:.1em; text-transform:uppercase; color:var(--faint);
  padding:.95rem .95rem .35rem; }

/* ---------- site header (public) ---------- */
#siteHeader{ transition:padding .25s ease; }
#siteHeader .hdr-inner{ position:relative; overflow:hidden; background:rgba(15,17,21,.72);
  border-bottom:1px solid var(--line); backdrop-filter:blur(14px); -webkit-backdrop-filter:blur(14px); transition:all .25s ease; }
#scroll-progress{ position:absolute; left:0; bottom:0; height:2px; width:0;
  background:linear-gradient(90deg,var(--accent),var(--accent-2)); transition:width .1s linear; }
#siteHeader.floating{ padding:.55rem .8rem 0; }
#siteHeader.floating .hdr-inner{ max-width:72rem; margin:0 auto; border:0; border-radius:1rem;
  box-shadow:0 12px 34px rgba(0,0,0,.45); background:rgba(20,22,27,.8); }

/* ---------- guided steps (tutorial) ---------- */
.step{ display:flex; gap:1rem; }
.step-rail{ display:flex; flex-direction:column; align-items:center; }
.step-num{ width:2.25rem; height:2.25rem; border-radius:9999px; display:grid; place-items:center;
  font-weight:700; font-family:"Space Grotesk",sans-serif; flex:0 0 auto;
  background:rgba(255,255,255,.05); border:1px solid var(--line); color:var(--muted); }
.step-line{ width:2px; flex:1; background:var(--line); margin:.35rem 0; min-height:1rem; }
.step.active .step-num{ border-color:var(--accent-strong); color:var(--accent-2); box-shadow:0 0 0 3px var(--accent-soft); }
.step.done .step-num{ background:linear-gradient(135deg,var(--accent),var(--accent-3)); color:var(--accent-ink); border-color:transparent; }
.step.done .step-line{ background:linear-gradient(var(--accent),var(--line)); }
.step-body{ flex:1; padding-bottom:1.4rem; }
.step:last-child .step-body{ padding-bottom:0; }
.step-title{ font-family:"Space Grotesk",sans-serif; font-weight:600; }
.step.done .step-title{ color:var(--accent-2); }

/* ---------- node selection ---------- */
.node-sel{ transition:.15s }
.node-sel.selected{ border-color:var(--accent-strong)!important; box-shadow:0 0 0 1px var(--accent-ring); }

/* ---------- ripple + motion ---------- */
.ring-r{ position:absolute; inset:0; margin:auto; border-radius:9999px; border:1px solid var(--accent-line); }
@keyframes ripple{ 0%{ transform:scale(.18); opacity:.7 } 100%{ transform:scale(1); opacity:0 } }
@keyframes pulse{ 0%,100%{ opacity:1 } 50%{ opacity:.5 } }
@media (prefers-reduced-motion:no-preference){
  .ring-r{ animation:ripple 4.4s ease-out infinite; }
  .ring-r:nth-child(2){ animation-delay:1.1s } .ring-r:nth-child(3){ animation-delay:2.2s } .ring-r:nth-child(4){ animation-delay:3.3s }
  .pulse-dot{ animation:pulse 1.8s ease-in-out infinite; }
}

/* ---------- misc ---------- */
::selection{ background:var(--accent-ring); }
::-webkit-scrollbar{ width:10px; height:10px } ::-webkit-scrollbar-thumb{ background:rgba(255,255,255,.08); border-radius:9px }
summary::-webkit-details-marker{ display:none } summary::marker{ content:"" }

/* ============================================================================
   PANEL v2 — profile box, channel cards, settings tabs, animations
   ========================================================================== */

/* sidebar profile box (top of sidebar) */
.profile-box{ position:relative; }
.profile-trigger{ display:flex; align-items:center; gap:.6rem; width:100%; padding:.55rem .6rem;
  border-radius:.8rem; border:1px solid var(--line); background:rgba(255,255,255,.028); cursor:pointer;
  transition:border-color .15s, background .15s; }
.profile-trigger:hover{ border-color:var(--accent-line); background:rgba(255,255,255,.05); }
.avatar{ flex:none; width:34px; height:34px; border-radius:.7rem; display:grid; place-items:center;
  font-weight:700; color:var(--accent-ink); background:linear-gradient(135deg,var(--accent),var(--accent-3)); }
.profile-menu{ position:absolute; left:0; right:0; top:calc(100% + .4rem); z-index:60;
  background:var(--surface); border:1px solid var(--line); border-radius:.9rem; padding:.35rem;
  box-shadow:0 16px 40px rgba(0,0,0,.5); opacity:0; transform:translateY(-6px) scale(.98);
  pointer-events:none; transition:opacity .16s, transform .16s; }
.profile-box.open .profile-menu{ opacity:1; transform:none; pointer-events:auto; }
.profile-menu a{ display:flex; align-items:center; gap:.6rem; padding:.5rem .6rem; border-radius:.6rem;
  font-size:.85rem; color:var(--muted); transition:background .12s,color .12s; }
.profile-menu a:hover{ background:rgba(255,255,255,.05); color:var(--ink); }
.profile-menu a i{ width:1.1rem; text-align:center; }
.profile-menu .sep{ height:1px; background:var(--line); margin:.3rem .2rem; }

/* channel catalog cards (Add a channel grid) */
.chan-grid{ display:grid; grid-template-columns:repeat(auto-fill,minmax(150px,1fr)); gap:.65rem; }
.chan-card{ display:flex; flex-direction:column; align-items:center; justify-content:center; gap:.5rem;
  padding:1.1rem .6rem; border-radius:1rem; border:1px solid var(--line); background:rgba(255,255,255,.028);
  cursor:pointer; text-align:center; transition:transform .18s, border-color .18s, background .18s; }
.chan-card:hover{ transform:translateY(-3px); border-color:var(--accent-line); background:rgba(255,255,255,.05); }
.chan-card i{ font-size:1.7rem; color:var(--ink); transition:color .18s; }
.chan-card:hover i{ color:var(--accent-2); }
.chan-card .nm{ font-size:.82rem; font-weight:600; }
.chan-card .sub{ font-size:.66rem; color:var(--faint); }

/* settings tabs */
.tab-link{ padding:.5rem .9rem; border-radius:.7rem; font-size:.85rem; color:var(--muted);
  border:1px solid transparent; transition:all .15s; white-space:nowrap; }
.tab-link:hover{ color:var(--ink); background:rgba(255,255,255,.04); }
.tab-link.active{ color:var(--accent-2); background:var(--accent-soft); border-color:var(--accent-line); }

/* ---- animation layer (gated on reduced-motion) ---- */
@keyframes fadeUp{ from{ opacity:0; transform:translateY(10px) } to{ opacity:1; transform:none } }
@keyframes fadeIn{ from{ opacity:0 } to{ opacity:1 } }
@keyframes popIn{ 0%{ opacity:0; transform:scale(.96) } 100%{ opacity:1; transform:none } }
@media (prefers-reduced-motion:no-preference){
  .anim-page > *{ animation:fadeUp .5s both; }
  .anim-page > *:nth-child(2){ animation-delay:.05s }
  .anim-page > *:nth-child(3){ animation-delay:.1s }
  .anim-page > *:nth-child(4){ animation-delay:.15s }
  .anim-page > *:nth-child(5){ animation-delay:.2s }
  .anim-page > *:nth-child(n+6){ animation-delay:.25s }
  .stagger > *{ animation:popIn .42s both; }
  .stagger > *:nth-child(2){ animation-delay:.04s } .stagger > *:nth-child(3){ animation-delay:.08s }
  .stagger > *:nth-child(4){ animation-delay:.12s } .stagger > *:nth-child(5){ animation-delay:.16s }
  .stagger > *:nth-child(6){ animation-delay:.2s }  .stagger > *:nth-child(7){ animation-delay:.24s }
  .stagger > *:nth-child(8){ animation-delay:.28s } .stagger > *:nth-child(n+9){ animation-delay:.32s }
  .lift{ transition:transform .18s, box-shadow .18s, border-color .18s; }
  .lift:hover{ transform:translateY(-2px); box-shadow:0 10px 28px rgba(0,0,0,.28); }
  .side-item{ transition:background .15s,color .15s,box-shadow .15s,transform .12s; }
  .side-item:hover{ transform:translateX(2px); }
}

/* multi-chat rows (panel view; overlay has its own copy) */
.cmsg{font-size:14px;line-height:1.4;word-wrap:break-word}
.cmsg.chist{opacity:.55}
.cplat{margin-right:6px;font-size:12px}
.cbadge{margin-right:3px;font-size:11px;vertical-align:middle}
/* display:inline-block is load-bearing: Tailwind's preflight sets img{display:block},
   which put every emote on its own line and split the sentence around it. The
   overlay page does not load Tailwind, which is why it only showed in the panel. */
.cemote{display:inline-block;height:1.5em;width:auto;vertical-align:middle;margin:0 1px}
.cbadge{display:inline-block}
.cmsg{overflow-wrap:anywhere}
.cuser{font-weight:700;margin-right:6px}
.ctext{color:var(--muted)}
/* Legal pages (privacy, terms). Long-form prose needs different rhythm from
   the dashboard: readable measure, clear heading hierarchy, real list spacing. */
.legal h2{font-family:'Space Grotesk',Inter,sans-serif;font-weight:600;font-size:1.05rem;margin:2rem 0 .6rem;color:var(--ink)}
.legal h3{font-weight:600;font-size:.92rem;margin:1.2rem 0 .4rem;color:var(--ink)}
.legal p{color:var(--muted);font-size:.92rem;line-height:1.7;margin:.6rem 0}
.legal ul{margin:.6rem 0 .6rem 1.1rem;padding:0}
.legal li{color:var(--muted);font-size:.92rem;line-height:1.7;margin:.35rem 0;list-style:disc}
.legal b{color:var(--ink);font-weight:600}
.legal a{color:var(--accent-2);text-decoration:underline}

/* Kick has no FontAwesome icon — the brand set only carries Kickstarter, which
   is a different company — so it was falling back to a bolt or a generic video
   glyph. This draws the mark as a mask so it inherits currentColor and sizes
   like any other <i>, with no extra network request. */
.icon-kick{
  display:inline-block; width:1em; height:1em; vertical-align:-.125em;
  background-color:currentColor;
  -webkit-mask:var(--kick-mark) center/contain no-repeat;
          mask:var(--kick-mark) center/contain no-repeat;
}
:root{
  --kick-mark:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M3 3h5v6h2V6h2V3h6v6h-2v3h-2v3h2v3h2v6h-6v-3h-2v-3H8v6H3z'/></svg>");
}
.text-kick{ color:#53FC18 }

/* The dots that travel the hero wires from the mark out to each platform. They
   are SMIL <animateMotion>, which no media query can pause, so hide them
   outright for anyone who has asked for less movement. */
@media (prefers-reduced-motion: reduce) { .echo-packet { display: none; } }

/* Channel tag on a chat message. Only rendered when more than one channel is
   feeding the window - with a single channel it says nothing and costs a line
   of width on every message. */
.cchan{
  display:inline-block; margin-right:6px; padding:1px 6px; border-radius:9999px;
  font-size:10px; font-weight:600; vertical-align:middle; white-space:nowrap;
  background:var(--accent-soft); color:var(--accent-2); border:1px solid var(--accent-line);
}

/* YouTube ships its own emoji as :shortcodes: with no artwork in the API. Mapped
   ones render as Unicode at message size; unmapped ones become a readable chip
   rather than raw punctuation. */
.cemoji{ font-size:1.15em; line-height:1; vertical-align:-.1em }
.cshort{
  display:inline-block; padding:0 5px; border-radius:6px; font-size:11px;
  vertical-align:middle; background:hsla(0,0%,100%,.07); color:var(--muted);
}

/* The hero mark. No tile: a card around the logo read as a screenshot of a UI
   element, and the wires appeared to leave the card rather than the mark. What
   is left is light - a soft field behind the artwork with no edge anywhere for
   the eye to read as a box. */
.echo-hub{ perspective:620px; }
.echo-hub::before{
  content:""; position:absolute; inset:-22%; pointer-events:none; z-index:0;
  background:radial-gradient(circle at 50% 44%,
             rgba(38,216,176,.30), rgba(38,216,176,.10) 40%, transparent 68%);
  filter:blur(8px);
}

/* The mark, lifted rather than extruded.
   A stack of stepped drop-shadows did read as a solid object, but the artwork
   is thin outlines: the extrusion filled the gaps between them and the whole
   glyph turned to mud at hero size. What lifts it now is depth cues that leave
   the line work alone - a tight contact shadow, a wider soft one for the drop,
   and a bloom that sits behind the strokes instead of smearing across them. */
.echo-hub img{
  position:relative; z-index:1;
  filter:
    drop-shadow(0 2px 3px rgba(0,0,0,.55))
    drop-shadow(0 14px 22px rgba(0,0,0,.45))
    drop-shadow(0 0 26px rgba(38,216,176,.38));
}
@media (prefers-reduced-motion:no-preference){
  .echo-hub img{ animation:markfloat 6s ease-in-out infinite; }
}
@keyframes markfloat{
  0%,100%{ transform:translateY(-5px) }
  50%    { transform:translateY(5px)  }
}
}

/* The rings are wider now, so they need to start smaller and fade sooner or
   they read as a box around the whole graphic rather than as waves. */
.ring-r{ border-color:rgba(38,216,176,.22) }
@media (prefers-reduced-motion: no-preference){
  .ring-r{ animation:ripple 5.2s cubic-bezier(.22,.61,.36,1) infinite }
}
