/* ════════════════════════════════════════════════════════════════
   THEME: justwitter (default)
   The original comic-zine look: yellow/red/black, thick borders,
   hard drop shadows, Bangers + Permanent Marker + Courier Prime.
   ════════════════════════════════════════════════════════════════ */

html[data-theme="justwitter"] {
  /* ── Palette ── */
  --paper:      #f7f4ee;   /* page background */
  --ink:        #1a1a1a;   /* primary text */
  --ink-mid:    #666;      /* secondary text */
  --ink-faint:  #6e6e6e;   /* tertiary / timestamps */
  --rule:       #e0ddd6;   /* hairlines, dividers */
  --red:        #D10F24;   /* brand accent, CTAs, header */
  --yellow:     #FFE600;   /* hero background, highlights */
  --black:      #111;      /* borders, sticker outlines */
  --surface:    #fff;      /* card / panel background */
  --on-accent:  #fff;      /* text & borders on --red / --black fills */
  --icon-fill:       rgba(255,255,255,.16); /* header/footer icon-button fill (bell, burger, theme toggle, footer nav icons) — replaces the old 2px on-accent border look */
  --icon-fill-hover: rgba(255,255,255,.26);

  /* ── Fonts ──
     Loaded via the Google Fonts <link> in <head>. If you introduce
     a theme that needs a different family, add its own font <link>
     and reference it here. */
  --font-display: 'Bangers', cursive;             /* logo, buttons, tabs, shouty headings */
  --font-mono:    'Courier Prime', monospace;      /* body copy, inputs, timestamps */
  --font-accent:  'Permanent Marker', cursive;     /* hero tagline sticker */
}

/* Footer nav icons: icon-only circles instead of labeled pills, matching
   kaiunta's own .footer-feed-btn/.footer-stations-btn/.footer-autostream-btn
   treatment (font-size:0 + ::before mask icon) and justwitter's own
   header login/signup circles above — one icon language across header
   and footer. Text is hidden via font-size:0 (markup untouched, so other
   themes/states can still read it), 34px to match the header's circles.
   Same SVG data URIs as kaiunta's, just tinted for justwitter's on-accent
   (white-on-black) footer instead of kaiunta's ink-on-paper one. */
html[data-theme="justwitter"] .footer-feed-btn,
html[data-theme="justwitter"] .footer-stations-btn,
html[data-theme="justwitter"] .footer-autostream-btn {
  width: 34px;
  height: 34px;
  padding: 0;
  font-size: 0;
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}
html[data-theme="justwitter"] .footer-feed-btn::before,
html[data-theme="justwitter"] .footer-stations-btn::before,
html[data-theme="justwitter"] .footer-autostream-btn::before {
  content: "";
  display: block;
  width: 16px;
  height: 16px;
  flex-shrink: 0;
  background-color: var(--on-accent);
  transition: background-color .15s;
}
/* voices = mic icon (same glyph as kaiuntatheme.css .footer-feed-btn::before) */
html[data-theme="justwitter"] .footer-feed-btn::before {
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 1a3 3 0 0 0-3 3v8a3 3 0 0 0 6 0V4a3 3 0 0 0-3-3z'/%3E%3Cpath d='M19 10v2a7 7 0 0 1-14 0v-2'/%3E%3Cline x1='12' y1='19' x2='12' y2='23'/%3E%3Cline x1='8' y1='23' x2='16' y2='23'/%3E%3C/svg%3E") center / contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 1a3 3 0 0 0-3 3v8a3 3 0 0 0 6 0V4a3 3 0 0 0-3-3z'/%3E%3Cpath d='M19 10v2a7 7 0 0 1-14 0v-2'/%3E%3Cline x1='12' y1='19' x2='12' y2='23'/%3E%3Cline x1='8' y1='23' x2='16' y2='23'/%3E%3C/svg%3E") center / contain no-repeat;
}
/* stations = broadcast-tower icon (same glyph as kaiunta's + the station-avatar fallback) */
html[data-theme="justwitter"] .footer-stations-btn::before {
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4.93 4.93a10 10 0 0 0 0 14.14'/%3E%3Cpath d='M7.76 7.76a6 6 0 0 0 0 8.49'/%3E%3Cpath d='M16.24 7.76a6 6 0 0 1 0 8.49'/%3E%3Cpath d='M19.07 4.93a10 10 0 0 1 0 14.14'/%3E%3Ccircle cx='12' cy='12' r='1.5' fill='%23000' stroke='none'/%3E%3Cline x1='12' y1='13.5' x2='12' y2='20'/%3E%3Cline x1='9.5' y1='20' x2='14.5' y2='20'/%3E%3C/svg%3E") center / contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4.93 4.93a10 10 0 0 0 0 14.14'/%3E%3Cpath d='M7.76 7.76a6 6 0 0 0 0 8.49'/%3E%3Cpath d='M16.24 7.76a6 6 0 0 1 0 8.49'/%3E%3Cpath d='M19.07 4.93a10 10 0 0 1 0 14.14'/%3E%3Ccircle cx='12' cy='12' r='1.5' fill='%23000' stroke='none'/%3E%3Cline x1='12' y1='13.5' x2='12' y2='20'/%3E%3Cline x1='9.5' y1='20' x2='14.5' y2='20'/%3E%3C/svg%3E") center / contain no-repeat;
}
/* stream = play triangle. The button's own text already toggles between
   "▶ stream"/"❚❚ stream" unicode glyphs (see footerAutoStreamBtn logic in
   index-theme.php), so swap this icon on the same .active class it
   already gets, exactly like kaiunta's play/pause swap below. */
html[data-theme="justwitter"] .footer-autostream-btn::before {
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%23000' stroke='none'%3E%3Cpolygon points='6,4 20,12 6,20'/%3E%3C/svg%3E") center / contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%23000' stroke='none'%3E%3Cpolygon points='6,4 20,12 6,20'/%3E%3C/svg%3E") center / contain no-repeat;
}
html[data-theme="justwitter"] .footer-feed-btn:hover::before,
html[data-theme="justwitter"] .footer-stations-btn:hover::before,
html[data-theme="justwitter"] .footer-autostream-btn:hover::before {
  background-color: var(--red);
}
html[data-theme="justwitter"] .footer-autostream-btn.active::before {
  background-color: var(--black);
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%23000' stroke='none'%3E%3Crect x='5' y='4' width='5' height='16'/%3E%3Crect x='14' y='4' width='5' height='16'/%3E%3C/svg%3E") center / contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%23000' stroke='none'%3E%3Crect x='5' y='4' width='5' height='16'/%3E%3Crect x='14' y='4' width='5' height='16'/%3E%3C/svg%3E") center / contain no-repeat;
}

