/*
 * Default styling for a channel feed rendered by this package.
 *
 * How to use it
 * -------------
 * Serve this file and link it, or inline it into a <style> tag. A post is
 * self-contained: everything it needs is declared on .chf-post, so it renders
 * correctly on its own, inside the .chf-feed wrapper, or dropped into any
 * markup of your own. The wrapper is optional and merely stacks posts.
 *
 * How to customise it
 * -------------------
 * Every colour and measurement is a custom property, so a site overrides values
 * instead of fighting rules. Override them on the post, and narrow the scope on
 * the left side of the selector when only part of the page is meant:
 *
 *     .chf-post          { --chf-accent: #c00; --chf-width: 100%; }
 *     .sidebar .chf-post { --chf-accent: #c00; }
 *
 * Setting a property on a parent element has no effect: a post declares its own
 * values, and an own declaration always beats an inherited one.
 *
 * Two levels are exposed. The palettes (--chf-light-* / --chf-dark-*) hold the
 * raw colours and are declared once. The semantic properties (--chf-bg,
 * --chf-text, ...) are what the rules actually read, and they simply point at
 * one of the palettes. Override a palette entry to recolour both themes at
 * once, or a semantic property to change one specific thing.
 *
 * Themes
 * ------
 * By default a post follows the reader's system setting. A site with its own
 * theme switch overrides that with .chf-theme-dark or .chf-theme-light, either
 * on the post or on any element above it — the wrapper, a section, <body>.
 *
 * Specificity
 * -----------
 * Rules are scoped through :where(), which contributes no specificity, so every
 * rule below weighs exactly one class. Any site rule with a single class beats
 * it. There is no !important anywhere and no bare element selectors, so nothing
 * here can reach outside a post.
 *
 * Defaults are taken from Telegram's own widget-frame.css so that the feed
 * resembles the web preview out of the box.
 */

.chf-post {
  /* Palettes: raw colours, declared once. */
  --chf-light-bg: #ffffff;
  --chf-light-border: #d7e3ec;
  --chf-light-text: #000000;
  --chf-light-muted: #7d7f81;
  --chf-light-accent: #2481cc;
  --chf-light-accent-line: #4ca3e2;
  --chf-light-accent-soft: rgba(36, 129, 204, 0.12);
  --chf-light-surface: rgba(0, 0, 0, 0.04);
  --chf-light-button: #b5c0c8;
  --chf-light-button-hover: #a3aeb6;
  --chf-light-button-text: #ffffff;
  --chf-light-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);

  --chf-dark-bg: #1e1e1e;
  --chf-dark-border: #364049;
  --chf-dark-text: #ffffff;
  --chf-dark-muted: #7d7f81;
  --chf-dark-accent: #64b5ef;
  --chf-dark-accent-line: #64b5ef;
  --chf-dark-accent-soft: rgba(100, 181, 239, 0.12);
  --chf-dark-surface: rgba(255, 255, 255, 0.08);
  --chf-dark-button: #45566a;
  --chf-dark-button-hover: #52657b;
  --chf-dark-button-text: #ffffff;
  --chf-dark-shadow: 0 2px 4px rgba(0, 0, 0, 0.4);

  /* Semantic colours: what the rules read. Light theme by default. */
  --chf-bg: var(--chf-light-bg);
  --chf-border: var(--chf-light-border);
  --chf-text: var(--chf-light-text);
  --chf-text-muted: var(--chf-light-muted);
  --chf-accent: var(--chf-light-accent);
  --chf-link: var(--chf-light-accent);
  --chf-link-hover: var(--chf-light-accent);

  --chf-reply-bg: var(--chf-light-surface);
  --chf-reply-bar: var(--chf-light-accent);
  --chf-link-card-bg: var(--chf-light-surface);
  --chf-link-card-bar: var(--chf-light-accent);

  --chf-poll-bar: var(--chf-light-accent-line);
  --chf-poll-bar-bg: var(--chf-light-surface);
  --chf-poll-percent: var(--chf-light-text);

  --chf-button-bg: var(--chf-light-button);
  --chf-button-hover-bg: var(--chf-light-button-hover);
  --chf-button-text: var(--chf-light-button-text);

  --chf-reaction-bg: var(--chf-light-accent-soft);
  --chf-reaction-text: var(--chf-light-accent);

  --chf-code-bg: var(--chf-light-surface);
  --chf-code-text: var(--chf-light-text);

  --chf-unsupported-bg: var(--chf-light-surface);
  --chf-unsupported-text: var(--chf-light-muted);

  /* Sits on top of the video frame, so it stays dark in both themes. */
  --chf-video-duration-bg: rgba(0, 0, 0, 0.5);
  --chf-video-duration-text: #ffffff;

  /* Metrics. */
  --chf-width: 420px;
  --chf-radius: 15px;
  --chf-media-radius: 6px;
  --chf-button-radius: 10px;
  --chf-border-width: 1px;
  --chf-padding: 12px 17px;
  --chf-gap: 10px;
  --chf-media-gap: 2px;

  /*
   * Media grows with the post, so a wide --chf-width makes for very tall
   * pictures. Cap them here — "none" by default, since at the standard width
   * there is nothing to cap:
   *
   *     .chf-post { --chf-media-max-height: 60vh; }
   *
   * --chf-media-fit decides what happens to a picture that hits the cap:
   * "contain" shows all of it and leaves empty space around, "cover" fills the
   * box and crops the overflow, which is what Telegram does in albums.
   */
  --chf-media-max-height: none;
  --chf-media-fit: contain;

  /*
   * Posts are separated by a border, because a post sits on whatever background
   * the host page has and a shadow this soft would not tell white posts apart
   * on a white page. The preview does the opposite: no border and a barely
   * visible shadow, relying on its own grey page background. To match it, drop
   * the border and turn the shadow on:
   *
   *     .chf-post { --chf-border-width: 0; --chf-shadow: var(--chf-light-shadow); }
   *     .chf-post.chf-theme-dark { --chf-shadow: var(--chf-dark-shadow); }
   */
  --chf-shadow: none;

  --chf-font: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  --chf-font-mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  --chf-font-size: 16px;
  --chf-font-size-small: 14px;
  --chf-line-height: 21px;
  --chf-line-height-small: 19px;
}

