diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,10 @@
 # Changelog for `hgg-3d`
 
+## 0.2.0.0 — 2026-08-13
+
+- Follows the hgg-core 0.2 coordinate generalization.
+- Bilingual (English / Japanese) haddock.
+
 ## 0.1.0.0 — 2026-07-18
 
 First public release on Hackage.
diff --git a/hgg-3d.cabal b/hgg-3d.cabal
--- a/hgg-3d.cabal
+++ b/hgg-3d.cabal
@@ -1,6 +1,6 @@
 cabal-version:      3.0
 name:               hgg-3d
-version:            0.1.0.0
+version:            0.2.0.0
 extra-doc-files:    CHANGELOG.md
 synopsis:           3D plot (CPU projection) for hgg; works with all 2D backends
 description:
@@ -8,7 +8,7 @@
   CPU-based projection plus the painter's algorithm let the existing hgg
   2D backends (SVG / PDF / Rasterific) render 3D scatter / line /
   wireframe / surface plots as-is.
-  .
+
   No WebGL required — pure Haskell end to end. Interactive 3D (camera
   rotation etc.) in web environments is handled by a separate
   PureScript / WebGL frontend outside this package, connected through the
@@ -50,11 +50,11 @@
                   , text                 >= 2.0  && < 2.2
                   , containers           >= 0.6  && < 0.8
                   , vector               >= 0.13 && < 0.14
-                  , hgg-core        ^>= 0.1
-                  , hgg-svg         ^>= 0.1
-                  , hgg-pdf         ^>= 0.1
-                  , hgg-rasterific  ^>= 0.1
-                  , hgg-frame       ^>= 0.1
+                  , hgg-core        ^>= 0.2
+                  , hgg-svg         ^>= 0.2
+                  , hgg-pdf         ^>= 0.2
+                  , hgg-rasterific  ^>= 0.2
+                  , hgg-frame       ^>= 0.2
                   , aeson                >= 2.1  && < 2.3
                   , bytestring           >= 0.11 && < 0.13
                   , directory            >= 1.3  && < 1.4
diff --git a/src/Graphics/Hgg/ThreeD.hs b/src/Graphics/Hgg/ThreeD.hs
--- a/src/Graphics/Hgg/ThreeD.hs
+++ b/src/Graphics/Hgg/ThreeD.hs
@@ -1,28 +1,42 @@
 -- |
 -- Module      : Graphics.Hgg.ThreeD
--- Description : hgg-3d 公開エントリ (= 主要 API の再エクスポート)
+-- Description : Public entry point of hgg-3d (re-exports the main API)
 -- Copyright   : (c) 2026 Aelysce Project (Toshiaki Honda)
 -- License     : BSD-3-Clause
 --
