@charset "utf-8";
/* ==========================================================================
   Foundation — デザイントークン / リセット / 要素の既定
   FLOCSS の Foundation 層。ここだけが「値」を持ち、以降の層は var() で参照する。
   ========================================================================== */

/* 書体 ── Noto Sans JP を「このサイトで使う文字だけ」に絞って自己ホストしている。
   元は 10.2MB（248分割）あるが、実際に出てくる960字だけ取り出して各約115KBにした。
   生成は _build_font.py（文言を足したら再実行する）。
   ⛔ CDN を直接読まないのは、外部への接続が増えるとサイト内で説明している
      「外部のスクリプトを読み込まない作り」と食い違うため。 */
@font-face {
  font-family: "Noto Sans JP Subset";
  src: url("/assets/font/noto-sans-jp-400.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;   /* 読み込み中もシステムフォントで即座に表示する */
}
@font-face {
  font-family: "Noto Sans JP Subset";
  src: url("/assets/font/noto-sans-jp-700.woff2") format("woff2");
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}

/* レイヤの優先順位をここで宣言する。以降どのファイルで何を書いても、
   詳細度ではなくこの並び順で勝敗が決まる（FLOCSS の思想をネイティブCSSで保証する）。 */
@layer foundation, layout, component, project, utility;

/* --------------------------------------------------------------------------
   トークン定義は @layer の外に置く。
   レイヤ内で定義したカスタムプロパティは、レイヤ外の無指定スタイルに負ける
   ケースがあるため、値の供給源だけは最優先で確定させる。
   -------------------------------------------------------------------------- */
:root {
  /* 色 ── 役割で名前をつける。#f7f6f3 のような値を component 層に書かない。
     ライト/ダークは「同じ名前・別の値」で差し替える（名前が意味を持つため、
     --gray-100 のようなプリミティブ名は使わない。ダークで名前が嘘になる） */
  --color-text-primary: #15181c;    /* 本文 */
  --color-text-secondary: #3d444d;  /* リード・カード説明 */
  --color-text-muted: #6d757f;      /* メタ情報・注記 */

  --color-bg-base: #f7f6f3;         /* ページの地 */
  --color-bg-surface: #ffffff;      /* カード・パネル */
  --color-bg-surface-alt: #f1efea;  /* 面の中の差分（サムネ地・表の縞） */

  --color-border: #e2ddd4;
  --color-border-strong: #cfc8bb;

  --color-accent: #155e63;
  --color-accent-hover: #0f4a4e;
  --color-accent-surface: #e3efef;
  --color-text-on-accent: #ffffff;

  --color-warn-text: #8a5a00;
  --color-warn-surface: #fdf4e0;
  --color-warn-border: #e7cf9a;

  /* デモ告知バー専用 ── テーマに追従させない。
     架空であることの告知は、暗い配色でも沈んではいけない性質のもの。 */
  --color-demo-bar-bg: #12171c;
  --color-demo-bar-text: #f2f5f7;
  --color-demo-bar-badge: #f6c945;

  /* 文字サイズ ── 8段階。すべて整数px。
     ⛔ em の入れ子・clamp()・vw を使わない（14.08px のような端数はそこから生まれる） */
  --fs-xs: 12px;       /* タグ・キッカー・キャプション */
  --fs-sm: 14px;       /* カード説明・メタ・フッター */
  --fs-md: 16px;       /* 本文 */
  --fs-lg: 18px;       /* リード文・カード見出し */
  --fs-xl: 20px;       /* h3 */
  --fs-2xl: 24px;      /* h2 */
  --fs-3xl: 28px;      /* ページタイトル */
  --fs-display: 40px;  /* 見出しの最大（下層ページ） */
  /* ── ジャンプ率の設計 ────────────────────────────────
     本文16px を 1.0 とし、見出しの倍率を決める。
       ヒーロー大見出し 50px = 3.13倍   ← 紙面で最も強い一点。短い句を3行に積む
       章見出し h2      24px = 1.50倍
       小見出し h3      20px = 1.25倍
       本文             16px = 1.00倍
       補助             14px = 0.88倍
       ラベル           12px = 0.75倍
     ⛔ 3.13倍は制作会社サイトの実測帯（Shin Design 3.13倍）。ベイジは2.40倍で、
        どちらも成立する。分かれ目は「1行の長さ」で、長い文を大きくすると破綻する。
        50pxを採るなら見出しは短い句に割って縦に積むこと。 */
  --fs-hero: 50px;     /* ヒーロー大見出し。本文の3.13倍
                          ⛔ 3行に短く積む前提の大きさ。1行が長いと破綻する */
  --fs-figure: 48px;   /* 実測値の数字だけ。本文の3.00倍
                          ⛔ 3項目に絞ったので1つあたりに余白が取れる。見出し38pxを超えるが、
                             数が3つなら「同じ強さの塊が5つ並ぶ」状態にならず主従が壊れない */

  /* 行間 ── 和文は欧文より広く取る。本文1.8、見出しは詰める */
  --lh-tight: 1.35;
  --lh-heading: 1.5;
  --lh-body: 1.8;
  --lh-compact: 1.7;

  /* 余白 ── 4px 基底。名前の数字 × 4px で暗算できるようにしてある */
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-6: 24px;
  --space-8: 32px;
  --space-12: 48px;
  --space-16: 64px;
  --space-24: 96px;

  --radius-sm: 6px;
  --radius-md: 10px;
  --radius-lg: 14px;
  --radius-full: 999px;

  --shadow-card: 0 1px 2px rgb(20 24 28 / 5%), 0 8px 24px -12px rgb(20 24 28 / 12%);
  /* 浮かせるための影。カードより一段強く、遠くまで落とす */
  --shadow-float: 0 2px 4px rgb(20 24 28 / 6%), 0 24px 48px -16px rgb(20 24 28 / 22%);

  /* ヒーローの面。写真は使わず、ぼかした光の玉・方眼・粒子の3層で作る。
     ⛔ 写真を敷かない理由は2つ。①自己ホストすると数百KB増える（現在の総転送は
        フォント込みで約440KB）②ぼかした抽象写真は生成AIの出力に見えやすい。
     ⛔ どの層も本文の可読性を落とさない濃度に留める（実測でコントラスト比を確認）。 */
  /* ⛔ 一度は単色に戻した（見出し50pxと階調つき背景が競合したため）。
     2026-08-21 に写真へ切り替えた。競合しないのは、ぼかしで細部が消えていて
     「模様」ではなく「面のむら」として働くから。⛔ ぼかしを弱めると競合が戻る。 */
  --hero-bg: #edeae4;                          /* 写真が来る前に出る地の色 */
  --hero-photo: url("/assets/img/hero-office.webp");
  /* ヒーローの白パネルの地。⛔ わずかに透かして、写真の上に浮いていることを見せる。
     透かすのはこのパネルだけ（他のカードは不透明のまま）。
     ⛔ 数字を下げすぎると中の文字が写真の模様と干渉する。合否は実測で決める。 */
  --panel-bg: rgb(255 255 255 / 89%);
  /* パネル内の小さい文字の色。⛔ 通常の --color-text-muted (#6d757f) は
     白地100%でも 4.67:1 しかなく、パネルを94%まで透かすと 4.45:1 で基準を割る。
     ここだけ一段濃くして余裕を作る（見た目の差はほぼ出ない）。
     実測（不透明度89%・透過10%のとき）: ラベル 4.95:1 ／ 数字 16.34:1 ＝ AA合格。
     ⛔ 透過を上げるときは必ず `_check_hero_contrast.py` で測り直す。
        ラベルが先に割れる（数字は16:1あるので、数字を見て判断すると必ず薄くしすぎる）。 */
  --panel-label: #636b75;
  /* 技術タグの地。写真の上に載るので、塗りが無いと読めない（実機で発生）。
     ⛔ 不透明にはしない。写真の上に浮いた小さな板に見せる。
     実測（ヒーロー全域の最悪地で）: 文字 #3d444d が PC 8.24:1 ／ スマホ 7.95:1。 */
  --chip-bg: rgb(255 255 255 / 80%);
  --panel-blur: 3px;
  /* 補助の実測値。上の3つ(48px)より一段落として主従を保つ */
  --fs-figure-sub: 30px;
  /* 写真の上にかぶせる膜。⛔ ここが薄いと見出しが読めない。
     写真側の実測（暗部5%＝輝度167）に対し、左を92%まで上げて本文の
     コントラストを確保し、右に向けて薄くして写真を見せる。
     ⛔ 色は地の色と同系にする（白だと写真だけ浮いて見える）
     ── この数字の決め方（⛔ 目分量で動かさない） ──────────────
     `_check_hero_contrast.py` が、この膜と写真を実際に合成して、文字が
     載る4箇所の最悪コントラストを測る。触ったら必ず再実行する。
     実測（2026-08-21・PC 1568px）:
       キッカー 6.62:1 ／ 前置き 6.47:1 ／ 大見出し 12.80:1 ／ リード文 5.20:1
     ⛔ 効いている制約はリード文だけ（右端ほど膜が薄いため）。左を 50% まで
        抜いても大見出しは 11.7:1 あるが、左下のモニターが濃い塊として
        リード文の帯に食い込むので 72% で止めている（見た目の判断）。 */
  --hero-veil: linear-gradient(100deg,
      rgb(247 246 243 / 72%) 0%,
      rgb(247 246 243 / 70%) 36%,
      rgb(241 239 234 / 56%) 70%,
      rgb(238 235 228 / 38%) 100%);

  /* 幅 ── コンテナは3カラムが成立する最小格。
     和文の読みやすさは行の文字数で決まるので、本文柱は別に 40em で締める */
  /* 固定ヘッダーの高さ。本文の押し下げとアンカーの着地位置に使う。
     ⛔ 実測値（68px）と合わせること。ずれると本文が隠れるか、無駄な隙間が空く */
  --header-h: 68px;

  --width-container: 1040px;
  --width-prose: 40em;

  /* 書体 ── 外部フォントを1つも読み込まない方針のため、システムフォントで組む */
  --font-sans: "Noto Sans JP Subset", system-ui, -apple-system, "Hiragino Sans",
               "Hiragino Kaku Gothic ProN", "Yu Gothic", "Meiryo", sans-serif;
  --font-serif: "Hiragino Mincho ProN", "Yu Mincho", serif;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --chip-bg: rgb(23 27 31 / 80%);
    --panel-label: #8f99a3;   /* 実測 5.44:1（透過13%時）。ダークは薄いままで足りる */
    --panel-bg: rgb(23 27 31 / 87%);
    --hero-bg: #191d21;
    /* 暗い面では、明るい写真をそのまま出すと本文が読めない。膜を暗い側で作る */
    --hero-veil: linear-gradient(100deg,
        rgb(16 19 22 / 93%) 0%,
        rgb(16 19 22 / 88%) 36%,
        rgb(23 27 31 / 74%) 70%,
        rgb(25 29 33 / 64%) 100%);
    --shadow-float: 0 2px 4px rgb(0 0 0 / 50%), 0 24px 48px -16px rgb(0 0 0 / 70%);
    --color-text-primary: #eef1f3;
    --color-text-secondary: #c3cad1;
    --color-text-muted: #8f99a3;
    --color-bg-base: #101316;
    --color-bg-surface: #171b1f;
    --color-bg-surface-alt: #1d2227;
    --color-border: #2a3036;
    --color-border-strong: #39424a;
    --color-accent: #5fd0cf;
    --color-accent-hover: #8ce3e0;
    --color-accent-surface: #16302f;
    --color-text-on-accent: #07211f;
    --color-warn-text: #f0c874;
    --color-warn-surface: #2a2317;
    --color-warn-border: #4a3d21;
    --shadow-card: 0 1px 2px rgb(0 0 0 / 40%), 0 8px 24px -12px rgb(0 0 0 / 60%);
  }
}

