/*
 * 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.
 */

/* Orbitron font - self-hosted variable font for sci-fi headings */
/* Using individual weight declarations for broader browser compatibility */
@font-face {
  font-family: 'Orbitron';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("/assets/orbitron-v35-latin-3ec90f13.woff2") format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'Orbitron';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("/assets/orbitron-v35-latin-3ec90f13.woff2") format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'Orbitron';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url("/assets/orbitron-v35-latin-3ec90f13.woff2") format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'Orbitron';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url("/assets/orbitron-v35-latin-3ec90f13.woff2") format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* SparTakus font - sci-fi font with sharp angular design */
@font-face {
  font-family: 'SparTakus';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("/assets/spartakus-240d40bc.ttf") format('truetype');
}

@font-face {
  font-family: 'SparTakus';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url("/assets/spartakus-240d40bc.ttf") format('truetype');
}

/* Custom font utility class */
.font-spartakus {
  font-family: 'SparTakus', sans-serif !important;
}

/* Markdown content styles */
.markdown-content {
  line-height: 1.6;
}

.markdown-content h1 {
  font-size: 1.75rem;
  font-weight: 700;
  margin-top: 1.5rem;
  margin-bottom: 0.75rem;
}

.markdown-content h2 {
  font-size: 1.5rem;
  font-weight: 600;
  margin-top: 1.25rem;
  margin-bottom: 0.5rem;
}

.markdown-content h3 {
  font-size: 1.25rem;
  font-weight: 600;
  margin-top: 1rem;
  margin-bottom: 0.5rem;
}

.markdown-content h4,
.markdown-content h5,
.markdown-content h6 {
  font-size: 1.1rem;
  font-weight: 600;
  margin-top: 0.75rem;
  margin-bottom: 0.5rem;
}

.markdown-content.flat-headings h1,
.markdown-content.flat-headings h2,
.markdown-content.flat-headings h3,
.markdown-content.flat-headings h4,
.markdown-content.flat-headings h5,
.markdown-content.flat-headings h6 {
  font-size: 1rem;
  font-weight: 700;
  line-height: 1.6;
  margin-top: 0.75rem;
  margin-bottom: 0.5rem;
}

.markdown-content p {
  margin-bottom: 0.75rem;
}

.markdown-content ul,
.markdown-content ol {
  margin-left: 1.5rem;
  margin-bottom: 0.75rem;
}

.markdown-content ul {
  list-style-type: disc;
}

.markdown-content ol {
  list-style-type: decimal;
}

.markdown-content li {
  margin-bottom: 0.25rem;
}

.markdown-content blockquote {
  border-left: 4px solid #64748b;
  padding-left: 1rem;
  margin-left: 0;
  margin-bottom: 0.75rem;
  font-style: italic;
  font-size: 0.85em;
  color: #64748b;
}

.dark .markdown-content blockquote {
  border-left-color: #94a3b8;
  color: #94a3b8;
}

.markdown-content code {
  background-color: #f1f5f9;
  padding: 0.125rem 0.375rem;
  border-radius: 0.25rem;
  font-size: 0.875em;
  font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
}

.dark .markdown-content code {
  background-color: #1e293b;
}

.markdown-content pre {
  background-color: #1e293b;
  color: #e2e8f0;
  padding: 1rem;
  border-radius: 0.5rem;
  overflow-x: auto;
  margin-bottom: 0.75rem;
}

.markdown-content pre code {
  background-color: transparent;
  padding: 0;
  font-size: 0.875rem;
}

.markdown-content a {
  color: #0f4b91;
  text-decoration: underline;
}

.dark .markdown-content a {
  color: #38bdf8;
}

.markdown-content hr {
  border: none;
  border-top: 1px solid #e2e8f0;
  margin: 1rem 0;
}

.dark .markdown-content hr {
  border-top-color: #334155;
}

.markdown-content del {
  text-decoration: line-through;
  opacity: 0.7;
}

.markdown-content sup {
  font-size: 0.75em;
  vertical-align: super;
}

.markdown-content table {
  width: 100%;
  border-collapse: collapse;
  margin-bottom: 0.75rem;
  font-size: 0.875rem;
  display: block;
  overflow-x: auto;
}

@media (max-width: 640px) {
  .markdown-content th,
  .markdown-content td {
    padding: 0.375rem 0.5rem;
    font-size: 0.8125rem;
  }
}

.markdown-content th,
.markdown-content td {
  border: 1px solid #cbd5e1;
  padding: 0.5rem 0.75rem;
  text-align: left;
}

.dark .markdown-content th,
.dark .markdown-content td {
  border-color: #475569;
}

.markdown-content th {
  background-color: #f1f5f9;
  font-weight: 600;
}

.dark .markdown-content th {
  background-color: #1e293b;
}

.markdown-content tr:nth-child(even) td {
  background-color: #f8fafc;
}

.dark .markdown-content tr:nth-child(even) td {
  background-color: #0f172a;
}

/* Custom fast tooltips */
[data-tooltip] {
  position: relative;
}

[data-tooltip]::after {
  content: attr(data-tooltip);
  position: absolute;
  bottom: 100%;
  left: 50%;
  transform: translateX(-50%);
  padding: 0.375rem 0.625rem;
  background-color: #1e293b;
  color: #f1f5f9;
  font-size: 0.75rem;
  font-weight: 500;
  white-space: nowrap;
  border-radius: 0.375rem;
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.15s ease, visibility 0.15s ease;
  pointer-events: none;
  z-index: 9999;
  margin-bottom: 0.375rem;
}

[data-tooltip]:hover::after {
  opacity: 1;
  visibility: visible;
}

.dark [data-tooltip]::after {
  background-color: #475569;
  color: #f1f5f9;
}

/* Galaxy loading spinner - shown when Turbo frame is busy */
@keyframes galaxy-spinner-fade-in {
  from { opacity: 0; }
  to { opacity: 1; }
}

turbo-frame[busy] .galaxy-loading-overlay {
  display: flex !important;
  animation: galaxy-spinner-fade-in 0.15s ease 0.3s backwards;
}

turbo-frame[busy] .galaxy-table-content {
  transition: opacity 0.15s ease 0.3s;
  opacity: 0.4;
  pointer-events: none;
}

/* Prevent CSS tooltip when Stimulus controller is active */
[data-controller~="tooltip"]::after {
  display: none !important;
}

/* ============================================================
   TOUCH TEXT-ENTRY ZOOM GUARD
   ============================================================ */

/*
   Safari on iOS zooms the ENTIRE page in when a text control it is about to
   focus would render below 16px, and it never zooms back out -- not on blur,
   not on submit. On a full-screen surface like the chat dock that leaves the
   player stranded in a magnified, horizontally scrolling page with no obvious
   way back.

   The guard is keyed to the POINTER, not to a width breakpoint, and that is the
   whole point of it. Per-element `text-base md:text-sm` looks like it covers
   this, but `md` is 768px of CSS width, which every phone in landscape and
   every tablet in either orientation clears -- so exactly the same touch device
   that needs 16px drops to 14px by rotating. `(hover: none) and
   (pointer: coarse)` asks the question that actually matters: is a finger and a
   software keyboard going to be used here?

   It sits outside @layer on purpose. Tailwind v4 emits its utilities inside
   `@layer utilities`, and unlayered rules beat every layered one regardless of
   specificity or source order, so this wins over `text-sm` / `text-xs` on the
   element without !important and without touching 224 form controls by hand.
   Most inputs in this app carry no text-* class at all and inherit their size
   from a `text-sm` ancestor (Tailwind's preflight sets `font: inherit` on form
   controls), which no per-element audit would have caught anyway.

   max() rather than a bare 16px so a player who has raised their browser's
   default text size keeps the larger value; 16px is a floor, not a target.
   Buttons, checkboxes, radios, ranges, colors and file pickers are excluded --
   they never raise a keyboard, and pinning their font-size resizes the control.
*/
@media (hover: none) and (pointer: coarse) {
  textarea,
  select,
  input:not([type="button"]):not([type="checkbox"]):not([type="color"]):not([type="file"]):not([type="image"]):not([type="radio"]):not([type="range"]):not([type="reset"]):not([type="submit"]) {
    font-size: max(1rem, 16px);
  }
}

/* ============================================================
   Public homepage (landing page) — all classes prefixed .home-
   or .font-orbitron; nothing here touches game UI.
   ============================================================ */

.font-orbitron {
  font-family: 'Orbitron', sans-serif;
}

/* Blinking terminal caret */
.home-caret {
  display: inline-block;
  margin-left: 2px;
  animation: home-blink 1.1s steps(1) infinite;
}

@keyframes home-blink {
  50% { opacity: 0; }
}

/* LIVE indicator dot */
.home-pulse-dot {
  display: inline-block;
  width: 8px;
  height: 8px;
  border-radius: 9999px;
  background: #E0F7FA;
  box-shadow: 0 0 8px rgba(224, 247, 250, 0.9);
  animation: home-pulse 2s ease-in-out infinite;
}

@keyframes home-pulse {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.35; }
}

