/* =====================================================================
   Public land-node detail page (V1.3).
   A node carries ~70 content columns; the old page showed six. The job of this
   sheet is to make a fully-populated node scannable rather than a wall: a hero
   that answers "what and where", a sticky nav, then panels of label/value pairs.
   Palette + radii come from mln-directory.css's --mln-* tokens.
   ===================================================================== */

/* ---------------------------------------------------------------- hero */
.mln-node-hero {
    padding: 1.25rem 0 0.5rem;
}

.mln-node-title {
    font: 700 clamp(1.6rem, 3.2vw, 2.35rem)/1.12 var(--mln-disp, system-ui, sans-serif);
    letter-spacing: -0.02em;
    color: var(--mln-ink, #132420);
    margin: 0 0 0.6rem;
}

.mln-node-chips {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.35rem;
    margin-bottom: 0.85rem;
}

.mln-node-summary {
    font: 400 1.05rem/1.65 var(--mln-ui, system-ui, sans-serif);
    color: var(--mln-muted, #5c6b65);
    max-width: 62ch;
    margin: 0 0 1.1rem;
}

/* Key facts: an at-a-glance row, auto-fitting so 2 facts look as deliberate as 4. */
.mln-node-facts {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
    gap: 0.6rem;
    margin: 0 0 0.5rem;
}
.mln-node-fact {
    padding: 0.7rem 0.85rem;
    border: 1px solid var(--mln-line, #e3ebe7);
    border-radius: var(--mln-r-sm, 10px);
    background: var(--mln-surface, #fff);
    box-shadow: var(--mln-shadow-sm, 0 1px 2px rgba(19,36,32,.06));
}
.mln-node-fact dt {
    font-size: 0.7rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--mln-faint, #93a099);
    margin-bottom: 0.2rem;
}
.mln-node-fact dd {
    margin: 0;
    font-weight: 600;
    font-size: 0.95rem;
    color: var(--mln-ink, #132420);
    /* A long focus string must not stretch the tile past its neighbours. */
    overflow-wrap: anywhere;
}

/* ---------------------------------------------------------------- layout */
.mln-node-grid {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 320px;
    gap: 1.75rem;
    align-items: start;
    margin-top: 1.25rem;
}
/* minmax(0, 1fr) above matters: without it a wide child (a table in a panel)
   can force the main column past the viewport and scroll the whole page. */

.mln-node-main { min-width: 0; }

.mln-node-aside {
    min-width: 0;
    /*
      The aside must fill the grid ROW, not just its own content, or the sticky child
      below cannot move at all.

      .mln-node-grid sets align-items:start, which sizes every item to its content. That
      made this column exactly as tall as the card inside it — measured 431px against a
      431px child, i.e. ZERO travel room. A sticky element can only move within its
      containing block, so it was correctly "stuck" and simply had nowhere to go: it
      scrolled away with the page and looked like position:sticky was being ignored.
      Stretching this one item (the main column keeps start alignment) gives the card the
      full row to travel down — measured 0px -> 13348px of range on a populated node.
    */
    align-self: stretch;
}
.mln-node-aside-sticky {
    position: sticky;
    /* Clear the sticky section nav so the map never hides behind it. */
    top: 4.25rem;
    display: flex;
    flex-direction: column;
    gap: 1rem;
}

.mln-node-aside-card {
    padding: 0.9rem 1rem;
    border: 1px solid var(--mln-line, #e3ebe7);
    border-radius: var(--mln-r, 14px);
    background: var(--mln-surface, #fff);
}
.mln-node-aside-card h3 {
    font: 700 0.78rem/1 var(--mln-ui, system-ui, sans-serif);
    text-transform: uppercase;
    letter-spacing: 0.07em;
    color: var(--mln-faint, #93a099);
    margin: 0 0 0.6rem;
}
.mln-node-aside-facts dt {
    font-size: 0.72rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--mln-faint, #93a099);
    margin-top: 0.5rem;
}
.mln-node-aside-facts dd {
    margin: 0.1rem 0 0;
    font-size: 0.9rem;
    line-height: 1.45;
    color: var(--mln-ink, #132420);
}

/* ---------------------------------------------------------------- panels */
.mln-node-panel {
    padding: 1.5rem 0;
    border-bottom: 1px solid var(--mln-line, #e3ebe7);
}
.mln-node-panel:last-child { border-bottom: 0; }
/* Anchored jumps land under the sticky nav rather than beneath it. */
.mln-node-panel { scroll-margin-top: 4.5rem; }

.mln-node-panel-title {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    font: 700 1.15rem/1.25 var(--mln-disp, system-ui, sans-serif);
    letter-spacing: -0.01em;
    color: var(--mln-ink, #132420);
    margin: 0 0 1rem;
}
.mln-node-panel-title i { color: var(--mln-primary, #00594c); font-size: 1.05rem; }

.mln-node-prose {
    font: 400 1rem/1.7 var(--mln-ui, system-ui, sans-serif);
    color: var(--mln-ink, #132420);
    max-width: 70ch;
    /* Intake-sourced prose arrives with real newlines and no markup. */
    white-space: pre-line;
}

/* Two columns of label/value, with long prose spanning both. */
.mln-node-fields {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
    gap: 0.9rem 1.5rem;
    margin: 0;
}
.mln-node-field.is-wide { grid-column: 1 / -1; }

.mln-node-field dt {
    font-size: 0.72rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--mln-faint, #93a099);
    margin-bottom: 0.2rem;
}
.mln-node-field dd {
    margin: 0;
    font-size: 0.95rem;
    line-height: 1.6;
    color: var(--mln-ink, #132420);
    white-space: pre-line;
    overflow-wrap: anywhere;
}
/* A wide field is prose, so give it prose measure rather than full bleed. */
.mln-node-field.is-wide dd { max-width: 70ch; }

.mln-node-panel h3 {
    font: 700 0.95rem/1.3 var(--mln-ui, system-ui, sans-serif);
    color: var(--mln-muted, #5c6b65);
    margin: 1.2rem 0 0.6rem;
}

/* ---------------------------------------------------------------- responsive */
@media (max-width: 1024px) {
    .mln-node-grid { grid-template-columns: 1fr; gap: 1.25rem; }
    /* Un-stick the aside once it is stacked, or the map pins itself mid-scroll. */
    .mln-node-aside-sticky { position: static; }
    .mln-node-aside { order: -1; }
}

@media (max-width: 640px) {
    .mln-node-facts { grid-template-columns: repeat(auto-fit, minmax(130px, 1fr)); }
    .mln-node-fields { grid-template-columns: 1fr; }
    .mln-node-panel { padding: 1.15rem 0; }
    .mln-node-summary { font-size: 1rem; }
}

/* ---------- V1.5 — favourite / save button in the node hero ----------
   The button reuses .mln-dir-save so the directory's JS (mlnWishlistToggle +
   the hydrate() pre-fill pass) drives it unchanged. That class is tuned for an
   absolutely-positioned 2rem circle on a card thumbnail, so every one of those
   geometry rules is overridden here. The selector is doubled
   (.mln-dir-save.mln-node-save) so it wins on specificity rather than on
   stylesheet order — mln-directory.css and mln-node-detail.css are loaded by
   two different mechanisms (template vs page), and relying on their order is
   how a rule silently stops existing. */
.mln-node-hero {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 1rem;
    flex-wrap: wrap;
}
.mln-node-hero-main { flex: 1 1 20rem; min-width: 0; }
.mln-node-hero-actions { flex: 0 0 auto; padding-top: 1.35rem; }

.mln-dir-save.mln-node-save {
    position: static;
    top: auto; left: auto;
    width: auto; height: auto;
    padding: 0.5rem 0.95rem;
    border-radius: 999px;
    gap: 0.45rem;
    font: 600 0.85rem/1.35 var(--mln-body, system-ui, sans-serif);
    background: var(--mln-surface, #fff);
    border: 1px solid var(--mln-line, #dfe5e2);
    white-space: nowrap;
}
.mln-dir-save.mln-node-save:hover {
    transform: none;
    background: var(--mln-bg, #f4f7f5);
    border-color: var(--mln-accent, #c2571f);
}
.mln-dir-save.mln-node-save.saved {
    background: var(--mln-accent, #c2571f);
    border-color: var(--mln-accent, #c2571f);
    color: #fff;
}
