/*
 * buildings.css — ShadowDark DM Companion
 * The unified "Buildings" module (Houses + Shops + Taverns -> one section).
 * FRONTEND ONLY. Implements Ken's 2026-06-25 reframe + KDL 2026-06-27's direction
 * (_team/design/2026-06-25_buildings_dashboard_direction.md): a building is a
 * TYPE (house/shop/tavern), generated item-forge style, opened in a dashboard
 * VIEW (.bldg-dash) that is a PARALLEL INSTANCE of the character dashboard.
 *
 * STYLE DECISION (Ken §4, firm): the .bldg-dash adopts the dashboard's ACTUAL
 * --dash-* skin (clean rounded sans surfaces), NOT the OSR etched skin. We do
 * this by reusing the char-dash__* classes 1:1 inside a `.char-dash.bldg-dash`
 * wrapper (KDL 2026-06-27 §7 — "Reuse all char-dash__* CSS; Buildings adds no new
 * primitives"). char-dashboard.css therefore governs the panels/grid/tabs/
 * editbar/drag look; THIS file only adds the few building-specific pieces:
 *   - the unified roster's TYPE chip + type filter,
 *   - the item-forge TYPE PICKER (reusing the .item-choice--chip idiom),
 *   - the building glyph medallion in the banner (a square plate, not the
 *     character's circular portrait),
 *   - the per-container summary line idiom on the Overview grid.
 *
 * Blackletter survives in exactly one place: the building NAME (handled by the
 * reused .char-dash__identity-name). No raw hex; base.css tokens only.
 */

/* ============================================================
   UNIFIED ROSTER — type chip + type filter
   ============================================================ */

/* Filter rail host (#1, 2026-06-27). The Buildings roster now mounts the SHARED
   treasure-style filter rail (window.ShadowDark.mountRosterFilter — the same
   component the Item Forge + Adventurers + Commoners rosters use), which renders
   its own .treasure__layout (rail + results) into this host. So the host is a plain
   block wrapper; the rail owns its own layout + spacing. (The previous bespoke
   segmented type-chip bar was replaced by the shared rail's Type facet.) */
.bldg-roster__filter {
  display: block;
}

/* The TYPE chip on each roster row — a small inline badge naming the building's
   type (House/Shop/Tavern) with its glyph. Placed in the row's main block so it
   reads with the name. Reuses the saved-roster row chrome (saved.css). */
.bldg-type-chip {
  display: inline-flex;
  align-items: center;
  gap: 0.35em;
  padding: 0.12rem 0.5rem;
  margin-left: var(--space-xs);
  font-size: 0.72rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--color-text-muted);
  background-color: var(--color-bg);
  border: 1px solid var(--color-border);
  vertical-align: middle;
}
.bldg-type-chip svg {
  width: 13px;
  height: 13px;
  stroke: currentColor;
  fill: none;
  stroke-width: 1.5;
}
.bldg-type-chip--tavern { color: var(--color-accent); border-color: color-mix(in srgb, var(--color-accent) 50%, var(--color-border)); }
.bldg-type-chip--shop   { color: var(--color-heading); }
.bldg-type-chip--house  { color: var(--color-text-muted); }

/* ============================================================
   ROSTER CARD GRID (Ken, 2026-06-26 #6) — the Buildings roster reuses the
   character-roster card idiom (.char-card-grid / .char-card from components.css):
   whole-card open button + corner delete, shared grid + responsive rules. This
   block adds only the building-specific deltas: a SQUARE type-image medallion
   (reads as "a place", mirroring the .bldg-dash banner glyph plate) and the type
   chip sitting in the card meta row. No new color/font/radius tokens.
   ============================================================ */

/* The medallion is a SQUARE rounded plate (not the character's circle) so a place
   never reads as a person. Same footprint as .char-card__portrait. */
.bldg-card-tile__portrait {
  border-radius: var(--dash-radius-sm, 8px);
}
/* The resolved type IMAGE fills the plate; object-fit:contain keeps the etched
   building silhouette whole (it is a centered line study, not a face crop). */
.bldg-card-tile__img {
  object-fit: contain;
  object-position: center;
  padding: 0.2rem;
}
/* Glyph fallback (image 404) — tints to the type accent like the banner plate. */
.bldg-card-tile__glyph {
  color: var(--color-accent);
}
.bldg-card-tile__glyph svg {
  /* Scaled up with the 5rem card portrait (#2, 2026-06-27) so the building glyph
     fallback keeps parity with the enlarged person/item roster media. */
  width: 2.25rem;
  height: 2.25rem;
  stroke: currentColor;
  fill: none;
  stroke-width: 1.5;
}
/* The type chip rides in the card's meta row; reset the inline margin it carries on
   the (old) list rows so it sits flush at the row start. */
