/* =========================================================================
   OAT — news.css
   The News desk (/news/): a sign surface, not an article page. A NO-SCROLL
   board at desk widths: header + panel grid + two crawling ribbons fill the
   viewport exactly; panels cycle their overflow on a timer instead of
   scrolling (the page JS paginates each list to what fits). Below 1000px it
   falls back to a normal scrolling grid. This page keeps the site header
   and drops the footer (see /news/index.php).

   Every color/space/type value derives from theme.css tokens. The component
   dials live in the --news-* block below; tune there, not in the rules.
   Documented in system.html §14.
   ========================================================================= */

.news-desk {
  /* component dials */
  --news-gap: var(--space-4);
  --news-panel-bg: var(--surface-raised);
  --news-panel-border: var(--border);
  --news-panel-radius: var(--radius-base);
  --news-label-size: var(--size-eyebrow);
  --news-item-size: var(--size-small);
  --news-meta-size: var(--size-tiny);
  --news-ribbon-h: 2.6rem;
  --news-ribbon-size: var(--size-body);
  --news-ribbon-a-bg: var(--primary-darker);
  --news-ribbon-a-fg: var(--text-on-primary);
  --news-ribbon-a-accent: var(--blue-300);
  --news-ribbon-a-speed: 128s;  /* world: the slow wire */
  --news-ribbon-b-bg: var(--neutral-900);
  --news-ribbon-b-fg: #E8E2D6;
  --news-ribbon-b-accent: var(--green-300);
  --news-ribbon-b-speed: 88s;   /* markets: quicker of the two, still easy reading */

  width: 100%;
  padding: var(--space-4) var(--space-6) 0;
}

/* ── The no-scroll board (desk widths) ─────────────────────────────────────
   body:has(main.news-desk) scopes these to the real page only — the
   system.html demo wraps in a <div class="news-desk"> and stays untouched. */
@media (min-width: 1000px) {
  body:has(main.news-desk) {
    height: 100dvh;
    overflow: hidden;
    display: flex;
    flex-direction: column;
  }
  body:has(main.news-desk) .site-header { flex: 0 0 auto; }
  main.news-desk {
    flex: 1 1 auto;
    min-height: 0;
    display: flex;
    flex-direction: column;
  }
  main.news-desk .news-desk__head { flex: 0 0 auto; }
  main.news-desk .news-grid {
    flex: 1 1 auto;
    min-height: 0;
    overflow: hidden;
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    grid-template-rows: repeat(2, minmax(0, 1fr));
    /* stretch is load-bearing: with align-items:start a tall panel overflows
       its track and draws over the row below (the "garbled text" failure) */
    align-items: stretch;
    padding-bottom: var(--news-gap);
  }
  main.news-desk .news-panel {
    display: flex;
    flex-direction: column;
    min-height: 0;
    overflow: hidden;
  }
  main.news-desk .news-list {
    flex: 1 1 auto;
    min-height: 0;
    overflow: hidden;
    position: relative;   /* pagination JS measures li.offsetTop against the list */
  }
  main.news-desk .news-ribbons { flex: 0 0 auto; position: static; }
  /* the weather body flexes and clips; the attribution line below it is
     pinned, so the required DB-IP credit can never fall off the panel */
  main.news-desk #wx-body { flex: 1 1 auto; min-height: 0; overflow: hidden; }
  /* weather periods on the fixed board: two clean tiles; rows that don't
     fit collapse entirely instead of peeking half-sliced at the panel edge */
  main.news-desk .wx__periods {
    grid-template-columns: repeat(2, 1fr);
    grid-template-rows: auto;   /* row 1 sizes normally… */
    grid-auto-rows: 0;          /* …rows that would clip collapse instead */
    row-gap: 0;
    overflow: hidden;
  }
  main.news-desk .wx__period { overflow: hidden; }
}

/* ── Desk masthead — broadsheet rule: the desk name + date on the left,
      status + clock + controls on the right (2026-07-11) ── */