/* Key-art card: real game art with a slow zoom on hover */
.home-card {
  border: 1px solid rgba(224, 247, 250, 0.14);
  border-radius: 0.5rem;
  overflow: hidden;
  background: #05080a;
  transition: border-color 0.2s ease, box-shadow 0.2s ease;
}

.home-card:hover {
  border-color: rgba(224, 247, 250, 0.4);
  box-shadow: 0 0 30px rgba(224, 247, 250, 0.1);
}

.home-card-art {
  transition: transform 0.6s ease;
}

.home-card:hover .home-card-art {
  transform: scale(1.05);
}

@media (prefers-reduced-motion: reduce) {
  .home-caret,
  .home-pulse-dot {
    animation: none;
  }

  .home-card-art,
  .home-card:hover .home-card-art {
    transition: none;
    transform: none;
  }
}

/* ============================================================
   ALLIANCE CHAT DOCK
   ============================================================ */

/*
   The floating chat bubble is only harmless when the viewport is wide enough to
   give it a gutter to sit in. <main> caps at max-w-7xl (1280px) and the bubble
   claims 72px of one gutter (a 3.5rem circle plus a 1rem inset), so it clears
   the content column only from 1280 + 2*72 = 1424px up. <main> is mx-auto, so
   the two gutters are symmetric and the threshold is the same on either side.
   Below it -- every phone, both iPad orientations, and any half-width desktop
   window -- the circle sits ON the page and permanently covers a piece of
   whatever is being read.

   Under the threshold it tucks half of itself past the docked edge and becomes a
   pull tab: the overlap drops from 72px to 28px, and the half-disc that remains
   reads as a drawer handle rather than as something dropped on the content.
   position:fixed boxes do not extend the document's scrollable overflow, so
   hanging off the edge cannot introduce a horizontal scrollbar.

   WHICH edge is the player's choice: data-chat-side on the dock root, from the
   chat_dock_left flag (Settings -> Interface). Right is the default, and the
   [data-chat-side="left"] rules below are its mirror image, nothing more.

   Two reasons this is CSS and not utility classes on the element: 1423px is not
   a Tailwind screen, and the offsets being overridden used to be an inline style
   that no class could beat. Load order is not a hazard -- Tailwind v4 emits its
   utilities inside @layer utilities, and unlayered rules like these outrank
   every layer regardless of source order, even though :app links this file
   first.
*/
.chat-dock-anchor {
  right: max(1rem, env(safe-area-inset-right, 0px));
  bottom: max(1rem, calc(env(safe-area-inset-bottom, 0px) + 0.5rem));
}

