/* Insights page shells — homepage (/insights) + category (/insights/:slug).
   Variables stick to the rest of the site's palette (matches sedar-filings). */

:root {
  --ins-bg: #f7f7f7;
  --ins-card: #ffffff;
  --ins-border: #e5e7eb;
  --ins-text: #1f2937;
  --ins-text-muted: #6b7280;
  --ins-accent: #30a5bf;
  --ins-accent-dark: #1f7e93;
}

body { background-color: var(--ins-bg); margin: 0; }

.ins-page {
  max-width: 1280px;
  margin: 0 auto;
  padding: 24px 16px 64px;
  color: var(--ins-text);
}

.ins-header { margin: 8px 0 16px; }
.ins-title { font-size: 28px; font-weight: 600; margin: 0 0 4px; }
.ins-subtitle { color: var(--ins-text-muted); margin: 0; font-size: 14px; }

/* Generic feature-row host used by the page-banner widget. Neutral naming
   on purpose so ad-blocker selectors don't strip it; the widget mounts its
   own content inside. Match the rounded-corner card rhythm used by hero /
   supporting / category cards on this surface (8px); the widget sets
   overflow:hidden internally so the image is clipped to the radius. */
.ins-feature-row { margin: 12px 0 20px; }
/* Reserve the banner slot's height while empty so the ad's arrival doesn't
   push the page down. Same reasoning + same collapse contract as
   `.lp-feature-row:empty` in landing.css — read the long note there. 700/115
   is the banner aspect contract from root CLAUDE.md. Collapses via
   AdsWidget._hideQuietly's inline display:none (widget ran, no eligible ad)
   or via initFeatureStrips (widget never loaded). */
