HEX
Server: nginx/1.18.0
System: Linux test-ipsremont 5.4.0-214-generic #234-Ubuntu SMP Fri Mar 14 23:50:27 UTC 2025 x86_64
User: ips (1000)
PHP: 8.0.30
Disabled: pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,pcntl_unshare,
Upload Files
File: //var/www/quadcode.com/src/components/blocks/hero/Hero.svelte
<script lang="ts">
    import type { IPost } from "$type/post";
    import {locale, localeLink, t} from '$lib/translations';

    import expert from "../../../assets/post/expert-icon-big.svg";
    export let data: IPost;

    const modifiedDate = new Date(data.modified);
    const createdDate = new Date(data.date);
    const modifiedMonthName = modifiedDate.toLocaleString($locale, { month: 'long' });
    const createdMonthName = createdDate.toLocaleString($locale, { month: 'long' });

    const modifiedText = modifiedMonthName + ' ' + modifiedDate.getDate() + ', ' + modifiedDate.getFullYear();
    const createdText = createdMonthName + ' ' + createdDate.getDate() + ', ' + createdDate.getFullYear();
</script>
<div class="hero">
  <div>
    <div class="hero__content">
      <div class="article-hero-badges">
        {#if data?.expertData}
          <div class="expert-badge-wrap">
            <button type="button" class="expert-badge-btn" id="expertBadgeBtn" aria-expanded="false" aria-haspopup="true" aria-label="Expert reviewed – click for details">
              <img src={expert} alt="" width="18" height="18">
              {$t('Expert reviewed')}
            </button>
            <div class="expert-badge-tooltip" id="expertBadgeTooltip" role="tooltip">
              {$t('Our subject matter experts have reviewed this article to ensure it meets the highest standard for accurate information and guidance. Learn more about our <a href="/blog/editorial-standards">editorial standards</a> and <a href="/blog/editorial-process">process</a>.')}
            </div>
          </div>
        {/if}
        {#if data?.tagsData}
          {#each data.tagsData as tag}
            <div class="article-tag">{tag}</div>
          {/each}
        {/if}
      </div>
      <h1 class="hero__title">{@html data.title.rendered}</h1>
      <div class="article-hero-meta">
        <div class="article-meta">
          <div class="article-meta-author">
            <div class="article-meta-avatar">
              {#if data?.authorData?.avatar?.thumbnail}
              <img
                src={data.authorData.avatar.thumbnail}
                alt={data.authorData.name}
                class="hero__avatar"
              />
              {/if}
            </div>
            <div>
              <span class="article-meta-name-row">
                <a href="{localeLink()}/author/{data.authorData.slug}" class="article-meta-name">{data.authorData.name}</a>
                {#if data.authorData.linkedin}
                  <a
                    href={data.authorData.linkedin}
                    target="_blank"
                    rel="noopener noreferrer"
                    class="article-meta-linkedin"
                    aria-label="LinkedIn"
                  >
                    <svg viewBox="0 0 24 24" fill="#0a66c2" width="14" height="14"><path d="M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433c-1.144 0-2.063-.926-2.063-2.065 0-1.138.92-2.063 2.063-2.063 1.14 0 2.064.925 2.064 2.063 0 1.139-.925 2.065-2.064 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z"></path></svg>
                  </a>
                {/if}
              </span>
              <div class="article-meta-detail">{data.authorData.position}</div>
            </div>
          </div>
          <span class="article-meta-sep"></span>
          <span class="article-meta-detail">{data.estReadingTime} {$t('blog.readingTimeSuffix')}</span>
          <span class="article-meta-sep"></span>
          <span class="article-meta-detail">{createdText}</span>
          <span class="article-meta-sep"></span>
          <span class="article-meta-detail">{$t('Updated')} {modifiedText}</span>
          <span class="article-meta-sep"></span>
          <span class="article-meta-detail">{data.views} {$t('blog.viewsLabel')}</span>
        </div>
        <p class="article-contributors"><strong>{$t('blog.contributorsLabel')}</strong>
          {#if data.authorData}
            <a href="{localeLink()}/author/{data.authorData.slug}">{data.authorData.name}</a>
          {/if}
          {#if data.expertData}
            , <a href="{localeLink()}/author/{data.expertData.slug}">{data.expertData.name}</a>
          {/if}
      </div>
    </div>
  </div>
</div>
<style lang="scss">
  @import 'src/scss/media';
  @import 'src/scss/mixins';
  @import 'src/scss/variables';

  .article-hero-badges { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin-bottom: 16px; }
  .article-badge {
    font-size: 0.75rem; font-weight: 600; padding: 4px 10px; border-radius: 4px;
    background: #f0f9ff; color: #0369a1; border: 1px solid #bae6fd;
  }
  .expert-badge-wrap { position: relative; display: inline-block; }
  .expert-badge-btn {
    display: inline-flex; align-items: center; gap: 6px; padding: 6px 12px;
    color: #374151;
    background: #fff; border: 1px solid #e5e7eb; border-radius: 6px;
    cursor: pointer; transition: border-color 0.2s, box-shadow 0.2s;
    line-height: 1;
    font-size: 0.75rem;
    font-weight: 600;
  }
  .expert-badge-btn:hover { border-color: #d1d5db; box-shadow: 0 1px 3px rgba(0,0,0,0.06); }
  .expert-badge-btn img { width: 18px; height: 18px; display: block; flex-shrink: 0; }
  .expert-badge-tooltip {
    display: none; position: absolute; left: 0; top: calc(100% + 8px); z-index: 200;
    width: 320px; max-width: 90vw; padding: 14px 16px;
    background: #fff; border: 1px solid #e5e7eb; border-radius: 8px;
    box-shadow: 0 10px 25px rgba(0,0,0,0.12); font-size: 0.8125rem; line-height: 1.5; color: #374151;
  }
  .expert-badge-tooltip::before {
    content: ''; position: absolute; left: 16px; top: -6px;
    border-left: 6px solid transparent; border-right: 6px solid transparent;
    border-bottom: 6px solid #e5e7eb;
  }
  .expert-badge-tooltip::after {
    content: ''; position: absolute; left: 17px; top: -5px;
    border-left: 5px solid transparent; border-right: 5px solid transparent;
    border-bottom: 5px solid #fff;
  }
  .expert-badge-tooltip.is-open { display: block; }
  .expert-badge-tooltip a { color: #E62334; text-decoration: underline; text-underline-offset: 2px; }
  .expert-badge-tooltip a:hover { color: #c41e2a; }

  .article-hero-meta { padding-bottom: 32px; border-bottom: 1px solid #eaedf0; }
  .article-meta {
    display: flex; align-items: center; gap: 16px; flex-wrap: wrap;
  }
  .article-tag {
    font-family: 'Inter', system-ui, -apple-system, sans-serif;
    font-weight: 600;
    display: inline-block;
    font-size: 0.75rem;
    line-height: 1.7;
    color: #E62334;
    background: rgba(230, 35, 52, 0.08);
    padding: 4px 12px;
    border-radius: 4px;
  }
  .article-contributors {
    font-size: 0.8125rem; color: #5a6872; margin-top: 12px;
  }
  .article-contributors strong { color: #374151; font-weight: 600; }
  .article-contributors a { color: #E62334; text-decoration: underline; text-underline-offset: 2px; }
  .article-contributors a:hover { color: #c41e2a; }
  .article-meta-author {
    display: flex; align-items: center; gap: 12px;
  }
  .article-meta-avatar {
    width: 44px; height: 44px; overflow: hidden; flex-shrink: 0;
    clip-path: url(#authorShape);
    -webkit-clip-path: url(#authorShape);
    border: 1px solid #e5e7eb;
  }
  .article-meta-avatar img { width: 100%; height: 100%; object-fit: cover; }
  .article-meta-name-row {
    display: inline-flex; align-items: center; gap: 5px; flex-wrap: wrap;
  }
  .article-meta-name {
    font-size: 0.875rem; font-weight: 600; color: #141414;
    text-decoration: none;
  }
  .article-meta-name:hover { text-decoration: underline; }
  .article-meta-linkedin {
    display: inline-flex; line-height: 0; color: #0a66c2;
    transition: opacity 0.2s;
  }
  .article-meta-linkedin:hover { opacity: 0.8; }
  .article-meta-detail { font-size: 0.8125rem; color: #889aa8; }
  .article-meta-sep { width: 4px; height: 4px; border-radius: 50%; background: #c5cfd6; }

  .hero {
    width: 100%;
    padding: 32px 0;

    @media (max-width: 768px) {
      padding-top: 16px; padding-bottom: 10px;
    }

    &__title {
      font-size: clamp(1.75rem, 3.2vw, 2.5rem); font-weight: 800;
      line-height: 1.2; color: #141414; letter-spacing: -0.02em;
      margin-bottom: 20px; max-width: 780px;
      font-family: 'Inter', system-ui, -apple-system, sans-serif;
    }

    &__meta {
      display: flex;
      align-items: center;
      gap: 12px;
    }

    &__avatar {
      width: 40px;
      height: 40px;
      border-radius: 50%;
      object-fit: cover;
      flex-shrink: 0;
    }

    &__metaText {
      display: flex;
      flex-direction: column;
      gap: 2px;
    }

    &__authorName {
      font-family: Suisse Intl;
      font-weight: 600;
      font-size: 14px;
      line-height: 20px;
      color: $fontPrimary;
    }

    &__metaDetails {
      display: flex;
      align-items: center;
      gap: 6px;
      flex-wrap: wrap;
      font-family: Suisse Intl;
      font-weight: 400;
      font-size: 13px;
      line-height: 18px;
      color: $techBlueSecondary;
    }

    &__sep {
      color: $techBlue3;
      user-select: none;
    }

    @media (max-width: 768px) {
      .qc-topbar { display: none; }
      .qc-header-nav { display: none; }
      .qc-header-inner, .article-wrapper { padding-left: 20px; padding-right: 20px; max-width: 100%; }
      .article-hero .breadcrumbs, .article-hero .article-header { padding-left: 20px; padding-right: 20px; }
      .article-hero .article-header { padding-top: 16px; padding-bottom: 10px; }
      .article-hero-meta { padding-bottom: 10px; }
      .article-body { padding-top: 12px; }
      .qc-footer-grid { grid-template-columns: repeat(2, 1fr); }
      .sidebar { flex-direction: column; }
      .author-card { flex-direction: column; align-items: center; text-align: center; }
      .qc-footer-inner { padding: 0 20px; }
      /* Hide author detail at top of article on mobile */
      .article-meta-author, .article-contributors { display: none !important; }
      .sidebar { display: none !important; }
    }
  }
</style>