.trim {
    position: relative;
    overflow: hidden;
    width: 110px;
    height: 110px;
    border-radius: 50%;
    margin-left: auto;
    margin-right: auto;
}

.trim img {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    -webkit-transform: translate(-50%, -50%);
    -ms-transform: translate(-50%, -50%);
    height: 100%;
}

@media (max-width: 767px) {
    .container {
        padding-left: 15px;
        padding-right: 15px;
        width: 100%;
    }
}

.channel-card-col {
    margin-bottom: 20px;
}

.channel-card {
    display: block;
    text-align: center;
    padding: 15px 10px;
    border-radius: 8px;
    transition: box-shadow .15s ease, transform .15s ease;
}

.channel-card:hover {
    box-shadow: 0 4px 14px rgba(0, 0, 0, 0.08);
    transform: translateY(-2px);
}

.channel-card-title {
    margin: 10px 0 0;
    font-size: 14px;
    font-weight: 600;
    color: #333;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* /channel(更新日時)・/channel/ranking(登録者数・動画本数・集計日時)の補足テキスト(#126).
   1行に収まらないことが多いため(登録者数・動画本数・集計日時の3項目)、titleと違い折り返す. */
.channel-card-meta {
    margin: 4px 0 0;
    font-size: 11px;
    line-height: 1.4;
    color: #888;
}

/* 動画一覧(video_card, viewer/parts.html)。<ul class="video-list">の各<li class="video-card-item">が1件分(#135)。
   list-styleとブラウザ既定のul/olマージンを消しておく。 */
.video-list {
    list-style: none;
    margin: 0;
    padding: 0;
}

.video-card-item {
    margin-top: 20px;
}

.video-card-item:first-child {
    margin-top: 0;
}

/* ループに差し込む広告(ads()マクロ)を<ul class="video-list">の直接の子として置くための<li>(#135)。
   カード本体のマージンとは別に持たせておく */
.video-card-ad {
    margin-top: 20px;
}

.video-card {
    display: flex;
    gap: 15px;
    padding: 12px;
    background: #fff;
    border-radius: 8px;
    box-shadow: 0 1px 4px rgba(0, 0, 0, 0.08);
}

/* サムネイルはDBに保存されている唯一のサイズ(120x90)が上限(#122)。以前はPCで200pxへ、
   SPではカード幅いっぱい(100%、画面幅近く)へ拡大しており、いずれも保存解像度を超える
   引き伸ばしになっていた(#135, Codexの指摘1)。原寸を活かすコンパクト表示として
   PC/SPで幅を固定する(表示を縮小する分には拡大にあたらないため崩れない)。 */
.video-card-thumb {
    flex: 0 0 120px;
    width: 120px;
}

.video-card-thumb img {
    display: block;
    width: 120px;
    /* height:auto が無いと、CLS対策で付けた width/height 属性の height="90" が
       そのまま高さとして使われ、幅だけ伸びて画像が横に潰れる（本番で発生）。
       width だけをCSSで指定する場合は height:auto を必ず添えること */
    height: auto;
    /* width/height属性とonerror(#124)で画像が消えた場合でも、.video-card-thumbの
       背景プレースホルダ(下部で定義, 120x90相当)の比率をimg自身にも持たせておく保険(#90の再発防止) */
    aspect-ratio: 4 / 3;
    border-radius: 6px;
}

.video-card-body {
    flex: 1 1 auto;
    min-width: 0;
}

.video-card-title {
    margin: 0 0 6px;
    font-size: 15px;
    line-height: 1.4;
    /* タイトル長でカード高がバラつくのを抑えるため2行で省略する(#135, Codexの指摘1) */
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.video-card-title a {
    color: #222;
}

.video-card-date {
    color: #888;
    font-size: 12px;
    margin-bottom: 4px;
}

.video-card-stats {
    font-size: 12px;
    color: #555;
    margin-bottom: 4px;
    line-height: 1.4;
}

.video-card-channel {
    font-size: 12px;
    margin: 0;
}

@media (max-width: 575px) {
    /* SPでも横型(サムネ+右側テキスト)のまま維持する。以前はここでflex-direction:columnに
       切り替えてサムネイルをカード幅いっぱい(≒画面幅近く)まで拡大しており、これが
       「1ページが非常に長い」の主因だった(#135, Codexの指摘1)。行を積まず、余白と
       行数を詰めて高密度にする。 */
    .video-card {
        gap: 10px;
        padding: 10px;
    }
    .video-card-thumb {
        flex: 0 0 100px;
        width: 100px;
    }
    .video-card-thumb img {
        width: 100px;
    }
    .video-card-item,
    .video-card-ad {
        margin-top: 12px;
    }
    .video-card-title {
        font-size: 14px;
        margin-bottom: 4px;
    }
    .video-card-date,
    .video-card-stats,
    .video-card-channel {
        font-size: 11px;
    }
}

.frame-wrapper__video {
    position: relative;
    width: 100%;
    height: 0;
    padding-bottom: 56.25%;
    overflow: hidden;
    margin-bottom: 50px;
}

.frame-wrapper__video iframe {
    width: 100%;
    height: 100%;
    position: absolute;
    top: 0;
    left: 0;
}
/* ページャ (viewer/parts.html の pager マクロ) */
.viewer-pager {
    margin-top: 30px;
}

/* 現在地表示(N / Mページ)。ページ送りリンクの少し上に置く(#135, Codexの指摘2) */
.viewer-pager-status {
    margin: 0 0 8px;
    font-size: 13px;
    color: #666;
}

.viewer-pager .shop-pagination {
    list-style: none;
    margin: 0;
    padding: 10px 0;
    /* ページ数が多くても横にはみ出さず折り返す */
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    align-items: center;
    gap: 6px;
}

.viewer-pager .shop-pagination > li {
    margin-right: 0;
}

.viewer-pager .shop-pagination > li > a,
.viewer-pager .shop-pagination > li > span {
    border: 1px solid #eee;
    color: #999999;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 13px;
    /* タップ領域は最低44x44px(#135, Codexの指摘2)。ページ番号の1桁だけの見た目より
       当たり判定を広げるため、見た目のパディングではなくmin-width/min-heightで確保する */
    min-width: 44px;
    min-height: 44px;
    padding: 0 8px;
    text-align: center;
    box-sizing: border-box;
}

/* 前へ/次へは記号だけでなく文言を可視表示する(#135, Codexの指摘2) */
.viewer-pager-prev,
.viewer-pager-next {
    gap: 4px;
    white-space: nowrap;
}

.viewer-pager .shop-pagination > li.disabled > span {
    color: #ddd;
    background: #fafafa;
}

.viewer-pager .shop-pagination > li.active > a {
    border-color: #ff7f00;
    color: #ff7f00;
}

.video-list-empty {
    color: #666;
    margin-bottom: 15px;
}

/* 見出し階層是正で <h3> から <p> に置き換えたリード文。見た目は従来のh3相当を維持する */
.section-lead {
    font-size: 1.17em;
    font-weight: bold;
    margin: 1em 0;
}

/* パンくずリスト(viewer/parts.html の breadcrumb マクロ) */
.viewer-breadcrumb {
    margin-bottom: 15px;
}

.viewer-breadcrumb .breadcrumb {
    margin-bottom: 0;
    padding: 8px 12px;
    font-size: 13px;
}

/* チャンネルバナー(channel/show.html)。画像が読み込みエラーになるとブラウザはimgを非置換要素扱いに戻し、
   width:100%/aspect-ratioが効かなくなってCLSが起きる。display:blockを明示することでエラー時も
   ブロックボックスとしてwidth/aspect-ratioを確実に適用させる */
.blog-details-photo > img {
    display: block;
    width: 100%;
    aspect-ratio: 16 / 9;
    height: auto;
    object-fit: cover;
}

/* 動画詳細のクリック・トゥ・プレイ(video/show.html)。.frame-wrapper__videoはposition:relativeで
   アスペクト比(padding-bottom:56.25%)を確保済みなので、facadeはそこに重ねるだけでCLSは発生しない */
.video-facade {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    border: 0;
    padding: 0;
    cursor: pointer;
    background-color: #000;
    background-size: cover;
    background-position: center;
}

.video-facade-play {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    width: 68px;
    height: 48px;
    background-color: rgba(0, 0, 0, 0.7);
    border-radius: 10px;
}

.video-facade-play::before {
    content: '';
    position: absolute;
    top: 50%;
    left: 54%;
    transform: translate(-50%, -50%);
    border-style: solid;
    border-width: 12px 0 12px 20px;
    border-color: transparent transparent transparent #fff;
}

/* チャンネル名検索フォーム(/channel, #126) */
.channel-search-form {
    display: flex;
    gap: 8px;
    max-width: 360px;
    margin: 0 0 15px;
}

.channel-search-form input[type="search"] {
    flex: 1 1 auto;
    padding: 6px 10px;
    border: 1px solid #ddd;
    border-radius: 4px;
    font-size: 13px;
}

.channel-search-form button {
    padding: 6px 16px;
    border: 1px solid #333;
    border-radius: 4px;
    background: #333;
    color: #fff;
    font-size: 13px;
    cursor: pointer;
}

/* 並び替え(?sort=)UI(ranking/new/recommend共通. viewer/channel/ranking,new,video/recommendのindex.htmlで使用. #39) */
.viewer-sort-list {
    list-style: none;
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    padding: 0;
    margin: 0 0 15px;
    font-size: 13px;
}

.viewer-sort-list li {
    /* タップ領域は最低44x44px(#135, Codexの指摘2)。文言が短いピルでも当たり判定を
       確保するためmin-width/min-heightで底上げし、中身はflexで中央寄せする */
    display: flex;
    align-items: center;
    justify-content: center;
    min-width: 44px;
    min-height: 44px;
    padding: 4px 14px;
    border: 1px solid #ddd;
    border-radius: 999px;
    box-sizing: border-box;
}

.viewer-sort-list li.active {
    background: #333;
    color: #fff;
    border-color: #333;
}

.viewer-sort-list a,
.viewer-sort-list span {
    color: inherit;
    text-decoration: none;
}

/* ランキング(/channel/ranking)の順位バッジ(#39) */
.channel-ranking-rank {
    margin: 0 0 4px;
    font-weight: 700;
    font-size: 13px;
    color: #e0402a;
}

/* タグ一覧・トップのTAGセクションの動画件数バッジ(/tag, /. #41) */
.tag-video-count {
    font-size: 11px;
    color: #999;
}

/* タグピル・共有/導線ボタン(class="button extra-small button-white")共通のタップ領域対策(#135, Codexの指摘2)。
   テーマのa.button/a.button-whiteは本来<span>で囲んだテキストにpaddingを付ける前提(lib/subas-v1.5)だが、
   このサイトの実装は<span>を使わずテキストを直接入れているため、a.button自体のpadding:0がそのまま効いて
   タップ領域がテキストの行送り分(15px前後)しか無かった。margin-bottom等の既存ユーティリティクラス
   (mb-10/mb-20)と衝突しないよう、ここではmarginに触れずpaddingだけで44px以上を確保する */
a.button.extra-small.button-white {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-height: 44px;
    box-sizing: border-box;
    padding: 6px 20px;
}

/* 動画詳細のチャンネル情報ブロック(video/show.html)。共有マクロchannel_cardとは別実装(#42) */
.video-channel-info {
    display: flex;
    align-items: center;
    gap: 15px;
    margin-bottom: 20px;
}

.video-channel-info-icon img {
    width: 72px;
    height: 72px;
    border-radius: 50%;
    object-fit: cover;
}

.video-channel-info-title {
    font-weight: bold;
    margin-bottom: 4px;
}

.video-channel-info-subscribers {
    color: #777;
    font-size: 13px;
    margin-bottom: 8px;
}

/* 動画詳細のYouTube導線・シェアボタン(video/show.html)。外部JSを使わず素のリンクのみで実装する(#42) */
.video-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}

/* 動画詳細の統計値(video/show.html) */
.video-stats-list {
    display: flex;
    flex-wrap: wrap;
    gap: 4px 20px;
    list-style: none;
    padding-left: 0;
    margin: 0;
}

.video-stats-label {
    color: #777;
    font-size: 12px;
    margin-right: 4px;
}

.video-stats-note {
    color: #999;
    font-size: 12px;
    margin-top: 8px;
    margin-bottom: 0;
}

/* 動画詳細の説明文(video/show.html)。長文は<details>でJS無しに折りたたむ(#42) */
.video-description-details > summary {
    cursor: pointer;
    font-weight: bold;
}

.video-description-body {
    margin-top: 10px;
    line-height: 1.7;
    word-break: break-word;
    overflow-wrap: anywhere;
}

.video-description-empty {
    color: #999;
}

/* 画像取得エラー時の代替表示(#124)。外部配信元(yt3.ggpht.com)の画像が読み込みエラーになると
   従来は空白領域になっていた(Epic #122でCodexが指摘)。parts.htmlの<img onerror>で
   visibility:hiddenにするだけにし(display:noneにしないのはCLS対策のwidth/height属性による
   確保済みレイアウトを維持するため)、あらかじめ敷いておいた背景色+アイコン(サーバ生成
   ではなくCSSのdata URI SVG)を見せる。画像が正常に読み込めた場合はimgがこの背景を覆う
   ため見た目には影響しない。 */
.trim {
    background-color: #eee;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Ccircle cx='12' cy='8' r='4' fill='%23ccc'/%3E%3Cpath d='M4 21c0-4.4 3.6-8 8-8s8 3.6 8 8' fill='%23ccc'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: center;
    background-size: 40%;
}

.video-card-thumb {
    position: relative;
    background-color: #eee;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Crect x='2' y='5' width='20' height='14' rx='2' ry='2' fill='none' stroke='%23ccc' stroke-width='2'/%3E%3Cpolygon points='10,9 16,12 10,15' fill='%23ccc'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: center;
    background-size: 30%;
    border-radius: 6px;
}

/* チャンネルバナー(channel/show.html)の画像エラー時の代替表示(#124)。parts.htmlのimg onerrorは
   visibility:hiddenでimg自身を消すため、背景は「hiddenにする要素自身」ではなく親の.blog-details-photo
   に敷く必要がある(imgに敷くとvisibility:hiddenで一緒に消えて空白に戻ってしまう。実機検証で発覚)。
   .bg-img-1(lib/subas-v1.5/style.css)のテーマ既定背景(斜線パターン)より優先させるため2クラス指定にして
   読み込み順に依存せず確実に上書きする。img読み込み成功時はobject-fit:coverで全面を覆うため見た目には
   影響しない(p-20のpadding分の縁取りのみ意匠が変わる)。 */
.blog-details-photo.bg-img-1 {
    background-color: #eee;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Crect x='2' y='5' width='20' height='14' rx='2' ry='2' fill='none' stroke='%23ccc' stroke-width='2'/%3E%3Cpolygon points='10,9 16,12 10,15' fill='%23ccc'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: center;
    background-size: 12%;
}