/* `right: auto` is load-bearing, not tidiness. The anchor has no width, so a
   fixed box with BOTH offsets set resolves its width to the whole viewport --
   an invisible 3.5rem-tall strip at z-30 eating every click along the bottom of
   the page, while the flex button inside still renders in the right place and
   looks perfectly fine. (It is repeated in the media query below purely so that
   block reads standalone -- this rule already outranks the one it overrides
   there, so the repeat does no work.) */
[data-chat-side="left"] .chat-dock-anchor {
  right: auto;
  left: max(1rem, env(safe-area-inset-left, 0px));
}

@media (max-width: 1423px) {
  /* Half of the bubble's 3.5rem width. Raise it toward 3.5rem to hide more of
     the circle, lower it to show more; the icon and badge below follow along. */
  .chat-dock-anchor {
    --chat-dock-tuck: 1.75rem;
    right: calc(env(safe-area-inset-right, 0px) - var(--chat-dock-tuck));
  }

  /* Re-centre the glyph in the half that is still on screen, and trim it so it
     is not flush against both edges of a 28px-wide tab. */
  .chat-dock-icon {
    width: 1.375rem;
    height: 1.375rem;
    transform: translateX(calc(-1 * var(--chat-dock-tuck) / 2));
  }

  /* Tailwind pins the unread/mention badge to the top-RIGHT corner, which for a
     right-docked bubble is the half that just went off screen. Move it to the
     visible side: without this the count and the mention alert silently stop
     being visible on exactly the devices this rule exists for. Left mode has
     the opposite problem and undoes this below. */
  .chat-dock-badge {
    right: auto;
    left: -0.25rem;
  }

  /* The left mirror has to be repeated INSIDE this media query. A media query
     contributes nothing to specificity and specificity outranks source order,
     so the base [data-chat-side="left"] rule above -- (0,2,0) against this
     block's (0,1,0) -- would otherwise win at every width and the bubble would
     simply never tuck: a full circle parked on the content column on exactly
     the narrow screens this block exists for. */
  [data-chat-side="left"] .chat-dock-anchor {
    right: auto;
    left: calc(env(safe-area-inset-left, 0px) - var(--chat-dock-tuck));
  }

  /* --chat-dock-tuck is still inherited from .chat-dock-anchor above: the
     cascade resolves per declaration, and a rule that sets only left/right
     does not disturb the custom property. Only the sign flips here; the
     width/height shrink above still applies. */
  [data-chat-side="left"] .chat-dock-icon {
    transform: translateX(calc(var(--chat-dock-tuck) / 2));
  }

  /* Mirror of the mirror: the rule above moved the badge to the LEFT corner,
     which is the half that is off screen when the tab hangs off the left edge.
     `left: auto` is required -- with a definite width and both offsets set the
     box is over-constrained and LTR drops `right`, silently leaving the count
     and the mention alert invisible. */
  [data-chat-side="left"] .chat-dock-badge {
    left: auto;
    right: -0.25rem;
  }
}
