/* =====================================================================
   ibit.dev — calm dark modern theme
   Clean, restrained dark portfolio: one accent color, smooth bars,
   subtle hovers, readable typography.
   NOTE: this stylesheet is SHARED with エラーページ(404/403/500) — keep structural
   classes (.navbar/.nav-*, .section*, .btn*, .site-footer/.footer-*) working there too.
   エラーページ固有の装飾は public/css/error.css。Index-only flourishes は `main.left` 配下。
   ===================================================================== */

/* セルフホストフォント（Google Fonts CDN 不使用。woff2 は public/fonts/ に配置し、
   サイトで実際に使う字形にサブセット済み）。@import はレンダリングブロックのため不使用。
   ?v= はフォントのキャッシュバスト版数。woff2 は immutable 1年キャッシュ + SW
   cache-first のため、再サブセット時は URL を変えないと旧フォントが配り続けられる。
   再生成したら fonts/README.md の手順どおり、ここ・render.php の preload・sw.js の
   PRECACHE の3箇所を同じ版数に揃えること（不一致だと preload が二重ダウンロードになる）。 */
@font-face { font-family: 'Inter'; font-style: normal; font-weight: 400; font-display: swap; src: url('../fonts/inter-400.woff2?v=3') format('woff2'); }
@font-face { font-family: 'Inter'; font-style: normal; font-weight: 600; font-display: swap; src: url('../fonts/inter-600.woff2?v=3') format('woff2'); }
@font-face { font-family: 'Inter'; font-style: normal; font-weight: 700; font-display: swap; src: url('../fonts/inter-700.woff2?v=3') format('woff2'); }
/* Noto Sans JP は unicode-range スライス配信 (tools/slice_noto.py が生成)。
   s0=かな/和文約物 (preload 対象) / s1-s4=漢字の頻度順 4 分割 / s5=その他
   (ラテン・記号: スタック先頭の Inter が持つ字では要求されない)。
   ブラウザはページで実際に使う範囲のスライスだけを取得する。
   再生成手順: resubset_noto.py → slice_noto.py → ?v= を 3 箇所同期 (README)。 */