html:not([data-mh-no-ads]) .ins-feature-row:empty {
  aspect-ratio: 700 / 115;
  border-radius: 8px;
  background: linear-gradient(90deg, #f1f1f1 0%, #e5e7eb 50%, #f1f1f1 100%);
  background-size: 200% 100%;
  animation: ins-shimmer 1.4s linear infinite;
}
/* Plan-gated viewers (basic/core/explorer) never get an ad, so they must not
   get the reservation either — see the note in landing.css. */
[data-mh-no-ads] .ins-feature-row:empty { display: none; }
@media (prefers-reduced-motion: reduce) {
  .ins-feature-row:empty { animation: none; }
}
@keyframes ins-shimmer {
  0% { background-position: 200% 0; }
  100% { background-position: -200% 0; }
}
.ins-feature-row.mh-rotator {
  border-radius: 8px;
}

/* Breadcrumb. */
.ins-breadcrumb {
  font-size: 13px;
  color: var(--ins-text-muted);
  margin: 0 0 16px;
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 6px;
}
.ins-breadcrumb a {
  color: var(--ins-text-muted);
  text-decoration: none;
}
.ins-breadcrumb a:hover { color: var(--ins-accent); }
.ins-breadcrumb-sep { color: #c4c8cf; }
.ins-breadcrumb-current { color: var(--ins-text); font-weight: 500; }

/* Section eyebrow titles ("TOP INSIGHTS", "BROWSE BY CATEGORY", etc.). */
.ins-section-title {
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ins-text);
  margin: 0 0 14px;
}
.ins-section-title-suffix {
  font-weight: 500;
  color: var(--ins-text-muted);
  margin-left: 4px;
}

/* Hero section — 1 main + 4 supporting. Two columns on desktop. */
.ins-hero-section { margin-bottom: 32px; }
.ins-hero {
  display: grid;
  grid-template-columns: minmax(0, 1.45fr) minmax(0, 1fr);
  gap: 12px;
}
/* aspect-ratio reserves the main hero container's height BEFORE JS
   injects the card (was: empty div → 0 height → CLS on hydrate). Child
   card also has aspect-ratio 16/10 (see below), so injecting a card
   into a container that already has the right shape is a no-op for
   layout. MHD-2022 W6. */
.ins-hero-main { min-height: 0; aspect-ratio: 16 / 10; }
.ins-hero-supporting {
  display: grid;
  grid-template-columns: 1fr 1fr;
  grid-template-rows: 1fr 1fr;
  gap: 12px;
  min-height: 0;
}

/* Hero cards — shared image-overlay treatment. The image is set via inline
   background-image so we can fall back to a dark gradient when no
   share_image_id is present. The dark gradient on `::after` is the readable-
   text overlay; the badge sits above it via z-index. */
.ins-hero-card {
  position: relative;
  display: block;
  border-radius: 8px;
  overflow: hidden;
  text-decoration: none;
  color: white;
  background-color: #1a2230;
  background-size: cover;
  background-position: center;
  transition: transform 0.15s ease, box-shadow 0.15s ease;
}
.ins-hero-card:hover { transform: translateY(-1px); box-shadow: 0 4px 12px rgba(0,0,0,0.12); }
.ins-hero-card::after {
  content: '';
  position: absolute;
  inset: 0;
  /* Floor at 0.4 instead of 0 so admin-supplied images with embedded text
     (captions, scale bars, project labels) don't compete with our headline. */
  background: linear-gradient(180deg, rgba(0,0,0,0.4) 0%, rgba(0,0,0,0.6) 55%, rgba(0,0,0,0.9) 100%);
  pointer-events: none;
}
/* Main owns the hero height (16:10 keeps it landscape but not boxy). The
   supporting cards drop their own aspect-ratio and stretch to fill their grid
   row so the 2x2 stack matches the main's height exactly. */
.ins-hero-main .ins-hero-card { aspect-ratio: 16 / 10; }
.ins-hero-supporting .ins-hero-card { height: 100%; min-height: 0; }
/* Supporting tiles: badge (top-left) → headline pinned to top, meta pinned
   to the bottom. Hero main keeps its bottom-aligned overlay. Gradient is
   darkened at both ends so top text and bottom meta stay readable. */
.ins-hero-supporting .ins-hero-card::after {
  background: linear-gradient(180deg, rgba(0,0,0,0.85) 0%, rgba(0,0,0,0.45) 50%, rgba(0,0,0,0.85) 100%);
}
.ins-hero-supporting .ins-hero-overlay {
  top: 0;
  bottom: 0;
  display: flex;
  flex-direction: column;
  /* padding-top clears the badge (12px top + ~22px badge + ~8px gap). */
  padding: 44px 20px 16px;
}
.ins-hero-supporting .ins-hero-meta { margin-top: auto; }

/* Tag badge — dark pill, top-left of the image. */
.ins-badge {
  position: absolute;
  top: 12px;
  left: 12px;
  z-index: 2;
  background: rgba(20, 28, 40, 0.92);
  color: #ffffff;
  padding: 4px 10px;
  border-radius: 3px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  line-height: 1.4;
  max-width: calc(100% - 24px);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Hero overlay — title + excerpt + meta over the gradient. */
.ins-hero-overlay {
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  padding: 18px 20px;
  z-index: 1;
  color: white;
}
.ins-hero-main .ins-hero-overlay { padding: 22px 24px; }
.ins-hero-title {
  font-size: 16px;
  font-weight: 600;
  margin: 0 0 4px;
  line-height: 1.3;
  color: #ffffff;
}
.ins-hero-main .ins-hero-title { font-size: 24px; line-height: 1.25; margin-bottom: 6px; }
.ins-hero-excerpt {
  font-size: 13px;
  color: rgba(255,255,255,0.85);
  margin: 0 0 8px;
  line-height: 1.4;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.ins-hero-meta {
  font-size: 12px;
  color: rgba(255,255,255,0.78);
  line-height: 1.4;
}
.ins-hero-meta-sep { margin: 0 6px; }

/* Browse by category row — dark image-backed tiles with a centered icon. */
.ins-category-row { margin-bottom: 32px; }
.ins-category-cards {
  display: grid;
  /* Reserve the tile row's height BEFORE JS injects (each card is
     min-height: 200px + 10px gap). Value tracks the widest breakpoint
     (8 tiles in one row = 200px). Narrower breakpoints override below
     (2/3/4-col layouts wrap to more rows). MHD-2022 W6. */
  min-height: 200px;
  /* Eight columns now that 3D Models is a category tile — Drilling,
     Exploration, Financials, M&A, Financings, Company & Project,
     Interviews, 3D Models. Adding a ninth needs a re-think of the row (or
     an early breakpoint to two rows) — the tiles are already snug at
     desktop. Padding, icon size and label wrap were re-tuned below to hold
     the row at the /companies / /investor-deck breakpoint (≥1100px). */
  grid-template-columns: repeat(8, minmax(0, 1fr));
  gap: 10px;
}
.ins-category-card {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  /* Content (icon + label + 2-line subtitle + count) drives the height;
     min-height keeps short-content cards from collapsing while letting them
     stay snug against the content. Avoid aspect-ratio so empty cards don't
     stretch to a tall placeholder. */
  min-height: 200px;
  padding: 20px 10px 16px;
  border-radius: 8px;
  text-decoration: none;
  color: white;
  overflow: hidden;
  background-color: #1a2230;
  background-size: cover;
  background-position: center;
  transition: transform 0.15s ease, box-shadow 0.15s ease;
}
.ins-category-card::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(135deg, rgba(20,28,40,0.78) 0%, rgba(10,14,20,0.88) 100%);
  pointer-events: none;
}
.ins-category-card > * { position: relative; z-index: 1; }
.ins-category-card:hover { transform: translateY(-1px); box-shadow: 0 4px 12px rgba(0,0,0,0.18); }
.ins-category-card-icon {
  width: 44px;
  height: 44px;
  border-radius: 50%;
  border: 1.5px solid rgba(255,255,255,0.85);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: #ffffff;
  font-size: 17px;
  margin-bottom: 12px;
}
.ins-category-card-label {
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: #ffffff;
  line-height: 1.2;
  margin-bottom: 10px;
}
.ins-category-card-subtitle {
  font-size: 12px;
  color: rgba(255,255,255,0.78);
  line-height: 1.45;
  margin-bottom: 12px;
}
/* "N Insights" sits at the bottom — push it down with margin-top:auto so the
   icon/label/subtitle stay top-anchored even when content is short. */
.ins-category-card-count {
  font-size: 12px;
  font-weight: 600;
  color: #ffffff;
  letter-spacing: 0.02em;
  margin-top: auto;
}

/* Category tab strip (category page). */
.ins-tab-strip {
  display: flex;
  gap: 8px;
  overflow-x: auto;
  border-bottom: 1px solid var(--ins-border);
  margin-bottom: 16px;
  padding-bottom: 0;
}
.ins-tab-strip a {
  flex-shrink: 0;
  padding: 10px 14px;
  font-size: 14px;
  color: var(--ins-text-muted);
  text-decoration: none;
  border-bottom: 2px solid transparent;
  white-space: nowrap;
}
.ins-tab-strip a.is-active {
  color: var(--ins-text);
  border-bottom-color: var(--ins-accent);
  font-weight: 600;
}

/* Main grid — title + controls live in column 1, sidebar spans rows 1–3
   in column 2 so its height matches the left column's title + controls +
   feed list (but NOT the load-more button, which lives on its own row 4
   in column 1 only). This keeps the right column's CTA bottom aligned
   with the bottom of the feed cards, not with the load-more button. */
.ins-grid {
  display: grid;
  grid-template-columns: 1fr 320px;
  grid-template-areas:
    "title    sidebar"
    "controls sidebar"
    "stack    sidebar"
    "loadmore .";
  column-gap: 24px;
  row-gap: 14px;
  align-items: start;
}
.ins-grid > .ins-grid-title { grid-area: title; margin: 0; }
.ins-grid > .ins-feed-controls { grid-area: controls; margin: 0; }
.ins-grid > .ins-feed-stack { grid-area: stack; min-width: 0; }
.ins-grid > .ins-grid-loadmore { grid-area: loadmore; margin-top: 6px; }
/* Sidebar sits at content height in column 2. We deliberately do NOT
   stretch it to match the left column — if sidebar content (trending +
   CTA) ever exceeded the natural left-column row heights, CSS grid would
   distribute the overflow across the rows and push the feed cards down,
   producing an awkward gap above the first feed card. Keeping the sidebar
   at content height makes the left column always align cleanly to the top. */
.ins-grid > .ins-sidebar { grid-area: sidebar; align-self: start; }

/* Feed column — controls row. Single line on desktop: search | 4 chips, with
   the Region chip flexed to fill the trailing space. Wraps only at the mobile
   breakpoint, where chip widths drop and search goes full-width. */
.ins-feed-controls {
  display: flex;
  flex-wrap: nowrap;
  gap: 8px;
  align-items: center;
  margin-bottom: 14px;
}

/* Shoelace sl-select chips ("Last 30 Days", "Category", etc.).
   Defaults are sized to match the design: gently rounded corners (6px, not
   pills), white bg, light gray border, medium font-weight, dark gray text,
   muted chevron. sl-select is block-level by default so explicit widths are
   needed; per-chip widths set further down. */
.ins-chip {
  --sl-input-border-radius-small: 6px;
  --sl-input-border-color: #e5e7eb;
  --sl-input-border-color-hover: #cbd5e1;
  --sl-input-border-color-focus: var(--ins-accent);
  --sl-input-background-color: #ffffff;
  --sl-input-color: #1f2937;
  --sl-input-color-hover: #1f2937;
  --sl-input-color-focus: #1f2937;
  --sl-input-placeholder-color: #1f2937;
  --sl-input-font-size-small: 13px;
  --sl-input-spacing-small: 12px;
  min-width: 0;
  display: inline-block;
}
.ins-chip::part(combobox) {
  min-height: 34px;
  font-weight: 500;
  box-shadow: none;
}
.ins-chip::part(display-input) {
  font-size: 13px;
  font-weight: 500;
  color: #1f2937;
}
.ins-chip::part(expand-icon) { color: #6b7280; }
.ins-chip::part(prefix) { color: #6b7280; margin-right: 6px; font-size: 13px; }
.ins-chip::part(clear-button) { color: #9ca3af; }
.ins-chip[placeholder]::part(display-input)::placeholder { color: #1f2937; opacity: 1; font-weight: 500; }

/* Per-chip widths so the controls row fits on a single line at desktop and
   each chip is tight to its longest option label. */
.ins-search-input { width: 220px; flex-shrink: 1; }
.ins-chip-date { width: 156px; }
#ins-category.ins-chip { width: 130px; }
#ins-commodity.ins-chip { width: 130px; }
#ins-region.ins-chip { flex: 1 1 auto; min-width: 116px; }

/* Search input — same border radius / color as chips. */
.ins-search-input {
  position: relative;
  display: flex;
  align-items: center;
}
.ins-search-input input {
  padding: 8px 14px 8px 32px;
  border: 1px solid #e5e7eb;
  border-radius: 6px;
  font-size: 13px;
  background: #ffffff;
  color: #1f2937;
  width: 100%;
  outline: none;
  height: 34px;
  box-sizing: border-box;
  font-weight: 500;
}
.ins-search-input input::placeholder { color: #9ca3af; font-weight: 400; }
.ins-search-input input:focus { border-color: var(--ins-accent); }
.ins-search-icon {
  position: absolute;
  left: 11px;
  color: #9ca3af;
  font-size: 12px;
  pointer-events: none;
}
.ins-search-dropdown {
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  background: var(--ins-card);
  border: 1px solid var(--ins-border);
  border-radius: 6px;
  margin-top: 4px;
  box-shadow: 0 4px 12px rgba(0,0,0,0.08);
  max-height: 320px;
  overflow-y: auto;
  z-index: 50;
}
.ins-search-dropdown .ins-search-row {
  padding: 8px 12px;
  cursor: pointer;
  font-size: 13px;
}
.ins-search-dropdown .ins-search-row:hover { background: #f5f7fa; }

/* Feed — vertical list of horizontal rows.
   Each row: thumbnail (left) | badge + title + excerpt + meta (middle) | chevron (right). */
.ins-feed {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  background: var(--ins-card);
  border: 1px solid var(--ins-border);
  border-radius: 8px;
  overflow: hidden;
}
.ins-feed-row { border-bottom: 1px solid var(--ins-border); }
.ins-feed-row:last-child { border-bottom: none; }
.ins-feed-row-link {
  display: flex;
  gap: 18px;
  padding: 16px 20px;
  text-decoration: none;
  color: var(--ins-text);
  align-items: center;
  transition: background 0.12s;
}
.ins-feed-row-link:hover { background: #fafbfc; }
.ins-feed-row-thumb {
  flex-shrink: 0;
  width: 150px;
  height: 100px;
  background-color: #e5e7eb;
  background-size: cover;
  background-position: center;
  border-radius: 6px;
  /* Positioning context for the "Stock image" disclosure pill (see
     /components/article-thumb.css). */
  position: relative;
}
.ins-feed-row-body {
  flex-grow: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
}
/* Inline tag pill (not absolutely positioned like the hero badge). Tighter
   padding + letter-spacing than the hero badge so the inline list reads more
   compactly. */
.ins-tag-pill {
  display: inline-block;
  background: #2d3748;
  color: white;
  padding: 2px 7px;
  border-radius: 3px;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  line-height: 1.4;
  margin-bottom: 8px;
  align-self: flex-start;
}
.ins-feed-row-title {
  font-size: 16px;
  font-weight: 600;
  margin: 0 0 6px;
  line-height: 1.3;
  color: var(--ins-text);
}
.ins-feed-row-excerpt {
  font-size: 13px;
  color: var(--ins-text-muted);
  margin: 0 0 8px;
  line-height: 1.45;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.ins-feed-row-meta {
  font-size: 12px;
  color: var(--ins-text-muted);
  line-height: 1.4;
}
.ins-feed-row-meta-sep { margin: 0 6px; color: #c4c8cf; }
/* Company name in meta — non-italic, semi-bold, same dark color as the rest
   of the card text (rather than the previous accent-blue italic). */
.ins-feed-row-meta em {
  font-style: normal;
  font-weight: 600;
  color: var(--ins-text);
}
.ins-feed-row-chevron {
  flex-shrink: 0;
  color: var(--ins-text-muted);
  font-size: 14px;
  margin-left: 4px;
}

/* Load more — outlined rounded-rect button with a chevron-down.
   width: fit-content lets `margin: auto` center it without a wrapper. */
.ins-load-more {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  width: fit-content;
  margin: 20px auto 0;
  padding: 10px 22px;
  background: #ffffff;
  color: var(--ins-accent-dark);
  border: 1px solid #e5e7eb;
  border-radius: 6px;
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  transition: border-color 0.15s, color 0.15s;
}
.ins-load-more:hover { border-color: var(--ins-accent); color: var(--ins-accent); }
/* `display: flex` above wins over the [hidden] user-agent style, so without
   this rule setting `more.hidden = true` from JS would have no visual effect. */
.ins-load-more[hidden] { display: none; }

.ins-loading { text-align: center; padding: 24px; }
.ins-spinner {
  display: inline-block;
  width: 24px;
  height: 24px;
  border: 3px solid var(--ins-border);
  border-top-color: var(--ins-accent);
  border-radius: 50%;
  animation: ins-spin 0.8s linear infinite;
}
@keyframes ins-spin { to { transform: rotate(360deg); } }

/* Skeleton placeholders — rendered synchronously at boot so the feed + trending
   containers occupy their real content shape BEFORE the fetch resolves. Real
   render replaces innerHTML. MHD-2022 W6.
   Shares the single `ins-shimmer` keyframes declared beside `.ins-feature-row`
   above. A second @keyframes of the same name does NOT scope to nearby rules —
   the last declaration in the sheet wins for every user of the name — so the
   px-based copy that used to live here silently retimed the feature-row
   shimmer. Percentage background-size keeps the sweep proportional across
   skeleton elements of very different widths (a 70px badge vs a full-width
   excerpt line), which the old fixed 800px did not. */
.ins-skel-shimmer,
.ins-skel-line {
  display: block;
  background: linear-gradient(90deg, #eef1f5 0%, #f7f8fa 50%, #eef1f5 100%);
  background-size: 200% 100%;
  animation: ins-shimmer 1.4s linear infinite;
  border-radius: 4px;
}
@media (prefers-reduced-motion: reduce) {
  .ins-skel-shimmer,
  .ins-skel-line { animation: none; }
}
/* Feed row skeleton — shape matches .ins-feed-row-link (padding + gap + thumb). */
.ins-feed-row-link--skel {
  display: flex;
  gap: 18px;
  padding: 16px 20px;
  align-items: center;
}
.ins-feed-row--skel .ins-feed-row-thumb {
  /* Override the picture background — the skeleton element IS the shimmer. */
  background: linear-gradient(90deg, #eef1f5 0%, #f7f8fa 50%, #eef1f5 100%);
  background-size: 200% 100%;
  animation: ins-shimmer 1.4s linear infinite;
}
.ins-feed-row--skel .ins-feed-row-body {
  flex-grow: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.ins-skel-line--badge   { width: 70px;  height: 16px; }
.ins-skel-line--title   { width: 80%;   height: 18px; }
.ins-skel-line--excerpt { width: 100%;  height: 14px; }
.ins-skel-line--meta    { width: 40%;   height: 12px; }
/* Trending skeleton — one line per item, matches real link height. */
.ins-trending-skel {
  padding: 5px 0;
  border-bottom: 1px solid var(--ins-border);
}
.ins-trending-skel:last-child { border-bottom: none; }
.ins-skel-line--trend { width: 90%; height: 14px; }
/* Mobile parity with .ins-feed-row-link's mobile override. */
@media (max-width: 768px) {
  .ins-feed-row-link--skel { gap: 12px; padding: 14px 14px; }
}

.ins-empty { text-align: center; padding: 48px 16px; color: var(--ins-text-muted); }
.ins-empty-msg { font-size: 14px; }

/* Sidebar — flex column at content height. Trending + CTA stack naturally
   with the standard 12px gap between them. */
.ins-sidebar { display: flex; flex-direction: column; gap: 12px; }
.ins-trending {
  background: var(--ins-card);
  border: 1px solid var(--ins-border);
  border-radius: 8px;
  padding: 14px 14px 10px;
  flex-shrink: 0;
}
.ins-trending > .ins-section-title { margin-bottom: 10px; }
.ins-trending-list { list-style: none; padding: 0; margin: 0; counter-reset: ins-trend; }
.ins-trending-list li {
  counter-increment: ins-trend;
  display: flex;
  gap: 10px;
  padding: 5px 0;
  border-bottom: 1px solid var(--ins-border);
}
.ins-trending-list li:last-child { border-bottom: none; padding-bottom: 0; }
.ins-trending-list li::before {
  content: counter(ins-trend);
  font-size: 15px;
  font-weight: 600;
  color: var(--ins-accent);
  width: 20px;
  flex-shrink: 0;
  line-height: 1.4;
}
.ins-trending-list a { text-decoration: none; color: var(--ins-text); font-size: 12px; line-height: 1.35; }
.ins-trending-list a:hover { color: var(--ins-accent); }

/* Daily email subscription CTA — light blue card, centered headline +
   inline subscribe form. POSTs to /api/newsletter/subscribe; success
   state replaces the form. Shown to everyone (including users already
   subscribed) — Mailchimp dedupes server-side. */
.ins-email-cta {
  background: #eef3fb;
  border: 1px solid #dbe5f1;
  border-radius: 8px;
  padding: 16px 14px;
  text-align: center;
  flex-shrink: 0;
}
.ins-ec-title {
  font-size: 15px;
  font-weight: 700;
  margin: 0 0 8px;
  line-height: 1.25;
  color: var(--ins-text);
}
.ins-ec-body {
  font-size: 12px;
  color: var(--ins-text-muted);
  margin: 0 0 12px;
  line-height: 1.45;
}
.ins-ec-form { display: flex; flex-direction: column; gap: 8px; }
.ins-ec-form[hidden] { display: none; }
.ins-ec-input {
  width: 100%;
  padding: 10px 12px;
  border: 1px solid #cbd5e1;
  border-radius: 6px;
  font-size: 13px;
  color: #111827;
  background: #fff;
  box-sizing: border-box;
  transition: border-color 0.15s, box-shadow 0.15s;
}
.ins-ec-input::placeholder { color: #9ca3af; }
.ins-ec-input:focus {
  outline: none;
  border-color: var(--ins-accent);
  box-shadow: 0 0 0 3px rgba(47, 128, 237, 0.15);
}
.ins-ec-error {
  color: #c53030;
  font-size: 12px;
  text-align: left;
}
.ins-ec-error:empty { display: none; }
.ins-ec-btn {
  display: block;
  width: 100%;
  padding: 10px 16px;
  background: #f5a623;
  color: white;
  border: none;
  border-radius: 6px;
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  transition: background 0.15s;
}
.ins-ec-btn:hover:not(:disabled) { background: #de9311; }
.ins-ec-btn:disabled { background: #d1d5db; cursor: not-allowed; }
.ins-ec-success {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  padding: 4px 0 2px;
  color: var(--ins-text);
}
.ins-ec-success[hidden] { display: none; }
.ins-ec-success i { color: #16a34a; font-size: 22px; }
.ins-ec-success p { margin: 0; font-size: 13px; line-height: 1.4; }

/* Tablet + small-desktop — 8 across gets too tight below ~1200px; drop to
   4-up so the tiles keep breathing room and Company & Project's label still
   wraps cleanly. Bumped from 1024px to 1199px when the row grew to 8 tiles. */
@media (max-width: 1199px) {
  /* 4 cols → 8 tiles = 2 rows → 2*200 + 10 gap = 410px. MHD-2022 W6. */
  .ins-category-cards { grid-template-columns: repeat(4, minmax(0, 1fr)); min-height: 410px; }
}

/* Mobile. */
@media (max-width: 768px) {
  .ins-hero { grid-template-columns: 1fr; }
  /* Reserve the supporting container's height at the 2x2 mobile layout
     (2 cards wide, 2 rows tall, each 16/10). Approximate container ratio =
     col-width / (2 * col-height) ~= 8/5. Without this reservation the
     container is 0px pre-hydration and pops when cards inject. MHD-2022 W6. */
  .ins-hero-supporting { grid-template-rows: none; grid-template-columns: 1fr 1fr; aspect-ratio: 8 / 5; }
  .ins-hero-main .ins-hero-card { aspect-ratio: 16 / 10; }
  .ins-hero-main .ins-hero-title { font-size: 20px; }
  /* Once stacked, the supporting cards have no parent height to fill — give
     them an aspect-ratio fallback so they don't collapse. */
  .ins-hero-supporting .ins-hero-card { height: auto; aspect-ratio: 16 / 10; }
  .ins-grid {
    grid-template-columns: 1fr;
    grid-template-areas:
      "title"
      "controls"
      "stack"
      "loadmore"
      "sidebar";
  }
  /* 3 cols → 8 tiles = ceil(8/3) = 3 rows → 3*200 + 2*10 = 620px. */
  .ins-category-cards { grid-template-columns: repeat(3, minmax(0, 1fr)); min-height: 620px; }
  .ins-feed-controls { flex-wrap: wrap; }
  .ins-search-input { width: 100%; min-width: 0; flex-shrink: 0; }
  /* On mobile the chip row wraps; let each chip size to ~half a row. */
  .ins-chip-date,
  #ins-category.ins-chip,
  #ins-commodity.ins-chip,
  #ins-region.ins-chip { width: calc(50% - 4px); flex: 0 0 auto; min-width: 0; }
  .ins-feed-row-link { gap: 12px; padding: 14px 14px; }
  .ins-feed-row-thumb { width: 84px; height: 84px; }
  .ins-feed-row-title { font-size: 15px; }
  .ins-feed-row-excerpt { -webkit-line-clamp: 1; }
  .ins-feed-row-chevron { display: none; }
  .ins-sidebar { order: 2; }
}

@media (max-width: 480px) {
  /* 2 cols → 8 tiles = 4 rows → 4*200 + 3*10 = 830px. */
  .ins-category-cards { grid-template-columns: repeat(2, minmax(0, 1fr)); min-height: 830px; }
  /* 1 col × 4 rows of 16/10 cards ~= 2:5 aspect ratio. */
  .ins-hero-supporting { grid-template-columns: 1fr; grid-auto-rows: auto; aspect-ratio: 2 / 5; }
}