/* Follows the system setting unless the site pinned the light theme. */
@media (prefers-color-scheme: dark) {
  .chf-post:not(.chf-theme-light):not(:where(.chf-theme-light) *) {
    --chf-bg: var(--chf-dark-bg);
    --chf-border: var(--chf-dark-border);
    --chf-text: var(--chf-dark-text);
    --chf-text-muted: var(--chf-dark-muted);
    --chf-accent: var(--chf-dark-accent);
    --chf-link: var(--chf-dark-accent);
    --chf-link-hover: var(--chf-dark-accent);

    --chf-reply-bg: var(--chf-dark-surface);
    --chf-reply-bar: var(--chf-dark-accent);
    --chf-link-card-bg: var(--chf-dark-surface);
    --chf-link-card-bar: var(--chf-dark-accent);

    --chf-poll-bar: var(--chf-dark-accent-line);
    --chf-poll-bar-bg: var(--chf-dark-surface);
    --chf-poll-percent: var(--chf-dark-text);

    --chf-button-bg: var(--chf-dark-button);
    --chf-button-hover-bg: var(--chf-dark-button-hover);
    --chf-button-text: var(--chf-dark-button-text);

    --chf-reaction-bg: var(--chf-dark-accent-soft);
    --chf-reaction-text: var(--chf-dark-accent);

    --chf-code-bg: var(--chf-dark-surface);
    --chf-code-text: var(--chf-dark-text);

    --chf-unsupported-bg: var(--chf-dark-surface);
    --chf-unsupported-text: var(--chf-dark-muted);
  }
}

/* Pinned by the site, regardless of the system setting. */
.chf-post.chf-theme-dark,
:where(.chf-theme-dark) .chf-post {
  --chf-bg: var(--chf-dark-bg);
  --chf-border: var(--chf-dark-border);
  --chf-text: var(--chf-dark-text);
  --chf-text-muted: var(--chf-dark-muted);
  --chf-accent: var(--chf-dark-accent);
  --chf-link: var(--chf-dark-accent);
  --chf-link-hover: var(--chf-dark-accent);

  --chf-reply-bg: var(--chf-dark-surface);
  --chf-reply-bar: var(--chf-dark-accent);
  --chf-link-card-bg: var(--chf-dark-surface);
  --chf-link-card-bar: var(--chf-dark-accent);

  --chf-poll-bar: var(--chf-dark-accent-line);
  --chf-poll-bar-bg: var(--chf-dark-surface);
  --chf-poll-percent: var(--chf-dark-text);

  --chf-button-bg: var(--chf-dark-button);
  --chf-button-hover-bg: var(--chf-dark-button-hover);
  --chf-button-text: var(--chf-dark-button-text);

  --chf-reaction-bg: var(--chf-dark-accent-soft);
  --chf-reaction-text: var(--chf-dark-accent);

  --chf-code-bg: var(--chf-dark-surface);
  --chf-code-text: var(--chf-dark-text);

  --chf-unsupported-bg: var(--chf-dark-surface);
  --chf-unsupported-text: var(--chf-dark-muted);
}

/* Layout */

/*
 * A post carries everything it needs, so it can be dropped into any markup on
 * its own. The .chf-feed wrapper is optional and only stacks posts; it declares
 * no properties of its own, which is why the spacing between posts lives on the
 * post itself.
 */
