/*
 * components.css
 * 再利用可能なUIコンポーネントのスタイル定義。
 * 新しい共通スタイルはここに追加する。
 * テンプレート内インラインスタイルの移行先。
 */

/* ── Glassmorphism ユーティリティ ───────────────────────────────── */

/* blur(10px) 標準カード */
.glass-blur-sm {
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
}

/* blur(16px) フォーム・モーダル向け */
.glass-blur-md {
    backdrop-filter: blur(16px);
    -webkit-backdrop-filter: blur(16px);
}

/* blur(20px) ヒーロー・大型パネル向け */
.glass-blur-lg {
    backdrop-filter: blur(20px);
    -webkit-backdrop-filter: blur(20px);
}

/* Cookie consent */
/* 星空トースト型: デスクトップは右下のコンパクトカード、モバイルは下部カード。
   同意ボタンをブランドグラデーション(青→紫)の主役に据え、拒否は視認性を保った
   まま重み付けだけ下げる（枠線で目立たせない）。 */
.cookie-consent-banner {
    position: fixed;
    right: 1rem;
    bottom: 1rem;
    left: 1rem;
    z-index: 1080;
    max-width: 380px;
    margin-right: 0;
    margin-left: auto;
    padding: 1.15rem 1.25rem 1.1rem;
    color: #ffffff;
    background:
        radial-gradient(120% 100% at 100% 0%, rgba(157, 80, 187, 0.22) 0%, rgba(157, 80, 187, 0) 60%),
        linear-gradient(160deg, rgba(26, 22, 69, 0.92) 0%, rgba(12, 12, 30, 0.94) 100%);
    border: 1px solid rgba(255, 255, 255, 0.12);
    border-radius: 1rem;
    box-shadow: 0 1rem 2.5rem rgba(0, 0, 0, 0.55);
    backdrop-filter: blur(18px);
    -webkit-backdrop-filter: blur(18px);
    animation: sg-cookie-consent-in 0.38s cubic-bezier(0.2, 0.8, 0.3, 1);
}

/* fill-mode は付けないこと。アニメーション終了後に transform が残ると、
   position:fixed の子孫にとっての包含ブロックを作ってしまう（既知の地雷）。 */
@keyframes sg-cookie-consent-in {
    from {
        opacity: 0;
        transform: translateY(14px) scale(0.98);
    }

    to {
        opacity: 1;
        transform: translateY(0) scale(1);
    }
}

/* モバイルは下部固定ナビ(.mobile-bottom-nav, 高さ64px)が <html> 直下(<body>の外)に
   退避されており(static/js/base_layout.js)、z-indexの大小に関わらずbody配下の
   position:fixedより手前に描画される。バナーの同意/拒否ボタンがナビの裏に隠れて
   押せなくなるため、ナビの高さ分だけ常に上へ逃がして重なり自体を発生させない。 */
@media (max-width: 991.98px) {
    .cookie-consent-banner {
        bottom: calc(64px + env(safe-area-inset-bottom, 0px) + 1rem);
    }
}

.cookie-consent-banner__head {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    margin-bottom: 0.55rem;
}

.cookie-consent-banner__icon {
    display: inline-flex;
    flex: 0 0 34px;
    align-items: center;
    justify-content: center;
    width: 34px;
    height: 34px;
    font-size: 1.05rem;
    line-height: 1;
    background: rgba(255, 255, 255, 0.08);
    border: 1px solid rgba(255, 255, 255, 0.12);
    border-radius: 50%;
}

.cookie-consent-banner__title {
    font-size: 0.95rem;
    font-weight: 700;
    letter-spacing: 0.02em;
}

.cookie-consent-banner__text {
    margin: 0 0 0.9rem;
    font-size: 0.8rem;
    line-height: 1.65;
    color: rgba(255, 255, 255, 0.75);
}

