/* site.css — small extensions to victoria.css for site-shell components the
   mock doesn't define: the authenticated user's dropdown menu, the Django
   messages framework, and the stale-data banner (docs/PAGES.md §0).
   victoria.css itself is ported verbatim and never forked (AGENTS.md §6);
   new components live here instead, using the same `v-` vocabulary and the
   existing design tokens. */

/* Alpine hides x-cloak elements only once it boots; this rule hides them
   before that so the user menu never flashes open on load. */
[x-cloak] {
  display: none !important;
}

/* `.v-btn`'s own `display: inline-flex` (victoria.css) and the browser's
   default `[hidden] { display: none }` rule have equal CSS specificity,
   and an author stylesheet always beats the user-agent one — so a hidden
   `.v-btn` stayed visible regardless of source order (found via the
   no-JS screenshot check for the map panel's collapse/expand toggle,
   feedback-2026-08-18 WO-F4.1; also affects map-viewer.js's pre-existing
   fullscreen-button hide when the browser has no Fullscreen API). */
.v-btn[hidden] {
  display: none !important;
}

/* --- User chip dropdown --------------------------------------------------- */

.v-user-menu {
  position: relative;
}
.v-user-menu img.v-avatar {
  object-fit: cover;
}
.v-user-menu__panel {
  position: absolute;
  top: calc(100% + 8px);
  right: 0;
  z-index: 60;
  min-width: 170px;
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: var(--v-2);
  background: var(--v-panel-dark-2);
  border: var(--v-border);
  border-radius: var(--v-radius);
  box-shadow: var(--v-shadow-lg);
}
.v-user-menu__panel form {
  margin: 0;
}
.v-user-menu__item {
  display: block;
  width: 100%;
  padding: var(--v-2) var(--v-3);
  font-family: var(--v-font-body);
  font-size: var(--v-fs-sm);
  color: var(--v-cream);
  text-align: left;
  background: transparent;
  border: none;
  border-radius: var(--v-radius);
  cursor: pointer;
}
.v-user-menu__item:hover {
  background: rgba(194, 161, 90, 0.16);
  color: var(--v-gold-bright);
  text-decoration: none;
}

/* --- Django messages framework -------------------------------------------- */

.v-messages {
  padding-block: var(--v-4) 0;
  display: flex;
  flex-direction: column;
  gap: var(--v-2);
}
.v-message {
  padding: var(--v-3) var(--v-4);
  border: 1px solid var(--v-gold-dim);
  border-left-width: 4px;
  border-radius: var(--v-radius);
  background: var(--v-panel-dark);
  color: var(--v-cream);
  font-size: var(--v-fs-sm);
}
.v-message--success {
  border-left-color: var(--v-green);
}
.v-message--error {
  border-left-color: var(--v-red);
}
.v-message--warning {
  border-left-color: var(--v-gold);
}
.v-message--info,
.v-message--debug {
  border-left-color: var(--v-blue);
}

/* --- Footer health line (PAGES.md §0) ------------------------------------- */

.v-health {
  margin: 0 0 var(--v-2);
}
.v-health__dot {
  display: inline-block;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  margin-right: 4px;
  vertical-align: baseline;
}
.v-health__dot--live {
  background: var(--v-green);
}
.v-health__dot--refreshing {
  background: var(--v-gold);
}
.v-health__dot--unavailable {
  background: var(--v-cream-2);
  opacity: 0.5;
}

/* --- Stale-data banner (PAGES.md §0) -------------------------------------- */

.v-stale-banner {
  padding: var(--v-3) var(--v-4);
  text-align: center;
  font-size: var(--v-fs-sm);
  color: var(--v-cream);
  background: var(--v-maroon-2);
  border-bottom: 1px solid var(--v-gold-dim);
}

/* --- Notice-page shell (error pages, interstitials) ------------------------ */

/* The centred framed-card layout the mock uses inline on its 404; shared by
   the error pages so the shell isn't copy-pasted per template. */
.v-notice-page {
  display: grid;
  place-items: center;
  min-height: 70vh;
}
.v-notice-page > .v-paper {
  max-width: 520px;
}

/* --- Pagination (templates/common/pagination.html) ------------------------- */

.v-pager {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--v-2);
  padding-block: var(--v-4);
  flex-wrap: wrap;
}
.v-pager__pages {
  display: inline-flex;
  align-items: center;
  gap: var(--v-1);
}
.v-pager__current {
  min-width: 28px;
  text-align: center;
}
.v-pager__ellipsis {
  color: var(--v-ink-2);
  padding-inline: var(--v-1);
}