@font-face { font-family: 'Noto Sans JP'; font-style: normal; font-weight: 400; font-display: swap; src: url('../fonts/noto-sans-jp-400.s0.woff2?v=2') format('woff2'); unicode-range: U+3001-303F,U+3041-3096,U+3099-30FF; }
@font-face { font-family: 'Noto Sans JP'; font-style: normal; font-weight: 400; font-display: swap; src: url('../fonts/noto-sans-jp-400.s1.woff2?v=2') format('woff2'); unicode-range: U+4E00,U+4E0A-4E0B,U+4E0D,U+4E2D,U+4E8B,U+4EBA,U+4ED6,U+4ED8,U+4EE5,U+4EF6,U+4F4D,U+4F53,U+4F5C,U+4F7F,U+4F8B,U+4FB5,U+4FDD,U+4FE1,U+500B,U+5024,U+5074,U+507D,U+50CF,U+5143,U+5148,U+5165,U+5168,U+516C,U+5171,U+5185,U+518D,U+51FA,U+5206-5207,U+5217,U+521D,U+5224-5225,U+5236,U+523B,U+524D,U+529B,U+52A0,U+52B9,U+52D5,U+5316,U+5358,U+53C2,U+53D6,U+53EF,U+5408,U+540C-540D,U+547C,U+554F,U+55B6,U+56DE,U+56FA,U+5728,U+5831,U+5834,U+5909,U+5916,U+5927,U+5931,U+5B57-5B58,U+5B66,U+5B8C,U+5B9A,U+5B9F,U+5BB9,U+5BFE,U+5C0F,U+5DEE,U+5E38,U+5EA6,U+5F0F,U+5F53,U+5F62,U+5F8C,U+5F97,U+5FA9,U+5FC5,U+5FDC,U+6027,U+60C5,U+610F,U+614B,U+6210,U+623B,U+6280,U+6301,U+63CF,U+6557,U+6570,U+6587,U+65B0,U+65B9,U+65E2,U+65E5,U+660E,U+6642,U+66F4,U+66F8,U+66FF-6700,U+6709,U+671F,U+672A,U+672C,U+6765,U+691C,U+6B21,U+6B62-6B63,U+6B8B,U+6BB5,U+6C7A,U+6E08,U+6E96,U+7121,U+72B6,U+73FE,U+7406,U+751F,U+7528,U+753B,U+756A,U+767A,U+7684,U+76EE,U+76F4,U+76F8,U+7740,U+77E5,U+78BA,U+793A,U+79FB,U+7A2E,U+7A7A,U+7B49,U+7BA1,U+7D04,U+7D20,U+7D30,U+7D42,U+7D44,U+7D9A,U+7DE8,U+7F6E,U+8005,U+80FD,U+81EA,U+843D,U+884C,U+8853,U+8868,U+88C5,U+8907,U+8981,U+898B,U+898F,U+8996,U+89A7,U+89E3,U+8A00,U+8A08,U+8A18,U+8A2D,U+8A3C,U+8A66,U+8A73,U+8A8D,U+8AAD,U+8FBC,U+8FD1,U+8FD4,U+8FFD,U+9001,U+901A,U+9023,U+904B,U+9078,U+90E8,U+914D,U+91CD,U+9332,U+9589,U+958B,U+9593,U+95A2,U+9632,U+9650,U+9664,U+96C6,U+9759,U+975E,U+9762,U+9806,U+982D; }
@font-face { font-family: 'Noto Sans JP'; font-style: normal; font-weight: 400; font-display: swap; src: url('../fonts/noto-sans-jp-400.s2.woff2?v=2') format('woff2'); unicode-range: U+4E16,U+4E21,U+4E26,U+4E3B,U+4E86,U+4E88,U+4E8C,U+4ECA-4ECB,U+4ED5,U+4EE3,U+4EFB,U+4F1D,U+4F55,U+4F9D,U+5012,U+5019,U+5099,U+512A,U+51E6,U+5229,U+5230,U+524A,U+5272,U+529F,U+52D9,U+5373,U+53BB,U+53CD-53CE,U+53D7,U+53E4,U+53F3,U+5404,U+5411,U+5426,U+542B,U+544A,U+5473,U+54C1,U+5584,U+56F2-56F3,U+56FD,U+5730,U+578B,U+57CB,U+57FA,U+5883,U+5897,U+58CA,U+591A,U+59CB,U+59D4,U+5B50,U+5B89,U+5C02,U+5C0E,U+5C11,U+5C3E,U+5C5E,U+5C64-5C65,U+5DE5,U+5E45,U+5E74,U+5EF6,U+5F15,U+5F35,U+5F37,U+5F79,U+5F93,U+5FA1,U+5FC3,U+60F3,U+611F,U+6240,U+624B,U+6253,U+6271,U+6291,U+629E,U+62C5,U+62E0,U+62FE,U+6307,U+633F,U+6368,U+6392,U+63A5,U+63C3,U+63D0,U+63DB,U+63F4,U+6483,U+64CD,U+6539,U+653B,U+6563,U+6574,U+65AD,U+65E7,U+6620,U+666E,U+6708,U+672B,U+6761,U+679C,U+67FB,U+6848,U+68C4,U+6982,U+69CB,U+6A19,U+6A21,U+6A2A,U+6A5F,U+6B74,U+6BCE,U+6BD4,U+6C17,U+6CC1,U+6CE8,U+6D3B,U+6D41,U+6D88,U+6E21,U+6E2C,U+6E90,U+6F0F,U+706B,U+70B9,U+7167,U+7269,U+74B0,U+7531,U+7533,U+767B,U+76E3,U+771F,U+7834,U+79D2,U+7A81,U+7A93,U+7ACB,U+7AEF,U+7AF6,U+7B56,U+7B97,U+7BC0,U+7CFB,U+7D22,U+7D39,U+7D4C,U+7D50,U+7D5E,U+7D71,U+7D76,U+7DDA,U+7FA9,U+7FD2,U+81F4,U+8272,U+885D,U+88DC,U+899A,U+89E6,U+8A31,U+8A70-8A72,U+8A9E,U+8AAC,U+8AC7,U+8B66,U+8C61,U+8D77,U+8D85,U+8DEF,U+8EAB,U+8EFD,U+8F09,U+8FF7,U+9000,U+9014,U+901F-9020,U+9045,U+904E,U+9054-9055,U+907F,U+9577,U+964D,U+967A,U+969B,U+96A0,U+96E2,U+9805,U+9808,U+983C,U+984C; }
@font-face { font-family: 'Noto Sans JP'; font-style: normal; font-weight: 400; font-display: swap; src: url('../fonts/noto-sans-jp-400.s3.woff2?v=2') format('woff2'); unicode-range: U+4E07,U+4E09,U+4E0E,U+4E38,U+4E45,U+4E71,U+4EA4,U+4F01,U+4F1A,U+4F38,U+4F4E,U+4F59,U+4F9B,U+4FA1,U+4FC3,U+4FEE,U+500D,U+50CD,U+5100,U+5149,U+5177,U+5186,U+5192,U+5199,U+526F-5270,U+5275,U+52DD,U+5305,U+533A,U+5341,U+534A,U+5360,U+5374,U+539F,U+53E3,U+53F0,U+53F7,U+5438,U+547D,U+548C,U+552F,U+57DF,U+58C1,U+58EB,U+592B,U+597D,U+59A5,U+5B88,U+5B9B,U+5BB3,U+5BC4,U+5BC6,U+5BF8,U+5C4A,U+5C90,U+5DE6,U+5DF1,U+5E03,U+5E0C,U+5E2F-5E30,U+5E83,U+5E8F,U+5EA7,U+5F3E,U+5F71,U+5F85,U+5FEB,U+5FF5,U+601D,U+6025,U+60AA,U+628A,U+6295,U+6298,U+629C,U+62BC,U+62D2,U+62E1,U+62F6,U+6319,U+639B,U+63A1-63A2,U+63A7-63A8,U+63B2,U+63E1,U+652F,U+653E,U+6545,U+65E9,U+666F,U+671B,U+6790,U+679A,U+67A0,U+683C,U+68D2,U+696D,U+697D,U+69D8,U+6A29,U+6B04,U+6B20,U+6B69,U+6C38,U+6C42,U+6C4E,U+6CD5,U+6D6A,U+6D6E,U+6DF1,U+6DF7,U+6DFB,U+6E1B,U+6E80,U+6F14,U+7136,U+7279,U+72EC,U+754C,U+7559,U+7565,U+7573,U+767D,U+7701,U+77AC,U+7981,U+7A3F,U+7A4D,U+7B2C,U+7B54,U+7B87,U+7BC4,U+7BC9,U+7D0D,U+7D14,U+7D2F,U+7D61,U+7DAD,U+7DCF,U+7DD2,U+7E26,U+7E2E,U+7E3E,U+7E55,U+7F60,U+7F72,U+7FA4,U+8003,U+8010,U+80A5,U+80CC,U+8131,U+8208,U+826F,U+82F1,U+8349,U+88FD,U+89B3,U+89D2,U+8A17,U+8A33,U+8A55,U+8AA4,U+8AB2,U+8ABF,U+8B58,U+8B72,U+8CAC,U+8CBB-8CBC,U+8CEA,U+8D70,U+8DB3,U+8E0F,U+8F03,U+9006,U+900F,U+9032,U+904A,U+9069,U+906E,U+9077,U+91CF,U+91DD,U+9375,U+95B2,U+968E,U+9694,U+9732,U+97FF,U+9818,U+98A8,U+98DB,U+98FE,U+99C4,U+99C6,U+9A13,U+9AA8; }
@font-face { font-family: 'Noto Sans JP'; font-style: normal; font-weight: 400; font-display: swap; src: url('../fonts/noto-sans-jp-400.s4.woff2?v=2') format('woff2'); unicode-range: U+4E01,U+4E08,U+4EE4,U+4EEE,U+4F11,U+4FBF,U+4FC2,U+505C,U+5065,U+50BE,U+5145,U+5178,U+517C,U+51CD,U+5237,U+52D8,U+52E2,U+5348,U+5370,U+53B3,U+53CC,U+5468,U+5546,U+5668,U+56F0,U+571F,U+5805,U+5857,U+58F0,U+58F2,U+591C,U+592E,U+5951,U+596A,U+59A8,U+59FF,U+5ACC,U+5BB6,U+5BE7,U+5C04,U+5C06,U+5C0A,U+5C55,U+5DE1,U+5E02,U+5E2D,U+5E95,U+5F31,U+5F90,U+5FB9,U+5FD8,U+6163,U+616E,U+61A9,U+6212,U+62B5,U+62EC,U+631F,U+6328,U+632F,U+6349,U+6355,U+636E,U+6383,U+6398,U+63B4,U+640D,U+643A,U+6458,U+64AE,U+6559,U+6577,U+6599,U+65BD,U+65E6,U+65E8,U+6607,U+6613,U+6697,U+66B4,U+66DC,U+6728,U+6750,U+67D3-67D4,U+6841,U+68B0,U+6955,U+6975,U+6B32,U+6B53,U+6C34,U+6C5A,U+6CE2,U+6D17,U+6D2A,U+6D3E,U+6DE1,U+6E9C,U+6EC5,U+6FEB,U+70BA,U+7169,U+719F,U+7206,U+7248,U+7262,U+72D9,U+72ED,U+7387,U+7523,U+75B2,U+76BF,U+76DB,U+77E2,U+77E9,U+77ED,U+7956,U+7965,U+79F0,U+7A00,U+7A0B,U+7A3C,U+7AE0,U+7C21,U+7C8B,U+7C92,U+7C97,U+7CBE,U+7D10,U+7D1A,U+7D2B,U+7D3A,U+7D75,U+7DB2,U+7DE0,U+7DEF,U+7E01,U+7E70,U+7F85,U+7F8E,U+7FCC,U+8077,U+80A2,U+8106,U+8108,U+8155,U+82BD,U+8352,U+8377,U+8449,U+853D,U+885B,U+88C1,U+88D5,U+8912,U+8997,U+89AA,U+8A2A,U+8A98,U+8AB0,U+8AD6,U+8B77,U+8CA0,U+8CA9,U+8CAB,U+8CB7,U+8CC7,U+8CFC,U+8DE1,U+8DE8,U+8EE2,U+8EF8,U+8F9E,U+8FCE,U+9031,U+9053,U+90FD,U+91C8,U+91CE,U+91D1,U+932F,U+95BE,U+968F,U+969C,U+96E3,U+96F0,U+96FB,U+9752,U+97F3,U+983B,U+9854,U+985E,U+98DF,U+99D2,U+9A12,U+9AD8,U+9CF4,U+9ED2,U+9ED9; }
@font-face { font-family: 'Noto Sans JP'; font-style: normal; font-weight: 400; font-display: swap; src: url('../fonts/noto-sans-jp-400.s5.woff2?v=2') format('woff2'); unicode-range: U+0021-007E,U+00A1-00FF,U+2010-2016,U+2018-201A,U+201C-201E,U+2020-2022,U+2025-2027,U+2030,U+2032-2033,U+2035,U+2039-203C,U+2042,U+2047-2049,U+2051,U+2190-2194,U+2500,U+2580,U+2584,U+2588,U+25CF,U+25EF,U+2600,U+FF01-FF9F,U+FFA1-FFBE,U+FFC2-FFC7,U+FFCA-FFCF,U+FFD2-FFD7,U+FFDA-FFDC,U+FFE0-FFE6,U+FFE8-FFEE; }
@font-face { font-family: 'Noto Sans JP'; font-style: normal; font-weight: 700; font-display: swap; src: url('../fonts/noto-sans-jp-700.s0.woff2?v=2') format('woff2'); unicode-range: U+3001-303F,U+3041-3096,U+3099-30FF; }
@font-face { font-family: 'Noto Sans JP'; font-style: normal; font-weight: 700; font-display: swap; src: url('../fonts/noto-sans-jp-700.s1.woff2?v=2') format('woff2'); unicode-range: U+4E00,U+4E0A-4E0B,U+4E0D,U+4E2D,U+4E8B,U+4EBA,U+4ED6,U+4ED8,U+4EE5,U+4EF6,U+4F4D,U+4F53,U+4F5C,U+4F7F,U+4F8B,U+4FB5,U+4FDD,U+4FE1,U+500B,U+5024,U+5074,U+507D,U+50CF,U+5143,U+5148,U+5165,U+5168,U+516C,U+5171,U+5185,U+518D,U+51FA,U+5206-5207,U+5217,U+521D,U+5224-5225,U+5236,U+523B,U+524D,U+529B,U+52A0,U+52B9,U+52D5,U+5316,U+5358,U+53C2,U+53D6,U+53EF,U+5408,U+540C-540D,U+547C,U+554F,U+55B6,U+56DE,U+56FA,U+5728,U+5831,U+5834,U+5909,U+5916,U+5927,U+5931,U+5B57-5B58,U+5B66,U+5B8C,U+5B9A,U+5B9F,U+5BB9,U+5BFE,U+5C0F,U+5DEE,U+5E38,U+5EA6,U+5F0F,U+5F53,U+5F62,U+5F8C,U+5F97,U+5FA9,U+5FC5,U+5FDC,U+6027,U+60C5,U+610F,U+614B,U+6210,U+623B,U+6280,U+6301,U+63CF,U+6557,U+6570,U+6587,U+65B0,U+65B9,U+65E2,U+65E5,U+660E,U+6642,U+66F4,U+66F8,U+66FF-6700,U+6709,U+671F,U+672A,U+672C,U+6765,U+691C,U+6B21,U+6B62-6B63,U+6B8B,U+6BB5,U+6C7A,U+6E08,U+6E96,U+7121,U+72B6,U+73FE,U+7406,U+751F,U+7528,U+753B,U+756A,U+767A,U+7684,U+76EE,U+76F4,U+76F8,U+7740,U+77E5,U+78BA,U+793A,U+79FB,U+7A2E,U+7A7A,U+7B49,U+7BA1,U+7D04,U+7D20,U+7D30,U+7D42,U+7D44,U+7D9A,U+7DE8,U+7F6E,U+8005,U+80FD,U+81EA,U+843D,U+884C,U+8853,U+8868,U+88C5,U+8907,U+8981,U+898B,U+898F,U+8996,U+89A7,U+89E3,U+8A00,U+8A08,U+8A18,U+8A2D,U+8A3C,U+8A66,U+8A73,U+8A8D,U+8AAD,U+8FBC,U+8FD1,U+8FD4,U+8FFD,U+9001,U+901A,U+9023,U+904B,U+9078,U+90E8,U+914D,U+91CD,U+9332,U+9589,U+958B,U+9593,U+95A2,U+9632,U+9650,U+9664,U+96C6,U+9759,U+975E,U+9762,U+9806,U+982D; }
@font-face { font-family: 'Noto Sans JP'; font-style: normal; font-weight: 700; font-display: swap; src: url('../fonts/noto-sans-jp-700.s2.woff2?v=2') format('woff2'); unicode-range: U+4E16,U+4E21,U+4E26,U+4E3B,U+4E86,U+4E88,U+4E8C,U+4ECA-4ECB,U+4ED5,U+4EE3,U+4EFB,U+4F1D,U+4F55,U+4F9D,U+5012,U+5019,U+5099,U+512A,U+51E6,U+5229,U+5230,U+524A,U+5272,U+529F,U+52D9,U+5373,U+53BB,U+53CD-53CE,U+53D7,U+53E4,U+53F3,U+5404,U+5411,U+5426,U+542B,U+544A,U+5473,U+54C1,U+5584,U+56F2-56F3,U+56FD,U+5730,U+578B,U+57CB,U+57FA,U+5883,U+5897,U+58CA,U+591A,U+59CB,U+59D4,U+5B50,U+5B89,U+5C02,U+5C0E,U+5C11,U+5C3E,U+5C5E,U+5C64-5C65,U+5DE5,U+5E45,U+5E74,U+5EF6,U+5F15,U+5F35,U+5F37,U+5F79,U+5F93,U+5FA1,U+5FC3,U+60F3,U+611F,U+6240,U+624B,U+6253,U+6271,U+6291,U+629E,U+62C5,U+62E0,U+62FE,U+6307,U+633F,U+6368,U+6392,U+63A5,U+63C3,U+63D0,U+63DB,U+63F4,U+6483,U+64CD,U+6539,U+653B,U+6563,U+6574,U+65AD,U+65E7,U+6620,U+666E,U+6708,U+672B,U+6761,U+679C,U+67FB,U+6848,U+68C4,U+6982,U+69CB,U+6A19,U+6A21,U+6A2A,U+6A5F,U+6B74,U+6BCE,U+6BD4,U+6C17,U+6CC1,U+6CE8,U+6D3B,U+6D41,U+6D88,U+6E21,U+6E2C,U+6E90,U+6F0F,U+706B,U+70B9,U+7167,U+7269,U+74B0,U+7531,U+7533,U+767B,U+76E3,U+771F,U+7834,U+79D2,U+7A81,U+7A93,U+7ACB,U+7AEF,U+7AF6,U+7B56,U+7B97,U+7BC0,U+7CFB,U+7D22,U+7D39,U+7D4C,U+7D50,U+7D5E,U+7D71,U+7D76,U+7DDA,U+7FA9,U+7FD2,U+81F4,U+8272,U+885D,U+88DC,U+899A,U+89E6,U+8A31,U+8A70-8A72,U+8A9E,U+8AAC,U+8AC7,U+8B66,U+8C61,U+8D77,U+8D85,U+8DEF,U+8EAB,U+8EFD,U+8F09,U+8FF7,U+9000,U+9014,U+901F-9020,U+9045,U+904E,U+9054-9055,U+907F,U+9577,U+964D,U+967A,U+969B,U+96A0,U+96E2,U+9805,U+9808,U+983C,U+984C; }
@font-face { font-family: 'Noto Sans JP'; font-style: normal; font-weight: 700; font-display: swap; src: url('../fonts/noto-sans-jp-700.s3.woff2?v=2') format('woff2'); unicode-range: U+4E07,U+4E09,U+4E0E,U+4E38,U+4E45,U+4E71,U+4EA4,U+4F01,U+4F1A,U+4F38,U+4F4E,U+4F59,U+4F9B,U+4FA1,U+4FC3,U+4FEE,U+500D,U+50CD,U+5100,U+5149,U+5177,U+5186,U+5192,U+5199,U+526F-5270,U+5275,U+52DD,U+5305,U+533A,U+5341,U+534A,U+5360,U+5374,U+539F,U+53E3,U+53F0,U+53F7,U+5438,U+547D,U+548C,U+552F,U+57DF,U+58C1,U+58EB,U+592B,U+597D,U+59A5,U+5B88,U+5B9B,U+5BB3,U+5BC4,U+5BC6,U+5BF8,U+5C4A,U+5C90,U+5DE6,U+5DF1,U+5E03,U+5E0C,U+5E2F-5E30,U+5E83,U+5E8F,U+5EA7,U+5F3E,U+5F71,U+5F85,U+5FEB,U+5FF5,U+601D,U+6025,U+60AA,U+628A,U+6295,U+6298,U+629C,U+62BC,U+62D2,U+62E1,U+62F6,U+6319,U+639B,U+63A1-63A2,U+63A7-63A8,U+63B2,U+63E1,U+652F,U+653E,U+6545,U+65E9,U+666F,U+671B,U+6790,U+679A,U+67A0,U+683C,U+68D2,U+696D,U+697D,U+69D8,U+6A29,U+6B04,U+6B20,U+6B69,U+6C38,U+6C42,U+6C4E,U+6CD5,U+6D6A,U+6D6E,U+6DF1,U+6DF7,U+6DFB,U+6E1B,U+6E80,U+6F14,U+7136,U+7279,U+72EC,U+754C,U+7559,U+7565,U+7573,U+767D,U+7701,U+77AC,U+7981,U+7A3F,U+7A4D,U+7B2C,U+7B54,U+7B87,U+7BC4,U+7BC9,U+7D0D,U+7D14,U+7D2F,U+7D61,U+7DAD,U+7DCF,U+7DD2,U+7E26,U+7E2E,U+7E3E,U+7E55,U+7F60,U+7F72,U+7FA4,U+8003,U+8010,U+80A5,U+80CC,U+8131,U+8208,U+826F,U+82F1,U+8349,U+88FD,U+89B3,U+89D2,U+8A17,U+8A33,U+8A55,U+8AA4,U+8AB2,U+8ABF,U+8B58,U+8B72,U+8CAC,U+8CBB-8CBC,U+8CEA,U+8D70,U+8DB3,U+8E0F,U+8F03,U+9006,U+900F,U+9032,U+904A,U+9069,U+906E,U+9077,U+91CF,U+91DD,U+9375,U+95B2,U+968E,U+9694,U+9732,U+97FF,U+9818,U+98A8,U+98DB,U+98FE,U+99C4,U+99C6,U+9A13,U+9AA8; }
@font-face { font-family: 'Noto Sans JP'; font-style: normal; font-weight: 700; font-display: swap; src: url('../fonts/noto-sans-jp-700.s4.woff2?v=2') format('woff2'); unicode-range: U+4E01,U+4E08,U+4EE4,U+4EEE,U+4F11,U+4FBF,U+4FC2,U+505C,U+5065,U+50BE,U+5145,U+5178,U+517C,U+51CD,U+5237,U+52D8,U+52E2,U+5348,U+5370,U+53B3,U+53CC,U+5468,U+5546,U+5668,U+56F0,U+571F,U+5805,U+5857,U+58F0,U+58F2,U+591C,U+592E,U+5951,U+596A,U+59A8,U+59FF,U+5ACC,U+5BB6,U+5BE7,U+5C04,U+5C06,U+5C0A,U+5C55,U+5DE1,U+5E02,U+5E2D,U+5E95,U+5F31,U+5F90,U+5FB9,U+5FD8,U+6163,U+616E,U+61A9,U+6212,U+62B5,U+62EC,U+631F,U+6328,U+632F,U+6349,U+6355,U+636E,U+6383,U+6398,U+63B4,U+640D,U+643A,U+6458,U+64AE,U+6559,U+6577,U+6599,U+65BD,U+65E6,U+65E8,U+6607,U+6613,U+6697,U+66B4,U+66DC,U+6728,U+6750,U+67D3-67D4,U+6841,U+68B0,U+6955,U+6975,U+6B32,U+6B53,U+6C34,U+6C5A,U+6CE2,U+6D17,U+6D2A,U+6D3E,U+6DE1,U+6E9C,U+6EC5,U+6FEB,U+70BA,U+7169,U+719F,U+7206,U+7248,U+7262,U+72D9,U+72ED,U+7387,U+7523,U+75B2,U+76BF,U+76DB,U+77E2,U+77E9,U+77ED,U+7956,U+7965,U+79F0,U+7A00,U+7A0B,U+7A3C,U+7AE0,U+7C21,U+7C8B,U+7C92,U+7C97,U+7CBE,U+7D10,U+7D1A,U+7D2B,U+7D3A,U+7D75,U+7DB2,U+7DE0,U+7DEF,U+7E01,U+7E70,U+7F85,U+7F8E,U+7FCC,U+8077,U+80A2,U+8106,U+8108,U+8155,U+82BD,U+8352,U+8377,U+8449,U+853D,U+885B,U+88C1,U+88D5,U+8912,U+8997,U+89AA,U+8A2A,U+8A98,U+8AB0,U+8AD6,U+8B77,U+8CA0,U+8CA9,U+8CAB,U+8CB7,U+8CC7,U+8CFC,U+8DE1,U+8DE8,U+8EE2,U+8EF8,U+8F9E,U+8FCE,U+9031,U+9053,U+90FD,U+91C8,U+91CE,U+91D1,U+932F,U+95BE,U+968F,U+969C,U+96E3,U+96F0,U+96FB,U+9752,U+97F3,U+983B,U+9854,U+985E,U+98DF,U+99D2,U+9A12,U+9AD8,U+9CF4,U+9ED2,U+9ED9; }
@font-face { font-family: 'Noto Sans JP'; font-style: normal; font-weight: 700; font-display: swap; src: url('../fonts/noto-sans-jp-700.s5.woff2?v=2') format('woff2'); unicode-range: U+0021-007E,U+00A1-00FF,U+2010-2016,U+2018-201A,U+201C-201E,U+2020-2022,U+2025-2027,U+2030,U+2032-2033,U+2035,U+2039-203C,U+2042,U+2047-2049,U+2051,U+2190-2194,U+2500,U+2580,U+2584,U+2588,U+25CF,U+25EF,U+2600,U+FF01-FF9F,U+FFA1-FFBE,U+FFC2-FFC7,U+FFCA-FFCF,U+FFD2-FFD7,U+FFDA-FFDC,U+FFE0-FFE6,U+FFE8-FFEE; }