/* 「プライバシーポリシー」が文字単位の改行で途中から次行に落ちるのを防ぐ */
.cookie-consent-banner__link {
    margin-left: 0.15rem;
    color: var(--accent-blue, #00d2ff);
    text-decoration: none;
    white-space: nowrap;
}

.cookie-consent-banner__link:hover,
.cookie-consent-banner__link:focus {
    color: var(--accent-blue, #00d2ff);
    text-decoration: underline;
}

.cookie-consent-banner__actions {
    display: flex;
    flex-direction: column;
    gap: 0.4rem;
}

.cookie-consent-banner__btn {
    width: 100%;
    padding: 0.62rem 1rem;
    font-size: 0.87rem;
    font-weight: 700;
    line-height: 1.2;
    border: 1px solid transparent;
    border-radius: 999px;
    cursor: pointer;
    transition: transform 0.15s ease, box-shadow 0.2s ease, background-color 0.2s ease, color 0.2s ease;
}

.cookie-consent-banner__btn:focus-visible {
    outline: 2px solid #ffffff;
    outline-offset: 2px;
}

/* グラデーションは白文字とのコントラスト比 5.3:1 以上を確保できる濃さに落とし、
   ブランドの鮮やかさは外周のグロー側で出す。明るい #00d2ff を地色に使うと
   白文字が 2.9:1 まで落ちて読めないので、値を上げないこと。 */
.cookie-consent-banner__btn--accept {
    color: #ffffff;
    background: linear-gradient(135deg, #0072a8 0%, #6f2f9c 100%);
    box-shadow: 0 0.4rem 1.2rem rgba(0, 160, 220, 0.38);
}

.cookie-consent-banner__btn--accept:hover,
.cookie-consent-banner__btn--accept:focus {
    color: #ffffff;
    transform: translateY(-1px);
    box-shadow: 0 0.6rem 1.6rem rgba(0, 180, 235, 0.5);
}

.cookie-consent-banner__btn--reject {
    color: rgba(255, 255, 255, 0.7);
    background: rgba(255, 255, 255, 0.06);
}

.cookie-consent-banner__btn--reject:hover,
.cookie-consent-banner__btn--reject:focus {
    color: #ffffff;
    background: rgba(255, 255, 255, 0.12);
}

@media (prefers-reduced-motion: reduce) {
    .cookie-consent-banner {
        animation: none;
    }

    .cookie-consent-banner__btn {
        transition: none;
    }

    .cookie-consent-banner__btn--accept:hover,
    .cookie-consent-banner__btn--accept:focus {
        transform: none;
    }
}

/* ── ユーザーアバター ─────────────────────────────────────────── */

.avatar-sm {
    width: 32px;
    height: 32px;
    border-radius: 50%;
    object-fit: cover;
}

.avatar-md {
    width: 48px;
    height: 48px;
    border-radius: 50%;
    object-fit: cover;
}

.avatar-lg {
    width: 80px;
    height: 80px;
    border-radius: 50%;
    object-fit: cover;
}

/* ── スケルトンローダー ───────────────────────────────────────── */

.skeleton {
    background: linear-gradient(90deg,
        rgba(255,255,255,0.04) 25%,
        rgba(255,255,255,0.08) 50%,
        rgba(255,255,255,0.04) 75%);
    background-size: 200% 100%;
    animation: skeleton-shimmer 1.5s infinite;
}

@keyframes skeleton-shimmer {
    0%   { background-position: 200% 0; }
    100% { background-position: -200% 0; }
}

/* ── 用語集自動リンク (.glossary-link) ─────────────────────────────── */
.glossary-link {
    color: inherit;
    text-decoration: underline;
    text-decoration-style: dotted;
    text-decoration-color: rgba(197, 160, 89, 0.6);
    text-underline-offset: 3px;
    cursor: help;
    transition: color 0.15s ease, text-decoration-color 0.15s ease;
}
.glossary-link:hover {
    color: #e2c585;
    text-decoration-color: #e2c585;
    text-decoration-style: solid;
}

/* ── アフィリエイト商品カード (.gear-product-card) ──────────────────────
 * [[GEAR:]]マーカー / render_gear_card / spot_gear_recommend / gear_card.html 共通。
 * 各寸法・フォントサイズは CSS カスタムプロパティで制御し、スコープ別バリアント
 * (.spot-gear-cards 等) やページ別の詰め幅は「変数の再代入」だけで行う。
 * モバイル(≤480px)の詰め値も末尾の media query で変数を再代入して一括適用する。
 * クラス名は utils/affiliate.py・gear_card.html と一致させること（変更禁止）。
 */
.gear-product-card {
    --gc-thumb: 100px;
    --gc-thumb-radius: 10px;
    --gc-pad-y: 1rem;
    --gc-pad-x: 1.15rem;
    --gc-gap: 1rem;
    --gc-margin-y: 1.5rem;
    --gc-radius: 12px;
    --gc-name-fs: 1.05rem;
    --gc-note-fs: 0.88rem;
    --gc-note-lh: 1.55;
    --gc-price-fs: 1.15rem;
    --gc-pr-fs: 0.64rem;
    --gc-rating-fs: 0.9rem;
    --gc-score-fs: 0.85rem;
    --gc-review-fs: 0.8rem;
    --gc-btn-fs: 0.92rem;
    --gc-btn-minh: 0;
    --gc-btn-pad: 0.55rem 1.3rem;
    --gc-btn-flex: 0 1 auto;
    --gc-btn-radius: 50px;
    --gc-actions-gap: 0.9rem;
    --gc-actions-mt: 0.9rem;
    --gc-align: center;
    --gc-accent: #ff9900;
    --gc-bg: linear-gradient(135deg, rgba(255,153,0,0.06), rgba(255,153,0,0.015));
    --gc-border-color: rgba(255,153,0,0.22);

    position: relative;
    display: flex;
    gap: var(--gc-gap);
    align-items: var(--gc-align);
    flex-wrap: wrap;
    background: var(--gc-bg);
    border: 1px solid var(--gc-border-color);
    border-radius: var(--gc-radius);
    padding: var(--gc-pad-y) var(--gc-pad-x);
    margin: var(--gc-margin-y) 0;
    /* 記事本文(.ql-editor)が white-space: pre-wrap を継承させるため、
     * Jinjaの{% if %}が偽の時に残る空行がそのまま縦の空白として表示されてしまう。
     * カードは地の文ではないウィジェットなので明示的にリセットする。 */
    white-space: normal;
}
/* 任意の「イチオシ」バッジ（[[GEAR:...|バッジ文言]]で指定時のみ表示）。
 * Pochip/Rinker系の商品カードに見られるコーナーラベルを踏襲し、
 * 既存の gear-compare-rank--gold と同系色で統一する。 */
.gear-product-badge {
    position: absolute;
    top: -0.6rem;
    left: 1rem;
    background: linear-gradient(135deg,#d4af37,#f3d57a);
    color: #1a1206;
    font-size: 0.7rem;
    font-weight: 800;
    padding: 0.25rem 0.75rem;
    border-radius: 50px;
    box-shadow: 0 3px 8px rgba(0,0,0,0.35);
    letter-spacing: 0.02em;
    z-index: 1;
}
.gear-product-thumb {
    flex: 0 0 var(--gc-thumb);
    width: var(--gc-thumb);
    height: var(--gc-thumb);
    border-radius: var(--gc-thumb-radius);
    overflow: hidden;
    background: #fff;
    display: flex;
    align-items: center;
    justify-content: center;
}
.gear-product-thumb img { width: 100%; height: 100%; object-fit: contain; }
.gear-product-thumb--empty {
    background: rgba(255,255,255,0.04);
    color: rgba(255,153,0,0.5);
    font-size: 2rem;
}
.gear-product-body { flex: 1 1 220px; min-width: 0; }
.gear-product-pr {
    font-size: var(--gc-pr-fs);
    font-weight: 700;
    letter-spacing: 0.08em;
    color: var(--gc-accent);
    margin-bottom: 0.3rem;
}
.gear-product-name {
    font-weight: 700;
    color: #fff;
    font-size: var(--gc-name-fs);
    line-height: 1.4;
    word-break: keep-all;
    overflow-wrap: anywhere;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}
.gear-product-rating { display: flex; align-items: center; gap: 0.35rem; }
.gear-product-review-count { color: #8a8f98; font-size: var(--gc-review-fs); }
/* 星評価は render_stars() が .gear-compare-stars/.gear-compare-score を吐くため、
 * カード内スコープに限定して比較表(.gear-compare-row)側と干渉させない。 */
.gear-product-card .gear-compare-stars {
    display: inline-flex;
    align-items: center;
    gap: 0.1rem;
    color: #ffc107;
    font-size: var(--gc-rating-fs);
    margin-top: 0.3rem;
}
.gear-product-card .gear-compare-stars .far { color: rgba(255,193,7,0.35); }
.gear-product-card .gear-compare-score {
    color: #ffc107;
    font-weight: 700;
    font-size: var(--gc-score-fs);
    margin-left: 0.25rem;
}
.gear-product-price {
    display: inline-block;
    color: var(--gc-accent);
    font-weight: 800;
    font-size: var(--gc-price-fs);
    margin-top: 0.35rem;
    padding: 0.15rem 0.6rem;
    background: rgba(255,153,0,0.12);
    border-radius: 6px;
}
.gear-product-note {
    color: #b9bdc4;
    font-size: var(--gc-note-fs);
    margin-top: 0.3rem;
    line-height: var(--gc-note-lh);
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}
.gear-product-actions {
    display: flex;
    flex-wrap: wrap;
    gap: var(--gc-actions-gap);
    margin-top: var(--gc-actions-mt);
}
.gear-product-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.45rem;
    flex: var(--gc-btn-flex);
    min-height: var(--gc-btn-minh);
    font-weight: 800;
    text-decoration: none;
    border-radius: var(--gc-btn-radius);
    padding: var(--gc-btn-pad);
    font-size: var(--gc-btn-fs);
    white-space: nowrap;
    /* 常時ごく薄い影を落として押せる要素であることを主張し、hoverでさらに強める */
    box-shadow: 0 2px 6px rgba(0,0,0,0.25);
    transition: transform 0.15s ease, box-shadow 0.15s ease;
}
.gear-product-btn:hover { transform: translateY(-2px); }
.gear-product-btn--amazon { background: linear-gradient(135deg,#ff9900,#ffb84d); color: #1a1206; }
.gear-product-btn--amazon:hover { box-shadow: 0 6px 18px rgba(255,153,0,0.35); color:#1a1206; }
.gear-product-btn--rakuten { background: linear-gradient(135deg,#bf0000,#e60000); color: #fff; }
.gear-product-btn--rakuten:hover { box-shadow: 0 6px 18px rgba(191,0,0,0.4); color:#fff; }
.gear-product-btn--mapcamera { background: linear-gradient(135deg,#2c3e50,#34495e); color: #fff; }
.gear-product-btn--mapcamera:hover { box-shadow: 0 6px 18px rgba(44,62,80,0.4); color:#fff; }
.gear-product-btn--yahoo { background: linear-gradient(135deg,#258bf7,#4169E1); color: #fff; }
.gear-product-btn--yahoo:hover { box-shadow: 0 6px 18px rgba(37,139,247,0.4); color:#fff; }

/* コンパクトバリアント: スポット詳細のBortle連動レコメンド（.spot-gear-cards）。
 * 変数の再代入のみ。プロパティは基底定義を再利用する。 */
.spot-gear-cards .gear-product-card {
    --gc-thumb: 72px;
    --gc-thumb-radius: 8px;
    --gc-pad-y: 0.9rem;
    --gc-pad-x: 1.1rem;
    --gc-margin-y: 0.6rem;
    --gc-radius: 14px;
    --gc-name-fs: 0.95rem;
    --gc-note-fs: 0.8rem;
    --gc-note-lh: 1.5;
    --gc-price-fs: 0.88rem;
    --gc-pr-fs: 0.6rem;
    --gc-rating-fs: 0.78rem;
    --gc-score-fs: 0.74rem;
    --gc-review-fs: 0.72rem;
    --gc-btn-fs: 0.8rem;
    --gc-btn-pad: 0.4rem 1rem;
    --gc-actions-gap: 0.7rem;
    --gc-actions-mt: 0.65rem;
}

/* モバイル詰め値（≤480px）。変数の再代入で一括適用。
 * .spot-gear-cards 等の高詳細度バリアントが宣言済みの変数はそちら（既にコンパクト）が
 * 優先されるが、buttons の tap ターゲット化 (--gc-btn-flex / --gc-btn-minh) は
 * バリアント未宣言のため全カードに効く。 */
@media (max-width: 480px) {
    .gear-product-card {
        --gc-thumb: 84px;
        --gc-thumb-radius: 8px;
        --gc-pad-y: 0.75rem;
        --gc-pad-x: 0.8rem;
        --gc-gap: 0.7rem;
        --gc-margin-y: 1rem;
        --gc-name-fs: 0.95rem;
        --gc-note-fs: 0.8rem;
        --gc-note-lh: 1.5;
        --gc-price-fs: 1.05rem;
        --gc-pr-fs: 0.6rem;
        --gc-rating-fs: 0.8rem;
        --gc-score-fs: 0.74rem;
        --gc-review-fs: 0.72rem;
        --gc-btn-fs: 0.84rem;
        --gc-btn-minh: 44px;
        --gc-btn-pad: 0.55rem 0.25rem;
        --gc-btn-flex: 1 1 0;
        --gc-actions-gap: 0.7rem;
        --gc-actions-mt: 0.6rem;
    }
}

/* 画像フォールバック(static/js/ui/img-fallback.js)がプレースホルダーに差し替えた際の見た目。
 * object-fit:cover等の既存指定でアイコンが引き伸ばされないよう contain で上書きする。
 * padding は%指定だと親要素の幅基準になり小さいアバター等で破綻するため使わない。
 * SVG自体の余白で十分なので、既存クラス(.author-avatar等)のgradient背景が透けないよう
 * background だけ明示的に上書きする。 */
.img-fallback {
    object-fit: contain !important;
    background: #2a2f3a !important;
}

/* ── Masonry風グリッド (.masonry-grid) ──────────────────────────────
 * CSS column-count によるお手軽Masonryレイアウト。
 * dashboard.html の .my-gallery-masonry と dashboard/user_profile.html の
 * .user-masonry が column-count: 3→2→1 (ブレークポイント 992px/576px) で
 * 完全に同一構成だったため共通化。gap 値だけページごとに異なる
 * (dashboard: 16px / user_profile: 20px) ため、.gear-product-card と同じ
 * 「カスタムプロパティ再代入」方式で吸収する。デフォルト値は dashboard.html
 * 側 (16px) に合わせている。異なるページで使う場合はスコープ付きセレクタで
 * --masonry-gap を再代入すること（.gear-product-card の
 * .spot-gear-cards バリアントと同じパターン）。
 */
.masonry-grid {
    --masonry-gap: 16px;
    column-count: 3;
    column-gap: var(--masonry-gap);
}

@media (max-width: 992px) {
    .masonry-grid { column-count: 2; }
}

@media (max-width: 576px) {
    .masonry-grid { column-count: 1; }
}

/*
 * index.html ヒーローCTA専用ボタン。
 * 既存の .btn-premium-* 系（ゴールド配色）とは意図的に別配色（シアン系）であり、
 * 統一しない（見た目を変えず、インラインstyleをクラスへ切り出しただけ）。
 */
.btn-hero-solid {
    background: #00d4ff;
    border: none;
    color: #080b14;
}

.btn-hero-glass {
    background: rgba(255, 255, 255, 0.05);
    -webkit-backdrop-filter: blur(5px);
    backdrop-filter: blur(5px);
}

.img-fallback-bg {
    background-size: contain !important;
    background-repeat: no-repeat !important;
    background-position: center !important;
    background-color: #2a2f3a;
}

/* ── マガジン記事 メディアマーカー ────────────────────────────────────
 * docs/magazine_media_markers_plan_2026-07.md §3 が定める生成HTMLに対応する。
 * クラス名・data属性は utils/article_render.py と一致させること（変更禁止）。
 */

/* [[PHOTOS:]] … 写真の横並びグリッド。列数は data-cols（1〜4）から
 * --cols へ引き込み、grid-template-columns はそれを参照するだけにする
 * （attr()のtrack-list対応はブラウザ間でまだ不安定なため使わない）。
 * モバイル(≤640px)は縦位置4枚が1枚あたり細くなりすぎるため最大2列に落とす
 * （AGENTS.md既知の地雷: .photo-viewer と同種の「作品が成立しない」クロップ/縮小を避ける）。
 */
.article-photos {
    --cols: 2;
    display: grid;
    grid-template-columns: repeat(var(--cols), 1fr);
    gap: 0.5rem;
    margin: 1.5rem 0;
}
.article-photos[data-cols="1"] { --cols: 1; }
.article-photos[data-cols="2"] { --cols: 2; }
.article-photos[data-cols="3"] { --cols: 3; }
.article-photos[data-cols="4"] { --cols: 4; }
.article-photos figure {
    margin: 0;
}
.article-photos img {
    display: block;
    width: 100%;
    height: auto;
    margin: 0;
    border-radius: 8px;
}
@media (max-width: 640px) {
    .article-photos[data-cols="3"],
    .article-photos[data-cols="4"] {
        --cols: 2;
    }
}

/* [[BEFORE_AFTER:]] … レタッチ前後比較スライダー。
 * .ba-after が通常フローで高さを決め、.ba-before はその上へ絶対配置で重ねて
 * clip-path で右側を切る。実際の操作は透明化した <input type=range> に任せ、
 * ドラッグ実装は自前で書かない（キーボード・タッチ・スクリーンリーダー対応が
 * 標準で手に入るため。static/js/article_media.js が --ba-pos を更新するだけ）。
 * JSが無効/失敗しても inline style の --ba-pos:50% がそのまま効き、
 * 両画像が半分ずつ見える状態で記事は壊れない。
 */
.ba-compare {
    margin: 1.5rem 0;
}
.ba-frame {
    position: relative;
    overflow: hidden;
    border-radius: 8px;
    user-select: none;
    -webkit-user-select: none;
}
.ba-img {
    display: block;
    margin: 0;
}
.ba-after {
    width: 100%;
    height: auto;
}
.ba-before {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    clip-path: inset(0 calc(100% - var(--ba-pos)) 0 0);
}
.ba-range {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    margin: 0;
    padding: 0;
    opacity: 0;
    cursor: ew-resize;
    -webkit-appearance: none;
    appearance: none;
    background: transparent;
    /* 枠全面を覆うため、これが無いとスマホで画像の上を縦スクロールできなくなる。
     * pan-y でブラウザに縦パンを渡し、横方向のドラッグだけスライダーが受け取る。 */
    touch-action: pan-y;
}
.ba-range:focus-visible {
    outline: 2px solid var(--accent-blue, #00d2ff);
    outline-offset: -2px;
}
.ba-handle {
    position: absolute;
    top: 0;
    bottom: 0;
    left: var(--ba-pos);
    width: 3px;
    margin-left: -1.5px;
    background: #fff;
    box-shadow: 0 0 6px rgba(0, 0, 0, 0.5);
    pointer-events: none;
}
.ba-handle::before {
    content: "";
    position: absolute;
    top: 50%;
    left: 50%;
    width: 32px;
    height: 32px;
    transform: translate(-50%, -50%);
    border-radius: 50%;
    background: #fff;
    box-shadow: 0 2px 10px rgba(0, 0, 0, 0.45);
}
.ba-label {
    position: absolute;
    bottom: 0.6rem;
    padding: 0.2rem 0.65rem;
    border-radius: 999px;
    background: rgba(0, 0, 0, 0.55);
    color: #fff;
    font-size: 0.72rem;
    font-weight: 700;
    letter-spacing: 0.02em;
    pointer-events: none;
    white-space: nowrap;
}
.ba-label-before { left: 0.6rem; }
.ba-label-after { right: 0.6rem; }

/* [[SNS_CARD:]] … X / Instagram 投稿の静的紹介カード（公式埋め込み不使用。
 * docs/magazine_media_markers_plan_2026-07.md F2）。画像の縦横比は投稿ごとに
 * まちまちなので高さを固定しない（AGENTS.md既知の地雷: .photo-viewer で
 * max-height を入れてクロップが再発した前例と同じ理由で height:auto を維持）。
 */
.sns-card {
    margin: 1.5rem 0;
    max-width: 420px;
}
.sns-card-link {
    display: block;
    overflow: hidden;
    border-radius: 14px;
    border: 1px solid var(--border-fine);
    background: var(--article-surface-elevated);
    text-decoration: none;
    color: var(--article-text);
    transition: transform 0.15s ease, box-shadow 0.15s ease, border-color 0.15s ease;
}
.sns-card-link:hover {
    transform: translateY(-2px);
    box-shadow: 0 10px 26px rgba(0, 0, 0, 0.3);
    text-decoration: none;
    color: var(--article-text);
}
.sns-card-image {
    display: block;
    width: 100%;
    height: auto;
    margin: 0;
}
.sns-card-text {
    margin: 0;
    padding: 0.9rem 1rem 0.3rem;
    font-size: 0.92rem;
    line-height: 1.65;
    color: var(--article-text);
}
.sns-card-meta {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    padding: 0.6rem 1rem 0.9rem;
    font-size: 0.78rem;
    font-weight: 700;
    letter-spacing: 0.01em;
    color: var(--article-text-muted);
}
.sns-card-meta::before {
    content: "\f35d"; /* FontAwesome 6 external-link-alt */
    font-family: "Font Awesome 6 Free";
    font-weight: 900;
    font-size: 0.68rem;
}
/* サービス別アクセントカラー（data-service属性で出し分け。未知の値は既定色のまま） */
.sns-card[data-service="x"] .sns-card-link:hover { border-color: rgba(255, 255, 255, 0.4); }
.sns-card[data-service="x"] .sns-card-meta { color: #e7e9ea; }
.sns-card[data-service="instagram"] .sns-card-link:hover { border-color: rgba(225, 48, 108, 0.55); }
.sns-card[data-service="instagram"] .sns-card-meta { color: #e1306c; }
/* --- 夜景 / 昼景マップ切り替え --- */
.map-mode-tabs {
    display: inline-flex;
    align-items: center;
    overflow: hidden;
    border: 1px solid rgba(143, 183, 255, 0.3);
    border-radius: 999px;
    background: rgba(13, 27, 42, 0.45);
    box-shadow: 0 4px 14px rgba(0, 0, 0, 0.18);
}

.map-mode-tab {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    padding: 0.38rem 0.72rem;
    color: rgba(255, 255, 255, 0.68);
    font-size: 0.82rem;
    line-height: 1;
    text-decoration: none;
    transition: background-color 0.15s, color 0.15s;
    /* <button> の .map-mode-tab（公開マップ/マイマップ切替）向け: ブラウザ既定のボタン外観をリセットし、
       <a>/<span> 版と同じく親 .map-mode-tabs の背景・.is-active の配色をそのまま透過させる */
    background: none;
    border: none;
    appearance: none;
    font-family: inherit;
    cursor: pointer;
}

.map-mode-tab:hover {
    color: #fff;
    background: rgba(143, 183, 255, 0.14);
}

.map-mode-tab.is-active {
    color: #fff;
    background: linear-gradient(135deg, rgba(61, 90, 254, 0.72), rgba(86, 140, 255, 0.62));
    font-weight: 600;
}

/* ── 編集部おすすめ（spot_guides）本文 ─────────────────────────────
 * render_article_body() が返す生HTML(h2/h3/p/a)をダークテーマに合わせて整える。
 * gear/detail.html の .ql-editor はそのテンプレート専用のローカル<style>にのみ
 * 定義されており他ページから参照できないため、別名クラスとして独立に定義する。 */
.spot-guide-body h2,
.spot-guide-body h3 {
    color: #fff;
    font-size: 1.1rem;
    font-weight: 600;
    margin: 1.5rem 0 0.75rem;
}

.spot-guide-body h2:first-child,
.spot-guide-body h3:first-child {
    margin-top: 0;
}

.spot-guide-body p {
    color: rgba(255, 255, 255, 0.75);
    line-height: 1.8;
    margin-bottom: 1rem;
}

.spot-guide-body a {
    color: #0dcaf0;
    text-decoration: underline;
}

.spot-guide-body a:hover {
    color: #39d6f5;
}