/* Header search icon just opens #viewSearch and focuses its input — but
   the feed's own "search voices..." trigger box (#feedSearchTrigger) does
   the exact same thing on click (see its listener further down), so this
   is a hard duplicate once the feed's showing. Same reasoning kaiunta
   already hides #btnSearchHeader for (see kaiuntatheme.css), just a
   tighter case here since justwitter's trigger isn't even a different
   interaction — clicking either one runs the identical showView+focus. */
html[data-theme="justwitter"] #btnSearchHeader {
  display: none;
}

/* Trying lowercase here too (was uppercase-only, justwitter's own comic-
   poster styling) — same text-transform: lowercase technique
   kaiuntatheme.css's .hdr-logo rule already uses, not a change to the
   #hdrLogo button's actual text content (see index2.php's $brand_wordmark),
   so reverting this is just deleting this one rule. Loses a bit of the
   loud/quiet contrast between the two themes' wordmarks that justified
   keeping this uppercase originally — worth a second look once it's live
   rather than a rule to keep on faith either way.
*/
html[data-theme="justwitter"] .hdr-logo {
  text-transform: lowercase;
}

/* Header login/signup: icon-only circles instead of text pills — same
   font-size:0 + ::before mask-icon swap kaiunta uses on its own
   #btnHdrLogin/#btnHdrSignup, kept in justwitter's language (34px
   on-accent-bordered circle) instead of kaiunta's hairline pill. Removes
   the wrap-and-overflow bug on narrow phones outright since there's no
   button text left to wrap, and frees enough width for the temporary
   #hdrThemeToggle "..." button to keep fitting alongside them.
   Same login (head+shoulders) / signup (plus) glyphs as kaiunta's SVGs,
   so the icon language stays consistent across themes — just tinted for
   justwitter's red/white instead of kaiunta's ink/paper. */
html[data-theme="justwitter"] #btnHdrLogin,
html[data-theme="justwitter"] #btnHdrSignup {
  width: 34px;
  height: 34px;
  padding: 0;
  font-size: 0;
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}
html[data-theme="justwitter"] #btnHdrLogin::before,
html[data-theme="justwitter"] #btnHdrSignup::before {
  content: "";
  display: block;
  width: 15px;
  height: 15px;
  -webkit-mask-position: center;
  mask-position: center;
  -webkit-mask-size: contain;
  mask-size: contain;
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  transition: background-color .15s;
}
/* LOG IN — base .hdr-btn is transparent/on-accent, so the icon starts
   on-accent (white); base .hdr-btn:hover flips the button to white
   bg/red text, so the icon follows to red. */
html[data-theme="justwitter"] #btnHdrLogin::before {
  background-color: var(--on-accent);
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='8' r='4'/%3E%3Cpath d='M4 20c0-4 4-6 8-6s8 2 8 6'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='8' r='4'/%3E%3Cpath d='M4 20c0-4 4-6 8-6s8 2 8 6'/%3E%3C/svg%3E");
}
html[data-theme="justwitter"] #btnHdrLogin:hover::before {
  background-color: var(--red);
}
/* START WITTERING→ — base .hdr-btn-primary is white bg/red text, so the
   icon starts red; base .hdr-btn-primary:hover flips the button to
   black bg/on-accent text, so the icon follows to on-accent (white). */
html[data-theme="justwitter"] #btnHdrSignup::before {
  background-color: var(--red);
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round'%3E%3Cline x1='12' y1='5' x2='12' y2='19'/%3E%3Cline x1='5' y1='12' x2='19' y2='12'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round'%3E%3Cline x1='12' y1='5' x2='12' y2='19'/%3E%3Cline x1='5' y1='12' x2='19' y2='12'/%3E%3C/svg%3E");
}
html[data-theme="justwitter"] #btnHdrSignup:hover::before {
  background-color: var(--on-accent);
}

/* Burger menu — guest CTAs: the menu's own labeled log in / start
   wittering buttons (see index-theme.php's #menuGuestCtas — now shown
   for justwitter too, not just kaiunta, since the header versions above
   are icon-only and no longer duplicate these). Full-width comic-style
   buttons matching .menu-logout-btn's thick-border language rather than
   the header's compact on-accent pills, since these sit on the paper
   background inside the menu, not on the red header bar. */
html[data-theme="justwitter"] .menu-guest-ctas {
  display: flex;
  flex-direction: column;
  gap: .75rem;
  margin-bottom: .5rem;
}
html[data-theme="justwitter"] .menu-cta-btn {
  width: 100%;
  height: 50px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .6rem;
  background: var(--surface);
  border: 3px solid var(--black);
  border-radius: 6px;
  font-family: var(--font-display);
  font-size: 1rem;
  letter-spacing: .08em;
  color: var(--black);
  cursor: pointer;
  transition: background .15s, color .15s;
}
html[data-theme="justwitter"] #menuLoginBtn:hover {
  background: var(--yellow);
}
html[data-theme="justwitter"] #menuSignupBtn {
  background: var(--red);
  color: var(--on-accent);
  border-color: var(--black);
}
html[data-theme="justwitter"] #menuSignupBtn:hover {
  background: var(--black);
}
/* Same person/plus glyphs as the header's icon-only login/signup circles
   (#btnHdrLogin/#btnHdrSignup) — here they sit inline next to the label
   since the burger menu keeps full text, unlike the header's icon-only
   treatment. */