/* ---- Design tokens ---- */
:root {
    --header-height: 68px;
    --container-max: 1040px;

    --bg: #0e1217;
    --bg-2: #0b0e13;
    --surface: #161b22;
    --surface-2: #1b212a;
    --border: #232a34;
    --border-bright: #323b48;

    --text: #e8ebf0;
    --muted: #a4aebc;
    --dim: #8b95a3;

    --accent: #4d9bf5;
    --accent-rgb: 77, 155, 245; /* V15: --accent-soft より前に置いて派生トークンから参照可能に */
    --accent-strong: #6fb0ff;
    --accent-deep: #2f7de0;
    --accent-deep-rgb: 47, 125, 224; /* rgba(var(--accent-deep-rgb), .N) 参照用 */
    /* V15: 旧 rgba(77,155,245,0.12) 直書き → --accent-rgb 参照に統一。127 箇所の
       --accent-soft 参照が --accent の変更に追従するようになる。 */
    --accent-soft: rgba(var(--accent-rgb), 0.12);

    /* フォーム検証・結果バナーの状態色 */
    --error: #e5544e;
    --error-text: #ff8c87;
    --error-text-soft: #ffc9c5;
    --error-icon: #ff6b63;
    --success: #2ea05f;
    --success-text: #b9f5d0;
    --success-icon: #3ddc84;

    /* ブランドカラー（技術ロゴ由来。スキルバーとアイコン配色で共有） */
    --brand-php: #8b93d6;
    --brand-js: #f0db4f;
    --brand-css: #4aa3e0;
    --brand-python: #5fa9dc;
    /* (旧 --brand-ai は削除: 全参照を --accent-2 へ振り分け済みで消費者ゼロだった) */
    --brand-git: #f0623c;
    --brand-security: #5fc88f;
    --brand-security-rgb: 95, 200, 143; /* rgb(var(--brand-security-rgb)) 参照用 */
    --brand-discord: #7c84ff;
    --brand-x: #e8ebf0;       /* X (2023 rebrand 以降のモノクロブランド)。アイコン色 = --text 相当の白系 */
    --brand-x-hover: #1d9bf0; /* hover 時の border/glow は旧 Twitter 青で Twitter 派 nostalgia + GitHub 白系との差別化を確保 */
    --brand-gold: #f5b301;
    --brand-yt: #ff3d3d;
    --brand-github: #cdd5e0;
    --brand-keybase: #ff9d3d;
    --brand-zenn:          #3EA8FF;
    --brand-qiita:         #55C500;
    --brand-stackoverflow: #F58025;
    --brand-linkedin:      #0A66C2;
    --brand-bluesky:       #0285FF;
    --brand-misskey:       #A1CA03;
    /* V16: sponsor.css の Sponsor CTA (GitHub Sponsors 由来のピンク→ローズ) を昇格。
       -rgb 版は rgba(var(--brand-sponsor-rgb), .N) で glow / focus ring から参照。 */
    --brand-sponsor:       #ea4c89;
    --brand-sponsor-2:     #db61a2;
    --brand-sponsor-rgb:   234, 76, 137;
    --brand-database:      #4B7BA8;

    /* UI第2ヒュー。旧 --brand-ai と同値だが役割が別（見出しグラデ・ボタン・装飾リング用） */
    --accent-2: #a78bfa;
    --accent-2-rgb: 167, 139, 250;
    --warn: var(--brand-gold); /* 警戒色。旧 --sev-warn の参照先を明示的なセマンティックトークンに */

    /* Claude（Anthropic）本家ブランドカラー。--accent-2（サイト共通の紫UIアクセント）とは別トークンで管理 */
    --brand-claude: #d97757;      /* Claude 本家ブランドの Clay オレンジ */
    --brand-claude-rgb: 217, 119, 87;

    --radius: 12px;
    --radius-sm: 8px;
    /* 公開ページはrefine.cssがこの値を16px/10pxへ上書きする。admin/system（/admin, /system）は
       refine.cssを読まないためこの値(12px/8px)が実効値になる */
    /* 小型コントロール専用。refine.cssで --radius-sm が10pxに拡大されても、
       チップ/アイコンボタン等の小さな面はこの値(8px)に留める */
    --radius-xs: 8px;
    --font: 'Inter', 'Noto Sans JP', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
    /* 等幅（システム等幅スタック・外部CDN不使用）。code 要素や URL/ドメイン表記
       (.links-card-url / .domain-name 等) で使用中。 */
    --font-mono: ui-monospace, 'SF Mono', SFMono-Regular, Menlo, Consolas, 'Liberation Mono', 'DejaVu Sans Mono', monospace;
    --shadow: 0 10px 30px rgba(0, 0, 0, 0.35);

    /* ---- 追加トークン（2026-07 デザイン刷新「リビングインターフェース」） ---- */
    /* --accent-rgb は V15 で --accent-soft より前 (line 39) に前倒し済。
       (旧 --ai-rgb は削除: --accent-2-rgb と同値の消費者ゼロトークンだった) */
    /* 状態色/背景色の RGB 三つ組。rgba(var(--error-rgb), .N) 等で参照する */
    --error-rgb: 229, 84, 78;
    --success-rgb: 46, 160, 95;
    --gold-rgb: 245, 179, 1;
    --gold-bright: #ffd166; /* /system の警戒バッジ文字色。--brand-gold より明るい別トーン */
    --bg-rgb: 14, 18, 23;
    /* スクリム/シェードの基色統一（旧 rgba(5,8,12,) / (6,8,11,) / (10,14,20,) / (11,14,19,) の4系統を集約） */
    --scrim-rgb: 6, 9, 13;   /* オーバーレイ幕（モーダル/ドロワー背景）用 */
    --shade-rgb: 11, 14, 19; /* 画像下グラデーション（--bg-2と同値）用 */
    /* アクセント塗りの上に載せる文字色（旧 #06121f 直書きの名前化） */
    --on-accent: #06121f;

    /* エレベーション: 黒影3段 + 青発光2段（rest=sm / hover=shadow+glow / modal=lg+glow-strong） */
    --shadow-sm: 0 4px 14px rgba(0, 0, 0, 0.28);
    --shadow-lg: 0 24px 60px rgba(0, 0, 0, 0.5);
    /* V15b: dropdown/suggest メニュー用の中間 shadow (--shadow は 30px/0.35 でやや強く、
       --shadow-sm は 14px/0.28 で弱い。8px offset 24px blur/0.35 の中間帯を切り出す) */
    --shadow-menu: 0 8px 24px rgba(0, 0, 0, 0.35);
    --glow: 0 0 24px rgba(var(--accent-rgb), 0.16);
    --glow-strong: 0 0 36px rgba(var(--accent-rgb), 0.28);
    /* フォーム入力のフォーカスリング。admin.css は refine.css を読まないため、
       ここ(style.css)で定義して両方から参照できるようにする。 */
    --focus-ring: 0 0 0 3px var(--accent-soft);
    /* 小さな丸みのあるバッジ/タグ共通の余白(件数バッジ・番号バッジ・
       ロール/状態タグ・ログイン結果バッジ等)。admin/system も参照するため
       ここに置く。 */
    --badge-pad: 2px 9px;

    /* リフト量2段（旧 -1/-2/-4/-5px 混在の正規化） */
    --lift-sm: -2px;
    --lift: -4px;

    /* モーション3帯域: 応答 / 標準 / 登場。イージングは page-enter と同曲線に統一 */
    --dur-fast: 0.15s;
    --dur: 0.2s;
    --dur-slow: 0.45s;
    --ease-out: cubic-bezier(0.22, 1, 0.36, 1);
    --ease-spring: cubic-bezier(0.34, 1.4, 0.64, 1);

    /* 面の質感 */
    --edge-light: rgba(255, 255, 255, 0.05);
    /* ホバー/チップ背景の白ウォッシュ3段階（旧 0.03/0.05/0.055/0.06/0.07 等の直書きばらつきを
       集約する新規トークン。既存直書きの一括置換はしない。新規コードから段階的に採用する方針） */
    --wash-1: rgba(255, 255, 255, 0.03);
    --wash-2: rgba(255, 255, 255, 0.05);
    --wash-3: rgba(255, 255, 255, 0.07);

    /* 角丸の補完（999px 直書きの名前化） */
    --radius-pill: 999px;

    /* ナビ/フッターの広幅コンテナ（既存ハードコード 1200px の名前化） */
    --container-wide: 1200px;
    /* 本文最適幅 (V14): 70ch は refine.css の --measure と等価。
       760px は widget カード (.timeline / .ai-card / .policy-list / .contact-faq) の
       広幅本文用。1 の値変更で 4-5 箇所の広幅ブロックが自動追従する。 */
    --measure-wide: 760px;

    /* 見出しグラデの一元化（refine.css / error.css の重複実装を統合） */
    --grad-heading: linear-gradient(120deg, var(--accent-strong), var(--accent-2));
    --grad-rule: linear-gradient(90deg, var(--accent), var(--accent-strong) 55%, var(--accent-2));

    /* スペーシングスケール（4pxベース）。新規コードから段階的に採用する（既存の一括置換はしない） */
    --space-1: 4px;
    --space-2: 8px;
    --space-3: 12px;
    --space-4: 16px;
    --space-5: 20px;
    --space-6: 24px;
    --space-7: 32px;
    --space-8: 48px;
}