.bldg-card-tile__meta {
  display: flex;
  align-items: center;
}
.bldg-card-tile__meta .bldg-type-chip {
  margin-left: 0;
}

/* ============================================================
   ITEM-FORGE TYPE PICKER — pick a type, then Generate
   ============================================================ */

.bldg-forge {
  display: flex;
  flex-direction: column;
  gap: var(--space-lg);
  max-width: 44rem;
}

.bldg-forge__lede {
  color: var(--color-text-muted);
  margin: 0;
}

/* The chip ROW of type radios — models the Item Forge's .item-choice--chip row
   (items.js typeSelectorHTML). Each is a label wrapping a radio + glyph + name. */
.bldg-forge__types {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-sm);
}

.bldg-type-radio {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 0.5em;
  padding: 0.6rem 1rem;
  cursor: pointer;
  color: var(--color-text);
  background-color: var(--color-surface);
  border: 1px solid var(--color-border);
  transition: border-color var(--transition-fast), color var(--transition-fast),
    background-color var(--transition-fast);
}
.bldg-type-radio:hover { border-color: var(--color-accent); }
/* The native radio is visually hidden but kept in the a11y tree + focusable. */
.bldg-type-radio input {
  position: absolute;
  opacity: 0;
  width: 1px;
  height: 1px;
  margin: 0;
}
.bldg-type-radio:has(input:focus-visible) {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
}
.bldg-type-radio:has(input:checked) {
  color: var(--color-accent);
  border-color: var(--color-accent);
  background-color: color-mix(in srgb, var(--color-accent) 12%, var(--color-surface));
}
.bldg-type-radio svg {
  width: 18px;
  height: 18px;
  stroke: currentColor;
  fill: none;
  stroke-width: 1.5;
}
.bldg-type-radio__sub {
  display: block;
  font-size: 0.72rem;
  color: var(--color-text-muted);
}
.bldg-type-radio:has(input:checked) .bldg-type-radio__sub { color: inherit; }

.bldg-forge__sub {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: var(--space-md);
}
.bldg-forge__actions {
  display: flex;
  gap: var(--space-sm);
}

/* ============================================================
   .bldg-dash — the building dashboard VIEW (parallel to .char-dash)
   We piggyback on .char-dash for the whole --dash-* skin + panel/grid/tab/drag
   CSS; .bldg-dash only retargets the few character-only bits.
   ============================================================ */

/* VIEWPORT FIT (Ken #1, 2026-06-26). The character dashboard mounts .char-dash as
   a DIRECT block child of #app-content (renderIntoContent), so width:auto fills the
   content column (≈1212px @1280). buildings.js wraps .bldg-dash in a .module-view
   FLEX COLUMN; a flex item that is itself a flex column shrinks to its content's
   max-content (≈932px here) instead of stretching, so the dash used only ~2/3 of the
   width. width:100% makes the flex item fill its .module-view track, matching the
   character dashboard's fill. The inherited .char-dash max-width:1480 still caps it on
   ultrawide, and margin:0 auto 0 0 keeps it left-anchored. The Overview grid's
   minmax(0,…) tracks + the roster/type-picker (their own max-width) and the narrow
   (<760px) single-column collapse are untouched. */
.bldg-dash.char-dash {
  width: 100%;
}

/* The building glyph medallion replaces the character's circular portrait. A
   SQUARE plate with the rounded dashboard radius reads as "a place", not "a
   person", while sharing the medallion footprint + framing. */
.bldg-dash__glyph {
  display: flex;
  align-items: center;
  justify-content: center;
  /* Hero plate — enlarged 3rem->6rem (#3, 2026-06-27) to match the adventurer/
     commoner/item detail hero. Stays SQUARE (a place, not a person) with the
     dashboard radius; object-fit:contain keeps the etched silhouette whole. */
  width: 6rem;
  height: 6rem;
  flex: none;
  color: var(--color-accent);
  background-color: var(--color-bg);
  border: 1px solid var(--color-border);
  border-radius: var(--dash-radius-sm, 8px);
}
.bldg-dash__glyph svg {
  /* Scaled up with the 6rem hero plate (#3) so the glyph fallback stays
     proportionate when no building image resolves. */
  width: 2.75rem;
  height: 2.75rem;
  stroke: currentColor;
  fill: none;
  stroke-width: 1.5;
}
/* The resolved building TYPE image inside the banner plate (Ken, 2026-06-26 #5).
   Fills the plate; contain keeps the centered etched silhouette whole. The plate's
   own border-radius clips it. When the image 404s, img-fallback.js swaps in the SVG
   glyph above (exactly today's look). */