/* === Phase 2: timeline — owned by apps/timeline ========================== */

/* The whole card is the expand affordance (PAGES.md §2 "cards are
   clickable"): the title link stretches over the card; buttons and the
   title itself sit above the stretched hit area. */
.v-event__card {
  position: relative;
}
.v-event__title a::after {
  content: "";
  position: absolute;
  inset: 0;
}
.v-event__card .v-btn,
.v-event__title a {
  position: relative;
  z-index: 1;
}
.v-event__title a::after {
  z-index: 0;
}

/* Era header — breaks out of the year gutter to span the full spine width,
   marking where the stream crosses into the era's span (PAGES.md §2). */
.v-timeline__era {
  position: relative;
  margin: var(--v-6) 0 var(--v-4) -92px;
  padding: var(--v-3) var(--v-4);
  background: rgba(43, 36, 28, 0.06);
  border-top: var(--v-border);
  border-bottom: var(--v-border);
}
.v-timeline__era:first-child {
  margin-top: 0;
}
.v-timeline__era-title {
  margin: 0;
  font-family: var(--v-font-display);
  font-size: var(--v-fs-lg);
}
.v-timeline__era-years {
  font-size: var(--v-fs-sm);
  color: var(--v-ink-3);
  font-weight: normal;
}
.v-timeline__era-desc {
  margin-top: var(--v-2);
  font-size: var(--v-fs-sm);
  color: var(--v-ink-2);
}

/* Soft-deleted events, staff view only (PAGES.md §2) — dimmed, never hidden
   from the staff who need the Restore button. */
.v-event--hidden .v-event__card {
  opacity: 0.55;
}
.v-tag--muted {
  color: var(--v-ink-3);
}

/* A real uploaded thumbnail dropped into the mock's placeholder slot. */
img.v-event__thumb {
  object-fit: cover;
  border-radius: var(--v-radius);
}

/* Expanded card: room for the full body, image, and staff actions. */
.v-event__card--expanded {
  flex-direction: column;
}
.v-event__image {
  display: block;
  max-width: 100%;
  height: auto;
  border-radius: var(--v-radius);
  margin: var(--v-3) 0;
}
.v-event__meta {
  margin: 0 0 var(--v-2);
}
.v-event__prose :is(p, ul, ol, blockquote, table) {
  margin: 0 0 var(--v-3);
}
.v-event__prose img {
  max-width: 100%;
  height: auto;
  border-radius: var(--v-radius);
}

/* The inline add/edit form card mirrors the mock's admin panel fields
   inside a timeline card instead of a separate panel (edit replaces the
   card in place — PAGES.md §2). */
.v-event__card--form {
  flex-direction: column;
}
.v-field-error {
  color: var(--v-red);
  font-size: var(--v-fs-xs);
}

/* Events filter toolbar's region checkbox group (WO-H, phase-5.5 R4-14) —
   replaces the old `<select multiple>`, which a plain click could never
   fully unselect. `.v-row` (victoria.css) already wraps, but a bare
   `width:auto` field can grow as wide as the whole panel body before any
   wrapping kicks in, so cap the group's width itself — ten seeded regions
   today, more expected in production (PAGES.md §2) — so a long list
   breaks into several short lines inside the collapsible panel instead of
   one wide ragged row. */
.v-filter-regions {
  max-width: 420px;
  gap: var(--v-1) var(--v-4);
}
.v-filter-regions label {
  display: inline-flex;
  align-items: center;
  gap: var(--v-1);
  font-size: var(--v-fs-sm);
  white-space: nowrap;
}

@media (max-width: 820px) {
  .v-timeline__era {
    margin-left: calc(-1 * var(--v-5));
  }
}

/* === Phase 2: world map viewer — owned by apps/world ===================== */

/* The pan/zoom container: a fixed-aspect frame that clips the zoomed/panned
   stage. panzoom (static/js/map-viewer.js) attaches to `__stage` and drives
   it with a CSS transform; the frame just clips and anchors the controls. */