/* ---- ブレークポイント方針 ----
   〜380px: 最小幅の微調整 / 〜600-640px: スマホ縦 / 〜768px: ナビのドロワー切替 /
   〜860-900px: タブレット（グリッド段数） / 769px〜: デスクトップ。
   新規のメディアクエリは 380 / 600 / 768 / 860 のいずれかに寄せる（新値を増やさない）。 */

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

/* =====================================================================
   Base
   ===================================================================== */
html,
body {
    height: 100%;
    margin: 0;
    padding: 0;
}

/* 固定ナビにキーボードスクロール（Space/Page Down/Home/Tab フォーカス移動など）で
   コンテンツが潜らないよう、スクロールポート全体にナビ高分の上余白を敷く。
   マウスホイールの生スクロールには効かないが、ホイールで見切れた際もナビ側の
   背景で透過を抑える設計（.navbar の rgba）と合わせて多層で守る。 */
html {
    scroll-padding-top: calc(var(--header-height) + 16px);
}

body {
    min-height: 100%;
    display: flex;
    flex-direction: column;
    font-family: var(--font);
    font-size: 16px;
    line-height: 1.7;
    color: var(--text);
    background-color: var(--bg);
    -webkit-font-smoothing: antialiased;
    text-rendering: optimizeLegibility;
    /* body に overflow-x: hidden を敷くと、仕様上 overflow-y も visible→auto に
       引き上げられて body がスクロールコンテナ化し、環境によりホイール/PageDown が
       効かなくなる。clip はスクロールコンテナを作らないため、水平方向のはみ出しを
       抑えつつ通常のドキュメントスクロールを保てる。 */
    overflow-x: clip;
}

/* スキップリンク: 通常は画面外に隠し、フォーカス時のみ表示する */
.skip-link {
    position: absolute;
    left: 8px;
    top: -48px;
    z-index: 1000;
    padding: 8px 16px;
    border-radius: var(--radius-sm);
    background: var(--accent);
    color: var(--on-accent);
    font-weight: 600;
    text-decoration: none;
    transition: top var(--dur-fast) ease;
}

.skip-link:focus {
    top: 8px;
    outline: 2px solid var(--accent-strong);
    outline-offset: 2px;
    /* 後勝ちの :focus-visible (角丸のない要素の outline を丸める目的で
       border-radius:4px を持つ) が .skip-link 本体の --radius-sm と同詳細度
       (0,1,0) で書かれた行数が後のため勝ち、フォーカス時だけ角丸が変わって
       いた。ここは :focus 分クラスが増えて詳細度が上 (0,2,0) になるので
       明示すれば確実に勝つ。 */
    border-radius: var(--radius-sm);
    /* 後勝ちの :focus-visible に top を奪われないよう、ここで top を含めて明示し、
       スキップリンクのスライドイン（top のトランジション）を維持する。 */
    transition: top var(--dur-fast) ease, outline-offset var(--dur-fast) ease-out, outline-color var(--dur-fast) ease-out;
}

/* プログラム的にフォーカスを受けるコンテナ（main 等）には枠線を出さない */
[tabindex="-1"]:focus {
    outline: none;
}

/* 視覚的に隠すが読み上げは残すユーティリティ（全ページ共通） */
.visually-hidden {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

/* V16: リスト装飾の "純粋リセット" 共通化。
   list-style:none + margin:0 + padding:0 の 3 セット reset を必要とする
   セレクタを :where() (specificity 0) で 1 箇所にまとめる。個別ルール側で
   margin/padding を上書きしたい場合は詳細度勝ちで通常通り効く。
   HTML 側は無変更、各ページ CSS からは 3 行の reset を削除できる。
   注意: /system は style.css を読まないため sys-* セレクタは対象外
   (system.css 側で個別 reset を保持)。 */
:where(
    .experience-list,
    .value-list,
    .ai-list,
    .article-related-list,
    .community-stats,
    .community-roles,
    .contact-notes,
    .domain-list,
    .org-list,
    .timeline
) {
    list-style: none;
    margin: 0;
    padding: 0;
}

/* V17: アクセントピルバッジの基底 (V16 リストリセットと同じ :where() 手法)。
   「accent 枠 + accent-soft 地 + pill 角丸 + accent 文字」の同一見た目が
   6 ファイルに分散直書きされていたのを 1 箇所に集約。各ページ CSS には
   margin / padding / font-size / letter-spacing 等の差分だけを残す。
   バッジ色の変更はこの 1 ブロックで全ページ追従する。 */
:where(
    .count-badge,
    .section-count,
    .skills-badge,
    .works-count,
    .skills-count,
    .contact-faq-count,
    .now-updated,
    .now-entry-badge
),
/* 疑似要素は :where() の中に書けない (仕様上無効 → forgiving parsing で
   黙って破棄され、privacy の章番号が裸の数字になる回帰が実際に起きた)。
   セレクタリストの外に並記する。specificity は 0,2,0 になるが、この
   セレクタを上書きするページ側宣言は存在しないため実害なし。 */
.policy-item .card-title::before {
    border: 1px solid rgba(var(--accent-rgb), 0.28);
    border-radius: var(--radius-pill);
    background: var(--accent-soft);
    color: var(--accent);
    font-weight: 600;
    font-variant-numeric: tabular-nums;
}

/* V17: アイコンタイルの基底。「inline-flex 中央 + radius-sm + accent-soft 地」の
   同一土台が 5 ファイル 7 定義に反復していたのを集約。ページ側は width/height/
   font-size/margin 等のみ。refine.css G ブロック (グラデ格上げ + ホバー) も
   同じセレクタ群を :is() で列挙している — タイルを増やす時はここと G の 2 箇所。 */
:where(
    .ai-card-icon,
    .stat-icon,
    .role-icon,
    .ai-flow-icon,
    .stack-card-icon,
    .tool-card-icon
) {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: var(--radius-sm);
    background: var(--accent-soft);
    color: var(--accent);
}

/* very subtle ambient glow behind the top of the page — calm, not flashy */
body::before {
    content: "";
    position: fixed;
    inset: 0;
    z-index: -1;
    pointer-events: none;
    background:
        radial-gradient(60% 50% at 75% -5%, rgba(var(--accent-rgb), 0.12), transparent 60%),
        radial-gradient(55% 45% at 12% 2%, rgba(var(--accent-rgb), 0.07), transparent 58%);
}

a {
    color: var(--accent);
    text-decoration: none;
    transition: color var(--dur) ease;
}

a:hover {
    color: var(--accent-strong);
}

::selection {
    background: rgba(var(--accent-rgb), 0.4);
    color: var(--text);
}

/* 入力欄のプレースホルダーをテーマのミュート色に統一（Firefox の既定は
   透明度が下がるため opacity:1 で揃える）。 */
::placeholder {
    color: var(--dim);
    opacity: 1;
}

:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
    border-radius: 4px;
    /* キーボード操作時にアウトラインがスッと寄る程度の軽い遷移（可視性は犠牲にしない）。 */
    transition: outline-offset var(--dur-fast) ease-out, outline-color var(--dur-fast) ease-out;
}