:root[data-theme="dark"] {
  --chip-bg: rgb(23 27 31 / 80%);
  --panel-label: #8f99a3;   /* 実測 5.44:1（透過13%時）。ダークは薄いままで足りる */
  --panel-bg: rgb(23 27 31 / 87%);
  --hero-bg: #191d21;
  --hero-veil: linear-gradient(100deg,
      rgb(16 19 22 / 93%) 0%,
      rgb(16 19 22 / 88%) 36%,
      rgb(23 27 31 / 74%) 70%,
      rgb(25 29 33 / 64%) 100%);
  --shadow-float: 0 2px 4px rgb(0 0 0 / 50%), 0 24px 48px -16px rgb(0 0 0 / 70%);
  --color-text-primary: #eef1f3;
  --color-text-secondary: #c3cad1;
  --color-text-muted: #8f99a3;
  --color-bg-base: #101316;
  --color-bg-surface: #171b1f;
  --color-bg-surface-alt: #1d2227;
  --color-border: #2a3036;
  --color-border-strong: #39424a;
  --color-accent: #5fd0cf;
  --color-accent-hover: #8ce3e0;
  --color-accent-surface: #16302f;
  --color-text-on-accent: #07211f;
  --color-warn-text: #f0c874;
  --color-warn-surface: #2a2317;
  --color-warn-border: #4a3d21;
  --shadow-card: 0 1px 2px rgb(0 0 0 / 40%), 0 8px 24px -12px rgb(0 0 0 / 60%);
}