.v-map-viewer__frame {
  position: relative;
  overflow: hidden;
  border-radius: var(--v-radius);
  background: #0b0906;
  aspect-ratio: 16 / 9;
  max-height: 78vh;
}
.v-map-viewer__stage {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  transform-origin: 0 0;
  cursor: grab;
  touch-action: none;
}
.v-map-viewer__stage:active {
  cursor: grabbing;
}
.v-map-viewer__img {
  display: block;
  width: 100%;
  height: auto;
  user-select: none;
  -webkit-user-drag: none;
}
.v-map-viewer__controls {
  position: absolute;
  right: var(--v-3);
  bottom: var(--v-3);
  z-index: 2;
  display: flex;
  gap: var(--v-2);
}
.v-map-viewer__controls .v-btn {
  min-height: 36px;
  padding: var(--v-1) var(--v-3);
}
.v-map-panel__caption {
  margin: var(--v-2) 0 0;
}

/* The map panel's old cropped-strip collapse (PAGES.md §3.1,
   feedback-2026-08-18 WO-F4.1) is gone — phase-5.5 fourth round replaced
   it with a real `<details>`/`<summary>` (`{% collapse_panel %}`, see the
   "Collapsible panel — shared" block below), which hides the whole body
   natively instead of cropping it to a fixed-height strip. Nothing sets
   `.v-map-panel--collapsible` or `.is-collapsed` any more. */

/* Fullscreen: the frame fills the viewport; the small vendor-prefixed
   selectors cover older WebKit (map-viewer.js falls back the same way). */
.v-map-viewer__frame:fullscreen,
.v-map-viewer__frame:-webkit-full-screen {
  aspect-ratio: auto;
  max-height: none;
  width: 100vw;
  height: 100vh;
  border-radius: 0;
}

/* The era-maps strip (contract with apps/timeline — templates/world/era_maps.html) */
.v-era-maps {
  display: flex;
  flex-wrap: wrap;
  gap: var(--v-3);
}
.v-era-maps__item {
  display: flex;
  align-items: center;
  gap: var(--v-2);
  padding: var(--v-1) var(--v-2);
  border: 1px solid var(--v-gold-dim);
  border-radius: var(--v-radius);
  text-decoration: none;
  color: inherit;
  background: rgba(0, 0, 0, 0.15);
}
.v-era-maps__item:hover {
  border-color: var(--v-gold);
  text-decoration: none;
}
.v-era-maps__thumb {
  width: 64px;
  height: 40px;
  object-fit: cover;
  border-radius: 2px;
  display: block;
  flex: none;
}
.v-era-maps__meta {
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.v-era-maps__label {
  font-family: var(--v-font-display);
  font-size: var(--v-fs-sm);
}

/* --- Collapsible panel — shared (WO-F9 feedback-2026-08-18; generalized
   phase-5.5 fourth round, "allow minimizing the world map and the
   leaderboard like we can minimize the filter tab") ----------------------- */
/* Two components share this native-<details>-based collapse: the original
   filter toolbar (`.v-filter-toggle`, apps/common/templatetags/
   filter_toolbar.py — world directory, character database, timeline) and
   the newer generic panel (`.v-collapse`, apps/common/templatetags/
   collapse_panel.py — the world map panel and the Leaderboards section).
   Both wrap a page's own content in <details>/<summary> so it starts
   hidden behind one clickable head, no JS required — a no-JS visitor gets
   a real, always-openable control either way. Built on `.v-panel`/
   `.v-panel__head`/`.v-panel__body` (victoria.css) for the frame/surface;
   only the summary's disclosure triangle (and, for the filter toolbar
   only, its count badge) are new.

   The two components render genuinely different classes on purpose —
   `filter_toolbar.py`'s markup (and this file's rules for it) predate
   `collapse_panel.py` and are left exactly as WO-F9 shipped them, so nothing
   about the filter toolbar's rendered appearance changes here — but the
   caret/marker/summary mechanics are identical, so those rules are grouped
   under both selectors together below instead of being duplicated as a
   second, separate block. Only `.v-filter-toggle` gets the count badge
   rule at the end: neither `.v-collapse` caller has a count to show. */
details.v-filter-toggle,
details.v-collapse {
  overflow: hidden;
}
.v-filter-toggle__summary,
.v-collapse__summary {
  cursor: pointer;
  user-select: none;
  list-style: none;
}
.v-filter-toggle__summary::-webkit-details-marker,
.v-collapse__summary::-webkit-details-marker {
  display: none;
}
.v-filter-toggle__summary::marker,
.v-collapse__summary::marker {
  content: "";
}
.v-filter-toggle__caret,
.v-collapse__caret {
  display: inline-block;
  flex: none;
  width: 0.6em;
  transition: transform 0.15s ease;
  transform: rotate(0deg);
}
.v-filter-toggle__caret::before,
.v-collapse__caret::before {
  content: "\25B8"; /* ▸ */
}
details.v-filter-toggle[open] > .v-filter-toggle__summary .v-filter-toggle__caret,
details.v-collapse[open] > .v-collapse__summary .v-collapse__caret {
  transform: rotate(90deg);
}
.v-filter-toggle__summary:focus-visible,
.v-collapse__summary:focus-visible {
  outline: 2px solid var(--v-gold-bright);
  outline-offset: -2px;
}
/* Decorative pill echoing the count that already sits in the summary's own
   text ("Filters (3)") — reinforcement for a sighted user skimming the
   page, never the only place the number appears. A real `aria-hidden`
   `<span>` (filter_toolbar.py), not CSS `content: attr()`: Chromium folds
   generated pseudo-element content into the accessible name, which would
   have announced the count twice ("Filters (1) 1" — caught via an
   accessibility-tree dump during WO-F9 QA). `aria-hidden` on a real node
   is the one way to keep it decoration-only. `.v-collapse` has no
   equivalent — its callers show a fixed title, not a count. */
.v-filter-toggle__badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 1.4em;
  padding: 0 5px;
  margin-left: auto;
  border: 1px solid var(--v-gold-dim);
  border-radius: 999px;
  background: var(--v-gold-dim);
  color: var(--v-panel-dark);
  font-size: var(--v-fs-xs);
  font-weight: 700;
}