--- 3D plot library (CPU projection + painter's algorithm)。 既存の hgg
--- 2D backend (SVG / PDF / Rasterific) でそのまま使える。
+-- [日本語]: 3D plot library (CPU projection + painter's algorithm)。 既存の
+--   hgg 2D backend (SVG / PDF / Rasterific) でそのまま使える。
 --
--- 主要型と関数を本 module で再エクスポート。 細部は子 module を参照:
+--   主要型と関数を本 module で再エクスポート。 細部は子 module を参照:
 --
--- * "Graphics.Hgg.ThreeD.Types" — Point3 / Vec3 / Mat4 / Camera3D / Projection3D
--- * "Graphics.Hgg.ThreeD.Projection" — project3D / lookAt 等の純粋関数
--- * "Graphics.Hgg.ThreeD.Axes" — Axes3D (= 立方体 wireframe + 3 軸 tick)
--- * "Graphics.Hgg.ThreeD.Scatter" — MScatter3D
--- * "Graphics.Hgg.ThreeD.Line" — MLine3D / MWireframe3D
--- * "Graphics.Hgg.ThreeD.Surface" — MSurface3D
--- * "Graphics.Hgg.ThreeD.Easy" — matplotlib mplot3d 風 helper
+--   * "Graphics.Hgg.ThreeD.Types" — Point3 / Vec3 / Mat4 / Camera3D / Projection3D
+--   * "Graphics.Hgg.ThreeD.Projection" — project3D / lookAt 等の純粋関数
+--   * "Graphics.Hgg.ThreeD.Axes" — Axes3D (= 立方体 wireframe + 3 軸 tick)
+--   * "Graphics.Hgg.ThreeD.Scatter" — MScatter3D
+--   * "Graphics.Hgg.ThreeD.Line" — MLine3D / MWireframe3D
+--   * "Graphics.Hgg.ThreeD.Surface" — MSurface3D
+--   * "Graphics.Hgg.ThreeD.Easy" — matplotlib mplot3d 風 helper
+-- [English]: A 3D plot library (CPU projection + the painter's algorithm).
+--   Works directly with the existing hgg 2D backends (SVG / PDF /
+--   Rasterific).
+--
+--   This module re-exports the main types and functions; see the child
+--   modules for the details:
+--
+--   * "Graphics.Hgg.ThreeD.Types" — Point3 / Vec3 / Mat4 / Camera3D / Projection3D
+--   * "Graphics.Hgg.ThreeD.Projection" — pure functions such as project3D / lookAt
+--   * "Graphics.Hgg.ThreeD.Axes" — Axes3D (a cube wireframe plus tick marks on the 3 axes)
+--   * "Graphics.Hgg.ThreeD.Scatter" — MScatter3D
+--   * "Graphics.Hgg.ThreeD.Line" — MLine3D / MWireframe3D
+--   * "Graphics.Hgg.ThreeD.Surface" — MSurface3D
+--   * "Graphics.Hgg.ThreeD.Easy" — matplotlib mplot3d-style helpers
 module Graphics.Hgg.ThreeD
-  ( -- * 中核型 (= A3 で実装)
+  ( -- * 中核型
     module Graphics.Hgg.ThreeD.Types
-    -- * Projection (= A3 で実装)
+    -- * Projection
   , module Graphics.Hgg.ThreeD.Projection
-    -- * Axes3D (= A4 で実装)
-    -- * Scatter / Line / Wireframe / Surface (= A5-A7 で実装)
+    -- * Axes3D
+    -- * Scatter / Line / Wireframe / Surface
   ) where
 
 import Graphics.Hgg.ThreeD.Types
diff --git a/src/Graphics/Hgg/ThreeD/Axes.hs b/src/Graphics/Hgg/ThreeD/Axes.hs
--- a/src/Graphics/Hgg/ThreeD/Axes.hs
+++ b/src/Graphics/Hgg/ThreeD/Axes.hs
@@ -1,19 +1,34 @@
 -- |
 -- Module      : Graphics.Hgg.ThreeD.Axes
--- Description : 3D 軸 (立方体 wireframe + 3 軸 tick / label) (Phase 3 A4)
+-- Description : 3D axes (cube wireframe with tick marks and labels on 3 axes)
 -- Copyright   : (c) 2026 Aelysce Project (Toshiaki Honda)
 -- License     : BSD-3-Clause
 --
--- mplot3d 風の axes: data bounding box (= xMin..zMax) を立方体 wireframe で
--- 囲み、 各軸に等間隔の tick を 1 列描画。 ラベルは tick の少し外側へ。
+-- [日本語]: mplot3d 風の axes: data bounding box (= xMin..zMax) を立方体
+--   wireframe で囲み、 各軸に等間隔の tick を 1 列描画。 ラベルは tick の少し
+--   外側へ。
 --
--- 設計判断:
+--   設計判断:
 --
---   * Phase 3 では「奥側面のみ」 を厳密判定せず、 12 辺全て描画 (= 多少視認性
---     落ちるが mplot3d 流の hairy wireframe より単純)
---   * tick は (xMin..xMax 等) の niceTicks3D で 5 点 default
---   * label: tick 値 + 軸名 (= "x"/"y"/"z")
---   * 出力は '[Primitive]' (= hgg-core の 2D primitive)、 既存 backend で描画
+--     * 「奥側面のみ」 を厳密判定せず、 12 辺全て描画 (= 多少視認性落ちるが
+--       mplot3d 流の hairy wireframe より単純)
+--     * tick は (xMin..xMax 等) の niceTicks3D で 5 点 default
+--     * label: tick 値 + 軸名 (= "x"/"y"/"z")
+--     * 出力は '[Primitive]' (= hgg-core の 2D primitive)、 既存
+--       backend で描画
+-- [English]: mplot3d-style axes: surrounds the data bounding box
+--   (xMin..zMax) with a cube wireframe and draws a row of evenly spaced
+--   ticks on each axis. Labels sit just outside the ticks.
+--
+--   Design decisions:
+--
+--     * Rather than strictly determining "only the back-facing sides", all
+--       12 edges are drawn (slightly less legible, but simpler than
+--       mplot3d's hairy wireframe)
+--     * Ticks default to 5 points via niceTicks3D over (xMin..xMax, etc.)
+--     * Labels: the tick value plus the axis name ("x"/"y"/"z")
+--     * Output is '[Primitive]' (the 2D primitive from hgg-core),
+--       rendered by the existing backends
 {-# LANGUAGE DeriveGeneric     #-}
 {-# LANGUAGE OverloadedStrings #-}
 module Graphics.Hgg.ThreeD.Axes
@@ -25,7 +40,7 @@
   , renderAxes3D
   , renderAxes3DWith
   , renderAxes3DWithLabels
-    -- * 壁面 pane + gridline (Phase 25 A6)
+    -- * 壁面 pane + gridline
   , PaneStyle3D (..)
   , defaultPaneStyle3D
   , renderAxes3DPanes
@@ -47,7 +62,8 @@
                                                   project3D)
 import           Graphics.Hgg.ThreeD.Types
 
--- | 3D 軸の bounding box + tick 数。
+-- | [日本語]: 3D 軸の bounding box + tick 数。
+--   [English]: The 3D axes' bounding box plus the tick count.
 data Axes3D = Axes3D
   { axesXMin  :: !Double
   , axesXMax  :: !Double
@@ -55,15 +71,20 @@
   , axesYMax  :: !Double
   , axesZMin  :: !Double
   , axesZMax  :: !Double
-  , axesNTicks :: !Int       -- ^ 軸あたり tick 数 (= default 5)
-  , axesXLog  :: !Bool       -- ^ Phase 25 A8: x 軸を log scale に (既定 False)
-  , axesYLog  :: !Bool       -- ^ Phase 25 A8: y 軸を log scale に (既定 False)
-  , axesZLog  :: !Bool       -- ^ Phase 25 A8: z 軸を log scale に (既定 False)
+  , axesNTicks :: !Int       -- ^ [日本語]: 軸あたり tick 数 (= default 5)
+                              --   [English]: The number of ticks per axis (default 5).
+  , axesXLog  :: !Bool       -- ^ [日本語]: x 軸を log scale に (既定 False)
+                              --   [English]: Whether to use a log scale for the x axis (default False).
+  , axesYLog  :: !Bool       -- ^ [日本語]: y 軸を log scale に (既定 False)
+                              --   [English]: Whether to use a log scale for the y axis (default False).
+  , axesZLog  :: !Bool       -- ^ [日本語]: z 軸を log scale に (既定 False)
+                              --   [English]: Whether to use a log scale for the z axis (default False).
   } deriving (Show, Eq, Generic)
 instance ToJSON   Axes3D
 instance FromJSON Axes3D
 
--- | 単位 cube (= [-1, 1]^3) + tick 5。
+-- | [日本語]: 単位 cube (= [-1, 1]^3) + tick 5。
+--   [English]: The unit cube (@[-1, 1]^3@) with 5 ticks per axis.
 defaultAxes3D :: Axes3D
 defaultAxes3D = Axes3D
   { axesXMin = -1, axesXMax = 1
@@ -73,8 +94,10 @@
   , axesXLog = False, axesYLog = False, axesZLog = False
   }
 
--- | 等間隔 tick 位置を 'n' 個生成。 niceNumbers アルゴリズム ではなく素朴な等間隔
--- (= mplot3d 風)。
+-- | [日本語]: 等間隔 tick 位置を @n@ 個生成。 niceNumbers アルゴリズム ではなく
+--   素朴な等間隔 (= mplot3d 風)。
+--   [English]: Generates @n@ evenly spaced tick positions. Uses plain even
+--   spacing (mplot3d-style) rather than a niceNumbers algorithm.
 niceTicks3D :: Int -> Double -> Double -> [Double]
 niceTicks3D n lo hi
   | n <= 1 || abs (hi - lo) < 1e-12 = [lo]
@@ -82,9 +105,14 @@
       let step = (hi - lo) / fromIntegral (n - 1)
       in [ lo + step * fromIntegral i | i <- [0 .. n - 1] ]
 
--- | Phase 25 A8: log scale 軸の tick 位置 = @[lo, hi]@ 区間内の 10 の冪
--- (decade)。 端 (lo/hi) も含め、 冪が 1 個以下なら端 2 点で補う。 値は正前提
--- (lo<=0 は 1e-12 に clamp)。 軸ラベルは元の値のまま 'formatNum' で出る。
+-- | [日本語]: log scale 軸の tick 位置 = @[lo, hi]@ 区間内の 10 の冪
+--   (decade)。 端 (lo/hi) も含め、 冪が 1 個以下なら端 2 点で補う。 値は正前提
+--   (lo<=0 は 1e-12 に clamp)。 軸ラベルは元の値のまま 'formatNum' で出る。
+--   [English]: The tick positions for a log-scale axis: powers of 10
+--   (decades) within @[lo, hi]@. Includes the endpoints (lo/hi); if fewer
+--   than two powers fall in range, falls back to the two endpoints. Values
+--   are assumed positive (lo<=0 is clamped to 1e-12). Axis labels still show
+--   the original value via 'formatNum'.
 logTicks3D :: Double -> Double -> [Double]
 logTicks3D lo0 hi0 =
   let lo = max 1e-12 lo0
@@ -99,8 +127,10 @@
        (_:_:_) -> inRange
        _       -> [lo, hi]   -- 冪が足りなければ端 2 点
 
--- | Phase 25 A8: log フラグで tick 生成を切替える (log = 'logTicks3D'・線形 =
--- 'niceTicks3D')。 両 axes renderer が共有。
+-- | [日本語]: log フラグで tick 生成を切替える (log = 'logTicks3D'・線形 =
+--   'niceTicks3D')。 両 axes renderer が共有。
+--   [English]: Switches tick generation based on the log flag (log uses
+--   'logTicks3D', linear uses 'niceTicks3D'). Shared by both axes renderers.
 axisTicks3D :: Bool -> Int -> Double -> Double -> [Double]
 axisTicks3D isLog n lo hi
   | isLog     = logTicks3D lo hi
@@ -110,18 +140,26 @@
 -- 描画
 -- ===========================================================================
 
--- | Axes3D を 2D Primitive 列にレンダリング (= cube wireframe + 3 軸 tick + label)。
+-- | [日本語]: Axes3D を 2D Primitive 列にレンダリング (= cube wireframe + 3 軸 tick + label)。
+--   [English]: Renders an 'Axes3D' as a list of 2D primitives (cube
+--   wireframe plus ticks and labels on the 3 axes).
 renderAxes3D :: Camera3D -> Projection3D -> Viewport -> Axes3D -> [Primitive]
 renderAxes3D = renderAxes3DWith id
 
--- | Phase 24 A3: 投影前に座標変換 @f@ を合成する版。 @f@ に正規化
--- (データ bbox → [-1,1]^3) を渡すと、 **tick ラベルは元のデータ値のまま**
--- 形状だけ view box に収まる (saveSVG3D の正規化 pipeline 用)。
+-- | [日本語]: 投影前に座標変換 @f@ を合成する版。 @f@ に正規化
+--   (データ bbox → [-1,1]^3) を渡すと、 __tick ラベルは元のデータ値のまま__
+--   形状だけ view box に収まる (saveSVG3D の正規化 pipeline 用)。
+--   [English]: The variant that composes a coordinate transform @f@ before
+--   projection. Passing normalization (data bbox to @[-1,1]^3@) as @f@
+--   fits the shape into the view box, __leaving tick labels unchanged__
+--   (used by the @saveSVG3D@ normalization pipeline).
 renderAxes3DWith :: (Point3 -> Point3)
                  -> Camera3D -> Projection3D -> Viewport -> Axes3D -> [Primitive]
 renderAxes3DWith f = renderAxes3DWithLabels f ("x", "y", "z")
 
--- | Phase 24 A8: 軸名を任意指定する版 ('renderAxes3DWith' = @("x","y","z")@)。
+-- | [日本語]: 軸名を任意指定する版 ('renderAxes3DWith' = @("x","y","z")@)。
+--   [English]: The variant that takes arbitrary axis names ('renderAxes3DWith'
+--   is this with @("x","y","z")@).
 renderAxes3DWithLabels :: (Point3 -> Point3) -> (Text, Text, Text)
                        -> Camera3D -> Projection3D -> Viewport -> Axes3D -> [Primitive]
 renderAxes3DWithLabels f (xName, yName, zName) cam proj vp ax =
@@ -234,31 +272,50 @@
   in cubeLines <> xTickPrims <> yTickPrims <> zTickPrims <> axisNames
 
 -- ===========================================================================
--- 壁面 pane + gridline (Phase 25 A6 = G5)
+-- 壁面 pane + gridline
 -- ===========================================================================
 
--- | Phase 25 A6: 壁面 pane (= mplot3d の背面 3 壁) のスタイル。
--- pane = 薄灰の塗り面、 gridline = 壁面に引く tick 格子線 (mplot3d 既定は白)。
+-- | [日本語]: 壁面 pane (= mplot3d の背面 3 壁) のスタイル。
+--   pane = 薄灰の塗り面、 gridline = 壁面に引く tick 格子線 (mplot3d 既定は白)。
+--   [English]: The style for a wall pane (mplot3d's 3 back walls). Pane =
+--   the light-gray filled face; gridline = the tick gridlines drawn on the
+--   wall (mplot3d's default is white).
 data PaneStyle3D = PaneStyle3D
-  { paneFill    :: !Text    -- ^ 壁面塗り色
-  , paneOpacity :: !Double  -- ^ 塗り不透明度 (0..1)
-  , paneGrid    :: !Text    -- ^ 格子線色
+  { paneFill    :: !Text    -- ^ [日本語]: 壁面塗り色
+                              --   [English]: The wall's fill color.
+  , paneOpacity :: !Double  -- ^ [日本語]: 塗り不透明度 (0..1)
+                              --   [English]: The fill opacity (0..1).
+  , paneGrid    :: !Text    -- ^ [日本語]: 格子線色
+                              --   [English]: The gridline color.
   } deriving (Show, Eq, Generic)
 instance ToJSON   PaneStyle3D
 instance FromJSON PaneStyle3D
 
--- | mplot3d 風 default (薄灰 pane + 白格子線)。
+-- | [日本語]: mplot3d 風 default (薄灰 pane + 白格子線)。
+--   [English]: The mplot3d-style default (a light-gray pane with white
+--   gridlines).
 defaultPaneStyle3D :: PaneStyle3D
 defaultPaneStyle3D = PaneStyle3D "#eaeaea" 1.0 "#ffffff"
 
--- | Phase 25 A6: 3 つの「奥壁」 を薄灰 pane で塗り、 各壁に tick 格子線を引く
--- (mplot3d 標準の axes pane)。 出力は @pane 塗り → gridline@ の順なので、
--- 'renderAxes3DWithLabels' (cube wireframe + tick) の **前** に置けば最背面に
--- なる (= データ・wireframe が pane の手前に来る)。
+-- | [日本語]: 3 つの「奥壁」 を薄灰 pane で塗り、 各壁に tick 格子線を引く
+--   (mplot3d 標準の axes pane)。 出力は @pane 塗り → gridline@ の順なので、
+--   'renderAxes3DWithLabels' (cube wireframe + tick) の __前__ に置けば最背面に
+--   なる (= データ・wireframe が pane の手前に来る)。
 --
--- 奥壁判定: 各軸の対向 2 面のうち、 面中心の投影 depth ('projDepth'、 +1 が奥)
--- が大きい方を奥壁に採る。 視点回転に追従する。 @f@ は 'renderAxes3DWith' と
--- 同じ正規化変換 (データ bbox → [-1,1]^3)。
+--   奥壁判定: 各軸の対向 2 面のうち、 面中心の投影 depth ('projDepth'、 +1 が奥)
+--   が大きい方を奥壁に採る。 視点回転に追従する。 @f@ は 'renderAxes3DWith' と
+--   同じ正規化変換 (データ bbox → [-1,1]^3)。
+--   [English]: Fills the 3 "back walls" with a light-gray pane and draws
+--   tick gridlines on each wall (mplot3d's standard axes pane). The output
+--   goes pane fill first, then gridlines, so placing this call __before__
+--   'renderAxes3DWithLabels' (the cube wireframe plus ticks) puts it at the
+--   very back (data and the wireframe end up drawn in front of the pane).
+--
+--   Back-wall determination: for each axis's pair of opposing faces, the
+--   one with the larger projected depth at its center ('projDepth', where
+--   +1 is farthest) is chosen as the back wall — this tracks camera
+--   rotation. @f@ is the same normalization transform (data bbox to
+--   @[-1,1]^3@) as 'renderAxes3DWith'.
 renderAxes3DPanes :: (Point3 -> Point3) -> PaneStyle3D
                   -> Camera3D -> Projection3D -> Viewport -> Axes3D -> [Primitive]
 renderAxes3DPanes f sty cam proj vp ax =
@@ -310,9 +367,14 @@
 
   in [xPane, yPane, zPane] <> xGrid <> yGrid <> zGrid
 
--- | 数値を短く整形 (= 小数 1 桁、 末尾 0 と . を除去)。 ★末尾 0 除去は **小数点が
--- ある場合のみ** (整数の末尾 0 を削ると 10→1・100→1 になるバグを Phase 25 A8 で
--- 修正。 log tick の 10/100/1000 で顕在化)。
+-- | [日本語]: 数値を短く整形 (= 小数 1 桁、 末尾 0 と . を除去)。 ★末尾 0 除去は
+--   __小数点がある場合のみ__ (整数の末尾 0 を削ると 10→1・100→1 になるバグを
+--   修正済。 log tick の 10/100/1000 で顕在化)。
+--   [English]: Formats a number compactly (1 decimal place, trailing zeros
+--   and the decimal point stripped). Trailing-zero stripping only applies
+--   __when there is a decimal point__ (stripping trailing zeros from an
+--   integer used to turn 10 into 1 and 100 into 1 — a bug now fixed; it
+--   surfaced with log ticks like 10/100/1000).
 formatNum :: Double -> Text
 formatNum x =
   let s = T.pack (show (fromIntegral (round (x * 10) :: Int) / 10.0 :: Double))
diff --git a/src/Graphics/Hgg/ThreeD/Bar.hs b/src/Graphics/Hgg/ThreeD/Bar.hs
--- a/src/Graphics/Hgg/ThreeD/Bar.hs
+++ b/src/Graphics/Hgg/ThreeD/Bar.hs
@@ -1,23 +1,43 @@
 -- |
 -- Module      : Graphics.Hgg.ThreeD.Bar
--- Description : 3D bar (直方体 / stick) + 誤差棒 (Phase 25 A5)
+-- Description : 3D bar charts (cuboid / stick) with error bars
 -- Copyright   : (c) 2026 Aelysce Project (Toshiaki Honda)
 -- License     : BSD-3-Clause
 --
--- DoE / 実験データ定番の 3D 棒グラフ。 各 (x, y) 位置に底面 (base z) から高さ
--- (top z) までの棒を立てる。 2 スタイル:
+-- [日本語]: DoE / 実験データ定番の 3D 棒グラフ。 各 (x, y) 位置に底面 (base z)
+--   から高さ (top z) までの棒を立てる。 2 スタイル:
 --
---   * 'BarCuboid' — 直方体 (top + 4 側面の 5 quad)。 surface 同様 painter's の
---     depth 統合 ('barFacesDepth') に乗せ、 scatter/surface と層横断ソートされる。
---   * 'BarStick'  — 太い縦線 1 本 (面なし・軽量)。 line/wireframe 同様 depth 統合
---     対象外で前面に描く ('renderBarSticks')。
+--     * 'BarCuboid' — 直方体 (top + 4 側面の 5 quad)。 surface 同様 painter's の
+--       depth 統合 ('barFacesDepth') に乗せ、 scatter/surface と層横断ソートされる。
+--     * 'BarStick'  — 太い縦線 1 本 (面なし・軽量)。 line/wireframe 同様 depth 統合
+--       対象外で前面に描く ('renderBarSticks')。
 --
--- 誤差棒 ('renderErrorBars3D') は棒/点の頂点に z 方向 ±err の縦線 + 端キャップ。
--- bar・scatter どちらの layer にも付けられる (層の per-point err 列で駆動)。
+--   誤差棒 ('renderErrorBars3D') は棒/点の頂点に z 方向 ±err の縦線 + 端キャップ。
+--   bar・scatter どちらの layer にも付けられる (層の per-point err 列で駆動)。
 --
--- ⚠ 入力 ('Bar3D' の点・base・half-width・err) はすべて**正規化済**座標
--- ([-1,1]^3・z-aspect 適用後) を渡す前提。 正規化は 'Easy.normLayer3D' /
--- 'scaleZLayer' が担い、 本 module は投影 + 幾何のみ。
+--   ⚠ 入力 ('Bar3D' の点・base・half-width・err) はすべて__正規化済__座標
+--   ([-1,1]^3・z-aspect 適用後) を渡す前提。 正規化は 'Easy.normLayer3D' /
+--   @scaleZLayer@ が担い、 本 module は投影 + 幾何のみ。
+-- [English]: A 3D bar chart, a DoE / experimental-data staple. Each (x, y)
+--   position gets a bar from a base z to a top z. Two styles:
+--
+--     * 'BarCuboid' — a cuboid (top plus 4 side quads, 5 total). Like a
+--       surface, it joins the painter's-algorithm depth integration
+--       ('barFacesDepth') and is sorted across layers together with
+--       scatter / surface.
+--     * 'BarStick'  — a single thick vertical line (no faces, lightweight).
+--       Like line / wireframe, it stays outside depth integration and is
+--       drawn in front ('renderBarSticks').
+--
+--   Error bars ('renderErrorBars3D') draw a z-direction ±err vertical line
+--   plus end caps at each bar's or point's vertex; they can be attached to
+--   either a bar or scatter layer (driven by the layer's per-point err
+--   column).
+--
+--   ⚠ All inputs (the points, base, half-width, err of 'Bar3D') are assumed to be
+--   __already normalized__ coordinates (@[-1,1]^3@, after z-aspect is
+--   applied). Normalization is handled by 'Easy.normLayer3D' /
+--   @scaleZLayer@; this module only does projection and geometry.
 {-# LANGUAGE DeriveGeneric     #-}
 {-# LANGUAGE OverloadedStrings #-}
 module Graphics.Hgg.ThreeD.Bar
@@ -43,28 +63,40 @@
                                                   project3D)
 import           Graphics.Hgg.ThreeD.Types
 
--- | 棒のスタイル。
+-- | [日本語]: 棒のスタイル。
+--   [English]: The bar's style.
 data BarStyle3D
-  = BarCuboid   -- ^ 直方体 (top + 4 側面・depth 統合)
-  | BarStick    -- ^ 太い縦線 (面なし・前面描画)
+  = BarCuboid   -- ^ [日本語]: 直方体 (top + 4 側面・depth 統合)
+                --   [English]: A cuboid (top plus 4 sides; joins depth integration).
+  | BarStick    -- ^ [日本語]: 太い縦線 (面なし・前面描画)
+                --   [English]: A thick vertical line (no faces; drawn in front).
   deriving (Show, Eq, Generic)
 instance ToJSON   BarStyle3D
 instance FromJSON BarStyle3D
 
--- | 3D bar 1 series 分の設定 (= 全点共通スタイル・点ごとに棒を立てる)。
+-- | [日本語]: 3D bar 1 series 分の設定 (= 全点共通スタイル・点ごとに棒を立てる)。
+--   [English]: The configuration for one series of a 3D bar chart (a shared
+--   style, with one bar per point).
 data Bar3D = Bar3D
-  { br3Tops   :: ![Point3]    -- ^ 各棒の頂点 (x, y, 高さ z)・正規化済
-  , br3BaseZ  :: !Double      -- ^ 底面 z (正規化済・通常 data z=0 の正規化値)
-  , br3HalfW  :: !Double      -- ^ footprint 半幅 (正規化空間・x/y 共通)
+  { br3Tops   :: ![Point3]    -- ^ [日本語]: 各棒の頂点 (x, y, 高さ z)・正規化済
+                                --   [English]: Each bar's top vertex (x, y, height z), already normalized.
+  , br3BaseZ  :: !Double      -- ^ [日本語]: 底面 z (正規化済・通常 data z=0 の正規化値)
+                                --   [English]: The base z (already normalized; usually the normalized value of data z=0).
+  , br3HalfW  :: !Double      -- ^ [日本語]: footprint 半幅 (正規化空間・x/y 共通)
+                                --   [English]: The footprint half-width (in normalized space; shared by x/y).
   , br3Style  :: !BarStyle3D
   , br3Color  :: !Text
-  , br3Alpha  :: !Double      -- ^ 面/線の不透明度 (0..1)
-  , br3Width  :: !Double      -- ^ stick 線幅 px ('BarStick' 時)
+  , br3Alpha  :: !Double      -- ^ [日本語]: 面/線の不透明度 (0..1)
+                                --   [English]: The face / line opacity (0..1).
+  , br3Width  :: !Double      -- ^ [日本語]: stick 線幅 px ('BarStick' 時)
+                                --   [English]: The stick line width in px (used with 'BarStick').
   } deriving (Show, Eq, Generic)
 instance ToJSON   Bar3D
 instance FromJSON Bar3D
 
--- | default: 青、 base 0、 半幅 0.04、 直方体、 alpha 1、 stick 幅 6。
+-- | [日本語]: default: 青、 base 0、 半幅 0.04、 直方体、 alpha 1、 stick 幅 6。
+--   [English]: The default: blue, base 0, half-width 0.04, cuboid, alpha 1,
+--   stick width 6.
 defaultBar3D :: [Point3] -> Bar3D
 defaultBar3D tops = Bar3D
   { br3Tops  = tops
@@ -80,9 +112,14 @@
 -- 直方体 face の depth 列 (= surfaceFacesDepth と同型・大域ソートに混ぜる)
 -- ===========================================================================
 
--- | 各棒を直方体の 5 quad (top + 4 側面・底面は隠れるので省く) に展開し、
--- @(投影 depth, PPath)@ で**未ソート**返す。 'BarStick' 時は @[]@ (= 'renderBarSticks'
--- が描く)。 簡易 Lambert shading (surface と同じ light) で立体感を付ける。
+-- | [日本語]: 各棒を直方体の 5 quad (top + 4 側面・底面は隠れるので省く) に展開し、
+--   @(投影 depth, PPath)@ で__未ソート__返す。 'BarStick' 時は @[]@ (= 'renderBarSticks'
+--   が描く)。 簡易 Lambert shading (surface と同じ light) で立体感を付ける。
+--   [English]: Expands each bar into the cuboid's 5 quads (top plus 4
+--   sides; the bottom is hidden and omitted), returning
+--   @(projected depth, PPath)@ pairs __unsorted__. Returns @[]@ for
+--   'BarStick' (drawn instead by 'renderBarSticks'). Adds a sense of solidity
+--   via simple Lambert shading (the same light as surfaces).
 barFacesDepth
   :: Camera3D -> Projection3D -> Viewport
   -> Bar3D -> [(Double, Primitive)]
@@ -128,7 +165,9 @@
 -- stick スタイル (太い縦線・前面描画)
 -- ===========================================================================
 
--- | 'BarStick' 時、 各棒を底面→頂点の太い縦線で描く。 'BarCuboid' 時は @[]@。
+-- | [日本語]: 'BarStick' 時、 各棒を底面→頂点の太い縦線で描く。 'BarCuboid' 時は @[]@。
+--   [English]: For 'BarStick', draws each bar as a thick vertical line from
+--   base to top vertex. Returns @[]@ for 'BarCuboid'.
 renderBarSticks
   :: Camera3D -> Projection3D -> Viewport
   -> Bar3D -> [Primitive]
@@ -145,17 +184,25 @@
                (solid (br3Color br) (br3Width br))
 
 -- ===========================================================================
--- stem (Phase 26 A4・3D lollipop = 細い垂線 + 先端マーカー・前面描画)
+-- stem (3D lollipop = 細い垂線 + 先端マーカー・前面描画)
 -- ===========================================================================
 
--- | Phase 26 A4: 各点を底面 ('br3BaseZ') → 先端の細い縦線 + 先端の円マーカーで
--- 描く (3D lollipop)。 'renderBarSticks' (太線・マーカー無し) と違い stem は
--- 細線 + マーカー。 線色/幅/alpha は 'Bar3D' から、 マーカー半径は引数 @markerR@
--- (px)。 depth 統合外の前面 overlay。 先端の depth cue で僅かに半径を変える
--- (scatter と同じ・近側が大きい)。
+-- | [日本語]: 各点を底面 ('br3BaseZ') → 先端の細い縦線 + 先端の円マーカーで
+--   描く (3D lollipop)。 'renderBarSticks' (太線・マーカー無し) と違い stem は
+--   細線 + マーカー。 線色/幅/alpha は 'Bar3D' から、 マーカー半径は引数 @markerR@
+--   (px)。 depth 統合外の前面 overlay。 先端の depth cue で僅かに半径を変える
+--   (scatter と同じ・近側が大きい)。
+--   [English]: Draws each point as a thin vertical line from the base
+--   ('br3BaseZ') to the top, plus a circular marker at the top (a 3D
+--   lollipop). Unlike 'renderBarSticks' (a thick line with no marker), a
+--   stem is a thin line plus marker. Line color / width / alpha come from
+--   'Bar3D'; the marker radius is the @markerR@ argument (px). Drawn as a
+--   front overlay outside depth integration. The tip's radius shifts
+--   slightly with a depth cue (same as scatter — nearer points are larger).
 renderStems3D
   :: Camera3D -> Projection3D -> Viewport
-  -> Bar3D -> Double          -- ^ マーカー基本半径 px
+  -> Bar3D -> Double          -- ^ [日本語]: マーカー基本半径 px
+                                --   [English]: The marker's base radius, in px.
   -> [Primitive]
 renderStems3D cam proj vp br markerR =
   concatMap stem (br3Tops br)
@@ -180,13 +227,20 @@
 -- 誤差棒 (z 方向 ±err・縦線 + 端キャップ)
 -- ===========================================================================
 
--- | 各頂点 @(x,y,z)@ に z 方向 ±err の縦線 + 上下端の水平キャップ (画面空間の
--- 短い横線) を描く。 err は正規化済 z 量 (= 'normLayer3D' で換算済)。 bar/scatter
--- どちらの頂点列にも使える。 err <= 0 の点はスキップ。 線色 'col'・幅 'lw'。
+-- | [日本語]: 各頂点 @(x,y,z)@ に z 方向 ±err の縦線 + 上下端の水平キャップ (画面空間の
+--   短い横線) を描く。 err は正規化済 z 量 (= 'Graphics.Hgg.ThreeD.Easy.normLayer3D' で換算済)。 bar/scatter
+--   どちらの頂点列にも使える。 err <= 0 の点はスキップ。 線色 @col@・幅 @lw@。
+--   [English]: Draws a z-direction ±err vertical line at each vertex
+--   @(x,y,z)@, plus horizontal end caps (short screen-space lines) at the
+--   top and bottom. err is an already-normalized z quantity (converted via
+--   'Graphics.Hgg.ThreeD.Easy.normLayer3D'). Works on either a bar or scatter vertex list. Points
+--   with err <= 0 are skipped. Line color @col@, width @lw@.
 renderErrorBars3D
   :: Camera3D -> Projection3D -> Viewport
-  -> Text -> Double          -- ^ 色・線幅 px
-  -> [(Point3, Double)]      -- ^ (頂点, 正規化 err)
+  -> Text -> Double          -- ^ [日本語]: 色・線幅 px
+                                --   [English]: The color and line width, in px.
+  -> [(Point3, Double)]      -- ^ [日本語]: (頂点, 正規化 err)
+                                --   [English]: (vertex, normalized err) pairs.
   -> [Primitive]
 renderErrorBars3D cam proj vp col lw pes =
   concatMap whisker pes
diff --git a/src/Graphics/Hgg/ThreeD/Bound.hs b/src/Graphics/Hgg/ThreeD/Bound.hs
--- a/src/Graphics/Hgg/ThreeD/Bound.hs
+++ b/src/Graphics/Hgg/ThreeD/Bound.hs
@@ -1,18 +1,30 @@
 -- |
 -- Module      : Graphics.Hgg.ThreeD.Bound
--- Description : 3D の df バインド (Phase 24 A6 = 2D `df |>> spec` の 3D 対応)
+-- Description : 3D dataframe binding (the 3D counterpart of 2D's `df |>> spec`)
 -- Copyright   : (c) 2026 Aelysce Project (Toshiaki Honda)
 -- License     : BSD-3-Clause
 --
--- 2D と同じ書き味で 3D に列名バインドを通す:
+-- [日本語]: 2D と同じ書き味で 3D に列名バインドを通す:
 --
 -- > df |>> (layer3D (scatter3D "x" "y" "z" <> colormap3D) <> title3D "...")
 -- >   :: BoundPlot3D
 -- > saveSVG3DBound "out.svg" bound
 --
--- 'BindableSpec' (hgg-frame) の 'VisualSpec3D' instance を本 module
--- で与える (型の定義 package 側 = 非 orphan)。 検証は 2D と同方針で
--- **バインド時に値として** 'PlotDiagnostic' に格納し、 例外は投げない。
+--   'BindableSpec' (hgg-frame) の 'VisualSpec3D' instance を本 module
+--   で与える (型の定義 package 側 = 非 orphan)。 検証は 2D と同方針で
+--   __バインド時に値として__ 'PlotDiagnostic' に格納し、 例外は投げない。
+-- [English]: Threads column-name binding through to 3D with the same feel
+--   as 2D:
+--
+-- > df |>> (layer3D (scatter3D "x" "y" "z" <> colormap3D) <> title3D "...")
+-- >   :: BoundPlot3D
+-- > saveSVG3DBound "out.svg" bound
+--
+--   This module supplies the 'VisualSpec3D' instance of 'BindableSpec'
+--   (hgg-frame) — the package that defines the type, so it is not
+--   an orphan. Validation follows the same policy as 2D: it is stored
+--   __as a value in 'PlotDiagnostic' at bind time__, and no exception is
+--   ever thrown.
 {-# LANGUAGE OverloadedStrings #-}
 {-# LANGUAGE TypeFamilies      #-}
 module Graphics.Hgg.ThreeD.Bound
@@ -41,7 +53,9 @@
                                                  lyr3EncX, lyr3EncY, lyr3EncZ,
                                                  lyr3TextBy, resolveSpec3D)
 
--- | df バインド済の 3D plot (2D 'Graphics.Hgg.Frame.BoundPlot' の 3D 版)。
+-- | [日本語]: df バインド済の 3D plot (2D 'Graphics.Hgg.Frame.BoundPlot' の 3D 版)。
+--   [English]: A dataframe-bound 3D plot (the 3D counterpart of the 2D
+--   'Graphics.Hgg.Frame.BoundPlot').
 data BoundPlot3D = BoundPlot3D
   { bp3Resolver    :: Resolver
   , bp3Spec        :: VisualSpec3D
@@ -54,7 +68,9 @@
     BoundPlot3D (toResolver df) spec
                 (emptyDfDiagnostics df ++ checkColumns (columnNames df) spec)
 
--- | spec 中の 'ColByName' を df の列名と突合する (編集距離 suggestion 付き)。
+-- | [日本語]: spec 中の 'ColByName' を df の列名と突合する (編集距離 suggestion 付き)。
+--   [English]: Matches the 'ColByName' references in a spec against the
+--   dataframe's column names (with edit-distance suggestions).
 checkColumns :: [Text] -> VisualSpec3D -> [PlotDiagnostic]
 checkColumns known spec =
   [ PlotError (ColumnNotFound nm (suggest known nm)) (DiagnosticContext (Just i) Nothing)
@@ -69,20 +85,30 @@
   byName (Just (ColByName nm)) = Just nm
   byName _                     = Nothing
 
--- | バインド済 3D plot を SVG 保存 (列参照を解決してから 'saveSVG3D')。
+-- | [日本語]: バインド済 3D plot を SVG 保存 (列参照を解決してから 'saveSVG3D')。
+--   [English]: Saves a bound 3D plot as SVG (resolves column references,
+--   then calls 'saveSVG3D').
 saveSVG3DBound :: FilePath -> BoundPlot3D -> IO ()
 saveSVG3DBound path b = saveSVG3D path (resolveSpec3D (bp3Resolver b) (bp3Spec b))
 
--- | バインド済 3D plot を **WebGL self-contained HTML** として保存
+-- | [日本語]: バインド済 3D plot を __WebGL self-contained HTML__ として保存
 --   (= 'saveSVG3DBound' の interactive 版・列参照と resolve 産物を解決してから
---   'saveHTML3D')。 df 連携 3D の browser 経路欠落を埋める (Phase 27 A2)。
+--   'saveHTML3D')。 df 連携 3D の browser 経路欠落を埋める。
+--   [English]: Saves a bound 3D plot as __self-contained WebGL HTML__ (the
+--   interactive counterpart of 'saveSVG3DBound' — resolves column references
+--   and the resolved spec, then calls 'saveHTML3D'). Fills the gap that used
+--   to leave dataframe-bound 3D plots without a browser rendering path.
 saveHTML3DBound :: FilePath -> BoundPlot3D -> IO ()
 saveHTML3DBound path b = saveHTML3D path (resolveSpec3D (bp3Resolver b) (bp3Spec b))
 
--- | バインド済 3D plot を **ブラウザで interactive 表示** ('showBrowser' の df 連携版)。
+-- | [日本語]: バインド済 3D plot を __ブラウザで interactive 表示__ ('showBrowser' の df 連携版)。
+--   [English]: Displays a bound 3D plot __interactively in the browser__
+--   (the dataframe-bound counterpart of 'showBrowser').
 showBrowser3DBound :: BoundPlot3D -> IO ()
 showBrowser3DBound b = showBrowser (resolveSpec3D (bp3Resolver b) (bp3Spec b))
 
--- | (Resolver, 解決済み spec) を取り出す raw 経路 (2D 'unBound' 同型)。
+-- | [日本語]: (Resolver, 解決済み spec) を取り出す raw 経路 (2D 'Graphics.Hgg.Frame.unBound' 同型)。
+--   [English]: The raw escape hatch that extracts (Resolver, resolved spec)
+--   (mirroring the 2D 'Graphics.Hgg.Frame.unBound').
 unBound3D :: BoundPlot3D -> (Resolver, VisualSpec3D)
 unBound3D b = (bp3Resolver b, resolveSpec3D (bp3Resolver b) (bp3Spec b))
diff --git a/src/Graphics/Hgg/ThreeD/Browser.hs b/src/Graphics/Hgg/ThreeD/Browser.hs
--- a/src/Graphics/Hgg/ThreeD/Browser.hs
+++ b/src/Graphics/Hgg/ThreeD/Browser.hs
@@ -1,6 +1,6 @@
 -- |
 -- Module      : Graphics.Hgg.ThreeD.Browser
--- Description : HS-side browser display driver (Phase 5 A5)
+-- Description : HS-side browser display driver
 -- Copyright   : (c) 2026 Aelysce Project (Toshiaki Honda)
 -- License     : BSD-3-Clause
 --
@@ -10,16 +10,32 @@
 -- main = showBrowser $ purePlot3D <> layer3D (scatter3D pts) <> camera (defaultCameraZUp 3)
 -- @
 --
--- 中身: spec を aeson で JSON 化、 PS WebGL bundle (= data-files) と inline 結合した
--- self-contained HTML を tmp に出力、 OS 別 browser-open コマンド (xdg-open / open / start) で起動。
+-- [日本語]: 中身: spec を aeson で JSON 化、 PS WebGL bundle (= data-files) と inline 結合した
+--   self-contained HTML を tmp に出力、 OS 別 browser-open コマンド (xdg-open / open / start) で起動。
 --
--- 設計判断 (= phase-5 計画 md §2.4):
+--   設計判断 (= phase-5 計画 md §2.4):
 --
---   * **bundle embed 方式**: cabal data-files 採用 (= dev iteration 速さ重視、
---     PS 側更新時 HS 再 build 不要)。 将来 TH 'embedFile' 切替時は 'getBundleJS'
---     の中身だけ差替えで済む。 詳細 → @design\/bundle-embed-choice.md@
---   * **3 つの出力経路**: 'showBrowser' (= tmp + open)、 'saveHTML3D' (= 配布用、 単一 HTML)、
---     'Graphics.Hgg.ThreeD.Easy.saveSVG3D' (= 静的 SVG、 Phase 3 CPU projection 経路)
+--     * __bundle embed 方式__: cabal data-files 採用 (= dev iteration 速さ重視、
+--       PS 側更新時 HS 再 build 不要)。 将来 TH @embedFile@ 切替時は 'getBundleJS'
+--       の中身だけ差替えで済む。 詳細 → @design\/bundle-embed-choice.md@
+--     * __3 つの出力経路__: 'showBrowser' (= tmp + open)、 'saveHTML3D' (= 配布用、 単一 HTML)、
+--       'Graphics.Hgg.ThreeD.Easy.saveSVG3D' (= 静的 SVG、 CPU projection 経路)
+-- [English]: Internals: JSON-encodes the spec via aeson, writes a
+--   self-contained HTML file to tmp that inline-embeds the PS WebGL bundle
+--   (from data-files), then launches it with the OS-specific browser-open
+--   command (xdg-open / open / start).
+--
+--   Design decisions (see phase-5 plan md §2.4):
+--
+--     * __The bundle-embed approach__: uses cabal data-files (prioritizing
+--       dev iteration speed — no HS rebuild is needed when the PS side
+--       changes). If this ever switches to TH @embedFile@, only the body of
+--       'getBundleJS' needs to change. Details:
+--       @design\/bundle-embed-choice.md@
+--     * __Three output paths__: 'showBrowser' (tmp file plus open),
+--       'saveHTML3D' (a single distributable HTML file), and
+--       'Graphics.Hgg.ThreeD.Easy.saveSVG3D' (a static SVG, via the CPU
+--       projection path)
 {-# LANGUAGE OverloadedStrings #-}
 module Graphics.Hgg.ThreeD.Browser
   ( -- * 主要 API
@@ -45,11 +61,18 @@
 -- bundle 取得 (= 絶縁レイヤ、 後で TH に swap 可能)
 -- ===========================================================================
 
--- | PS WebGL bundle (= data/webgl-spec.js) を ByteString で取得。
+-- | [日本語]: PS WebGL bundle (= data/webgl-spec.js) を ByteString で取得。
 --
--- 現在は @cabal data-files@ 経由 ('Paths_hgg_3d.getDataFileName')。
--- 将来 TH 'embedFile' に切替時はこの 1 関数のみ差替えれば済むよう設計
--- (= 切替手順は @design\/bundle-embed-choice.md@)。
+--   現在は @cabal data-files@ 経由 ('Paths_hgg_3d.getDataFileName')。
+--   将来 TH @embedFile@ に切替時はこの 1 関数のみ差替えれば済むよう設計
+--   (= 切替手順は @design\/bundle-embed-choice.md@)。
+--   [English]: Fetches the PS WebGL bundle (data/webgl-spec.js) as a
+--   ByteString.
+--
+--   Currently goes through @cabal data-files@
+--   ('Paths_hgg_3d.getDataFileName'). Designed so that a future
+--   switch to TH @embedFile@ only requires replacing this one function
+--   (the switch procedure is in @design\/bundle-embed-choice.md@).
 getBundleJS :: IO BS.ByteString
 getBundleJS = do
   path <- getDataFileName "data/webgl-spec.js"
@@ -59,10 +82,15 @@
 -- showBrowser / saveHTML3D
 -- ===========================================================================
 
--- | spec を **ブラウザで interactive 表示**。 tmp HTML 生成 + OS 別 browser-open。
+-- | [日本語]: spec を __ブラウザで interactive 表示__。 tmp HTML 生成 + OS 別 browser-open。
 --
--- WebGL2 backend で描画、 mouse drag で camera orbit、 wheel で zoom、
--- 右 drag で pan。 操作仕様は Phase 4 demo と同一。
+--   WebGL2 backend で描画、 mouse drag で camera orbit、 wheel で zoom、
+--   右 drag で pan。 操作仕様は demo と同一。
+--   [English]: Displays a spec __interactively in the browser__. Generates a
+--   tmp HTML file, then opens it with the OS-specific browser-open command.
+--
+--   Renders via the WebGL2 backend: mouse drag orbits the camera, the wheel
+--   zooms, and right-drag pans. The controls match the demo.
 showBrowser :: VisualSpec3D -> IO ()
 showBrowser spec = do
   tmpDir <- getTemporaryDirectory
@@ -70,9 +98,14 @@
   saveHTML3D path spec
   openInBrowser path
 
--- | spec を **self-contained HTML として保存** (= 配布用、 bundle inline 埋込)。
+-- | [日本語]: spec を __self-contained HTML として保存__ (= 配布用、 bundle inline 埋込)。
 --
--- 出力ファイルは外部依存無し、 ブラウザで直接開ける。
+--   出力ファイルは外部依存無し、 ブラウザで直接開ける。
+--   [English]: Saves a spec as __self-contained HTML__ (for distribution,
+--   with the bundle inline-embedded).
+--
+--   The output file has no external dependencies and opens directly in a
+--   browser.
 saveHTML3D :: FilePath -> VisualSpec3D -> IO ()
 saveHTML3D path spec = do
   bundleJS <- getBundleJS
@@ -84,9 +117,13 @@
 -- HTML 生成
 -- ===========================================================================
 
--- | bundle JS + spec JSON を 1 HTML に埋込。 ESM ではなく通常 script 経路
--- (= spago bundle 出力は IIFE、 ESM import すると export named 'main' 不在で失敗、
---    Phase 4 で確認済の罠)。
+-- | [日本語]: bundle JS + spec JSON を 1 HTML に埋込。 ESM ではなく通常 script 経路
+--   (= spago bundle 出力は IIFE、 ESM import すると export named @main@ 不在で失敗、
+--      確認済の罠)。
+--   [English]: Embeds the bundle JS plus spec JSON into a single HTML file.
+--   Uses a plain @<script>@ tag rather than ESM (spago's bundle output is
+--   an IIFE; ESM import fails because there is no named export @main@ — a
+--   confirmed gotcha).
 mkHTML :: BS.ByteString -> LBS.ByteString -> LBS.ByteString
 mkHTML bundleJS specJSON = LBS.concat
   [ "<!DOCTYPE html>\n"
@@ -135,10 +172,16 @@
 -- OS 別 browser-open
 -- ===========================================================================
 
--- | OS 検出して xdg-open (Linux) / open (macOS) / start (Windows) を呼ぶ。
+-- | [日本語]: OS 検出して xdg-open (Linux) / open (macOS) / start (Windows) を呼ぶ。
 --
--- WSL は @os == \"linux\"@ で xdg-open 経路。 wslview などインストール済なら動作。
--- 失敗時は path を stdout に出すので手動で開ける。
+--   WSL は @os == \"linux\"@ で xdg-open 経路。 wslview などインストール済なら動作。
+--   失敗時は path を stdout に出すので手動で開ける。
+--   [English]: Detects the OS and calls xdg-open (Linux), open (macOS), or
+--   start (Windows).
+--
+--   WSL reports @os == \"linux\"@, so it goes through the xdg-open path;
+--   this works if @wslview@ or similar is installed. On failure, the path
+--   is printed to stdout so it can be opened manually.
 openInBrowser :: FilePath -> IO ()
 openInBrowser path = case os of
   "linux"   -> safeCall ("xdg-open " <> quote path)
diff --git a/src/Graphics/Hgg/ThreeD/Delaunay.hs b/src/Graphics/Hgg/ThreeD/Delaunay.hs
--- a/src/Graphics/Hgg/ThreeD/Delaunay.hs
+++ b/src/Graphics/Hgg/ThreeD/Delaunay.hs
@@ -1,17 +1,29 @@
 -- |
 -- Module      : Graphics.Hgg.ThreeD.Delaunay
--- Description : 2D Delaunay 三角分割 (Phase 26 A5・trisurf 用)
+-- Description : 2D Delaunay triangulation (for trisurf)
 -- Copyright   : (c) 2026 Aelysce Project (Toshiaki Honda)
 -- License     : BSD-3-Clause
 --
--- 不規則 (非 grid) 点群を 'trisurf' で曲面化するための **純 Haskell** 2D Delaunay
--- 三角分割。 外部ライブラリ / バイナリ依存ゼロ (= spec §10.7・graphviz parity と
--- 同じ「自己完結」 方針)。 アルゴリズムは Bowyer-Watson の素朴版 (O(n²) 程度・
--- trisurf の点数は数十〜低数百なので十分)。
+-- [日本語]: 不規則 (非 grid) 点群を 'Graphics.Hgg.ThreeD.Spec.trisurf' で曲面化するための __純 Haskell__
+--   2D Delaunay 三角分割。 外部ライブラリ / バイナリ依存ゼロ (= spec §10.7・
+--   graphviz parity と同じ「自己完結」 方針)。 アルゴリズムは Bowyer-Watson の
+--   素朴版 (O(n²) 程度・trisurf の点数は数十〜低数百なので十分)。
 --
--- 入力は (x,y) 列。 z は呼び出し側で分割後に各頂点へ持ち上げる (= trisurf は
--- (x,y) 平面の 2D 分割だけで足り、 3D 四面体分割は不要)。 退化 (共円・共線) は
--- incircle 述語の符号で素朴に扱う (demo 用途では実害なし)。
+--   入力は (x,y) 列。 z は呼び出し側で分割後に各頂点へ持ち上げる (= trisurf は
+--   (x,y) 平面の 2D 分割だけで足り、 3D 四面体分割は不要)。 退化 (共円・共線) は
+--   incircle 述語の符号で素朴に扱う (demo 用途では実害なし)。
+-- [English]: A __pure Haskell__ 2D Delaunay triangulation for turning
+--   irregular (non-grid) point clouds into a surface via 'Graphics.Hgg.ThreeD.Spec.trisurf'. Zero
+--   external library / binary dependencies (the same "self-contained"
+--   policy as spec §10.7 / graphviz parity). The algorithm is a naive
+--   Bowyer-Watson implementation (roughly O(n²), which is fine since
+--   'Graphics.Hgg.ThreeD.Spec.trisurf' typically deals with tens to low hundreds of points).
+--
+--   The input is a list of (x,y) columns; z is lifted onto each vertex by
+--   the caller after triangulation ('Graphics.Hgg.ThreeD.Spec.trisurf' only needs the 2D
+--   triangulation of the (x,y) plane, not a 3D tetrahedralization).
+--   Degenerate cases (co-circular or collinear points) are handled naively
+--   via the sign of the incircle predicate (harmless for demo purposes).
 {-# LANGUAGE BangPatterns #-}
 module Graphics.Hgg.ThreeD.Delaunay
   ( delaunay2D
@@ -20,8 +32,12 @@
 import           Data.List       (foldl')
 import qualified Data.Map.Strict as M
 
--- | (x,y) 点列を 2D Delaunay 三角分割し、 三角形を元の点配列への index 三つ組
+-- | [日本語]: (x,y) 点列を 2D Delaunay 三角分割し、 三角形を元の点配列への index 三つ組
 --   @(i,j,k)@ で返す。 点が 3 未満 / 全点共線などで三角形が作れない時は @[]@。
+--   [English]: Triangulates a list of (x,y) points via 2D Delaunay
+--   triangulation, returning each triangle as an index triple @(i,j,k)@ into
+--   the original point array. Returns @[]@ when fewer than 3 points are
+--   given, or triangulation is impossible (e.g. all points collinear).
 delaunay2D :: [(Double, Double)] -> [(Int, Int, Int)]
 delaunay2D pts0
   | n < 3     = []
@@ -64,7 +80,9 @@
 
     triEdges (a, b, c) = [(a, b), (b, c), (c, a)]
 
--- | 点 d が三角形 (a,b,c) の外接円の内部か。 三角形の向き (CCW/CW) を符号で吸収。
+-- | [日本語]: 点 d が三角形 (a,b,c) の外接円の内部か。 三角形の向き (CCW/CW) を符号で吸収。
+--   [English]: Whether point d lies inside the circumcircle of triangle
+--   (a,b,c). The triangle's winding order (CCW/CW) is absorbed via the sign.
 inCircle :: (Double, Double) -> (Double, Double) -> (Double, Double)
          -> (Double, Double) -> Bool
 inCircle (ax, ay) (bx, by) (cx, cy) (dx, dy) =
diff --git a/src/Graphics/Hgg/ThreeD/Easy.hs b/src/Graphics/Hgg/ThreeD/Easy.hs
--- a/src/Graphics/Hgg/ThreeD/Easy.hs
+++ b/src/Graphics/Hgg/ThreeD/Easy.hs
@@ -1,35 +1,49 @@
 -- |
 -- Module      : Graphics.Hgg.ThreeD.Easy
--- Description : 3D 出力経路の薄い wrap (Phase 5 A6 saveSVG3D)
+-- Description : A thin wrapper over the 3D output paths (saveSVG3D)
 -- Copyright   : (c) 2026 Aelysce Project (Toshiaki Honda)
 -- License     : BSD-3-Clause
 --
--- 'VisualSpec3D' から各出力経路への dispatch helper。 3 経路:
+-- [日本語]: 'VisualSpec3D' から各出力経路への dispatch helper。 3 経路:
 --
---   * 'saveSVG3D'   ─ Phase 3 CPU projection (= 静的 SVG 出力、 本 module 実装)
---   * 'saveHTML3D'  ─ Phase 4 WebGL bundle 埋込 HTML (= 'Graphics.Hgg.ThreeD.Browser')
---   * 'showBrowser' ─ tmp HTML + xdg-open (= 'Graphics.Hgg.ThreeD.Browser')
+--   * 'saveSVG3D'   ─ CPU projection (= 静的 SVG 出力、 本 module 実装)
+--   * 'Graphics.Hgg.ThreeD.Browser.saveHTML3D'  ─ WebGL bundle 埋込 HTML (= 'Graphics.Hgg.ThreeD.Browser')
+--   * 'Graphics.Hgg.ThreeD.Browser.showBrowser' ─ tmp HTML + xdg-open (= 'Graphics.Hgg.ThreeD.Browser')
 --
--- 同 spec を 3 経路に出し分けられる。 用途で使い分け:
+--   同 spec を 3 経路に出し分けられる。 用途で使い分け:
 --
 --   * 印刷 / doc 埋込 → 'saveSVG3D'
---   * 配布 / 単一 HTML 配布 → 'saveHTML3D'
---   * 開発時 interactive 確認 → 'showBrowser'
+--   * 配布 / 単一 HTML 配布 → 'Graphics.Hgg.ThreeD.Browser.saveHTML3D'
+--   * 開発時 interactive 確認 → 'Graphics.Hgg.ThreeD.Browser.showBrowser'
+-- [English]: Dispatch helpers from a 'VisualSpec3D' to each output path.
+--   Three paths:
+--
+--   * 'saveSVG3D'   ─ CPU projection (static SVG output, implemented here)
+--   * 'Graphics.Hgg.ThreeD.Browser.saveHTML3D'  ─ WebGL bundle embedded in HTML (see
+--     'Graphics.Hgg.ThreeD.Browser')
+--   * 'Graphics.Hgg.ThreeD.Browser.showBrowser' ─ a tmp HTML file plus xdg-open (see
+--     'Graphics.Hgg.ThreeD.Browser')
+--
+--   The same spec can be routed to any of the three. Pick based on use case:
+--
+--   * printing / embedding in a doc → 'saveSVG3D'
+--   * distribution as a single HTML file → 'Graphics.Hgg.ThreeD.Browser.saveHTML3D'
+--   * interactive checking during development → 'Graphics.Hgg.ThreeD.Browser.showBrowser'
 {-# LANGUAGE OverloadedStrings #-}
 module Graphics.Hgg.ThreeD.Easy
   ( saveSVG3D
-    -- * PDF / PNG 出力 (Phase 24 A8 glue)
+    -- * PDF / PNG 出力 (glue)
   , savePDF3D
   , savePNG3D
   , spec3DToPrimitives
-    -- * 群別タイル配置 (Phase 24 A7)
+    -- * 群別タイル配置
   , saveSVG3DFacet
   , renderSpec3DInPanel
-    -- * 正規化 pipeline (Phase 24 A3・test 用に公開)
+    -- * 正規化 pipeline (test 用に公開)
   , padAxes3D
   , normPoint3D
   , normLayer3D
-    -- * 投影 contour (Phase 24 A5・test 用に公開)
+    -- * 投影 contour (test 用に公開)
   , renderProjectedContour3D
   ) where
 
@@ -95,24 +109,39 @@
                                                     renderErrorBars3D)
 import           Graphics.Hgg.ThreeD.Types
 
--- | 'VisualSpec3D' を Phase 3 CPU projection で SVG に保存。
+-- | [日本語]: 'VisualSpec3D' を CPU projection で SVG に保存。
 --
--- defaults:
+--   defaults:
 --
 --   * camera     → 'defaultCameraZUp' 3
 --   * projection → 'defaultPerspective'
 --   * axes       → 'autoAxes3D' (= layers の Point3 集合から bbox 算出)
 --   * width / height → 700 / 700
 --   * title      → ""
+--   [English]: Saves a 'VisualSpec3D' as SVG via CPU projection.
+--
+--   Defaults:
+--
+--   * camera     → 'defaultCameraZUp' 3
+--   * projection → 'defaultPerspective'
+--   * axes       → 'autoAxes3D' (bbox computed from the layers' Point3 sets)
+--   * width / height → 700 / 700
+--   * title      → ""
 saveSVG3D :: FilePath -> VisualSpec3D -> IO ()
 saveSVG3D path spec =
   let (w, h, title, prims) = spec3DToPrimitives spec
   in savePrimitivesSVG path w h title prims
 
--- | Phase 24 A8: 'VisualSpec3D' を (幅, 高さ, タイトル, [Primitive]) に落とす
--- 共通核。 各 backend (SVG/PDF/PNG) の出力関数が共有する。 prims は
--- 'renderSpec3DInPanel' 単一 panel (= キャンバス全域)。 title は別返し
--- (SVG は backend が <text> 化・PDF/PNG は 'savePDF3D'/'savePNG3D' が PText 化)。
+-- | [日本語]: 'VisualSpec3D' を (幅, 高さ, タイトル, [Primitive]) に落とす
+--   共通核。 各 backend (SVG/PDF/PNG) の出力関数が共有する。 prims は
+--   'renderSpec3DInPanel' 単一 panel (= キャンバス全域)。 title は別返し
+--   (SVG は backend が <text> 化・PDF/PNG は 'savePDF3D'/'savePNG3D' が PText 化)。
+--   [English]: The shared core that reduces a 'VisualSpec3D' to
+--   (width, height, title, [Primitive]), shared by each backend's (SVG /
+--   PDF / PNG) output function. prims come from a single
+--   'renderSpec3DInPanel' panel (the whole canvas). title is returned
+--   separately (the SVG backend turns it into @\<text\>@; PDF/PNG have
+--   'savePDF3D' / 'savePNG3D' turn it into a @PText@).
 spec3DToPrimitives :: VisualSpec3D -> (Int, Int, Text, [Primitive])
 spec3DToPrimitives spec =
   let w     = fromMaybe 700 (getLast (vs3Width  spec))
@@ -121,24 +150,35 @@
       prims = renderSpec3DInPanel 0 0 (fromIntegral w) (fromIntegral h) spec
   in (w, h, title, prims)
 
--- | Phase 24 A8: 3D 図を PDF に保存 ('saveSVG3D' の PDF 版)。 [Primitive] を
--- 既存 PDF backend ('savePrimitivesPDF') へ配線。 title は上部中央の PText に
--- する (PDF backend は title 引数を持たないため)。 ⚠ PDF 標準フォントは
--- Latin-1 のみ (日本語ラベルは 'savePNG3D')。
+-- | [日本語]: 3D 図を PDF に保存 ('saveSVG3D' の PDF 版)。 [Primitive] を
+--   既存 PDF backend ('savePrimitivesPDF') へ配線。 title は上部中央の PText に
+--   する (PDF backend は title 引数を持たないため)。 ⚠ PDF 標準フォントは
+--   Latin-1 のみ (日本語ラベルは 'savePNG3D')。
+--   [English]: Saves a 3D figure as PDF (the PDF counterpart of
+--   'saveSVG3D'). Wires @[Primitive]@ to the existing PDF backend
+--   ('savePrimitivesPDF'). The title is turned into a top-centered 'PText'
+--   (the PDF backend has no title argument). ⚠ PDF's standard fonts are
+--   Latin-1 only (use 'savePNG3D' for Japanese labels).
 savePDF3D :: FilePath -> VisualSpec3D -> IO ()
 savePDF3D path spec =
   let (w, h, title, prims) = spec3DToPrimitives spec
   in savePrimitivesPDF path w h (titlePrims w title <> prims)
 
--- | Phase 24 A8: 3D 図を PNG に保存 ('saveSVG3D' の PNG 版・日本語ラベル可)。
--- [Primitive] を既存 Rasterific backend ('savePrimitivesPNG') へ配線。
+-- | [日本語]: 3D 図を PNG に保存 ('saveSVG3D' の PNG 版・日本語ラベル可)。
+--   [Primitive] を既存 Rasterific backend ('savePrimitivesPNG') へ配線。
+--   [English]: Saves a 3D figure as PNG (the PNG counterpart of
+--   'saveSVG3D'; supports Japanese labels). Wires @[Primitive]@ to the
+--   existing Rasterific backend ('savePrimitivesPNG').
 savePNG3D :: FilePath -> VisualSpec3D -> IO ()
 savePNG3D path spec =
   let (w, h, title, prims) = spec3DToPrimitives spec
   in savePrimitivesPNG defaultPNGConfig path w h (titlePrims w title <> prims)
 
--- | タイトルを上部中央の PText に (空なら無し)。 SVG backend の title 描画
--- (font-size 16・中央・y≈24) に概ね合わせる。
+-- | [日本語]: タイトルを上部中央の PText に (空なら無し)。 SVG backend の title 描画
+--   (font-size 16・中央・y≈24) に概ね合わせる。
+--   [English]: Turns the title into a top-centered 'PText' (nothing if
+--   empty). Roughly matches the SVG backend's title rendering (font-size
+--   16, centered, y≈24).
 titlePrims :: Int -> Text -> [Primitive]
 titlePrims w title
   | T.null title = []
@@ -146,10 +186,16 @@
       [ PText (Point (fromIntegral w / 2) 24) title
               (TextStyle "#333333" 16 "sans-serif" AnchorMiddle 0 "normal" False) ]
 
--- | Phase 24 A7: 'VisualSpec3D' を**任意のパネル矩形** @(px,py,pw,ph)@ 内に
--- 描画する純粋核 ('saveSVG3D' と 'saveSVG3DFacet' が共有)。 軸 box・正規化
--- pipeline・layer・colorbar をパネル局所座標で出す。 @(0,0,w,h)@ で呼ぶと
--- 旧 'saveSVG3D' とビット同一 (margin 50・colorbar 右端)。
+-- | [日本語]: 'VisualSpec3D' を__任意のパネル矩形__ @(px,py,pw,ph)@ 内に
+--   描画する純粋核 ('saveSVG3D' と 'saveSVG3DFacet' が共有)。 軸 box・正規化
+--   pipeline・layer・colorbar をパネル局所座標で出す。 @(0,0,w,h)@ で呼ぶと
+--   旧 'saveSVG3D' とビット同一 (margin 50・colorbar 右端)。
+--   [English]: The pure core that renders a 'VisualSpec3D' into
+--   __an arbitrary panel rectangle__ @(px,py,pw,ph)@ (shared by 'saveSVG3D'
+--   and 'saveSVG3DFacet'). Emits the axis box, normalization pipeline,
+--   layers, and colorbar in panel-local coordinates. Calling it with
+--   @(0,0,w,h)@ is bit-identical to the original 'saveSVG3D' (margin 50,
+--   colorbar on the right edge).
 renderSpec3DInPanel :: Double -> Double -> Double -> Double -> VisualSpec3D -> [Primitive]
 renderSpec3DInPanel px py pw ph spec =
   let layers = vs3Layers spec
@@ -218,8 +264,12 @@
        <> maybe [] (renderColorbar3D px py pw ph) cbInfo
        <> renderLegend3D px py pw ph legendEntries
 
--- | Phase 25 A2: 群色分けの離散凡例 (色チップ + ラベル) をパネル右端に縦並び。
--- colorbar があればその左、 無ければ右端。 entries = (カテゴリ, 色) の初出順。
+-- | [日本語]: 群色分けの離散凡例 (色チップ + ラベル) をパネル右端に縦並び。
+--   colorbar があればその左、 無ければ右端。 entries = (カテゴリ, 色) の初出順。
+--   [English]: Renders the discrete group-coloring legend (color chips plus
+--   labels), stacked vertically along the panel's right edge. Sits left of
+--   the colorbar if there is one, otherwise flush right. entries are
+--   (category, color) pairs in first-occurrence order.
 renderLegend3D :: Double -> Double -> Double -> Double -> [(Text, Text)] -> [Primitive]
 renderLegend3D _  _  _  _  []      = []
 renderLegend3D px py pw ph entries =
@@ -236,8 +286,11 @@
            , PText (Point (x0 + chip + 6) (y + chip - 2)) cat tsL ]
   in concatMap row (zip [0 :: Int ..] entries)
 
--- | Phase 24 A8: depth 統合対象 (surface 面・scatter 点) を @(depth, Primitive)@
--- で返す。 line/wireframe/floor は対象外 ([])。
+-- | [日本語]: depth 統合対象 (surface 面・scatter 点) を @(depth, Primitive)@
+--   で返す。 line/wireframe/floor は対象外 ([])。
+--   [English]: Returns the depth-integration targets (surface faces,
+--   scatter points) as @(depth, Primitive)@ pairs. line / wireframe / floor
+--   are excluded (@[]@).
 depthItemsOf :: Camera3D -> Projection3D -> Viewport -> Layer3D -> [(Double, Primitive)]
 depthItemsOf cam proj vp l = case getFirst (lyr3Kind l) of
   Just M3Surface -> surfaceFacesDepth  cam proj vp (layerToSurface l)
@@ -257,7 +310,9 @@
     in trianglesFacesDepth cam proj vp col ecol shaded cmap alpha triPts
   _              -> []
 
--- | Phase 24 A8: depth 統合対象外の layer (line/wireframe・bar stick) を描く。
+-- | [日本語]: depth 統合対象外の layer (line/wireframe・bar stick) を描く。
+--   [English]: Draws the layers that are excluded from depth integration
+--   (line / wireframe, bar sticks).
 otherLayerPrims :: Camera3D -> Projection3D -> Viewport -> Layer3D -> [Primitive]
 otherLayerPrims cam proj vp l = case getFirst (lyr3Kind l) of
   Just M3Line      -> renderLine3D      cam proj vp (layerToLine      l)
@@ -273,8 +328,12 @@
   Just M3Quiver    -> renderQuiver3D cam proj vp (layerToQuiver l)
   _                -> []
 
--- | Phase 25 A5: 層の per-point err (正規化済) があれば誤差棒を描く (bar/scatter
--- 共通)。 頂点列は正規化済 'lyr3Points'。 最前面に描くため depth 統合外。
+-- | [日本語]: 層の per-point err (正規化済) があれば誤差棒を描く (bar/scatter
+--   共通)。 頂点列は正規化済 'lyr3Points'。 最前面に描くため depth 統合外。
+--   [English]: Draws error bars when a layer's per-point err (already
+--   normalized) is present (shared by bar and scatter). Vertices come from
+--   the already-normalized 'lyr3Points'. Drawn in front, outside depth
+--   integration.
 errorBarPrimsOf :: Camera3D -> Projection3D -> Viewport -> Layer3D -> [Primitive]
 errorBarPrimsOf cam proj vp l =
   case (getLast (lyr3PtErrs l), getLast (lyr3Points l)) of
@@ -282,10 +341,15 @@
       renderErrorBars3D cam proj vp "#333333" 1.0 (zip pts es)
     _ -> []
 
--- | Phase 25 A7: テキスト注釈 layer (M3Text) を描く。 正規化済 'lyr3Points' を
--- 投影し、 各点に 'lyr3Labels' の文字列を PText で置く (depth 統合外の前面 overlay)。
--- 文字色 = 'lyr3Color' (既定 @#333333@)、 サイズ = 'lyr3Size' (既定 11)。 点の
--- 少し上 (-6px) に中央寄せ。
+-- | [日本語]: テキスト注釈 layer (M3Text) を描く。 正規化済 'lyr3Points' を
+--   投影し、 各点に 'lyr3Labels' の文字列を PText で置く (depth 統合外の前面 overlay)。
+--   文字色 = 'lyr3Color' (既定 @#333333@)、 サイズ = 'lyr3Size' (既定 11)。 点の
+--   少し上 (-6px) に中央寄せ。
+--   [English]: Draws the text-annotation layer (M3Text). Projects the
+--   already-normalized 'lyr3Points' and places each point's 'lyr3Labels'
+--   string as a 'PText' (a front overlay outside depth integration). Text
+--   color comes from 'lyr3Color' (default @#333333@), size from
+--   'lyr3Size' (default 11). Centered, slightly above each point (-6px).
 textPrimsOf :: Camera3D -> Projection3D -> Viewport -> Layer3D -> [Primitive]
 textPrimsOf cam proj vp l = case getFirst (lyr3Kind l) of
   Just M3Text ->
@@ -299,10 +363,16 @@
     in zipWith place pts lbs
   _ -> []
 
--- | Phase 24 A8 / 25 A8: 正規化済 layer を box aspect @(xa, ya, za)@ 倍する。
--- surface は grid z (za) と x/y range (xa/ya)、 それ以外は点列の各成分。
--- @(1,1,1)@ は恒等 (= 旧出力ビット不変)。 surface の grid x/y は xRange を縮める
--- ことで反映 (Surface.hs が xRange を線形補間して頂点を置くため)。
+-- | [日本語]: 正規化済 layer を box aspect @(xa, ya, za)@ 倍する。
+--   surface は grid z (za) と x/y range (xa/ya)、 それ以外は点列の各成分。
+--   @(1,1,1)@ は恒等 (= 旧出力ビット不変)。 surface の grid x/y は xRange を縮める
+--   ことで反映 (Surface.hs が xRange を線形補間して頂点を置くため)。
+--   [English]: Scales an already-normalized layer by the box aspect
+--   @(xa, ya, za)@. For a surface, this scales grid z (za) and the x/y
+--   range (xa/ya); for other layers, each component of the point list.
+--   @(1,1,1)@ is the identity (bit-identical to legacy output). A surface's
+--   grid x/y is reflected by shrinking xRange (since Surface.hs places
+--   vertices by linearly interpolating xRange).
 scaleAspectLayer :: Double -> Double -> Double -> Layer3D -> Layer3D
 scaleAspectLayer xa ya za l
   | xa == 1 && ya == 1 && za == 1 = l
@@ -324,12 +394,21 @@
         sv (Vec3 vx vy vz) = Vec3 (vx * xa) (vy * ya) (vz * za)
         scaleRange a (lo, hi) = (lo * a, hi * a)
 
--- | Phase 24 A7: 群別 3D 図のタイル配置 (= 「群別曲面の並置」)。 N 個の
--- @(群ラベル, spec)@ を near-square グリッド (@ncol = ceil(√n)@) に並べ、 各
--- パネルを 'renderSpec3DInPanel' で描き、 上部に群ラベルを置く。 colorbar は
--- panel 毎 (各 spec の colormap surface に追従)。 camera/axes は各 spec が個別に
--- 持つ前提 (analyze の群別 'surfaceOf' 出力をそのまま渡せる)。 1 パネルの
--- 既定サイズは 380×380 px (spec が 'width3DV'/'height3DV' を持てばそれを使う)。
+-- | [日本語]: 群別 3D 図のタイル配置 (= 「群別曲面の並置」)。 N 個の
+--   @(群ラベル, spec)@ を near-square グリッド (@ncol = ceil(√n)@) に並べ、 各
+--   パネルを 'renderSpec3DInPanel' で描き、 上部に群ラベルを置く。 colorbar は
+--   panel 毎 (各 spec の colormap surface に追従)。 camera/axes は各 spec が個別に
+--   持つ前提 (analyze の群別 @surfaceOf@ 出力をそのまま渡せる)。 1 パネルの
+--   既定サイズは 380×380 px (spec が @width3DV@/@height3DV@ を持てばそれを使う)。
+--   [English]: Tiles a set of grouped 3D figures ("placing group surfaces
+--   side by side"). Arranges N @(group label, spec)@ pairs into a
+--   near-square grid (@ncol = ceil(√n)@), draws each panel with
+--   'renderSpec3DInPanel', and places the group label above it. The
+--   colorbar is per-panel (following each spec's colormap surface).
+--   camera / axes are assumed to belong to each spec individually (so
+--   output from hanalyze's grouped @surfaceOf@ can be passed
+--   straight through). Each panel defaults to 380×380 px (used unless the
+--   spec sets @width3DV@/@height3DV@).
 saveSVG3DFacet :: FilePath -> [(Text, VisualSpec3D)] -> IO ()
 saveSVG3DFacet _    []     = pure ()
 saveSVG3DFacet path panels = do
@@ -352,7 +431,9 @@
       prims = concat (zipWith panelPrims [0 ..] panels)
   savePrimitivesSVG path wPx hPx "" prims
 
--- | Phase 24 A3: 退化した軸 (min == max) を ±0.5 に広げる (正規化の 0 割り防止)。
+-- | [日本語]: 退化した軸 (min == max) を ±0.5 に広げる (正規化の 0 割り防止)。
+--   [English]: Widens a degenerate axis (min == max) to ±0.5 (prevents
+--   division by zero during normalization).
 padAxes3D :: Axes3D -> Axes3D
 padAxes3D ax =
   let pad lo hi | hi > lo   = (lo, hi)
@@ -364,16 +445,22 @@
         , axesYMin = y0, axesYMax = y1
         , axesZMin = z0, axesZMax = z1 }
 
--- | Phase 24 A3 / 25 A8: 軸 bbox を [-1,1]^3 へ写す正規化 (各軸独立)。 log 軸
--- ('axes*Log') は log10 空間で affine、 線形軸はそのまま affine。
+-- | [日本語]: 軸 bbox を [-1,1]^3 へ写す正規化 (各軸独立)。 log 軸
+--   ('axes*Log') は log10 空間で affine、 線形軸はそのまま affine。
+--   [English]: Normalizes the axis bbox to @[-1,1]^3@ (each axis
+--   independently). A log axis ('axes*Log') is affine in log10 space; a
+--   linear axis is affine directly.
 normPoint3D :: Axes3D -> Point3 -> Point3
 normPoint3D ax (Point3 x y z) =
   Point3 (normCoord (axesXLog ax) (axesXMin ax) (axesXMax ax) x)
          (normCoord (axesYLog ax) (axesYMin ax) (axesYMax ax) y)
          (normCoord (axesZLog ax) (axesZMin ax) (axesZMax ax) z)
 
--- | Phase 25 A8: 1 軸の正規化 (log/線形)。 @[lo,hi]@ → @[-1,1]@。 log は値・端を
--- 1e-12 に clamp してから log10 空間で affine。
+-- | [日本語]: 1 軸の正規化 (log/線形)。 @[lo,hi]@ → @[-1,1]@。 log は値・端を
+--   1e-12 に clamp してから log10 空間で affine。
+--   [English]: Normalizes a single axis (log or linear): @[lo,hi]@ to
+--   @[-1,1]@. For log, values and endpoints are clamped to 1e-12 and then
+--   made affine in log10 space.
 normCoord :: Bool -> Double -> Double -> Double -> Double
 normCoord isLog lo hi v
   | isLog =
@@ -384,8 +471,12 @@
   | hi <= lo  = 0
   | otherwise = -1 + 2 * (v - lo) / (hi - lo)
 
--- | Phase 24 A3: layer のデータを正規化座標に写す。 surface は grid の z と
--- x/y range、 それ以外は点列。 colormap の色は z 正規化に対して不変 (affine)。
+-- | [日本語]: layer のデータを正規化座標に写す。 surface は grid の z と
+--   x/y range、 それ以外は点列。 colormap の色は z 正規化に対して不変 (affine)。
+--   [English]: Maps a layer's data into normalized coordinates. For a
+--   surface, this is the grid's z and the x/y range; for other layers, the
+--   point list. Colormap colors are invariant under z normalization
+--   (it's affine).
 normLayer3D :: Axes3D -> Layer3D -> Layer3D
 normLayer3D ax l0 = case getFirst (lyr3Kind l) of
   Just M3Surface ->
@@ -430,9 +521,13 @@
                , lyr3Labels = Last (Just (map snd annots)) }
           _ -> l0
 
--- | Phase 24 A2: パネル右端の縦 colorbar (gradient strip + min/mid/max ラベル)。
+-- | [日本語]: パネル右端の縦 colorbar (gradient strip + min/mid/max ラベル)。
 --   2D の gradient bar 凡例と同じ 'continuousColor' 補間 = palette 整合。
---   Phase 24 A7: パネル矩形 @(px,py,pw,ph)@ 局所座標で配置 (facet 対応)。
+--   パネル矩形 @(px,py,pw,ph)@ 局所座標で配置 (facet 対応)。
+--   [English]: The vertical colorbar (a gradient strip plus min/mid/max
+--   labels) along the panel's right edge, using the same 'continuousColor'
+--   interpolation as the 2D gradient-bar legend (palette-consistent).
+--   Positioned in panel-local coordinates @(px,py,pw,ph)@ (supports facets).
 renderColorbar3D :: Double -> Double -> Double -> Double -> ([Text], Double, Double) -> [Primitive]
 renderColorbar3D px py pw ph (stops, zMin, zMax) =
   let barW = 14 :: Double
@@ -456,14 +551,16 @@
   in map strip [0 .. nStrip - 1]
      <> map tick [zMin, (zMin + zMax) / 2, zMax]
 
--- | tick 値の短い整形 (Axes3D の formatNum と同形)。
+-- | [日本語]: tick 値の短い整形 (Axes3D の formatNum と同形)。
+--   [English]: A compact formatting for tick values (the same shape as
+--   Axes3D's formatNum).
 fmtNum3D :: Double -> Text
 fmtNum3D x =
   let s = T.pack (show (fromIntegral (round (x * 10) :: Int) / 10.0 :: Double))
   in T.dropWhileEnd (== '.') (T.dropWhileEnd (== '0') s)
 
--- | Phase 24 A5 / #2: surface の contour を壁面へ投影する (matplotlib
--- @contour(..., zdir=)@ 相当)。 'lyr3Contours' の各 @(dir, n)@ を描く:
+-- | [日本語]: surface の contour を壁面へ投影する (matplotlib
+--   @contour(..., zdir=)@ 相当)。 'lyr3Contours' の各 @(dir, n)@ を描く:
 --
 --   * 'ContourZ' (床) = z 等値面 level set @{f=z_k}@ を 'marchingSegments' で抽出し
 --     floor へ落とす (topographic map)。
@@ -471,9 +568,27 @@
 --     @z = f(x_k, y)@ を yz 壁へ描く。
 --   * 'ContourY' (前後壁) = y 軸の @n@ 位置で断面 @z = f(x, y_k)@ を xz 壁へ描く。
 --
--- 投影壁は **カメラから遠い面に自動固定** (eye と target の各軸符号で min/max 面を選ぶ・
--- 曲面の手前に出て遮らないように)。 grid・aspect 正規化済 layer を受ける。 mpl の
--- rotate_axes 経路 (= dir⊥平面で切った断面を壁へ投影) を再現 (実測で数値突合済)。
+--   投影壁は __カメラから遠い面に自動固定__ (eye と target の各軸符号で min/max 面を選ぶ・
+--   曲面の手前に出て遮らないように)。 grid・aspect 正規化済 layer を受ける。 mpl の
+--   rotate_axes 経路 (= dir⊥平面で切った断面を壁へ投影) を再現 (実測で数値突合済)。
+--   [English]: Projects a surface's contour onto a wall (equivalent to
+--   matplotlib's @contour(..., zdir=)@). Draws each @(dir, n)@ from
+--   'lyr3Contours':
+--
+--   * 'ContourZ' (floor) — extracts the z level-set contour @{f=z_k}@ via
+--     'marchingSegments' and drops it onto the floor (a topographic map).
+--   * 'ContourX' (left/right wall) — slices the surface at @n@ positions
+--     along x, drawing the cross-section profile @z = f(x_k, y)@ on the yz
+--     wall.
+--   * 'ContourY' (front/back wall) — draws the cross-section
+--     @z = f(x, y_k)@ at @n@ positions along y on the xz wall.
+--
+--   The projection wall __auto-pins to the far face from the camera__
+--   (chosen from the eye's and target's sign along each axis, so it never
+--   gets in front of the surface and occludes it). Takes an
+--   already grid- and aspect-normalized layer. Reproduces matplotlib's
+--   rotate_axes path (projecting a cross-section cut perpendicular to
+--   @dir@ onto the wall); verified numerically against it.
 renderProjectedContour3D
   :: (Double, Double, Double)
   -> Camera3D -> Projection3D -> Viewport -> Layer3D -> [Primitive]
@@ -532,8 +647,12 @@
               in concatMap section (innerLevels nLev yMin yMax)
         in concatMap one cs
 
--- | 1 次元線形補間。 @interp1 nodes vals p@ は昇順 @nodes@ 上の値 @vals@ を位置 @p@ で
--- 補間 (範囲外は端値で clamp・隣接 2 点で線形)。 断面 contour の grid 補間に使う。
+-- | [日本語]: 1 次元線形補間。 @interp1 nodes vals p@ は昇順 @nodes@ 上の値 @vals@ を位置 @p@ で
+--   補間 (範囲外は端値で clamp・隣接 2 点で線形)。 断面 contour の grid 補間に使う。
+--   [English]: 1D linear interpolation. @interp1 nodes vals p@ interpolates
+--   the values @vals@ over ascending @nodes@ at position @p@ (out-of-range
+--   is clamped to the endpoint value; linear between the two neighbors).
+--   Used for grid interpolation in cross-section contours.
 interp1 :: [Double] -> [Double] -> Double -> Double
 interp1 nodes vals p = go (zip nodes vals)
   where
diff --git a/src/Graphics/Hgg/ThreeD/Line.hs b/src/Graphics/Hgg/ThreeD/Line.hs
--- a/src/Graphics/Hgg/ThreeD/Line.hs
+++ b/src/Graphics/Hgg/ThreeD/Line.hs
@@ -1,6 +1,6 @@
 -- |
 -- Module      : Graphics.Hgg.ThreeD.Line
--- Description : 3D 線 / wireframe (Phase 3 A6)
+-- Description : 3D lines and wireframes
 -- Copyright   : (c) 2026 Aelysce Project (Toshiaki Honda)
 -- License     : BSD-3-Clause
 {-# LANGUAGE DeriveGeneric     #-}
@@ -86,15 +86,24 @@
   in map mkLine sorted
 
 -- ===========================================================================
--- Phase 26 A3: 3D vector field (quiver3D)
+-- 3D vector field (quiver3D)
 -- ===========================================================================
 
--- | 3D vector field。 各矢印は始点 'q3Starts' → 終点 'q3Ends' (= 正規化済・
--- autoscale + aspect 適用後の点列)。 描画は両端を投影して 2D 矢印 (本線 + 矢じり)
--- にする (= mplot3d も実質 2D 矢じり)。 depth 統合外の前面 overlay。
+-- | [日本語]: 3D vector field。 各矢印は始点 'q3Starts' → 終点 'q3Ends' (= 正規化済・
+--   autoscale + aspect 適用後の点列)。 描画は両端を投影して 2D 矢印 (本線 + 矢じり)
+--   にする (= mplot3d も実質 2D 矢じり)。 depth 統合外の前面 overlay。
+--   [English]: A 3D vector field. Each arrow runs from a start point
+--   'q3Starts' to an end point 'q3Ends' (already normalized — the point
+--   lists have autoscale and aspect already applied). Rendering projects
+--   both endpoints and draws a 2D arrow (shaft plus arrowhead), the same
+--   way mplot3d effectively draws 2D arrowheads too. Drawn as a front
+--   overlay, outside of depth integration.
 data Quiver3D = Quiver3D
-  { q3Starts :: ![Point3]   -- ^ 矢印の始点 (正規化済)
-  , q3Ends   :: ![Point3]   -- ^ 矢印の終点 (正規化済・始点 + scaled vec)
+  { q3Starts :: ![Point3]   -- ^ [日本語]: 矢印の始点 (正規化済)
+                             --   [English]: The arrow's start point (already normalized).
+  , q3Ends   :: ![Point3]   -- ^ [日本語]: 矢印の終点 (正規化済・始点 + scaled vec)
+                             --   [English]: The arrow's end point (already normalized;
+                             --   start point plus the scaled vector).
   , q3Color  :: !Text
   , q3Width  :: !Double
   } deriving (Show, Eq, Generic)
@@ -115,8 +124,11 @@
           Projected ex ey _ = project e
       in arrowHead2D sx sy ex ey style
 
--- | 投影後の 2D 矢印 (本線 + 矢じり 2 本)。 矢じり形状は 2D quiver
--- (core Render.Basic drawArrow2D) と同じ (長さ 9px・開き比 0.5)。
+-- | [日本語]: 投影後の 2D 矢印 (本線 + 矢じり 2 本)。 矢じり形状は 2D quiver
+--   (core Render.Basic drawArrow2D) と同じ (長さ 9px・開き比 0.5)。
+--   [English]: The projected 2D arrow (a shaft plus two arrowhead lines).
+--   The arrowhead shape matches the 2D quiver's (core Render.Basic
+--   drawArrow2D): length 9px, spread ratio 0.5.
 arrowHead2D :: Double -> Double -> Double -> Double -> LineStyle -> [Primitive]
 arrowHead2D px1 py1 px2 py2 ls =
   let dx = px2 - px1; dy = py2 - py1
diff --git a/src/Graphics/Hgg/ThreeD/Projection.hs b/src/Graphics/Hgg/ThreeD/Projection.hs
--- a/src/Graphics/Hgg/ThreeD/Projection.hs
+++ b/src/Graphics/Hgg/ThreeD/Projection.hs
@@ -1,18 +1,28 @@
 -- |
 -- Module      : Graphics.Hgg.ThreeD.Projection
--- Description : 3D → 2D 投影 (Phase 3 A3)
+-- Description : 3D to 2D projection
 -- Copyright   : (c) 2026 Aelysce Project (Toshiaki Honda)
 -- License     : BSD-3-Clause
 --
--- 標準 3D グラフィックス pipeline:
+-- [日本語]: 標準 3D グラフィックス pipeline:
 --
 --   world space → (view 行列、 lookAt) → camera space
 --               → (projection 行列、 ortho or persp) → clip space
 --               → (perspective divide) → NDC (= [-1, 1]^3)
 --               → (viewport 変換) → 2D screen 座標
 --
--- 'project3D' が全 step をまとめて (Point3 world → Point2D screen + zClip) を返す。
--- z は depth cue (= painter's algorithm の sort key) に使う。
+--   'project3D' が全 step をまとめて (Point3 world → Point2D screen + zClip) を返す。
+--   z は depth cue (= painter's algorithm の sort key) に使う。
+-- [English]: The standard 3D graphics pipeline:
+--
+--   world space → (view matrix, lookAt) → camera space
+--               → (projection matrix, ortho or persp) → clip space
+--               → (perspective divide) → NDC (@[-1, 1]^3@)
+--               → (viewport transform) → 2D screen coordinates
+--
+--   'project3D' bundles every step and returns (Point3 world to Point2D
+--   screen + zClip). z is used as a depth cue (the sort key for the
+--   painter's algorithm).
 {-# LANGUAGE BangPatterns #-}
 module Graphics.Hgg.ThreeD.Projection
   ( -- * Matrix 演算
@@ -36,11 +46,13 @@
 -- Matrix 基本演算 (= 4x4)
 -- ===========================================================================
 
--- | 単位行列。
+-- | [日本語]: 単位行列。
+--   [English]: The identity matrix.
 identityM :: Mat4
 identityM = Mat4 1 0 0 0  0 1 0 0  0 0 1 0  0 0 0 1
 
--- | 行列積 (= row-major、 自分 × 引数)。
+-- | [日本語]: 行列積 (= row-major、 自分 × 引数)。
+--   [English]: Matrix multiplication (row-major, @self × argument@).
 multM :: Mat4 -> Mat4 -> Mat4
 multM
   (Mat4 a11 a12 a13 a14
@@ -72,8 +84,11 @@
     (a41*b13 + a42*b23 + a43*b33 + a44*b43)
     (a41*b14 + a42*b24 + a43*b34 + a44*b44)
 
--- | Point3 を 4x4 行列で変換 (= 同次座標で w=1 として扱い、 結果も Point3 返す)。
--- w 成分は別途扱うので 'project3D' を経由するのが通常。
+-- | [日本語]: Point3 を 4x4 行列で変換 (= 同次座標で w=1 として扱い、 結果も Point3 返す)。
+--   w 成分は別途扱うので 'project3D' を経由するのが通常。
+--   [English]: Transforms a 'Point3' by a 4x4 matrix (treats the homogeneous
+--   w component as 1 and returns a 'Point3' too). Since the w component
+--   needs separate handling, going through 'project3D' is the usual path.
 transformPoint :: Mat4 -> Point3 -> Point3
 transformPoint
   (Mat4 m11 m12 m13 m14
@@ -90,10 +105,16 @@
 -- View 行列 (= lookAt) / Projection 行列
 -- ===========================================================================
 
--- | lookAt: camera の view 行列を生成。 右手系、 OpenGL 流。
+-- | [日本語]: lookAt: camera の view 行列を生成。 右手系、 OpenGL 流。
 --
--- 結果: world space の点 P に対し viewMatrix * P が camera space の P' を返す。
--- camera space では camera が原点、 -z 方向を向く (= 右手系 OpenGL 慣例)。
+--   結果: world space の点 P に対し viewMatrix * P が camera space の P' を返す。
+--   camera space では camera が原点、 -z 方向を向く (= 右手系 OpenGL 慣例)。
+--   [English]: lookAt: builds the camera's view matrix. Right-handed,
+--   OpenGL-style.
+--
+--   Result: for a point P in world space, @viewMatrix * P@ gives P' in
+--   camera space. In camera space, the camera sits at the origin and looks
+--   down -z (the right-handed OpenGL convention).
 viewMatrix :: Camera3D -> Mat4
 viewMatrix (Camera3D (Point3 ex ey ez) (Point3 tx ty tz) up) =
   let -- forward = normalize(target - eye)、 ただし camera は -z を向くので f は実は反転して使う
@@ -112,10 +133,16 @@
        (-fx)    (-fy)    (-fz)    tz'
        0        0        0        1
 
--- | Projection 行列を生成。 'Orthographic' / 'Perspective' どちらも対応。
+-- | [日本語]: Projection 行列を生成。 'Orthographic' / 'Perspective' どちらも対応。
 --
--- 出力: camera space の点 P → clip space の P' (= w 成分も含む)。
--- 'project3D' で perspective divide (= x,y,z を w で割る) を続けて NDC へ。
+--   出力: camera space の点 P → clip space の P' (= w 成分も含む)。
+--   'project3D' で perspective divide (= x,y,z を w で割る) を続けて NDC へ。
+--   [English]: Builds the projection matrix. Handles both 'Orthographic' and
+--   'Perspective'.
+--
+--   Output: for a point P in camera space, produces P' in clip space
+--   (including the w component). 'project3D' follows up with the
+--   perspective divide (dividing x, y, z by w) to reach NDC.
 projectionMatrix :: Projection3D -> Mat4
 projectionMatrix (Orthographic xH yH n f) =
   let !sx = 1 / xH
@@ -135,8 +162,11 @@
 -- Projection 一発
 -- ===========================================================================
 
--- | Viewport: NDC (= [-1, 1]^2) → screen pixel への変換パラメタ。
--- 通常 Layout 領域に合わせて (xMin, yMin, width, height) で指定。
+-- | [日本語]: Viewport: NDC (= [-1, 1]^2) → screen pixel への変換パラメタ。
+--   通常 Layout 領域に合わせて (xMin, yMin, width, height) で指定。
+--   [English]: Viewport: the parameters for converting NDC (@[-1, 1]^2@) to
+--   screen pixels. Usually specified as (xMin, yMin, width, height) to match
+--   the layout region.
 data Viewport = Viewport
   { vpX :: !Double
   , vpY :: !Double
@@ -144,23 +174,34 @@
   , vpH :: !Double
   } deriving (Show, Eq)
 
--- | NDC [-1,1] の (x, y) → screen pixel への変換。 y は反転 (= SVG 慣例で y 下方向)。
+-- | [日本語]: NDC [-1,1] の (x, y) → screen pixel への変換。 y は反転 (= SVG 慣例で y 下方向)。
+--   [English]: Converts NDC @[-1,1]@ (x, y) to screen pixels. y is flipped
+--   (following the SVG convention where y points down).
 viewportTransform :: Viewport -> Double -> Double -> (Double, Double)
 viewportTransform (Viewport vx vy vw vh) ndcX ndcY =
   let sx = vx + (ndcX + 1) / 2 * vw
       sy = vy + (1 - (ndcY + 1) / 2) * vh
   in (sx, sy)
 
--- | 投影結果。 screen 座標 (= viewport 変換後) + z (= depth cue / sort 用、 NDC z)。
+-- | [日本語]: 投影結果。 screen 座標 (= viewport 変換後) + z (= depth cue / sort 用、 NDC z)。
+--   [English]: The projection result: screen coordinates (after the
+--   viewport transform) plus z (the NDC z, used as a depth cue / sort key).
 data Projected = Projected
-  { projX     :: !Double  -- ^ screen pixel x
-  , projY     :: !Double  -- ^ screen pixel y
-  , projDepth :: !Double  -- ^ NDC z ∈ [-1, 1]、 -1 が手前、 +1 が奥
+  { projX     :: !Double  -- ^ [日本語]: screen pixel x
+                           --   [English]: The screen pixel x coordinate.
+  , projY     :: !Double  -- ^ [日本語]: screen pixel y
+                           --   [English]: The screen pixel y coordinate.
+  , projDepth :: !Double  -- ^ [日本語]: NDC z ∈ [-1, 1]、 -1 が手前、 +1 が奥
+                           --   [English]: The NDC z ∈ [-1, 1]; -1 is nearest, +1 is farthest.
   } deriving (Show, Eq)
 
--- | World point → Projected (screen + depth)。
+-- | [日本語]: World point → Projected (screen + depth)。
 --
--- pipeline: world → view → projection → perspective divide → viewport。
+--   pipeline: world → view → projection → perspective divide → viewport。
+--   [English]: Converts a world point to 'Projected' (screen + depth).
+--
+--   Pipeline: world to view to projection to perspective divide to
+--   viewport.
 project3D :: Camera3D -> Projection3D -> Viewport -> Point3 -> Projected
 project3D cam proj vp p =
   let view = viewMatrix cam
diff --git a/src/Graphics/Hgg/ThreeD/Scatter.hs b/src/Graphics/Hgg/ThreeD/Scatter.hs
--- a/src/Graphics/Hgg/ThreeD/Scatter.hs
+++ b/src/Graphics/Hgg/ThreeD/Scatter.hs
@@ -1,11 +1,16 @@
 -- |
 -- Module      : Graphics.Hgg.ThreeD.Scatter
--- Description : 3D scatter plot (Phase 3 A5)
+-- Description : 3D scatter plot
 -- Copyright   : (c) 2026 Aelysce Project (Toshiaki Honda)
 -- License     : BSD-3-Clause
 --
--- 3D 点群を camera + projection で 2D に変換し、 painter's algorithm (= z で sort、
--- 奥から手前へ) で描画。 depth cue として size と alpha を z で線形に減衰させる。
+-- [日本語]: 3D 点群を camera + projection で 2D に変換し、 painter's algorithm
+--   (= z で sort、 奥から手前へ) で描画。 depth cue として size と alpha を z で
+--   線形に減衰させる。
+-- [English]: Converts a 3D point cloud into 2D via the camera and
+--   projection, then renders it with the painter's algorithm (sorted by z,
+--   drawn from back to front). Size and alpha fade linearly with z as a
+--   depth cue.
 {-# LANGUAGE DeriveGeneric     #-}
 {-# LANGUAGE OverloadedStrings #-}
 module Graphics.Hgg.ThreeD.Scatter
@@ -27,39 +32,65 @@
                                                   project3D)
 import           Graphics.Hgg.ThreeD.Types
 
--- | 3D scatter 1 series 分の設定。
+-- | [日本語]: 3D scatter 1 series 分の設定。
+--   [English]: The configuration for one series of a 3D scatter plot.
 data Scatter3D = Scatter3D
-  { sc3Points :: ![Point3]   -- ^ 3D 点群
-  , sc3Color  :: !Text       -- ^ 色 (= hex 例 "#1f77b4")
-  , sc3Size   :: !Double     -- ^ 基本 size (= 近側の半径 px、 奥は depth cue で小さく)
-  , sc3Alpha  :: !Double     -- ^ 基本 alpha (= 近側の値、 奥は depth cue で薄く)
+  { sc3Points :: ![Point3]   -- ^ [日本語]: 3D 点群
+                              --   [English]: The 3D point cloud.
+  , sc3Color  :: !Text       -- ^ [日本語]: 色 (= hex 例 "#1f77b4")
+                              --   [English]: The color (hex, e.g. "#1f77b4").
+  , sc3Size   :: !Double     -- ^ [日本語]: 基本 size (= 近側の半径 px、 奥は depth cue で小さく)
+                              --   [English]: The base size (the near-side radius in
+                              --   px; farther points shrink via the depth cue).
+  , sc3Alpha  :: !Double     -- ^ [日本語]: 基本 alpha (= 近側の値、 奥は depth cue で薄く)
+                              --   [English]: The base alpha (the near-side value;
+                              --   farther points fade via the depth cue).
   , sc3Colors :: !(Maybe [Text])
-    -- ^ Phase 25 A2: 点ごとの色 (= 群色分け / 連続色マップ)。 @Just cs@ で
+    -- ^ [日本語]: 点ごとの色 (= 群色分け / 連続色マップ)。 @Just cs@ で
     --   @cs !! i@ を点 i に使う (長さが点数未満なら超過点は 'sc3Color')。
     --   @Nothing@ = 全点 'sc3Color' (後方互換)。
+    --   [English]: A per-point color (for group coloring or a continuous
+    --   colormap). With @Just cs@, point i uses @cs !! i@ (points beyond the
+    --   list's length fall back to 'sc3Color'). @Nothing@ means every point
+    --   uses 'sc3Color' (backward compatible).
   , sc3Sizes  :: !(Maybe [Double])
-    -- ^ Phase 25 A3: 点ごとの基本 size (= 値マップ bubble)。 @Just ss@ で
+    -- ^ [日本語]: 点ごとの基本 size (= 値マップ bubble)。 @Just ss@ で
     --   @ss !! i@ を点 i の基本半径に使う (長さが点数未満なら超過点は 'sc3Size')。
     --   @Nothing@ = 全点 'sc3Size' (後方互換)。 depth cue は基本 size に乗算。
+    --   [English]: A per-point base size (a value-mapped bubble). With
+    --   @Just ss@, point i's base radius is @ss !! i@ (points beyond the
+    --   list's length fall back to 'sc3Size'). @Nothing@ means every point
+    --   uses 'sc3Size' (backward compatible). The depth cue multiplies the
+    --   base size.
   } deriving (Show, Eq, Generic)
 instance ToJSON   Scatter3D
 instance FromJSON Scatter3D
 
--- | default: 青、 size 5、 alpha 0.85、 単色・単 size (per-point 無し)。
+-- | [日本語]: default: 青、 size 5、 alpha 0.85、 単色・単 size (per-point 無し)。
+--   [English]: The default: blue, size 5, alpha 0.85, a single color and
+--   size (no per-point overrides).
 defaultScatter3D :: [Point3] -> Scatter3D
 defaultScatter3D ps = Scatter3D ps "#1f77b4" 5 0.85 Nothing Nothing
 
--- | 3D scatter を 2D Primitive (= PCircle) 列に変換。
--- z で sort して painter's (= 奥から描画)、 size / alpha は depth cue で減衰。
+-- | [日本語]: 3D scatter を 2D Primitive (= PCircle) 列に変換。
+--   z で sort して painter's (= 奥から描画)、 size / alpha は depth cue で減衰。
+--   [English]: Converts a 3D scatter into a list of 2D primitives (@PCircle@).
+--   Sorted by z for the painter's algorithm (drawn back-to-front); size and
+--   alpha fade via the depth cue.
 renderScatter3D
   :: Camera3D -> Projection3D -> Viewport
   -> Scatter3D -> [Primitive]
 renderScatter3D cam proj vp sc =
   map snd (sortOn (negate . fst) (scatterPointsDepth cam proj vp sc))
 
--- | Phase 24 A8 (depth 統合): 各点を @(投影 depth, PCircle)@ として**未ソート**で
--- 返す (= 'renderScatter3D' は @sortOn (negate.fst)@ → @map snd@・ビット同一)。
--- surface 面との層横断 depth 統合に使う (scatter 点が膜を透ける問題の解消)。
+-- | [日本語]: (depth 統合): 各点を @(投影 depth, PCircle)@ として__未ソート__で
+--   返す (= 'renderScatter3D' は @sortOn (negate.fst)@ → @map snd@・ビット同一)。
+--   surface 面との層横断 depth 統合に使う (scatter 点が膜を透ける問題の解消)。
+--   [English]: (depth integration): Returns each point as
+--   @(projected depth, PCircle)@, __unsorted__ ('renderScatter3D' is
+--   bit-identical to @sortOn (negate . fst)@ followed by @map snd@ of this).
+--   Used to integrate depth across layers together with surface faces
+--   (fixing scatter points showing through a surface).
 scatterPointsDepth
   :: Camera3D -> Projection3D -> Viewport
   -> Scatter3D -> [(Double, Primitive)]
diff --git a/src/Graphics/Hgg/ThreeD/Spec.hs b/src/Graphics/Hgg/ThreeD/Spec.hs
--- a/src/Graphics/Hgg/ThreeD/Spec.hs
+++ b/src/Graphics/Hgg/ThreeD/Spec.hs
@@ -1,11 +1,11 @@
 -- |
 -- Module      : Graphics.Hgg.ThreeD.Spec
--- Description : 3D VisualSpec / Layer + Monoid (Phase 5 A3)
+-- Description : 3D VisualSpec / Layer types with a Monoid instance
 -- Copyright   : (c) 2026 Aelysce Project (Toshiaki Honda)
 -- License     : BSD-3-Clause
 --
--- 2D 同型 (= Graphics.Hgg.Spec の 'VisualSpec' / 'Layer' / Monoid 構成) を踏襲した
--- 3D 用 spec API。 ユーザ視点で 2D と同じ構文で組める:
+-- [日本語]: 2D 同型 (= Graphics.Hgg.Spec の 'Graphics.Hgg.Spec.VisualSpec' / 'Graphics.Hgg.Spec.Layer' / Monoid 構成) を踏襲した
+--   3D 用 spec API。 ユーザ視点で 2D と同じ構文で組める:
 --
 -- @
 -- -- 2D
@@ -16,13 +16,28 @@
 --            <> camera (defaultCameraZUp 3) <> axes3D defaultAxes3D <> title3D "..."
 -- @
 --
--- 値型は分離 (= 'Layer' と 'Layer3D' は別)。 理由は phase-5 計画 md §2.2。
+--   値型は分離 (= 'Graphics.Hgg.Spec.Layer' と 'Layer3D' は別)。 理由は phase-5 計画 md §2.2。
+-- [English]: A 3D spec API that mirrors the 2D one (the
+--   'Graphics.Hgg.Spec.VisualSpec' / 'Graphics.Hgg.Spec.Layer' / Monoid design in Graphics.Hgg.Spec). From a
+--   user's perspective, it's built with the exact same syntax as 2D:
+--
+-- @
+-- -- 2D
+-- purePlot <> layer (scatter x y <> color (fromHex "#ff0000") <> alpha 0.7) <> title "..."
+--
+-- -- 3D (100% syntax-identical)
+-- purePlot3D <> layer3D (scatter3D pts <> color3D (fromHex "#ff0000") <> alpha3D 0.7)
+--            <> camera (defaultCameraZUp 3) <> axes3D defaultAxes3D <> title3D "..."
+-- @
+--
+--   The value types are kept separate ('Graphics.Hgg.Spec.Layer' and 'Layer3D' are distinct
+--   types); see phase-5 plan md §2.2 for why.
 {-# LANGUAGE DeriveGeneric     #-}
 {-# LANGUAGE OverloadedStrings #-}
 module Graphics.Hgg.ThreeD.Spec
   ( -- * MarkKind3D
     Mark3DKind (..)
-    -- * Bar スタイル (Phase 25 A5・Bar module 再 export)
+    -- * Bar スタイル (Bar module 再 export)
   , BarStyle3D (..)
     -- * Layer3D (= 1 layer の per-field Monoid)
   , Layer3D (..)
@@ -30,7 +45,7 @@
   , VisualSpec3D (..)
     -- * 純粋起点
   , purePlot3D
-    -- * Layer 起点 (= 2D 'layer' 同型)
+    -- * Layer 起点 (= 2D 'Graphics.Hgg.Spec.layer' 同型)
   , layer3D
     -- * Mark コンストラクタ (= Layer3D 返却)
   , scatter3D
@@ -97,7 +112,7 @@
   , layerToSurface
   , layerToBar
   , layerToQuiver
-    -- * 列参照の解決 (Phase 24 A6)
+    -- * 列参照の解決
   , resolveLayer3D
   , resolveSpec3D
     -- * Helper: layers から bounding box 自動算出 (= Axes 未指定時の default)
@@ -135,7 +150,9 @@
 -- MarkKind3D
 -- ===========================================================================
 
--- | 3D layer の幾何種別 (= 2D 'MarkKind' の 3D 版)。
+-- | [日本語]: 3D layer の幾何種別 (= 2D 'Graphics.Hgg.Spec.MarkKind' の 3D 版)。
+--   [English]: A 3D layer's geometry kind (the 3D counterpart of 2D
+--   'Graphics.Hgg.Spec.MarkKind').
 data Mark3DKind
   = M3Scatter
   | M3Line
@@ -151,14 +168,21 @@
 instance FromJSON Mark3DKind
 
 -- ===========================================================================
--- Layer3D (= 2D 'Layer' 同型、 per-field First/Last Monoid)
+-- Layer3D (= 2D 'Graphics.Hgg.Spec.Layer' 同型、 per-field First/Last Monoid)
 -- ===========================================================================
 
--- | 3D 1 layer の rolled-up 表現。 全 field が 'First' or 'Last' なので per-field
---   '(<>)' で自然に合成可能 (= 2D 'Layer' と同じ規律)。
+-- | [日本語]: 3D 1 layer の rolled-up 表現。 全 field が 'First' or 'Last' なので per-field
+--   '(<>)' で自然に合成可能 (= 2D 'Graphics.Hgg.Spec.Layer' と同じ規律)。
 --
---   * 'lyr3Kind' は 'First' (= 最初に設定した kind が勝つ、 2D 'lyKind' と同じ)
---   * その他属性は 'Last' (= 後勝ち、 2D 'lyColor' 等と同じ)
+--   * 'lyr3Kind' は 'First' (= 最初に設定した kind が勝つ、 2D @lyKind@ と同じ)
+--   * その他属性は 'Last' (= 後勝ち、 2D @lyColor@ 等と同じ)
+--   [English]: The rolled-up representation of a single 3D layer. Every
+--   field is 'First' or 'Last', so per-field @(\<\>)@ composes naturally
+--   (the same discipline as 2D 'Graphics.Hgg.Spec.Layer').
+--
+--   * 'lyr3Kind' is 'First' (the first kind set wins, same as 2D @lyKind@)
+--   * every other attribute is 'Last' (last one wins, same as 2D @lyColor@
+--     and friends)
 data Layer3D = Layer3D
   { lyr3Kind      :: !(First Mark3DKind)
   , lyr3Points    :: !(Last [Point3])
@@ -261,10 +285,12 @@
                    mempty mempty mempty mempty mempty mempty
 
 -- ===========================================================================
--- VisualSpec3D (= 2D 'VisualSpec' 同型、 layers ++ + per-field Last)
+-- VisualSpec3D (= 2D 'Graphics.Hgg.Spec.VisualSpec' 同型、 layers ++ + per-field Last)
 -- ===========================================================================
 
--- | 3D 図全体の spec。 'layers' は append、 その他は 'Last' (= 後勝ち)。
+-- | [日本語]: 3D 図全体の spec。 @layers@ は append、 その他は 'Last' (= 後勝ち)。
+--   [English]: The spec for an entire 3D figure. @layers@ appends; every
+--   other field is 'Last' (last one wins).
 data VisualSpec3D = VisualSpec3D
   { vs3Layers     :: ![Layer3D]
   , vs3Title      :: !(Last Text)
@@ -296,14 +322,18 @@
                         mempty mempty mempty
 
 -- ===========================================================================
--- 純粋起点 + lift helpers (= 2D 'purePlot' / 'layer' 同型)
+-- 純粋起点 + lift helpers (= 2D 'Graphics.Hgg.Spec.purePlot' / 'Graphics.Hgg.Spec.layer' 同型)
 -- ===========================================================================
 
--- | 'VisualSpec3D' 起点 (= 2D 'purePlot' 同型、 'mempty' alias)。
+-- | [日本語]: 'VisualSpec3D' 起点 (= 2D 'Graphics.Hgg.Spec.purePlot' 同型、 'mempty' alias)。
+--   [English]: The 'VisualSpec3D' starting point (the counterpart of 2D
+--   'Graphics.Hgg.Spec.purePlot'; an alias for 'mempty').
 purePlot3D :: VisualSpec3D
 purePlot3D = mempty
 
--- | 'Layer3D' を 'VisualSpec3D' に lift (= 2D 'layer' 同型)。
+-- | [日本語]: 'Layer3D' を 'VisualSpec3D' に lift (= 2D 'Graphics.Hgg.Spec.layer' 同型)。
+--   [English]: Lifts a 'Layer3D' into a 'VisualSpec3D' (the counterpart of
+--   2D 'Graphics.Hgg.Spec.layer').
 layer3D :: Layer3D -> VisualSpec3D
 layer3D l = mempty { vs3Layers = [l] }
 
@@ -311,37 +341,47 @@
 -- Mark コンストラクタ (= Layer3D を返却、 後で `<> color3D ...` で属性 append)
 -- ===========================================================================
 
--- | 3D scatter (= M3Scatter)。 Phase 24 A6: 2D 'Graphics.Hgg.Spec.scatter' と
--- 対称の **ColRef 3 つ** (x, y, z)。 列名 (OverloadedStrings) か 'inline' の
--- 生値を渡す。 旧 [Point3] 直入れは 'scatter3DPoints'。
+-- | [日本語]: 3D scatter (= M3Scatter)。 2D 'Graphics.Hgg.Spec.scatter' と
+--   対称の __ColRef 3 つ__ (x, y, z)。 列名 (OverloadedStrings) か 'Graphics.Hgg.Spec.inline' の
+--   生値を渡す。 旧 [Point3] 直入れは 'scatter3DPoints'。
+--   [English]: A 3D scatter (M3Scatter). Symmetric with 2D
+--   'Graphics.Hgg.Spec.scatter': __three ColRefs__ (x, y, z). Pass a column
+--   name (via OverloadedStrings) or raw 'Graphics.Hgg.Spec.inline' values. For the older
+--   direct @[Point3]@ form, use 'scatter3DPoints'.
 scatter3D :: ColRef -> ColRef -> ColRef -> Layer3D
 scatter3D x y z = mempty
   { lyr3Kind = First (Just M3Scatter)
   , lyr3EncX = Last (Just x), lyr3EncY = Last (Just y), lyr3EncZ = Last (Just z)
   }
 
--- | 3D scatter ([Point3] 直入れ・旧 'scatter3D')。
+-- | [日本語]: 3D scatter ([Point3] 直入れ・旧 'scatter3D')。
+--   [English]: A 3D scatter with @[Point3]@ passed directly (the older form
+--   of 'scatter3D').
 scatter3DPoints :: [Point3] -> Layer3D
 scatter3DPoints pts = mempty
   { lyr3Kind   = First (Just M3Scatter)
   , lyr3Points = Last  (Just pts)
   }
 
--- | 3D line (= MLine3D、 連続折れ線)。
+-- | [日本語]: 3D line (= MLine3D、 連続折れ線)。
+--   [English]: A 3D line (MLine3D, a continuous polyline).
 line3D :: ColRef -> ColRef -> ColRef -> Layer3D
 line3D x y z = mempty
   { lyr3Kind = First (Just M3Line)
   , lyr3EncX = Last (Just x), lyr3EncY = Last (Just y), lyr3EncZ = Last (Just z)
   }
 
--- | 3D line ([Point3] 直入れ・旧 'line3D')。
+-- | [日本語]: 3D line ([Point3] 直入れ・旧 'line3D')。
+--   [English]: A 3D line with @[Point3]@ passed directly (the older form of
+--   'line3D').
 line3DPoints :: [Point3] -> Layer3D
 line3DPoints pts = mempty
   { lyr3Kind   = First (Just M3Line)
   , lyr3Points = Last  (Just pts)
   }
 
--- | 3D wireframe (= MWireframe3D、 任意 edge 群)。
+-- | [日本語]: 3D wireframe (= MWireframe3D、 任意 edge 群)。
+--   [English]: A 3D wireframe (MWireframe3D, an arbitrary set of edges).
 wireframe3D :: [Point3] -> [(Int, Int)] -> Layer3D
 wireframe3D pts es = mempty
   { lyr3Kind   = First (Just M3Wireframe)
@@ -349,10 +389,16 @@
   , lyr3Edges  = Last  (Just es)
   }
 
--- | Phase 30 A6: 列駆動 3D surface (案C・= 2D 系と対称の ColRef 3 つ x/y/z)。 df の
---   long 形 (各行 = 格子点 (x,y,z)) を受け、 'resolveLayer3D' で **内部 pivot** して
+-- | [日本語]: 列駆動 3D surface (案C・= 2D 系と対称の ColRef 3 つ x/y/z)。 df の
+--   long 形 (各行 = 格子点 (x,y,z)) を受け、 'resolveLayer3D' で __内部 pivot__ して
 --   grid mesh ('lyr3Grid' + xRange/yRange) に落とす。 grid は x/y が規則格子である前提
 --   (= 全 (x_i,y_j) 組が揃う・欠損は NaN 穴)。 既に行列を持っている場合は 'surface3DGrid'。
+--   [English]: A column-driven 3D surface (plan C — symmetric with the 2D
+--   family's 3 ColRefs x/y/z). Takes a dataframe's long form (each row is a
+--   grid point (x,y,z)) and __pivots internally__ via 'resolveLayer3D' into
+--   a grid mesh ('lyr3Grid' plus xRange/yRange). Assumes x/y form a regular
+--   grid (every (x_i,y_j) pair is present; missing cells become NaN holes).
+--   If you already have a matrix, use 'surface3DGrid' instead.
 --
 --   @df |>> layer3D (surface3D \"x\" \"y\" \"z\" <> colormap3D)@
 surface3D :: ColRef -> ColRef -> ColRef -> Layer3D
@@ -361,33 +407,47 @@
   , lyr3EncX = Last (Just x), lyr3EncY = Last (Just y), lyr3EncZ = Last (Just z)
   }
 
--- | 3D surface (= MSurface3D、 grid mesh・行列直入れ・旧 'surface3D')。 z 値の
+-- | [日本語]: 3D surface (= MSurface3D、 grid mesh・行列直入れ・旧 'surface3D')。 z 値の
 --   2 次元配列を受け、 x/y 範囲は 'xRange3D'/'yRange3D' (既定 (-1,1)) で与える。
+--   [English]: A 3D surface (MSurface3D, a grid mesh with the matrix passed
+--   directly; the older form of 'surface3D'). Takes a 2D array of z values;
+--   the x/y range is given via 'xRange3D' / 'yRange3D' (default (-1,1)).
 surface3DGrid :: [[Double]] -> Layer3D
 surface3DGrid grid = mempty
   { lyr3Kind = First (Just M3Surface)
   , lyr3Grid = Last  (Just grid)
   }
 
--- | Phase 25 A5: 3D bar (= M3Bar)。 'scatter3D' と対称の ColRef 3 つ (x, y,
+-- | [日本語]: 3D bar (= M3Bar)。 'scatter3D' と対称の ColRef 3 つ (x, y,
 --   高さ z)。 各 (x,y) に底面 (data z=0) から高さ z までの棒を立てる。 既定は
 --   直方体 ('barStyle3D' で stick へ)。 [Point3] 直入れは 'bar3DPoints'。
+--   [English]: A 3D bar (M3Bar). Symmetric with 'scatter3D': three ColRefs
+--   (x, y, height z). Raises a bar at each (x,y) from the base (data z=0)
+--   to height z. Defaults to a cuboid (use 'barStyle3D' to switch to a
+--   stick). For direct @[Point3]@ input, use 'bar3DPoints'.
 bar3D :: ColRef -> ColRef -> ColRef -> Layer3D
 bar3D x y z = mempty
   { lyr3Kind = First (Just M3Bar)
   , lyr3EncX = Last (Just x), lyr3EncY = Last (Just y), lyr3EncZ = Last (Just z)
   }
 
--- | Phase 25 A5: 3D bar ([Point3] 直入れ・各点の z = 棒の高さ)。
+-- | [日本語]: 3D bar ([Point3] 直入れ・各点の z = 棒の高さ)。
+--   [English]: A 3D bar with @[Point3]@ passed directly (each point's z is
+--   the bar's height).
 bar3DPoints :: [Point3] -> Layer3D
 bar3DPoints tops = mempty
   { lyr3Kind   = First (Just M3Bar)
   , lyr3Points = Last  (Just tops)
   }
 
--- | Phase 26 A4: 3D stem (= M3Stem)。 'bar3D' と対称の ColRef 3 つ (x, y, z)。
+-- | [日本語]: 3D stem (= M3Stem)。 'bar3D' と対称の ColRef 3 つ (x, y, z)。
 --   各 (x,y) に底面 ('stemBaseZ'・既定 0) から z までの細い垂線 + 先端マーカーを
 --   描く (3D lollipop)。 [Point3] 直入れは 'stem3DPoints'。 底面は 'stemBaseZ' で変更。
+--   [English]: A 3D stem (M3Stem). Symmetric with 'bar3D': three ColRefs
+--   (x, y, z). Draws a thin vertical line plus a tip marker (a 3D lollipop)
+--   from the base ('stemBaseZ', default 0) up to z at each (x,y). For
+--   direct @[Point3]@ input, use 'stem3DPoints'. Change the base with
+--   'stemBaseZ'.
 --
 --   @stem3D \"x\" \"y\" \"z\" <> color3D (fromHex \"#d62728\") <> stemBaseZ 0@
 stem3D :: ColRef -> ColRef -> ColRef -> Layer3D
@@ -396,21 +456,31 @@
   , lyr3EncX = Last (Just x), lyr3EncY = Last (Just y), lyr3EncZ = Last (Just z)
   }
 
--- | Phase 26 A4: 3D stem ([Point3] 直入れ・各点の z = stem の先端高さ)。
+-- | [日本語]: 3D stem ([Point3] 直入れ・各点の z = stem の先端高さ)。
+--   [English]: A 3D stem with @[Point3]@ passed directly (each point's z is
+--   the stem's tip height).
 stem3DPoints :: [Point3] -> Layer3D
 stem3DPoints tops = mempty
   { lyr3Kind   = First (Just M3Stem)
   , lyr3Points = Last  (Just tops)
   }
 
--- | Phase 26 A4: stem の底面 z (data 空間・既定 0)。 mplot3d @stem(..., bottom=)@ 相当。
---   'normLayer3D' が axes に基づき正規化して 'lyr3BarBaseZ' へ落とす。
+-- | [日本語]: stem の底面 z (data 空間・既定 0)。 mplot3d @stem(..., bottom=)@ 相当。
+--   'Graphics.Hgg.ThreeD.Easy.normLayer3D' が axes に基づき正規化して 'lyr3BarBaseZ' へ落とす。
+--   [English]: The stem's base z (in data space, default 0). Equivalent to
+--   mplot3d's @stem(..., bottom=)@. 'Graphics.Hgg.ThreeD.Easy.normLayer3D' normalizes it based on
+--   the axes and stores it into 'lyr3BarBaseZ'.
 stemBaseZ :: Double -> Layer3D
 stemBaseZ z = mempty { lyr3StemBaseZ = Last (Just z) }
 
--- | Phase 26 A3: 3D vector field (= M3Quiver)。 各 @(位置, ベクトル)@ に矢印を描く
+-- | [日本語]: 3D vector field (= M3Quiver)。 各 @(位置, ベクトル)@ に矢印を描く
 --   (= mplot3d @quiver@)。 矢印長は autoscale (= 最長矢印が cube の ~35%) に
 --   'vecScale3D' 倍を掛けた長さ。 描画は投影後の 2D 矢印 (本線 + 矢じり)。
+--   [English]: A 3D vector field (M3Quiver). Draws an arrow at each
+--   @(position, vector)@ (equivalent to mplot3d's @quiver@). Arrow length
+--   is autoscaled (the longest arrow becomes ~35% of the cube), multiplied
+--   by 'vecScale3D'. Rendering draws the projected 2D arrow (shaft plus
+--   arrowhead).
 --
 --   @quiver3D [(Point3 0 0 0, Vec3 1 0 0), (Point3 1 1 1, Vec3 0 0 1)]@
 quiver3D :: [(Point3, Vec3)] -> Layer3D
@@ -420,13 +490,20 @@
   , lyr3Vectors = Last  (Just (map snd items))
   }
 
--- | Phase 26 A3: quiver3D 矢印長の倍率 (autoscale × この値・既定 1)。
+-- | [日本語]: quiver3D 矢印長の倍率 (autoscale × この値・既定 1)。
+--   [English]: The multiplier on quiver3D's arrow length (autoscale times
+--   this value, default 1).
 vecScale3D :: Double -> Layer3D
 vecScale3D s = mempty { lyr3VecScale = Last (Just s) }
 
--- | Phase 26 A5: trisurf (= M3Trisurf)。 不規則 (非 grid) な 3D 点群を (x,y) 平面で
+-- | [日本語]: trisurf (= M3Trisurf)。 不規則 (非 grid) な 3D 点群を (x,y) 平面で
 --   Delaunay 三角分割して曲面化する (= mplot3d @plot_trisurf@)。 散らばった観測点・
 --   GP 事後点など、 規則 grid でない曲面を描ける。 z 連続色は 'colormap3D' で。
+--   [English]: trisurf (M3Trisurf). Surfaces an irregular (non-grid) 3D
+--   point cloud by Delaunay-triangulating it in the (x,y) plane (equivalent
+--   to mplot3d's @plot_trisurf@). Suited to scattered observations, GP
+--   posterior points, or other surfaces that don't form a regular grid.
+--   Use 'colormap3D' for a continuous z color.
 --
 --   @trisurf pts <> colormap3D viridisStops3D@
 trisurf :: [Point3] -> Layer3D
@@ -435,11 +512,18 @@
   , lyr3Points = Last  (Just pts)
   }
 
--- | Phase 30 A6: 列駆動の 3D テキスト注釈 (= 2D 'Graphics.Hgg.Spec.text' と対称・
---   ColRef 4 つ x/y/z + **label 列**)。 df の各行を投影し、 label 列の文字を PText で
+-- | [日本語]: 列駆動の 3D テキスト注釈 (= 2D 'Graphics.Hgg.Spec.text' と対称・
+--   ColRef 4 つ x/y/z + __label 列__)。 df の各行を投影し、 label 列の文字を PText で
 --   置く。 解決は 'resolveLayer3D' (x/y/z → 'lyr3Points'・label → 'lyr3Labels')。
 --   inline 生値版は 'text3DPoints'。 文字色は 'color3D' (既定 @#333333@)、 サイズは
 --   'size3D' (既定 11)。
+--   [English]: A column-driven 3D text annotation (symmetric with 2D
+--   'Graphics.Hgg.Spec.text': 4 ColRefs — x/y/z plus a __label column__).
+--   Projects each row of the dataframe and places the label column's text
+--   via 'Graphics.Hgg.Primitive.PText'. Resolved by 'resolveLayer3D' (x/y/z go to 'lyr3Points',
+--   the label goes to 'lyr3Labels'). For the inline raw-value form, use
+--   'text3DPoints'. Text color comes from 'color3D' (default @#333333@),
+--   size from 'size3D' (default 11).
 --
 --   @text3D \"x\" \"y\" \"z\" \"name\"@
 text3D :: ColRef -> ColRef -> ColRef -> ColRef -> Layer3D
@@ -449,10 +533,16 @@
   , lyr3TextBy = Last (Just lab)
   }
 
--- | Phase 30 A6: 3D テキスト注釈 (inline・[(点, 文字列)] 直入れ・旧 'text3D')。 各
+-- | [日本語]: 3D テキスト注釈 (inline・[(点, 文字列)] 直入れ・旧 'text3D')。 各
 --   @(点, 文字列)@ を投影して PText を出す (depth 統合外の前面 overlay)。 位置は他
 --   mark と同じ正規化 / z-aspect pipeline を通る。 'lyr3Annots' (concat Monoid) に
 --   積むので 'annotate3D' と @<>@ で畳める。
+--   [English]: A 3D text annotation (inline, taking @[(point, string)]@
+--   directly; the older form of 'text3D'). Projects each
+--   @(point, string)@ pair and emits a 'Graphics.Hgg.Primitive.PText' (a front overlay outside
+--   depth integration). Positions go through the same normalization /
+--   z-aspect pipeline as other marks. Accumulates into 'lyr3Annots' (a
+--   concat Monoid), so it folds together with 'annotate3D' via @\<\>@.
 --
 --   @text3DPoints [(Point3 0 0 1, \"peak\"), (Point3 1 1 0, \"corner\")]@
 text3DPoints :: [(Point3, Text)] -> Layer3D
@@ -461,9 +551,14 @@
   , lyr3Annots = items
   }
 
--- | Phase 25 A7 / 30 A6: 単一ラベルの注釈。 'lyr3Annots' に 1 件積むので
---   @annotate3D a \"A\" <> annotate3D b \"B\"@ のように **畳める** (= 複数注釈が累積。
+-- | [日本語]: 単一ラベルの注釈。 'lyr3Annots' に 1 件積むので
+--   @annotate3D a \"A\" <> annotate3D b \"B\"@ のように __畳める__ (= 複数注釈が累積。
 --   旧実装は 'lyr3Labels' が Last で後勝ち → 畳めなかった)。
+--   [English]: A single-label annotation. Accumulates one entry into
+--   'lyr3Annots', so it __folds together__ like
+--   @annotate3D a \"A\" <> annotate3D b \"B\"@ (multiple annotations
+--   accumulate; the older implementation used a 'Last' 'lyr3Labels' where
+--   the last one won, so it could not fold).
 --
 --   @annotate3D (Point3 0 0 1) \"max\" <> color3D (fromHex \"#d62728\") <> size3D 13@
 annotate3D :: Point3 -> Text -> Layer3D
@@ -473,67 +568,111 @@
 -- per-layer 属性 (= 2D 'color' / 'size' / 'alpha' 同型、 Layer3D 返却)
 -- ===========================================================================
 
--- | Phase 30 A5: 固定色 (= 2D 'Graphics.Hgg.Spec.color' 同型・型安全な 'Color')。
+-- | [日本語]: 固定色 (= 2D 'Graphics.Hgg.Spec.color' 同型・型安全な 'Color')。
 --   @scatter3D pts <> color3D (fromHex "#56B4E9")@。 ワイヤは従来通り Text なので
 --   入口で 'toCss' 変換して格納する (Render / PS / JSON は無改修)。
+--   [English]: A fixed color (the counterpart of 2D
+--   'Graphics.Hgg.Spec.color'; a type-safe 'Color').
+--   @scatter3D pts <> color3D (fromHex "#56B4E9")@. The wire representation
+--   remains Text as before, so it's converted with 'toCss' at the entry
+--   point (Render / PS / JSON stay unchanged).
 color3D :: Color -> Layer3D
 color3D c = mempty { lyr3Color = Last (Just (toCss c)) }
 
--- | 便利関数 (2D 'Graphics.Hgg.Spec.colorRGBA' の 3D 双子): 8 桁 RGBA hex
+-- | [日本語]: 便利関数 (2D 'Graphics.Hgg.Spec.colorRGBA' の 3D 双子): 8 桁 RGBA hex
 --   (@"#rrggbbaa"@ / 4 桁 @"#rgba"@) を @color3D (fromHex …) <> alpha3D …@ に展開。
 --   不正入力は 'error' (total 版は 'colorRGBA3DMaybe')。
+--   [English]: A convenience function (the 3D twin of 2D
+--   'Graphics.Hgg.Spec.colorRGBA'): expands an 8-digit RGBA hex
+--   (@"#rrggbbaa"@, or 4-digit @"#rgba"@) into
+--   @color3D (fromHex …) <> alpha3D …@. Invalid input calls 'error' (see
+--   'colorRGBA3DMaybe' for a total version).
 colorRGBA3D :: Text -> Layer3D
 colorRGBA3D t = let (c, a) = fromHexA t in color3D c <> alpha3D a
 
--- | 'colorRGBA3D' の total 版。 不正な hex は 'Nothing'。
+-- | [日本語]: 'colorRGBA3D' の total 版。 不正な hex は 'Nothing'。
+--   [English]: The total version of 'colorRGBA3D'. An invalid hex yields
+--   'Nothing'.
 colorRGBA3DMaybe :: Text -> Maybe Layer3D
 colorRGBA3DMaybe t = (\(c, a) -> color3D c <> alpha3D a) <$> fromHexAMaybe t
 
--- | Phase 25 A2: scatter/line を**カテゴリ列**で群色分けする (+ 離散凡例)。
+-- | [日本語]: scatter/line を__カテゴリ列__で群色分けする (+ 離散凡例)。
 --   @scatter3D "x" "y" "z" <> colorBy3D "group"@。 色は 2D 同型の ggplot 既定
 --   palette ('ggplotHue')。 解決は 'resolveLayer3D' で点ごと色 + 凡例 mapping に
 --   落とす (カテゴリは初出順)。
+--   [English]: Colors scatter/line by group using a __category column__
+--   (plus a discrete legend). @scatter3D "x" "y" "z" <> colorBy3D "group"@.
+--   Colors follow the same ggplot default palette as 2D ('ggplotHue').
+--   Resolved by 'resolveLayer3D' into a per-point color plus a legend
+--   mapping (categories in first-occurrence order).
 colorBy3D :: ColRef -> Layer3D
 colorBy3D c = mempty { lyr3ColorBy = Last (Just c) }
 
--- | Phase 25 A3: scatter を**数値列**の連続色 (viridis) でマップする (+ colorbar)。
---   @scatter3D "x" "y" "z" <> colorContinuousBy3D "temp"@。 A2 'colorBy3D' (カテゴリ
+-- | [日本語]: scatter を__数値列__の連続色 (viridis) でマップする (+ colorbar)。
+--   @scatter3D "x" "y" "z" <> colorContinuousBy3D "temp"@。 'colorBy3D' (カテゴリ
 --   →離散凡例) と対。 解決は 'resolveLayer3D' で点ごと色 + colorbar 情報
 --   (stops, min, max) に落とす。 stops は surface と共有の 'viridisStops3D'。
---   (Phase 30 A5: 2D 'colorContinuousBy' と命名対称化。 旧名 @colorByValue3D@。)
+--   (2D 'Graphics.Hgg.Spec.colorContinuousBy' と命名対称化。 旧名 @colorByValue3D@。)
+--   [English]: Maps scatter to a continuous color (viridis) via a
+--   __numeric column__ (plus a colorbar).
+--   @scatter3D "x" "y" "z" <> colorContinuousBy3D "temp"@. The counterpart
+--   to 'colorBy3D' (a category to a discrete legend). Resolved by
+--   'resolveLayer3D' into a per-point color plus colorbar info
+--   (stops, min, max). Shares 'viridisStops3D' with surface. (Named to
+--   match 2D's @colorContinuousBy@; the older name was @colorByValue3D@.)
 colorContinuousBy3D :: ColRef -> Layer3D
 colorContinuousBy3D c = mempty { lyr3ColorByV = Last (Just c) }
 
--- | Phase 25 A3: scatter の点サイズ (= 基本半径 px) を**数値列**でマップする
+-- | [日本語]: scatter の点サイズ (= 基本半径 px) を__数値列__でマップする
 --   (bubble chart)。 @scatter3D "x" "y" "z" <> sizeBy3D "mass"@。 px 範囲は
 --   既定 @(4, 18)@、 変えたい時は 'sizeRange3D'。 値→size は線形 (min→範囲下端、
 --   max→範囲上端)。 depth cue は基本 size に乗算される。
+--   [English]: Maps a scatter's point size (the base radius in px) via a
+--   __numeric column__ (a bubble chart). @scatter3D "x" "y" "z" <>
+--   sizeBy3D "mass"@. The px range defaults to @(4, 18)@; change it with
+--   'sizeRange3D'. Value-to-size is linear (min maps to the range's lower
+--   end, max to the upper end). The depth cue multiplies the base size.
 sizeBy3D :: ColRef -> Layer3D
 sizeBy3D c = mempty { lyr3SizeBy = Last (Just c) }
 
--- | Phase 25 A3: 'sizeBy3D' の出力 px 範囲を明示指定 (下端, 上端)。 単独では
+-- | [日本語]: 'sizeBy3D' の出力 px 範囲を明示指定 (下端, 上端)。 単独では
 --   無効 ('sizeBy3D' と併用)。 未指定時の既定は @(4, 18)@。
+--   [English]: Explicitly sets the output px range (lower, upper) for
+--   'sizeBy3D'. Has no effect on its own (use together with 'sizeBy3D').
+--   Defaults to @(4, 18)@ when unspecified.
 sizeRange3D :: (Double, Double) -> Layer3D
 sizeRange3D r = mempty { lyr3SizeRange = Last (Just r) }
 
--- | Phase 25 A5: bar スタイル (直方体 'BarCuboid' / 縦線 'BarStick')。 既定は
+-- | [日本語]: bar スタイル (直方体 'BarCuboid' / 縦線 'BarStick')。 既定は
 --   'BarCuboid'。 @bar3D "x" "y" "z" <> barStyle3D BarStick@。
+--   [English]: The bar style (cuboid 'BarCuboid' or vertical line
+--   'BarStick'). Defaults to 'BarCuboid'.
+--   @bar3D "x" "y" "z" <> barStyle3D BarStick@.
 barStyle3D :: BarStyle3D -> Layer3D
 barStyle3D s = mempty { lyr3BarStyle = Last (Just s) }
 
--- | Phase 25 A5: bar footprint の半幅 (= 軸 span に対する比・既定 0.04)。
+-- | [日本語]: bar footprint の半幅 (= 軸 span に対する比・既定 0.04)。
 --   正規化空間 ([-1,1]) では x/y 共通でこの値がそのまま半幅になる。
+--   [English]: The bar footprint's half-width (as a ratio of the axis span,
+--   default 0.04). In normalized space (@[-1,1]@), this value directly
+--   becomes the half-width, shared by x/y.
 barWidth3D :: Double -> Layer3D
 barWidth3D w = mempty { lyr3BarWidth = Last (Just w) }
 
--- | Phase 25 A5: 誤差棒 (z 方向 ±err) を**数値列**で付ける。 bar・scatter
+-- | [日本語]: 誤差棒 (z 方向 ±err) を__数値列__で付ける。 bar・scatter
 --   どちらの layer にも付けられる (頂点に縦線 + 端キャップ)。
 --   @bar3D "x" "y" "z" <> errorBar3D "se"@。
+--   [English]: Attaches error bars (z-direction ±err) via a __numeric column__.
+--   Can be attached to either a bar or scatter layer (a vertical line plus
+--   end caps at each vertex). @bar3D "x" "y" "z" <> errorBar3D "se"@.
 errorBar3D :: ColRef -> Layer3D
 errorBar3D c = mempty { lyr3ErrBy = Last (Just c) }
 
--- | Phase 30 A5: surface 等のエッジ線色 (固定色・型安全な 'Color')。
+-- | [日本語]: surface 等のエッジ線色 (固定色・型安全な 'Color')。
 --   ワイヤは Text 維持 ('toCss' 変換して格納)。
+--   [English]: The edge line color for surfaces and similar (a fixed,
+--   type-safe 'Color'). The wire representation stays Text ('toCss' is
+--   applied at the entry point).
 edgeColor3D :: Color -> Layer3D
 edgeColor3D c = mempty { lyr3EdgeColor = Last (Just (toCss c)) }
 
@@ -549,53 +688,93 @@
 shaded3D :: Bool -> Layer3D
 shaded3D b = mempty { lyr3Shaded = Last (Just b) }
 
--- | Phase 24 A2: surface 面色を z 値の連続色 (viridis) にする。
+-- | [日本語]: surface 面色を z 値の連続色 (viridis) にする。
 --   @layer3D (surface3DGrid grid <> colormap3D)@。 stops を変えたい時は
 --   'colormapWith3D'。
+--   [English]: Colors surface faces by a continuous z color (viridis).
+--   @layer3D (surface3DGrid grid <> colormap3D)@. Use 'colormapWith3D' to
+--   change the stops.
 colormap3D :: Layer3D
 colormap3D = colormapWith3D viridisStops3D
 
--- | Phase 24 A2: 任意 gradient stops の colormap (hex 色の線形補間)。
+-- | [日本語]: 任意 gradient stops の colormap (hex 色の線形補間)。
+--   [English]: A colormap over arbitrary gradient stops (linear
+--   interpolation between hex colors).
 colormapWith3D :: [Text] -> Layer3D
 colormapWith3D stops = mempty { lyr3Colormap = Last (Just stops) }
 
--- | surface を**面なしの格子線メッシュ**で描く (matplotlib @plot_wireframe@ 相当)。
+-- | [日本語]: surface を__面なしの格子線メッシュ__で描く (matplotlib @plot_wireframe@ 相当)。
 --   @surface3D@ に @\<>@ で合成: @layer3D (surface3DGrid grid \<> surfaceWire \<> color3D (fromHex "#2563eb"))@。
 --   面を塗らないので 'colormap3D' / 'shaded3D' は無効 (線色は 'color3D')。 任意エッジの
 --   'wireframe3D' とは別 (こちらは grid から行/列の線メッシュを自動生成)。
+--   [English]: Draws a surface as a __faceless gridline mesh__ (equivalent
+--   to matplotlib's @plot_wireframe@). Compose with @surface3D@ via
+--   @\<\>@: @layer3D (surface3DGrid grid \<\> surfaceWire \<\> color3D
+--   (fromHex "#2563eb"))@. Since no faces are filled, 'colormap3D' /
+--   'shaded3D' have no effect (line color comes from 'color3D'). Distinct
+--   from 'wireframe3D' (arbitrary edges); this one auto-generates the
+--   row/column line mesh from the grid.
 surfaceWire :: Layer3D
 surfaceWire = mempty { lyr3SurfaceWire = Last (Just True) }
 
--- | 投影 contour の軸 (内部表現)。 'contourX' / 'contourY' / 'contourZ' が設定する。
+-- | [日本語]: 投影 contour の軸 (内部表現)。 'contourX' / 'contourY' / 'contourZ' が設定する。
 --   matplotlib @contour(..., zdir=)@ 相当 (= dir に垂直な平面で曲面を切り、 壁へ投影)。
+--   [English]: The axis for a projected contour (internal representation),
+--   set by 'contourX' / 'contourY' / 'contourZ'. Equivalent to matplotlib's
+--   @contour(..., zdir=)@ (slices the surface with a plane perpendicular to
+--   @dir@ and projects it onto the wall).
 data ContourDir = ContourX | ContourY | ContourZ
   deriving (Show, Eq, Generic)
 instance ToJSON   ContourDir
 instance FromJSON ContourDir
 
--- | surface の **x 断面** @n@ 本を左右の壁 (yz 平面) へ投影する (matplotlib
---   @contour(..., zdir='x')@ / plotly @contours.x.project@ 相当)。 x 軸を等分した
+-- | [日本語]: surface の __x 断面__ @n@ 本を左右の壁 (yz 平面) へ投影する (matplotlib
+--   @contour(..., zdir="x")@ / plotly @contours.x.project@ 相当)。 x 軸を等分した
 --   @n@ 位置で曲面を切り、 各断面プロファイル @z = f(x_k, y)@ を壁に描く。 投影壁は
---   **カメラから遠い面に自動固定**。 同じ surface に 'contourY' / 'contourZ' を @\<>@ で
+--   __カメラから遠い面に自動固定__。 同じ surface に 'contourY' / 'contourZ' を @\<>@ で
 --   合成可。 線色は colormap (既定 viridis) の x 連続色。
 --   @surface3DGrid grid \<> colormap3D \<> contourX 8 \<> contourY 8 \<> contourZ 8@。
+--   [English]: Projects @n@ __x cross-sections__ of a surface onto the
+--   left/right walls (yz plane) (equivalent to matplotlib's
+--   @contour(..., zdir="x")@ / plotly's @contours.x.project@). Slices the
+--   surface at @n@ evenly spaced x positions and draws each cross-section
+--   profile @z = f(x_k, y)@ on the wall. The projection wall
+--   __auto-pins to the face farthest from the camera__. Composable with
+--   'contourY' / 'contourZ' on the same surface via @\<\>@. Line color
+--   follows the colormap's (default viridis) continuous x color.
+--   @surface3DGrid grid \<\> colormap3D \<\> contourX 8 \<\> contourY 8
+--   \<\> contourZ 8@.
 contourX :: Int -> Layer3D
 contourX n = mempty { lyr3Contours = [(ContourX, n)] }
 
--- | surface の **y 断面** @n@ 本を前後の壁 (xz 平面) へ投影する (matplotlib
---   @contour(..., zdir='y')@ 相当)。 各断面プロファイル @z = f(x, y_k)@ を壁に描く。
+-- | [日本語]: surface の __y 断面__ @n@ 本を前後の壁 (xz 平面) へ投影する (matplotlib
+--   @contour(..., zdir="y")@ 相当)。 各断面プロファイル @z = f(x, y_k)@ を壁に描く。
 --   投影壁はカメラから遠い面に自動固定。 'contourX' / 'contourZ' と合成可。
+--   [English]: Projects @n@ __y cross-sections__ of a surface onto the
+--   front/back walls (xz plane) (equivalent to matplotlib's
+--   @contour(..., zdir="y")@). Draws each cross-section profile
+--   @z = f(x, y_k)@ on the wall. The projection wall auto-pins to the face
+--   farthest from the camera. Composable with 'contourX' / 'contourZ'.
 contourY :: Int -> Layer3D
 contourY n = mempty { lyr3Contours = [(ContourY, n)] }
 
--- | surface の **等高線 (z 等値面)** @n@ 本を床 (xy 平面) へ投影する (matplotlib
---   @contour(..., zdir='z')@ / plotly @contours_z@ 相当)。 z 軸を等分した @n@ 値で
+-- | [日本語]: surface の __等高線 (z 等値面)__ @n@ 本を床 (xy 平面) へ投影する (matplotlib
+--   @contour(..., zdir="z")@ / plotly @contours_z@ 相当)。 z 軸を等分した @n@ 値で
 --   level set @{f = z_k}@ を抽出し床へ落とす (topographic map)。 投影面はカメラから
 --   遠い面 (通常は床) に自動固定。 'contourX' / 'contourY' と合成可。
+--   [English]: Projects @n@ __contour lines (z level sets)__ of a surface
+--   onto the floor (xy plane) (equivalent to matplotlib's
+--   @contour(..., zdir="z")@ / plotly's @contours_z@). Extracts the level
+--   set @{f = z_k}@ at @n@ evenly spaced z values and drops it onto the
+--   floor (a topographic map). The projection face auto-pins to the face
+--   farthest from the camera (usually the floor). Composable with
+--   'contourX' / 'contourY'.
 contourZ :: Int -> Layer3D
 contourZ n = mempty { lyr3Contours = [(ContourZ, n)] }
 
--- | 2D 'ColorByContinuous' と同じ viridis 5-stop (palette 共有)。
+-- | [日本語]: 2D 'Graphics.Hgg.Spec.ColorByContinuous' と同じ viridis 5-stop (palette 共有)。
+--   [English]: The same viridis 5-stop palette as 2D 'Graphics.Hgg.Spec.ColorByContinuous'
+--   (shared).
 viridisStops3D :: [Text]
 viridisStops3D = ["#440154", "#3B528B", "#21918C", "#5EC962", "#FDE725"]
 
@@ -609,59 +788,87 @@
 -- VisualSpec3D 属性
 -- ===========================================================================
 
--- | camera 設定 (= 後勝ち、 'Last')。
+-- | [日本語]: camera 設定 (= 後勝ち、 'Last')。
+--   [English]: The camera setting (last one wins, 'Last').
 camera :: Camera3D -> VisualSpec3D
 camera c = mempty { vs3Camera = Last (Just c) }
 
--- | projection 設定。
+-- | [日本語]: projection 設定。
+--   [English]: The projection setting.
 projection :: Projection3D -> VisualSpec3D
 projection p = mempty { vs3Proj = Last (Just p) }
 
--- | axes 設定。 名前は 'axes3D' で 2D 'theme' / 'facet' と同型語感。
+-- | [日本語]: axes 設定。 名前は 'axes3D' で 2D 'Graphics.Hgg.Spec.theme' / 'Graphics.Hgg.Spec.facet' と同型語感。
+--   [English]: The axes setting. Named 'axes3D' to echo the feel of 2D
+--   'Graphics.Hgg.Spec.theme' / 'Graphics.Hgg.Spec.facet'.
 axes3D :: Axes3D -> VisualSpec3D
 axes3D a = mempty { vs3Axes = Last (Just a) }
 
--- | title (= 2D 'title' 同型、 ただし `3D` suffix で衝突回避)。
+-- | [日本語]: title (= 2D 'Graphics.Hgg.Spec.title' 同型、 ただし `3D` suffix で衝突回避)。
+--   [English]: The title (the counterpart of 2D 'Graphics.Hgg.Spec.title', with a @3D@ suffix
+--   to avoid a name clash).
 title3D :: Text -> VisualSpec3D
 title3D t = mempty { vs3Title = Last (Just t) }
 
--- | Phase 24 A8: 軸名 (x, y, z) を任意指定 (既定 "x"/"y"/"z")。
+-- | [日本語]: 軸名 (x, y, z) を任意指定 (既定 "x"/"y"/"z")。
+--   [English]: Sets arbitrary axis names (x, y, z), defaulting to
+--   "x"/"y"/"z".
 axisTitles3D :: Text -> Text -> Text -> VisualSpec3D
 axisTitles3D x y z = mempty { vs3AxisTitles = Last (Just (x, y, z)) }
 
--- | Phase 24 A8: z 軸の box 縦横比 (正規化後の z スケール係数・既定 1)。
+-- | [日本語]: z 軸の box 縦横比 (正規化後の z スケール係数・既定 1)。
 --   @< 1@ で扁平、 @> 1@ で縦長。 軸 box・surface・scatter・床面 contour すべてに
 --   一貫適用される。
+--   [English]: The z axis's box aspect ratio (the post-normalization z
+--   scale factor, default 1). @< 1@ flattens, @> 1@ elongates. Applied
+--   consistently to the axis box, surface, scatter, and floor contour.
 zAspect3D :: Double -> VisualSpec3D
 zAspect3D a = mempty { vs3ZAspect = Last (Just a) }
 
--- | Phase 25 A6: 壁面 pane + gridline の on/off (mplot3d 標準の薄灰 3 壁・既定 ON)。
+-- | [日本語]: 壁面 pane + gridline の on/off (mplot3d 標準の薄灰 3 壁・既定 ON)。
 --   @pane3D False@ で従来の cube wireframe + tick のみに戻す。
+--   [English]: Toggles the wall pane plus gridlines (mplot3d's standard
+--   light-gray 3-wall style; default ON). @pane3D False@ reverts to the
+--   original cube wireframe plus ticks only.
 pane3D :: Bool -> VisualSpec3D
 pane3D b = mempty { vs3Pane = Last (Just b) }
 
--- | Phase 25 A8: x 軸の box 縦横比 (正規化後 x スケール係数・既定 1。 'zAspect3D' の x 版)。
+-- | [日本語]: x 軸の box 縦横比 (正規化後 x スケール係数・既定 1。 'zAspect3D' の x 版)。
+--   [English]: The x axis's box aspect ratio (the post-normalization x
+--   scale factor, default 1; the x counterpart of 'zAspect3D').
 xAspect3D :: Double -> VisualSpec3D
 xAspect3D a = mempty { vs3XAspect = Last (Just a) }
 
--- | Phase 25 A8: y 軸の box 縦横比 (正規化後 y スケール係数・既定 1。 'zAspect3D' の y 版)。
+-- | [日本語]: y 軸の box 縦横比 (正規化後 y スケール係数・既定 1。 'zAspect3D' の y 版)。
+--   [English]: The y axis's box aspect ratio (the post-normalization y
+--   scale factor, default 1; the y counterpart of 'zAspect3D').
 yAspect3D :: Double -> VisualSpec3D
 yAspect3D a = mempty { vs3YAspect = Last (Just a) }
 
--- | Phase 25 A8: 軸を log scale に (x, y, z の順で flag 指定・既定 全 False)。
+-- | [日本語]: 軸を log scale に (x, y, z の順で flag 指定・既定 全 False)。
 --   log 軸はデータが正の前提 (非正は 1e-12 に clamp)。 tick は 10 の冪 (decade)、
 --   ラベルは元の値のまま。 surface の log-z は対応、 surface の log-x/y は現状未対応
 --   (point 系 mark = scatter/line/bar は全軸 log 可)。
 --
 --   @logScale3D False False True@  -- z だけ log (片対数)
+--   [English]: Switches axes to a log scale (flags given in x, y, z order,
+--   default all False). A log axis assumes positive data (non-positive
+--   values are clamped to 1e-12). Ticks are powers of 10 (decades); labels
+--   still show the original value. surface's log-z is supported, but
+--   surface's log-x/y is not currently (point-style marks — scatter/line/
+--   bar — support log on every axis).
+--
+--   @logScale3D False False True@  -- only z is log (semi-log)
 logScale3D :: Bool -> Bool -> Bool -> VisualSpec3D
 logScale3D x y z = mempty { vs3Log = Last (Just (x, y, z)) }
 
--- | width (= canvas 幅 px、 2D 'vsWidth' 同型)。
+-- | [日本語]: width (= canvas 幅 px、 2D 'Graphics.Hgg.Spec.vsWidth' 同型)。
+--   [English]: The canvas width in px (the counterpart of 2D 'Graphics.Hgg.Spec.vsWidth').
 width3DV :: Int -> VisualSpec3D
 width3DV w = mempty { vs3Width = Last (Just w) }
 
--- | height (= canvas 高さ px、 2D 'vsHeight' 同型)。
+-- | [日本語]: height (= canvas 高さ px、 2D 'Graphics.Hgg.Spec.vsHeight' 同型)。
+--   [English]: The canvas height in px (the counterpart of 2D 'Graphics.Hgg.Spec.vsHeight').
 height3DV :: Int -> VisualSpec3D
 height3DV h = mempty { vs3Height = Last (Just h) }
 
@@ -670,8 +877,11 @@
 -- (= render 経路で使う。 defaults は existing default*3D 関数を経由)
 -- ===========================================================================
 
--- | Layer3D (= rolled-up) を 'Scatter3D' に変換。 'lyr3Kind' が 'M3Scatter' か
+-- | [日本語]: Layer3D (= rolled-up) を 'Scatter3D' に変換。 'lyr3Kind' が 'M3Scatter' か
 --   未指定の時に意味あり。 必須項目 ('lyr3Points') 未指定なら空 points で。
+--   [English]: Converts a rolled-up Layer3D into a 'Scatter3D'. Meaningful
+--   when 'lyr3Kind' is 'M3Scatter' or unspecified. If the required
+--   'lyr3Points' is unset, uses an empty points list.
 layerToScatter :: Layer3D -> Scatter3D
 layerToScatter l =
   let pts = fromMaybe [] (getLast (lyr3Points l))
@@ -718,9 +928,14 @@
        , sf3Wire      = fromMaybe (sf3Wire      base) (getLast (lyr3SurfaceWire l))
        }
 
--- | Phase 25 A5: Layer3D を 'Bar3D' に変換 (render 経路で使う)。 点・base・half-width
---   は正規化済前提 ('normLayer3D' / 'scaleZLayer' が事前に処理)。 base は
+-- | [日本語]: Layer3D を 'Bar3D' に変換 (render 経路で使う)。 点・base・half-width
+--   は正規化済前提 ('Graphics.Hgg.ThreeD.Easy.normLayer3D' / @scaleZLayer@ が事前に処理)。 base は
 --   'lyr3BarBaseZ' (未設定なら 0)、 半幅は 'lyr3BarWidth' (既定 0.04)。
+--   [English]: Converts a Layer3D into a 'Bar3D' (used on the render path).
+--   Points, base, and half-width are assumed already normalized
+--   ('Graphics.Hgg.ThreeD.Easy.normLayer3D' / @scaleZLayer@ handle this beforehand). base comes from
+--   'lyr3BarBaseZ' (0 if unset); half-width from 'lyr3BarWidth' (default
+--   0.04).
 layerToBar :: Layer3D -> Bar3D
 layerToBar l =
   let tops = fromMaybe [] (getLast (lyr3Points l))
@@ -734,10 +949,16 @@
        , br3Width = fromMaybe (br3Width base) (getLast (lyr3Width    l))
        }
 
--- | Phase 26 A3: Layer3D を 'Quiver3D' に変換 (render 経路で使う)。 点・ベクトルは
---   正規化済前提 ('normLayer3D' / 'scaleAspectLayer' が事前に処理)。 autoscale =
+-- | [日本語]: Layer3D を 'Quiver3D' に変換 (render 経路で使う)。 点・ベクトルは
+--   正規化済前提 ('Graphics.Hgg.ThreeD.Easy.normLayer3D' / 'Graphics.Hgg.ThreeD.Easy.scaleAspectLayer' が事前に処理)。 autoscale =
 --   最長矢印が cube の 35% になるよう正規化ベクトル長で割り、 'lyr3VecScale' を掛ける。
 --   終点 = 始点 + scale × vec。
+--   [English]: Converts a Layer3D into a 'Quiver3D' (used on the render
+--   path). Points and vectors are assumed already normalized
+--   ('Graphics.Hgg.ThreeD.Easy.normLayer3D' / 'Graphics.Hgg.ThreeD.Easy.scaleAspectLayer' handle this beforehand). autoscale
+--   divides by the normalized vector length so the longest arrow becomes
+--   35% of the cube, then multiplies by 'lyr3VecScale'. End point = start
+--   point + scale × vec.
 layerToQuiver :: Layer3D -> Quiver3D
 layerToQuiver l =
   let starts = fromMaybe [] (getLast (lyr3Points  l))
@@ -759,14 +980,23 @@
 -- autoAxes3D: layers から bounding box を自動算出 (= Axes 未指定時の default)
 -- ===========================================================================
 
--- | 全 layer の Point3 集合から min/max を取って 'Axes3D' を生成。
+-- | [日本語]: 全 layer の Point3 集合から min/max を取って 'Axes3D' を生成。
 --   surface3D は xRange/yRange + grid 高さで Point3 集合を構成。
 --   layer が無い / 全 Point3 が空なら 'defaultAxes3D' (= 単位 cube)。
--- Phase 24 A6: 列参照 (Enc) の解決 — Resolver で [Point3] に落とす
+--   [English]: Generates an 'Axes3D' by taking min/max over every layer's
+--   Point3 set. For surface3D, the Point3 set is built from xRange/yRange
+--   plus the grid heights. With no layers, or every Point3 set empty, falls
+--   back to 'defaultAxes3D' (the unit cube).
+-- 列参照 (Enc) の解決 — Resolver で [Point3] に落とす
 
--- | 層の列参照 (x,y,z) を 'Resolver' で解決して 'lyr3Points' に格納する。
---   3 列が全部解決できた時だけ上書き ('inline' 生値は resolver 不要で解決)。
+-- | [日本語]: 層の列参照 (x,y,z) を 'Resolver' で解決して 'lyr3Points' に格納する。
+--   3 列が全部解決できた時だけ上書き ('Graphics.Hgg.Spec.inline' 生値は resolver 不要で解決)。
 --   Enc が無い層 (旧 [Point3] 直入れ・surface 等) は素通し。
+--   [English]: Resolves a layer's column references (x,y,z) via a
+--   'Resolver' and stores the result into 'lyr3Points'. Only overwrites
+--   when all three columns resolve successfully ('Graphics.Hgg.Spec.inline' raw values need
+--   no resolver and are already resolved). Layers with no Enc (older direct
+--   @[Point3]@ input, surface, etc.) pass through unchanged.
 resolveLayer3D :: Resolver -> Layer3D -> Layer3D
 resolveLayer3D r l0 =
   let -- まず x/y/z 列参照 → 点列 (Phase 24 A6)
@@ -799,9 +1029,13 @@
         _ -> l1
   in resolveTextBy3D r (resolveErrBy3D r (resolveSizeBy3D r (resolveColorByValue3D r (resolveColorBy3D r l2))))
 
--- | Phase 30 A6: 列駆動 'text3D' の label 列 ('lyr3TextBy') を解決して 'lyr3Labels' に
+-- | [日本語]: 列駆動 'text3D' の label 列 ('lyr3TextBy') を解決して 'lyr3Labels' に
 --   落とす (x/y/z は 'resolveLayer3D' 先頭で既に 'lyr3Points' へ解決済)。 数値列は
 --   'numLabel' で文字化。 未指定なら素通し。
+--   [English]: Resolves the label column ('lyr3TextBy') of a column-driven
+--   'text3D' into 'lyr3Labels' (x/y/z were already resolved into
+--   'lyr3Points' earlier in 'resolveLayer3D'). A numeric column is
+--   stringified via 'numLabel'. Passes through unchanged when unset.
 resolveTextBy3D :: Resolver -> Layer3D -> Layer3D
 resolveTextBy3D r l = case getLast (lyr3TextBy l) of
   Nothing -> l
@@ -812,10 +1046,17 @@
           Nothing          -> []
     in if null labels then l else l { lyr3Labels = Last (Just labels) }
 
--- | Phase 30 A6: surface 案C の pivot。 long 形の (xs, ys, zs) を規則格子の z 行列に
+-- | [日本語]: surface 案C の pivot。 long 形の (xs, ys, zs) を規則格子の z 行列に
 --   畳む。 列 = x の昇順 unique・行 = y の昇順 unique。 grid[i][j] = (uxs[j], uys[i]) の z。
 --   欠損 (組が無い) セルは NaN (= 描画穴)。 重複 (同一 (x,y)) は後勝ち。 xRange/yRange は
 --   実データの min/max (空なら (-1,1))。
+--   [English]: The pivot for surface plan C. Folds the long-form
+--   (xs, ys, zs) into a regular-grid z matrix. Columns are x's ascending
+--   uniques, rows are y's ascending uniques; @grid[i][j]@ is the z at
+--   @(uxs[j], uys[i])@. Missing cells (no matching pair) become NaN
+--   (rendering holes). Duplicates (same (x,y)) let the last one win.
+--   xRange/yRange come from the actual data's min/max (defaulting to
+--   (-1,1) when empty).
 pivotSurface3D :: [Double] -> [Double] -> [Double]
                -> ([[Double]], (Double, Double), (Double, Double))
 pivotSurface3D xs ys zs =
@@ -827,8 +1068,12 @@
       rng vs = if null vs then (-1, 1) else (minimum vs, maximum vs)
   in (grid, rng xs, rng ys)
 
--- | Phase 25 A2: カテゴリ列 ('lyr3ColorBy') を解決して点ごと色 + 凡例 mapping に
+-- | [日本語]: カテゴリ列 ('lyr3ColorBy') を解決して点ごと色 + 凡例 mapping に
 --   落とす。 カテゴリは初出順、 色は 'ggplotHue'。 未指定なら素通し。
+--   [English]: Resolves the category column ('lyr3ColorBy') into a
+--   per-point color plus a legend mapping. Categories are in
+--   first-occurrence order; colors come from 'ggplotHue'. Passes through
+--   unchanged when unset.
 resolveColorBy3D :: Resolver -> Layer3D -> Layer3D
 resolveColorBy3D r l = case getLast (lyr3ColorBy l) of
   Nothing -> l
@@ -845,10 +1090,16 @@
        else l { lyr3PtColors = Last (Just (map colOf labels))
               , lyr3Legend   = Last (Just catColor) }
 
--- | Phase 25 A3: 数値列 ('lyr3ColorByV') を解決して点ごと連続色 (viridis) +
+-- | [日本語]: 数値列 ('lyr3ColorByV') を解決して点ごと連続色 (viridis) +
 --   colorbar 情報 (stops, min, max) に落とす。 値→色は線形正規化 + 'continuousColor'
 --   (= 2D gradient 凡例 / surface colormap と同じ補間)。 未指定 / 非数値なら素通し。
 --   全値同一なら中央色 (t=0.5)。
+--   [English]: Resolves the numeric column ('lyr3ColorByV') into a
+--   per-point continuous color (viridis) plus colorbar info
+--   (stops, min, max). Value-to-color is a linear normalization followed
+--   by 'continuousColor' (the same interpolation as the 2D gradient legend
+--   / surface colormap). Passes through unchanged when unset or
+--   non-numeric. Uses the middle color (t=0.5) when every value is equal.
 resolveColorByValue3D :: Resolver -> Layer3D -> Layer3D
 resolveColorByValue3D r l = case getLast (lyr3ColorByV l) of
   Nothing -> l
@@ -865,10 +1116,15 @@
         in l { lyr3PtColors = Last (Just cols)
              , lyr3Colorbar = Last (Just (stops, vMin, vMax)) }
 
--- | Phase 25 A3: 数値列 ('lyr3SizeBy') を解決して点ごと基本 size (px) に落とす
+-- | [日本語]: 数値列 ('lyr3SizeBy') を解決して点ごと基本 size (px) に落とす
 --   (bubble)。 値→size は線形 (min→範囲下端、 max→範囲上端)。 範囲は
 --   'lyr3SizeRange' (既定 (4, 18))。 未指定 / 非数値なら素通し。 全値同一なら
 --   範囲の中点。
+--   [English]: Resolves the numeric column ('lyr3SizeBy') into a per-point
+--   base size in px (a bubble chart). Value-to-size is linear (min maps to
+--   the range's lower end, max to the upper end). The range comes from
+--   'lyr3SizeRange' (default (4, 18)). Passes through unchanged when unset
+--   or non-numeric. Uses the range's midpoint when every value is equal.
 resolveSizeBy3D :: Resolver -> Layer3D -> Layer3D
 resolveSizeBy3D r l = case getLast (lyr3SizeBy l) of
   Nothing -> l
@@ -884,9 +1140,13 @@
                        else sLo + (sHi - sLo) * (x - vMin) / (vMax - vMin)
         in l { lyr3PtSizes = Last (Just (map sizeOf vals)) }
 
--- | Phase 25 A5: 誤差棒の err 列 ('lyr3ErrBy') を解決して点ごと err (data 単位)
+-- | [日本語]: 誤差棒の err 列 ('lyr3ErrBy') を解決して点ごと err (data 単位)
 --   に落とす。 正規化 (data z → [-1,1]) は 'Easy.normLayer3D' が行う。 未指定 /
 --   非数値なら素通し。
+--   [English]: Resolves the error-bar err column ('lyr3ErrBy') into a
+--   per-point err (in data units). Normalization (data z to @[-1,1]@) is
+--   handled by 'Easy.normLayer3D'. Passes through unchanged when unset or
+--   non-numeric.
 resolveErrBy3D :: Resolver -> Layer3D -> Layer3D
 resolveErrBy3D r l = case getLast (lyr3ErrBy l) of
   Nothing -> l
@@ -896,13 +1156,17 @@
                in if null vals then l
                   else l { lyr3PtErrs = Last (Just vals) }
 
--- | 数値カテゴリのラベル整形 (整数なら末尾 .0 を落とす)。
+-- | [日本語]: 数値カテゴリのラベル整形 (整数なら末尾 .0 を落とす)。
+--   [English]: Formats a numeric category label (strips a trailing .0 for
+--   integers).
 numLabel :: Double -> Text
 numLabel x =
   let r = fromIntegral (round x :: Int) :: Double
   in if r == x then T.pack (show (round x :: Int)) else T.pack (show x)
 
--- | spec 内の全層の列参照を解決する ('saveSVG3DBound' / bind 経路の正本)。
+-- | [日本語]: spec 内の全層の列参照を解決する (@saveSVG3DBound@ / bind 経路の正本)。
+--   [English]: Resolves the column references in every layer of a spec (the
+--   canonical implementation for @saveSVG3DBound@ / bind path).
 resolveSpec3D :: Resolver -> VisualSpec3D -> VisualSpec3D
 resolveSpec3D r spec = spec { vs3Layers = map (resolveLayer3D r) (vs3Layers spec) }
 
@@ -926,9 +1190,13 @@
               , axesXLog = False, axesYLog = False, axesZLog = False
               }
 
--- | Layer から Point3 集合を抽出 (= Surface は grid を Point3 に展開)。
--- Phase 25 A5: bar は底面 (z=0) を、 誤差棒のある層は z±err 端を含めて axis box が
--- 棒の根本 / whisker を覆うようにする。
+-- | [日本語]: Layer から Point3 集合を抽出 (= Surface は grid を Point3 に展開)。
+--   bar は底面 (z=0) を、 誤差棒のある層は z±err 端を含めて axis box が
+--   棒の根本 / whisker を覆うようにする。
+--   [English]: Extracts a layer's Point3 set (for Surface, expands the grid
+--   into points). For a bar, includes the base (z=0); for a layer with
+--   error bars, includes the z±err endpoints, so the axis box covers the
+--   bar's foot / whiskers too.
 layerPoints :: Layer3D -> [Point3]
 layerPoints l = case getFirst (lyr3Kind l) of
   Just M3Surface ->
@@ -966,7 +1234,9 @@
   _ -> let pts = fromMaybe [] (getLast (lyr3Points l))
        in pts ++ errPoints l pts
 
--- | Phase 25 A5: 誤差棒のある層で、 各点の z±err 端点を返す (axis box 拡張用)。
+-- | [日本語]: 誤差棒のある層で、 各点の z±err 端点を返す (axis box 拡張用)。
+--   [English]: For a layer with error bars, returns each point's z±err
+--   endpoints (used to extend the axis box).
 errPoints :: Layer3D -> [Point3] -> [Point3]
 errPoints l pts = case getLast (lyr3PtErrs l) of
   Nothing -> []
diff --git a/src/Graphics/Hgg/ThreeD/Surface.hs b/src/Graphics/Hgg/ThreeD/Surface.hs
--- a/src/Graphics/Hgg/ThreeD/Surface.hs
+++ b/src/Graphics/Hgg/ThreeD/Surface.hs
@@ -1,11 +1,15 @@
 -- |
 -- Module      : Graphics.Hgg.ThreeD.Surface
--- Description : 3D surface plot (grid mesh + painter's algorithm) (Phase 3 A7)
+-- Description : 3D surface plot (grid mesh + painter's algorithm)
 -- Copyright   : (c) 2026 Aelysce Project (Toshiaki Honda)
 -- License     : BSD-3-Clause
 --
--- 規則 grid (= 2D 配列の z 値) から triangle mesh を作り、 painter's algorithm
--- で奥から塗り潰す。 optional Lambert shading (= flat、 1 directional light)。
+-- [日本語]: 規則 grid (= 2D 配列の z 値) から triangle mesh を作り、
+--   painter's algorithm で奥から塗り潰す。 optional Lambert shading
+--   (= flat、 1 directional light)。
+-- [English]: Builds a triangle mesh from a regular grid (a 2D array of z
+--   values) and fills it back-to-front with the painter's algorithm.
+--   Optional Lambert shading (flat, one directional light).
 {-# LANGUAGE DeriveGeneric     #-}
 {-# LANGUAGE OverloadedStrings #-}
 module Graphics.Hgg.ThreeD.Surface
@@ -41,17 +45,30 @@
   , sf3EdgeColor  :: !Text
   , sf3Shaded     :: !Bool
   , sf3Colormap   :: !(Maybe [Text])
-    -- ^ Phase 24 A2: @Just stops@ で面色を z 値の連続色 (gradient stops の
-    --   線形補間・2D 'ColorByContinuous' と同じ 'continuousColor') にする。
+    -- ^ [日本語]: @Just stops@ で面色を z 値の連続色 (gradient stops の
+    --   線形補間・2D 'Graphics.Hgg.Spec.ColorByContinuous' と同じ 'continuousColor') にする。
     --   @Nothing@ = 従来の単色 'sf3Color' (後方互換)。
+    --   [English]: With @Just stops@, face colors follow a continuous z
+    --   colormap (linear interpolation of gradient stops, via the same
+    --   'continuousColor' used by 2D 'Graphics.Hgg.Spec.ColorByContinuous'). @Nothing@ means
+    --   the traditional single color 'sf3Color' (backward compatible).
   , sf3Alpha      :: !Double
-    -- ^ Phase 25 A4: 面の不透明度 (0..1・既定 1)。 @< 1@ で半透明 surface。
-    --   face は depth ソート済 (painter's・A8 で scatter と大域マージ) なので
+    -- ^ [日本語]: 面の不透明度 (0..1・既定 1)。 @< 1@ で半透明 surface。
+    --   face は depth ソート済 (painter's・scatter と大域マージ) なので
     --   back-to-front 合成が正しく重なる。
+    --   [English]: The face opacity (0..1, default 1). @< 1@ gives a
+    --   semi-transparent surface. Faces are already depth-sorted (via the
+    --   painter's algorithm, merged globally with scatter), so
+    --   back-to-front compositing layers correctly.
   , sf3Wire       :: !Bool
-    -- ^ surfaceWire: 面を塗らず grid の行/列を**格子線メッシュ**で描く
+    -- ^ [日本語]: surfaceWire: 面を塗らず grid の行/列を__格子線メッシュ__で描く
     --   (matplotlib @plot_wireframe@ 相当)。 True で fill 三角形の代わりに
     --   隣接 grid 点を結ぶ line segment を depth 統合付きで返す。 colormap/shaded は無効。
+    --   [English]: surfaceWire: rather than filling faces, draws the grid's
+    --   rows/columns as a __gridline mesh__ (equivalent to matplotlib's
+    --   @plot_wireframe@). When True, returns line segments connecting
+    --   adjacent grid points (with depth integration) instead of filled
+    --   triangles. colormap / shaded are disabled.
   } deriving (Show, Eq, Generic)
 instance ToJSON   Surface3D
 instance FromJSON Surface3D
@@ -92,9 +109,13 @@
 renderSurface3D cam proj vp sf =
   map snd (sortOn (negate . fst) (surfaceFacesDepth cam proj vp sf))
 
--- | Phase 24 A8 (depth 統合): 各 face を @(投影 depth, poly Primitive)@ として
--- **未ソート**で返す (= 'renderSurface3D' は @sortOn (negate.fst)@ してから
--- @map snd@・ビット同一)。 scatter 点との層横断 depth 統合に使う。
+-- | [日本語]: (depth 統合): 各 face を @(投影 depth, poly Primitive)@ として
+--   __未ソート__で返す (= 'renderSurface3D' は @sortOn (negate.fst)@ してから
+--   @map snd@・ビット同一)。 scatter 点との層横断 depth 統合に使う。
+--   [English]: (depth integration): Returns each face as
+--   @(projected depth, poly Primitive)@, __unsorted__ ('renderSurface3D' is
+--   bit-identical to @sortOn (negate . fst)@ followed by @map snd@ of this).
+--   Used to integrate depth across layers with scatter points.
 surfaceFacesDepth
   :: Camera3D -> Projection3D -> Viewport
   -> Surface3D -> [(Double, Primitive)]
@@ -180,18 +201,30 @@
     subAsVec (Point3 bx by bz) (Point3 ax ay az) =
       Vec3 (bx - ax) (by - ay) (bz - az)
 
--- | Phase 26 A5 (trisurf): grid 非依存に **任意の三角形 face 列**を depth +
--- Lambert shading + (任意) colormap で @(投影 depth, PPath)@ 化する
--- ('surfaceFacesDepth' の grid 専用ロジックを triangle 列入力へ一般化した版)。
--- 頂点は正規化済前提。 colormap の z range は全 face 頂点 z から算出。
+-- | [日本語]: (trisurf): grid 非依存に __任意の三角形 face 列__を depth +
+--   Lambert shading + (任意) colormap で @(投影 depth, PPath)@ 化する
+--   ('surfaceFacesDepth' の grid 専用ロジックを triangle 列入力へ一般化した版)。
+--   頂点は正規化済前提。 colormap の z range は全 face 頂点 z から算出。
+--   [English]: (trisurf): Converts an __arbitrary list of triangle faces__
+--   (not tied to a grid) into @(projected depth, PPath)@ using depth,
+--   Lambert shading, and an optional colormap (a generalization of the
+--   grid-specific logic in 'surfaceFacesDepth' to a list-of-triangles
+--   input). Vertices are assumed already normalized. The colormap's z range
+--   is computed from every face vertex's z.
 trianglesFacesDepth
   :: Camera3D -> Projection3D -> Viewport
-  -> Text          -- ^ 基本色 (colormap 無しの単色)
-  -> Text          -- ^ edge 色
-  -> Bool          -- ^ shaded (Lambert)
-  -> Maybe [Text]  -- ^ colormap stops (Just で z 連続色)
-  -> Double        -- ^ alpha
-  -> [(Point3, Point3, Point3)]  -- ^ 三角形 (正規化済)
+  -> Text          -- ^ [日本語]: 基本色 (colormap 無しの単色)
+                    --   [English]: The base color (a single color when no colormap is used).
+  -> Text          -- ^ [日本語]: edge 色
+                    --   [English]: The edge color.
+  -> Bool          -- ^ [日本語]: shaded (Lambert)
+                    --   [English]: Whether to apply Lambert shading.
+  -> Maybe [Text]  -- ^ [日本語]: colormap stops (Just で z 連続色)
+                    --   [English]: The colormap stops (@Just@ gives a continuous z colormap).
+  -> Double        -- ^ [日本語]: alpha
+                    --   [English]: The alpha (opacity).
+  -> [(Point3, Point3, Point3)]  -- ^ [日本語]: 三角形 (正規化済)
+                                  --   [English]: The triangles (already normalized).
   -> [(Double, Primitive)]
 trianglesFacesDepth cam proj vp baseCol edgeCol shaded cmap alpha triangles =
   let project = project3D cam proj vp
diff --git a/src/Graphics/Hgg/ThreeD/Types.hs b/src/Graphics/Hgg/ThreeD/Types.hs
--- a/src/Graphics/Hgg/ThreeD/Types.hs
+++ b/src/Graphics/Hgg/ThreeD/Types.hs
@@ -1,15 +1,25 @@
 -- |
 -- Module      : Graphics.Hgg.ThreeD.Types
--- Description : 3D の中核型 (Point3 / Vec3 / Mat4 / Camera3D / Projection3D)
+-- Description : Core 3D types (Point3 / Vec3 / Mat4 / Camera3D / Projection3D)
 -- Copyright   : (c) 2026 Aelysce Project (Toshiaki Honda)
 -- License     : BSD-3-Clause
 --
--- Phase 3 A2 段階: 中核型のみ定義。 関数 (= project3D / lookAt 等) は A3
--- (Graphics.Hgg.ThreeD.Projection) で実装。
+-- [日本語]: 中核型のみを定義する。 関数 (= project3D / lookAt 等) は
+--   Graphics.Hgg.ThreeD.Projection で実装する。
 --
--- 設計判断: linear package 等の外部依存を入れず、 自前 Vec3 / Mat4 を持つ。
--- これで core (= base/vector/text/containers のみ) の依存戦略と整合する。
--- 行列演算は 4x4 で十分 (= camera + projection)、 性能不問の前提で simple list 実装。
+--   設計判断: linear package 等の外部依存を入れず、 自前 Vec3 / Mat4 を持つ。
+--   これで core (= base/vector/text/containers のみ) の依存戦略と整合する。
+--   行列演算は 4x4 で十分 (= camera + projection)、 性能不問の前提で simple
+--   list 実装。
+-- [English]: Defines only the core types here. Functions (@project3D@,
+--   @lookAt@, etc.) are implemented in Graphics.Hgg.ThreeD.Projection.
+--
+--   Design decision: rather than depending on an external package such as
+--   @linear@, this module carries its own 'Vec3' / 'Mat4'. This keeps it
+--   consistent with core's dependency strategy (base/vector/text/containers
+--   only). 4x4 matrices are enough for camera + projection math, and since
+--   performance is not a concern here, they are implemented as a simple
+--   list of fields.
 {-# LANGUAGE DeriveGeneric #-}
 module Graphics.Hgg.ThreeD.Types
   ( -- * 幾何プリミティブ
@@ -26,7 +36,7 @@
   , yUp
   , defaultCameraZUp
   , defaultCameraYUp
-    -- * 視点 preset (Phase 24 A8・z-up)
+    -- * 視点 preset (z-up)
   , cameraIso
   , cameraTop
   , cameraFront
@@ -45,65 +55,99 @@
 import           Data.Aeson      (FromJSON, ToJSON)
 import           GHC.Generics    (Generic)
 
--- | 3D 点 (= world / camera space どちらでも使う)。
+-- | [日本語]: 3D 点 (= world / camera space どちらでも使う)。
 --
--- JSON: positional fields → array `[x, y, z]` (= aeson Generic デフォルト挙動)。
--- PS Argonaut 側も同形式で decode。
+--   JSON: positional fields → array `[x, y, z]` (= aeson Generic デフォルト挙動)。
+--   PS Argonaut 側も同形式で decode。
+--   [English]: A 3D point (used for both world space and camera space).
+--
+--   JSON: positional fields serialize to the array @[x, y, z]@ (aeson's
+--   default Generic behavior). The PureScript Argonaut side decodes the
+--   same format.
 data Point3 = Point3 !Double !Double !Double
   deriving (Show, Eq, Generic)
 instance ToJSON   Point3
 instance FromJSON Point3
 
--- | 3D ベクトル (= 方向 / 法線)。 JSON は Point3 と同じく array `[x, y, z]`。
+-- | [日本語]: 3D ベクトル (= 方向 / 法線)。 JSON は Point3 と同じく array `[x, y, z]`。
+--   [English]: A 3D vector (a direction or normal). Serializes to JSON as the
+--   same array `[x, y, z]` as 'Point3'.
 data Vec3 = Vec3 !Double !Double !Double
   deriving (Show, Eq, Generic)
 instance ToJSON   Vec3
 instance FromJSON Vec3
 
 -- $convention
--- hgg-3d は **z-up と y-up の両方をサポート** する。 default は **z-up**
--- (= mplot3d / 工学慣例)。 user は用途に応じて切替可能。
+-- [日本語]: hgg-3d は __z-up と y-up の両方をサポート__ する。 default は
+--   __z-up__ (= mplot3d / 工学慣例)。 user は用途に応じて切替可能。
 --
--- == 業界の使い分け (= 2026 時点の調査)
+--   == 業界の使い分け (= 2026 時点の調査)
 --
--- +-------------------+-------------------------------------------------+------------+
--- | 分野              | 主要ライブラリ                                  | up         |
--- +===================+=================================================+============+
--- | __data viz__      | matplotlib mplot3d / plotly / Mathematica /     | __z-up__   |
--- |                   | gnuplot splot / mayavi / R rgl                  |            |
--- +-------------------+-------------------------------------------------+------------+
--- | __工学 / CAD__    | AutoCAD / SolidWorks / Inventor / Unreal Engine | __z-up__   |
--- +-------------------+-------------------------------------------------+------------+
--- | __game / CG__     | Unity / Godot 3D / OpenGL 慣例 / DirectX 慣例   | __y-up__   |
--- +-------------------+-------------------------------------------------+------------+
--- | __3D modeling__   | Blender (= z-up に切替済) / Maya (= y-up)       | 分裂       |
--- +-------------------+-------------------------------------------------+------------+
+--   [data viz]: __z-up__ — matplotlib mplot3d、 plotly、 Mathematica、
+--     gnuplot splot、 mayavi、 R rgl
+--   [工学 / CAD]: __z-up__ — AutoCAD、 SolidWorks、 Inventor、 Unreal Engine
+--   [game / CG]: __y-up__ — Unity、 Godot 3D、 OpenGL 慣例、 DirectX 慣例
+--   [3D modeling]: 分裂 — Blender (= z-up に切替済) と Maya (= y-up) で割れている
 --
--- == hgg-3d の default = z-up を選んだ理由
+--   == hgg-3d の default = z-up を選んだ理由
 --
--- * メインターゲットが data viz (= hanalyze の HBM 等)
--- * mplot3d / plotly の慣例と整合 → 既存 user 知識が活きる
--- * @z = f(x, y)@ の数学慣例と一致 → 'Graphics.Hgg.ThreeD.Surface.Surface3D' が直感的
--- * z = 物理量の高さ (= 確率密度 / 計測値 / 標高) の伝統
+--   * メインターゲットが data viz (= hanalyze の HBM 等)
+--   * mplot3d / plotly の慣例と整合 → 既存 user 知識が活きる
+--   * @z = f(x, y)@ の数学慣例と一致 → 'Graphics.Hgg.ThreeD.Surface.Surface3D' が直感的
+--   * z = 物理量の高さ (= 確率密度 / 計測値 / 標高) の伝統
 --
--- == どちらを使うべきか
+--   == どちらを使うべきか
 --
--- * __z-up__ ('zUp' / 'defaultCameraZUp'): data viz、 工学解析、 統計分布、 surface plot。 default 推奨
--- * __y-up__ ('yUp' / 'defaultCameraYUp'): game-like view、 OpenGL 系 sample との整合、 既存 CG 知識の流用
+--   * __z-up__ ('zUp' / 'defaultCameraZUp'): data viz、 工学解析、 統計分布、 surface plot。 default 推奨
+--   * __y-up__ ('yUp' / 'defaultCameraYUp'): game-like view、 OpenGL 系 sample との整合、 既存 CG 知識の流用
 --
--- 両 helper とも up vector を切替えるだけで他は同じ。 任意の up vector が必要なら
--- 'Camera3D' を直接構築する。
+--   両 helper とも up vector を切替えるだけで他は同じ。 任意の up vector が必要なら
+--   'Camera3D' を直接構築する。
+--
+-- [English]: hgg-3d supports __both z-up and y-up__ conventions. The
+--   default is __z-up__ (following the mplot3d / engineering convention);
+--   users may switch depending on the use case.
+--
+--   == Industry conventions (as surveyed in 2026)
+--
+--   [data viz]: __z-up__ — matplotlib mplot3d, plotly, Mathematica,
+--     gnuplot splot, mayavi, R rgl
+--   [engineering / CAD]: __z-up__ — AutoCAD, SolidWorks, Inventor, Unreal Engine
+--   [game / CG]: __y-up__ — Unity, Godot 3D, the OpenGL convention, the DirectX convention
+--   [3D modeling]: split — Blender (switched to z-up) and Maya (y-up) disagree
+--
+--   == Why hgg-3d chose z-up as the default
+--
+--   * The main target is data viz (e.g. HBM plots in hanalyze)
+--   * It matches the mplot3d / plotly convention, so existing user knowledge transfers
+--   * It matches the mathematical convention @z = f(x, y)@, making 'Graphics.Hgg.ThreeD.Surface.Surface3D' intuitive
+--   * z as the height of a physical quantity (probability density, a measurement, elevation) is a long-standing tradition
+--
+--   == Which one should you use
+--
+--   * __z-up__ ('zUp' / 'defaultCameraZUp'): data viz, engineering analysis, statistical distributions, surface plots. Recommended default
+--   * __y-up__ ('yUp' / 'defaultCameraYUp'): game-like views, alignment with OpenGL-style samples, reuse of existing CG knowledge
+--
+--   Both helpers only swap the up vector; everything else stays the same. If
+--   an arbitrary up vector is needed, construct 'Camera3D' directly.
 
--- | z-up convention の up vector (= 'Vec3' 0 0 1)。 data viz / mplot3d 慣例。
+-- | [日本語]: z-up convention の up vector (= 'Vec3' 0 0 1)。 data viz / mplot3d 慣例。
+--   [English]: The up vector for the z-up convention ('Vec3' 0 0 1). Follows
+--   the data-viz / mplot3d convention.
 zUp :: Vec3
 zUp = Vec3 0 0 1
 
--- | y-up convention の up vector (= 'Vec3' 0 1 0)。 OpenGL / game engine 慣例。
+-- | [日本語]: y-up convention の up vector (= 'Vec3' 0 1 0)。 OpenGL / game engine 慣例。
+--   [English]: The up vector for the y-up convention ('Vec3' 0 1 0). Follows
+--   the OpenGL / game-engine convention.
 yUp :: Vec3
 yUp = Vec3 0 1 0
 
--- | z-up convention の default camera。 'eye' を data の bounding box 寄りに配置し、
--- 'target' を原点、 up を 'zUp' に。 typical 3/4 view (= 上前方斜め見下ろし)。
+-- | [日本語]: z-up convention の default camera。 @eye@ を data の bounding box 寄りに配置し、
+--   @target@ を原点、 up を 'zUp' に。 typical 3/4 view (= 上前方斜め見下ろし)。
+--   [English]: The default camera for the z-up convention. Places @eye@ near
+--   the data's bounding box, sets @target@ to the origin, and up to 'zUp' —
+--   a typical 3/4 view (looking down diagonally from the front).
 --
 -- @
 -- defaultCameraZUp 5  -- camera at (5, -5, 3) → origin (= 上前方斜め)
@@ -115,9 +159,13 @@
   , cameraUp     = zUp
   }
 
--- | y-up convention の default camera。 OpenGL / Unity 慣例に整合する 3/4 view
--- (= y = 縦軸、 x/z = 床平面、 camera は y > 0 から見下ろし)。 game-like 表現や
--- OpenGL 系 sample との整合に。
+-- | [日本語]: y-up convention の default camera。 OpenGL / Unity 慣例に整合する 3/4 view
+--   (= y = 縦軸、 x/z = 床平面、 camera は y > 0 から見下ろし)。 game-like 表現や
+--   OpenGL 系 sample との整合に。
+--   [English]: The default camera for the y-up convention. A 3/4 view
+--   consistent with the OpenGL / Unity convention (y is the vertical axis,
+--   x/z form the ground plane, and the camera looks down from y > 0). Useful
+--   for game-like presentations or alignment with OpenGL-style samples.
 --
 -- @
 -- defaultCameraYUp 5  -- camera at (5, 3, 5) → origin (= 上前方斜め、 y = up)
@@ -129,13 +177,19 @@
   , cameraUp     = yUp
   }
 
--- | Phase 24 A8: 視点 preset (z-up・target = 原点)。 'cameraIso' = 'defaultCameraZUp'
--- (上前方斜め見下ろし)。 @dist@ は eye と原点の距離スケール。
+-- | [日本語]: 視点 preset (z-up・target = 原点)。 'cameraIso' = 'defaultCameraZUp'
+--   (上前方斜め見下ろし)。 @dist@ は eye と原点の距離スケール。
+--   [English]: A viewpoint preset (z-up, target at the origin). 'cameraIso'
+--   is 'defaultCameraZUp' (looking down diagonally from the front). @dist@
+--   scales the distance between eye and origin.
 cameraIso :: Double -> Camera3D
 cameraIso = defaultCameraZUp
 
--- | Phase 24 A8: 真上から見下ろす視点 (xy 平面を正対・z は奥行き)。 up は y 軸
--- (見下ろし時に zUp は eye 方向と平行になり退化するため)。
+-- | [日本語]: 真上から見下ろす視点 (xy 平面を正対・z は奥行き)。 up は y 軸
+--   (見下ろし時に zUp は eye 方向と平行になり退化するため)。
+--   [English]: A top-down viewpoint (facing the xy plane, with z as depth).
+--   Up is the y axis, because looking straight down would make 'zUp'
+--   parallel to the eye direction and degenerate.
 cameraTop :: Double -> Camera3D
 cameraTop dist = Camera3D
   { cameraEye    = Point3 0 0 dist
@@ -143,7 +197,9 @@
   , cameraUp     = yUp
   }
 
--- | Phase 24 A8: 正面 (−y 方向から xz 面を正対・z = 縦)。
+-- | [日本語]: 正面 (−y 方向から xz 面を正対・z = 縦)。
+--   [English]: A front view (facing the xz plane from the −y direction, with
+--   z as vertical).
 cameraFront :: Double -> Camera3D
 cameraFront dist = Camera3D
   { cameraEye    = Point3 0 (negate dist) 0
@@ -151,7 +207,9 @@
   , cameraUp     = zUp
   }
 
--- | Phase 24 A8: 真横 (+x 方向から yz 面を正対・z = 縦)。
+-- | [日本語]: 真横 (+x 方向から yz 面を正対・z = 縦)。
+--   [English]: A side view (facing the yz plane from the +x direction, with
+--   z as vertical).
 cameraSide :: Double -> Camera3D
 cameraSide dist = Camera3D
   { cameraEye    = Point3 dist 0 0
@@ -159,12 +217,16 @@
   , cameraUp     = zUp
   }
 
--- | aspect 1:1 / fov 45° / near 0.1 / far 100 の sane default。
+-- | [日本語]: aspect 1:1 / fov 45° / near 0.1 / far 100 の sane default。
+--   [English]: A sane default with aspect 1:1, fov 45°, near 0.1, far 100.
 defaultPerspective :: Projection3D
 defaultPerspective = Perspective (pi / 4) 1.0 0.1 100
 
--- | 4x4 同次座標行列 (= row-major、 16 Double を直接持つ)。
--- camera transform / perspective projection / model matrix で使う。
+-- | [日本語]: 4x4 同次座標行列 (= row-major、 16 Double を直接持つ)。
+--   camera transform / perspective projection / model matrix で使う。
+--   [English]: A 4x4 homogeneous-coordinate matrix (row-major, storing 16
+--   'Double's directly). Used for the camera transform, perspective
+--   projection, and model matrix.
 data Mat4 = Mat4
   !Double !Double !Double !Double
   !Double !Double !Double !Double
@@ -175,8 +237,11 @@
 instance ToJSON   Mat4
 instance FromJSON Mat4
 
--- | Camera 設定。 eye (= 視点)、 target (= 注視点)、 up (= 上方向、 通常 (0,1,0))。
--- 'Graphics.Hgg.ThreeD.Projection.lookAt' で view 行列を生成する。
+-- | [日本語]: Camera 設定。 eye (= 視点)、 target (= 注視点)、 up (= 上方向、 通常 (0,1,0))。
+--   'Graphics.Hgg.ThreeD.Projection.lookAt' で view 行列を生成する。
+--   [English]: Camera settings: eye (viewpoint), target (look-at point), and
+--   up (up direction, usually (0,1,0)). 'Graphics.Hgg.ThreeD.Projection.lookAt'
+--   builds the view matrix from these.
 data Camera3D = Camera3D
   { cameraEye    :: !Point3
   , cameraTarget :: !Point3
@@ -185,21 +250,32 @@
 instance ToJSON   Camera3D
 instance FromJSON Camera3D
 
--- | Projection 設定。 orthographic / perspective の 2 種。
+-- | [日本語]: Projection 設定。 orthographic / perspective の 2 種。
 --
---   * 'Orthographic': 平行投影。 box の半幅 (xHalf, yHalf, near, far) で領域指定
---   * 'Perspective': 透視投影。 fov (= 縦方向視野角、 radians) + aspect ratio +
---     near + far クリップ面
+--     * 'Orthographic': 平行投影。 box の半幅 (xHalf, yHalf, near, far) で領域指定
+--     * 'Perspective': 透視投影。 fov (= 縦方向視野角、 radians) + aspect ratio +
+--       near + far クリップ面
+--   [English]: Projection settings; either orthographic or perspective.
+--
+--     * 'Orthographic': parallel projection, specifying the region by box
+--       half-widths (xHalf, yHalf, near, far)
+--     * 'Perspective': perspective projection, specified by fov (vertical
+--       field of view, in radians), aspect ratio, and the near/far clip
+--       planes
 data Projection3D
   = Orthographic
-      { orthoXHalf :: !Double  -- ^ x 方向半幅
-      , orthoYHalf :: !Double  -- ^ y 方向半幅
+      { orthoXHalf :: !Double  -- ^ [日本語]: x 方向半幅
+                                --   [English]: The half-width along x.
+      , orthoYHalf :: !Double  -- ^ [日本語]: y 方向半幅
+                                --   [English]: The half-width along y.
       , orthoNear  :: !Double
       , orthoFar   :: !Double
       }
   | Perspective
-      { perspFov    :: !Double  -- ^ 縦方向 FOV、 radians
-      , perspAspect :: !Double  -- ^ aspect ratio (= width / height)
+      { perspFov    :: !Double  -- ^ [日本語]: 縦方向 FOV、 radians
+                                 --   [English]: The vertical field of view, in radians.
+      , perspAspect :: !Double  -- ^ [日本語]: aspect ratio (= width / height)
+                                 --   [English]: The aspect ratio (width / height).
       , perspNear   :: !Double
       , perspFar    :: !Double
       }
@@ -213,32 +289,40 @@
 -- 基本ベクトル演算
 -- ===========================================================================
 
--- | 加算。
+-- | [日本語]: 加算。
+--   [English]: Addition.
 addV3 :: Vec3 -> Vec3 -> Vec3
 addV3 (Vec3 ax ay az) (Vec3 bx by bz) = Vec3 (ax + bx) (ay + by) (az + bz)
 
--- | 減算。
+-- | [日本語]: 減算。
+--   [English]: Subtraction.
 subV3 :: Vec3 -> Vec3 -> Vec3
 subV3 (Vec3 ax ay az) (Vec3 bx by bz) = Vec3 (ax - bx) (ay - by) (az - bz)
 
--- | スカラー倍。
+-- | [日本語]: スカラー倍。
+--   [English]: Scalar multiplication.
 scaleV3 :: Double -> Vec3 -> Vec3
 scaleV3 s (Vec3 x y z) = Vec3 (s * x) (s * y) (s * z)
 
--- | 内積。
+-- | [日本語]: 内積。
+--   [English]: The dot product.
 dotV3 :: Vec3 -> Vec3 -> Double
 dotV3 (Vec3 ax ay az) (Vec3 bx by bz) = ax * bx + ay * by + az * bz
 
--- | 外積 (= 右手系)。
+-- | [日本語]: 外積 (= 右手系)。
+--   [English]: The cross product (right-handed).
 crossV3 :: Vec3 -> Vec3 -> Vec3
 crossV3 (Vec3 ax ay az) (Vec3 bx by bz) =
   Vec3 (ay * bz - az * by) (az * bx - ax * bz) (ax * by - ay * bx)
 
--- | L2 ノルム。
+-- | [日本語]: L2 ノルム。
+--   [English]: The L2 norm.
 lengthV3 :: Vec3 -> Double
 lengthV3 v = sqrt (dotV3 v v)
 
--- | 正規化 (= 単位ベクトル化)。 ゼロベクトルは (0,0,0) 返す (= 例外無し)。
+-- | [日本語]: 正規化 (= 単位ベクトル化)。 ゼロベクトルは (0,0,0) 返す (= 例外無し)。
+--   [English]: Normalization (converts to a unit vector). A zero vector
+--   returns (0,0,0) (no exception is thrown).
 normalizeV3 :: Vec3 -> Vec3
 normalizeV3 v =
   let l = lengthV3 v