html[data-theme="justwitter"] .menu-cta-icon {
  width: 15px;
  height: 15px;
  flex-shrink: 0;
  -webkit-mask-position: center;
  mask-position: center;
  -webkit-mask-size: contain;
  mask-size: contain;
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
}
html[data-theme="justwitter"] .menu-cta-icon-login {
  background-color: var(--black);
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='8' r='4'/%3E%3Cpath d='M4 20c0-4 4-6 8-6s8 2 8 6'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='8' r='4'/%3E%3Cpath d='M4 20c0-4 4-6 8-6s8 2 8 6'/%3E%3C/svg%3E");
}
html[data-theme="justwitter"] .menu-cta-icon-signup {
  background-color: var(--on-accent);
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round'%3E%3Cline x1='12' y1='5' x2='12' y2='19'/%3E%3Cline x1='5' y1='12' x2='19' y2='12'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round'%3E%3Cline x1='12' y1='5' x2='12' y2='19'/%3E%3Cline x1='5' y1='12' x2='19' y2='12'/%3E%3C/svg%3E");
}

/* Burger menu — voices/stations nav links: index-theme.php's base CSS
   hides .menu-nav-links entirely for every theme (it was bare unstyled
   button chrome, never an intentional design — see its comment there),
   only kaiuntatheme.css turned it back on. Give justwitter the same
   treatment here: shown, and styled like a shouty comic list instead of
   kaiunta's hairline-italic one — thick black bottom border per row
   (matching .menu-accordion-item), Bangers display type, same mic/tower
   glyphs as the footer's icon-only circles above so the icon language
   matches everywhere it shows up. */
html[data-theme="justwitter"] .menu-nav-links {
  display: flex;
  flex-direction: column;
  margin: .25rem 0 .5rem;
}
html[data-theme="justwitter"] .menu-nav-link {
  display: flex;
  align-items: center;
  gap: .75rem;
  width: 100%;
  background: none;
  border: none;
  border-bottom: 3px solid var(--black);
  text-align: left;
  font-family: var(--font-display);
  letter-spacing: .06em;
  color: var(--black);
  font-size: 1.3rem;
  padding: .85rem .25rem;
  cursor: pointer;
  transition: color .15s;
}
html[data-theme="justwitter"] .menu-nav-link:hover {
  color: var(--red);
}
html[data-theme="justwitter"] .menu-nav-icon {
  width: 18px;
  height: 18px;
  flex-shrink: 0;
  background-color: var(--black);
  -webkit-mask-position: center;
  mask-position: center;
  -webkit-mask-size: contain;
  mask-size: contain;
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  transition: background-color .15s;
}
html[data-theme="justwitter"] .menu-nav-link:hover .menu-nav-icon {
  background-color: var(--red);
}
html[data-theme="justwitter"] .menu-nav-icon-voices {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 1a3 3 0 0 0-3 3v8a3 3 0 0 0 6 0V4a3 3 0 0 0-3-3z'/%3E%3Cpath d='M19 10v2a7 7 0 0 1-14 0v-2'/%3E%3Cline x1='12' y1='19' x2='12' y2='23'/%3E%3Cline x1='8' y1='23' x2='16' y2='23'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 1a3 3 0 0 0-3 3v8a3 3 0 0 0 6 0V4a3 3 0 0 0-3-3z'/%3E%3Cpath d='M19 10v2a7 7 0 0 1-14 0v-2'/%3E%3Cline x1='12' y1='19' x2='12' y2='23'/%3E%3Cline x1='8' y1='23' x2='16' y2='23'/%3E%3C/svg%3E");
}
html[data-theme="justwitter"] .menu-nav-icon-stations {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4.93 4.93a10 10 0 0 0 0 14.14'/%3E%3Cpath d='M7.76 7.76a6 6 0 0 0 0 8.49'/%3E%3Cpath d='M16.24 7.76a6 6 0 0 1 0 8.49'/%3E%3Cpath d='M19.07 4.93a10 10 0 0 1 0 14.14'/%3E%3Ccircle cx='12' cy='12' r='1.5' fill='%23000' stroke='none'/%3E%3Cline x1='12' y1='13.5' x2='12' y2='20'/%3E%3Cline x1='9.5' y1='20' x2='14.5' y2='20'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4.93 4.93a10 10 0 0 0 0 14.14'/%3E%3Cpath d='M7.76 7.76a6 6 0 0 0 0 8.49'/%3E%3Cpath d='M16.24 7.76a6 6 0 0 1 0 8.49'/%3E%3Cpath d='M19.07 4.93a10 10 0 0 1 0 14.14'/%3E%3Ccircle cx='12' cy='12' r='1.5' fill='%23000' stroke='none'/%3E%3Cline x1='12' y1='13.5' x2='12' y2='20'/%3E%3Cline x1='9.5' y1='20' x2='14.5' y2='20'/%3E%3C/svg%3E");
}
/* Menu — bookmarks row: same ribbon glyph as the cast-card bookmark
   button (see .cast-bookmark svg in index.php), so the icon language
   matches between the per-cast toggle and this menu entry. */
html[data-theme="justwitter"] .menu-nav-icon-bookmarks {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M19 21l-7-5-7 5V5a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2z'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M19 21l-7-5-7 5V5a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2z'/%3E%3C/svg%3E");
}
/* Menu — stream row: same play-triangle glyph as the footer's icon-only
   stream circle, swapped to pause bars via the same .active class the
   footer button gets (see #footerAutoStreamBtn/.active above and
   setAutoStreamBtnState() in index-theme.php, which now keeps this row
   and the footer button in sync). Active state fills the whole row
   yellow/black — same "this one's live" language as the footer's filled
   circle — rather than reusing hover's red, so playing-vs-hovering stay
   visually distinct. */
html[data-theme="justwitter"] .menu-nav-icon-stream {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%23000' stroke='none'%3E%3Cpolygon points='6,4 20,12 6,20'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%23000' stroke='none'%3E%3Cpolygon points='6,4 20,12 6,20'/%3E%3C/svg%3E");
}
html[data-theme="justwitter"] .menu-nav-stream.active {
  background: var(--yellow);
  color: var(--black);
  border-bottom-color: var(--black);
}
html[data-theme="justwitter"] .menu-nav-stream.active .menu-nav-icon {
  background-color: var(--black);
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%23000' stroke='none'%3E%3Crect x='5' y='4' width='5' height='16'/%3E%3Crect x='14' y='4' width='5' height='16'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%23000' stroke='none'%3E%3Crect x='5' y='4' width='5' height='16'/%3E%3Crect x='14' y='4' width='5' height='16'/%3E%3C/svg%3E");
}
html[data-theme="justwitter"] .menu-nav-stream.active:hover {
  color: var(--red);
}
html[data-theme="justwitter"] .menu-nav-stream.active:hover .menu-nav-icon {
  background-color: var(--red);
}