.bldg-dash__glyph-img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  object-position: center;
  padding: 0.15rem;
  display: block;
  border-radius: inherit;
}
.bldg-dash__glyph {
  overflow: hidden;
}

/* CLICK-TO-UPLOAD custom banner image (Ken #2, 2026-06-26). In editable context the
   medallion is a <button>; mirrors char-dash__identity-portrait--btn (the person/
   adventurer portrait-upload idiom) but keeps the SQUARE building plate. The camera
   overlay fades in on hover/focus to advertise "click to upload". The resolved image
   (custom upload, then default type-image) renders inside via .bldg-dash__glyph-img. */
button.bldg-dash__glyph--btn {
  position: relative;
  padding: 0;
  cursor: pointer;
  -webkit-appearance: none;
  appearance: none;
}
button.bldg-dash__glyph--btn:hover {
  border-color: var(--color-accent);
}
button.bldg-dash__glyph--btn:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
}
.bldg-dash__glyph-overlay {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--color-bg);
  background-color: rgba(0, 0, 0, 0.55);
  opacity: 0;
  border-radius: inherit;
  transition: opacity var(--transition-fast);
}
.bldg-dash__glyph-overlay svg {
  width: 1.1rem;
  height: 1.1rem;
  stroke: currentColor;
  fill: none;
  stroke-width: 1.5;
}
button.bldg-dash__glyph--btn:hover .bldg-dash__glyph-overlay,
button.bldg-dash__glyph--btn:focus-visible .bldg-dash__glyph-overlay {
  opacity: 1;
}
@media (prefers-reduced-motion: reduce) {
  .bldg-dash__glyph-overlay { transition: none; }
}

/* Per-container Overview SUMMARY — the high-level line(s) each topic container
   shows on the grid (counts + 2-3 sample lines). Quiet, scannable. The DETAIL
   lives in that container's tab (the focused view). */
.bldg-card__summary {
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
  padding: var(--space-sm) var(--space-md) var(--space-md);
  color: var(--color-text);
}
.bldg-card__summary-counts {
  font-size: 0.9rem;
  color: var(--color-text-muted);
}
.bldg-card__summary-list {
  margin: 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
  font-size: 0.9rem;
}
.bldg-card__summary-more {
  font-size: 0.82rem;
  color: var(--color-text-muted);
  font-style: italic;
}
.bldg-card__summary-empty {
  font-size: 0.9rem;
  color: var(--color-text-muted);
  font-style: italic;
}

/* The focused detail view wrapper inside a tab (the .char-dash__focus analogue).
   The existing tavern/shop/house content renderers (.loc-view sections, priced
   tables) drop straight in; we only ensure they wear the dashboard surface. */
.bldg-dash__focus {
  display: flex;
  flex-direction: column;
  gap: var(--space-lg);
}

/* Map container thumbnail summary. */
.bldg-card__map-thumb {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
  font-size: 0.9rem;
  color: var(--color-text-muted);
}
.bldg-card__map-thumb svg {
  width: 1.4rem;
  height: 1.4rem;
  stroke: currentColor;
  fill: none;
  stroke-width: 1.5;
}

/* A "View · read-only" hint badge in the banner of the read-only VIEW. */
.bldg-dash__ro-badge,
.cmnr-dash__ro-badge {
  display: inline-flex;
  align-items: center;
  gap: 0.35em;
  font-size: 0.72rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--color-text-muted);
}
/* The cmnr-dash glyph SVGs carry no sizing class (self-sufficient icon()), so pin the
   read-only badge glyph to the label size rather than letting it fill its box. */
.cmnr-dash__ro-badge svg {
  width: 0.95em;
  height: 0.95em;
  flex: none;
  stroke: currentColor;
  fill: none;
  stroke-width: 1.5;
}

