/* =============================================================================
   SudaHub — The Wire
   RESKIN Phase 4 (docs/RESKIN.md §2.3, §2.4). Rebuilt from the console-era
   News screen: the ≥1280px master–detail split is gone with the console
   shell, and the card follows the mockup's own structure —

       kicker · time                              [saved]
       headline
       dek
       ──────────── fading hairline ────────────
       ▬▬▬ confirmed · 3 sources          [ REGION ]

   "The wire" is the feed's name now (§2.3). Data surfaces stay sober: flat,
   no gradient, credibility never green (§7.2).
   ========================================================================== */

.news-shell {
    display: flex;
    flex-direction: column;
    gap: var(--space-6);
}

.news-filters {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
}

.news-list {
    display: flex;
    flex-direction: column;
    gap: var(--space-4);
}

/* ---------- Swipe to save (RESKIN §2.2) ----------
   The wrapper clips the reveal; the card slides over it. `touch-action:
   pan-y` is what keeps vertical scrolling native and instant — without it
   the browser waits on our pointer handler before scrolling, and the feed
   feels laggy on touch even when the JS is correct. */
.news-card-swipe {
    position: relative;
    overflow: hidden;
    border-radius: var(--radius-md);
    touch-action: pan-y;
}
.news-card-reveal {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    /* flex-end, not `right` — this mirrors on its own under RTL, which is
       what puts the label on the side the card slides away from in BOTH
       directions without a single direction branch in CSS or JS. */
    justify-content: flex-end;
    padding-inline: var(--space-8);
    border-radius: var(--radius-md);
    background: var(--color-accent-900);
}
.news-card-reveal-label {
    font-family: var(--font-label);
    font-size: var(--fs-micro);
    font-weight: var(--fw-semibold);
    letter-spacing: var(--tracking-label);
    color: var(--color-accent-200);
}
[lang="en"] .news-card-reveal-label { text-transform: uppercase; }

/* ---------- Card ---------- */
.news-card {
    position: relative;
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
    width: 100%;
    text-align: start;
    padding: var(--space-6);
    border-radius: var(--radius-md);
    border: 1px solid var(--color-neutral-900);
    background: var(--color-surface);
    box-shadow: var(--shadow-sm);
    cursor: pointer;
    transition: border-color var(--dur-base) var(--ease-out), transform var(--dur-base) var(--ease-out);
}
.news-card:hover { border-color: var(--color-accent-800); }
.news-card.is-active { border-color: var(--color-accent); }