/* Stream loading toast — chunky comic-style pill matching .menu-logout-btn's
   thick-border language: black fill, red border, hard offset shadow,
   shouty uppercase Bangers (the shared markup's text stays lowercase in
   the DOM/JS; text-transform handles the shouty-caps look here only). */
html[data-theme="justwitter"] .stream-loading-toast {
  background: var(--black);
  color: var(--on-accent);
  border: 2px solid var(--red);
  box-shadow: 3px 3px 0 var(--black);
  font-family: var(--font-display);
  letter-spacing: .08em;
  text-transform: uppercase;
}

/* Actionable hero — swaps the ambient animated "voices. not posts."
   slogan for the same static eyebrow/headline/copy/CTA block kaiunta
   uses (shared markup, .hero-kaiunta), restyled in justwitter's own
   comic voice: centered, Bangers display font, yellow bg + dot texture
   kept (unlike kaiunta which strips both), buttons using the site's
   existing thick-border/hard-shadow .btn-primary language instead of
   kaiunta's quiet italic links. Only active when #viewHero carries
   .hero-actionable — see $justwitter_hero_actionable in index-theme.php.
   Without that class justwitter's hero is untouched (ambient slogan,
   nothing actionable in the hero itself). */
html[data-theme="justwitter"] #viewHero.hero-actionable .hero-bangers {
  display: none;
}
html[data-theme="justwitter"] #viewHero.hero-actionable .hero-kaiunta {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 1.25rem;
  max-width: 640px;
  margin: 0 auto;
  position: relative;
}
html[data-theme="justwitter"] #viewHero.hero-actionable .hero-eyebrow {
  font-family: var(--font-mono);
  font-size: .8rem;
  font-weight: 700;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--red);
  margin: 0;
}
html[data-theme="justwitter"] #viewHero.hero-actionable .hero-kai-title {
  font-family: var(--font-display);
  font-weight: 400;
  letter-spacing: .02em;
  line-height: 1.1;
  font-size: clamp(2.4rem, 8vw, 5.5rem);
  color: var(--black);
  text-transform: uppercase;
  margin: 0;
}
html[data-theme="justwitter"] #viewHero.hero-actionable .hero-kai-copy {
  font-family: var(--font-mono);
  color: var(--ink-mid);
  font-size: clamp(.9rem, 1.6vw, 1.05rem);
  line-height: 1.7;
  max-width: 46ch;
  margin: 0;
}
html[data-theme="justwitter"] #viewHero.hero-actionable .hero-kai-ctas {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: .85rem;
  width: min(320px, 88vw);
  margin-top: .5rem;
}
html[data-theme="justwitter"] #viewHero.hero-actionable .hero-kai-ctas .btn-primary {
  text-transform: uppercase;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .5em;
}
html[data-theme="justwitter"] #viewHero.hero-actionable .hero-kai-login {
  background: none;
  border: none;
  padding: 0;
  font-family: var(--font-display);
  font-size: .85rem;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--black);
  border-bottom: 3px solid var(--black);
  padding-bottom: .15em;
  cursor: pointer;
  transition: color .15s, border-color .15s;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .4em;
}
html[data-theme="justwitter"] #viewHero.hero-actionable .hero-kai-login:hover {
  color: var(--red);
  border-bottom-color: var(--red);
}
/* Icons inherit each button's own text color via currentColor. */
html[data-theme="justwitter"] #viewHero.hero-actionable .hero-kai-cta-icon {
  flex-shrink: 0;
}

/* Opt-in left-aligned variant — off by default (justwitter stays centered,
   its normal "poster" read). Toggle $justwitter_hero_left_align in
   index-theme.php to switch it on; adds .hero-left alongside
   .hero-actionable rather than replacing it, so every rule above still
   applies and this block only overrides the alignment-specific bits.
   The earlier version of this only touched .hero-kaiunta's own text-align/
   margin, which wasn't enough — the outer #viewHero (.hero) flex container
   itself has align-items:center in the base theme, and that's what was
   actually centering the whole box regardless of what happened inside it.
   kaiunta escapes this the same way: by overriding align-items on .hero
   itself, not just the child. Padding also switches to kaiunta's own
   responsive inset so the block sits at a matching distance from the
   real page edge, not just left-aligned within its old centered slot. */
html[data-theme="justwitter"] #viewHero.hero-actionable.hero-left {
  align-items: flex-start;
  text-align: left;
  padding-left: clamp(1.5rem, 8vw, 6rem);
  padding-right: clamp(1.5rem, 8vw, 6rem);
}
html[data-theme="justwitter"] #viewHero.hero-actionable.hero-left .hero-kaiunta {
  align-items: flex-start;
  text-align: left;
  margin: 0;
}
html[data-theme="justwitter"] #viewHero.hero-actionable.hero-left .hero-kai-ctas {
  align-items: stretch;
  margin-left: 0;
}
html[data-theme="justwitter"] #viewHero.hero-actionable.hero-left .hero-kai-ctas .btn-primary,
html[data-theme="justwitter"] #viewHero.hero-actionable.hero-left .hero-kai-login {
  justify-content: flex-start;
}
html[data-theme="justwitter"] #viewHero.hero-actionable.hero-left .hero-kai-login {
  align-self: flex-start;
}
@media (max-width: 480px) {
  html[data-theme="justwitter"] #viewHero.hero-actionable.hero-left .hero-kai-login {
    align-self: flex-start;
  }
}

/* Staggered fade-up entrance, reusing the base theme's own fadeUp
   keyframe (see .hero-actions/.hero-legal in index-theme.php) instead
   of duplicating kaiunta's separate kaiuntaHeroIn animation. */