/* ============================================================
   COMMONER DASHBOARD (.cmnr-dash) — the standalone Commoner detail view as a
   PARALLEL INSTANCE of the character dashboard (Ken #5, 2026-06-26; KDL 2026-06-27's
   commoners spec). It reuses the entire .char-dash__* skin (topbar / stat cards /
   tabs / grid / panels / editbar / drag) and the .person-card component, so this
   block is only the small glue specific to a Commoner: the identity portrait
   medallion (which, unlike Buildings' square glyph plate, is the SAME circular
   .char-dash__identity-portrait a character uses, fed by the race+gender resolver)
   and the read-only badge above. No new color / font / radius tokens.
   ============================================================ */
.cmnr-dash__portrait {
  flex: none;
}
/* The campaigns cross-link panel sits below the Overview grid (parity with the
   building dash). It is a NON-draggable footer panel that stacks directly under the
   Overview grid inside .char-dash__body (which has no gap of its own), so without a
   top margin it bunched right against the grid (Ken, 2026-06-26 #5). Use --space-lg
   to MATCH the gap between the other dash containers (the .char-dash__grid gap is
   --space-lg), so the footer reads as one more separated container, not glued on. */
.bldg-dash__campaigns,
.cmnr-dash__campaigns {
  margin-top: var(--space-lg);
}

/* IMAGE tab (batch-9 #9) — the commoner's portrait shown LARGE/centered, mirroring the
   item-dashboard Image-tab pattern:
     .cmnr-dash__image-panel = a flex column that fills the tab body
       .cmnr-dash__image-stage = flex:1 centered stage holding the one media frame
         .cmnr-dash__media-large = the frame; portrait at object-fit:contain (the whole
                                    portrait shows, no crop), centered.
   No controls — the portrait is the ancestry×gender×wealth art, edited on the Identity
   tab; this view is read-only-safe (works unchanged in admin View). No new tokens. */
.cmnr-dash__image-panel {
  display: flex;
  flex-direction: column;
  margin-inline: auto;
}
.cmnr-dash__image-stage {
  flex: 1 1 auto;
  display: flex;
  align-items: center;
  justify-content: center;
  /* Make the portrait genuinely large in the viewport even when the body is short. */
  min-height: min(60vh, 32rem);
  padding: var(--space-md) 0;
}
.cmnr-dash__media-large {
  width: 100%;
  max-width: min(60vh, 32rem);
  aspect-ratio: 1 / 1;
  max-height: min(60vh, 32rem);
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--color-border);
  background-color: var(--color-surface);
  overflow: hidden;
}
.cmnr-dash__media-large .cmnr-dash__image-img {
  width: 100%;
  height: 100%;
  /* contain (not cover): the entire portrait is visible, centered, never cropped. */
  object-fit: contain;
  display: block;
}
/* Glyph fallback (no resolvable art) — scaled up so it reads as a deliberate
   placeholder at large size, muted, not a broken sliver. */
.cmnr-dash__media-large .cmnr-dash__image-glyph {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 45%;
  height: 45%;
  color: var(--color-text-muted);
}
.cmnr-dash__media-large .cmnr-dash__image-glyph svg {
  width: 100%;
  height: 100%;
}

/* #9 (2026-06-27) — the "broad description" banner sits ABOVE the Overview grid as a
   full-width, non-draggable panel (outside [data-dash-region]). It reuses the
   char-dash__panel skin so it reads as one of the dash containers, but spans the whole
   content column to give the prose room to breathe and to read as the lead blurb. */
.bldg-dash__description {
  margin-bottom: var(--space-lg);
  /* Full-width lead panel: clamp to the content column and never let a long,
     unbroken description string push the panel wider than its container
     (Ken #1, 2026-06-27 — description banner text was overrunning). */
  width: 100%;
  max-width: 100%;
  min-width: 0;
  box-sizing: border-box;
  overflow: hidden;
}
.bldg-dash__desc-body {
  padding-top: var(--space-xs);
  min-width: 0;
}
.bldg-dash__desc-text {
  margin: 0;
  line-height: 1.6;
  color: var(--color-text);
  /* Wrap prose normally on spaces, but also break inside an over-long token
     (e.g. a runaway generated string / URL) so it can never overflow the panel
     at any width. overflow-wrap handles the common case; word-break is the
     last-resort guard for tokens with no break opportunity at all. */
  overflow-wrap: anywhere;
  word-break: break-word;
}
.bldg-dash__desc-text--empty {
  color: var(--color-text-muted);
  font-style: italic;
}
/* The Re-roll/Roll control lives in the panel head's tools slot (mirrors the open-tab
   chevron affordance). Icon + a compact label so the action reads clearly.
   #5 (2026-06-28): this is a .char-dash__tool, which pins width/height to 1.85rem
   square — fine for an icon-only tool, but here it crushed the icon + "Re-roll" label
   together. Release the fixed square so the button hugs its icon+label, give it
   comfortable horizontal padding (a roomier hit target) and a steady height so it
   never jams against the description text or the panel edge. Mirrors the
   char-dash__log-btn idiom (icon-tool + text label). */