/* === Country sheet — owned by apps/world ================================= */

/* Overview pane's Nation/Economy-Ruler-PowerBloc-Government two-column
   layout (world/_country_overview.html, WO-F5) — previously an inline
   `grid-template-columns:minmax(220px,1fr) minmax(0,1.4fr)` on a bare
   `.v-grid`, which a media query cannot override (an element's own inline
   style always wins over any stylesheet rule short of `!important`). At
   375px the 220px minimum alone exceeds the available content width, so
   the second column was forced into ~90px: every info-box value wrapped
   one word per line and the trailing text was cut off entirely
   (`Cash 71...K`, `CONCE...RT OF THE ATLANT...` — feedback-2026-08-18
   mobile pass, USA/SWE/GBR sheets). A named class moves the two-column
   layout into the stylesheet where the existing `.v-shell`-style pattern
   (victoria.css §16, "Responsive") can collapse it to one column below
   the tablet breakpoint. */
.v-overview-grid {
  grid-template-columns: minmax(220px, 1fr) minmax(0, 1.4fr);
}
@media (max-width: 820px) {
  .v-overview-grid {
    grid-template-columns: minmax(0, 1fr);
  }
}

/* Hero CTA row (`content/partials/hero.html`, phase-5.5 item R4-3, owner
   decision) — "Join the campaign" moves to the top on a phone-width
   viewport, desktop order unchanged. Two of the row's three buttons
   ("Join", "Download the Mod") are conditionally rendered, so the DOM is
   `[Read, Join, Download]`, `[Read, Download]`, or `[Read, Join]`
   depending on viewer/config state — an `:nth-child()` `order` rule would
   therefore pick the wrong element in at least one state. `order` is keyed
   to `.v-hero-cta__join`, a class on the Join button itself, so it is
   correct in every DOM state regardless of which siblings rendered; the
   other two buttons need no class at all. `justify-content:center` was
   moved here from the row's inline `style=` — an inline style outranks any
   stylesheet rule, so leaving it inline would have blocked this override. */
.v-hero-cta {
  justify-content: center;
}
@media (max-width: 520px) {
  .v-hero-cta {
    flex-direction: column;
    align-items: stretch;
  }
  .v-hero-cta__join {
    order: -1;
  }
}

/* Pagination links (`.v-pager`, templates/common/pagination.html) reuse
   `.v-btn--sm` (min-height 34px), fine with a mouse but tight for a thumb
   once the "1"/"2"-style single-digit pages sit only `var(--v-1)` (4px)
   apart — confirmed via bounding-box measurement at 375px (single-digit
   page links measured ~33x34px). Scoped to `.v-pager` so the very common
   `.v-btn--sm` elsewhere (inline card actions, admin bar) keeps its
   desktop-tuned size. */