html[data-theme="justwitter"] #viewHero.hero-actionable .hero-eyebrow,
html[data-theme="justwitter"] #viewHero.hero-actionable .hero-kai-title,
html[data-theme="justwitter"] #viewHero.hero-actionable .hero-kai-copy,
html[data-theme="justwitter"] #viewHero.hero-actionable .hero-kai-ctas {
  opacity: 0;
  animation: fadeUp .9s ease forwards;
}
html[data-theme="justwitter"] #viewHero.hero-actionable .hero-eyebrow   { animation-delay: .1s; }
html[data-theme="justwitter"] #viewHero.hero-actionable .hero-kai-title { animation-delay: .3s; }
html[data-theme="justwitter"] #viewHero.hero-actionable .hero-kai-copy  { animation-delay: .55s; }
html[data-theme="justwitter"] #viewHero.hero-actionable .hero-kai-ctas  { animation-delay: .8s; }

@media (prefers-reduced-motion: reduce) {
  html[data-theme="justwitter"] #viewHero.hero-actionable .hero-eyebrow,
  html[data-theme="justwitter"] #viewHero.hero-actionable .hero-kai-title,
  html[data-theme="justwitter"] #viewHero.hero-actionable .hero-kai-copy,
  html[data-theme="justwitter"] #viewHero.hero-actionable .hero-kai-ctas {
    animation: none;
    opacity: 1;
  }
}

/* ── Hero background video/image (justwitter's own take) ──
   Same shared markup/attribute (#viewHero[data-hero-media]) and same
   JS (mute toggle, mobile pause/resume — see index.php's script) as
   kaiunta uses; see kaiuntatheme.css's parallel block for the fuller
   write-up of the mechanics. This block only adds the CSS justwitter
   was missing to actually show/style that layer — without it the
   video markup exists in the DOM but stays display:none here.

   Legibility approach differs from kaiunta on purpose: kaiunta's hero
   text is left-aligned, so a left-to-right paper gradient works. Both
   of justwitter's hero variants (.hero-bangers ambient slogan AND the
   centered .hero-kaiunta actionable block) are centered, so this uses
   a centered radial scrim instead — solid yellow behind the copy,
   fading to transparent toward the corners — plus the same halftone
   dot texture (.hero::before) that's always been part of justwitter's
   look, so the video reads as "under" the comic paper rather than
   replacing it outright. */
html[data-theme="justwitter"] #viewHero[data-hero-media="video"] .hero-kai-media,
html[data-theme="justwitter"] #viewHero[data-hero-media="image"] .hero-kai-media {
  display: block;
  position: absolute;
  inset: 0;
  z-index: 0;
  overflow: hidden;
}
html[data-theme="justwitter"] .hero-kai-media-video,
html[data-theme="justwitter"] .hero-kai-media-image {
  display: none; /* only the matching option below turns its element on */
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
}
html[data-theme="justwitter"] #viewHero[data-hero-media="video"] .hero-kai-media-video {
  display: block;
}
html[data-theme="justwitter"] #viewHero[data-hero-media="image"] .hero-kai-media-image {
  display: block;
}
html[data-theme="justwitter"] .hero-kai-media-scrim {
  position: absolute;
  inset: 0;
  background: radial-gradient(
    ellipse at center,
    var(--yellow) 0%,
    var(--yellow) 30%,
    rgba(255, 230, 0, .82) 45%,
    rgba(255, 230, 0, .35) 65%,
    rgba(255, 230, 0, 0) 82%
  );
}
/* hero-left swaps the centered radial scrim above for a left-to-right
   linear one — the radial version puts its solid yellow "backing" in the
   middle of the screen assuming centered text; once text moves to the
   left (see .hero-left below) that backing sits over empty video instead
   of the copy, leaving the actual text under the gradient's fading tail
   with too little contrast. Mirrors kaiunta's own linear scrim approach
   (same idea, different accent color) since kaiunta solves the identical
   left-aligned-text-over-video problem. */
html[data-theme="justwitter"] #viewHero.hero-left .hero-kai-media-scrim {
  background: linear-gradient(
    90deg,
    var(--yellow) 0%,
    var(--yellow) 34%,
    rgba(255, 230, 0, .82) 50%,
    rgba(255, 230, 0, .35) 68%,
    rgba(255, 230, 0, 0) 85%
  );
}

/* Text stack needs to sit above the media layer — plain flex/fixed
   children with no z-index today, fine when nothing's behind them,
   now needs to explicitly win the stacking order. Covers both hero
   variants since either can be the one showing (see
   $justwitter_hero_actionable in index.php). .hero-bangers is already
   position:fixed (see base index.php CSS) — only z-index is added
   here, not position, so its full-viewport fixed layout isn't touched. */
html[data-theme="justwitter"] #viewHero[data-hero-media="video"] .hero-bangers,
html[data-theme="justwitter"] #viewHero[data-hero-media="image"] .hero-bangers {
  z-index: 1;
}
html[data-theme="justwitter"] #viewHero[data-hero-media="video"] .hero-kaiunta,
html[data-theme="justwitter"] #viewHero[data-hero-media="image"] .hero-kaiunta {
  position: relative;
  z-index: 1;
}

/* Sound toggle: hidden by default, only shown for the "video" option.
   Sits on the right, same side kaiunta puts it. Reuses justwitter's
   own thick-border comic button language (unlike kaiunta's quiet
   blurred-glass pill) so it doesn't look like a borrowed component. */