.bldg-dash__desc-roll.char-dash__tool {
  width: auto;
  min-height: 1.85rem;
  height: auto;
  padding: 0.3rem 0.7rem;
  gap: var(--space-xs);
}
.bldg-dash__desc-roll {
  display: inline-flex;
  align-items: center;
  gap: var(--space-xs);
}
.bldg-dash__desc-roll[disabled] {
  opacity: 0.5;
  cursor: default;
}
.bldg-dash__desc-roll-text {
  font-size: var(--text-sm);
  /* Keep the label on one line so it reads as a single control, not a wrapped pair. */
  white-space: nowrap;
}

/* batch-12 #2 — the LOCATION story hook banner. Shares the description banner's
   full-width lead-panel posture and overflow guards; the hook text reads as a quoted
   line (the open/close quotes are emitted in the markup, like the person-hook block).
   Two controls live in the panel-head tools slot: Roll/Re-roll (sparkle) + Clear
   (trash, revealed only when a hook exists). */
.bldg-dash__hook {
  margin-bottom: var(--space-lg);
  width: 100%;
  max-width: 100%;
  min-width: 0;
  box-sizing: border-box;
  overflow: hidden;
}
.bldg-dash__hook-body {
  padding-top: var(--space-xs);
  min-width: 0;
}
.bldg-dash__hook-text {
  margin: 0;
  line-height: 1.6;
  color: var(--color-text);
  font-style: italic;
  overflow-wrap: anywhere;
  word-break: break-word;
}
.bldg-dash__hook-text--empty {
  color: var(--color-text-muted);
  font-style: italic;
}
.bldg-dash__hook-roll.char-dash__tool,
.bldg-dash__hook-clear.char-dash__tool {
  width: auto;
  min-height: 1.85rem;
  height: auto;
  padding: 0.3rem 0.7rem;
  gap: var(--space-xs);
}
.bldg-dash__hook-roll,
.bldg-dash__hook-clear {
  display: inline-flex;
  align-items: center;
  gap: var(--space-xs);
}
.bldg-dash__hook-roll[disabled],
.bldg-dash__hook-clear[disabled] {
  opacity: 0.5;
  cursor: default;
}
.bldg-dash__hook-roll-text {
  font-size: var(--text-sm);
  white-space: nowrap;
}

/* Narrow-screen guard (KDL 2026-06-27, 2026-06-26). The shared char-dash mobile rules hide
   the CHARACTER dash's #char-dash-customize on mobile (HTML5 drag has no touch
   fallback) but key on that specific id, so the cmnr-dash customize control is not
   covered. Below --bp-tab (700px): (1) hide the cmnr customize button for the same
   reason (drag is a desktop affordance; layout still persists once set on desktop),
   and (2) hard-clamp the dash + its flex rows to the viewport width with min-width:0
   so the topbar / tabrow / body can never force a horizontal page scroll (the tab
   strip itself already scrolls via the shared .char-dash__tabs mobile rule). */
@media (max-width: 700px) {
  #cmnr-dash-customize {
    display: none !important;
  }
  .cmnr-dash,
  .cmnr-dash .char-dash__topbar,
  .cmnr-dash .char-dash__tabrow,
  .cmnr-dash .char-dash__body {
    max-width: 100%;
    min-width: 0;
  }
  .cmnr-dash .char-dash__identity,
  .cmnr-dash .char-dash__stat-cards,
  .cmnr-dash .char-dash__topbar-actions {
    min-width: 0;
  }
}

/* ============================================================
   COMMONER IDENTITY ROLL-OR-TYPE EDITOR (Ken #2/#3, 2026-06-26) — the per-field
   manual edit + reroll block beneath the read-only lead person-card in the Identity
   tab, and the ad-hoc secret editor in the Secret tab. Reuses the .btn /
   .loc-menu__reroll system + the field tokens; no new color/radius tokens. View
   read-only never renders these (Rule 1).
   ============================================================ */