/* タップ時のハイライトをテーマ色に揃える（既定の半透明黒は暗背景で目立ちすぎる） */
a,
button,
label,
summary {
    -webkit-tap-highlight-color: rgba(var(--accent-rgb), 0.18);
}

/* 操作系はダブルタップズーム待ち（約300ms）を無効化して反応を機敏にする */
.btn,
.card-link,
.social-btn,
.nav-toggle-btn,
.card-detail-btn,
.back-to-top,
summary {
    touch-action: manipulation;
}

img {
    max-width: 100%;
}

.fa-icon {
    width: 1em;
    height: 1em;
    fill: currentColor;
    display: inline-block;
    vertical-align: -0.125em;
    flex-shrink: 0;
}


/* =====================================================================
   Main layout
   ===================================================================== */
main {
    flex: 1;
}

main.left {
    display: block;
    text-align: left;
    padding-top: var(--header-height);
}

/* =====================================================================
   Navigation
   ===================================================================== */
.navbar {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: var(--header-height);
    z-index: 1000;
    display: flex;
    justify-content: center;
    align-items: center;
    border-bottom: 1px solid var(--border);
    /* スクロール中にナビ裏の本文（画像内のキャッチコピー等）が透けて見えないよう、
       非対応環境でも実質的に不透明に近い塗りにする。 */
    background: rgba(var(--bg-rgb), 0.95);
}

@supports ((backdrop-filter: blur(8px)) or (-webkit-backdrop-filter: blur(8px))) {
    .navbar {
        /* backdrop-filter で背後がぼけるぶん透過を強められるが、
           透け見えの解消を優先して不透明寄りに上げる。 */
        background: rgba(var(--bg-rgb), 0.88);
        -webkit-backdrop-filter: blur(12px) saturate(140%);
        backdrop-filter: blur(12px) saturate(140%);
    }
}

.nav-container {
    display: flex;
    justify-content: space-between;
    align-items: center;
    width: 100%;
    max-width: var(--container-wide);
    margin: 0 auto;
    /* viewport-fit=cover 端末で、ノッチ/丸角に内容が潜らないよう左右に safe-area を確保 */
    padding: 0 max(1.8rem, env(safe-area-inset-right)) 0 max(1.8rem, env(safe-area-inset-left));
    height: 100%;
}

.nav-logo {
    font-size: 1.3rem;
    font-weight: 700;
    letter-spacing: -0.01em;
    color: var(--text);
    text-decoration: none;
}

.nav-logo:hover {
    color: var(--text);
}

.nav-menu {
    list-style: none;
    display: flex;
    gap: 0.4rem;
    margin: 0;
    padding: 0;
}

.nav-menu li a {
    position: relative;
    color: var(--muted);
    text-decoration: none;
    font-size: 0.92rem;
    font-weight: 600;
    padding: 8px 12px;
    border-radius: var(--radius-sm);
    transition: color var(--dur) ease, background var(--dur) ease;
}

.nav-menu li a::after {
    content: "";
    position: absolute;
    left: 12px;
    right: 12px;
    bottom: 4px;
    height: 2px;
    border-radius: 2px;
    background: var(--accent);
    opacity: 0;
    transform: scaleX(0);
    transform-origin: center;
    transition: transform 0.18s ease-out, opacity 0.18s ease-out;
}

.nav-menu li a:hover,
.nav-menu li a:focus-visible {
    color: var(--text);
}

.nav-menu li a:hover::after,
.nav-menu li a:focus-visible::after {
    opacity: 1;
    transform: scaleX(1);
}

/* Scroll-spy active item (JS adds .is-active) / current page (aria-current) */
.nav-menu li a.is-active,
.nav-menu li a[aria-current] {
    color: var(--text);
}

.nav-menu li a.is-active::after,
.nav-menu li a[aria-current]::after {
    opacity: 1;
    transform: scaleX(1);
}

/* Mobile nav toggle
   非JSでもキーボードで開閉できるよう「見えないがフォーカス可能」に隠す
   （display:none だと非JS時にキーボード操作の手段が無くなる）。
   JS有効時は script.js が tabindex=-1 / aria-hidden を付けてタブ順から外す。 */
.nav-toggle {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

/* デスクトップではトグル自体が不要 */
@media (min-width: 769px) {
    .nav-toggle { display: none; }
}

/* チェックボックスへのフォーカスは、視覚上のボタン（label）にリングを出して示す */
.nav-toggle:focus-visible + .nav-toggle-btn {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
    border-radius: var(--radius-sm);
}

.nav-toggle-btn {
    display: none;
    width: 44px;
    height: 44px;
    align-items: center;
    justify-content: center;
    flex-direction: column;
    cursor: pointer;
}

.nav-toggle-btn span {
    display: block;
    width: 24px;
    height: 2px;
    background: var(--text);
    border-radius: 2px;
    margin: 3px 0;
    transform-origin: center;
    transition: transform 0.32s var(--ease-spring), opacity 0.18s ease;
}

/* =====================================================================
   Hero
   ===================================================================== */
.hero {
    max-width: var(--container-max);
    margin: 0 auto;
    padding: 64px 20px 40px;
}

.hero-container {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 48px;
}

.hero-left {
    flex: 1 1 auto;
    min-width: 0;
}

.hero-eyebrow {
    margin: 0 0 10px;
    font-size: 0.95rem;
    font-weight: 600;
    letter-spacing: 0.02em;
    color: var(--accent);
}

#typewriter,
.hero-name {
    margin: 0 0 14px;
    font-size: clamp(2.3rem, 6vw, 3.4rem);
    font-weight: 700;
    line-height: 1.1;
    letter-spacing: -0.02em;
    color: var(--text);
}

.subtext {
    font-size: 1.15rem;
    margin: 0 0 26px;
    color: var(--muted);
    min-height: 1.6em;
}

/* Existing typewriter target — DO NOT rename id/class (#hero-typed/.typed-text/.is-idle) */
.typed-text {
    display: inline;
    color: var(--text);
    position: relative;
}

.typed-text::after {
    content: '';
    display: inline-block;
    width: 2px;
    height: 1.05em;
    margin-left: 5px;
    vertical-align: text-bottom;
    background: var(--accent);
    animation: caret-blink 1s steps(1, end) infinite;
}

.typed-text.is-idle::after {
    opacity: 0;
    animation: none;
}

@keyframes caret-blink {
    0%, 49% { opacity: 1; }
    50%, 100% { opacity: 0; }
}

.hero-right {
    flex: 0 0 auto;
    display: flex;
    justify-content: center;
}

.profile-icon {
    width: 220px;
    height: 220px;
    border-radius: 50%;
    object-fit: cover;
    border: 3px solid var(--border-bright);
    box-shadow: var(--shadow);
    transition: transform 0.3s ease, border-color 0.3s ease;
}

.profile-icon:hover {
    transform: translateY(var(--lift)); /* V15: -4px 直書き → token */
    border-color: var(--accent);
}

/* =====================================================================
   Social buttons
   ===================================================================== */
.social-bar {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}

.social-btn {
    --brand: var(--accent);
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 9px 15px;
    font-size: 0.9rem;
    /* ラベルは X/GitHub/YouTube 等の固有名詞で Latin 専用のため Inter 600 のまま */
    font-weight: 600;
    border-radius: var(--radius-sm);
    border: 1px solid var(--border);
    background: var(--surface);
    color: var(--text);
    text-decoration: none;
    transition: border-color var(--dur) ease, background var(--dur) ease, transform var(--dur-fast) ease, color var(--dur) ease;
}

.social-btn .fa-icon {
    font-size: 1.05rem;
    /* 常時ブランド色でアイコンを表示（ホバー待たずに視認できる）。
       transition の詳細は refine.css 側で spring 曲線に上書きする。 */
    color: var(--brand);
    transition: color var(--dur) ease, transform var(--dur) ease, filter var(--dur) ease;
}

.social-btn:hover,
.social-btn:focus-visible {
    transform: translateY(var(--lift-sm)); /* V15: -2px 直書き → token */
    border-color: var(--brand);
    background: var(--surface-2);
    color: var(--text);
}

.social-btn:hover .fa-icon,
.social-btn:focus-visible .fa-icon {
    color: var(--brand);
}

.social-btn.x       { --brand: var(--brand-x);       --brand-glow: var(--brand-x-hover); }
.social-btn.github  { --brand: var(--brand-github); }
.social-btn.yt      { --brand: var(--brand-yt); }
.social-btn.discord { --brand: var(--brand-discord); }
.social-btn.keybase { --brand: var(--brand-keybase); }

/* rest 状態の常時 brand tint (border + halo) は refine.css 側の .social-btn base 直後に
   同居させる (refine が style.css より後発ロードのため specificity 同値では refine が勝ち、
   ここで書いても効かない)。 */

/* =====================================================================
   Sections
   ===================================================================== */
.section {
    padding: 72px 20px;
}

.section-container {
    max-width: var(--container-max);
    margin: 0 auto;
}

section[id] {
    scroll-margin-top: calc(var(--header-height) + 16px);
}

/* ページ内目次（about/projects の .page-toc 共通）。main.left 直下に置かれても
   本文（hero/section）と左端が揃うようコンテナ制約を共通化。チップ等の見た目は
   各ページCSSの .page-toc ul / .page-toc a が担当。 */
.page-toc {
    max-width: var(--container-max);
    margin-left: auto;
    margin-right: auto;
    padding-left: 20px;
    padding-right: 20px;
}

.section-title {
    position: relative;
    font-size: 1.9rem;
    font-weight: 700;
    letter-spacing: -0.01em;
    /* V15: 28 → 32 (--space-7) で 4px グリッドに乗せる。他の見出し下余白 22/26
       とも足並みが揃う (別途 hero-blurb を 24 に降ろす予定) */
    margin: 0 0 var(--space-7);
    color: var(--text);
}

/* accent underline — index only (keeps 404 title plain & centered) */
main.left .section-title {
    padding-bottom: 12px;
}

main.left .section-title::after {
    content: "";
    position: absolute;
    left: 0;
    bottom: 0;
    width: 56px;
    height: 3px;
    border-radius: 3px;
    background: var(--accent);
}

/* =====================================================================
   About
   ===================================================================== */
.about-text {
    font-size: 1.1rem;
    line-height: 1.95;
    color: var(--muted);
    max-width: var(--measure); /* refine.cssの--measure(70ch)に統一 */
    margin: 0;
}

.about-text .hl {
    color: var(--text);
    font-weight: 600;
}

/* =====================================================================
   Projects — project cards
   ===================================================================== */
.cards {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 20px;
}

.card {
    position: relative;
    overflow: hidden;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: var(--space-6);
    /* インタラクティブ要素で ease-out / ~0.2s に揃え、手触りを一貫させる。 */
    transition: transform var(--dur) var(--ease-out), border-color var(--dur) var(--ease-out), box-shadow var(--dur) var(--ease-out);
}

.card::before {
    content: "";
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: 3px;
    background: var(--accent);
    transform: scaleX(0);
    transform-origin: left;
    transition: transform 0.3s ease;
    z-index: 2;
}

.card:hover {
    /* -5px は他 hover 全て --lift (-4px) に統一済のなか唯一の残り。1px 差の
       意匠差はなくトークン統一を優先 (視覚差はほぼ検知不可)。 */
    transform: translateY(var(--lift));
    border-color: var(--border-bright);
    box-shadow: var(--shadow);
}

.card:hover::before {
    transform: scaleX(1);
}

.card-title {
    margin: 0 0 10px;
    font-size: 1.2rem;
    /* Noto Sans JP に 600 実体が無く 700 にフォールバックされるため、和文主体のこの見出しは指定を実体に合わせる */
    font-weight: 700;
    color: var(--text);
}

.cards .card-title a {
    color: var(--text);
    text-decoration: none;
    transition: color var(--dur) ease;
}

.cards .card-title a:hover {
    color: var(--accent);
}

.card.is-pending .card-title {
    color: var(--muted);
}

.card-text {
    margin: 0;
    font-size: 0.98rem;
    line-height: 1.75;
    color: var(--muted);
}

.card-tag {
    display: inline-block;
    font-size: 0.74rem;
    font-weight: 600;
    letter-spacing: 0.03em;
    color: var(--accent);
    background: var(--accent-soft);
    border-radius: var(--radius-pill);
    padding: 3px 12px;
}

.card.is-pending .card-tag {
    color: var(--dim);
    background: rgba(255, 255, 255, 0.04);
}

/* Rich work cards: full-bleed thumbnail on top, actions pinned to the bottom */
.work-card {
    display: flex;
    flex-direction: column;
    padding: 0;
}

/* 詳細を持つカードは全体がクリックで開く（準備中カードは除く） */
.work-card:not(.is-pending) {
    cursor: pointer;
}

.work-card .card-body {
    flex: 1;
    padding: 20px var(--space-6) 0;
}

.work-card > .card-meta {
    margin-top: auto;
    padding: 16px var(--space-6) 20px;
}

/* 状態バッジ（公開中/準備中）は、年・担当などのメタ情報がある場合だけ右端へ寄せる。
   準備中カードはバッジ単独なので :first-child を除外して左のままにする。 */
.work-card > .card-meta .card-tag:not(:first-child) {
    margin-left: auto;
}

/* Site preview thumbnail */
.card-thumb {
    position: relative;
    aspect-ratio: 16 / 9;
    overflow: hidden;
    background: var(--surface-2);
    border-bottom: 1px solid var(--border);
}

.card-thumb img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: top center;
    display: block;
    transition: transform 0.4s ease;
}