html[data-theme="justwitter"] .hero-kai-mute {
  display: none;
}
html[data-theme="justwitter"] #viewHero[data-hero-media="video"] .hero-kai-mute {
  display: inline-flex;
  align-items: center;
  gap: .5rem;
  position: absolute;
  right: clamp(1rem, 3vw, 2rem);
  bottom: calc(var(--ftr-h) + clamp(1rem, 3vw, 2rem));
  z-index: 2;
  height: 40px;
  padding: 0 1rem;
  border: 3px solid var(--black);
  border-radius: 999px;
  background: var(--surface);
  box-shadow: 4px 4px 0 var(--black);
  color: var(--black);
  font-family: var(--font-mono);
  font-weight: 700;
  font-size: .72rem;
  letter-spacing: .04em;
  text-transform: uppercase;
  cursor: pointer;
  transition: transform .1s, box-shadow .1s, background .15s;
}
html[data-theme="justwitter"] #viewHero[data-hero-media="video"] .hero-kai-mute:hover {
  transform: translate(-2px, -2px);
  box-shadow: 6px 6px 0 var(--black);
  background: var(--yellow);
}
html[data-theme="justwitter"] #viewHero[data-hero-media="video"] .hero-kai-mute:active {
  transform: translate(2px, 2px);
  box-shadow: 2px 2px 0 var(--black);
}
html[data-theme="justwitter"] .hero-kai-mute-icon {
  width: 14px;
  height: 14px;
  flex-shrink: 0;
  background-color: currentColor;
  -webkit-mask-position: center;
  mask-position: center;
  -webkit-mask-size: contain;
  mask-size: contain;
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  /* Muted (default) glyph: speaker with an X. Same data URI as
     kaiunta's — a plain speaker glyph isn't a themed asset. */
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolygon points='11 5 6 9 2 9 2 15 6 15 11 19 11 5'/%3E%3Cline x1='23' y1='9' x2='17' y2='15'/%3E%3Cline x1='17' y1='9' x2='23' y2='15'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolygon points='11 5 6 9 2 9 2 15 6 15 11 19 11 5'/%3E%3Cline x1='23' y1='9' x2='17' y2='15'/%3E%3Cline x1='17' y1='9' x2='23' y2='15'/%3E%3C/svg%3E");
}
html[data-theme="justwitter"] .hero-kai-mute[aria-pressed="true"] .hero-kai-mute-icon {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolygon points='11 5 6 9 2 9 2 15 6 15 11 19 11 5'/%3E%3Cpath d='M15.54 8.46a5 5 0 0 1 0 7.07'/%3E%3Cpath d='M18.36 5.64a9 9 0 0 1 0 12.73'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolygon points='11 5 6 9 2 9 2 15 6 15 11 19 11 5'/%3E%3Cpath d='M15.54 8.46a5 5 0 0 1 0 7.07'/%3E%3Cpath d='M18.36 5.64a9 9 0 0 1 0 12.73'/%3E%3C/svg%3E");
}
@media (max-width: 640px) {
  html[data-theme="justwitter"] #viewHero[data-hero-media="video"] .hero-kai-mute {
    right: 1rem;
    bottom: calc(var(--ftr-h) + 1rem);
    font-size: .68rem;
    padding: 0 .85rem;
  }
}
/* Portrait phones only: .hero itself is now position:fixed and already
   clipped to bottom:var(--ftr-h) (see the shared mobile-portrait fix in
   index.php's base <style> block) — its own bottom edge sits right at
   the footer already, so this button's "bottom" offset no longer needs
   to add var(--ftr-h) on top of that. Left as-is above for any width
   where .hero ISN'T fixed (e.g. landscape), where the old full-height
   .hero and its calc(var(--ftr-h) + 1rem) math still applies. */
@media (max-width: 640px) and (orientation: portrait) {
  html[data-theme="justwitter"] #viewHero[data-hero-media="video"] .hero-kai-mute {
    bottom: 1rem;
  }
}

/* Reduced motion: don't play the video at all — swap to the still
   poster frame instead, same as kaiunta. */
@media (prefers-reduced-motion: reduce) {
  html[data-theme="justwitter"] #viewHero[data-hero-media="video"] .hero-kai-media-video {
    display: none;
  }
  html[data-theme="justwitter"] #viewHero[data-hero-media="video"] .hero-kai-media-image {
    display: block;
  }
}

/* Mobile: video is a desktop-only feature by default, same reasoning
   and same opt-out flag as kaiunta ($mobile_hero_video in index.php,
   surfaced here as data-mobile-video="on"). When it's off, phones get
   nothing behind the text at all — just the flat yellow + halftone
   dots justwitter always had — not even the still image, so there's no
   extra image request on top of no video. */
@media (max-width: 640px) {
  html[data-theme="justwitter"] #viewHero[data-hero-media="video"]:not([data-mobile-video="on"]) .hero-kai-media-video {
    display: none;
  }
  html[data-theme="justwitter"] #viewHero[data-hero-media="video"]:not([data-mobile-video="on"]) .hero-kai-media-image {
    display: none;
  }
  html[data-theme="justwitter"] #viewHero[data-hero-media="video"]:not([data-mobile-video="on"]) .hero-kai-mute {
    display: none;
  }
}

/* Mobile: when the video (or still image) IS showing, the radial scrim
   above is tuned for desktop's wider canvas — on a narrow viewport the
   "solid yellow" center zone can end up almost as wide as the whole
   hero, leaving barely a sliver of video visible at the edges. Tighten
   the stops so more of the frame actually reads as video/image on
   phones. */
@media (max-width: 640px) {
  html[data-theme="justwitter"] #viewHero[data-hero-media="video"][data-mobile-video="on"] .hero-kai-media-scrim,
  html[data-theme="justwitter"] #viewHero[data-hero-media="image"] .hero-kai-media-scrim {
    background: radial-gradient(
      ellipse at center,
      var(--yellow) 0%,
      var(--yellow) 16%,
      rgba(255, 230, 0, .8) 30%,
      rgba(255, 230, 0, .3) 48%,
      rgba(255, 230, 0, 0) 68%
    );
  }
  /* .hero-left needs its own entry here, not just the desktop one above —
     the two selectors just above this match on plain .hero-kai-media-scrim
     with more attribute selectors than the desktop .hero-left rule has, so
     without this override they'd win at this width and silently bring
     back the centered radial glare (mismatched with left-aligned text)
     that this whole change was meant to fix. Same tightened stops as the
     centered mobile version above, just left-anchored instead of centered. */
  html[data-theme="justwitter"] #viewHero.hero-left[data-hero-media="video"][data-mobile-video="on"] .hero-kai-media-scrim,
  html[data-theme="justwitter"] #viewHero.hero-left[data-hero-media="image"] .hero-kai-media-scrim {
    background: linear-gradient(
      90deg,
      var(--yellow) 0%,
      var(--yellow) 20%,
      rgba(255, 230, 0, .8) 38%,
      rgba(255, 230, 0, .3) 55%,
      rgba(255, 230, 0, 0) 72%
    );
  }
}