.news-desk__head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--space-4);
  border-bottom: var(--border-heavy) solid var(--text-heading);
  padding-bottom: var(--space-1-2);
  margin-bottom: var(--news-gap);
}
.news-desk__brand {
  display: flex;
  align-items: baseline;
  gap: var(--space-4);
  min-width: 0;
}
.news-desk__title {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: var(--size-h3);
  color: var(--text-heading);
  white-space: nowrap;
  margin: 0;   /* it's an h1; the masthead rule owns the spacing */
}
.news-desk__date {
  font-family: var(--font-mono);
  font-size: var(--news-meta-size);
  text-transform: uppercase;
  letter-spacing: var(--tracking-wide);
  color: var(--text-muted);
  white-space: nowrap;
}
.news-desk__status {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  font-family: var(--font-mono);
  font-size: var(--news-meta-size);
  color: var(--text-muted);
}
/* same type as the weather temperature (mono, 600), sized for the strip */
.news-clock {
  font-family: var(--font-mono);
  font-size: var(--size-h3);
  font-weight: 600;
  color: var(--text-heading);
  font-variant-numeric: tabular-nums;
}
.news-stale {
  background: var(--warning-light);
  color: var(--warning);
  border-radius: var(--radius-sm);
  padding: var(--space-1) var(--space-2);
  font-weight: 600;
}
.news-focus-btn {
  font-family: var(--font-mono);
  font-size: var(--news-meta-size);
  color: var(--text-body);
  background: var(--surface-alt);
  border: var(--border-thin) solid var(--border-strong);
  border-radius: var(--radius-sm);
  padding: var(--space-1) var(--space-3);
  cursor: pointer;
}
.news-focus-btn:hover { background: var(--hover-tint, var(--surface-alt)); border-color: var(--text-muted); }

/* ── Panel grid (scroll fallback below 1000px; board overrides above) ──── */
.news-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(330px, 1fr));
  gap: var(--news-gap);
  align-items: start;
  padding-bottom: var(--space-4);
}

/* Each stream wears its own hue: a top strip, a faint wash, and the label
   dot. Headlines stay in ink (identity is the panel's job, not the text's). */
.news-panel { --panel-hue: var(--primary); }
.news-panel[data-stream="hort-cea"] { --panel-hue: var(--green-500); }
.news-panel[data-stream="cannabis"] { --panel-hue: var(--warning); }
.news-panel[data-stream="agtech"]   { --panel-hue: var(--blue-400); }
.news-panel[data-stream="policy"]   { --panel-hue: var(--danger); }
.news-panel[data-stream="grants"]   { --panel-hue: var(--warning); }
.news-panel[data-stream="makers"]   { --panel-hue: var(--green-700); }
.news-panel[data-stream="ai"]       { --panel-hue: var(--brand-blue-deep); }
.news-panel[data-stream="weather"]  { --panel-hue: var(--blue-300); }

.news-panel {
  background: color-mix(in oklab, var(--panel-hue) 4%, var(--news-panel-bg));
  border: var(--border-thin) solid var(--news-panel-border);
  border-top: 3px solid var(--panel-hue);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
  padding: var(--space-3) var(--space-4) var(--space-4);
}
.news-panel__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-2);
  /* the divider borrows the stream's hue, so each panel reads as one piece */
  border-bottom: var(--border-thin) solid color-mix(in oklab, var(--panel-hue) 30%, var(--news-panel-border));
  padding-bottom: var(--space-2);
  margin-bottom: var(--space-1-2);
}
.news-panel__label {
  font-family: var(--font-mono);
  font-size: var(--news-label-size);
  font-weight: 600;
  letter-spacing: var(--tracking-wide, 0.08em);
  text-transform: uppercase;
  color: var(--text-heading);
}
.news-panel__label::before {
  content: "";
  display: inline-block;
  width: 0.55em;
  height: 0.55em;
  border-radius: var(--radius-full);
  background: var(--panel-hue);
  margin-right: var(--space-2);
}
.news-panel__asof {
  font-family: var(--font-mono);
  font-size: var(--news-meta-size);
  color: var(--text-muted);
}
/* icon tool links on a panel's title bar — always visible whatever the
   panel body holds (the weather radar + 14-day forecast pair) */