.chf-post {
  box-sizing: border-box;
  /*
   * Width comes from the container, capped by --chf-width, so every post in a
   * feed is the same width no matter how little content it holds. Without the
   * 100% a post shrinks to its content in any layout that does not stretch its
   * children — a centred flex column, for one.
   */
  width: 100%;
  max-width: var(--chf-width);
  margin-bottom: var(--chf-gap);
  padding: var(--chf-padding);
  background: var(--chf-bg);
  border: var(--chf-border-width) solid var(--chf-border);
  border-radius: var(--chf-radius);
  box-shadow: var(--chf-shadow);
  font-family: var(--chf-font);
  font-size: var(--chf-font-size);
  line-height: var(--chf-line-height);
  color: var(--chf-text);
  overflow-wrap: break-word;
}

.chf-feed {
  display: flex;
  flex-direction: column;
}

:where(.chf-feed) .chf-post:last-child {
  margin-bottom: 0;
}

/* Header: channel name, via bot, forward origin */

:where(.chf-post) .chf-author,
:where(.chf-post) .chf-forwarded {
  font-size: var(--chf-font-size);
  line-height: 23px;
  color: var(--chf-accent);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

:where(.chf-post) .chf-via {
  color: var(--chf-text-muted);
}

/* Reply quote */

:where(.chf-post) .chf-reply {
  display: block;
  margin: 6px 0;
  padding: 3px 8px;
  border-left: 2px solid var(--chf-reply-bar);
  border-radius: 0 var(--chf-media-radius) var(--chf-media-radius) 0;
  background: var(--chf-reply-bg);
  color: inherit;
  text-decoration: none;
}

:where(.chf-post) .chf-reply-author {
  color: var(--chf-accent);
  font-size: var(--chf-font-size-small);
  line-height: var(--chf-line-height-small);
}

:where(.chf-post) .chf-reply-text {
  color: var(--chf-text-muted);
  font-size: var(--chf-font-size-small);
  line-height: var(--chf-line-height-small);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Media */

:where(.chf-post) .chf-media {
  margin: 8px 0;
}

:where(.chf-post) .chf-media-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--chf-media-gap);
}

:where(.chf-post) .chf-photo,
:where(.chf-post) .chf-video {
  display: block;
  width: 100%;
  height: auto;
  max-height: var(--chf-media-max-height);
  object-fit: var(--chf-media-fit);
  border-radius: var(--chf-media-radius);
}

:where(.chf-post) .chf-video-wrap {
  position: relative;
}

:where(.chf-post) .chf-video-duration {
  position: absolute;
  right: 6px;
  bottom: 6px;
  padding: 1px 5px;
  border-radius: 400px;
  background: var(--chf-video-duration-bg);
  color: var(--chf-video-duration-text);
  font-size: 12px;
  line-height: 17px;
}

:where(.chf-post) .chf-document {
  display: flex;
  flex-direction: column;
  margin: 8px 0;
  padding: 8px 10px;
  border-radius: var(--chf-media-radius);
  background: var(--chf-reply-bg);
}

:where(.chf-post) .chf-document-title {
  color: var(--chf-accent);
}

:where(.chf-post) .chf-document-size {
  color: var(--chf-text-muted);
  font-size: var(--chf-font-size-small);
  line-height: var(--chf-line-height-small);
}

/* Link preview card */

:where(.chf-post) .chf-link {
  display: block;
  margin: 8px 0;
  padding: 4px 10px;
  border-left: 2px solid var(--chf-link-card-bar);
  border-radius: 0 var(--chf-media-radius) var(--chf-media-radius) 0;
  background: var(--chf-link-card-bg);
  color: inherit;
  text-decoration: none;
}

:where(.chf-post) .chf-link-site {
  color: var(--chf-accent);
  font-size: var(--chf-font-size-small);
  line-height: var(--chf-line-height-small);
}

:where(.chf-post) .chf-link-title {
  font-weight: 500;
}

:where(.chf-post) .chf-link-desc {
  color: var(--chf-text-muted);
  font-size: var(--chf-font-size-small);
  line-height: var(--chf-line-height-small);
}

:where(.chf-post) .chf-link-image {
  display: block;
  width: 100%;
  height: auto;
  max-height: var(--chf-media-max-height);
  object-fit: var(--chf-media-fit);
  margin-top: 6px;
  border-radius: var(--chf-media-radius);
}

/* Poll */

:where(.chf-post) .chf-poll {
  margin: 8px 0;
}

:where(.chf-post) .chf-poll-question {
  font-weight: 500;
}