.cmnr-identity-edit {
  margin-top: var(--space-md, 0.75rem);
  padding-top: var(--space-md, 0.75rem);
  border-top: 1px solid var(--color-border);
  display: flex;
  flex-direction: column;
  gap: var(--space-sm, 0.5rem);
}

/* Section-level "i" leading the commoner Identity detail (info_tooltips_app_wide
   follow-up, 2026-06-28). A quiet label + icon explaining the identity cluster. */
.cmnr-identity__section-info {
  display: flex;
  align-items: center;
  gap: var(--space-xs, 0.35rem);
  margin: 0 0 var(--space-xs, 0.35rem);
}
.cmnr-identity__section-info-label {
  font-family: var(--font-heading-ui);
  font-size: var(--text-sm, 0.8rem);
  letter-spacing: var(--ls-cinzel-caps);
  text-transform: uppercase;
  color: var(--color-text-muted);
}
.cmnr-identity-edit__head {
  margin: 0 0 var(--space-xs, 0.35rem);
  font-size: 0.78rem;
  color: var(--color-text-muted);
}
.cmnr-identity-edit__row {
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
}
.cmnr-identity-edit__label {
  font-family: var(--font-heading-ui, inherit);
  font-size: 0.72rem;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--color-text-muted);
}
.cmnr-identity-edit__controls {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  gap: var(--space-xs, 0.35rem);
}
.cmnr-identity-edit__input {
  flex: 1 1 14rem;
  min-width: 0;
}
.cmnr-identity-edit__btns,
.cmnr-secret-edit__btns {
  display: flex;
  gap: var(--space-xs, 0.35rem);
  flex: none;
}

.cmnr-secret-edit {
  margin-top: var(--space-sm, 0.5rem);
  display: flex;
  flex-direction: column;
  gap: var(--space-sm, 0.5rem);
}
.cmnr-secret-edit__input {
  width: 100%;
  min-width: 0;
}

/* The clickable Origin stat chip (forward back-link, Ken #1) — the same stat-card
   skin, turned into a button with a pointer + a clear focus ring + hover lift. The
   .char-dash__stat-card--link modifier is reusable for any clickable stat card. */
.char-dash__stat-card--link {
  cursor: pointer;
  text-align: left;
  font: inherit;
  color: inherit;
  border: none;
  background: none;
  padding: 0;
  transition: filter 120ms ease, transform 120ms ease;
}
.char-dash__stat-card--link:hover {
  filter: brightness(1.08);
}
.char-dash__stat-card--link:active {
  transform: translateY(1px);
}
.char-dash__stat-card--link:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
}
.cmnr-dash__origin-link .char-dash__stat-card-value {
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 2px;
}

/* ============================================================
   EXPORTED-TO-COMMONERS PANEL (reverse back-link, Ken #1, 2026-06-26) — in the
   building dash, the Commoners exported FROM this building (GET /:id/commoners).
   Each entry (name + role) opens that Commoner in the cmnr-dash. Reuses the dash
   surfaces + .btn focus idiom; no new color/radius tokens.
   ============================================================ */
.bldg-exported__list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-xs, 0.35rem);
}
.bldg-exported__entry {
  display: flex;
  align-items: baseline;
  gap: var(--space-sm, 0.5rem);
  width: 100%;
  text-align: left;
  padding: var(--space-xs, 0.4rem) var(--space-sm, 0.5rem);
  background: var(--color-bg);
  border: 1px solid var(--color-border);
  border-radius: var(--dash-radius-sm, 6px);
  color: inherit;
  font: inherit;
}
.bldg-exported__entry--link {
  cursor: pointer;
  transition: border-color 120ms ease, background-color 120ms ease;
}
.bldg-exported__entry--link:hover {
  border-color: var(--color-accent);
}
.bldg-exported__entry--link:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
}
.bldg-exported__name {
  font-weight: 600;
}
.bldg-exported__name + .bldg-exported__role::before {
  content: "·";
  margin-right: var(--space-sm, 0.5rem);
  color: var(--color-text-muted);
}
.bldg-exported__role {
  font-size: 0.8rem;
  color: var(--color-text-muted);
  letter-spacing: 0.03em;
  text-transform: uppercase;
}

