/* ═══════════════════════════════════════════════════════════════
   social.elarial.tech — "phosphor" terminal theme
   Mastodon 4.7.0
   Re-check after any major Mastodon upgrade; the variable block
   does the heavy lifting, the element rules are the fragile part.
   ═══════════════════════════════════════════════════════════════ */

/* ── Self-hosted JetBrainsMono Nerd Font ─────────────────────
   local() is listed FIRST on purpose: any machine with the font
   installed (i.e. yours) uses it directly and downloads nothing.
   The url() fallback is only fetched by devices without it.
   ~988KB per weight; JetBrains Mono is OFL-1.1 and the Nerd Font
   patch preserves that, so self-hosting is permitted.
   Drop the Bold @font-face if mobile load matters more than
   having a real bold; the browser will synthesise one.
   ──────────────────────────────────────────────────────────── */
@font-face {
  font-family: "JBM Nerd Web";
  src: local("JetBrainsMono Nerd Font"),
       local("JetBrainsMonoNerdFont-Regular"),
       local("JetBrainsMono NF"),
       url("/system/fonts/JetBrainsMonoNerdFont-Regular.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "JBM Nerd Web";
  src: local("JetBrainsMono Nerd Font Bold"),
       local("JetBrainsMonoNerdFont-Bold"),
       url("/system/fonts/JetBrainsMonoNerdFont-Bold.woff2") format("woff2");
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}

:root {
  --ph-bg:        #0b0f0b;   /* near-black, faint green cast   */
  --ph-surface:   #11170f;   /* columns, panels                */
  --ph-raised:    #161d14;   /* hovers, raised chrome          */
  --ph-border:    #263021;   /* 1px hairlines                  */
  --ph-text:      #c9d1c9;
  --ph-dim:       #7f8c7f;
  --ph-accent:    #3fb950;   /* phosphor                       */
  --ph-accent-dim:#2ea043;
  --ph-warn:      #d29922;
  --ph-err:       #f85149;
  /* "JBM Nerd Web" resolves to the locally-installed Nerd Font when
     present, else the self-hosted woff2 above. Plain "JetBrains Mono"
     is deliberately absent — it is NOT installed on discripper and
     falls back to Liberation Sans. */
  --ph-mono: "JBM Nerd Web", "JetBrainsMono Nerd Font",
             "CaskaydiaMono Nerd Font",
             ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}

/* Mastodon's own custom properties — the broadest lever we have. */
:root,
:root[data-theme="mastodon-dark"] {
  --background-color:                 var(--ph-bg);
  --background-color-tint:            var(--ph-surface);
  --background-filter:                blur(0px);
  --surface-background-color:         var(--ph-surface);
  --surface-variant-background-color: var(--ph-raised);
  --surface-variant-active-background-color: var(--ph-raised);
  --on-surface-color:                 var(--ph-text);
  --primary-text-color:               var(--ph-text);
  --secondary-text-color:             var(--ph-dim);
  --highlight-text-color:             var(--ph-accent);
  --error-color:                      var(--ph-err);
  --error-red:                        var(--ph-err);
  --border-color:                     var(--ph-border);
  --rich-text-container-color:        rgba(63, 185, 80, 0.10);
  --rich-text-text-color:             var(--ph-accent);
}

/* ── SECOND token family: Mastodon 4.7's "--color-*" set ──────
   The block above is the OLD family. 4.7 added a second one, and
   newer components read only that — the search field is the
   obvious casualty, but the sign-up panel copy and the loading
   placeholders were affected too.

   Mastodon declares it twice:

     [data-color-scheme=dark], html:not([data-color-scheme])  -> dark
     [data-color-scheme=light]                                -> light

   and for LOGGED-OUT visitors it chooses between them from the
   VISITOR's OS setting (the page carries data-system-theme="true").
   So anyone browsing in light mode got a white search box on a
   black page. Logged-in accounts never saw it, because an account's
   own appearance preference pins the scheme — which is why it
   looked like an incognito-only bug.

   Those selectors are specificity (0,1,0) and (0,1,1). The pair
   below is (0,1,1) and custom CSS loads after the theme, so it
   wins in BOTH schemes and the palette no longer depends on who
   is looking. Re-check these names after a major upgrade.
   ──────────────────────────────────────────────────────────── */
html[data-color-scheme],
html:not([data-color-scheme]) {
  --color-bg-primary:          var(--ph-bg);
  --color-bg-secondary:        var(--ph-surface);
  --color-bg-tertiary:         var(--ph-raised);
  --color-text-primary:        var(--ph-text);
  --color-text-secondary:      var(--ph-dim);
  --color-text-tertiary:       var(--ph-dim);
  --color-text-on-media:       var(--ph-text);
  --color-border-primary:      var(--ph-border);
  --color-border-secondary:    var(--ph-border);
  --color-border-brand:        var(--ph-accent-dim);
  --color-text-brand:          var(--ph-accent);
  --color-bg-brand-base:       var(--ph-accent);
  --color-bg-brand-softest:    rgba(63, 185, 80, 0.10);
  --color-text-on-brand-base:  var(--ph-bg);
  --color-text-error:          var(--ph-err);
  --color-text-success:        var(--ph-accent);
}

body,
body.app-body,
.ui,
.columns-area,
.columns-area__panels,
.columns-area__panels__main,
.columns-area__panels__pane__inner {
  background: var(--ph-bg);
  color: var(--ph-text);
}

/* ── Square everything off ─────────────────────────────────── */
.column > .scrollable,
.column-header,
.column-header__wrapper,
.drawer__inner,
.status,
.detailed-status,
.account__header,
.dropdown-menu,
.compose-form__wrapper,
.search__input,
.button,
.icon-button,
.card,
.notification,
.modal-root__modal,
.list,
.account-card {
  border-radius: 0 !important;
}

/* ── Monospace for structural type ─────────────────────────── */
.column-header,
.column-header__title,
.account__display-name strong,
.display-name__html,
.display-name__account,
.navigation-panel a,
.tabs-bar__link,
.button,
.status__relative-time,
.detailed-status__datetime,
.column-link,
.column-subheading {
  font-family: var(--ph-mono);
  letter-spacing: -0.01em;
}

.column-header,
.column-header__button,
.column-header__back-button {
  background: var(--ph-surface);
  color: var(--ph-accent);
  border-bottom: 1px solid var(--ph-border);
  text-transform: lowercase;
}
.column-header__title::before { content: "> "; color: var(--ph-accent-dim); }

/* ── Statuses ──────────────────────────────────────────────── */
.status,
.notification,
.account-card,
.conversation {
  background: var(--ph-surface);
  border-bottom: 1px solid var(--ph-border) !important;
}
.status:hover,
.notification:hover { background: var(--ph-raised); }

.status.status-direct { border-left: 2px solid var(--ph-warn); }
.detailed-status {
  background: var(--ph-raised);
  border: 1px solid var(--ph-border);
}

.status__content a,
.status__content a.unhandled-link,
.reply-indicator__content a,
a.mention {
  color: var(--ph-accent);
  text-decoration: none;
  border-bottom: 1px dotted var(--ph-accent-dim);
}
.status__content a:hover { background: rgba(63,185,80,.12); }

/* Hashtags read as tokens */
a.mention.hashtag, .hashtag {
  color: var(--ph-accent-dim);
  font-family: var(--ph-mono);
}

/* Code inside posts */
.status__content code,
.status__content pre {
  font-family: var(--ph-mono);
  background: #0d120c;
  border: 1px solid var(--ph-border);
  padding: 0 .25em;
}

/* ── Buttons ───────────────────────────────────────────────── */
.button {
  background: transparent;
  color: var(--ph-accent);
  border: 1px solid var(--ph-accent-dim);
  text-transform: lowercase;
  font-weight: 500;
}
.button:hover:not(:disabled) {
  background: var(--ph-accent);
  color: var(--ph-bg);
}
.button.button-secondary {
  color: var(--ph-dim);
  border-color: var(--ph-border);
}
.icon-button:hover { color: var(--ph-accent); background: rgba(63,185,80,.10); }
.icon-button.active,
.icon-button.star-icon.active { color: var(--ph-accent); }

/* ── Compose ───────────────────────────────────────────────── */
.drawer__inner,
.compose-form__wrapper,
.compose-form .autosuggest-textarea__textarea,
.compose-form .spoiler-input__input {
  background: var(--ph-surface);
  color: var(--ph-text);
  border: 1px solid var(--ph-border);
  font-family: var(--ph-mono);
}
.compose-form .autosuggest-textarea__textarea:focus {
  border-color: var(--ph-accent-dim);
  outline: none;
  box-shadow: 0 0 0 1px var(--ph-accent-dim);
}

/* ── Search field ──────────────────────────────────────────────
   Needs explicit colours even with the token block above: the
   theme hands it a 4px radius and Mastodon's own focus outline,
   neither of which matches the zero-radius hairline used
   everywhere else. Keep this together rather than folding the
   focus rule back in with compose — it was easy to miss there.
   ──────────────────────────────────────────────────────────── */
.search__input {
  background: var(--ph-surface);
  color: var(--ph-text);
  border: 1px solid var(--ph-border);
  border-radius: 0;
  font-family: var(--ph-mono);
}
.search__input::placeholder {
  color: var(--ph-dim);
  opacity: 1;             /* Firefox dims placeholders by default */
}
.search__input:focus {
  border-color: var(--ph-accent-dim);
  outline: none;
  box-shadow: 0 0 0 1px var(--ph-accent-dim);
}
/* The magnifier sits inside the field via absolute positioning. */
.search__icon .icon,
.search__icon svg { color: var(--ph-dim); }

/* ── Navigation ────────────────────────────────────────────── */
.navigation-panel,
.tabs-bar,
.drawer__header {
  background: var(--ph-surface);
  border-right: 1px solid var(--ph-border);
}
.column-link:hover { background: var(--ph-raised); color: var(--ph-accent); }
.column-link--transparent.active { color: var(--ph-accent); }

/* ── Profile header ────────────────────────────────────────── */
.account__header__bar,
.account__header__tabs__buttons,
.account__header__extra {
  background: var(--ph-surface);
  border-bottom: 1px solid var(--ph-border);
}
.account__header__tabs__name h1 { font-family: var(--ph-mono); }
.account__header__fields dt { color: var(--ph-dim); font-family: var(--ph-mono); }
.account__header__fields .verified {
  border-color: var(--ph-accent);
  background: rgba(63,185,80,.10);
}
.account__header__fields .verified a { color: var(--ph-accent); }

/* ── Scrollbars ────────────────────────────────────────────── */
.scrollable::-webkit-scrollbar-thumb { background: var(--ph-border); border-radius: 0; }
.scrollable::-webkit-scrollbar-thumb:hover { background: var(--ph-accent-dim); }
.scrollable { scrollbar-color: var(--ph-border) var(--ph-bg); }

/* ── Landing / about page ──────────────────────────────────── */
.landing-page__call-to-action,
.hero-widget__text,
.about__header__hero,
.about__section,
.server-banner {
  background: var(--ph-surface);
  border: 1px solid var(--ph-border);
  border-radius: 0;
}
h1, h2, h3, .about h3 { font-family: var(--ph-mono); }

/* Cursor blink on the compose placeholder — small flourish */
.compose-form .autosuggest-textarea__textarea::placeholder {
  color: var(--ph-dim);
}
.compose-form .autosuggest-textarea__textarea::placeholder::after {
  content: "_";
}

/* ═══════════════════════════════════════════════════════════════
   CRT OVERLAY
   ───────────────────────────────────────────────────────────────
   TOGGLE:  the "crt on/off" button, bottom-right of the screen
            (state persists per-browser in localStorage)
   ALSO:    Preferences → Appearance → "Reduce motion"
            Ticking that box disables this entire block.
            (It also respects the OS-level prefers-reduced-motion.)

   HARD OFF: delete everything from this banner to the end of file
            in Admin → Appearance → Custom CSS.

   All layers are pointer-events:none, so nothing here can ever
   intercept a click.
   ═══════════════════════════════════════════════════════════════ */

/* Layer 1 — aperture grille. Vertical RGB triads, very low alpha.
   This is the layer that sells "phosphor" rather than "stripes". */
html:not([data-crt="off"]) body:not(.reduce-motion)::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 9998;
  pointer-events: none;
  background: repeating-linear-gradient(
    90deg,
    rgba(255, 0, 0, 0.030) 0px, rgba(255, 0, 0, 0.030) 1px,
    rgba(0, 255, 0, 0.022) 1px, rgba(0, 255, 0, 0.022) 2px,
    rgba(0, 0, 255, 0.030) 2px, rgba(0, 0, 255, 0.030) 3px
  );
}