@media (max-width: 820px) {
  .v-pager { gap: var(--v-3); }
  .v-pager__pages { gap: var(--v-2); }
  .v-pager .v-btn--sm {
    min-height: 44px;
    min-width: 44px;
    padding-inline: var(--v-3);
  }
}

/* R5-3 (owner, 2026-08-19): a Goals-pane trait/role chip
   (`templates/council/_goal_card_body.html`'s `.v-goal-tag`, only the
   role/trait tags — not the "Rewarded"/"Locked"/"Scales with level" chips
   beside them, which are always short) could overflow its card. Most of
   that length is now gone (`apps.council.pane_goals._collapse_tier_group`
   turns a tiered trait ladder into one base label), but a genuinely
   disjoint trait/role group can still run long, and the fix must hold for
   that case regardless of the wording. Root cause: `.v-tag` in
   victoria.css sets `white-space: nowrap`, which is right for the SHORT
   chips it was designed for (a role name, a country tag) but forces a
   long joined chip to keep its full one-line width no matter how narrow
   its flex row is — the containing `.v-row` already wraps chips onto new
   lines (`flex-wrap: wrap`, victoria.css), it just can't wrap the TEXT
   inside one chip that is itself too wide.

   `.v-tag` itself is the ported design system and must not be forked
   (AGENTS.md §6) — a global `white-space: normal` there would also let
   every short chip sitewide (roster role chips, country-tag chips,
   category tags) reflow it never needs to. `.v-goal-tag` is the
   project-authored class the goal-card template adds alongside `.v-tag`
   for exactly its long trait/role chips, so this rule reaches only them:
   `white-space: normal` lets the chip's own text wrap, and `max-width:
   100%` (with the flex item's `min-width` reset off its nowrap-driven
   intrinsic width) stops the chip claiming more width than its row has,
   which is what "overflow" meant here — a chip wider than the card,
   spilling past its right edge, rather than wrapping down. */
.v-goal-tag {
  white-space: normal;
  min-width: 0;
  max-width: 100%;
}

/* Home page body (`templates/home.html`, item R5-4, owner decision
   2026-08-19) — Campaign Overview and Recent Events side by side on
   desktop instead of one full-width stack. The fourth round removed the
   home page's only other two-column grid (banner beside the news list)
   when the banner image option itself was cut, leaving recent-events as a
   lone very-wide column of narrow cards — "too spread […] too much
   whitespace" (owner). News gets the wider share: its cards carry an
   image, a title, tagged-nation flags and a summary and want room to
   breathe, where the overview is a dense grid of short number tiles that
   reads fine narrow. 2fr/3fr, not an even split. Collapses to one column
   at the tablet breakpoint, same as every other two-column layout on the
   site (`.v-overview-grid` above). `home.html` only wraps the pair in this
   grid when Campaign Overview will actually render (`show_figures` on, or
   edit mode) — with it off, Recent Events renders alone at full width
   rather than sitting beside an empty column. */
.v-home-columns {
  grid-template-columns: minmax(0, 2fr) minmax(0, 3fr);
  align-items: start;
}
@media (max-width: 820px) {
  .v-home-columns {
    grid-template-columns: minmax(0, 1fr);
  }
}

/* Campaign Overview's tile grid (`.v-grid--4`, figures.html) is
   `auto-fit, minmax(180px,1fr)` (victoria.css), sized on the assumption of
   a full-width container. Nested in `.v-home-columns__overview` that
   reflows unpredictably across the desktop range: 2 tiles wide on a wide
   monitor, but a column too narrow for a second 180px tile plus gap
   between ~820px and ~900px of viewport width collapses it to a single
   stack of 8 full-width rows — squashed exactly where the two-column body
   is active and least expected. Forcing 2 columns (the same count the
   existing sub-520px rule in victoria.css already settles on, for the same
   reason) keeps the tile grid compact and even across that range.

   **Scoped to the widths where the two column layout is actually active**
   (review gatekeeper 2026-08-19): the wrapper `div` exists at every width,
   so an unconditional rule here also overrode the *single*-column layout
   below 820px, where `.v-home-columns__overview` is the full container
   width and `auto-fit` gives 3-4 tiles correctly — a silent tablet
   regression, and a contradiction of what this comment and PAGES.md §1
   both said the rule did. Below 520px victoria.css already pins 2 columns
   for its own (unrelated, still-correct) reason. */
@media (min-width: 821px) {
  .v-home-columns__overview .v-grid--4 {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}