/* ============================================================
   INLINE MAP EMBED (Ken #2, 2026-06-26) — the building's interior map rendered
   READ-ONLY, INLINE, inside the dash Map container. The maps module renders its
   own .module-view.maps shell into .bldg-map-inline__host; body.maps-readonly
   (set by setMapsView for the inline embed) already hides the editing rail /
   status / title re-roll. Here we only (a) put the escape-hatch bar above the
   pane, (b) suppress the Map Builder titlestrip heading (the dash panel head
   already labels this "Map"), and (c) keep the rendered plate inside the panel.
   No new color/font/radius tokens — reuses the .btn system + maps.css surfaces.
   ============================================================ */
.bldg-map-inline {
  display: flex;
  flex-direction: column;
  gap: var(--space-sm, 0.5rem);
}

/* Escape-hatch row ("Open in full map editor") above the rendered map. */
.bldg-map-inline__bar {
  display: flex;
  justify-content: flex-end;
  gap: var(--space-sm, 0.5rem);
}

/* The host the maps module renders into. Clip nothing vertically; the canvas
   plate sizes itself, and the floor switcher + legend lay out beneath the bar. */
.bldg-map-inline__host {
  min-width: 0;
}

/* The inline embed is a READ-ONLY VIEW inside a panel — drop the Map Builder's
   own titlestrip ("Map Builder / Roll the bones…"); the panel head already reads
   "Map". The map NAME + floor label still show — on the canvas itself as of
   2026-07-07 (see maps.js's title box), previously in the now-retired
   .maps__platehead DOM band. */
.bldg-map-inline__host .maps__titlestrip {
  display: none;
}

/* Keep the rendered workspace within the panel width (the editor's wide-breakout
   column is body-scoped; inside a dash panel we want it to fit the panel track,
   not break out). The plate column flexes; the legend keeps its intrinsic width. */
.bldg-map-inline__host .maps {
  gap: var(--space-xs, 0.35rem);
}
.bldg-map-inline__host .maps__workspace {
  width: 100%;
}

/* NO-MAP inline state: the Generate (Dynamic/Manual) affordance, stacked. */
.bldg-map-inline__nomap {
  display: flex;
  flex-direction: column;
  gap: var(--space-sm, 0.5rem);
}
.bldg-map-inline__gen {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-sm, 0.5rem);
}

/* ============================================================
   PERSON CARD (.person-card) — people-architecture batch, 2026-06-26.
   The ONE component for every building person (tavern proprietor/servers/
   patrons, shop shopkeeper/assistants, house household head/members). Wears the
   --dash-* skin (it lives inside the .bldg-dash). Two fidelities via --lead.
   Blackletter is reserved for the person NAME only (.person-card__name).
   Reuses the char-dash portrait medallion classes 1:1 (see char-dashboard.css);
   THIS block only lays out the card around it.
   ============================================================ */
.person-card {
  display: flex;
  align-items: flex-start;
  gap: var(--space-md, 0.85rem);
  padding: var(--space-md, 0.85rem);
  border: 1px solid var(--color-border);
  border-radius: var(--dash-radius-sm, 8px);
  background-color: var(--color-surface);
  font-family: var(--dash-sans);
}
/* A stack of cards spaces them out (assistants/household/servers lists). */
.person-card-list {
  display: flex;
  flex-direction: column;
  gap: var(--space-sm, 0.5rem);
}
.person-card-list__add {
  margin-top: var(--space-xs, 0.35rem);
}
/* The lead card (proprietor/keeper/head) reads slightly heavier — an accent spine
   marks it as the owner-role person. */
.person-card--lead {
  border-left: 3px solid var(--color-accent);
  background-color: var(--color-bg);
}

/* Portrait medallion: the char-dash medallion geometry is inherited from
   .char-dash__identity-portrait (char-dashboard.css). person-card__portrait just
   keeps it from shrinking and a touch larger on a lead card. */
.person-card__portrait {
  flex: none;
}
.person-card--lead .person-card__portrait,
.person-card--lead .char-dash__identity-portrait {
  width: 3.5rem;
  height: 3.5rem;
}

.person-card__body {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-xs, 0.35rem);
}

.person-card__identity {
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
}
.person-card__name {
  margin: 0;
  font-family: var(--font-heading); /* blackletter — the NAME only */
  font-size: 1.15rem;
  line-height: 1.2;
  color: var(--color-text);
  /* An unusually long commoner name wraps within the card body instead of
     overflowing it (the body already carries min-width:0). */
  max-width: 100%;
  overflow-wrap: anywhere;
  word-break: break-word;
}
.person-card__meta {
  margin: 0;
  font-size: 0.85rem;
  color: var(--color-text-muted);
}

