diff --git a/public/images/imu.svg b/public/images/imu.svg
new file mode 100644
index 0000000000..b641bcb584
--- /dev/null
+++ b/public/images/imu.svg
@@ -0,0 +1,26 @@
+
diff --git a/src/content/docs/components/index.mdx b/src/content/docs/components/index.mdx
index ceb2d3bae1..cdabfbea08 100644
--- a/src/content/docs/components/index.mdx
+++ b/src/content/docs/components/index.mdx
@@ -529,12 +529,15 @@ Sensors are organized into categories; if a given sensor fits into more than one
### Motion
+## Motion Components
+
+
+
## Number Components
diff --git a/src/content/docs/components/motion/images/calibrate.jpg b/src/content/docs/components/motion/images/calibrate.jpg
new file mode 100644
index 0000000000..8e7dba0889
Binary files /dev/null and b/src/content/docs/components/motion/images/calibrate.jpg differ
diff --git a/src/content/docs/components/motion/index.mdx b/src/content/docs/components/motion/index.mdx
new file mode 100644
index 0000000000..160f59e50d
--- /dev/null
+++ b/src/content/docs/components/motion/index.mdx
@@ -0,0 +1,198 @@
+---
+description: "Instructions for setting up Accelerometer/Gyroscope components."
+title: "Motion Component (IMU)"
+---
+
+import APIRef from '@components/APIRef.astro';
+import Figure from '@components/Figure.astro';
+import calibrationImg from './images/calibrate.jpg';
+
+The `motion` hub component allows you to define sensors that read data from inertial measurement units (IMUs)
+such as accelerometers and gyroscopes. Not all IMU chips support all types of measurements, see the individual platform
+documentation for details.
+
+```yaml
+# Example configuration entry
+motion:
+ - platform: ...
+ accelerometer_range: 4G # Platform dependent options here
+
+sensor:
+ - platform: motion
+ type: acceleration_x
+ name: "Accel X"
+ - platform: motion
+ type: angular_rate_x
+ name: "Gyro X"
+ - platform: motion
+ type: pitch
+ name: "Pitch Angle"
+```
+
+## Configuration variables
+
+### Base configuration
+
+- **axis_map** (*Optional*, mapping): Remap or invert the physical axes of the sensor to match
+ your board orientation. Each key (`x`, `y`, `z`) maps to the physical axis it should read from,
+ optionally prefixed with `-` to invert. All three axes must be present and each physical axis
+ may only appear once. Mutually exclusive with `transform_matrix`.
+
+ ```yaml
+ # Example: swap X and Y, invert Z
+ motion:
+ - platform: ...
+ axis_map:
+ x: y
+ y: x
+ z: "-z"
+ ```
+
+- **transform_matrix** (*Optional*, list of floats): A 3×3 transformation matrix applied to
+ raw accelerometer and gyroscope readings. This allows arbitrary calibration beyond simple
+ axis remapping. Can be specified as a flat list of 9 values (row-major order) or as a
+ 3×3 nested list. Mutually exclusive with `axis_map`.
+
+ ```yaml
+ # Example: 3x3 nested format
+ motion:
+ - platform: ...
+ transform_matrix:
+ - [0.998, 0.010, -0.050]
+ - [-0.010, 0.999, 0.020]
+ - [0.050, -0.020, 0.998]
+ ```
+
+ ```yaml
+ # Example: flat format
+ motion:
+ - platform: ...
+ transform_matrix: [0.998, 0.010, -0.050, -0.010, 0.999, 0.020, 0.050, -0.020, 0.998]
+ ```
+
+ The matrix can be obtained from the runtime calibration actions described below — after
+ calibration the computed matrix is logged in a format that can be copied directly into
+ your configuration for persistent use.
+
+- **update_interval** (*Optional*, [Time](/guides/configuration-types#time)): The interval at which
+ sensor data is read. Defaults to `250ms`.
+- **id** (*Optional*, [ID](/guides/configuration-types#id)): Manually specify the ID used for code generation.
+
+### Sensor configuration
+
+- **type** (**Required**, string): The type of measurement to expose. One of:
+ - `acceleration_x`: X-axis acceleration in `g`.
+ - `acceleration_y`: Y-axis acceleration in `g`.
+ - `acceleration_z`: Z-axis acceleration in `g`.
+ - `angular_rate_x`: X-axis angular velocity in `°/s`.
+ - `angular_rate_y`: Y-axis angular velocity in `°/s`.
+ - `angular_rate_z`: Z-axis angular velocity in `°/s`.
+ - `gyroscope_x`: Synonym for `angular_rate_x`.
+ - `gyroscope_y`: Synonym for `angular_rate_y`.
+ - `gyroscope_z`: Synonym for `angular_rate_z`.
+ - `pitch`: Pitch angle in `°`.
+ - `roll`: Roll angle in `°`.
+- All other options from [Sensor](/components/sensor).
+
+## Actions
+
+### `motion.calibrate_level` Action
+
+This [action](/automations/actions#all-actions) computes a calibration matrix so that the
+current accelerometer reading maps to `[0, 0, 1]` (device flat, Z pointing up). Place the
+device on a level surface and trigger this action. It replaces the current `transform_matrix`.
+
+- **save** (*Optional*, boolean): Save the resulting matrix to NVS flash so it is
+ automatically restored on the next boot. Defaults to `false`.
+- **on_success** (*Optional*, [Automation](/automations/actions)): Actions to run when calibration succeeds.
+- **on_error** (*Optional*, [Automation](/automations/actions)): Actions to run when calibration fails
+ (e.g. sensor read failure or insufficient tilt).
+
+```yaml
+on_...:
+ then:
+ - motion.calibrate_level:
+ id: my_motion
+ save: true
+ on_success:
+ - logger.log: "Level calibration succeeded"
+ on_error:
+ - logger.log: "Level calibration failed"
+```
+
+After execution the resulting matrix is logged at INFO level in a format that can be
+copied into the `transform_matrix` configuration for persistent calibration.
+
+### `motion.calibrate_heading` Action
+
+This [action](/automations/actions#all-actions) corrects the heading (rotation around Z)
+after a prior level calibration. Tilt the device around its Y axis only (pitch forward or
+backward) and trigger this action. It composes a Z-rotation correction with the existing
+matrix so that the horizontal acceleration component falls entirely on the X axis, with its
+sign preserved.
+
+- **save** (*Optional*, boolean): Save the resulting matrix to NVS flash. Defaults to `false`.
+- **on_success** (*Optional*, [Automation](/automations/actions)): Actions to run when calibration succeeds.
+- **on_error** (*Optional*, [Automation](/automations/actions)): Actions to run when calibration fails.
+
+```yaml
+on_...:
+ then:
+ - motion.calibrate_heading:
+ id: my_motion
+ save: true
+ on_success:
+ - logger.log: "Heading calibration succeeded"
+```
+
+### `motion.clear_calibration` Action
+
+This [action](/automations/actions#all-actions) discards any runtime calibration and restores
+the build-time matrix defined by `axis_map` or `transform_matrix` (or the identity matrix if
+neither is configured). Use it to undo a `motion.calibrate_level` / `motion.calibrate_heading`
+sequence without re-flashing.
+
+- **save** (*Optional*, boolean): Also clear the saved calibration in NVS flash so the reset
+ persists across reboots. Defaults to `false`. When `false`, the in-memory matrix is reset but
+ a previously saved calibration will be restored again on the next boot.
+
+```yaml
+on_...:
+ then:
+ - motion.clear_calibration:
+ id: my_motion
+ save: true
+```
+
+### Calibration persistence
+
+When a calibration action is run with `save: true`, the resulting matrix is stored in NVS flash
+and automatically restored on the next boot, taking precedence over the `axis_map` /
+`transform_matrix` configuration. The saved calibration is tied to the configured base matrix:
+if you change `axis_map` or `transform_matrix` and re-flash, the stale saved calibration is
+automatically discarded and the new configuration is used. To explicitly return to the
+configured base at runtime, use `motion.clear_calibration`.
+
+### Calibration procedure
+
+1. Place the device on a flat, level surface.
+2. Trigger `motion.calibrate_level`. This aligns Z with gravity.
+3. Tilt the device around the Y axis only (e.g. prop one edge up along the X direction).
+4. Trigger `motion.calibrate_heading`. This fixes the X/Y heading.
+
+The new calibration matrix is now active and can be saved to flash if desired.
+If you have a way to monitor the logs, you can verify that the calibration succeeded by checking for an INFO log
+entry with the resulting matrix in a format suitable for copy-pasting into your configuration.
+
+
+
+## See Also
+
+- [Sensor Filters](/components/sensor#sensor-filters)
+- [BMI270 Accelerometer/Gyroscope platform](/components/motion/bmi270/)
+- [LSM6DS Accelerometer/Gyroscope platform](/components/motion/lsm6ds/)
+-
diff --git a/src/content/docs/components/motion/lsm6ds.mdx b/src/content/docs/components/motion/lsm6ds.mdx
new file mode 100644
index 0000000000..5b5ce3425f
--- /dev/null
+++ b/src/content/docs/components/motion/lsm6ds.mdx
@@ -0,0 +1,53 @@
+---
+description: "Instructions for setting up LSM6DS Accelerometer/Gyroscope sensors."
+title: "LSM6DS Accelerometer/Gyroscope Sensor"
+---
+
+import APIRef from '@components/APIRef.astro';
+
+The `lsm6ds` motion platform allows you to use your LSM6DS Accelerometer/Gyroscope
+([datasheet](https://www.st.com/resource/en/datasheet/lsm6ds3tr-c.pdf))
+sensors with ESPHome. The [I²C Bus](/components/i2c) is required to be set up in
+your configuration for this sensor to work.
+
+The LSM6DS is an IMU including a 16-bit 3-axis accelerometer and a 16-bit 3-axis gyroscope, plus an on-chip temperature sensor.
+
+The LSM6DS3 and LSM6DSO are the currently supported variants. Detection of the chip variant is automatic.
+
+```yaml
+# Example configuration entry
+motion:
+ - platform: lsm6ds
+ accelerometer_range: 4G
+ gyroscope_range: 2000DPS
+
+sensor:
+ - platform: motion
+ type: acceleration_x
+ name: "LSM6DS Accel X"
+ - platform: motion
+ type: gyroscope_x
+ name: "LSM6DS Gyro X"
+ - platform: motion
+ type: roll
+ name: "LSM6DS Roll"
+```
+
+## Configuration variables
+
+- **address** (*Optional*, int): Manually specify the I²C address of the sensor. Defaults to `0x6A`, on some boards it may need to be set to `0x6B`..
+- **accelerometer_range** (*Optional*, string): The full-scale range of the accelerometer. One of
+ `2G`, `4G`, `8G`, `16G`. Defaults to `4G`.
+- **accelerometer_odr** (*Optional*, string): The output data rate of the accelerometer. One of
+ `OFF`, `12_5HZ`, `26HZ`, `52HZ`, `104HZ`, `208HZ`, `416HZ`, `833HZ`, `1666HZ`, `3332HZ`, `6664HZ`. Defaults to `104HZ`.
+- **gyroscope_range** (*Optional*, string): The full-scale range of the gyroscope. One of
+ `125DPS`, `250DPS`, `500DPS`, `1000DPS`, `2000DPS`. Defaults to `2000DPS`.
+- **gyroscope_odr** (*Optional*, string): The output data rate of the gyroscope. One of
+ `OFF`, `12_5HZ`, `26HZ`, `52HZ`, `104HZ`, `208HZ`, `416HZ`, `833HZ`, `1666HZ`, `3332HZ`, `6664HZ`. Defaults to `208HZ`.
+
+- All other options from [Motion](/components/motion).
+
+## See Also
+
+- [LSM6DS Temperature Sensor](/components/sensor/lsm6ds/)
+-
diff --git a/src/content/docs/components/sensor/bmi270.mdx b/src/content/docs/components/sensor/bmi270.mdx
new file mode 100644
index 0000000000..dab380618e
--- /dev/null
+++ b/src/content/docs/components/sensor/bmi270.mdx
@@ -0,0 +1,30 @@
+---
+description: "Instructions for setting up BMI270 temperature sensor."
+title: "BMI270 Temperature Sensor"
+---
+
+The `bmi270` sensor platform provides access to the temperature sensor in a BMI270 Accelerometer/Gyroscope
+([datasheet](https://www.bosch-sensortec.com/media/boschsensortec/downloads/datasheets/bst-bmi270-ds000.pdf)) with ESPHome.
+It requires a [`motion`](/components/motion) component to be configured with the `bmi270` platform,
+which handles the accelerometer and gyroscope data processing and configures the device. See that component for more information.
+
+```yaml
+# Example configuration entry
+motion:
+ - platform: bmi270
+
+sensor:
+ - platform: bmi270
+ type: temperature # Optional, temperature is the only supported type for this platform
+ name: "BMI270 Temperature"
+```
+
+## Configuration variables
+
+- **type** (*Optional*, string): Must be set to `temperature`, or simply omitted.
+- All other options from [Sensor](/components/sensor).
+
+## See Also
+
+- [Sensor Filters](/components/sensor#sensor-filters)
+- [BMI270 Accelerometer/Gyroscope platform](/components/motion/bmi270/)
diff --git a/src/content/docs/components/sensor/lsm6ds.mdx b/src/content/docs/components/sensor/lsm6ds.mdx
new file mode 100644
index 0000000000..25e7484eae
--- /dev/null
+++ b/src/content/docs/components/sensor/lsm6ds.mdx
@@ -0,0 +1,30 @@
+---
+description: "Instructions for setting up LSM6DS temperature sensor."
+title: "LSM6DS Temperature Sensor"
+---
+
+The `lsm6ds` sensor platform provides access to the temperature sensor in a LSM6DS Accelerometer/Gyroscope
+([datasheet](https://www.st.com/resource/en/datasheet/lsm6ds3tr-c.pdf)) with ESPHome.
+It requires a [`motion`](/components/motion) component to be configured with the `lsm6ds` platform,
+which handles the accelerometer and gyroscope data processing and configures the device. See that component for more information.
+
+```yaml
+# Example configuration entry
+motion:
+ - platform: lsm6ds
+
+sensor:
+ - platform: lsm6ds
+ type: temperature # Optional, temperature is the only supported type for this platform
+ name: "LSM6DS Temperature"
+```
+
+## Configuration variables
+
+- **type** (*Optional*, string): Must be set to `temperature`, or simply omitted.
+- All other options from [Sensor](/components/sensor).
+
+## See Also
+
+- [Sensor Filters](/components/sensor#sensor-filters)
+- [LSM6DS Accelerometer/Gyroscope platform](/components/motion/lsm6ds/)
diff --git a/src/content/docs/components/sensor/motion.mdx b/src/content/docs/components/sensor/motion.mdx
new file mode 100644
index 0000000000..9757e4e48d
--- /dev/null
+++ b/src/content/docs/components/sensor/motion.mdx
@@ -0,0 +1,23 @@
+---
+description: "Instructions for setting up motion (IMU) sensors with ESPHome."
+title: "Motion Sensor"
+---
+
+
+
+The Motion Sensor platform exposes sensors that read data from inertial measurement units (IMUs) such as accelerometers
+and gyroscopes.
+
+See the [Motion component](/components/motion) documentation for details on supported IMU chips and configuration options.
+
+```yaml
+# Example configuration entry
+sensor:
+ - platform: motion
+ type: acceleration_x
+ name: "Accel X"
+```
+
+## See Also
+
+- [Sensor Component](/components/sensor/)