.news-panel__tools {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2-3);
  margin-left: auto;
}
.news-panel__tools a { display: inline-flex; color: var(--text-muted); }
/* icon-only links: suppress the global ↗ glyph (match its a[href] specificity) */
.news-panel__tools a[href]::after { content: none; }
.news-panel__tools a:hover,
.news-panel__tools a:focus-visible { color: var(--link); }
.news-panel__tools svg { width: 1.2em; height: 1.2em; }

.news-list { list-style: none; margin: 0; padding: 0; }
.news-list.is-swap { animation: news-fade 400ms ease; }
@keyframes news-fade { from { opacity: 0; } }
.news-item { padding: var(--space-2-3) 0; }
.news-item + .news-item { border-top: var(--border-thin) solid color-mix(in oklab, var(--news-panel-border) 55%, transparent); }
.news-item a {
  color: var(--text-body);
  text-decoration: none;
  font-size: var(--news-item-size);
  font-weight: var(--weight-bold);
  line-height: var(--lh-tight);
  display: block;
}
.news-item a:hover { color: var(--link-hover); text-decoration: underline; }
.news-item__meta {
  display: block;
  margin-top: var(--space-1);
  font-family: var(--font-mono);
  font-size: var(--news-meta-size);
  color: var(--text-muted);
}
.news-empty { color: var(--text-muted); font-size: var(--news-item-size); margin: var(--space-2) 0 0; }

