@charset "UTF-8";

/* ===========================================================
   ■ このファイルは「DATA STUDIO」の一部です
     放送用の気象・防災グラフィックを作る Web アプリ。
     PHP ＋ 素の JavaScript（フレームワーク・ビルド工程なし。npm も
     TypeScript も使わない。JS は var と関数で書く）。
     「チャンネル ＞ パネル」の入れ子で、パネルは 1920x1080 の固定
     キャンバス。どこに何を置くかは自動レイアウトが決める（手で
     動かす機能は意図的に無い）。保存先は data/channels.json ひとつ。
     外部サイトへの通信は api/*.php を通す（トークンを隠す／相手への
     負担を減らすため）。
     ▶ 全体像・用語・「◯◯を追加したい」の手順は README.md を読むこと
   ■ この中での位置づけ
     全ページ共通のスタイル。クラス名は ds-（共通）/ pnl-（パネル設定画面）/
     ch-（チャンネル画面）で使い分ける。色と書体は :root の CSS 変数にまとめてある。
     パネルの中身の大きさは 1920x1080 空間の px で書く（表示側が縮める）。
   =========================================================== */

/* ===========================================================
   common.css  -  DATA STUDIO by Kactuif 全ページ共通スタイル
   =========================================================== */

/* -----------------------------------------------------------
   カラー / フォント変数
   ----------------------------------------------------------- */
:root {
  --ds-accent: #F6AA00;          /* テーマカラー（オレンジ） */
  --ds-blue: #0D62FF;            /* オープニングの幕 */
  --ds-danger: #ff0000;          /* 削除など破壊的操作 */
  --ds-text: #222222;
  --ds-bg: #ffffff;              /* ヘッダー等の基準背景 */
  --ds-page-bg: #dbdbdb;         /* ページ本体の背景（少しだけ暗め） */

  /* マップパネルの重ね表示（時計・凡例・見出し）の地。
     下の地図（衛星画像や航空写真）を少し透かす。
     透かしすぎると、白い雲や雪の上で文字が沈んで読めなくなるので
     この辺りが限度。濃さを変えたい時はここだけ直す */
  --ds-wx-ink:      rgba(17, 17, 17, .78);    /* 時刻（いちばん濃い） */
  --ds-wx-ink-soft: rgba(34, 34, 34, .74);    /* 日付 */
  --ds-wx-panel:    rgba(11, 11, 11, .76);    /* 凡例 */
  /* 見出しは色付きなので、同じ透け具合だと地図の柄を拾って濁る。
     少し濃いめにして色を保つ */
  --ds-wx-title:    rgba(0, 62, 179, .86);

  --ds-header-height: 90px;

  /* Adobe Fonts（Typekit, kitId: ggt4sbc）の UD角ゴ。js/typekit.js が読み込む */
  --ds-font: "fot-udkakugo-large-pr6n", sans-serif;
  --ds-weight-regular: 300;
  --ds-weight-bold: 600;
}

/* -----------------------------------------------------------
   リセット
   ----------------------------------------------------------- */
*,
*::before,
*::after { box-sizing: border-box; }

html, body { margin: 0; padding: 0; }

/* hidden 属性は UA スタイルシートの display:none で効いているだけなので、
   こちらで display:flex などを指定した要素では作者スタイルが勝って
   無効化されてしまう（実際に放送モードの全画面ステージが hidden の
   まま表示され、チャンネル画面が真っ赤になった）。
   hidden を付けたら必ず消えるようにここで固定する。 */
[hidden] { display: none !important; }

/* このデザインは MacBook Air（表示領域 1707×981）で Chrome の
   ページ拡大率 80% にした時のサイズを基準にしている。
   毎回手動で 80% にしなくて済むよう、最初からその縮尺で表示する。
   transform: scale() だと position:fixed の基準がズレる
   （ローダーや幅警告オーバーレイが崩れる）ので、実際の拡大率と
   同じ挙動をする zoom を使う。 */
html {
  zoom: 0.8;
}

body {
  font-family: var(--ds-font);
  font-weight: var(--ds-weight-regular);
  color: var(--ds-text);
  background: var(--ds-page-bg);
  -webkit-font-smoothing: antialiased;
}

img { display: block; max-width: 100%; }

/* -----------------------------------------------------------
   共通ヘッダー（js/header.js が生成）
   ----------------------------------------------------------- */
.ds-header {
  position: relative;
  width: 100%;
  height: var(--ds-header-height);
  border-bottom: 3px solid var(--ds-accent);
  background: var(--ds-bg);
}

/* タイトルはロゴの幅に影響されず、常にヘッダーの中央 */
.ds-header__title {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  margin: 0;
  font-size: 48px;
  font-weight: var(--ds-weight-bold);
  letter-spacing: 0.04em;
  white-space: nowrap;
}

/* ページ固有のボタンを置く左側スロット。
   下のツールバーと左端を揃えるため 40px にしている */
.ds-header__left {
  position: absolute;
  top: 50%;
  left: 40px;
  transform: translateY(-50%);
  display: flex;
  align-items: center;
  gap: 16px;
}

/* ロゴは右端 */
.ds-header__logo {
  position: absolute;
  top: 50%;
  right: 32px;
  transform: translateY(-50%);
  display: flex;
  align-items: center;
}

.ds-header__logo img {
  height: 54px;
  width: auto;
}

/* -----------------------------------------------------------
   ツールバー（新規作成 / 編集 / 削除 など）
   ----------------------------------------------------------- */
.ds-toolbar {
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 24px 0 0 40px;
}

/* 左右に振り分けるツールバー（チャンネル画面）。
   .ds-toolbar__group を2つ置いて、左寄せ／右寄せに分ける */
.ds-toolbar--split {
  justify-content: space-between;
  padding-right: 40px;
}

.ds-toolbar__group {
  display: flex;
  align-items: center;
  gap: 16px;
}

/* -----------------------------------------------------------
   放送モード（body.is-broadcasting）
   操作用のUIを引っ込めて、表示内容だけの画面にする。
   display:none だとアニメーションできないので、
   幅・高さを潰す形でたたんでいる。
   ----------------------------------------------------------- */

/* 「戻る」は幅を潰して消す。ヘッダー左側は flex なので、
   これだけで「放送モード」ボタンが戻るボタンの位置へ滑り込む。
   margin-right のマイナスは flex の gap(16px) を打ち消すため */
.ds-header__back {
  overflow: hidden;
  white-space: nowrap;
  max-width: 240px;
  transition: max-width 0.3s ease,
              opacity 0.3s ease,
              padding 0.3s ease,
              border-width 0.3s ease,
              margin-right 0.3s ease;
}

.is-broadcasting .ds-header__back {
  max-width: 0;
  opacity: 0;
  padding-left: 0;
  padding-right: 0;
  border-width: 0;
  margin-right: -16px;
  pointer-events: none;
}

/* パネル追加・編集・削除・チャンネル設定のツールバーごとたたむ */
.ds-toolbar--split {
  overflow: hidden;
  max-height: 200px;
  transition: max-height 0.3s ease,
              opacity 0.3s ease,
              padding-top 0.3s ease;
}

.is-broadcasting .ds-toolbar--split {
  max-height: 0;
  opacity: 0;
  padding-top: 0;
  pointer-events: none;
}

/* 下部のチャンネルID表示 */
.ds-channel-placeholder {
  transition: opacity 0.3s ease;
}

.is-broadcasting .ds-channel-placeholder {
  opacity: 0;
  pointer-events: none;
}

/* <button> でも <a> でも同じ見た目になるようにしている
   （チャンネル画面の「← チャンネル選択」はリンク） */
.ds-btn {
  appearance: none;
  -webkit-appearance: none;
  display: inline-flex;
  align-items: center;
  border-radius: 0;
  border: 2px solid transparent;
  padding: 8px 10px;
  font-family: var(--ds-font);
  font-size: 25px;
  font-weight: var(--ds-weight-bold);
  line-height: 1;
  letter-spacing: 0.04em;
  text-decoration: none;
  cursor: pointer;
  /* 状態が切り替わる時（放送モードのON/OFF、編集・削除の待機中など）
     塗りがパッと変わらずフェードするように。
     アイコンは fill:currentColor なので color の遷移に自動で追従する */
  transition: background-color 0.3s ease,
              color 0.3s ease,
              border-color 0.3s ease;
}

.ds-btn--dark {
  background: #222222;
  color: #ffffff;
}

.ds-btn--danger {
  background: transparent;
  color: var(--ds-danger);
  border-color: var(--ds-danger);
}

/* 縁 1px の枠線ボタン（放送モードなど、押すと状態が切り替わるもの）。
   .ds-btn の枠は 2px なので、1px にした分を padding に足して
   他のボタンと高さが揃うようにしている */
.ds-btn--outline {
  background: transparent;
  color: #222222;
  border: 1px solid #222222;
  padding: 9px 11px;
  gap: 8px;
}

/* 押して有効になっている間は背景を反転させる */
.ds-btn--outline.is-active {
  background: #222222;
  color: #ffffff;
}

/* アイコンは currentColor で塗るので、反転時に自動で白くなる */
.ds-btn__icon {
  width: 1em;
  height: 1em;
  flex: 0 0 auto;
  fill: currentColor;
}

.ds-btn:disabled {
  opacity: 0.35;
  cursor: not-allowed;
}

/* 「編集」「削除」を押した直後、次にカードを選ぶまでの待機中の見た目。
   点滅アニメーションは不要とのことなので、塗りつぶしで反転させるだけ
   の静的な見た目にする。 */
.ds-btn.is-armed {
  background: var(--ds-accent);
  border-color: var(--ds-accent);
  color: #1a1a1a;
}

/* 編集・削除の対象を選んでいる最中の案内文。座布団（背景・padding）は
   無しの赤文字だけ。
   line-height を明示しているのは、UD角ゴのデフォルトの行送りが
   フォントサイズよりかなり大きく、指定しないとこの文字が現れた時に
   ツールバーの行自体が広がってボタンやカードごと下にズレて
   しまうため（座布団の padding も同じ理由で持たせていない）。 */
.ds-hint {
  display: inline-flex;
  align-items: center;
  line-height: 1;
  color: var(--ds-danger);
  font-size: 20px;
  font-weight: var(--ds-weight-bold);
  letter-spacing: 0.02em;
  opacity: 0;
  transform: translateX(-8px);
  transition: opacity 0.15s ease-out, transform 0.15s ease-out;
  pointer-events: none;
}

.ds-hint.is-visible {
  opacity: 1;
  transform: translateX(0);
}

.ds-card-grid.is-picking .ds-card {
  cursor: pointer;
}

.ds-card-grid.is-picking .ds-card:hover {
  outline: 4px solid var(--ds-accent);
  outline-offset: -4px;
}

/* モーダルの「キャンセル」用。ダーク背景の中で悪目立ちしないよう控えめに */
.ds-btn--ghost {
  background: transparent;
  color: #222222;
  border-color: #cccccc;
}

/* 削除確認モーダルの「削除」ボタン。トーストバーの --danger は
   アウトラインだが、こちらは確定操作なので塗りにして区別する */
.ds-btn--filled.ds-btn--danger {
  background: var(--ds-danger);
  color: #ffffff;
  border-color: var(--ds-danger);
}

/* -----------------------------------------------------------
   チャンネルカード
   ----------------------------------------------------------- */
/* チャンネル画面のパネル一覧（.ds-panel-grid）と同じ詰め方。
   **幅を決め打ちにしないこと。** 横に並べられるだけ並べた後の余りが
   右と下に残って、逆L字の余白に見える（実測：1990px幅で右に195px、
   下は最後の行から下が丸ごと空く）。
   1fr で伸ばして端を余白（40px）にそろえる */
.ds-card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 420px), 1fr));
  justify-items: center;    /* 数が少なく列が広くなった時に中央へ寄せる */
  gap: 24px;
  padding: 24px 40px 40px;
}

.ds-card {
  position: relative;
  width: 100%;
  max-width: 600px;   /* 数が少ない時に1枚が大きくなりすぎないように */
  /* 高さは幅から決める（パネルと同じ16:9） */
  aspect-ratio: 16 / 9;
  padding: 0;
  border: none;
  cursor: pointer;
  overflow: hidden;
  background: #000000;
}