/* Layer 2 — scanlines + vignette + flicker. */
html:not([data-crt="off"]) body:not(.reduce-motion)::after {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 9999;
  pointer-events: none;
  background:
    radial-gradient(ellipse at center,
      transparent 52%,
      rgba(0, 0, 0, 0.28) 82%,
      rgba(0, 0, 0, 0.55) 100%),
    repeating-linear-gradient(
      to bottom,
      rgba(0, 0, 0, 0.17) 0px, rgba(0, 0, 0, 0.17) 1px,
      transparent 1px, transparent 3px
    );
  animation: ph-flicker 7s infinite;
  will-change: opacity;
}

/* Deliberately irregular so it reads as a failing tube, not a pulse. */
@keyframes ph-flicker {
  0%, 88%, 100% { opacity: 1; }
  89%  { opacity: 0.94; }
  90%  { opacity: 1; }
  93%  { opacity: 0.97; }
  94%  { opacity: 0.91; }
  95%  { opacity: 1; }
}

/* Phosphor bloom on structural type only — body text stays crisp,
   because glow on paragraph copy is unreadable after ten seconds. */
html:not([data-crt="off"]) body:not(.reduce-motion) .column-header__title,
html:not([data-crt="off"]) body:not(.reduce-motion) .account__header__tabs__name h1 {
  text-shadow: 0 0 5px rgba(63, 185, 80, 0.40);
}