/* ── Weather stat tile ─────────────────────────────────────────────────── */
.wx__now { display: flex; align-items: baseline; gap: var(--space-3); }
.wx__temp {
  font-family: var(--font-mono);
  font-size: clamp(2.2rem, 3.5vw, 3rem);
  font-weight: 600;
  color: var(--text-heading);
  font-variant-numeric: tabular-nums;
  line-height: 1;
}
.wx__desc { font-size: var(--news-item-size); color: var(--text-body); max-width: 26ch; }
.wx__loc {
  font-family: var(--font-mono);
  font-size: var(--news-meta-size);
  color: var(--text-muted);
  margin-top: var(--space-1);
}
.wx__periods {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(96px, 1fr));
  gap: var(--space-2);
  margin-top: var(--space-2);
}
.wx__period {
  background: var(--surface-alt);
  border-radius: var(--radius-sm);
  padding: var(--space-2);
  font-size: var(--news-meta-size);
}
.wx__period-name { font-family: var(--font-mono); color: var(--text-muted); display: block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.wx__period-temp { font-family: var(--font-mono); font-weight: 600; color: var(--text-heading); font-size: var(--size-small); }
.wx__period-desc {
  color: var(--text-body);
  margin-top: var(--space-2xs);
  /* bound the tile so the no-scroll panel never slices a forecast mid-word */
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.wx__alert {
  display: inline-block;
  background: var(--warning-light);
  color: var(--warning);
  border-radius: var(--radius-sm);
  padding: var(--space-1) var(--space-2);
  font-size: var(--news-meta-size);
  font-weight: 600;
  margin: var(--space-2) var(--space-1) 0 0;
}
.wx__attr { margin-top: var(--space-2); font-size: var(--news-meta-size); color: var(--text-muted); }
.wx__attr a { color: inherit; }
/* the radar link is an action, not attribution — it keeps the link color */
.wx__attr a.wx__radar { color: var(--link); font-weight: var(--link-weight, 500); }

/* ── Ribbons — full viewport width, two tempos ─────────────────────────── */
.news-ribbons {
  position: sticky;            /* scroll fallback only; the board pins it via flex */
  bottom: 0;
  z-index: 40;
  margin: 0 calc(-1 * var(--space-6));   /* full-bleed against .news-desk padding */
  box-shadow: var(--shadow-md);
  /* the lit-exhibit cue: signature gradient hairline where the board meets the wires */
  border-top: 2px solid transparent;
  border-image: var(--gradient-frame) 1;
}
.ribbon {
  display: flex;
  align-items: stretch;
  height: var(--news-ribbon-h);
  overflow: hidden;
}
/* fixed station chip on the left of each wire — the crawl scrolls past it */
.ribbon__label {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: 0 var(--space-4);
  font-family: var(--font-mono);
  font-size: var(--news-meta-size);
  font-weight: 600;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
}
.ribbon__label::before {
  content: "";
  width: 0.5em;
  height: 0.5em;
  border-radius: var(--radius-full);
  background: currentColor;
}
.ribbon--world .ribbon__label {
  color: var(--news-ribbon-a-accent);
  border-right: 1px solid color-mix(in oklab, var(--news-ribbon-a-accent) 35%, transparent);
}
.ribbon--fin .ribbon__label {
  color: var(--news-ribbon-b-accent);
  border-right: 1px solid color-mix(in oklab, var(--news-ribbon-b-accent) 35%, transparent);
}
.ribbon__viewport { padding-left: var(--space-4); }
.ribbon--world { background: var(--news-ribbon-a-bg); color: var(--news-ribbon-a-fg); }
.ribbon--fin   { background: var(--news-ribbon-b-bg); color: var(--news-ribbon-b-fg); }
.ribbon__viewport { flex: 1 1 auto; overflow: hidden; display: flex; align-items: center; }
.ribbon__track {
  display: inline-flex;
  white-space: nowrap;
  will-change: transform;
  animation: news-crawl var(--ribbon-speed, 60s) linear infinite;
}
.ribbon--world .ribbon__track { --ribbon-speed: var(--news-ribbon-a-speed); }
.ribbon--fin   .ribbon__track { --ribbon-speed: var(--news-ribbon-b-speed); }
.ribbon:hover .ribbon__track { animation-play-state: paused; }
.ribbon__set { display: inline-flex; padding-right: var(--space-6); font-size: var(--news-ribbon-size); }
.ribbon__sep { opacity: 0.5; padding: 0 var(--space-3); }
.ribbon--fin .ribbon__sep { color: var(--news-ribbon-b-accent); opacity: 0.8; }
@keyframes news-crawl {
  from { transform: translateX(0); }
  to   { transform: translateX(-50%); }
}
@media (prefers-reduced-motion: reduce) {
  .ribbon__track { animation: none; }
  .ribbon__viewport { overflow-x: auto; }
  .news-list.is-swap { animation: none; }
}

/* ── Focus (kiosk) mode — body.news-focus, normally paired with
      html[data-theme="dark"]; colors flip via theme tokens on their own ── */
/* the menu bar hides only in true fullscreen or on a kiosk sign — windowed
   Dark keeps it (Mark, 2026-07-11); the masthead's full site name keeps the
   brand on screen when it's gone */
body.news-fullscreen .site-header,
body.news-kiosk .site-header { display: none; }
body.news-focus .news-desk {
  --news-item-size: var(--size-body);
  --news-meta-size: var(--size-small);
  --news-ribbon-h: 3rem;
  --news-ribbon-size: var(--size-lead);
}
body.news-focus .news-desk__dek { display: none; }

@media (max-width: 640px) {
  .news-desk { padding: var(--space-4) var(--space-3) 0; }
  .news-ribbons { margin: 0 calc(-1 * var(--space-3)); }
  .news-desk__head { align-items: flex-start; }
  .news-clock { display: none; }
  .news-desk__date { display: none; }
  .ribbon__label { display: none; }
  .news-desk__title { white-space: normal; font-size: var(--size-h4); }
}