/* Mobile: header's own CTAs disappear below a certain width in some
   layouts, and three hero CTAs (pill + two links) have less room to
   breathe — drop the pill treatment on "start wittering" so it reads
   at the same weight as "log in"/"go to feed" once stacked tightly,
   matching the same reasoning kaiunta uses for its own 640px stack
   breakpoint. Kept comic (bordered) here rather than going bare-text
   like kaiunta, since justwitter's whole button language is the thick
   border + shadow. */
@media (max-width: 480px) {
  html[data-theme="justwitter"] #viewHero.hero-actionable .hero-kai-ctas .btn-primary {
    height: 52px;
    font-size: .95rem;
  }
  html[data-theme="justwitter"] #viewHero.hero-actionable .hero-kai-login {
    align-self: center;
  }
}

/* Enlarge #anonTokenOverlay / #welcomeOverlay / #confirmStationOverlay,
   matching kaiunta's treatment (see kaiuntatheme.css) — same reasoning:
   #anonTokenOverlay holds the only way back into an anonymous account,
   #welcomeOverlay is the app's one-time orientation, both too easy to
   skim past in the same small 380px card every other modal uses.
   Kept the comic aesthetic (thick border, hard offset shadow, Bangers
   display font) rather than switching to kaiunta's hairline look —
   just sized up. #recordOverlay is left alone on purpose: its
   timer/circle/caption/preview stack needs its own layout pass, not
   just bigger type. */
@media (min-width: 601px) {
  html[data-theme="justwitter"] #anonTokenOverlay .record-card,
  html[data-theme="justwitter"] #welcomeOverlay .record-card,
  html[data-theme="justwitter"] #confirmStationOverlay .record-card {
    width: min(480px, 90vw);
    padding: 2.5rem 2.25rem;
    gap: 1.5rem;
  }
  html[data-theme="justwitter"] #anonTokenOverlay .record-title,
  html[data-theme="justwitter"] #welcomeOverlay .record-title,
  html[data-theme="justwitter"] #confirmStationOverlay .record-title {
    font-size: 1.75rem;
  }
  html[data-theme="justwitter"] #anonTokenOverlay .record-hint,
  html[data-theme="justwitter"] #welcomeOverlay .record-hint,
  html[data-theme="justwitter"] #confirmStationOverlay .record-hint {
    font-size: 1rem;
    line-height: 1.7;
    max-width: 38ch;
  }
  html[data-theme="justwitter"] #anonTokenInput {
    font-size: 1rem !important;
    height: 56px !important;
    letter-spacing: .02em;
  }
  html[data-theme="justwitter"] #anonTokenOverlay .btn-ghost,
  html[data-theme="justwitter"] #anonTokenOverlay .btn-primary,
  html[data-theme="justwitter"] #welcomeOverlay .btn-primary,
  html[data-theme="justwitter"] #confirmStationOverlay .btn-ghost,
  html[data-theme="justwitter"] #confirmStationOverlay .btn-primary {
    height: 52px;
    font-size: .85rem;
  }
}

@media (max-width: 600px) {
  html[data-theme="justwitter"] #anonTokenOverlay,
  html[data-theme="justwitter"] #welcomeOverlay,
  html[data-theme="justwitter"] #confirmStationOverlay {
    padding: 0;
  }
  html[data-theme="justwitter"] #anonTokenOverlay .record-card,
  html[data-theme="justwitter"] #welcomeOverlay .record-card,
  html[data-theme="justwitter"] #confirmStationOverlay .record-card {
    width: 100%;
    max-width: 100%;
    height: 100dvh;
    border: none;
    border-radius: 0;
    box-shadow: none;
    justify-content: center;
    padding: 2.5rem 1.75rem;
    gap: 1.75rem;
  }
  html[data-theme="justwitter"] #anonTokenOverlay .record-title,
  html[data-theme="justwitter"] #welcomeOverlay .record-title,
  html[data-theme="justwitter"] #confirmStationOverlay .record-title {
    font-size: 1.6rem;
  }
  html[data-theme="justwitter"] #anonTokenOverlay .record-hint,
  html[data-theme="justwitter"] #welcomeOverlay .record-hint,
  html[data-theme="justwitter"] #confirmStationOverlay .record-hint {
    font-size: 1.05rem;
    line-height: 1.75;
    max-width: 32ch;
  }
  html[data-theme="justwitter"] #anonTokenInput {
    font-size: 1rem !important;
    height: 58px !important;
    letter-spacing: .02em;
  }
  html[data-theme="justwitter"] #anonTokenOverlay .btn-ghost,
  html[data-theme="justwitter"] #anonTokenOverlay .btn-primary,
  html[data-theme="justwitter"] #welcomeOverlay .btn-primary,
  html[data-theme="justwitter"] #confirmStationOverlay .btn-ghost,
  html[data-theme="justwitter"] #confirmStationOverlay .btn-primary {
    height: 58px;
    font-size: .85rem;
  }
}

/* Stations toolbar had its own top padding (.75rem, from the base theme)
   stacked on top of .feed-header's margin-bottom — feed's search row has
   no such padding of its own, so stations' search box sat noticeably
   further from the tabs than feed's did. Drop it to zero so the gap
   matches. Matches kaiunta's existing fix for the same base-theme bug;
   the 3px solid black divider stays as-is here since it's already
   consistent with justwitter's thick-border language (kaiunta swapped
   it for a hairline as part of its own unrelated shape overrides). */
html[data-theme="justwitter"] .stations-toolbar {
  padding-top: 0;
}

/* #feedBack and #stationsBack both only ever go to viewFeed or viewHero —
   exactly what tapping the logo (#hdrLogo) already does, so they're a
   redundant back step, not a real chain out of anywhere. Matches kaiunta's
   existing treatment of the same two elements. !important because
   #feedBack's visibility is also toggled inline by JS based on login
   state. */
html[data-theme="justwitter"] #feedBack,
html[data-theme="justwitter"] #stationsBack {
  display: none !important;
}

/* Feed/Stations/Search page titles: visually redundant here too — Feed's
   duplicates the active tab label right above it, Stations'/Search's are
   already covered by their search input's placeholder ("search
   stations...", "search voices..."). Hidden visually only (not
   display:none) so they stay in the accessibility tree as the page's
   heading for screen reader users, who don't have the
   placeholder-as-context shortcut. Matches kaiunta's existing treatment. */
