/*
 * This is a manifest file that'll be compiled into application.css.
 *
 * With Propshaft, assets are served efficiently without preprocessing steps. You can still include
 * application-wide styles in this file, but keep in mind that CSS precedence will follow the standard
 * cascading order, meaning styles declared later in the document or manifest will override earlier ones,
 * depending on specificity.
 *
 * Consider organizing styles into separate files for maintainability.
 */

html,
body {
  overflow-x: clip; /* 'clip' creates no scroll container; prevents touch-panning on Android Chrome */
  max-width: 100vw;
}

/* Wrapped in Tailwind's own `base` layer (2026-08-21, Tailwind v4 migration fix) -- these rules
   were written pre-v4, when this file's plain/unlayered CSS naturally out-specificity'd Tailwind's
   own utility classes wherever intended (see the two comments below, both written assuming exactly
   that). Tailwind v4 wraps every utility class in native CSS `@layer utilities`, and unlayered CSS
   ALWAYS wins over ANY layered CSS regardless of specificity or source order -- so once the v4
   migration shipped, this file's bare `img,video,iframe{height:auto}` silently started winning
   over EVERY fixed-height Tailwind utility (h-9, h-10, h-[323px], etc.) site-wide, not just the
   feed contexts these rules were actually meant to target. Found live (2026-08-21): every
   non-square-source-image avatar rendered as an oval instead of a circle (object-cover + a fixed
   Tailwind height class produces a circle only when height genuinely resolves to that fixed value;
   with height:auto winning instead, the box follows the source image's own aspect ratio) --
   confirmed via real production Wellbeing Dashboard avatars, dozens of non-square photos all
   showing squished ovals. The Activities > Videos section not filling its container was the exact
   same root cause hitting `video`/`iframe` instead of `img`. Wrapping these rules in `@layer base`
   -- the same layer Tailwind's own Preflight img/video reset already lives in -- restores the
   original relationship: still correctly overrides Tailwind's OWN bare Preflight reset (by
   specificity, within the same layer), but is now correctly subordinate to `@layer utilities`
   again, exactly as it behaved under Tailwind v3. */
@layer base {
  img,
  video,
  iframe {
    max-width: 100%;
    height: auto;
  }

  /* Scoped to #feed_frame (post feeds, room feeds, search, bookmarks) only.
     Exclusive content carousel cards are NOT inside #feed_frame and must not
     be affected — they set explicit h-[323px] on images that must be respected.
     Specificity 0,2,2 beats Tailwind h-full (0,1,0) inside feed contexts. */
  #feed_frame li[role="article"] img,
  #feed_frame li[role="article"] video,
  #feed_frame li[role="article"] iframe {
    max-width: 100%;
    height: auto;
  }

  /* Specificity 0,3,2 — restores height:100% for multi-image grids within feeds.
     Grid containers have a fixed h-[300px] so height:100% correctly fills each cell. */
  #feed_frame li[role="article"] .grid img,
  #feed_frame li[role="article"] .grid video {
    height: 100%;
    object-fit: cover;
  }
}

/* Feed container turbo-frames must be block so #feed_frame fills its parent width.
   Inline frames (comment-count, reaction-count, bookmark) must NOT be affected —
   they live inside text-flow and must remain inline-level. */
turbo-frame#main_page_feed,
turbo-frame#search_results {
  display: block;
}

/* Comment form + comment list turbo-frames must be block, same reasoning as above — they wrap a
   whole form and a comment list, not inline text-flow content (unlike the comments_count_* frame,
   which intentionally stays inline since it renders inside a "View all comments (N)" link's own
   text — the prefix selectors below stop short of matching that one). IDs are per-record
   (dom_id(postable, :comment_form) / dom_id(postable, :comments)), hence attribute-prefix
   selectors rather than hardcoded IDs like above.
   Found live: with these left at the undeclared custom-element default of display:inline, the
   GIF picker popover opened from the comment form — itself position:fixed with a high z-index —
   still ended up visually buried under, and unclickable behind, its own sibling comment-list
   <ul>, because their shared inline ancestor put them in inline painting order rather than normal
   block stacking, regardless of the popover's own position/z-index. */
turbo-frame[id^="comment_form_post_"],
turbo-frame[id^="comment_form_content_"],
turbo-frame[id^="comments_post_"],
turbo-frame[id^="comments_content_"] {
  display: block;
}

#feed_frame {
  overflow-x: clip;
}

/* Belt-and-suspenders: every feed ul must be width-locked to #feed_frame.
   Prevents a "problem post" from driving the ul wider via intrinsic sizing. */
#feed_frame ul[role="feed"] {
  width: 100%;
  max-width: 100%;
  overflow-x: clip;
}

/* 'clip' does not create a scroll container or BFC, so it safely constrains
   image width without breaking IntersectionObserver (used by Ahoy visit tracking). */
#feed_frame li[role="article"] {
  overflow-x: clip;
  min-width: 0;
}

.trix-content {
  overflow-wrap: break-word;
  word-break: break-word;
}

li a {
  font-weight: 600;
  transition: color 0.2s ease-in-out;
}

li a:hover {
  color: #1d4ed8;
}

.emoji-explosion {
  position: fixed;
  font-size: 24px;
  pointer-events: none;
  transition: all 0.8s ease-out;
  opacity: 0.75;
  transform: translate(0, 0);
  z-index: 9999;
}

/* Sensory-calm mode: respects the OS-level prefers-reduced-motion setting
   automatically, and the html.reduced-motion class lets a user opt in
   in-app regardless of their OS setting (see ApplicationHelper#reduced_motion?). */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

html.reduced-motion *,
html.reduced-motion *::before,
html.reduced-motion *::after {
  animation-duration: 0.01ms !important;
  animation-iteration-count: 1 !important;
  transition-duration: 0.01ms !important;
  scroll-behavior: auto !important;
}

/* High-contrast mode: darkens the app's lighter muted text colors and
   enforces minimum touch-target sizes on interactive elements.
   Targets the specific utility classes the app uses rather than redefining
   the Tailwind palette, since those colors are baked in at build time. */
html.high-contrast .text-disable-text,
html.high-contrast .text-secondary-text,
html.high-contrast .text-taupe-gray,
html.high-contrast .text-silver-sand {
  color: #2d2d2d !important;
}

html.high-contrast .border-disable-background {
  border-color: #4a4a4a !important;
}

/* Excludes <a> tags — inline links inside post/comment text would break
   text flow with a blanket min-size. Buttons and checkbox/radio inputs
   are reliably standalone controls and safe to enlarge everywhere. */
html.high-contrast button,
html.high-contrast input[type="checkbox"],
html.high-contrast input[type="radio"] {
  min-height: 44px;
  min-width: 44px;
}