.work-card:hover .card-thumb img {
    transform: scale(1.04);
}

.card-thumb.is-placeholder,
.card-thumb.is-failed {
    display: flex;
    align-items: center;
    justify-content: center;
    background-color: var(--surface-2);
    color: var(--accent);
    font-size: 1.8rem;
}

/* Tech stack chips: チップ自体はニュートラルに保ち、アイコンだけ各技術のイメージ色を載せる */
.tech-tags {
    list-style: none;
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    margin: 14px 0 0;
    padding: 0;
}

.tech-tags li {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    font-size: 0.74rem;
    font-weight: 400;
    color: var(--muted);
    background: rgba(255, 255, 255, 0.04);
    border: 1px solid var(--border);
    border-radius: 6px;
    padding: 3px 9px;
}

.tech-tags li .fa-icon {
    font-size: 0.85rem;
    color: var(--muted);
}

/* リンク化された tech-tag (render_tech_tags が link 付き項目に付与)。
   Skills「関心のある領域」など、そのキーワードに対応するページへ回遊させる。
   <li> の枠内で <a> がフルクリック領域を持つよう block ふるまいに寄せる。 */
.tech-tags li:has(> .tech-tag-link) {
    padding: 0;
}

.tech-tag-link {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 3px 9px;
    color: inherit;
    text-decoration: none;
    border-radius: 6px;
    transition: color var(--dur-fast) var(--ease-out), background var(--dur-fast) var(--ease-out);
}

.tech-tag-link:hover,
.tech-tag-link:focus-visible {
    color: var(--text);
    background: rgba(var(--accent-rgb), 0.1);
}

/* ピル型 tech-tags（Skills「言語/ツール」・「触ってみたい/関心」・AI ツールベルトで共有）。
   ページ側で位置調整（margin など）は個別に足す。ここは色・地・角の共通定義のみ。
   寸法(font-size/padding/gap)はサイズ別に skills-next だけ小さめに個別上書き。 */
.skills-stack .tech-tags,
.skills-next .tech-tags,
.ai-toolbelt .tech-tags {
    gap: 10px;
}

.skills-stack .tech-tags li,
.skills-next .tech-tags li,
.ai-toolbelt .tech-tags li {
    border-radius: var(--radius-pill);
    border-color: var(--border-bright);
    background: linear-gradient(180deg, rgba(255, 255, 255, 0.04), rgba(255, 255, 255, 0.01));
}

/* 大きめサイズ（デフォルト）: 「言語/ツール」「AI ツールベルト」 */
.skills-stack .tech-tags li,
.ai-toolbelt .tech-tags li {
    font-size: 0.95rem;
    padding: 10px 18px;
    gap: 10px;
}

.skills-stack .tech-tags li .fa-icon,
.ai-toolbelt .tech-tags li .fa-icon {
    font-size: 1.1rem;
}

/* tech-tag アイコンのブランド色（★単一の真実源）。
   tech-tags チップ内のアイコンだけを技術/ブランド固有色にする。
   新しいタグ色を足す・変えるときは "ここだけ" に1行。他ファイル
   （skills.css / console.css 等）に分散させないこと（＝一部だけ色が
   抜ける不整合を防ぐ）。色トークンは :root の --brand-* を参照。 */
.tech-tags li .fa-icon.fa-php           { color: var(--brand-php); }
.tech-tags li .fa-icon.fa-js            { color: var(--brand-js); }
.tech-tags li .fa-icon.fa-css3-alt      { color: var(--brand-css); }
.tech-tags li .fa-icon.fa-python        { color: var(--brand-python); }
.tech-tags li .fa-icon.fa-claude        { color: var(--brand-claude); }
.tech-tags li .fa-icon.fa-git-alt       { color: var(--brand-git); }
.tech-tags li .fa-icon.fa-shield-halved { color: var(--brand-security); }
.tech-tags li .fa-icon.fa-github        { color: var(--text); }
.tech-tags li .fa-icon.fa-database      { color: var(--brand-database); }
.tech-tags li .fa-icon.fa-x-twitter     { color: var(--brand-x); }
.tech-tags li .fa-icon.fa-discord       { color: var(--brand-discord); }
.tech-tags li .fa-icon.fa-crown         { color: var(--brand-gold); }
.tech-tags li .fa-icon.fa-handshake     { color: var(--brand-gold); }

/* Meta row (year / role / status) */
.card-meta {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 12px;
    margin-top: 16px;
}

.card-meta-item {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    font-size: 0.78rem;
    color: var(--dim);
}

.card-meta-item .fa-icon {
    font-size: 0.8rem;
}

/* Card action links/buttons */
.card-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    margin-top: 18px;
}

.work-card .card-actions {
    margin-top: auto;
    padding: 16px var(--space-6) 20px;
}

.card-link {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-family: var(--font);
    font-size: 0.82rem;
    font-weight: 600;
    color: var(--text);
    background: var(--surface-2);
    border: 1px solid var(--border);
    border-radius: var(--radius-xs);
    padding: 7px 12px;
    text-decoration: none;
    cursor: pointer;
    transition: border-color var(--dur) ease, background var(--dur) ease, color var(--dur) ease, transform var(--dur-fast) ease;
}

.card-link:hover,
.card-link:focus-visible {
    border-color: var(--accent);
    color: var(--accent);
    transform: translateY(var(--lift-sm));
}

.card-link .fa-icon {
    font-size: 0.8rem;
}

/* 「詳細」ボタン = モーダルを開くアフォーダンス。サイト/Code リンクから右側に
   分離（誤タップ防止）し、accent で色づけして「開ける」ことを明確にする。
   .card-link 系より後ろに置き、ホバー時の塗りつぶしが効くようにしている。 */
.card-actions .card-detail-btn {
    margin-left: auto;
    color: var(--accent-strong);
    border-color: rgba(var(--accent-rgb), 0.4);
}

/* カード全体タップで開くことが伝わるよう、カードのホバー時に詳細ボタンを際立たせる。 */
.work-card:not(.is-pending):hover .card-detail-btn,
.timeline-content:hover .card-detail-btn {
    border-color: var(--accent);
    color: var(--accent-strong);
}

.card-detail-btn:hover,
.card-detail-btn:focus-visible {
    background: var(--accent);
    border-color: var(--accent);
    color: var(--on-accent);
    transform: translateY(var(--lift-sm));
}

.card-detail-btn:hover .fa-icon,
.card-detail-btn:focus-visible .fa-icon {
    color: inherit;
}

/* =====================================================================
   Work detail modal (<dialog>)
   ===================================================================== */
.work-detail[hidden] {
    display: none;
}

.work-modal {
    margin: auto;
    padding: 0;
    border: none;
    background: transparent;
    max-width: 580px;
    width: calc(100% - 32px);
    color: var(--text);
    overflow: visible;
}

.work-modal::backdrop {
    background: rgba(var(--scrim-rgb), 0.72);
    -webkit-backdrop-filter: blur(3px);
    backdrop-filter: blur(3px);
}

.work-modal-inner {
    position: relative;
    background: var(--surface);
    border: 1px solid var(--border-bright);
    border-radius: var(--radius);
    box-shadow: var(--shadow);
    padding: 30px 28px;
    max-height: 85vh;
    overflow-y: auto;
    overscroll-behavior: contain;
    /* 既定の太いスクロールバーが目立たないよう、細く控えめにする（Firefox）。 */
    scrollbar-width: thin;
    scrollbar-color: var(--border-bright) transparent;
}

/* 控えめなスクロールバー（WebKit/Chrome）。トラックは透明、つまみは細く角丸。 */
.work-modal-inner::-webkit-scrollbar {
    width: 10px;
}

.work-modal-inner::-webkit-scrollbar-track {
    background: transparent;
}

.work-modal-inner::-webkit-scrollbar-thumb {
    background: var(--border-bright);
    border-radius: var(--radius-pill);
    border: 3px solid transparent;
    background-clip: padding-box;
}

.work-modal-inner::-webkit-scrollbar-thumb:hover {
    background: var(--dim);
    background-clip: padding-box;
}

/* 閉じる(×)ボタン: サムネイル画像の上でも埋もれないよう、暗い半透明チップ＋影で
   常にコントラストを確保し、サムネイルより前面(z-index)に出す。 */
