/* Write manual project CSS here.
 * This file is loaded directly after the generated CSS bundles.
 * It is intentionally outside _v2/css/src so saving it does not run Tailwind.
 */

/* ─── Font ───────────────────────────────────────────────────────
   @font-face has no Tailwind utility equivalent, so the font lives here
   (hand-written, loaded after the Tailwind bundles). */
@font-face {
  font-family: 'IRANSansFaNum';
  src: url('/_v2/fonts/IRANSansFaNum-Regular.woff2') format('woff2');
  font-weight: normal;
  font-style: normal;
  font-display: swap;
}

html, body, input, button, select, textarea {
  font-family: 'IRANSansFaNum', sans-serif;
}

/* ─── Dark mode ──────────────────────────────────────────────────
   Class-based (<html class="dark">). The design tokens (defined via @theme in
   src/tailwind.css and emitted as :root CSS vars) are re-pointed to a dark
   palette here, so every token utility (text-brand, bg-surface, border-line,
   …) flips automatically — no per-element dark: variants needed for tokenized
   colors. The page background + default text follow the page/text tokens. */
:root { color-scheme: light; }
.dark {
  color-scheme: dark;
  --color-brand: #5e9bdd;      /* lighter blue: readable on dark surfaces */
  --color-brand-dark: #4a86c9;
  --color-ink: #f2f2f2;        /* titles / hairline rules */
  --color-body: #d4d4d4;
  --color-muted: #9aa0a6;
  --color-subtle: #aab0b6;
  --color-lead: #c8c8c8;       /* article lead paragraph */
  --color-line: #434a54;       /* borders: visible hairline above page/surface/fill */
  --color-fill: #353a44;       /* light fills → dark fills */
  --color-page: #23262d;       /* page background (softer than near-black) */
  --color-surface: #2b2f37;    /* cards, header bar, menu panels (above page) */
  --color-text: #e6e6e6;       /* default body text */
}
body {
  background-color: var(--color-page);
  color: var(--color-text);
}

/* ─── Dark mode: darken hardcoded light borders ──────────────────
   Many elements use literal light-gray/beige border hexes (border-[#ccc],
   border-[#ddd], border-[#e6d9ce], …) that do NOT flip with the tokens, so
   in dark mode they render as bright hairlines on the dark background.
   Re-point them to the --color-line token in dark mode only — light mode
   keeps the original values. New markup should use border-line directly so
   it flips automatically.
   NB: uses [class*=…] substring matching (not the exact escaped classnames)
   so it also catches PREFIXED variants — responsive (min-[800px]:border-[#ddd],
   ×20) and pseudo (after:border-[#ddd] L-frame in FRONT_W1/W2/X). */
.dark :is(
  [class*="border-[#ccc]"],
  [class*="border-[#ddd]"],
  [class*="border-[#dcdcdc]"],
  [class*="border-[#dbdbdb]"],
  [class*="border-[#d6d6d6]"],
  [class*="border-[#e5e5e5]"],
  [class*="border-[#efefef]"],
  [class*="border-[#f0f0f0]"],
  [class*="border-[#babebf]"],
  [class*="border-[#e6d9ce]"]
) {
  border-color: var(--color-line);
}
/* Pseudo-element border frames (border-color lives on ::after/::before). */
.dark [class*="after:border-[#ddd]"]::after {
  border-color: var(--color-line);
}

/* ─── Dark mode: keyword chips (content/keywords.ctp) ────────────────
   The chips are filled `bg-brand` with white text. In dark mode --color-brand
   flips to a light blue (#5e9bdd) meant for TEXT on dark surfaces, which drops
   white-on-chip to ~2.9:1 (fails WCAG AA). Re-point just these chips to the
   dark surface tone so they read as neutral tags rather than blue buttons
   (white on #2b2f37 ≈ 12.4:1, hover #353a44 ≈ 10.3:1). Matched via the chip's
   unique clip-path utility substring (same approach as the border block above). */