.ds-card__thumb {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* 薄暗オーバーレイ。画像の上に重ねて中央にチャンネル名を出す */
.ds-card__overlay {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(0, 0, 0, 0.7);
}

.ds-card__label {
  color: #ffffff;
  font-family: var(--ds-font);
  font-size: 35px;
  font-weight: var(--ds-weight-bold);
  letter-spacing: 0.04em;
}

/* -----------------------------------------------------------
   モーダル（新規作成・編集・削除確認）
   MicroModal.js は class の付け外しと aria 属性だけ担当するので、
   見た目・アニメーションはここで用意する。
   ----------------------------------------------------------- */
.modal {
  display: none;
}

.modal.is-open {
  display: block;
}

.modal__overlay {
  position: fixed;
  inset: 0;
  z-index: 20000;
  background: rgba(0, 0, 0, 0.5);
  display: flex;
  align-items: center;
  justify-content: center;
}

/* header/footer は固定し、.modal__content だけがスクロールする。
   新規作成/編集モーダルは <form> が header/content/footer を
   まとめて包んでいるので、form 自身も縦方向 flex にしてサイズを
   引き継がせる。 */
.modal__container {
  display: flex;
  flex-direction: column;
  width: 480px;
  max-width: calc(100vw - 48px);
  max-height: 90vh;
  overflow: hidden;
  background: #ffffff;
  font-family: var(--ds-font);
}

.modal__container > form {
  display: flex;
  flex-direction: column;
  min-height: 0;
}

.modal__header {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 20px 24px;
  border-bottom: 1px solid #e0e0e0;
}

.modal__title {
  margin: 0;
  font-size: 22px;
  font-weight: var(--ds-weight-bold);
  color: var(--ds-text);
}

.modal__close {
  appearance: none;
  -webkit-appearance: none;
  border: none;
  background: transparent;
  width: 28px;
  height: 28px;
  cursor: pointer;
  position: relative;
}

.modal__close::before,
.modal__close::after {
  content: '';
  position: absolute;
  top: 50%;
  left: 50%;
  width: 18px;
  height: 2px;
  background: #222222;
}

.modal__close::before { transform: translate(-50%, -50%) rotate(45deg); }
.modal__close::after { transform: translate(-50%, -50%) rotate(-45deg); }

.modal__content {
  flex: 1 1 auto;
  overflow-y: auto;
  min-height: 0;
  padding: 24px;
}

.modal__content p {
  margin: 0;
  font-size: 16px;
  line-height: 1.6;
  color: var(--ds-text);
}

.modal__footer {
  flex: 0 0 auto;
  display: flex;
  justify-content: flex-end;
  gap: 12px;
  padding: 16px 24px;
  border-top: 1px solid #e0e0e0;
}

.modal__footer .ds-btn {
  padding: 10px 24px;
  font-size: 16px;
}

/* MicroModal 標準のフェード＋スライド演出。
   MicroModal.js は closeModal() 実行時、真っ先に aria-hidden="true" を
   セットしてから animationend を待って is-open を外す（＝閉じる演出は
   aria-hidden="true" になった"後"に再生される）。なので閉じる側にも
   ちゃんとしたキーフレームを用意する必要がある
   （前は animation:none にしていたため、閉じる時に animationend が
   一切発火せず is-open が外れないままフリーズしていた）。 */
.micromodal-slide[aria-hidden="false"] .modal__overlay {
  animation: ds-modal-fade-in 0.3s ease-out;
}

.micromodal-slide[aria-hidden="false"] .modal__container {
  animation: ds-modal-slide-in 0.3s cubic-bezier(0.22, 1, 0.36, 1);
}

.micromodal-slide[aria-hidden="true"] .modal__overlay {
  animation: ds-modal-fade-out 0.25s ease-in-out;
}

.micromodal-slide[aria-hidden="true"] .modal__container {
  animation: ds-modal-slide-out 0.25s ease-in-out;
}

.micromodal-slide .modal__container,
.micromodal-slide .modal__overlay {
  will-change: transform, opacity;
}

@keyframes ds-modal-fade-in {
  from { opacity: 0; }
  to { opacity: 1; }
}

@keyframes ds-modal-fade-out {
  from { opacity: 1; }
  to { opacity: 0; }
}

/* 「ふわー」と浮き上がるように見せるため、スライドだけでなく
   わずかな拡大縮小も合わせる */
@keyframes ds-modal-slide-in {
  from { transform: translateY(-28px) scale(0.96); opacity: 0; }
  to { transform: translateY(0) scale(1); opacity: 1; }
}

@keyframes ds-modal-slide-out {
  from { transform: translateY(0) scale(1); opacity: 1; }
  to { transform: translateY(-16px) scale(0.97); opacity: 0; }
}

/* ---- フォーム部品 ---- */
.ds-field {
  margin-bottom: 20px;
}

.ds-field:last-child {
  margin-bottom: 0;
}

.ds-field__label {
  display: block;
  margin-bottom: 8px;
  font-size: 14px;
  font-weight: var(--ds-weight-bold);
  color: var(--ds-text);
}

.ds-field__input {
  width: 100%;
  padding: 10px 12px;
  font-family: var(--ds-font);
  font-size: 16px;
  font-weight: var(--ds-weight-regular);
  border: 1px solid #cccccc;
  border-radius: 0;
  background: #ffffff;
  color: var(--ds-text);
}

.ds-field__input:focus {
  outline: none;
  border-color: var(--ds-accent);
}

/* サムネイル選択。16:9 のプレビュー枠 + ファイル入力 */
.ds-thumb-picker__preview {
  position: relative;
  width: 100%;
  aspect-ratio: 16 / 9;
  background: #222222;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  margin-bottom: 10px;
}

.ds-thumb-picker__preview img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.ds-thumb-picker__empty {
  color: #ffffff;
  font-size: 14px;
  opacity: 0.6;
}

/* -----------------------------------------------------------
   幅が狭くタイトルとロゴが被りそうな時の全画面案内
   ----------------------------------------------------------- */
.ds-narrow-overlay {
  display: none;
  position: fixed;
  inset: 0;
  z-index: 9999;
  background: var(--ds-bg);
  align-items: center;
  justify-content: center;
  padding: 24px;
  text-align: center;
}

.ds-narrow-overlay.is-visible {
  display: flex;
}

.ds-narrow-overlay__text {
  margin: 0;
  font-size: 18px;
  font-weight: var(--ds-weight-bold);
  color: var(--ds-text);
}

/* -----------------------------------------------------------
   オープニングアニメーション（js/loader.js が生成）

   .ds-loader            … 白い全画面の幕。中央に通常ロゴ
   .ds-loader__curtain   … 上から降りてくる青。height 0 → 100vh
   .ds-loader__logo--alt … 幕の中のロゴ。画面中央に固定してあるので
                           幕が伸びた分だけ現れる = ワイプで切り替わる
   ----------------------------------------------------------- */
.ds-loading,
.ds-loading body { overflow: hidden; }

.ds-loader {
  position: fixed;
  inset: 0;
  z-index: 10000;
  background: var(--ds-bg);
  opacity: 1;
  transition: opacity 700ms ease;   /* loader.js の FADE_TIME と揃える */
}

.ds-loader.is-hiding { opacity: 0; }

/* 通常ロゴ / 幕の中のロゴ を全く同じ位置・大きさに重ねる。
   left / max-width は % でよい（左右方向は幕もアニメーションしない
   ので、real な親幅に対する % で問題ない）。
   top だけは JS（loader.js）が px で直接指定している。
   理由: 幕の中のロゴの親は高さがアニメーションする .ds-loader__curtain
   なので、top を % にすると幕の高さに連動して動いてしまう。
   vh も使えない（zoom: 0.8 の影響で実際のビューポートより
   縮んで計算され、幕の下端との間に隙間ができる）。 */
.ds-loader__logo {
  position: absolute;
  left: 50%;
  transform: translate(-50%, -50%) scale(1);
  width: 420px;
  max-width: 60%;
  height: auto;
  /* transition（開始時刻と長さ）は loader.js が幕の動きから計算して入れる。
     幕がロゴに被り始める瞬間に合わせたいので、CSS では固定値を持たない。 */
}

/* 幕がロゴを通過する間、少しだけ大きくなる。
   2枚とも同じ値なので、拡大してもワイプの継ぎ目はズレない。 */
.ds-loader.is-dropping .ds-loader__logo {
  transform: translate(-50%, -50%) scale(1.2);
}

.ds-loader__curtain {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 0;
  overflow: hidden;                 /* これが logo2 のワイプになる */
  background: var(--ds-blue);
  /* イーズアウト強め（一気に降りて、最後にゆっくり収まる） */
  transition: height 1100ms cubic-bezier(0.16, 1, 0.3, 1);
}

/* 100vh ではなく 100%（親の .ds-loader は position:fixed; inset:0 で
   画面いっぱいなので同じ結果になる）。理由は上の .ds-loader__logo と同じ。 */
.ds-loader.is-dropping .ds-loader__curtain { height: 100%; }

/* 幕の中のロゴは、幕の高さが変わっても画面中央から動かない */
.ds-loader__logo--alt {
  left: 50%;
}

/* -----------------------------------------------------------
   ログイン画面（login.php） - Material Design 2
   この画面だけ UD角ゴ を使わず端末のデフォルトフォントにする。
   ----------------------------------------------------------- */

/* 他のページは 80% 縮小前提のデザインだが、この画面は
   MD2 の寸法（56px フィールド等）をそのまま使うので等倍に戻す */
.ds-login-html {
  zoom: 1;
}

.ds-login-page {
  /* --ds-font を上書きすることで、var(--ds-font) を参照している
     子要素もまとめて端末のデフォルトフォントになる。
     システムフォントは 300 を持たないことが多いので通常は 400 */
  --ds-font: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue",
             "Hiragino Sans", "Hiragino Kaku Gothic ProN", "Yu Gothic", Meiryo, sans-serif;
  --ds-weight-regular: 400;
  --ds-weight-bold: 500;          /* MD2 の medium 相当 */

  /* MD2 のカラーロール */
  --md-primary: var(--ds-accent);
  --md-on-surface: rgba(0, 0, 0, 0.87);
  --md-secondary-text: rgba(0, 0, 0, 0.6);
  --md-hint: rgba(0, 0, 0, 0.38);
  --md-divider: rgba(0, 0, 0, 0.42);
  --md-error: #b00020;            /* MD2 標準のエラー色 */

  font-family: var(--ds-font);
  font-weight: var(--ds-weight-regular);
  background: #fafafa;            /* MD2 の background */
  color: var(--md-on-surface);
}

.ds-auth {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
}

/* MD2 elevation 8（ダイアログ相当）の影 */
.ds-auth__card {
  width: 400px;
  max-width: 100%;
  padding: 32px 24px 24px;
  background: #ffffff;            /* MD2 の surface */
  border-radius: 4px;
  box-shadow:
    0 5px 5px -3px rgba(0, 0, 0, 0.2),
    0 8px 10px 1px rgba(0, 0, 0, 0.14),
    0 3px 14px 2px rgba(0, 0, 0, 0.12);
}

.ds-auth__logo {
  width: 200px;
  max-width: 64%;
  height: auto;
  margin: 0 auto 20px;
}

/* MD2 タイプスケールの headline6 */
.ds-auth__title {
  margin: 0 0 24px;
  text-align: center;
  font-size: 20px;
  font-weight: var(--ds-weight-bold);
  letter-spacing: 0.0125em;
  color: var(--md-on-surface);
}

/* ---- MD2 filled テキストフィールド ----------------------
   構造は  input → label → line  の順。
   CSS は後ろの兄弟しか選べない（~）ので、input の状態で
   ラベルと下線を制御するにはこの順番である必要がある。 */
.ds-tf {
  position: relative;
  height: 56px;
  background: rgba(0, 0, 0, 0.04);
  border-radius: 4px 4px 0 0;
  transition: background-color 0.15s ease;
}

.ds-tf:hover {
  background: rgba(0, 0, 0, 0.08);
}

.ds-tf__input {
  width: 100%;
  height: 100%;
  padding: 22px 16px 6px;         /* 浮いたラベルとぶつからない上余白 */
  border: none;
  background: transparent;
  font-family: inherit;
  font-size: 16px;
  color: var(--md-on-surface);
  caret-color: var(--md-primary);
}

.ds-tf__input:focus {
  outline: none;
}

/* 未入力かつ未フォーカスの時の位置。transform-origin を左上にして
   縮小した時に左揃えのまま上に上がるようにする */
.ds-tf__label {
  position: absolute;
  left: 16px;
  top: 18px;
  transform-origin: left top;
  font-size: 16px;
  line-height: 1;
  color: var(--md-secondary-text);
  pointer-events: none;
  transition: transform 0.15s cubic-bezier(0.4, 0, 0.2, 1),
              color 0.15s cubic-bezier(0.4, 0, 0.2, 1);
}

/* フォーカス時、または何か入力されている時にラベルを浮かせる */
.ds-tf__input:focus ~ .ds-tf__label,
.ds-tf__input:not(:placeholder-shown) ~ .ds-tf__label {
  transform: translateY(-10px) scale(0.75);
}

.ds-tf__input:focus ~ .ds-tf__label {
  color: var(--md-primary);
}

/* 下線。既定の 1px（::before）の上に、フォーカスで横に伸びる
   2px の線（.ds-tf__line）を重ねるのが MD2 の動き */
.ds-tf::before {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 1px;
  background: var(--md-divider);
}

.ds-tf__line {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 2px;
  background: var(--md-primary);
  transform: scaleX(0);
  transition: transform 0.15s cubic-bezier(0.4, 0, 0.2, 1);
}

.ds-tf__input:focus ~ .ds-tf__line {
  transform: scaleX(1);
}

/* エラー状態。MD2 ではフィールド自体が赤くなり、
   下に赤いヘルパーテキストが出る */
.ds-tf.is-invalid::before,
.ds-tf.is-invalid .ds-tf__line {
  background: var(--md-error);
}

.ds-tf.is-invalid .ds-tf__line {
  transform: scaleX(1);
}

.ds-tf.is-invalid .ds-tf__label,
.ds-tf.is-invalid .ds-tf__input:focus ~ .ds-tf__label {
  color: var(--md-error);
}

.ds-tf__helper {
  margin: 4px 16px 0;
  font-size: 12px;
  line-height: 1.4;
  color: var(--md-error);
}

/* ---- MD2 contained ボタン ------------------------------- */
.ds-mdbtn {
  position: relative;
  overflow: hidden;               /* リップルをボタンの外に出さない */
  appearance: none;
  -webkit-appearance: none;
  display: block;
  width: 100%;
  height: 44px;
  margin-top: 28px;
  padding: 0 16px;
  border: none;
  border-radius: 4px;
  background: var(--md-primary);
  color: rgba(0, 0, 0, 0.87);     /* オレンジ地なので白文字だと読みにくい */
  font-family: inherit;
  font-size: 14px;
  font-weight: var(--ds-weight-bold);
  letter-spacing: 0.0892857em;    /* MD2 button のトラッキング */
  cursor: pointer;
  /* elevation 2 */
  box-shadow:
    0 3px 1px -2px rgba(0, 0, 0, 0.2),
    0 2px 2px 0 rgba(0, 0, 0, 0.14),
    0 1px 5px 0 rgba(0, 0, 0, 0.12);
  transition: box-shadow 0.2s cubic-bezier(0.4, 0, 0.2, 1),
              filter 0.2s ease;
}

/* hover で elevation 4 に持ち上がる */
.ds-mdbtn:hover:not(:disabled) {
  filter: brightness(1.05);
  box-shadow:
    0 2px 4px -1px rgba(0, 0, 0, 0.2),
    0 4px 5px 0 rgba(0, 0, 0, 0.14),
    0 1px 10px 0 rgba(0, 0, 0, 0.12);
}

/* 押下中は elevation 8 */
.ds-mdbtn:active:not(:disabled) {
  box-shadow:
    0 5px 5px -3px rgba(0, 0, 0, 0.2),
    0 8px 10px 1px rgba(0, 0, 0, 0.14),
    0 3px 14px 2px rgba(0, 0, 0, 0.12);
}

.ds-mdbtn:disabled {
  background: rgba(0, 0, 0, 0.12);
  color: var(--md-hint);
  box-shadow: none;
  cursor: not-allowed;
}

/* リップル（js/md-ripple.js が生成） */
.ds-ripple {
  position: absolute;
  border-radius: 50%;
  background: rgba(0, 0, 0, 0.18);
  transform: scale(0);
  opacity: 1;
  pointer-events: none;
  animation: ds-ripple-expand 0.5s cubic-bezier(0.4, 0, 0.2, 1);
}

@keyframes ds-ripple-expand {
  to {
    transform: scale(1);
    opacity: 0;
  }
}

/* -----------------------------------------------------------
   フォームの補足・エラー表示
   ----------------------------------------------------------- */
.ds-field__note {
  margin: 8px 0 0;
  font-size: 13px;
  line-height: 1.5;
  color: #666666;
}

.ds-form-error {
  margin: 16px 0 0;
  color: var(--ds-danger);
  font-size: 15px;
  font-weight: var(--ds-weight-bold);
  line-height: 1.5;
}

/* 「サムネイルを外す」のような、ボタンだが文字リンクに見せたいもの */
.ds-link-btn {
  appearance: none;
  -webkit-appearance: none;
  border: none;
  background: transparent;
  padding: 0;
  margin-top: 10px;
  font-family: var(--ds-font);
  font-size: 14px;
  font-weight: var(--ds-weight-bold);
  color: var(--ds-danger);
  text-decoration: underline;
  cursor: pointer;
}

/* -----------------------------------------------------------
   チャンネル画面（channel.php）
   ----------------------------------------------------------- */
.ds-channel-body {
  padding: 24px 40px 40px;
}

.ds-channel-placeholder {
  margin: 0;
  font-size: 16px;
  color: #555555;
}

/* チャンネルが見つからない時 */
.ds-empty {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 20px;
  padding: 40px;
}

.ds-empty__text {
  margin: 0;
  font-size: 20px;
  font-weight: var(--ds-weight-bold);
}

/* -----------------------------------------------------------
   中央に一瞬出る通知（.ds-notice）
   「放送用モードに切り替えました」（channel.php / js/channel.js）
   「保存しました」（panel.php / js/panel.js）で共用する。
   ----------------------------------------------------------- */
.ds-notice {
  /* main の中ではなく、画面（ビューポート）そのものの中央に出す */
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  background: rgba(98, 98, 98, 0.7);
  color: white;
  padding: 20px 40px;
  border-radius: 60px;
  font-size: 30px;
  font-weight: 500;
  text-align: center;
  z-index: 10;
  opacity: 1;
  transition: opacity 0.3s ease;
  pointer-events: none;   /* 通知の裏にあるものをクリックできるように */
}

.ds-notice.fade-out {
  opacity: 0;
}

/* 出現時：中央から拡大しながらフェードイン。
   表示するたびにこのクラスを付け外しする
   （付けっぱなしだと2回目以降アニメーションが再生されない）。
   最後のキーフレームが定常状態（scale(1) 込みの transform）と
   同じ値なので、アニメーション終了後に見た目が変わらず自然に続く。 */
.ds-notice.is-entering {
  animation: ds-bcbox-in 0.3s cubic-bezier(0.16, 1, 0.3, 1);
}

@keyframes ds-bcbox-in {
  from {
    transform: translate(-50%, -50%) scale(0.85);
    opacity: 0;
  }
  to {
    transform: translate(-50%, -50%) scale(1);
    opacity: 1;
  }
}

/* -----------------------------------------------------------
   パネル設定画面（panel.php）
   ヘッダー / プレビュー / 右サイドバー の3分割。
   この画面は共通ヘッダーを使わず専用の作りにしている。
   ----------------------------------------------------------- */
:root {
  --pnl-blue: #0b7af5;          /* 保存ボタン・トグルON */
  --pnl-canvas-bg: #e7edfb;     /* プレビュー背景の淡い青 */
  --pnl-line: #d8d8d8;
  --pnl-muted: #9a9a9a;         /* OFF の行の文字色 */
}

/* height:100vh だと :root の zoom:0.8 の影響で vh が縮んで計算され、
   画面下に余白が残る（実測で 900px のビューポートに 720px しか
   埋まらなかった）。position:fixed は zoom の影響を受けず
   ビューポート全体に広がるので、そちらで確実に埋める。 */
.pnl-page {
  position: fixed;
  inset: 0;
  display: flex;
  flex-direction: column;
  overflow: hidden;             /* 画面内で完結させ、全体スクロールはしない */
  background: #ffffff;
}

/* ---- ヘッダー ---- */
.pnl-header {
  flex: 0 0 auto;
  height: var(--ds-header-height);
  display: flex;
  align-items: center;
  gap: 20px;
  padding: 0 24px;
  background: #ffffff;
  border-bottom: 1px solid var(--pnl-line);
}

.pnl-header__titles {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 2px;
  min-width: 0;
}

.pnl-header__channel {
  font-size: 15px;
  line-height: 1;
  color: #8a8a8a;
}

.pnl-header__panel {
  font-size: 30px;
  font-weight: var(--ds-weight-bold);
  line-height: 1.1;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* 右寄せにするため、間を押し広げる */
.pnl-header__actions {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 10px;
}

/* 元に戻す / やり直す */
.pnl-iconbtn {
  appearance: none;
  -webkit-appearance: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 42px;
  height: 38px;
  padding: 0;
  border: 1px solid #b9d3f5;
  border-radius: 3px;
  background: #ffffff;
  color: var(--pnl-blue);
  cursor: pointer;
  transition: background-color 0.15s ease, border-color 0.15s ease;
}

.pnl-iconbtn svg {
  width: 22px;
  height: 22px;
  fill: currentColor;
}

.pnl-iconbtn:hover:not(:disabled) {
  background: #eef5ff;
}

.pnl-iconbtn:disabled {
  color: #c2c2c2;
  border-color: #e0e0e0;
  cursor: not-allowed;
}

/* 保存 */
.pnl-savebtn {
  appearance: none;
  -webkit-appearance: none;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  height: 38px;
  padding: 0 18px;
  border: none;
  border-radius: 3px;
  background: var(--pnl-blue);
  color: #ffffff;
  font-family: var(--ds-font);
  font-size: 20px;
  font-weight: var(--ds-weight-bold);
  line-height: 1;
  cursor: pointer;
  transition: filter 0.15s ease;
}

.pnl-savebtn svg {
  width: 20px;
  height: 20px;
  fill: currentColor;
}

.pnl-savebtn:hover:not(:disabled) { filter: brightness(1.08); }
.pnl-savebtn:disabled { opacity: 0.5; cursor: not-allowed; }

/* ---- 本体（プレビュー + サイドバー） ---- */
.pnl-body {
  flex: 1 1 auto;
  display: flex;
  min-height: 0;
}

.pnl-canvas {
  flex: 1 1 auto;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 40px;
  background: var(--pnl-canvas-bg);
  min-width: 0;
}

/* 中身は js/panel-render.js が描く。
   大きさは親の .pnl-stage（16:9）が決めるので、
   ここでは位置合わせだけして中身に干渉しない */
.pnl-preview {
  position: absolute;
  inset: 0;
}

/* ---- 右サイドバー ---- */
/* position:relative が要る。これが無いと、中の .pnl-detail の
   inset:0 が position:fixed の .pnl-page を基準にしてしまい、
   要素の設定が画面全体を覆ってしまう */
.pnl-sidebar {
  position: relative;
  flex: 0 0 420px;
  display: flex;
  flex-direction: column;
  min-height: 0;
  background: #ffffff;
  border-left: 1px solid var(--pnl-line);
}

.pnl-sidebar__title {
  flex: 0 0 auto;
  margin: 0;
  height: var(--ds-header-height);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 30px;
  font-weight: var(--ds-weight-bold);
}

.pnl-list {
  flex: 1 1 auto;
  overflow-y: auto;
  border-top: 1px solid var(--pnl-line);
}

.pnl-list__section {
  margin: 0;
  padding: 12px 20px 6px;
  font-size: 15px;
  color: var(--pnl-muted);
}

/* ---- 設定の行 ---- */
.pnl-row {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 0 12px 0 20px;
  height: 52px;
  border-bottom: 1px solid #ececec;
}

.pnl-row__icon {
  width: 26px;
  height: 26px;
  flex: 0 0 auto;
  fill: #222222;
}

.pnl-row__label {
  flex: 1 1 auto;
  font-size: 22px;
  font-weight: var(--ds-weight-bold);
  color: #222222;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* PNG のアイコンは fill で色を変えられないので、
   縦横を揃えるだけにして OFF 時は opacity で淡くする */
.pnl-row__icon--img {
  object-fit: contain;
}

/* トグルOFFの行は、アイコン・文字ごと淡くして
   「今は効いていない」ことを見た目で示す */
.pnl-row.is-off .pnl-row__icon { fill: var(--pnl-muted); }
.pnl-row.is-off .pnl-row__label { color: var(--pnl-muted); }

/* PNG は fill が効かないので opacity で淡くする */
.pnl-row.is-off .pnl-row__icon--img { opacity: 0.4; }

/* 詳細（右向きシェブロン） */
.pnl-row__more {
  appearance: none;
  -webkit-appearance: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  flex: 0 0 auto;
  padding: 0;
  border: none;
  background: transparent;
  cursor: pointer;
}

.pnl-row__more svg {
  width: 26px;
  height: 26px;
  fill: #6b6b6b;
}

/* ---- トグルスイッチ ---- */
.pnl-toggle {
  appearance: none;
  -webkit-appearance: none;
  position: relative;
  flex: 0 0 auto;
  width: 46px;
  height: 26px;
  padding: 0;
  border: none;
  border-radius: 13px;
  background: #d0d0d2;
  cursor: pointer;
  transition: background-color 0.25s ease;
}

.pnl-toggle::after {
  content: "";
  position: absolute;
  top: 3px;
  left: 3px;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background: #ffffff;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.35);
  transition: transform 0.25s ease;
}

.pnl-toggle[aria-checked="true"] {
  background: var(--pnl-blue);
}

.pnl-toggle[aria-checked="true"]::after {
  transform: translateX(20px);
}

/* -----------------------------------------------------------
   チャンネル画面のパネル一覧
   ----------------------------------------------------------- */
/* 画面の幅いっぱいに、等間隔で敷き詰める。
   カードの幅を固定すると右端に半端な余白が残るので、
   「入るだけの列を作って、余りは各列で分け合う」形にする
   （列数は画面幅まかせ。カード自体が伸び縮みする） */
.ds-panel-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 300px), 1fr));
  justify-items: center;    /* 数が少なく列が広くなった時に中央へ寄せる */
  gap: 24px;
  padding: 24px 40px 40px;
}