.news-card-meta {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    font-family: var(--font-label);
    font-size: var(--fs-micro);
    min-width: 0;
}
.news-card-kicker {
    letter-spacing: var(--tracking-label);
    color: var(--color-neutral-500);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
[lang="en"] .news-card-kicker { text-transform: uppercase; }
.news-card-dot {
    width: 3px;
    height: 3px;
    flex: none;
    border-radius: var(--radius-pill);
    background: var(--color-neutral-700);
}
.news-card-time {
    letter-spacing: var(--tracking-tight);
    color: var(--color-neutral-500);
    white-space: nowrap;
}
.news-card-meta-spacer { flex: 1; }

/* Saved mark. A bookmark glyph, not just a border tint — colour alone must
   not carry state (§9), and the swipe leaves no other trace. */
.news-card-saved-mark { flex: none; width: 13px; height: 13px; color: var(--color-accent); }
.news-card.is-saved { border-color: var(--color-accent-700); }

/* Headline + standfirst on one side, thumbnail on the other. Plain flex, no
   direction branch: the row mirrors under RTL on its own, so the image sits
   on the inline-end side in both languages. */
.news-card-lead {
    display: flex;
    align-items: flex-start;
    gap: var(--space-4);
}
.news-card-lead-text {
    flex: 1;
    /* Without this the flex default of `min-width: auto` refuses to shrink
       below the longest word in the headline and pushes the thumbnail off
       the card. Same failure as the discussion room's 167px overflow. */
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
}
.news-card-thumb {
    position: relative;
    flex: 0 0 auto;
    width: 92px;
    aspect-ratio: 4 / 3;
    border-radius: var(--radius-sm);
    overflow: hidden;
    /* §7.3's reasoning applies to wire photos too: light-edged images
       dissolve into the surface on dark without an inset hairline. */
    border: 1px solid var(--color-neutral-900);
    background: var(--color-surface);
}
.news-card-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
/* Graphic content stays blurred in the feed. The reveal control is in the
   article, not here — see the note in news.js. */
.news-card-thumb.is-blurred img { filter: blur(12px); transform: scale(1.15); }
.news-card-thumb-flag {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(var(--scrim-rgb), 0.35);
    color: rgb(var(--text-on-accent-rgb));
}
.news-card-thumb-flag svg { width: 18px; height: 18px; }

.news-card-title {
    font-family: var(--font-ui);
    font-weight: var(--fw-medium);
    font-size: var(--fs-title-s);
    line-height: var(--lh-snug);
    letter-spacing: var(--tracking-heading);
    color: var(--color-neutral-100);
    text-wrap: pretty;
}
.news-card-body {
    font-size: var(--fs-body-s);
    line-height: var(--lh-body);
    color: var(--color-neutral-400);
    text-wrap: pretty;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

/* The fading hairline — a Nocturne signature (§2.1): rules fade to
   transparent at both ends instead of stopping cleanly. */
.news-card-rule {
    height: 1px;
    background: linear-gradient(90deg, transparent, var(--color-neutral-800) 12%, var(--color-neutral-800) 88%, transparent);
}

.news-card-footer {
    display: flex;
    align-items: center;
    gap: var(--space-3);
}
.news-card-footer-spacer { flex: 1; }
.news-region-pill {
    flex: none;
    display: grid;
    place-items: center;
    min-height: 24px;
    padding-inline: var(--space-3);
    border-radius: var(--radius-pill);
    border: 1px solid var(--color-neutral-800);
    font-family: var(--font-label);
    font-size: var(--fs-micro);
    letter-spacing: var(--tracking-label);
    color: var(--color-neutral-400);
    white-space: nowrap;
}
[lang="en"] .news-region-pill { text-transform: uppercase; }

.news-lang-tag {
    flex: none;
    font-family: var(--font-label);
    font-size: var(--fs-micro);
    font-weight: var(--fw-semibold);
    padding: 1px 5px;
    border-radius: var(--radius-sm);
    border: 1px solid var(--color-neutral-800);
    color: var(--color-neutral-500);
}

/* End-of-feed note (§2.4) — the wire has an end, and saying so is better
   than an infinite spinner that implies more is coming. */
.news-feed-foot {
    padding: var(--space-6) var(--space-1) 0;
    text-align: center;
    font-size: var(--fs-caption);
    color: var(--color-neutral-500);
}

/* ---------- Article viewer chrome ----------
   Slides in from the inline END and back out the same way, so under RTL it
   enters from the mirrored side (§4.1: "sheets, toasts and the onboarding
   sequence all slide from the mirrored side" — the article viewer is the
   same class of surface). */
.article-viewer {
    position: fixed;
    inset: 0;
    z-index: 50;
    overflow-y: auto;
    overscroll-behavior: contain;
    background: var(--color-bg);
    transform: translateX(100%);
    transition: transform var(--dur-enter) var(--ease-out);
}
[dir="rtl"] .article-viewer { transform: translateX(-100%); }
.article-viewer.is-open { transform: translateX(0); }
[dir="rtl"] .article-viewer.is-open { transform: translateX(0); }
@media (prefers-reduced-motion: reduce) {
    .article-viewer { transition: none; }
}

.article-viewer-inner {
    width: 100%;
    max-width: var(--shell-max, 480px);
    margin-inline: auto;
    min-height: 100vh;
    min-height: 100dvh;
    padding-inline: var(--space-6);
    padding-block-end: calc(var(--inset-bottom, 0px) + var(--space-8));
}

.article-viewer-bar {
    position: sticky;
    inset-block-start: 0;
    z-index: 10;
    display: flex;
    align-items: center;
    padding-block: calc(var(--inset-top, 0px) + var(--space-4)) var(--space-4);
    margin-block-end: var(--space-6);
    border-block-end: 1px solid var(--color-neutral-900);
    background: var(--glass-bg);
    backdrop-filter: blur(14px) saturate(140%);
    -webkit-backdrop-filter: blur(14px) saturate(140%);
}
.article-back-btn {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    min-height: 40px;
    padding-inline: var(--space-4);
    border-radius: var(--radius-md);
    border: none;
    background: transparent;
    color: var(--color-neutral-300);
    font-family: var(--font-ui);
    font-weight: var(--fw-medium);
    font-size: var(--fs-body-s);
    cursor: pointer;
}
.article-back-btn:hover { background: var(--color-surface); color: var(--color-accent-200); }
.article-back-btn svg { width: 18px; height: 18px; }
/* Direction-carrying icon — mirrors under RTL (§4.1). */
[dir="rtl"] .article-back-btn svg { transform: scaleX(-1); }

.article-viewer-content { display: block; }

/* ---------- Article view ---------- */
.news-article-progress {
    position: absolute;
    inset-inline: 0;
    inset-block-start: 0;
    height: 3px;
    z-index: 5;
    background: var(--color-neutral-900);
}
.news-article-progress-fill {
    height: 100%;
    width: 0;
    background: var(--color-accent);
    transition: width var(--dur-micro) linear;
}

.news-article-srcline {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    margin-block-end: var(--space-4);
}
.news-article-title {
    font-family: var(--font-ui);
    font-weight: var(--fw-medium);
    font-size: var(--fs-display);
    line-height: var(--lh-tight);
    letter-spacing: var(--tracking-heading);
    color: var(--color-neutral-100);
    text-wrap: pretty;
    margin-block-end: var(--space-3);
}
.news-article-meta {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    font-family: var(--font-label);
    font-size: var(--fs-caption);
    color: var(--color-neutral-500);
    margin-block-end: var(--space-6);
}
.news-article-body {
    display: flex;
    flex-direction: column;
    gap: var(--space-6);
    font-size: var(--fs-body-l);
    line-height: var(--lh-reading);
    /* 66ch EN / 60ch AR (§3 of CLAUDE.md). Inside a 480px column this
       rarely binds, but it holds the measure if the column ever widens. */
    max-width: 66ch;
    color: var(--color-neutral-200);
}
:lang(ar) .news-article-body { max-width: 60ch; }
.news-article-body p { margin: 0; text-wrap: pretty; }

/* ---------- The verify trail entry point (§2.3) ---------- */
.news-verify-btn {
    width: 100%;
    display: flex;
    align-items: center;
    gap: var(--space-4);
    padding: var(--space-6);
    margin-block-start: var(--space-8);
    border-radius: var(--radius-md);
    border: 1px solid var(--color-neutral-800);
    background: var(--color-surface);
    color: var(--color-text);
    cursor: pointer;
    text-align: start;
}
.news-verify-btn:hover { border-color: var(--color-accent-700); }
.news-verify-icon { flex: none; width: 18px; height: 18px; color: var(--color-accent); }
/* display:block on the children — they are spans, and inline spans ran the
   title and its subtitle together on one wrapped line. */
.news-verify-text { flex: 1; min-width: 0; }
.news-verify-title {
    display: block;
    font-family: var(--font-ui);
    font-weight: var(--fw-medium);
    font-size: var(--fs-label);
    color: var(--color-neutral-100);
}
.news-verify-sub {
    display: block;
    font-size: var(--fs-caption);
    color: var(--color-neutral-500);
    margin-block-start: 2px;
}
.news-verify-chevron { flex: none; width: 16px; height: 16px; color: var(--color-neutral-500); }
/* Direction-carrying icon — mirrors under RTL (§4.1). */
[dir="rtl"] .news-verify-chevron { transform: scaleX(-1); }

/* ---------- Sources sheet: "How we know this" (§2.3) ---------- */
.sources-list { display: flex; flex-direction: column; gap: var(--space-4); }
.source-row {
    display: flex;
    gap: var(--space-4);
    padding: var(--space-4);
    border-radius: var(--radius-md);
    border: 1px solid var(--color-neutral-800);
    background: var(--color-bg);
}
/* The 01 / 02 tag. Mono and NOT --font-label: it is a positional number in
   Western digits in both locales, so it wants tabular alignment (§4.2 —
   "source tags must not mirror"). */
.source-tag {
    flex: none;
    display: grid;
    place-items: center;
    width: 28px;
    height: 28px;
    border-radius: var(--radius-sm);
    background: var(--color-accent-900);
    font-family: var(--font-mono);
    font-size: var(--fs-meta);
    font-weight: var(--fw-medium);
    color: var(--color-accent-200);
}
.source-body { display: flex; flex-direction: column; gap: var(--space-1); min-width: 0; }
.source-name {
    font-family: var(--font-ui);
    font-weight: var(--fw-medium);
    font-size: var(--fs-body-s);
    color: var(--color-neutral-100);
}
.source-note {
    font-size: var(--fs-caption);
    line-height: var(--lh-body);
    color: var(--color-neutral-500);
    text-wrap: pretty;
}
.source-dependent {
    align-self: flex-start;
    font-family: var(--font-label);
    font-size: var(--fs-micro);
    letter-spacing: var(--tracking-label);
    color: var(--color-neutral-500);
}
[lang="en"] .source-dependent { text-transform: uppercase; }
.sources-note {
    padding: var(--space-2) var(--space-1);
    font-size: var(--fs-caption);
    line-height: var(--lh-body);
    color: var(--color-neutral-500);
}

/* ---------- Discussion sheet (§2.4) ----------
   Reuses premiere-chat's message rows, so there is one row renderer for
   both surfaces. Only the container differs. */
.thread-messages {
    display: flex;
    flex-direction: column;
    gap: var(--space-4);
    max-height: 48vh;
    overflow-y: auto;
    overscroll-behavior: contain;
    padding-block-end: var(--space-4);
}
.thread-composer {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    padding-block-start: var(--space-4);
    border-block-start: 1px solid var(--color-neutral-800);
}
.thread-input {
    flex: 1;
    min-width: 0;
    border-radius: var(--radius-pill);
}
.thread-send {
    flex: none;
    display: grid;
    place-items: center;
    width: 44px;
    height: 44px;
    border-radius: var(--radius-pill);
    border: 1px solid var(--color-accent);
    background: transparent;
    color: var(--color-accent-200);
    cursor: pointer;
}
.thread-send:hover { background: color-mix(in srgb, var(--color-accent) 16%, transparent); }
.thread-send svg { width: 17px; height: 17px; }
/* Direction-carrying: the send arrow points along the writing direction. */
[dir="rtl"] .thread-send svg { transform: scaleX(-1); }
.thread-note {
    padding-block-start: var(--space-4);
    font-size: var(--fs-caption);
    color: var(--color-neutral-500);
    text-align: center;
}

/* Graphic content: blurred until explicitly revealed, never autoplaying,
   only rendered when a real content flag says so (never guessed). */
.news-graphic-wrap { position: relative; border-radius: var(--radius-md); overflow: hidden; margin-block: var(--space-6); }
.news-graphic-wrap.is-blurred img { filter: blur(28px); transform: scale(1.05); }
.news-graphic-reveal-btn {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-2);
    background: rgba(var(--scrim-rgb), 0.45);
    color: rgb(var(--text-on-accent-rgb));
    font-family: var(--font-label);
    font-size: var(--fs-label);
    font-weight: var(--fw-semibold);
    border: none;
    cursor: pointer;
}

/* ---------- Ads: sober, no gradient (register split, §0) ---------- */
.news-ad-card {
    padding: var(--space-6);
    border-radius: var(--radius-md);
    border: 1px solid var(--color-neutral-800);
    background: var(--color-surface);
}
.news-ad-label {
    font-family: var(--font-label);
    font-size: var(--fs-micro);
    font-weight: var(--fw-semibold);
    letter-spacing: var(--tracking-label);
    color: var(--warning);
}