/* Lead field block (demeanor/appearance/quirk) — a compact label/value list. */
.person-card__fields {
  margin: 0;
}
.person-card__summary-line {
  margin: 0;
  font-size: 0.9rem;
}

.person-card__secret {
  margin: 0;
  font-size: 0.88rem;
  color: var(--color-text);
}
.person-card__secret-label {
  font-family: var(--font-heading-ui, inherit);
  font-size: 0.72rem;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--color-accent);
}

/* Cross-owner LOCKED secret/hook (#3, 2026-06-27): a non-owner viewing a shared
   commoner sees "Hidden in the darkness." in place of the real text. The locked text
   reads muted + italic so it's clearly an absence, not data — matching the existing
   GM-only/empty treatment rather than introducing a new visual idiom. */
.person-card__secret--locked .loc-menu__text,
.person-card__hook--locked .loc-person-hook__text {
  color: var(--color-text-muted);
  font-style: italic;
}

/* Gender edit (drives the default portrait). A quiet inline label + select. */
.person-card__gender {
  display: flex;
  align-items: center;
  gap: var(--space-xs, 0.35rem);
}
.person-card__gender-label {
  font-family: var(--font-heading-ui, inherit);
  font-size: 0.72rem;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--color-text-muted);
}
.person-card__gender-select {
  font: inherit;
  font-size: 0.85rem;
  padding: 0.15rem 0.4rem;
  border: 1px solid var(--color-border);
  border-radius: var(--dash-radius-sm, 8px);
  background-color: var(--color-bg);
  color: var(--color-text);
}

.person-card__actions {
  margin-top: var(--space-xs, 0.35rem);
}

/* Narrow: stack the medallion above the body so the card never overflows. */
@media (max-width: 460px) {
  .person-card {
    flex-direction: column;
    align-items: stretch;
  }
}

/* The Image tab (#9, 2026-06-28) — the building's image shown LARGE/centered, the
   dominant element of the tab body. Mirrors the item-dash Image-tab pattern
   (items.css .item-dash__image-*) — STAGE + object-fit:contain + ~45% glyph fallback
   — with ONE deliberate difference: building images are 16:9, NOT square, so the frame
   is `aspect-ratio: 16 / 9` (NOT 1/1) so the wide building image isn't letterboxed.
     .bldg-dash__image-panel = flex column that fills the tab body
       .bldg-dash__image-stage = flex:1 centered stage holding the one frame
         .bldg-dash__media-large = the 16:9 frame; image at object-fit:contain (the
                                    whole building shows, never cropped), centered */
.bldg-dash__image-panel {
  display: flex;
  flex-direction: column;
  /* The shared .char-dash__focus .char-dash__panel rule may cap width + flush-left;
     center this panel in the body so the hero image sits centered. */
  margin-inline: auto;
}
.bldg-dash__image-stage {
  flex: 1 1 auto;
  display: flex;
  align-items: center;
  justify-content: center;
  /* Large in the viewport even when the body is short, capped so it never grows
     unbounded on tall screens (mirrors the item Image stage). */
  min-height: min(60vh, 32rem);
  padding: var(--space-md) 0;
}
/* The large 16:9 frame — building images are wide, NOT square (item-slice caveat,
   2026-06-28): a 1/1 frame would letterbox them. object-fit:contain shows the WHOLE
   building. */
.bldg-dash__media-large {
  width: 100%;
  max-width: min(100%, 48rem);
  aspect-ratio: 16 / 9;
  max-height: min(60vh, 32rem);
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--color-border);
  background-color: var(--color-oracle-bg, var(--color-surface));
  border-radius: var(--dash-radius-sm, 8px);
  overflow: hidden;
}
.bldg-dash__media-large .bldg-dash__media-img {
  width: 100%;
  height: 100%;
  /* contain (not cover): the entire building is visible, centered, never cropped. */
  object-fit: contain;
  object-position: center;
  display: block;
}
/* Glyph fallback (no image) — scaled to ~45% of the frame, muted, so it reads as a
   deliberate placeholder at large size rather than a broken sliver. */
.bldg-dash__media-glyph {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 45%;
  height: 45%;
  color: var(--color-text-muted);
}
.bldg-dash__media-glyph svg {
  width: 100%;
  height: 100%;
}