/* カードは中身の縮小版そのもの。
   js/panel-render.js が描くので、編集画面や全画面と
   まったく同じ見た目になる（名前は出さない） */
.ds-panel-card {
  position: relative;
  width: 100%;
  max-width: 600px;   /* 数が少ない時に1枚が大きくなりすぎないように */
  padding: 0;
  border: none;
  background: transparent;
  font-family: var(--ds-font);
  display: block;
  cursor: pointer;
  text-align: left;
}

.ds-panel-card__body {
  display: block;
  width: 100%;
  aspect-ratio: 16 / 9;
  overflow: hidden;
  background: #ffffff;
  box-shadow: 0 1px 6px rgba(0, 0, 0, 0.18);
}

.ds-panel-grid.is-picking .ds-panel-card:hover .ds-panel-card__body {
  outline: 4px solid var(--ds-accent);
  outline-offset: -4px;
}

/* 選んだカード。ホバーが外れても選択状態は分かるように、
   枠は hover と関係なく付けたままにする */
.ds-panel-grid.is-picking .ds-panel-card.is-selected .ds-panel-card__body {
  outline: 4px solid var(--ds-accent);
  outline-offset: -4px;
}

/* チェック印。選択モード中だけ見せる。カードの選択有無に関わらず
   場所を確保しておき、選んだ時だけ塗りつぶす（is-selected） */
.ds-panel-card__check {
  display: none;
  position: absolute;
  top: 10px;
  right: 10px;
  width: 30px;
  height: 30px;
  border-radius: 50%;
  border: 2px solid #ffffff;
  background: rgba(0, 0, 0, 0.35);
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.3);
}

.ds-panel-grid.is-picking .ds-panel-card__check {
  display: block;
}

.ds-panel-card.is-selected .ds-panel-card__check {
  background: var(--ds-accent);
  border-color: var(--ds-accent);
}

.ds-panel-card.is-selected .ds-panel-card__check::after {
  content: '';
  position: absolute;
  left: 8px;
  top: 13px;
  width: 12px;
  height: 6px;
  border: 3px solid #1a1a1a;
  border-top: none;
  border-right: none;
  transform: rotate(-45deg);
}

/* 特別パネル（ツール）。削除できないので一覧でも見分けが付くように
   角に印を出す */
.ds-panel-card--tool .ds-panel-card__body {
  box-shadow: 0 1px 6px rgba(0, 0, 0, 0.18), 0 0 0 2px #1b4fd8;
}

/* 放送モード中は編集用の印を全部引っ込める（本番の画に余計な物を出さない） */
body.is-broadcasting .ds-panel-card--tool .ds-panel-card__body {
  box-shadow: 0 1px 6px rgba(0, 0, 0, 0.18);
}

body.is-broadcasting .ds-panel-card--tool::after {
  display: none;
}

.ds-panel-card--tool::after {
  content: 'ツール';
  position: absolute;
  top: 0;
  left: 0;
  padding: 4px 10px;
  background: #1b4fd8;
  color: #ffffff;
  font-size: 12px;
  line-height: 1.2;
  font-weight: var(--ds-weight-bold);
  letter-spacing: 0.04em;
  pointer-events: none;
}

.ds-panel-empty {
  grid-column: 1 / -1;   /* 1列に収まらないよう、行いっぱいに置く */
  justify-self: start;
  margin: 0;
  padding: 8px 0;
  font-size: 18px;
  color: #777777;
}

/* -----------------------------------------------------------
   放送モード中のパネル全画面表示（channel.php / js/channel.js）
   画面中央から手前へ向かって拡大してくる見せ方。
   ----------------------------------------------------------- */

/* position:fixed は :root の zoom の影響を受けずビューポート全体に
   広がるので、100vw/100vh を使わずこれで埋める。
   背景を半透明の黒にしているのは、周りの余白から後ろの
   チャンネル画面がうっすら見えるようにするため */
.ds-panel-stage {
  position: fixed;
  inset: 0;
  z-index: 15000;
  /* **余白を残さない。** 放送に出す絵なので画面いっぱいに出す。
     地を半透明ではなく真っ黒にしてあるのは、画面が16:9でない時に
     上下（左右）へ出る帯を、放送と同じ黒帯に見せるため */
  background: #000000;
  display: flex;
  align-items: center;
  justify-content: center;
}

/* 閉じる×。右上に固定で置く。
   **画面のどこを押しても閉じる形はやめた。** 余白が無くなって
   パネルが画面全体になったので、そのままだとパネルに触れた瞬間に
   閉じてしまう（潮位の吹き出しなど、触って使うものが出せない）。
   閉じるのはこの×か Escape、あとは16:9でない画面に出る黒帯の部分。

   見た目は設定モーダルの閉じる（.modal__close）と同じ作りで、
   線を2本傾けて交差させる。地の上に直に乗るので、丸い下地を敷いて
   どんな絵の上でも読めるようにしてある */
.ds-panel-stage__close {
  position: absolute;
  top: 28px;
  right: 28px;
  z-index: 2;               /* パネルの中身より前 */
  appearance: none;
  -webkit-appearance: none;
  border: none;
  width: 64px;
  height: 64px;
  border-radius: 50%;
  background: rgba(0, 0, 0, 0.45);
  cursor: pointer;
  transition: background 0.15s ease;
}