:where(.chf-post) .chf-poll-type,
:where(.chf-post) .chf-poll-voters {
  color: var(--chf-text-muted);
  font-size: var(--chf-font-size-small);
  line-height: var(--chf-line-height-small);
}

:where(.chf-post) .chf-poll-option {
  display: grid;
  grid-template-columns: 3em 1fr;
  align-items: baseline;
  margin-top: 6px;
}

:where(.chf-post) .chf-poll-percent {
  color: var(--chf-poll-percent);
  font-size: var(--chf-font-size-small);
}

:where(.chf-post) .chf-poll-bar {
  height: 4px;
  margin-top: 6px;
  border-radius: 2px;
  background: var(--chf-poll-bar-bg);
}

:where(.chf-post) .chf-poll-bar-fill {
  height: 100%;
  min-width: 4px;
  border-radius: 2px;
  background: var(--chf-poll-bar);
}

/* Post body */

:where(.chf-post) .chf-text {
  margin-top: 6px;
}

:where(.chf-post) .chf-text a {
  color: var(--chf-link);
  text-decoration: none;
}

:where(.chf-post) .chf-text a:hover {
  color: var(--chf-link-hover);
  text-decoration: underline;
}

:where(.chf-post) .chf-text b,
:where(.chf-post) .chf-text strong {
  font-weight: 500;
}

:where(.chf-post) .chf-text code,
:where(.chf-post) .chf-text pre {
  padding: 0 4px;
  border-radius: 4px;
  background: var(--chf-code-bg);
  color: var(--chf-code-text);
  font-family: var(--chf-font-mono);
  font-size: 0.9em;
}

/*
 * Telegram emoji. The sanitizer emits <i class="chf-emoji" style="…"> with the
 * unicode character inside, so the image is painted by the pseudo-element on
 * top of it: if the image never loads, the character underneath shows through
 * instead of a blank gap.
 */
:where(.chf-post) .chf-emoji {
  position: relative;
  display: inline-block;
  width: 1.25em;
  height: 1.25em;
  vertical-align: top;
  overflow: hidden;
  white-space: nowrap;
  font-style: normal;
  background-repeat: no-repeat;
  background-position: -1000px -1000px;
  background-size: contain;
}

/*
 * The unicode character underneath shows through while the image is missing,
 * and hides as soon as one is set — either by the sanitizer or, for a custom
 * emoji, by whatever script resolves it later. Without this the fallback and
 * the picture would be drawn on top of each other.
 */
:where(.chf-post) .chf-emoji[style] {
  color: transparent;
}

:where(.chf-post) .chf-emoji::before {
  content: "";
  position: absolute;
  inset: 0;
  background: inherit;
  background-position: center;
  pointer-events: none;
}

:where(.chf-post) .chf-text blockquote {
  margin: 6px 0;
  padding: 2px 8px;
  border-left: 2px solid var(--chf-reply-bar);
  background: var(--chf-reply-bg);
}

/* Inline keyboard */

:where(.chf-post) .chf-buttons {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-top: 8px;
}

:where(.chf-post) .chf-button-row {
  display: flex;
  gap: 6px;
}

:where(.chf-post) .chf-button {
  flex: 1;
  padding: 7px 12px 6px;
  border-radius: var(--chf-button-radius);
  background: var(--chf-button-bg);
  color: var(--chf-button-text);
  font-weight: 500;
  text-align: center;
  text-decoration: none;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

:where(.chf-post) .chf-button:hover {
  background: var(--chf-button-hover-bg);
}

/* Reactions */

:where(.chf-post) .chf-reactions {
  display: flex;
  flex-wrap: wrap;
  gap: 2px;
  margin-top: 8px;
}

:where(.chf-post) .chf-reaction {
  padding: 3px 8px 3px 5px;
  border-radius: 400px;
  background: var(--chf-reaction-bg);
  color: var(--chf-reaction-text);
  font-size: var(--chf-font-size-small);
  line-height: normal;
}

/* Footer */

:where(.chf-post) .chf-footer {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
  margin-top: 8px;
  color: var(--chf-text-muted);
  font-size: var(--chf-font-size-small);
  line-height: var(--chf-line-height-small);
}

:where(.chf-post) .chf-date {
  color: inherit;
  text-decoration: none;
  white-space: nowrap;
}

/* Posts the web preview does not render */

:where(.chf-post) .chf-unsupported {
  margin: 8px 0;
  padding: 12px;
  border-radius: var(--chf-media-radius);
  background: var(--chf-unsupported-bg);
  color: var(--chf-unsupported-text);
  text-align: center;
}

:where(.chf-post) .chf-unsupported-link {
  display: inline-block;
  margin-top: 6px;
  color: var(--chf-link);
  text-decoration: none;
}

:where(.chf-post) .chf-unsupported-link:hover {
  text-decoration: underline;
}