.dark [class*="clip-path:polygon(10px_0"] {
  background-color: #2b2f37;
}
.dark [class*="clip-path:polygon(10px_0"]:hover {
  background-color: #353a44;
}

/* ─── Dark mode: box header rule ─────────────────────────────────────
   Box headers (پربازدیدها, برگزیده‌ها, دیدگاه و تحلیل, …) are preceded by three
   stacked dotted near-black spans — that IS the live design, so LIGHT MODE KEEPS
   ALL THREE (`1px dotted #111`, `padding-bottom:2.3px`), verified against live.
   Only in dark, where --color-ink is near-white and three dotted rules glare,
   they collapse to a single plain --color-line hairline. Kept as one override
   rather than 237 markup edits, so the treatment stays tweakable in one place. */
.dark span.border-t.border-dotted.border-ink {
  border-top-style: solid;
  border-color: var(--color-line);
}
.dark span.border-t.border-dotted.border-ink ~ span.border-t.border-dotted.border-ink {
  display: none;
}

/* ─── Dark mode: news-card titles ────────────────────────────────────
   Live paints list/card titles `#333`, so the markup uses `text-body` and light
   mode matches live exactly. In dark, #d4d4d4 reads flat against the card, so
   these titles are lifted to the brighter title tone. Matched on the utility
   substrings (the shared title class string) so it stays a single lever. */
.dark [class*="leading-[26px]"][class*="text-body"] {
  color: var(--color-ink);
}

/* ─── Dark mode: sidebar tab strip (FRONT_B311/B312/B321/B322) ───────
   main.js toggles the `bg-line` class on the active <li> (setupTabs), so the
   active-tab fill can't be a `dark:` utility in the .ctp — it would paint the
   inactive tab too. Re-point the toggled class instead. */
.dark .tabs_title > li.bg-line {
  background-color: #2b2f37;
}

/* ─── Dark mode: link hover ──────────────────────────────────────────
   Links across the site hover to `text-brand`. In dark mode they instead fade
   toward white, matching the video box (FRONT_VIDEO uses hover:text-white/80).
   Matched on the utility substring so responsive/nested prefixes are caught. */
.dark [class*="hover:text-brand"]:hover {
  color: rgba(255, 255, 255, 0.8);
}

/* ─── Dark mode: article body ────────────────────────────────────────
   default.css sets the body to --color-ink (near-white, matching titles);
   in dark it reads too hot for long-form text, so drop it to the body tone. */
.dark .news_article_content.ck_editor,
.dark .news_article_content.ck_editor p {
  color: #d4d4d4;
}

/* ─── Dark mode: tables (site-wide) ──────────────────────────────────
   Near-black header row + alternating row fills. Painted on the CELLS so the
   rules survive any tr-level utility, and header rows (any <tr> containing a
   <th>) are excluded from the zebra so a mixed header row stays uniform.
   #archive-calendar opts out — it carries its own dark colors because of the
   extra Friday-column tint. */