.ds-panel-stage__close:hover,
.ds-panel-stage__close:focus-visible {
  background: rgba(0, 0, 0, 0.72);
}

.ds-panel-stage__close::before,
.ds-panel-stage__close::after {
  content: '';
  position: absolute;
  top: 50%;
  left: 50%;
  width: 30px;
  height: 4px;
  border-radius: 2px;
  background: #ffffff;
}

.ds-panel-stage__close::before { transform: translate(-50%, -50%) rotate(45deg); }
.ds-panel-stage__close::after  { transform: translate(-50%, -50%) rotate(-45deg); }

/* パネルは 16:9 を保ったまま、余白の内側に収まるようにする。
   width:100% + max-height だと高さだけが頭打ちになって比率が崩れる
   （実測で 1.83 になった）。高さを基準にして幅を auto にすると
   aspect-ratio が正しく効く。 */
/* 余白の内側いっぱいに広げ、16:9 に収めるのは
   js/panel-render.js に任せる（CSS の aspect-ratio は
   max-width / max-height のどちらが先に効くかで崩れるため） */
.ds-panel-stage__content {
  width: 100%;
  height: 100%;
  overflow: hidden;
  /* 中央基準で拡大させる */
  transform-origin: center center;
}

/* 出現：黒い幕がフェードインしながら、中身が中央から拡大してくる。
   幕（.ds-panel-stage 自身）の opacity と中身の scale を
   同じ長さで並走させることで一体の動きに見せる。
   中身側に opacity を持たせると二重に薄くなるので、
   フェードは幕にだけ持たせている。 */
.ds-panel-stage.is-entering {
  animation: ds-stage-fade-in 0.45s ease;
}

.ds-panel-stage.is-entering .ds-panel-stage__content {
  animation: ds-stage-zoom-in 0.45s cubic-bezier(0.16, 1, 0.3, 1);
}

/* 退出：来た道を戻るように、幕がフェードアウトしつつ中身が縮む */
.ds-panel-stage.is-leaving {
  animation: ds-stage-fade-out 0.3s ease forwards;
}

.ds-panel-stage.is-leaving .ds-panel-stage__content {
  animation: ds-stage-zoom-out 0.3s ease-in forwards;
}

@keyframes ds-stage-fade-in {
  from { opacity: 0; }
  to   { opacity: 1; }
}

@keyframes ds-stage-fade-out {
  from { opacity: 1; }
  to   { opacity: 0; }
}

@keyframes ds-stage-zoom-in {
  from { transform: scale(0.2); }
  to   { transform: scale(1); }
}

@keyframes ds-stage-zoom-out {
  from { transform: scale(1); }
  to   { transform: scale(0.2); }
}

/* -----------------------------------------------------------
   パネルの中身（js/panel-render.js が生成）
   1920x1080 のキャンバスを transform:scale で縮めて表示する。
   入れ物は必ず 16:9 にしてあるので、左上基準の scale で
   ちょうど収まる。
   ----------------------------------------------------------- */
/* 入れ物は好きな形でよい（16:9 でなくてもよい）。
   中の 1920x1080 を JS が縮尺＋中央寄せするので、余った部分は
   透明のまま背景が透ける */
.ds-panel-view {
  position: relative;
  overflow: hidden;
  background: transparent;
}