/* Belt and braces: honour the OS setting even if Mastodon's class
   is absent (logged-out views, the About page, error pages). */
@media (prefers-reduced-motion: reduce) {
  body::before,
  body::after { display: none !important; }
  body .column-header__title,
  body .account__header__tabs__name h1 { text-shadow: none; }
}

/* ── CRT toggle button ─────────────────────────────────────────
   The element itself is created by /crt-toggle.js, which SWAG
   injects into <head>. Styling lives here rather than in the
   script because Mastodon's CSP forbids inline styles.
   ──────────────────────────────────────────────────────────── */
#crt-toggle {
  position: fixed;
  right: 12px;
  bottom: 12px;
  z-index: 10000;                 /* above both overlay layers */
  font-family: var(--ph-mono);
  font-size: 11px;
  line-height: 1;
  letter-spacing: 0.04em;
  padding: 7px 10px;
  color: var(--ph-accent);
  background: rgba(11, 15, 11, 0.88);
  border: 1px solid var(--ph-accent-dim);
  border-radius: 0;
  cursor: pointer;
  opacity: 0.45;
  transition: opacity .15s ease, background .15s ease, color .15s ease;
}
#crt-toggle:hover {
  opacity: 1;
  background: var(--ph-accent);
  color: var(--ph-bg);
}
#crt-toggle:focus-visible {
  opacity: 1;
  outline: 1px solid var(--ph-accent);
  outline-offset: 2px;
}
#crt-toggle[aria-pressed="false"] {
  color: var(--ph-dim);
  border-color: var(--ph-border);
}

/* Mobile: Mastodon goes single-column at 895px. The bottom-right corner
   is taken by the compose FAB, which itself floats above a full-width
   nav bar, so the default position would collide with both. Move to the
   left and lift clear of the bar (plus the iOS home-indicator inset). */
@media (max-width: 895px) {
  #crt-toggle {
    right: auto;
    left: 10px;
    bottom: calc(env(safe-area-inset-bottom, 0px) + 66px);
    font-size: 10px;
    padding: 6px 8px;
    opacity: 0.35;
  }
}