.dark table:not(#archive-calendar) th,
.dark table:not(#archive-calendar) tr:has(> th) > td {
  background-color: #1c1c1c;
}
/* CKEditor tables have no <thead> — the header is the first <tr> inside
   <tbody> — so the zebra is keyed off whether this tbody holds a header row.
   Either way the first DATA row lands on #2b2f37. */
.dark table:not(#archive-calendar) tbody:has(tr > th) tr:not(:has(> th)):nth-child(even) > td,
.dark table:not(#archive-calendar) tbody:not(:has(tr > th)) tr:nth-child(odd) > td {
  background-color: #2b2f37;
}
.dark table:not(#archive-calendar) tbody:has(tr > th) tr:not(:has(> th)):nth-child(odd) > td,
.dark table:not(#archive-calendar) tbody:not(:has(tr > th)) tr:nth-child(even) > td {
  background-color: #23262d;
}

/* ─── Prices pages: embedded "ecodata" widget (CMS content) ──────────
   /tags/قیمت_طلا & friends render a CMS-authored price widget whose markup
   carries its own inline <style> (font-family: IRANYekan, its own filter-btn
   colors). That block sits in the body, so it wins ties against this file —
   these overrides are deliberately more specific.
   The widget's own table colors are already superseded by the site-wide dark
   table rules above. */
body .ecodata-widget,
body .ecodata-widget * {
  font-family: 'IRANSansFaNum', sans-serif;
}
/* chart range buttons (۲۴ ساعت اخیر / هفته گذشته / ماه گذشته) — the widget
   hovers them to #111827 in dark; match the site's near-black instead. */
.dark .ecodata-widget .filter-btn:hover {
  background-color: #1c1c1c;
}

/* ─── LANDING_A1 featured carousel pagination ────────────────────
   Splide generates the pagination <ul>/<button> markup at runtime, so it
   can't carry Tailwind utilities. The blue pill dots are themed here,
   scoped to .service-level so other carousels are unaffected. */
.service-level .splide__pagination {
  position: relative;
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 8px;
  margin: 0;
  padding: 0;
}
.service-level .splide__pagination__page {
  width: 25px;
  height: 5px;
  margin: 0;
  padding: 0;
  border: 0;
  border-radius: 5px;
  cursor: pointer;
  background-color: #d8d8d8;
  transition: background-color 0.3s;
}
.service-level .splide__pagination__page.is-active {
  background-color: var(--color-brand);
  transform: none;
}

/* ─── Header market ticker (CAROUSEL_HEADER) ─────────────────────
   The header element renders an empty <div id="carousel_header">, which
   main.js / main-news.js fill with the market-ticker fragment fetched from
   /CAROUSEL_HEADER.html. That fragment uses fixed classnames (.market-carousel,
   .view-content, .price-percentage, li.plus/.minus/.equal) with no Tailwind
   utilities, so it is styled here. Ported from the previous site; kept as a
   self-contained dark scrolling marquee band (matches the live site) that reads
   the same in light and dark mode. The JS clones .view-content into .content so
   the row scrolls seamlessly. */
.market-carousel {
  overflow: hidden;
  position: relative;
  width: 100%;
  background: #1c1c1c;
  padding: 10px 0;
}
.market-carousel .content {
  display: flex;
  flex-direction: row;
  width: max-content;
  animation: market-carousel-scroll 65s linear infinite;
}
.market-carousel ul.view-content {
  display: flex;
  padding: 0;
  margin: 0;
  list-style: none;
}
.market-carousel li {
  display: flex;
  align-items: center;
  gap: 1rem;
  flex-direction: row;
  margin-right: 10px;
  border: 1px solid #515151;
  padding: 5px 12px;
}
.market-carousel .content .view-content li span,
.market-carousel .content .view-content li a {
  color: #fff;
  font-size: 12px;
}
.market-carousel .price-percentage span:first-child {
  font-size: 14px;
}
.market-carousel .content .view-content li.plus .price-percentage * {
  color: #4db250;
}
.market-carousel .content .view-content li.minus .price-percentage * {
  color: #f05143;
}
.market-carousel .content .view-content li.equal .price-percentage * {
  color: #ffc107;
}
/* Tailwind Preflight resets `svg { display: block; vertical-align: middle }`,
   which drops each up/down arrow onto its own line and inflates the row height
   (56px → 66px). The live site renders these arrows inline — restore that so
   the arrow sits beside the percentage. */
.market-carousel .wrapper svg {
  display: inline;
  vertical-align: baseline;
}
@keyframes market-carousel-scroll {
  0% {
    transform: translateX(50%);
  }
  100% {
    transform: translateX(0);
  }
}

/* ─── Top-of-page banner slot (Elements/structure/top-ads.ctp) ───
   Home & service pages: K0 desktop / K1 mobile.
   News detail page:     O0 desktop / O1 mobile.
   Desktop: the banner is sticky at z-index 0 and the page wrapper sits above
   it at z-index 1, so scrolling slides the page over the banner (eco-iran
   style) instead of pushing it out of the way. Mobile: fixed on top (below).
   Styled here rather than with Tailwind utilities because the markup inside
   .adsTop is emitted by the CMS ad template (Advertisements/templates/
   resource.twig) and cannot carry classes of its own. */
.adsTop {
  position: sticky;
  top: 0;
  z-index: 0;
  background-color: var(--color-surface);
}
.outer_wrapper {
  position: relative;
  z-index: 1;
  background-color: var(--color-page);
}
/* Desktop/mobile creatives swap exactly where the header switches (800px). */
.adsTop .show-adv-desktop {
  display: none;
}
.adsTop .show-adv-mobile {
  display: block;
}
@media screen and (min-width: 800px) {
  .adsTop .show-adv-desktop {
    display: block;
  }
  .adsTop .show-adv-mobile {
    display: none;
  }
}
/* the ad slot's own default spacing is not wanted inside a full-bleed banner */
.adsTop .show-adv-desktop > div,
.adsTop .show-adv-mobile > div {
  padding: 0;
}
.adsTop .type-resource-image {
  position: relative;
  opacity: 0;
  transition: opacity 0.3s ease;
}
.adsTop .type-resource-image.visible {
  opacity: 1;
}
.adsTop .type-resource-image a {
  display: block;
}
.adsTop .type-resource-image img {
  display: block;
  width: 100%;
  max-width: 100%;
  height: auto;
  margin: 0 auto;
  border-radius: 0;
}
.adsTop .adv-close-btn {
  position: absolute;
  top: 35px;
  left: 35px;
  background: #00000066;
  color: #fff;
  border: none;
  padding: 4px 8px 2px 8px;
  line-height: 1;
  cursor: pointer;
  border-radius: 4px;
  z-index: 10;
}
/* Mobile (K1 / O1): the banner is pinned to the top of the viewport so it stays
   visible while scrolling. Being fixed it no longer takes space in the flow, so
   .outer_wrapper is pushed down by --adtop (the banner's real height, published
   by top-ads.ctp). z-index sits above .outer_wrapper's stacking context. */
@media screen and (max-width: 799px) {
  .adsTop {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    z-index: 10000000;
  }
  .outer_wrapper {
    margin-top: var(--adtop, 0px);
  }
  .adsTop .adv-close-btn {
    top: 5px;
    left: 5px;
  }
}
/* The mobile menu drawer is `position: fixed`, so it cannot inherit the header's
   position. top-ads.ctp publishes the header's real bottom edge as --menutop
   (remeasured on scroll/resize) so the drawer opens flush under the header even
   when the banner has pushed it down. 66px = header height with no banner. */
@media screen and (max-width: 799px) {
  #nav-toggle {
    top: var(--menutop, 66px);
    max-height: calc(100vh - var(--menutop, 66px));
  }
}

/* ─── Ad-slot QA placeholders (?SHOWADVPOS, painted by head/foot.ctp) ───
   Kept here rather than in a <style> inside <body>, which is invalid HTML. */
.ad-placeholder {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 4px 12px;
  width: 100%;
  max-width: 100%;
  margin-inline: auto;
  padding: 4px;
  box-sizing: border-box;
  border: 1px dashed #c7c7c7;
  border-radius: 6px;
  background: repeating-linear-gradient(45deg, #f4f4f5, #f4f4f5 10px, #eeeeef 10px, #eeeeef 20px);
  color: #9a9a9a;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: .5px;
  line-height: 1.4;
  text-align: center;
  overflow: hidden;
}
.ad-placeholder .adph-pos {
  color: #0d7377;
  font-weight: 800;
}