.ds-panel-canvas {
  position: absolute;
  top: 0;
  left: 0;
  transform-origin: 0 0;
  box-shadow: 0 2px 12px rgba(0, 0, 0, 0.14);
  /* 参考画像に寄せた、斜めの淡いストライプ入りの背景 */
  background:
    repeating-linear-gradient(115deg,
      rgba(255, 255, 255, 0.55) 0 64px,
      rgba(255, 255, 255, 0) 64px 210px),
    linear-gradient(160deg, #dbe7fb 0%, #eef4ff 60%, #e4edfd 100%);
}

/* 要素の枠。中身の文字は __text に入れる */
.ds-panel-el {
  position: absolute;
  display: flex;
}

.ds-panel-el__text {
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  font-family: var(--ds-font);
  font-weight: var(--ds-weight-bold);
  line-height: 1.15;
  white-space: pre-wrap;
  word-break: break-word;
}

/* 特別パネル（ツール）の中身。何を出すかは今後決めるので、
   今は場所だけを確保しているのが分かる見た目にしておく */
.ds-panel-el--tool {
  display: block;
  font-family: var(--ds-font);
}

/* マップパネル。パネル全面にマップだけを敷く */
.ds-map {
  position: relative;
  overflow: hidden;
  background: #0b2647;
  /* **地図の中の重なり順を、地図の中だけで完結させる。**
     地図は時計・凡例・再生バー・通知を z-index 5〜10 で重ねている。
     ここで閉じておかないと、その順番がパネル全体の重なりに混ざり、
     地図より後に置いたテロップ（z-index を持たない）より前へ
     出てしまう。テロップに再生バーが被るのはこれが原因。
     isolation は場所を動かさずに「囲い」だけ作る */
  isolation: isolate;
}

.ds-map__canvas {
  display: block;
  width: 100%;
  height: 100%;
  cursor: grab;
  touch-action: none;   /* 指で動かす時に画面ごとスクロールさせない */
}

.ds-map__canvas.is-dragging {
  cursor: grabbing;
}

/* 出典（右下）。地図の上に重ねる。大きさはパネルの座標系
   （1920x1080）での px で、カードでは他の文字と同じ比率で縮む */
.ds-map__attrib {
  z-index: 5;
  position: absolute;
  right: 0;
  bottom: 0;
  max-width: 100%;
  padding: 5px 16px;
  background: rgba(0, 0, 0, 0.55);
  color: rgba(255, 255, 255, 0.95);
  font-family: var(--ds-font);
  font-size: 23px;
  line-height: 1.3;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.ds-map__attrib a {
  color: inherit;
  text-decoration: none;
}

/* -----------------------------------------------------------
   雨雲パネル左側の重ね表示（js/map.js が組み立てる）
   時計・凡例・見出しを縦に並べる。位置と大きさはパネルの
   座標系（1920x1080）での px なので、カードでは他の要素と
   同じ比率で縮む。
   ----------------------------------------------------------- */
/* MapLibre は自分の canvas を、この入れ物の中に後から足す。
   時計・凡例・再生バー・出典はそれより先に作ってあるので、
   何もしないと DOM の順番で canvas の下に隠れる。
   z-index で前に出す（通知の 10 より下、地図より上） */
.ds-map__raininfo {
  z-index: 5;
  position: absolute;
  font-family: var(--ds-font);
  color: #ffffff;
  pointer-events: none;   /* 地図の操作を邪魔しない */
}

/* 時計。上段（日付）と下段（時刻）で地の濃さを変える */
.ds-rainclock__date,
.ds-rainclock__time {
  display: flex;
  align-items: center;
  justify-content: center;
  line-height: 1;
  font-weight: var(--ds-weight-bold);
  font-variant-numeric: tabular-nums;   /* 桁で幅が動かないように */
  letter-spacing: 0.02em;
}

.ds-rainclock__date {
  background: var(--ds-wx-ink-soft);
  font-size: 31px;
}

.ds-rainclock__time {
  background: var(--ds-wx-ink);
  font-size: 79px;
  letter-spacing: 0;
}

/* 雨雲の予想のコマ。日付の段に「予想」と出し、地の色を変えて
   実況と取り違えないようにする（js/map-canvas.js の updateWxInfo） */
.ds-rainclock.is-forecast .ds-rainclock__date {
  background: #C2410C;
}

/* 「:」だけ数字より少し上に寄せる（数字の中央に対して
   低く座って見えるための調整） */
.ds-rainclock__colon {
  display: inline-block;
  transform: translateY(-0.08em);
}

/* 凡例 */
.ds-rainlegend {
  position: relative;
  box-sizing: border-box;
  background: var(--ds-wx-panel);
}

/* 凡例の文字は太字にする。既定は weight 300（Light）で、
   配信（映像圧縮）を通すと細い線が真っ先に潰れる。
   ここは雨雲・アメダス共通（同じ .ds-rainlegend を使っている） */
.ds-rainlegend__unit {
  position: absolute;
  top: 8px;
  font-size: 24px;
  line-height: 1;
  font-weight: var(--ds-weight-bold);
}

.ds-rainlegend__scale {
  position: relative;
}

.ds-rainlegend__swatch {
  position: absolute;
  left: 0;
  display: block;
}

/* 段の境目に置く数字。top が境目そのものなので、
   自分の高さの半分だけ持ち上げて中心を合わせる */
.ds-rainlegend__tick {
  position: absolute;
  transform: translateY(-50%);
  /* 既定の大きさ。段が詰まっている凡例では js が小さくして入れ直す
     （js/map-canvas.js の WX_TICK_PX と tickPx） */
  font-size: 42px;
  line-height: 1;
  font-variant-numeric: tabular-nums;
  font-weight: var(--ds-weight-bold);
}

/* 推計気象分布の「天気」だけ、凡例が段階ではなく区分（晴れ・くもり・
   雨・雨または雪・雪）。数字を置く場所が無いので、色の隣に文字を
   並べる。箱の見た目（背景・角・影）は .ds-rainlegend をそのまま
   使い、ここでは中の並べ方だけを決める */
.ds-wxclass {
  width: auto;
  display: flex;
  flex-direction: column;
}

.ds-wxclass__row {
  display: flex;
  align-items: center;
}

/* 色見本。縁は付けない――雨雲・アメダスの凡例
   （.ds-rainlegend__swatch）と同じ見た目にそろえる。

   **特別警報（ほぼ黒）は凡例の暗い地に溶ける。** 縁で分けていたのを
   やめたので、そこだけは見分けにくい。直すなら縁を戻すのではなく、
   凡例の地を明るくするか、特別警報の色を上げること（縁を戻すと
   また雨雲・アメダスとずれる） */
.ds-wxclass__sw {
  flex: 0 0 auto;
}

.ds-wxclass__text {
  font-size: 38px;
  line-height: 1;
  font-weight: var(--ds-weight-bold);
  white-space: nowrap;
}

/* 見出し */
.ds-rainlegend__title {
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--ds-wx-title);
  font-size: 42px;
  line-height: 1;
  font-weight: var(--ds-weight-bold);
  letter-spacing: 0;
}

/* 雨雲の凡例（.ds-rainlegend）と、線状降水帯がONの時だけ隣に
   並ぶ小さい凡例（.ds-linearlegend）の行。線状降水帯がOFFなら
   凡例1つだけがそのまま入るので、見た目は今までと変わらない */
.ds-rainlegend-row {
  display: flex;
  align-items: flex-start;
}

/* 線状降水帯の小さい凡例。赤い四角＋説明文（3行）を並べるだけの、
   雨雲の凡例よりずっと軽い作り。横に長くなりすぎないよう、
   説明文は3行に折り返す（js/map.js 側で <br> を差し込む） */
.ds-linearlegend {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 16px 20px;
  background: var(--ds-wx-panel);
}

.ds-linearlegend__swatch {
  display: block;
  flex: 0 0 auto;
  width: 34px;
  height: 34px;
  /* タイル側で塗り替えている色（js/map-canvas.js・js/map.js の
     LINEARBAND_COLOR）と同じにする。気象庁の元の色 #FF2800 のままだと、
     雨雲の 50〜80mm/h の赤と見分けが付きにくいため。
     地図では白い輪の内側に半透明で重ねているが、**見本は不透明の
     オレンジ＋白い縁**にする。半透明のまま明るい地に重ねた見本にしたら、
     混ざって薄い肌色〜黄土色（242,152,115）になり「何色の地域か」が
     伝わらなかった（2026-09-22） */
  background: rgb(255, 75, 0);
  box-shadow: 0 0 0 3px #FFFFFF;
}

/* 線状降水帯まわりの凡例を縦に積む入れ物
   （上が「線状降水帯」、下が「線状降水帯（解析）」） */
.ds-linearlegend-stack {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 8px;
}

/* 線状降水帯（解析）の色見本。四角ではなく、地図に出るのと同じ
   「赤い縁の楕円」（js/map.js が組み立てる）。
   高さは四角の色見本とそろえる */
/* viewBox で描いてあるので、ここを変えれば中身ごと拡がる */
.ds-linearlegend__mark {
  display: block;
  flex: 0 0 auto;
  width: 62px;
  height: 36px;
}

/* 配信（映像圧縮）を通ると、細い字は真っ先に潰れる。
   本体の凡例が32px・見出しが42pxなのに対してここだけ24pxの標準ウェイト
   だったので、太字にして大きくしてある。3行とも短いので、
   これでも凡例の幅は雨雲パネルに収まる */
.ds-linearlegend__text {
  font-size: 30px;
  line-height: 1.35;
  font-weight: var(--ds-weight-bold);
  white-space: nowrap;
}

/* -----------------------------------------------------------
   雨雲パネル下側のツールメニュー（js/map.js が組み立てる）
   時間の目盛り・前後移動・再生・倍速・最新。大きさはパネルの
   座標系（1920x1080）での px。下端でそろえて横に並べる。
   ----------------------------------------------------------- */
/* 要素どうしの間隔はそろっていない（画像に合わせている）ので、
   ここでは gap を使わず js/map.js が margin-left で入れる */
.ds-rainbar {
  z-index: 5;
  position: absolute;
  display: flex;
  align-items: flex-end;
  font-family: var(--ds-font);
}

/* 時間の目盛り。見た目どおりの大きさの箱（まわりの並びに影響する
   のはこれだけ）。押せる範囲はこの中の .ds-rainbar__track-hit が
   別に持つ（丸いつまみのはみ出し分まで含めて広い） */
.ds-rainbar__track {
  position: relative;
  flex: 0 0 auto;
}

/* 白い縁の中に濃い地の、見た目の帯。押しても下の物へクリックが
   通るよう、当たり判定は持たない（.ds-rainbar__track-hit が受ける） */
.ds-rainbar__track-line {
  position: absolute;
  inset: 0;
  box-sizing: border-box;
  background: #3D3D3D;
  border-style: solid;
  border-color: #FFFFFF;
  border-radius: 999px;
  pointer-events: none;
}

/* left は 0〜100% で動かすので、自分の幅の半分だけ戻して中心を合わせる。
   つまみ自身も当たり判定を持たない（track-line と同じ理由） */
.ds-rainbar__thumb {
  position: absolute;
  top: 50%;
  transform: translate(-50%, -50%);
  border-radius: 50%;
  background: #FFFFFF;
  pointer-events: none;
}

/* 押せる範囲。丸いつまみが上下左右へはみ出す分まで含めて広い。
   .ds-rainbar__track（見た目どおりの大きさ）から position:absolute で
   はみ出させるだけなので、まわりの並び（flex）には影響しない。
   透明（見た目は track-line と thumb がすでに描いている） */
.ds-rainbar__track-hit {
  position: absolute;
  cursor: pointer;
  touch-action: none;   /* なぞって動かす時に画面ごとスクロールさせない */
}

.ds-rainbar__btn {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: center;
  appearance: none;
  -webkit-appearance: none;
  box-sizing: border-box;
  padding: 0;
  border: 2px solid #000000;
  border-radius: 8px;
  background: #CECECE;
  color: #000000;
  font-family: var(--ds-font);
  font-size: 21px;
  font-weight: var(--ds-weight-bold);
  line-height: 1;
  cursor: pointer;
}

.ds-rainbar__btn:hover {
  background: #E4E4E4;
}

/* 前後移動ボタンの文字。層によって文字数が変わる（雨雲は「-5m」、
   ひまわりは「-2.5m」など）ので、ボタンの大きさは変えずに、
   はみ出す時だけ文字を小さくする（js/map.js の setWxStepLabel）。
   font-size は JS 側で直接付け外しするので、ここでは特別なスタイルは
   要らない（class は JS がその場所を見つけるための目印） */

/* 再生／一時停止。丸い枠まで含めてアイコン1つ（Material Icons の
   play_circle / pause_circle）なので、ボタン自身は地も枠も持たない */
.ds-rainbar__play {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: center;
  appearance: none;
  -webkit-appearance: none;
  padding: 0;
  border: none;
  background: transparent;
  cursor: pointer;
}

.ds-rainbar__play svg {
  width: 100%;
  height: 100%;
  fill: #CECECE;
  stroke: #000000;
  stroke-width: 0.5;
  paint-order: stroke fill;   /* 縁を文字の外側だけに出す */
}

.ds-rainbar__play:hover svg {
  fill: #E4E4E4;
}

/* 右端。「自動更新」「プリロード」「1倍」「最新」を積む */
.ds-rainbar__right {
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
}

.ds-rainbar__right .ds-rainbar__btn {
  width: 100%;
}

.ds-rainbar__auto {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  box-sizing: border-box;
  min-height: 25px;
  padding: 3px 6px;
  border: 2px solid #000000;
  border-radius: 8px;
  background: #CECECE;
  color: #000000;
  font-family: var(--ds-font);
  font-size: 14px;
  font-weight: var(--ds-weight-bold);
  line-height: 1;
  white-space: nowrap;
  cursor: pointer;
}

.ds-rainbar__auto:hover {
  background: #E4E4E4;
}

.ds-rainbar__auto-input {
  flex: 0 0 auto;
  width: 15px;
  height: 15px;
  margin: 0;
  accent-color: #222222;
  cursor: pointer;
}

/* ひまわりだけ。「+5m/+10m」「+10m/+20m」の2つのボタンをまとめて
   1つの箱に入れ、その上に「レーダー」を大きめにまたがせて乗せる。
   ボタン自身の大きさ・間隔は今までどおりで、この箱がその上に
   もう1段足すだけ（雨雲レーダーパネルの見た目には関わらない） */
.ds-rainbar__radarstack {
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  /* 既定の stretch のまま（明示しておく）。下の2ボタンの並び
     （.ds-rainbar__radarstack-row）が幅を決め、その真上に
     「レーダー」を「+10m」の左端から「+20m」の右端まで
     ぴったり幅いっぱいに広げる */
  align-items: stretch;
  gap: 6px;
}

/* ボタン2つぶん（+間の隙間）の上にまたがるので、.ds-rainbar__auto と
   同じくらいの大きさで作ってよい */
.ds-rainbar__radarstack-row {
  display: flex;
}

.ds-rainbar__radar {
  /* 縦（列の中の並び順）には伸び縮みしない。横は親の stretch に
     任せる（flex-basis を明示しないことで、align-items: stretch が
     効く） */
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  box-sizing: border-box;
  min-height: 32px;
  padding: 5px 8px;
  border: 2px solid #000000;
  border-radius: 8px;
  background: #CECECE;
  color: #000000;
  font-family: var(--ds-font);
  font-size: 18px;
  font-weight: var(--ds-weight-bold);
  line-height: 1;
  white-space: nowrap;
  cursor: pointer;
}

.ds-rainbar__radar:hover {
  background: #E4E4E4;
}

.ds-rainbar__radar-input {
  flex: 0 0 auto;
  width: 17px;
  height: 17px;
  margin: 0;
  accent-color: #222222;
  cursor: pointer;
}

/* 「プリロード」は5文字と長く、他のボタンと同じ21pxだと詰まって
   はみ出す。ここだけ少し小さくする */
.ds-rainbar__preload {
  font-size: 17px;
}

/* 3D（アメダスだけ）。ONの間は押されたままに見せる */
.ds-rainbar__tilt {
  font-size: 21px;
}

.ds-rainbar__tilt.is-on {
  background: #003EB3;
  color: #ffffff;
}

.ds-rainbar__tilt.is-on:hover {
  background: #0B50D0;
}

/* 3D の間、下地の切り替えは効かない（単色地図で固定）ので、
   押せないことが見て分かるようにする */
.ds-rainbar__btn:disabled {
  opacity: 0.45;
  cursor: default;
}

.ds-rainbar__btn:disabled:hover {
  background: #CECECE;
}

/* アメダスの凡例は雨雲とまったく同じ作り（.ds-rainlegend）を使う。
   専用のスタイルは持たない（別々に持つと、片方だけ直した時に
   見た目がずれていくため。作るのは js/map.js の
   buildWxLegendColumn 1か所だけ） */

.ds-rainbar__latest {
  font-size: 33px;
  letter-spacing: 0.08em;
  text-indent: 0.08em;   /* letter-spacing の分だけ右に寄るのを戻す */
}

/* 「プリロード」の進み具合。パネル設定画面の「保存しました」
   （.ds-notice）と同じ見た目・出方で、雨雲パネルの中央に出す
   （あちらは画面全体の中央に出す作りなので、これは別に用意する）。
   ぐるぐるが要る間だけ、CSS 側で出し分ける */
.ds-rainbar__notice {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  display: flex;
  align-items: center;
  gap: 18px;
  background: rgba(98, 98, 98, 0.7);
  color: #ffffff;
  padding: 20px 40px;
  border-radius: 60px;
  font-family: var(--ds-font);
  font-size: 30px;
  font-weight: 500;
  white-space: nowrap;
  z-index: 10;
  opacity: 1;
  transition: opacity 0.3s ease;
  pointer-events: none;
}

.ds-rainbar__notice.fade-out {
  opacity: 0;
}

.ds-rainbar__notice.is-entering {
  animation: ds-bcbox-in 0.3s cubic-bezier(0.16, 1, 0.3, 1);
}

/* Material Design の不確定（indeterminate）インジケータ本体は
   js/map.js が組み立てる本物の MDC Web（@material/circular-progress。
   CSS は <head> 側で読み込み済み）に任せている。ここでは、その
   ライブラリの見た目をこのトースト用に合わせるための、大きさと
   色の上書きだけを行う（アニメーションそのものはライブラリの CSS
   が持っているので、ここでは書かない） */
.ds-rainbar__spinner {
  display: none;
  width: 34px;
  height: 34px;
  flex: 0 0 auto;
  --mdc-theme-primary: #ffffff;
}

.ds-rainbar__notice.is-spinning .ds-rainbar__spinner {
  display: inline-flex;
}


/* まだ中身を作っていないツールの仮表示 */
.ds-panel-el--tool.is-placeholder {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 18px;
  border: 4px dashed;          /* 枠と文字の色は js/panel-render.js が入れる */
  border-radius: 16px;
  text-align: center;
  padding: 24px;
}

.ds-panel-tool__name {
  font-size: 72px;
  font-weight: var(--ds-weight-bold);
  line-height: 1.15;
}

.ds-panel-tool__note {
  font-size: 40px;
  letter-spacing: 0.08em;
}

/* -----------------------------------------------------------
   ランキング（js/tools.js）
   気温などを高い順・低い順に並べる特別パネルの中身。
   大きさは 1920x1080 のキャンバス上の px で、行の高さから
   文字の大きさまで js/tools.js が計算して入れる。
   ----------------------------------------------------------- */
.ds-rank {
  position: absolute;
  color: #ffffff;
}

.ds-rank__head {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  color: rgba(255, 255, 255, 0.75);
  letter-spacing: 0.04em;
}

.ds-rank__list {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
}

.ds-rank__msg {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100%;
  color: rgba(255, 255, 255, 0.6);
}

/* 行。後ろの溝いっぱいが1位の長さで、帯がその中を伸び縮みする */
.ds-rank__row {
  position: absolute;
  left: 0;
  right: 0;
  background: rgba(255, 255, 255, 0.16);
  overflow: hidden;
}

.ds-rank__bar {
  position: relative;
  height: 100%;
  display: flex;
  align-items: center;
  min-width: 30%;
}

/* 行いっぱいの高さを持たせて中身を中央に置く。こうしておくと、
   ふりがなが文字の上へ出ても切られない（行からははみ出さない）。
   はみ出す長い地点名は、ここで切って気温に重ならないようにする */
.ds-rank__left {
  flex: 1 1 auto;
  min-width: 0;
  height: 100%;
  display: flex;
  align-items: center;
  gap: 0.3em;
  white-space: nowrap;
  overflow: hidden;
  font-weight: var(--ds-weight-bold);
  line-height: 1;
}

.ds-rank__no {
  font-variant-numeric: tabular-nums;
}

/* 中の一つ一つは縮ませない。縮むと文字が箱からあふれて隣に重なるので、
   はみ出しは行ごと（js/tools.js の fitRows）で文字を小さくして直す */
.ds-rank__left > * {
  flex: 0 0 auto;
}

/* ふりがなは絶対位置で上に浮かせる。行の高さの計算に入れないので、
   順位や県名と同じ高さのまま、地点名の上にだけ乗る */
.ds-rank__namebox {
  position: relative;
}

.ds-rank__kana {
  position: absolute;
  bottom: 100%;
  left: 50%;
  transform: translateX(-50%);
  font-size: 0.3em;
  font-weight: var(--ds-weight-regular);
  line-height: 1.2;
  letter-spacing: 0.02em;
  white-space: nowrap;
  color: rgba(255, 255, 255, 0.92);
}

.ds-rank__name {
  line-height: 1;
}

/* 観測時刻。最高・最低気温ランキングだけが持つ（地点ごとに違うため） */
.ds-rank__time {
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.01em;
}

/* 値。帯の右端に付いていく */
.ds-rank__right {
  flex: 0 0 auto;
  display: flex;
  align-items: stretch;
  height: 100%;
  margin-left: auto;
}

.ds-rank__value {
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: var(--ds-weight-bold);
  line-height: 1;
  white-space: nowrap;
}

.ds-rank__value {
  font-variant-numeric: tabular-nums;
  background: rgba(0, 0, 0, 0.12);
}

/* 出典（右下）。通常パネルのフッター要素と同じ位置・見た目
   （js/panel-render.js の renderText('footer', …) 相当）：
   一覧の下に場所を空けて置く、地に重ねる箱は持たない、右詰め */
/* ---- 噴火警報の一覧（js/tools.js の renderVolcano） ----
   行の高さは固定で、入り切らないぶんはスクロールで見せる。
   放送に出す絵なので**スクロールバーは出さない**（触れる相手が
   いないうえ、絵に棒が写り込む）。中身は動くので、下にまだ
   あることは自動スクロールの動きで伝わる */
.ds-volc__list {
  overflow-y: auto;
  overscroll-behavior: contain;
  scrollbar-width: none;          /* Firefox */
  -ms-overflow-style: none;
}

.ds-volc__list::-webkit-scrollbar {
  display: none;
}

/* 行は absolute で置くので、中身の高さはこの箱が持つ */
.ds-volc__inner {
  position: relative;
}

/* 行。ランキングと同じ骨組みを使うので、行の地や出典はそのまま。
   違うのは行の中身（段の札・火山名・区分・発表時刻）だけ */
.ds-volc__row {
  display: flex;
  align-items: center;
  gap: 28px;
  padding: 0 28px;
  box-sizing: border-box;
}

/* 段の札。レベル運用中は「レベル2」、していない火山は
   「入山危険」のように気象庁の言い方をそのまま入れる */
.ds-volc__level {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: center;
  min-width: 320px;
  padding: 10px 20px;
  box-sizing: border-box;
  border-radius: 8px;
  font-size: 46px;
  font-weight: var(--ds-weight-bold);
  line-height: 1;
  white-space: nowrap;
}

.ds-volc__name {
  flex: 1 0 auto;
  font-size: 60px;
  font-weight: var(--ds-weight-bold);
  line-height: 1;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* 噴火警戒レベルを運用している火山。気象庁のページと同じく下線で示す */
.ds-volc__name.is-leveled {
  text-decoration: underline;
  text-underline-offset: 0.14em;
  text-decoration-thickness: 0.05em;
}

/* 気象庁の言い方（「レベル３（入山規制）」など）。長い行があるので
   ここで縮める。火山名の方を優先して残す */
.ds-volc__kind {
  flex: 0 1 auto;
  overflow: hidden;
  text-overflow: ellipsis;
  font-size: 40px;
  font-weight: var(--ds-weight-bold);
  line-height: 1;
  white-space: nowrap;
  color: rgba(255, 255, 255, 0.85);
}

/* 発表時刻。日付と時刻の2段（js/tools.js の renderVolcano）。
   放送では画面の隅に3割ほどに縮めて出すので、ここも太字にする
   （細い字は映像圧縮で真っ先に潰れる） */
.ds-volc__time {
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 6px;
  min-width: 300px;
  text-align: right;
  font-size: 36px;
  font-weight: var(--ds-weight-bold);
  line-height: 1;
  white-space: nowrap;
  color: rgba(255, 255, 255, 0.72);
}

.ds-rank__attrib {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  display: flex;
  align-items: center;
  justify-content: flex-end;
  color: rgba(255, 255, 255, 0.92);
  font-family: var(--ds-font);
  line-height: 1.15;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* ===== バージョン表記（右下） =====
   パネル編集画面を除く各ページの右下。放送の全画面（.ds-panel-stage,
   z-index:15000）より下の層に置くので、放送中は自動的に隠れる（映らない） */
.ds-version {
  position: fixed;
  right: 12px;
  bottom: 10px;
  z-index: 10;
  color: #000000;
  font: 700 13px/1.2 var(--ds-font, sans-serif);
  letter-spacing: 0.02em;
  cursor: pointer;              /* 押すとリリースノート（js/version.js） */
  user-select: none;
}
.ds-version:hover { text-decoration: underline; }

/* ===== リリースノート（バージョン表記のモーダル中身） ===== */
.ds-relnotes__ver {
  margin: 0 0 8px;
  font-size: 16px;
  font-weight: 700;
  color: rgba(0, 0, 0, 0.87);
}
.ds-relnotes__ver + .ds-relnotes__list + .ds-relnotes__ver {
  margin-top: 20px;   /* 2つ目以降の版は上に間を空ける */
}
.ds-relnotes__date {
  margin-left: 8px;
  font-size: 13px;
  font-weight: 400;
  color: rgba(0, 0, 0, 0.5);
}
.ds-relnotes__list {
  margin: 0 0 14px;
  padding-left: 1.2em;
  line-height: 1.7;
}
.ds-relnotes__list li { margin-bottom: 6px; }
.ds-relnotes__note {
  margin: 0;
  font-size: 13px;
  color: rgba(0, 0, 0, 0.55);
}

/* ===== 気象警報・注意報 時系列情報パネル（ds-wts） =====
   行＝気象要素、列＝時刻（3時間毎）の色分け表。DOM の grid で組む */
.ds-wts {
  --wts-label: 256px;   /* 左端の要素名の列幅（「土砂災害」が入る幅） */
  --wts-hrow: 78px;     /* 上端の時刻見出しの行高 */
  font-family: var(--ds-font);
}
.ds-wts__list {
  display: flex;
  flex-direction: column;
}
.ds-wts__grid {
  flex: 0 0 auto;      /* 高さは js が行数から決めて明示する */
  display: grid;
  min-height: 0;
  /* マスの数値の大きさ。**ここに書くこと**（.ds-wts__cell に書くと
     クラスの指定が継承に勝ってしまい、js が行の高さから計算して
     入れた大きさが効かない。実際それで数値だけ 26px に張り付いていた） */
  font-size: 26px;
}
.ds-wts__corner {
  background: transparent;
}
.ds-wts__th {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-end;
  padding-bottom: 6px;
  color: rgba(255, 255, 255, 0.9);
  line-height: 1.05;
}
/* 時刻見出しの大きさは js/tools.js が行の高さから決めて入れる */
.ds-wts__thday {
  font-size: 22px;
  color: rgba(255, 255, 255, 0.6);
  min-height: 1.1em;
}
.ds-wts__thhour {
  font-size: 30px;
  font-weight: 700;
}
.ds-wts__rlabel {
  display: flex;
  align-items: center;
  justify-content: center;   /* 要素名（雷など）は中央寄せ */
  padding: 0 8px;
  font-size: 34px;
  font-weight: 700;
  color: #ffffff;
  background: rgba(255, 255, 255, 0.10);
  border-radius: 6px;
  white-space: nowrap;
}
.ds-wts__cell {
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 5px;
  font-weight: 700;
  line-height: 1;
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.14);
}
.ds-wts__cell.is-strong {
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.30);
}
/* それ未満・値なしのマスは非表示（枠も塗りも出さない） */
.ds-wts__cell.is-empty {
  background: transparent;
  box-shadow: none;
}
.ds-wts__val {
  padding: 0 2px;
}
.ds-wts__legend {
  flex: 0 0 auto;
  margin-top: auto;   /* 表の下の空きへ寄せる */
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px 26px;
  padding-top: 12px;
  font-size: 24px;
  /* 配信（映像圧縮）で細い線から潰れるので、凡例も太字にする */
  font-weight: var(--ds-weight-bold);
  /* 高さを読み切れるように行の高さを決めておく（js が場所を取り分ける） */
  line-height: 1.2;
  color: rgba(255, 255, 255, 0.85);
}
.ds-wts__lg {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  white-space: nowrap;
}
/* 色見本は文字に合わせて伸び縮みさせる（em） */
.ds-wts__sw {
  display: inline-block;
  width: 1.35em;
  height: 0.9em;
  border-radius: 4px;
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.35);
}

