/* estate.css — the shared estate directory, wearing the host's clothes.
 *
 * Every value resolves through a chain of the custom-property names the
 * Webspinner sites actually define, ending in a neutral literal. A host that
 * wants explicit control sets the --ws-* names and wins outright; a host that
 * defines nothing still gets something legible.
 *
 * Token chains, in the order they are tried:
 *   ink      --ws-ink      --ink      --ink-2
 *   muted    --ws-muted    --ink-dim  --ink-mute  --muted  --ink-light  --ink-3
 *   accent   --ws-accent   --accent   --teal      --gold
 *   surface  --ws-surface  --panel    --surface   --paper-2  --card-bg
 *   rule     --ws-rule     --rule     --line      --border
 *   serif / sans follow the same idea.
 *
 * Copyright (c) 2026 Webspinner Foundation.
 */

.ws-estate {
  --_ink:     var(--ws-ink, var(--ink, var(--ink-2, #1b1f22)));
  --_muted:   var(--ws-muted, var(--ink-dim, var(--ink-mute, var(--muted, var(--ink-light, var(--ink-3, #6d7681))))));
  --_accent:  var(--ws-accent, var(--accent, var(--teal, var(--gold, #2c6b65))));
  --_surface: var(--ws-surface, var(--panel, var(--surface, var(--paper-2, #ffffff))));
  --_rule:    var(--ws-rule, var(--rule, var(--line, var(--border, rgba(128,128,128,.22)))));
  --_serif:   var(--ws-serif, var(--serif, var(--display, Georgia, 'Times New Roman', serif)));
  --_sans:    var(--ws-sans, var(--sans, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif));

  font-family: var(--_sans);
  color: var(--_ink);
}

/* ── group heading ── */
.ws-estate .ws-group {
  /* Hosts style bare `section`; this block must not inherit their layout.
     Only tokens are inherited, never padding, width or margin. */
  margin: 0 0 clamp(24px, 2.6vw, 34px) !important;
  padding: 0 !important; max-width: none !important; width: auto !important;
  border: 0; background: none;
}
.ws-estate .ws-group-head {
  display: flex; align-items: baseline; gap: 14px;
  padding-bottom: 9px; margin-bottom: 16px;
  border-bottom: 1px solid var(--_rule);
}
.ws-estate .ws-group-name {
  font-family: var(--_sans); font-size: 11px; font-weight: 700;
  letter-spacing: .2em; text-transform: uppercase; color: var(--_accent);
}
.ws-estate .ws-group-n {
  font-family: var(--_sans); font-size: 10.5px; letter-spacing: .12em;
  text-transform: uppercase; color: var(--_muted); margin-left: auto;
}

/* ── the cards, read as a news index ── */
.ws-estate .ws-grid {
  display: grid; gap: clamp(14px, 1.8vw, 22px);
  grid-template-columns: repeat(auto-fill, minmax(232px, 1fr));
}
.ws-estate .ws-card {
  display: flex; flex-direction: column; text-decoration: none; color: inherit;
  border: 1px solid var(--_rule); border-radius: 10px; overflow: hidden;
  background: var(--_surface);
  transition: transform .28s cubic-bezier(.2,.7,.3,1), border-color .28s, box-shadow .28s;
}
.ws-estate .ws-card:hover {
  transform: translateY(-3px); border-color: var(--_accent);
  box-shadow: 0 16px 34px -18px rgba(0,0,0,.42);
}
.ws-estate .ws-shot { position: relative; aspect-ratio: 16/10; overflow: hidden; background: var(--_rule); }
.ws-estate .ws-shot img {
  width: 100%; height: 100%; object-fit: cover; object-position: top center;
  display: block; transition: transform .5s cubic-bezier(.2,.7,.3,1);
  /* .ws-noshot below is absolutely positioned, and a positioned element paints
     above in-flow content whatever the source order says. Without a stacking
     context of its own the artwork sat UNDER its own placeholder, so every card
     carried its hostname ghosted across the middle of the picture. Give the
     image a layer; the placeholder still shows when there is no image, or when
     onerror removes one that failed. */
  position: relative; z-index: 1;
}
.ws-estate .ws-card:hover .ws-shot img { transform: scale(1.04); }
.ws-estate .ws-noshot {
  position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
  font-family: var(--_sans); font-size: 10px; letter-spacing: .2em; text-transform: uppercase;
  color: var(--_muted);
}
.ws-estate .ws-body { padding: 14px 16px 16px; display: flex; flex-direction: column; flex: 1; }
.ws-estate .ws-kicker {
  font-family: var(--_sans); font-size: 9.5px; font-weight: 700; letter-spacing: .16em;
  text-transform: uppercase; color: var(--_accent); margin-bottom: 7px;
  display: flex; align-items: center; gap: 8px;
}
.ws-estate .ws-flag {
  font-weight: 600; letter-spacing: .1em; color: var(--_muted);
  border: 1px solid var(--_rule); border-radius: 20px; padding: 2px 7px;
}
.ws-estate .ws-title {
  font-family: var(--_serif); font-size: 1.06rem; line-height: 1.24;
  margin: 0 0 7px; color: var(--_ink); font-weight: 600;
}
.ws-estate .ws-blurb {
  font-family: var(--_sans); font-size: .82rem; line-height: 1.55;
  color: var(--_muted); margin: 0 0 12px;
  display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden;
}
.ws-estate .ws-go {
  margin-top: auto; font-family: var(--_sans); font-size: 11px; font-weight: 700;
  letter-spacing: .05em; color: var(--_accent);
  display: inline-flex; align-items: center; gap: 6px; transition: gap .22s;
}
.ws-estate .ws-card:hover .ws-go { gap: 11px; }

/* ── states ── */
.ws-estate .ws-loading, .ws-estate .ws-error {
  font-family: var(--_sans); font-size: 13px; color: var(--_muted);
  padding: 26px 0; text-align: center;
}
.ws-estate .ws-stamp {
  font-family: var(--_sans); font-size: 10px; letter-spacing: .12em;
  text-transform: uppercase; color: var(--_muted); opacity: .7;
  text-align: center; margin-top: 22px;
}

@media (prefers-reduced-motion: reduce) {
  .ws-estate .ws-card, .ws-estate .ws-shot img { transition: none; }
  .ws-estate .ws-card:hover { transform: none; }
  .ws-estate .ws-card:hover .ws-shot img { transform: none; }
}