html[data-theme="justwitter"] #feedTitle,
html[data-theme="justwitter"] #stationsTitle,
html[data-theme="justwitter"] #searchTitle {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* Stations subtitle ("every station that's posted a voice, most recently
   active first — log in to follow one.") explains the list's sort order —
   unlike the redundant titles above, sighted users have no other visual
   cue for this, so hiding it is a real (if minor) omission for them. It
   stays in the a11y tree because screen reader users, who can't glance at
   the list to infer sort order the way sighted users can, benefit from it
   more, not less. Matches kaiunta's existing treatment. */
html[data-theme="justwitter"] #stationsSubtitle {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}
/* ── Go Live (per-station live mic broadcasting) ─────────────────────────
   justwitter's loud voice: red fill, black offset shadow, Bangers caps —
   same button language as .btn-primary/.btn-ghost elsewhere in this theme.
   Gated behind LIVE_BROADCASTING_ENABLED server-side (index.php) — these
   rules just style the markup when it's present, they don't control
   whether it renders. */
html[data-theme="justwitter"] .go-live-panel {
  border: 3px solid var(--black);
  border-radius: 8px;
  padding: 1rem 1.1rem;
  background: var(--surface);
}
html[data-theme="justwitter"] .btn-go-live {
  width: 100%;
  height: 52px;
  background: var(--red);
  border: 3px solid var(--black);
  border-radius: 6px;
  font-family: var(--font-display);
  font-size: .95rem;
  letter-spacing: .1em;
  color: var(--on-accent);
  box-shadow: 4px 4px 0 var(--black);
  cursor: pointer;
  transition: transform .1s, box-shadow .1s;
}
html[data-theme="justwitter"] .btn-go-live:hover {
  transform: translate(-2px, -2px);
  box-shadow: 6px 6px 0 var(--black);
}
html[data-theme="justwitter"] .btn-go-live:active {
  transform: translate(2px, 2px);
  box-shadow: 2px 2px 0 var(--black);
}
html[data-theme="justwitter"] .go-live-hint {
  font-family: var(--font-mono);
  font-size: .72rem;
  color: var(--ink-mid);
  text-align: center;
  margin: .5rem 0 0;
}
html[data-theme="justwitter"] .go-live-active {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: .75rem;
  flex-wrap: wrap;
}
html[data-theme="justwitter"] .live-pill,
html[data-theme="justwitter"] .live-badge {
  display: inline-flex;
  align-items: center;
  gap: .4rem;
  background: var(--black);
  border-radius: 999px;
  padding: .4rem .85rem;
  font-family: var(--font-display);
  font-size: .78rem;
  letter-spacing: .08em;
  color: var(--on-accent);
}
html[data-theme="justwitter"] .live-badge {
  padding: .25rem .6rem;
  font-size: .68rem;
  margin-left: .5rem;
  vertical-align: middle;
  border: none;
  cursor: pointer;
  transition: transform .1s;
}
html[data-theme="justwitter"] .live-badge:hover {
  transform: scale(1.05);
}
html[data-theme="justwitter"] .live-badge.active {
  background: var(--red);
}
html[data-theme="justwitter"] .live-pill-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--red);
  display: inline-block;
  animation: justwitterLivePulse 1.2s infinite;
}
@keyframes justwitterLivePulse {
  0%, 100% { opacity: 1; }
  50% { opacity: .3; }
}
html[data-theme="justwitter"] .live-pill-timer {
  color: var(--yellow);
  font-family: var(--font-mono);
}
html[data-theme="justwitter"] .go-live-url-row {
  display: flex;
  gap: .6rem;
  align-items: center;
  margin-top: .85rem;
}

/* ── Global on-air bar ─────────────────────────────────────────────────
   Sits fixed just below the header, visible on every view (see the HTML
   comment above #globalOnAirBar for why this exists as a separate
   element from .go-live-active instead of relying on it). Loud like the
   rest of justwitter's Go Live language: red fill, black bottom border,
   Bangers caps. */
html[data-theme="justwitter"] .on-air-bar {
  position: fixed;
  top: var(--hdr-h);
  left: 0;
  right: 0;
  z-index: 99; /* one below .hdr's z-index:100, so header stays on top */
  height: 40px;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: .6rem;
  background: var(--red);
  border-bottom: 3px solid var(--black);
  padding: 0 1rem;
}
/* BUGFIX: without this, the [hidden] attribute (set/removed by
   setGoLiveUiLive() in index.php's JS) has NO effect — a class selector
   like .on-air-bar and the UA stylesheet's [hidden] selector have equal
   specificity, and this stylesheet's display:flex above, being an author
   rule, wins over the browser-default [hidden]{display:none}. Net result
   without this override: the bar renders permanently regardless of live
   state, which is exactly the bug reported (bar showing with placeholder
   "--:--" on a page load where no one had gone live). This rule's higher
   specificity — [hidden] combined with the class — forces display:none
   whenever the attribute is present, restoring the intended behavior. */
html[data-theme="justwitter"] .on-air-bar[hidden] {
  display: none;
}
html[data-theme="justwitter"] .on-air-bar .live-pill-dot {
  background: var(--on-accent);
}
html[data-theme="justwitter"] .on-air-bar .on-air-label {
  font-family: var(--font-display);
  font-size: .85rem;
  letter-spacing: .1em;
  color: var(--on-accent);
}
html[data-theme="justwitter"] .on-air-bar .live-pill-timer {
  font-family: var(--font-mono);
  font-size: .8rem;
  color: var(--yellow);
}
html[data-theme="justwitter"] .on-air-bar .live-pill-timer.on-air-ending-soon {
  color: var(--on-accent);
  animation: justwitterLivePulse 1.2s infinite;
}
html[data-theme="justwitter"] .on-air-end-btn {
  height: 28px;
  padding: 0 .8rem;
  background: var(--black);
  border: none;
  border-radius: 4px;
  color: var(--on-accent);
  font-family: var(--font-display);
  font-size: .68rem;
  letter-spacing: .06em;
  cursor: pointer;
  margin-left: .4rem;
}
html[data-theme="justwitter"] .on-air-end-btn:hover {
  opacity: .85;
}