/* 縁取り（太さ・色）は要素ごとの設定なので js/panel-render.js が入れる */
.ds-panel-el--title .ds-panel-el__text {
  letter-spacing: 0.01em;
}

.ds-panel-el--footer .ds-panel-el__text,
.ds-panel-el--telop .ds-panel-el__text {
  font-weight: var(--ds-weight-regular);
}

/* -----------------------------------------------------------
   テロップのひな型
   中の文字サイズは js/panel-render.js が「枠の高さ×割合」で
   入れるので、枠を伸び縮みさせると全体が比例して変わる。
   ----------------------------------------------------------- */
.ds-telop {
  display: flex;
  flex-direction: column;
  overflow: hidden;
  border-style: solid;
  border-color: #ffffff;
}

/* 高さは中身から決まる（余白は js/panel-render.js が文字サイズに
   合わせて入れる）ので、ここでは高さを固定しない */
.ds-telop__head {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 2%;
}

.ds-telop__headline {
  font-family: var(--ds-font);
  font-weight: var(--ds-weight-bold);
  line-height: 1;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* 右肩の地域バッジ。見出し帯の中で白く抜く */
.ds-telop__badge {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  font-family: var(--ds-font);
  font-weight: var(--ds-weight-bold);
  line-height: 1.35;
  white-space: nowrap;
}

.ds-telop__body {
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}

.ds-telop__line {
  font-family: var(--ds-font);
  font-weight: var(--ds-weight-bold);
  line-height: 1.25;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 100%;
}

/* 見出しラベル＋本文の1段帯。
   ラベルは中身の幅ぶんだけ、本文は残り全部を使う */
.ds-telop--label {
  flex-direction: row;
  align-items: stretch;
}

.ds-telop__label {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-family: var(--ds-font);
  font-weight: var(--ds-weight-bold);
  line-height: 1;
  white-space: nowrap;
}

.ds-telop__main {
  flex: 1 1 auto;
  min-width: 0;
  display: inline-flex;
  align-items: center;
  font-family: var(--ds-font);
  font-weight: var(--ds-weight-bold);
  line-height: 1;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* 文字だけ（枠・帯なし）。位置は js/panel.js のドラッグで動かせるので、
   はみ出しても見切れないようにしておく */
.ds-telop--plain {
  overflow: visible;
}

.ds-telop__plain {
  display: flex;
  align-items: center;
  width: 100%;
  font-family: var(--ds-font);
  font-weight: var(--ds-weight-bold);
  line-height: 1.15;
  white-space: pre-wrap;
  word-break: break-word;
  cursor: move;
}

/* 単色の帯1本。見出し・バッジは持たず本文だけを中央に置く */
.ds-telop__ribbon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  font-family: var(--ds-font);
  font-weight: var(--ds-weight-bold);
  line-height: 1.2;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* 左の帯線＋本文。コメントや引用向け */
.ds-telop--quote {
  flex-direction: row;
  align-items: stretch;
}

.ds-telop__stripe {
  flex: 0 0 auto;
}

.ds-telop__qbody {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  flex-direction: column;
  justify-content: center;
}

/* トグルOFFの要素は描画そのものをしない（js/panel-render.js）ので、
   ここに半透明などの見た目は持たせない */

/* -----------------------------------------------------------
   パネル編集（panel.php / js/panel.js）
   選択枠とハンドルはキャンバスの外側（縮尺のかからない層）に
   置く。中に入れると scale で一緒に縮んでしまい、小さい表示で
   ハンドルが潰れて掴めなくなる。
   ----------------------------------------------------------- */
/* 使える領域いっぱいに広げるだけ。16:9 に収めるのは
   js/panel-render.js が中で行う（影はキャンバス側に付く） */
.pnl-stage {
  position: relative;
  width: 100%;
  height: 100%;
}

.pnl-stage .ds-panel-view {
  position: absolute;
  inset: 0;
}

/* 自動レイアウトなので、プレビューは見るだけ（掴む手がかりは出さない） */

/* -----------------------------------------------------------
   要素ごとの設定（サイドバーから開く）
   ----------------------------------------------------------- */
.pnl-detail {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  background: #ffffff;
  z-index: 2;
}

.pnl-detail[hidden] { display: none; }

.pnl-detail__head {
  flex: 0 0 auto;
  height: var(--ds-header-height);
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 0 16px;
  border-bottom: 1px solid var(--pnl-line);
}

.pnl-detail__back {
  appearance: none;
  -webkit-appearance: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  padding: 0;
  border: none;
  background: transparent;
  cursor: pointer;
}

.pnl-detail__back svg {
  width: 26px;
  height: 26px;
  fill: #6b6b6b;
}

.pnl-detail__title {
  margin: 0;
  font-size: 22px;
  font-weight: var(--ds-weight-bold);
}

.pnl-detail__body {
  flex: 1 1 auto;
  overflow-y: auto;
  padding: 20px;
}

.pnl-field {
  margin-bottom: 20px;
}

.pnl-field__label {
  display: block;
  margin-bottom: 8px;
  font-size: 14px;
  font-weight: var(--ds-weight-bold);
  color: rgba(0, 0, 0, 0.6);
}

.pnl-field__row {
  display: flex;
  align-items: center;
  gap: 10px;
}

.pnl-input,
.pnl-textarea,
.pnl-select {
  width: 100%;
  padding: 9px 11px;
  font-family: var(--ds-font);
  font-size: 16px;
  font-weight: var(--ds-weight-regular);
  color: var(--ds-text);
  border: 1px solid #cccccc;
  border-radius: 0;
  background: #ffffff;
}

.pnl-select {
  appearance: auto;
}

.pnl-textarea {
  min-height: 86px;
  resize: vertical;
  line-height: 1.5;
}

.pnl-input:focus,
.pnl-textarea:focus,
.pnl-select:focus {
  outline: none;
  border-color: var(--pnl-blue);
}

.pnl-input--num { width: 96px; }

.pnl-color {
  width: 46px;
  height: 38px;
  padding: 2px;
  border: 1px solid #cccccc;
  background: #ffffff;
  cursor: pointer;
}

/* 左寄せ / 中央 / 右寄せ の切り替え */
.pnl-seg {
  display: flex;
}

.pnl-seg__btn {
  appearance: none;
  -webkit-appearance: none;
  flex: 1 1 auto;
  padding: 9px 0;
  border: 1px solid #cccccc;
  background: #ffffff;
  font-family: var(--ds-font);
  font-size: 15px;
  font-weight: var(--ds-weight-bold);
  color: #555555;
  cursor: pointer;
}

.pnl-seg__btn + .pnl-seg__btn { border-left: none; }

.pnl-seg__btn.is-on {
  background: var(--pnl-blue);
  border-color: var(--pnl-blue);
  color: #ffffff;
}

/* 画像のプレビュー（背景画像・パネル内画像の設定で共用） */
.pnl-bg-preview {
  position: relative;
  width: 100%;
  aspect-ratio: 16 / 9;
  display: flex;
  align-items: center;
  justify-content: center;
  background-color: #f2f2f2;
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
  border: 1px solid #dddddd;
}

.pnl-bg-preview__empty {
  font-size: 14px;
  color: #999999;
}

/* ひな型の選択（背景・テロップ） */
.pnl-tpl {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

.pnl-tpl__btn {
  appearance: none;
  -webkit-appearance: none;
  padding: 8px 12px;
  border: 1px solid #cccccc;
  background: #ffffff;
  font-family: var(--ds-font);
  font-size: 14px;
  font-weight: var(--ds-weight-bold);
  color: #555555;
  cursor: pointer;
}

.pnl-tpl__btn.is-on {
  background: var(--pnl-blue);
  border-color: var(--pnl-blue);
  color: #ffffff;
}

/* 背景色の見本。押すと背景色と模様の色がまとめて入る */
.pnl-swatches {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.pnl-swatch {
  width: 30px;
  height: 30px;
  padding: 0;
  border: 1px solid rgba(0, 0, 0, 0.25);
  border-radius: 50%;
  cursor: pointer;
}

.pnl-swatch.is-on {
  box-shadow: 0 0 0 2px #ffffff inset, 0 0 0 3px var(--pnl-blue);
  border-color: var(--pnl-blue);
}

/* 特別パネルの印（ヘッダーのパネル名の後ろ）とツール名 */
.pnl-badge-tool {
  display: inline-block;
  margin-left: 10px;
  padding: 3px 8px;
  border-radius: 3px;
  background: var(--pnl-blue);
  color: #ffffff;
  font-size: 12px;
  font-weight: var(--ds-weight-bold);
  letter-spacing: 0.04em;
  vertical-align: middle;
}

.pnl-tool-name {
  margin: 0;
  font-size: 18px;
  font-weight: var(--ds-weight-bold);
}

/* 入力欄の横に添える補足（「高さは自動」など） */
/* ---- アメダスの地点の吹き出し ----------------------------
   プロットを押すと出る。上が地点名（ルビ付き）、下が値。
   右下の三角が地点を指す。

   寸法は全部 em（＝この箱の font-size 基準）で書いてある。
   設定でサイズを変えられるよう、js が font-size だけを差し替えれば
   箱ごと拡大・縮小できるようにするため。基準は 100px。 */
/* 塗り分けの粗さを選ぶプルダウン（気象警報・注意報パネル）。
   パネルの右下。放送の絵に残るので、時計や凡例と同じ地の色にする */
.ds-wxscope {
  position: absolute;
  right: 83px;            /* 出典（右端から83px）と縦を揃える */
  bottom: 96px;
  z-index: 5;
  /* 「自動更新」を足す層（警報・注意報）では、プルダウンの上へ
     積む。下端を基準にしているので、増えた分は上へ伸びる＝
     プルダウンの位置は動かない。
     チェックそのものの見た目は再生バーの中と同じものを使い回す
     （.ds-rainbar__auto）ので、ここでは置き場所だけ決める */
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 10px;
}

.ds-wxscope__select {
  appearance: none;
  -webkit-appearance: none;
  background: var(--ds-wx-panel);
  color: #ffffff;
  border: 0;
  border-radius: 6px;
  font-family: var(--ds-font);
  font-size: 30px;
  font-weight: var(--ds-weight-bold);
  line-height: 1;
  /* 右側は三角の分だけ広く取る */
  padding: 14px 46px 14px 20px;
  cursor: pointer;

  /* 下向きの三角。画像を持たずに背景で描く */
  background-image:
    linear-gradient(45deg, transparent 50%, #ffffff 50%),
    linear-gradient(135deg, #ffffff 50%, transparent 50%);
  background-position:
    calc(100% - 26px) calc(50% + 2px),
    calc(100% - 18px) calc(50% + 2px);
  background-size: 8px 8px, 8px 8px;
  background-repeat: no-repeat;
}

/* ---- 台風でなくなった知らせ（js/map-canvas.js の syncTyphoonEnd） ----
   画面のまん中に大きく出す。地図の上に直に乗るので、地の色に
   関わらず読めるよう白抜き＋黒縁にしてある。
   縁は paint-order で文字の外側だけに出す（内側に食い込むと
   細い画がつぶれる） */
.ds-typhend {
  position: absolute;
  left: 0;
  right: 0;
  top: 50%;
  transform: translateY(-50%);
  z-index: 6;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 40px;
  padding: 0 80px;
  box-sizing: border-box;
  pointer-events: none;
  font-family: var(--ds-font);
  font-size: 78px;
  font-weight: var(--ds-weight-bold);
  line-height: 1.3;
  text-align: center;
  color: #ffffff;
  -webkit-text-stroke: 10px #000000;
  paint-order: stroke fill;
}

/* ---- 台風の詳細（js/map-canvas.js の updateTyphoonInfo） ----
   左の塊のいちばん下、見出しの下に積む。時計・凡例と同じ
   半透明の黒地に白抜き */
.ds-typhinfo {
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 18px 22px;
  border-radius: 6px;
  background: var(--ds-wx-panel);
  color: #ffffff;
  font-family: var(--ds-font);
  line-height: 1.1;
}

/* 放送では画面の隅に3割ほどに縮めて出すので、ここは大きめに。
   下に余っていた 270px ぶんを値の文字へ回してある
   （置き場所の取り分けは js/map-canvas.js の TYPHOON_INFO_MAX_H） */
.ds-typhinfo__head {
  font-size: 42px;
  font-weight: var(--ds-weight-bold);
  white-space: nowrap;
  /* 見出しと数字の間だけ少し空ける */
  margin-bottom: 4px;
}

/* 添え書き。見出し（台風第◯号）の真下に、一段小さく添える。
   「24時間以内に台風になる見込み」のように、項目名と値の対では
   書けないもの用 */
.ds-typhinfo__note {
  font-size: 32px;
  font-weight: var(--ds-weight-bold);
  white-space: nowrap;
  color: rgba(255, 255, 255, 0.78);
  margin-top: -2px;
  margin-bottom: 6px;
}

.ds-typhinfo__row {
  display: flex;
  align-items: baseline;
  gap: 14px;
  font-size: 38px;
  font-weight: var(--ds-weight-bold);
  white-space: nowrap;
}

/* 項目名は少し弱く、幅をそろえて数字の頭を縦に並べる */
.ds-typhinfo__key {
  flex: 0 0 auto;
  /* 項目名は数字より一段小さく、弱く。読ませたいのは値の方。
     いちばん長い項目名（大きさ・勢力）に合わせた幅を全部の行で
     そろえて、値の頭を縦に並べる */
  font-size: 30px;
  width: 6.4em;
  color: rgba(255, 255, 255, 0.72);
}

/* 削らない。長い行は箱ごと広がる（min-width だけ決めてある） */
.ds-typhinfo__val {
  flex: 0 0 auto;
}

/* ---- 降灰予報の諸元（js/map-canvas.js の syncAshfallInfo） ----
   台風の諸元（.ds-typhinfo）と同じ箱を使う。違うのは項目名の幅
   だけで、いちばん長いのが「予想の時間帯」なので、そこに合わせる
   （台風は「大きさ・勢力」に合わせた 6.4em） */
.ds-ashinfo .ds-typhinfo__key {
  width: 7.2em;
}

/* ---- 潮位（js/tools.js の renderTide） --------------------
   ランキングと同じ骨組み（白い文字・右下に出典）を使い、中は
   **左に塊・右にグラフ**。左の塊はマップパネル（雨雲・キキクル・
   台風）の時計や凡例と同じ半透明の黒地にそろえてある */
.ds-tide__col {
  position: absolute;
  left: 0;
  top: 0;
  display: flex;
  flex-direction: column;
  gap: 16px;
  z-index: 1;             /* グラフ（SVG）より前 */
}

/* 今の潮位。マップパネルの時計（.ds-rainclock）と同じ立ち位置で、
   放送で真っ先に読ませたい数字を大きく出す */
.ds-tide__now {
  box-sizing: border-box;
  padding: 16px 20px 18px;
  border-radius: 6px;
  background: var(--ds-wx-panel);
  font-family: var(--ds-font);
  line-height: 1;
}

.ds-tide__nowhead {
  font-size: 34px;
  font-weight: var(--ds-weight-bold);
  color: rgba(255, 255, 255, 0.72);
}

.ds-tide__nowvalue {
  display: flex;
  align-items: baseline;
  gap: 8px;
  margin-top: 12px;
  color: #ffffff;
  font-weight: var(--ds-weight-bold);
}

.ds-tide__nowvalue.is-none {
  font-size: 40px;
  color: rgba(255, 255, 255, 0.6);
}

.ds-tide__nownum {
  font-size: 108px;
  /* 数字の高さぶんだけ確保する（符号や桁数で行が動かないように） */
  line-height: 0.9;
}

.ds-tide__nowunit {
  font-size: 40px;
}

/* 偏差（天文潮位との差）。高潮で本当に効くのはここなので、
   単位より大きく、しかし潮位そのものよりは小さく */
.ds-tide__nowfoot {
  margin-top: 14px;
  font-size: 38px;
  font-weight: var(--ds-weight-bold);
  color: #ffffff;
  white-space: nowrap;
}

.ds-tide__nowtime {
  margin-top: 10px;
  font-size: 32px;
  font-weight: var(--ds-weight-bold);
  color: rgba(255, 255, 255, 0.66);
  letter-spacing: 0.04em;
}

/* 凡例。マップパネルの区分の凡例（.ds-wxclass）と同じ、
   色見本を縦に積む形 */
.ds-tide__legend {
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 14px 20px;
  border-radius: 6px;
  background: var(--ds-wx-panel);
  font-family: var(--ds-font);
  font-weight: var(--ds-weight-bold);
  line-height: 1;
  color: #ffffff;
}

.ds-tide__legendrow {
  display: flex;
  align-items: center;
  gap: 12px;
  white-space: nowrap;
}

/* 線の見本。実線・破線・点線は js が縞で描き分ける */
.ds-tide__swatch {
  flex: 0 0 auto;
  width: 54px;
  height: 7px;
  border-radius: 1px;
}

.ds-tide__legendtext {
  flex: 1 1 auto;
}

/* 基準の値。名前の右端にそろえる */
.ds-tide__legendval {
  flex: 0 0 auto;
  margin-left: 10px;
  color: rgba(255, 255, 255, 0.7);
}

/* グラフは箱いっぱいに敷く（中の座標は js が箱の px で組む） */
.ds-tide__svg {
  position: absolute;
  left: 0;
  top: 0;
  pointer-events: none;   /* 触るのは下の当たり判定（__hit）に任せる */
}

/* 触った所を拾うための透明な板。**毎回作り直す**ので、
   描き直しのたびに聞き手が積み上がらない */
.ds-tide__hit {
  position: absolute;
  inset: 0;
  z-index: 3;
}

/* 触った所の潮位。DSのデータポップアップ（.ds-tip）と同じ考え方で、
   角のひとつを尖らせて点を指す。地の色は左の塊（現在の潮位・凡例）と
   同じ半透明の黒 */
.ds-tide__tip {
  position: absolute;
  z-index: 4;
  box-sizing: border-box;
  padding: 12px 18px 14px;
  border-radius: 10px;
  border-bottom-left-radius: 0;
  background: var(--ds-wx-panel);
  font-family: var(--ds-font);
  font-weight: var(--ds-weight-bold);
  line-height: 1.1;
  white-space: nowrap;
  pointer-events: none;   /* 吹き出し自身が触るのを奪わないように */
}

/* 下へ回した時は上の角、左へ回した時は右の角を尖らせる */
/* 画像用の調整で固定した吹き出し。ダブルクリックで外せるよう、これだけは押せる
   （上の pointer-events: none を打ち消す。js/tools.js の renderTide） */
.ds-tide__tip.is-removable {
  pointer-events: auto;
  z-index: 5;
  cursor: pointer;
}

.ds-tide__tip.is-below {
  border-bottom-left-radius: 10px;
  border-top-left-radius: 0;
}

.ds-tide__tip.is-flip {
  border-bottom-left-radius: 10px;
  border-bottom-right-radius: 0;
}

.ds-tide__tip.is-flip.is-below {
  border-bottom-right-radius: 10px;
  border-top-right-radius: 0;
}

.ds-tide__tiptime {
  font-size: 32px;
  color: rgba(255, 255, 255, 0.68);
}

.ds-tide__tipval {
  margin-top: 6px;
  font-size: 54px;
  color: #ffffff;
}

/* ---- 市区町村の札（js/map-region.js） --------------------
   地図を押した所の市区町村を光らせて、その左上に名前を出す。
   マップパネル全部（雨雲・ひまわり・天気図・推計気象分布・アメダス）
   で同じ見た目。光らせる方は canvas / MapLibre がそれぞれ描く。

   アメダスの吹き出しと同じで、寸法は全部 em（＝札の font-size 基準）。
   js は font-size だけ差し替えれば、札ごと拡大・縮小される */
.ds-region-layer {
  position: absolute;
  inset: 0;
  z-index: 6;             /* 地図（canvas）より前、通知（10）より後ろ */
  pointer-events: none;   /* 地図の操作を邪魔しない */
  filter: drop-shadow(0 4px 10px rgba(0, 0, 0, .45));
}

/* left/top は光らせた区域の左上（＋手で動かしたぶん）。
   区域より少し外に出したいので、そこから上へ持ち上げる */
.ds-region {
  position: absolute;
  transform: translateY(-100%);
  font-size: 46px;                  /* js がここだけ差し替える */
  font-family: var(--ds-font);
  line-height: 1;
  white-space: nowrap;

  /* 上が地名の行、下が警報の名前の行（気象警報パネルだけ） */
  display: flex;
  flex-direction: column;
  gap: 0.22em;
  /* 薄暗い地に白文字。地図の上に置くので、下が写真でも単色でも
     読めるだけの濃さにする。

     **透かさないこと。** 半透明にすると、札の下にもぐらせた
     引き出し線の三角が地を透けて見え、札の中に濃い三角が浮く。
     見た目の濃さは、半透明で海の上に置いた時とほぼ同じにしてある */
  background: #242424;
  color: #ffffff;
  /* 上下の余白は同じでよい。ルビはこの余白の**中に**収まるのではなく、
     ルビ自身の行が箱の高さを押し広げるので、上を広めに取ると
     ルビのぶんと足し算になって上だけ間延びする */
  padding: 0.30em 0.62em 0.30em;

  pointer-events: auto;
  cursor: default;
}

/* 札から押した地点へ引く線と、その先の丸。
   札より**前**（DOM で先）に置いてあるので、付け根が札の下にもぐって
   札から生えて見える。色は札の地と同じ。影は層にまとめて掛かるので、
   札＋線＋丸がひとつながりの形として影を持つ */
.ds-region__leaders {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  overflow: visible;
  pointer-events: none;
}

/* 札と同じ色。違う色や半透明にすると、札にもぐらせた付け根の所で
   濃さが変わって、継ぎ目が見えてしまう */
.ds-region__leader {
  fill: #242424;
}

/* 押した地点そのもの。線の先が細くなって見失わないよう、
   丸を打って白でふちどる */
.ds-region__dot {
  fill: #242424;
  stroke: #ffffff;
  stroke-width: 3;
}

/* 地名の行。都道府県と市区町村を並べる */
.ds-region__head {
  display: flex;
  align-items: baseline;
  gap: 0.30em;
}

/* 地名の下に並べる、その区域に出ている警報・注意報。**縦に積む。** */
.ds-region__notes {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.08em;
}

/* 1つ分。**地に階級の色を敷いて、その上に文字**（色は js が入れる）。

   文字色だけで階級を分けるのは無理だった。札の地が薄暗いので、
   危険警報の紫は沈み、特別警報の黒はまったく見えない。地に色を
   敷けば、黒でも紫でも黄でも同じように読める（気象庁の
   警報・注意報のページと同じ見せ方）。

   内側の細い白線は、特別警報（ほぼ黒）が札の地に溶けないため。
   内側に引くので大きさは変わらない */
.ds-region__note {
  font-size: 0.62em;
  font-weight: var(--ds-weight-bold);
  line-height: 1;
  padding: 0.20em 0.44em 0.24em;
  border-radius: 0.14em;
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .45);
}

/* 「ほか」だけは地を敷かない（階級を持たないため） */
.ds-region__note.is-plain {
  background: none;
  color: #ffffff;
  box-shadow: none;
  padding-left: 0.1em;
}

/* 添え書き。キキクルの札の「※区域に少しでもかかる1kmメッシュの数」
   （js/map-canvas.js の riskNotes）。数字より控えめに */
.ds-region__note.is-foot {
  margin-top: 0.12em;
  font-size: 0.42em;
  font-weight: var(--ds-weight-bold);
  color: rgba(255, 255, 255, 0.8);
}

/* 都道府県名。市区町村名より一段小さくして、主役を市区町村にする */
.ds-region__pref {
  font-size: 0.62em;
  font-weight: var(--ds-weight-bold);
}

.ds-region__city {
  font-size: 1em;
  font-weight: var(--ds-weight-bold);
}

/* ふりがな。ruby の既定は小さすぎるので指定する */
.ds-region__city rt {
  font-size: 0.40em;
  font-weight: var(--ds-weight-bold);
  line-height: 1.9;
}

.ds-amecall-layer {
  position: absolute;
  inset: 0;
  z-index: 6;             /* 地図（canvas）より前、通知（10）より後ろ */
  pointer-events: none;   /* 地図の操作を邪魔しない */
  /* 影はここ（層）にまとめて掛ける。箱と三角に別々に掛けると、
     箱の影が三角の上に落ちて、継ぎ目が線になって見える。
     層にまとめれば「箱＋三角をひとつながりの形」として影が付く */
  filter: drop-shadow(0 4px 10px rgba(0, 0, 0, .45));
}

/* left/top は地点そのものの位置（＋手で動かしたぶん）。
   三角は箱の右下に出すので、**その三角の先**が地点に来るようにずらす。

     縦 … 箱の高さぶん持ち上げる（-100%）だけでは足りない。
           それだと「箱の下端」が地点に来るので、そこからさらに
           下へ出ている三角のぶん（0.22em）だけ地点より下に
           はみ出す。三角の高さも足して持ち上げること。
     横 … 箱の右端から三角の中心までのぶん（0.42em）だけ右へ戻す。
           ＝ .ds-amecall__tail の right(0.24em) + border-left(0.18em)

   どちらの数字も .ds-amecall__tail と対。片方だけ変えると
   先が地点からずれる */
.ds-amecall {
  position: absolute;
  font-size: 100px;                 /* js がここだけ差し替える */
  transform: translate(calc(-100% + 0.42em), calc(-100% - 0.22em));
  font-family: var(--ds-font);
  line-height: 1;
  white-space: nowrap;
}

.ds-amecall__head {
  background: #333333;
  color: #ffffff;
  font-size: 0.46em;
  font-weight: var(--ds-weight-bold);
  /* ルビが上に付くので、上を広めに取って全体を下げる */
  padding: 0.62em 0.57em 0.30em;
  text-align: center;
}

/* ふりがな。ruby の既定は小さすぎるので指定する。
   line-height で地点名との間を空ける */
.ds-amecall__head rt {
  font-size: 0.43em;
  font-weight: var(--ds-weight-bold);
  line-height: 1.9;
}

.ds-amecall__body {
  display: flex;
  align-items: flex-end;
  justify-content: center;
  gap: 0.04em;
  background: #ffffff;
  color: #E7382A;
  padding: 0.10em 0.26em 0.16em;
}

.ds-amecall__num {
  font-size: 0.96em;
  /* 放送で遠くから読ませる数字なので、見出しより更に太く。
     書体が持っている中でいちばん太い字面を使う */
  font-weight: 800;
  font-variant-numeric: tabular-nums;
}

.ds-amecall__unit {
  font-size: 0.44em;
  font-weight: 800;
  padding-bottom: 0.14em;
}

/* 箱の下の三角。右下に出して、その先が地点を指す。
   位置を変える時は .ds-amecall の transform の 0.42em も合わせること
   （右端から三角の中心までの距離＝ right + border-left）

   **三角は箱に少し食い込ませる**（top を 100% ちょうどにしない）。
   ぴったり突き合わせると、境目に細い線が出る。箱の下端と三角の
   上端は別々の要素として別々になめらかに描かれるので、境目が
   画素の途中に来ると、two 50% の白が重なっても 100% にならず、
   その行だけ透けて影が見えてしまう（実測で境目が .05px の
   端数に来ていた）。少し重ねれば重なった行は必ず白で埋まる。
   食い込ませたぶん border-top を足して、三角の先の位置は変えない */
.ds-amecall__tail {
  position: absolute;
  right: 0.24em;
  top: calc(100% - 0.02em);
  width: 0;
  height: 0;
  border-left: 0.18em solid transparent;
  border-right: 0.18em solid transparent;
  border-top: 0.24em solid #ffffff;
}

/* 箱そのものは常につまめるようにしておく（Shift+ドラッグで動かす）。
   層は触れないままなので、箱の外は今までどおり地図の操作が通る。
   「Shift を押している間だけ触れる」という作りにすると、
   キーの押下を拾えなかった時に動かせなくなるので、そうしない */
.ds-amecall { pointer-events: auto; cursor: default; }

/* 箱を動かした時に、地点まで伸びる三角。
   動かしていない時に箱の下に出る小さい三角が、そのまま地点まで
   伸びた形。箱より後ろに置くので、付け根が箱の下にもぐって
   箱から生えているように見える */
.ds-amecall__leaders {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  overflow: visible;
  pointer-events: none;
}

.ds-amecall__leader {
  /* 箱の下側（値の欄）と同じ白。地続きに見せる。
     影は層にまとめて掛けているので、ここには付けない */
  fill: #ffffff;
}

/* アメダスの色分けのしきい値。1段が1行。
   上（高い方）から並び、いちばん下は「それ未満すべて」 */
.pnl-levels {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.pnl-level {
  display: flex;
  align-items: center;
  gap: 8px;
}

.pnl-level__color {
  flex: 0 0 auto;
  width: 44px;
  height: 30px;
  padding: 0;
  border: 1px solid #cfcfcf;
  border-radius: 4px;
  background: none;
  cursor: pointer;
}

.pnl-level__color:disabled {
  opacity: .35;
  cursor: default;
}

.pnl-level__min {
  width: 90px;
}

.pnl-level__tail {
  font-size: 13px;
  color: #666666;
}

/* 「出さない」。降水量0を描かない、のような段に使う */
.pnl-level__offlabel {
  display: flex;
  align-items: center;
  gap: 4px;
  margin-left: auto;
  font-size: 13px;
  white-space: nowrap;
}

.pnl-level__del {
  flex: 0 0 auto;
}

.pnl-levels__actions {
  display: flex;
  gap: 8px;
  margin-top: 8px;
}

.pnl-note {
  font-size: 13px;
  color: #888888;
  line-height: 1.3;
}

/* -----------------------------------------------------------
   グラフ（js/panel-render.js が自動レイアウトで組む）
   縦棒 / 横棒 / 折れ線 / エリア / 円 / ドーナツ
   ----------------------------------------------------------- */
.ds-graph {
  display: flex;
  flex-direction: column;
}

/* 折れ線・円は SVG で描く。中の文字はパネル共通の書体に揃える */
.ds-graph > svg {
  display: block;
}

.ds-graph__svgtext {
  font-family: var(--ds-font);
  font-weight: var(--ds-weight-bold);
}

/* 棒は下端そろえ。本数で列幅を等分する */
.ds-graph__plot {
  flex: 0 0 auto;
  display: flex;
  align-items: flex-end;
  justify-content: space-around;
  gap: 1.5%;
}

.ds-graph__col {
  flex: 1 1 0;
  min-width: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
}

.ds-graph__value {
  display: flex;
  align-items: flex-end;
  justify-content: center;
  font-family: var(--ds-font);
  font-weight: var(--ds-weight-bold);
  line-height: 1;
  white-space: nowrap;
}

/* 棒の伸びしろ。中で下から伸ばす */
.ds-graph__barbox {
  width: 100%;
  display: flex;
  align-items: flex-end;
  justify-content: center;
}

.ds-graph__bar {
  width: 72%;
  border-radius: 4px 4px 0 0;
}

.ds-graph__label {
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--ds-font);
  font-weight: var(--ds-weight-bold);
  line-height: 1.2;
  text-align: center;
  white-space: nowrap;
}

/* データポップアップ。キャンバス（1920x1080）の中に置くので、
   パネルを縮めても文字との釣り合いが変わらない。
   寸法を em で書いてあるのは、親の font-size（＝設定の文字サイズ）
   を変えるだけで角丸や余白ごと拡縮させるため。
   色は js/panel-render.js が設定値から直接入れる */
.ds-tip {
  position: absolute;
  z-index: 5;
  display: flex;
  flex-direction: column;
  gap: 0.12em;
  padding: 0.5em 0.8em;
  border-radius: 0.35em;
  font-family: var(--ds-font);
  font-weight: var(--ds-weight-bold);
  line-height: 1.25;
  white-space: nowrap;
  pointer-events: none;   /* 吹き出し自身がホバーを奪わないように */
}

/* 帯：項目名と値を横に並べた1行 */
.ds-tip--bar {
  flex-direction: row;
  align-items: baseline;
  gap: 0.7em;
  border-radius: 0;
}

/* 吹き出し：左下の角を丸めず、そのままとがった点まで伸ばして
   指した場所を指す（角丸の1辺だけ「チョキ」に切れているイメージ）。
   色は js/panel-render.js が背景色と同じ色を tail にも入れる */
.ds-tip--pin {
  border-radius: 0.45em;
  border-bottom-left-radius: 0;
}

.ds-tip__tail {
  position: absolute;
  left: 0;
  top: 100%;
  width: 0.8em;
  height: 0.85em;
  margin-top: -0.02em;   /* 角のつなぎ目に隙間が出ないよう少し重ねる */
  clip-path: polygon(0 0, 100% 0, 0 100%);
}

/* 左右反転。円の左半分をホバーした時に使う（js/panel-render.js が
   ds-tip--flip を付け外しする）。とがらせる角を右下に持ち替える */
.ds-tip--pin.ds-tip--flip {
  border-bottom-left-radius: 0.45em;
  border-bottom-right-radius: 0;
}

.ds-tip--pin.ds-tip--flip .ds-tip__tail {
  left: auto;
  right: 0;
  clip-path: polygon(100% 0, 0 0, 100% 100%);
}

.ds-tip__name { font-size: 0.86em; }
.ds-tip__val  { font-size: 1.15em; }

.ds-tip--bar .ds-tip__name { font-size: 0.9em; }

/* 数値は編集画面でつまんで動かせる */
.pnl-preview .ds-graph__movable {
  cursor: move;
}

/* 欄からはみ出す文字を横だけ縮めるための入れ物（長体）。
   panel-render.js の squeezeInto が transform を入れる。
   幅は縮める前のままなので、親側で伸び縮みさせないこと */
.ds-graph__fit {
  display: inline-block;
  flex: 0 0 auto;
  white-space: nowrap;
}

/* 横棒。1行 ＝ 項目名 ／ 棒 ／ 数値。
   欄の幅は panel-render.js が px で入れるので、ここでは伸縮させない */
.ds-graph__rows {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  justify-content: center;
}

.ds-graph__row {
  display: flex;
  align-items: center;
}

.ds-graph__rowlabel {
  flex: 0 0 auto;
  text-align: right;
  font-family: var(--ds-font);
  font-weight: var(--ds-weight-bold);
  line-height: 1.2;
  white-space: nowrap;
}

.ds-graph__track {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
}

.ds-graph__hbar {
  border-radius: 0 4px 4px 0;
}

.ds-graph__rowvalue {
  flex: 0 0 auto;
  font-family: var(--ds-font);
  font-weight: var(--ds-weight-bold);
  line-height: 1;
  white-space: nowrap;
}

/* グラフのデータ入力表（サイドバー内） */
.pnl-data {
  width: 100%;
  border-collapse: collapse;
}

.pnl-data th {
  text-align: left;
  padding: 0 6px 6px 0;
  font-size: 13px;
  font-weight: var(--ds-weight-bold);
  color: rgba(0, 0, 0, 0.6);
}

.pnl-data td {
  padding: 0 6px 8px 0;
  vertical-align: middle;
}

.pnl-data td:last-child,
.pnl-data th:last-child { padding-right: 0; width: 30px; }

.pnl-data .pnl-input { padding: 7px 9px; font-size: 15px; }
.pnl-data .pnl-color { width: 40px; height: 34px; }

.pnl-data__del {
  appearance: none;
  -webkit-appearance: none;
  width: 28px;
  height: 28px;
  padding: 0;
  border: none;
  background: transparent;
  color: #999999;
  font-size: 20px;
  line-height: 1;
  cursor: pointer;
}

.pnl-data__del:hover { color: var(--ds-danger); }

/* -----------------------------------------------------------
   画像書き出し（panel-export.php）
   ----------------------------------------------------------- */
.exp-page { padding-bottom: 60px; }

.exp-section {
  margin: 24px 40px 0;
  padding: 20px 24px;
  background: var(--ds-bg);
  box-shadow: 0 1px 6px rgba(0, 0, 0, 0.12);
}

.exp-heading {
  margin: 0 0 14px;
  font-size: 20px;
  font-weight: var(--ds-weight-bold);
}

.exp-controls {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 16px 28px;
}

.exp-field {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 15px;
}

.exp-field > span { font-weight: var(--ds-weight-bold); }

.exp-field select,
.exp-item__mode {
  font: inherit;
  padding: 6px 8px;
  border: 1px solid #bbb;
  background: #fff;
}

.exp-radio {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  cursor: pointer;
}

.exp-status {
  margin: 14px 0 0;
  font-size: 14px;
  color: #555;
}

.exp-status.is-error { color: var(--ds-danger); }

.exp-grid { padding: 20px 0 0; }

.exp-card-name {
  display: block;
  margin-top: 6px;
  font-size: 14px;
  color: var(--ds-text);
  text-align: center;
}

.exp-list-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 8px 20px;
}

.exp-list-head .exp-heading { margin-bottom: 8px; }

.exp-live {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 14px;
  cursor: pointer;
}

.exp-live-status { font-size: 13px; color: #777; }

.exp-note { margin: 0 0 16px; font-size: 13px; color: #666; }

.exp-empty { color: #777; }

.exp-item {
  display: flex;
  gap: 20px;
  padding: 16px 0;
  border-top: 1px solid #e3e3e3;
}

.exp-item.is-new { background: #fff7e0; }

.exp-item__thumb {
  flex: 0 0 256px;
  aspect-ratio: 16 / 9;
  background: #eee;
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);
}

.exp-item__thumb img { width: 100%; height: 100%; object-fit: cover; }

.exp-item__info {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.exp-item__head {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
}

.exp-item__no {
  font-size: 18px;
  font-weight: var(--ds-weight-bold);
  font-variant-numeric: tabular-nums;
}

.exp-item__name { font-size: 15px; }

.exp-badge {
  padding: 2px 8px;
  font-size: 12px;
  background: #666;
  color: #fff;
}

.exp-badge--live { background: #d40000; }

.exp-item__url { display: flex; gap: 8px; }

.exp-item__url input {
  flex: 1 1 auto;
  min-width: 0;
  font: inherit;
  font-size: 14px;
  padding: 6px 8px;
  border: 1px solid #bbb;
  background: #fafafa;
}

.exp-item__meta { font-size: 13px; color: #777; }

.exp-item__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
}

/* 撮影用の置き場。見えない所に実寸で描く（縮めると地図の絵が粗くなる） */
.exp-stage {
  position: fixed;
  left: -40000px;
  top: 0;
  width: 1920px;
  height: 1080px;
  overflow: hidden;
  pointer-events: none;
}

.exp-target {
  margin: 20px 40px 0;
  font-size: 14px;
  color: #444;
}

.exp-target.is-warn { color: #9a5b00; }

.exp-target code { font-size: 12px; }

.exp-worker-state { font-weight: var(--ds-weight-bold); }
.exp-worker-state.is-on { color: #107c10; }
.exp-worker-state.is-off { color: var(--ds-danger); }

.exp-log {
  margin: 12px 0 0;
  padding-left: 1.4em;
  font-size: 13px;
  color: #555;
}

.exp-badge--custom { background: #1b4fd8; }

.exp-item__dirty {
  font-size: 17px;
  font-weight: var(--ds-weight-bold);
  color: var(--ds-danger);
}

/* パネル編集画面を「この画像用に調整」で開いた時の印 */
.pnl-export-note { color: #1b4fd8; font-weight: var(--ds-weight-bold); }

/* 画像の名前（任意）。書き出しの欄と、書き出し済みの一覧 */
.exp-field--name input {
  width: 340px;
  font: inherit;
  padding: 6px 8px;
  border: 1px solid #bbb;
}

.exp-item__nameinput {
  width: 100%;
  font: inherit;
  font-size: 18px;
  font-weight: var(--ds-weight-bold);
  padding: 4px 8px;
  border: 1px solid transparent;
  background: transparent;
}

.exp-item__nameinput:hover,
.exp-item__nameinput:focus {
  border-color: #bbb;
  background: #fff;
}

.exp-item__nameinput::placeholder {
  font-weight: var(--ds-weight-regular);
  color: #aaa;
}

.exp-item__nameinput.is-saved { border-color: #107c10; }

/* 画像書き出しの確認ダイアログの説明文（\n で改行する） */
.exp-dialog__message { white-space: pre-line; margin: 0 0 12px; }