@layer foundation {
  *,
  *::before,
  *::after { box-sizing: border-box; }

  html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }

  @media (prefers-reduced-motion: reduce) {
    html { scroll-behavior: auto; }
    *, *::before, *::after { animation-duration: .01ms !important; transition-duration: .01ms !important; }
  }

  body {
    margin: 0;
    background: var(--color-bg-base);
    color: var(--color-text-primary);
    font-family: var(--font-sans);
    font-size: var(--fs-md);
    font-weight: 400;
    line-height: var(--lh-body);
  }

  h1, h2, h3, h4 {
    margin: 0;
    font-weight: 700;
    line-height: var(--lh-heading);
    letter-spacing: .02em;
    /* 見出しだけ約物を詰める。本文に掛けると行長が不安定になるため掛けない */
    font-feature-settings: "palt";
  }
  h1 { font-size: var(--fs-3xl); line-height: var(--lh-tight); }
  h2 { font-size: var(--fs-2xl); }
  h3 { font-size: var(--fs-xl); }

  p, ul, ol, dl, figure, table { margin: 0; }
  /* ⛔ dd はブラウザ既定で margin-inline-start:40px が付く。
     dl を margin:0 にしても消えないため、明示的に落とす
     （実測: 数字がラベルより40px右にずれていた原因） */
  dd { margin-inline-start: 0; }
  ul, ol { padding-left: 1.25em; }
  li + li { margin-top: var(--space-1); }

  a { color: var(--color-accent); text-underline-offset: .2em; }
  a:hover { color: var(--color-accent-hover); }

  img, svg { max-width: 100%; height: auto; vertical-align: middle; }

  th, td { text-align: left; }

  :focus-visible {
    outline: 2px solid var(--color-accent);
    outline-offset: 2px;
    border-radius: var(--radius-sm);
  }

  ::selection { background: var(--color-accent-surface); }

  @media (max-width: 767px) {
    h1 { font-size: var(--fs-2xl); }
    h2 { font-size: var(--fs-xl); }
  }
}