.work-modal-close {
    position: absolute;
    top: 14px;
    right: 14px;
    z-index: 3;
    width: 36px;
    height: 36px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: rgba(var(--bg-rgb), 0.72);
    -webkit-backdrop-filter: blur(6px);
    backdrop-filter: blur(6px);
    border: 1px solid var(--border-bright);
    border-radius: var(--radius-xs);
    color: var(--text);
    cursor: pointer;
    box-shadow: 0 2px 10px rgba(0, 0, 0, 0.4);
    transition: color var(--dur) ease, border-color var(--dur) ease, background var(--dur) ease;
}

.work-modal-close:hover,
.work-modal-close:focus-visible {
    color: var(--text);
    background: var(--surface-2);
    border-color: var(--accent);
}

.work-modal-body h3 {
    margin: 0 6px 6px 0;
    padding-right: 36px;
    font-size: 1.45rem;
    font-weight: 700;
    color: var(--text);
}

.work-modal-body h4 {
    margin: 22px 0 8px;
    font-size: 1rem;
    font-weight: 600;
    color: var(--text);
}

.work-modal-body p {
    margin: 0 0 12px;
    font-size: 0.98rem;
    line-height: 1.85;
    color: var(--muted);
}

.work-modal-body .work-detail-lead {
    color: var(--text);
    font-weight: 400;
}

.work-modal-body .card-actions {
    margin-top: 24px;
}

.work-modal-body .card-thumb {
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    margin-bottom: 18px;
}

/* ケーススタディの要点（課題 / 工夫 / 取り組み）。ラベルをアクセントチップにして
   モーダル内で素早く読めるようにする。データに highlights があるときだけ出る。 */
.work-modal-body .work-detail-highlights {
    margin: 0 0 18px;
    display: grid;
    gap: 10px;
}

.work-modal-body .wd-highlight {
    display: grid;
    grid-template-columns: auto 1fr;
    align-items: start;
    gap: 12px;
    margin: 0;
    padding: 12px 14px;
    background: var(--surface-2);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
}

.work-modal-body .wd-highlight-label {
    /* padding/pill角丸/accent-soft地は .card-tag と共通のため、ここでは差分だけ持つ */
    margin: 0;
    font-weight: 700;
    white-space: nowrap;
}

.work-modal-body .wd-highlight-text {
    margin: 0;
    font-size: 0.95rem;
    line-height: 1.75;
    color: var(--muted);
}

/* =====================================================================
   Skills — smooth progress bars
   ===================================================================== */
.skills-grid {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 22px;
    align-items: start;
}

.skills-graph {
    display: flex;
    flex-direction: column;
    gap: 20px;
    margin-top: 20px;
}

/* メーターロウ: 左にブランド色のアイコンタイル、右に「名前+% / バー」。
   タイルはサイト共通のアイコンタイル語彙（stack-card-icon 等）と同族。 */
.skill {
    display: flex;
    flex-direction: row;
    align-items: center;
    gap: 14px;
}

.skill-icon {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 44px;
    height: 44px;
    border-radius: var(--radius-sm);
    color: var(--brand, var(--accent));
    background: var(--accent-soft);
    border: 1px solid var(--border);
    transition: transform var(--dur) ease;
}

.skill-icon .fa-icon {
    font-size: 1.25rem;
}

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

.skill-head {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 12px;
}

.skill-name {
    display: inline-flex;
    align-items: center;
    gap: 10px;
    font-weight: 600;
    font-size: 1rem;
    color: var(--text);
}

.skill-percentage {
    font-size: 1rem;
    font-weight: 700;
    color: var(--brand, var(--accent));
    font-variant-numeric: tabular-nums;
}

.skill-bar {
    height: 12px;
    border-radius: var(--radius-pill);
    background: rgba(255, 255, 255, 0.06);
    overflow: hidden;
}

.skill-level {
    height: 100%;
    width: var(--lvl, 0%);
    border-radius: var(--radius-pill);
    background-color: var(--brand, var(--accent));
    background-image: linear-gradient(90deg, rgba(0, 0, 0, 0.28), rgba(255, 255, 255, 0.14));
    transition: width 1.1s var(--ease-out), filter var(--dur) ease;
}

.skill:hover .skill-icon {
    transform: scale(1.08);
}

.skill:hover .skill-level {
    filter: brightness(1.1);
}

/* With JS, bars start empty and fill on scroll-in. Without JS the inline
   --lvl renders full, so the values are never lost. */
body.js .skills-graph .skill-level { width: 0; }
body.js .skills-graph.in-view .skill-level { width: var(--lvl, 0%); }

/* タッチ端末ではタップ後に :hover が貼り付き、カードが浮いたまま残るのを防ぐ。
   既存のホバー（.card / .work-card / .timeline-content）は壊さず、hover を持たない
   端末でのみ浮き上がり/移動の transform を無効化する（マウス環境はそのまま）。 */
@media (hover: none) {
    .card:hover,
    .work-card:hover .card-thumb img,
    .timeline-content:hover {
        transform: none;
    }
}

/* タッチ主体の端末ではカード導線（サイト/Code/詳細）のタップ高を44pxに拡大。
   マウス環境の見た目は変えない。 */
@media (pointer: coarse) {
    .card-link {
        min-height: 44px;
        padding-top: 10px;
        padding-bottom: 10px;
    }
}

/* =====================================================================
   Scroll reveal — 主要ブロックをスクロールでふわっと表示（控えめ）
   JS が .reveal を付けて初期非表示にし、交差時に .is-revealed で表示する。
   初期の非表示状態は body.js 下でのみ適用 → 非JSでは常に全表示（グレースフル）。
   ===================================================================== */
body.js .reveal {
    opacity: 0;
    transform: translateY(10px);
    transition: opacity var(--dur-slow) var(--ease-out), transform var(--dur-slow) var(--ease-out);
}

/* 合成ヒントは表示前の要素にだけ与え、reveal 完了後（.is-revealed）は自動で解除する
   （恒久付与による無駄な合成レイヤー保持を避ける）。 */
body.js .reveal:not(.is-revealed) {
    will-change: opacity, transform;
}

body.js .reveal.is-revealed {
    opacity: 1;
    transform: none;
}

/* =====================================================================
   Buttons (shared with 404)
   ===================================================================== */
.btn-group {
    display: flex;
    gap: 12px;
    flex-wrap: wrap;
    align-items: center;
}

.btn {
    display: inline-flex;
    align-items: center;
    gap: 9px;
    padding: 12px 22px;
    border-radius: var(--radius-sm);
    border: 1px solid transparent;
    background: var(--surface);
    color: var(--text);
    font-family: var(--font);
    font-size: 0.98rem;
    /* Noto Sans JP に 600 実体が無く 700 にフォールバックされるため、和文ラベルが多いボタンは指定を実体に合わせる */
    font-weight: 700;
    text-decoration: none;
    cursor: pointer;
    transition: background var(--dur) ease-out, transform 0.18s ease-out, box-shadow var(--dur) ease-out, border-color var(--dur) ease-out;
}

.btn:hover {
    transform: translateY(var(--lift-sm)); /* V15: -2px 直書き → token */
}

/* 押し込みは素早く沈める（スナッピーな手触り）。離すと上の transition で滑らかに戻る。 */
.btn:active {
    transform: translateY(0);
    transition-duration: 0.06s;
}

.btn-primary {
    background: var(--accent);
    color: var(--on-accent);
    border-color: var(--accent);
}

.btn-primary:hover {
    background: var(--accent-strong);
    box-shadow: 0 8px 22px rgba(var(--accent-rgb), 0.3);
}

.btn-primary .fa-icon {
    color: inherit;
}

/* =====================================================================
   Contact
   ===================================================================== */
.contact-lead {
    font-size: 1.08rem;
    color: var(--muted);
    margin: 0 0 22px;
}

/* ---- Contact form ---- */
.contact-form {
    max-width: 680px;
}

.form-row {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 16px;
}

.form-field {
    display: flex;
    flex-direction: column;
    gap: 7px;
    margin-bottom: 18px;
}

.form-field label {
    font-size: 0.9rem;
    /* Noto Sans JP に 600 実体が無く 700 にフォールバックされるため、和文ラベルは指定を実体に合わせる */
    font-weight: 700;
    color: var(--text);
}

.form-field .req {
    color: var(--accent);
    margin-left: 2px;
}

.contact-form input,
.contact-form textarea {
    width: 100%;
    font-family: var(--font);
    /* 16px 未満だと iOS Safari がフォーカス時に自動ズームするため 1rem(16px) を維持する */
    font-size: 1rem;
    color: var(--text);
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    padding: 11px 14px;
    transition: border-color var(--dur) ease, background var(--dur) ease, box-shadow var(--dur) ease;
}

.contact-form input::placeholder,
.contact-form textarea::placeholder {
    color: var(--dim);
}

.contact-form textarea {
    min-height: 140px;
    line-height: 1.7;
    resize: vertical;
}

.contact-form input:focus,
.contact-form textarea:focus {
    outline: none;
    border-color: var(--accent);
    background: var(--surface-2);
    box-shadow: var(--focus-ring);
}

.contact-form input[aria-invalid="true"],
.contact-form textarea[aria-invalid="true"] {
    border-color: var(--error);
    box-shadow: 0 0 0 3px rgba(var(--error-rgb), 0.14);
}

.field-error {
    margin: 0;
    font-size: 0.82rem;
    color: var(--error-text);
}

.form-actions {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 18px;
    margin-top: 4px;
}

.form-privacy {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    margin: 0;
    font-size: 0.8rem;
    color: var(--dim);
}

.form-privacy .fa-icon {
    color: var(--muted);
}

/* Result banners */
.form-alert {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    margin-bottom: 22px;
    padding: 13px 16px;
    font-size: 0.92rem;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
}

.form-alert .fa-icon {
    margin-top: 2px;
    font-size: 1.05rem;
}

.form-alert-success {
    color: var(--success-text);
    background: rgba(var(--success-rgb), 0.12);
    border-color: rgba(var(--success-rgb), 0.4);
}

.form-alert-success .fa-icon {
    color: var(--success-icon);
}

.form-alert-error {
    color: var(--error-text-soft);
    background: rgba(var(--error-rgb), 0.1);
    border-color: rgba(var(--error-rgb), 0.4);
}

.form-alert-error .fa-icon {
    color: var(--error-icon);
}

/* Honeypot — removed from the visual & a11y flow, still submitted for bots */
.hp-field {
    position: absolute;
    left: -9999px;
    width: 1px;
    height: 1px;
    overflow: hidden;
}

@media (max-width: 600px) {
    .form-row {
        grid-template-columns: 1fr;
        gap: 0;
    }
}

/* =====================================================================
   Privacy policy
   ===================================================================== */
/* レイアウト本体 (display/max-width/margin-top) は privacy.php でのみ使う
   クラスのため privacy.css 側に集約済み。ここでは style.css で共有する
   .policy-item の文字周りだけ残す。 */

.policy-item .card-title {
    margin-bottom: 10px;
}

.policy-item .card-text {
    color: var(--muted);
    margin: 0 0 10px;
}

.policy-item .card-text:last-child {
    margin-bottom: 0;
}

.policy-points {
    margin: 0 0 10px;
    padding-left: 1.2em;
    color: var(--muted);
    font-size: 0.96rem;
    line-height: 1.85;
}

.policy-points:last-child {
    margin-bottom: 0;
}

.policy-points strong {
    color: var(--text);
    font-weight: 600;
}

.policy-item code {
    font-family: var(--font-mono);
    font-size: 0.85em;
    color: var(--accent-strong);
    background: var(--accent-soft);
    border-radius: 4px;
    padding: 1px 6px;
}

/* =====================================================================
   Footer
   ===================================================================== */
.site-footer {
    width: 100%;
    border-top: 1px solid var(--border);
    background: var(--bg-2);
    color: var(--text);
}

.footer-container {
    max-width: var(--container-wide);
    margin: 0 auto;
    padding: 1.6rem 1.8rem;
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    gap: 6px;
}

.copyright {
    color: var(--muted);
    margin: 0;
    font-size: 0.85rem;
}

.last-updated {
    margin: 0;
    font-size: 0.76rem;
    color: var(--dim);
    font-variant-numeric: tabular-nums;
}

/* =====================================================================
   Back-to-top floating button (JS-generated)
   ===================================================================== */
.back-to-top {
    position: fixed;
    right: max(20px, env(safe-area-inset-right));
    bottom: max(20px, env(safe-area-inset-bottom));
    z-index: 900;
    width: 44px;
    height: 44px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    border: 1px solid var(--border-bright);
    border-radius: 50%;
    background: var(--surface);
    color: var(--text);
    cursor: pointer;
    box-shadow: var(--shadow);
    opacity: 0;
    transform: translateY(12px);
    pointer-events: none;
    transition: opacity 0.25s ease, transform 0.25s ease, background var(--dur) ease, border-color var(--dur) ease, color var(--dur) ease;
}

.back-to-top.is-visible {
    opacity: 1;
    transform: none;
    pointer-events: auto;
}

.back-to-top:hover,
.back-to-top:focus-visible {
    background: var(--accent);
    border-color: var(--accent);
    color: var(--on-accent);
}

.back-to-top .fa-icon {
    font-size: 1.05rem;
}

/* =====================================================================
   Responsive
   ===================================================================== */
@media (max-width: 860px) {
    .skills-grid { grid-template-columns: 1fr; }
    .cards { grid-template-columns: 1fr 1fr; }
}

@media (max-width: 768px) {
    .nav-toggle-btn { display: flex; }

    /* display:none だと開閉が一瞬でパッと切り替わるため、常時 flex のまま
       不可視（opacity/visibility）にしておき、上端からスッと降りてくる演出にする。
       閉じている間はタブ順・クリックからも外す（visibility:hidden + pointer-events）。 */
    .nav-menu {
        position: fixed;
        top: var(--header-height);
        left: 0;
        right: 0;
        background: rgba(var(--bg-rgb), 0.98);
        border-bottom: 1px solid var(--border);
        flex-direction: column;
        gap: 0;
        padding: 8px 16px 16px;
        display: flex;
        z-index: 1001;
        transform-origin: top center;
        opacity: 0;
        visibility: hidden;
        transform: translateY(-10px) scale(0.98);
        pointer-events: none;
        transition: opacity 0.22s var(--ease-out),
                    transform 0.28s var(--ease-out),
                    visibility 0s linear 0.28s;
    }

    .nav-menu li {
        padding: 4px 0;
        opacity: 0;
        transform: translateY(8px);
        transition: opacity 0.22s var(--ease-out), transform 0.26s var(--ease-out);
    }
    .nav-menu li a { display: block; }
    .nav-menu li a::after { left: 12px; right: auto; width: 0; }

    .nav-toggle:checked ~ .nav-menu {
        opacity: 1;
        visibility: visible;
        transform: none;
        pointer-events: auto;
        transition: opacity 0.22s var(--ease-out),
                    transform 0.28s var(--ease-out),
                    visibility 0s;
    }

    /* 開くときは各項目を少しずつ遅らせて上から順に立ち上げる（カスケード）。 */
    .nav-toggle:checked ~ .nav-menu li {
        opacity: 1;
        transform: none;
    }
    .nav-toggle:checked ~ .nav-menu li:nth-child(1) { transition-delay: 0.04s; }
    .nav-toggle:checked ~ .nav-menu li:nth-child(2) { transition-delay: 0.07s; }
    .nav-toggle:checked ~ .nav-menu li:nth-child(3) { transition-delay: 0.10s; }
    .nav-toggle:checked ~ .nav-menu li:nth-child(4) { transition-delay: 0.13s; }
    .nav-toggle:checked ~ .nav-menu li:nth-child(5) { transition-delay: 0.16s; }
    .nav-toggle:checked ~ .nav-menu li:nth-child(6) { transition-delay: 0.19s; }
    .nav-toggle:checked ~ .nav-menu li:nth-child(7) { transition-delay: 0.22s; }
    /* 8項目目以降の保険（現状7項目だが、増えても最後が先に出現しないよう頭打ちにする） */
    .nav-toggle:checked ~ .nav-menu li:nth-child(n+8) { transition-delay: 0.24s; }

    /* ハンバーガー→× は上下バーを中央線でぴったり交差させ（±8px）、中央バーは
       縮めて消す。スプリングのイージングで軽く弾ませる。 */
    .nav-toggle:checked + .nav-toggle-btn span:nth-child(1) {
        transform: translateY(8px) rotate(45deg);
    }
    .nav-toggle:checked + .nav-toggle-btn span:nth-child(2) {
        opacity: 0;
        transform: scaleX(0);
    }
    .nav-toggle:checked + .nav-toggle-btn span:nth-child(3) {
        transform: translateY(-8px) rotate(-45deg);
    }

    .hero { padding: 40px 16px 24px; }

    .hero-container {
        flex-direction: column-reverse;
        gap: 28px;
        align-items: center;
        text-align: center;
    }

    .hero-left { text-align: center; }

    .social-bar { justify-content: center; }

    .profile-icon { width: 160px; height: 160px; }

    .section { padding: 52px 16px; }

    /* ページ内目次も本文（hero/section）の左右paddingに揃える */
    .page-toc { padding-left: 16px; padding-right: 16px; }

    main.left .section-title::after { left: 0; }

    /* ドロワー内リンクは48px級のタップ標的に */
    .nav-menu li a { padding: 12px 14px; }
}

/* カードの1列化は 600px から（601-768px のタブレット縦/大型スマホ横は2列を維持） */
@media (max-width: 768px) {
    .cards { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 600px) {
    .cards { grid-template-columns: 1fr; }

    /* モーダルは外周を絞って本文を広げる（svh 非対応は直前の 85vh が生きる） */
    .work-modal { width: calc(100% - 20px); }
    .work-modal-inner { padding: 24px 18px; max-height: 88svh; }
}

/* タッチ端末は × ボタンを44pxへ（h3 の右逃げも追随） */
@media (pointer: coarse) {
    .work-modal-close { width: 44px; height: 44px; }
    .work-modal-body h3 { padding-right: 44px; }
}

@media (max-width: 380px) {
    .social-btn { flex: 1 1 100%; justify-content: center; }
}

/* =====================================================================
   Reduced motion
   ===================================================================== */
@media (prefers-reduced-motion: reduce) {
    *,
    *::before,
    *::after {
        animation-duration: 0.001ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.001ms !important;
        scroll-behavior: auto !important;
    }

    .typed-text::after {
        animation: none;
        opacity: 1;
    }

    body.js .skills-graph .skill-level,
    body.js .skills-graph.in-view .skill-level {
        width: var(--lvl, 0%);
        transition: none;
    }

    /* スクロール表示は隠さず即表示（JS でも .reveal を付けないが、保険として明示） */
    body.js .reveal {
        opacity: 1;
        transform: none;
        transition: none;
    }
}

/* =====================================================================
   AI / Claude
   ===================================================================== */
.ai-card {
    display: flex;
    gap: 22px;
    align-items: flex-start;
    max-width: var(--measure-wide); /* V14 */
}

/* 土台は V17 のアイコンタイル基底 (:where)。ここは寸法差分のみ。
   注意: ここで background 等を再宣言すると詳細度 0,1,0 で基底に勝ってしまう。 */
.ai-card-icon {
    flex-shrink: 0;
    width: 64px;
    height: 64px;
    font-size: 1.8rem;
}

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

.ai-card-body .card-text {
    margin-top: 8px;
}

.ai-card-body strong {
    color: var(--accent-strong);
    font-weight: 700;
}

@media (max-width: 600px) {
    .ai-card {
        flex-direction: column;
        gap: 14px;
    }
}

/* =====================================================================
   Community timeline
   ===================================================================== */
.timeline {
    /* list reset: 上記 :where() で一元管理 */
    position: relative;
    max-width: var(--measure-wide); /* V14 */
}

.timeline::before {
    content: "";
    position: absolute;
    left: 9px;
    top: 10px;
    bottom: 10px;
    width: 2px;
    background: var(--border-bright);
}

.timeline-item {
    position: relative;
    padding-left: 40px;
    margin-bottom: 22px;
}

.timeline-item:last-child {
    margin-bottom: 0;
}

.timeline-item::before {
    content: "";
    position: absolute;
    left: 2px;
    top: 8px;
    width: 16px;
    height: 16px;
    border-radius: 50%;
    background: var(--accent);
    border: 3px solid var(--bg);
    box-shadow: 0 0 0 2px var(--accent);
    z-index: 1;
}

.timeline-item.is-ended::before {
    background: var(--dim);
    box-shadow: 0 0 0 2px var(--dim);
}

.timeline-content {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: 18px 20px;
    cursor: pointer;
    transition: border-color var(--dur) ease, transform var(--dur) ease, box-shadow var(--dur) ease;
}

.timeline-content:hover {
    border-color: var(--border-bright);
    transform: translateX(4px);
    box-shadow: var(--shadow);
}

.timeline-head {
    display: flex;
    align-items: center;
    gap: 12px;
    margin-bottom: 8px;
}

.timeline-date {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: 0.82rem;
    font-weight: 600;
    color: var(--accent);
    font-variant-numeric: tabular-nums;
}

.timeline-content .card-title {
    margin: 0 0 8px;
}

.timeline-content .card-text {
    margin: 0 0 14px;
}

/* =====================================================================
   V15: @media print
   ---------------------------------------------------------------------
   article.php (長文記事) / privacy.php / about.php はブラウザ印刷需要が
   ある一方、fixed navbar / back-to-top / 右目次 / aurora グロー等は紙面に
   残ると本文を上書きする。印刷では装飾を全て畳み、白背景/黒テキストで
   読み物として出す。
   ===================================================================== */
@media print {
    .navbar,
    .back-to-top,
    .page-toc,
    .site-footer::before,
    .site-footer::after,
    .hero-right::before,
    .hero-right::after,
    .btn,
    .btn-group,
    .skip-link {
        display: none !important;
    }

    html,
    body {
        background: #fff;
        color: #000;
    }

    main.left {
        padding-top: 0;
    }

    a {
        color: #000;
        text-decoration: underline;
    }

    /* 画像は 100% 幅で紙面幅を超えないよう */
    img, svg {
        max-width: 100%;
    }
}
