diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 708a1ba9e..ba856061a 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -1,14 +1,13 @@ --- name: Bug report about: Create a report to help us improve -title: '' +title: "" labels: bug -assignees: '' - +assignees: "" --- -!!! Before submitting a new bug report, please ensure you have searched for any existing bugs. Duplicate issues or -questions that are overly simple or already addressed in the documentation will be removed without any +!!! Before submitting a new bug report, please ensure you have searched for any existing bugs. Duplicate issues or +questions that are overly simple or already addressed in the documentation will be removed without any response. **Describe the bug** @@ -19,6 +18,7 @@ Desribe your SRS Server version here. **To Reproduce** Steps to reproduce the behavior: + 1. Go to '...' 2. Click on '....' 3. Scroll down to '....' diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md index c9cd62803..53e719d50 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -1,10 +1,9 @@ --- name: Feature request about: Suggest an idea for this project -title: '' +title: "" labels: feature -assignees: '' - +assignees: "" --- !!! Before submitting a new feature request, please ensure you have searched for any existing features. Duplicate issues or questions that are overly simple or already addressed in the documentation will be removed without any response. diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 58829c3ae..c9c4cc426 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -14,7 +14,7 @@ jobs: strategy: fail-fast: false matrix: - language: [ 'cpp' ] + language: ["cpp"] steps: - name: Checkout repository diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 3216cbe22..13b8265cf 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -434,35 +434,35 @@ jobs: name: Release ${{ env.SRS_TAG }} body: | If you would like to support SRS, please consider contributing to our [OpenCollective](https://opencollective.com/srs-server). - + [${{ github.sha }}](https://github.com/ossrs/srs/commit/${{ github.sha }}) ${{ github.event.head_commit.message }} - + ## Resource * Source: ${{ env.SRS_SOURCE_MD5 }} [${{ env.SRS_SOURCE_TAR }}](https://github.com/ossrs/srs/releases/download/${{ env.SRS_TAG }}/${{ env.SRS_SOURCE_TAR }}) * Binary: ${{ env.SRS_PACKAGE_MD5 }} [${{ env.SRS_PACKAGE_ZIP }}](https://github.com/ossrs/srs/releases/download/${{ env.SRS_TAG }}/${{ env.SRS_PACKAGE_ZIP }}) * Binary: ${{ env.SRS_CYGWIN_MD5 }} [${{ env.SRS_CYGWIN_TAR }}](https://github.com/ossrs/srs/releases/download/${{ env.SRS_TAG }}/${{ env.SRS_CYGWIN_TAR }}) - + ## Resource Mirror: gitee.com * Source: ${{ env.SRS_SOURCE_MD5 }} [${{ env.SRS_SOURCE_TAR }}](https://gitee.com/ossrs/srs/releases/download/${{ env.SRS_TAG }}/${{ env.SRS_SOURCE_TAR }}) * Binary: ${{ env.SRS_PACKAGE_MD5 }} [${{ env.SRS_PACKAGE_ZIP }}](https://gitee.com/ossrs/srs/releases/download/${{ env.SRS_TAG }}/${{ env.SRS_PACKAGE_ZIP }}) * Binary: ${{ env.SRS_CYGWIN_MD5 }} [${{ env.SRS_CYGWIN_TAR }}](https://gitee.com/ossrs/srs/releases/download/${{ env.SRS_TAG }}/${{ env.SRS_CYGWIN_TAR }}) - + ## Docker * [docker pull ossrs/srs:${{ env.SRS_MAJOR }}](https://ossrs.io/lts/en-us/docs/v7/doc/getting-started) * [docker pull ossrs/srs:${{ env.SRS_TAG }}](https://ossrs.io/lts/en-us/docs/v7/doc/getting-started) * [docker pull ossrs/srs:${{ env.SRS_XYZ }}](https://ossrs.io/lts/en-us/docs/v7/doc/getting-started) - + ## Docker Mirror: aliyun.com * [docker pull registry.cn-hangzhou.aliyuncs.com/ossrs/srs:${{ env.SRS_MAJOR }}](https://ossrs.net/lts/zh-cn/docs/v7/doc/getting-started) * [docker pull registry.cn-hangzhou.aliyuncs.com/ossrs/srs:${{ env.SRS_TAG }}](https://ossrs.net/lts/zh-cn/docs/v7/doc/getting-started) * [docker pull registry.cn-hangzhou.aliyuncs.com/ossrs/srs:${{ env.SRS_XYZ }}](https://ossrs.net/lts/zh-cn/docs/v7/doc/getting-started) - + ## Doc: ossrs.io * [Getting Started](https://ossrs.io/lts/en-us/docs/v7/doc/getting-started) * [Wiki home](https://ossrs.io/lts/en-us/docs/v7/doc/introduction) * [FAQ](https://ossrs.io/lts/en-us/faq), [Features](https://github.com/ossrs/srs/blob/${{ github.sha }}/trunk/doc/Features.md#features) or [ChangeLogs](https://github.com/ossrs/srs/blob/${{ github.sha }}/trunk/doc/CHANGELOG.md#changelog) - + ## Doc: ossrs.net * [快速入门](https://ossrs.net/lts/zh-cn/docs/v7/doc/getting-started) * [中文Wiki首页](https://ossrs.net/lts/zh-cn/docs/v7/doc/introduction) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index e7a9d2875..ca90dacee 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -325,4 +325,3 @@ jobs: runs-on: ubuntu-22.04 steps: - run: echo 'All done' - diff --git a/.gitignore b/.gitignore index 0319e6d68..98d710e79 100644 --- a/.gitignore +++ b/.gitignore @@ -42,4 +42,3 @@ cmake-build-debug /trunk/ide/srs_clion/srs /trunk/ide/srs_clion/Testing/ /trunk/ide/vscode-build - diff --git a/.vscode/README.md b/.vscode/README.md index eb513707b..8af7b20de 100644 --- a/.vscode/README.md +++ b/.vscode/README.md @@ -15,7 +15,7 @@ Run commmand `> CMake: Configure` to configure the project. > Note: You can press `Ctrl+R`, then type `CMake: Configure` then select `Clang` as the toolchain. -> Note: The `settings.json` is used to configure the cmake. It will use `${workspaceFolder}/trunk/ide/srs_clion/CMakeLists.txt` +> Note: The `settings.json` is used to configure the cmake. It will use `${workspaceFolder}/trunk/ide/srs_clion/CMakeLists.txt` > and `${workspaceFolder}/trunk/ide/vscode-build` as the source file and build directory. Click the `Run > Run Without Debugging` button to start the server. diff --git a/.vscode/launch.json b/.vscode/launch.json index 047efcbfd..9358a53df 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -1,36 +1,36 @@ { - "version": "0.2.0", - "configurations": [ + "version": "0.2.0", + "configurations": [ + { + "name": "Launch SRS", + "type": "cppdbg", + "request": "launch", + "program": "${workspaceFolder}/trunk/ide/vscode-build/srs", + "args": ["-c", "conf/console.conf"], + "stopAtEntry": false, + "cwd": "${workspaceFolder}/trunk", + "environment": [], + "externalConsole": false, + "MIMode": "lldb", + "setupCommands": [ { - "name": "Launch SRS", - "type": "cppdbg", - "request": "launch", - "program": "${workspaceFolder}/trunk/ide/vscode-build/srs", - "args": ["-c", "conf/console.conf"], - "stopAtEntry": false, - "cwd": "${workspaceFolder}/trunk", - "environment": [], - "externalConsole": false, - "MIMode": "lldb", - "setupCommands": [ - { - "description": "Enable pretty-printing for gdb", - "text": "-enable-pretty-printing", - "ignoreFailures": true - } - ], - "preLaunchTask": "build", - "logging": { - "engineLogging": true - } - }, - { - "name": "Launch srs-proxy", - "type": "go", - "request": "launch", - "mode": "auto", - "cwd": "${workspaceFolder}/proxy", - "program": "${workspaceFolder}/proxy" - } - ] -} \ No newline at end of file + "description": "Enable pretty-printing for gdb", + "text": "-enable-pretty-printing", + "ignoreFailures": true + } + ], + "preLaunchTask": "build", + "logging": { + "engineLogging": true + } + }, + { + "name": "Launch srs-proxy", + "type": "go", + "request": "launch", + "mode": "auto", + "cwd": "${workspaceFolder}/proxy", + "program": "${workspaceFolder}/proxy" + } + ] +} diff --git a/.vscode/settings.json b/.vscode/settings.json index 58eb63a36..21ec94ae1 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,23 +1,24 @@ { - "cmake.sourceDirectory": "${workspaceFolder}/trunk/ide/srs_clion", - "cmake.buildDirectory": "${workspaceFolder}/trunk/ide/vscode-build", - "cmake.configureOnOpen": false, - "files.associations": { - "vector": "cpp", - "__hash_table": "cpp", - "__split_buffer": "cpp", - "__tree": "cpp", - "array": "cpp", - "bitset": "cpp", - "deque": "cpp", - "initializer_list": "cpp", - "list": "cpp", - "map": "cpp", - "queue": "cpp", - "set": "cpp", - "stack": "cpp", - "string": "cpp", - "string_view": "cpp", - "unordered_map": "cpp" - } + "cmake.sourceDirectory": "${workspaceFolder}/trunk/ide/srs_clion", + "cmake.buildDirectory": "${workspaceFolder}/trunk/ide/vscode-build", + "cmake.configureOnOpen": false, + "files.associations": { + "vector": "cpp", + "__hash_table": "cpp", + "__split_buffer": "cpp", + "__tree": "cpp", + "array": "cpp", + "bitset": "cpp", + "deque": "cpp", + "initializer_list": "cpp", + "list": "cpp", + "map": "cpp", + "queue": "cpp", + "set": "cpp", + "stack": "cpp", + "string": "cpp", + "string_view": "cpp", + "unordered_map": "cpp" + }, + "files.eol": "\n" } diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 98388f3b3..83fc97a9a 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -1,17 +1,16 @@ { - "version": "2.0.0", - "tasks": [ - { - "label": "build", - "type": "shell", - "command": "cmake --build ${workspaceFolder}/trunk/ide/vscode-build", - "group": { - "kind": "build", - "isDefault": true - }, - "problemMatcher": ["$gcc"], - "detail": "Build SRS by cmake." - } - ] - } - \ No newline at end of file + "version": "2.0.0", + "tasks": [ + { + "label": "build", + "type": "shell", + "command": "cmake --build ${workspaceFolder}/trunk/ide/vscode-build", + "group": { + "kind": "build", + "isDefault": true + }, + "problemMatcher": ["$gcc"], + "detail": "Build SRS by cmake." + } + ] +} diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md deleted file mode 100644 index af1600a2f..000000000 --- a/CONTRIBUTING.md +++ /dev/null @@ -1,15 +0,0 @@ -Welome to contribute to SRS! - -1. Please start from fixing some [Issues: good first issue](https://github.com/ossrs/srs/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22). -1. Please [setup your email](https://ossrs.io/lts/en-us/how-to-file-pr#setup-your-email) before contributing, this is important. -1. Then follow the [guide](https://ossrs.io/lts/en-us/how-to-file-pr) or [贡献代码](https://ossrs.net/lts/zh-cn/how-to-file-pr) to file a PR. -1. We will review your PR ASAP. Since our bandwidth is limited, we appreciate your patience. - -If achieve [50 commits](https://github.com/ossrs/srs/graphs/contributors), you will be [TOC of SRS](https://github.com/ossrs/srs/blob/develop/trunk/AUTHORS.md#toc). - -* The update of this file MUST be approved by [Winlin](https://github.com/winlinvip) and 3+ [TOC](https://github.com/ossrs/srs/blob/develop/trunk/AUTHORS.md#toc). -* Each [PullRequest](https://github.com/ossrs/srs/pulls) MUST be approved by 2+ [TOC](https://github.com/ossrs/srs/blob/develop/trunk/AUTHORS.md#toc) or [Developers](https://github.com/ossrs/srs/blob/develop/trunk/AUTHORS.md#developers). -* The name of TOC will be listed at [README](https://github.com/ossrs/srs#authors) forever. - -All [contributors](https://github.com/ossrs/srs/blob/develop/trunk/AUTHORS.md#contributors) are listed in SRS authors. - diff --git a/README.md b/README.md index 2ebe47cad..6b9147f0c 100755 --- a/README.md +++ b/README.md @@ -1,35 +1,11 @@ -# SRS(Simple Realtime Server) +# NPL ITP Intranet Livestream Server - -[](https://github.com/ossrs/srs/actions?query=workflow%3ACodeQL+branch%3Adevelop) -[](https://github.com/ossrs/srs/actions/workflows/release.yml?query=workflow%3ARelease) -[](https://github.com/ossrs/srs/actions?query=workflow%3ATest+branch%3Adevelop) -[](https://app.codecov.io/gh/ossrs/srs/tree/develop) -[](https://ossrs.net/lts/zh-cn/contact#discussion) -[](https://twitter.com/srs_server) -[](https://www.youtube.com/@srs_server) -[](https://discord.gg/yZ4BnPmHAd) -[](https://app.fossa.com/projects/git%2Bgithub.com%2Fossrs%2Fsrs?ref=badge_small) -[](https://stackoverflow.com/questions/tagged/simple-realtime-server) -[](https://opencollective.com/srs-server) -[](https://hub.docker.com/r/ossrs/srs/tags) +> This is a fork of SRS Service with additional features provided that enhance the experience of livestream in NPL. +> **COPYRIGHT (C) 2024-2025 Jason Yang Jiepeng, Jasper, HyperKNF, Hayden, NPL ITP Team, PLK, NPL** -SRS/6.0 ([Hang](https://ossrs.io/lts/en-us/product#release-60)) is a simple, high-efficiency, and real-time video server, -supporting RTMP/WebRTC/HLS/HTTP-FLV/SRT/MPEG-DASH/GB28181, Linux/Windows/macOS, X86_64/ARMv7/AARCH64/M1/RISCV/LOONGARCH/MIPS, -and essential [features](trunk/doc/Features.md#features). +## Usage (Simple Version) -[](https://ossrs.net/wiki/images/SRS-SingleNode-4.0-hd.png) - -> Note: For more details on the single-node architecture for SRS, please visit the following [link](https://www.figma.com/file/333POxVznQ8Wz1Rxlppn36/SRS-4.0-Server-Arch). - -SRS is licenced under [MIT](https://github.com/ossrs/srs/blob/develop/LICENSE), and some third-party libraries are -distributed under their [licenses](https://ossrs.io/lts/en-us/license). - - - -## Usage - -Please check the Getting Started guide in [English](https://ossrs.io/lts/en-us/docs/v5/doc/getting-started) +Please check the Getting Started guide in [English](https://ossrs.io/lts/en-us/docs/v5/doc/getting-started) or [Chinese](https://ossrs.net/lts/zh-cn/docs/v5/doc/getting-started). We highly recommend using SRS with docker: ```bash @@ -48,158 +24,150 @@ ffmpeg -re -i ./doc/source.flv -c copy -f flv -y rtmp://localhost/live/livestrea Alternatively, stream by [OBS](https://obsproject.com/download) using the following configuration: -* Service: `Custom` -* Server: `rtmp://localhost/live` -* Stream Key: `livestream` +- Service: `Custom` +- Server: `rtmp://localhost/live` +- Stream Key: `livestream` Play the following streams using media players: -* To play an RTMP stream with URL `rtmp://localhost/live/livestream` on [VLC player](https://www.videolan.org/), open the player, go to Media > Open Network Stream, enter the URL and click Play. -* You can play HTTP-FLV stream URL [http://localhost:8080/live/livestream.flv](http://localhost:8080/players/srs_player.html?autostart=true&stream=livestream.flv) on a webpage using the srs-player, an HTML5-based player. -* Use srs-player for playing HLS stream with URL [http://localhost:8080/live/livestream.m3u8](http://localhost:8080/players/srs_player.html?autostart=true&stream=livestream.m3u8). +- To play an RTMP stream with URL `rtmp://localhost/live/livestream` on [VLC player](https://www.videolan.org/), open the player, go to Media > Open Network Stream, enter the URL and click Play. +- You can play HTTP-FLV stream URL [http://localhost:8080/live/livestream.flv](http://localhost:8080/players/srs_player.html?autostart=true&stream=livestream.flv) on a webpage using the srs-player, an HTML5-based player. +- Use srs-player for playing HLS stream with URL [http://localhost:8080/live/livestream.m3u8](http://localhost:8080/players/srs_player.html?autostart=true&stream=livestream.m3u8). -If you'd like to use WebRTC, convert RTMP to WebRTC, or convert WebRTC to RTMP, please check out -the wiki documentation in either [English](https://ossrs.io/lts/en-us/docs/v5/doc/getting-started#webrtc) or +If you'd like to use WebRTC, convert RTMP to WebRTC, or convert WebRTC to RTMP, please check out +the wiki documentation in either [English](https://ossrs.io/lts/en-us/docs/v5/doc/getting-started#webrtc) or [Chinese](https://ossrs.net/lts/zh-cn/docs/v5/doc/getting-started#webrtc). -To learn more about RTMP, HLS, HTTP-FLV, SRT, MPEG-DASH, WebRTC protocols, clustering, -HTTP API, DVR, and transcoding, please check the documents in [English](https://ossrs.io) +To learn more about RTMP, HLS, HTTP-FLV, SRT, MPEG-DASH, WebRTC protocols, clustering, +HTTP API, DVR, and transcoding, please check the documents in [English](https://ossrs.io) or [Chinese](https://ossrs.net). -## Sponsor +## Complete User Guideline -Would you like additional assistance from us? By becoming a sponsor or backer of SRS, we can provide you -with the support you need: +### Features -* Backer: $5 per month, online text chat support through Discord. -* Sponsor: $100 per month, online text chat plus online meeting support. +Please read [FEATURES](trunk/doc/Features.md#features). -Please visit [OpenCollective](https://opencollective.com/srs-server) to become a backer or sponsor, and send -us a direct message on [Discord](https://discord.gg/yZ4BnPmHAd). We are currently providing support to the -developers listed below: +### Changelog -[](https://opencollective.com/srs-server) +Please read [CHANGELOG](trunk/doc/CHANGELOG.md#changelog). -At SRS, our goal is to create a free, open-source community that helps developers all over the world -build high-quality streaming and RTC platforms for their businesses. +### Performance - +Please read [PERFORMANCE](trunk/doc/PERFORMANCE.md#performance). -## Contributing +### Architecture -The [authors](trunk/AUTHORS.md#authors), [TOC(Technical Oversight Committee)](trunk/AUTHORS.md#toc), -and [contributors](trunk/AUTHORS.md#contributors) are listed [here](trunk/AUTHORS.md). The TOC members +Please read [ARCHITECTURE](trunk/doc/Architecture.md#architecture). + +### Ports + +Please read [PORTS](trunk/doc/Resources.md#ports). + +### APIs + +Please read [APIS](trunk/doc/Resources.md#apis). + +### Mirrors + +Please read [MIRRORS](trunk/doc/Resources.md#mirrors). + +### Dockers + +Please read [DOCKERS](trunk/doc/Dockers.md). + +## SRS(Simple Realtime Server) + +**Here is a short appendix introduce the official package of SRS Simple Realtime Server:** + +SRS/6.0 is a simple, high-efficiency, and real-time video server, +supporting RTMP/WebRTC/HLS/HTTP-FLV/SRT/MPEG-DASH/GB28181, Linux/Windows/macOS, X86_64/ARMv7/AARCH64/M1/RISCV/LOONGARCH/MIPS, +and essential [features](trunk/doc/Features.md#features). + +[](https://ossrs.net/wiki/images/SRS-SingleNode-4.0-hd.png) + +> Note: For more details on the single-node architecture for SRS, please visit the following [link](https://www.figma.com/file/333POxVznQ8Wz1Rxlppn36/SRS-4.0-Server-Arch). + +SRS is licenced under [MIT](https://github.com/ossrs/srs/blob/develop/LICENSE), and some third-party libraries are distributed under their [licenses](https://ossrs.io/lts/en-us/license). + +### Contribution to official repo of SRS + +The [authors](trunk/AUTHORS.md#authors), [TOC(Technical Oversight Committee)](trunk/AUTHORS.md#toc), +and [contributors](trunk/AUTHORS.md#contributors) are listed [here](trunk/AUTHORS.md). The TOC members who made significant contributions and maintained parts of SRS are listed below: -* [Winlin](https://github.com/winlinvip): Founder of the project, focusing on ST and Issues/PR. Responsible for architecture and maintenance. -* [ZhaoWenjie](https://github.com/wenjiegit): One of the earliest contributors, focusing on HDS and Windows. Has expertise in client technology. -* [ShiWei](https://github.com/runner365): Specializes in SRT and H.265, maintaining SRT and FLV patches for FFmpeg. An expert in codecs and FFmpeg. -* [XiaoZhihong](https://github.com/xiaozhihong): Concentrates on WebRTC/QUIC and SRT, with expertise in network QoS. Contributed to ARM on ST and was the original contributor for WebRTC. -* [WuPengqiang](https://github.com/Bepartofyou): Focused on H.265, initially contributed to the FFmpeg module in SRS for transcoding AAC with OPUS for WebRTC. -* [XiaLixin](https://github.com/xialixin): Specializes in GB28181, with expertise in live streaming and WebRTC. -* [LiPeng](https://github.com/lipeng19811218): Concentrates on WebRTC and contributes to memory management and smart pointers. -* [ChenGuanghua](https://github.com/chen-guanghua): Focused on WebRTC/QoS and introduced the Asan toolchain to SRS. -* [ChenHaibo](https://github.com/duiniuluantanqin): Specializes in GB28181 and HTTP API, contributing to patches for FFmpeg with WHIP. -* [ZhangJunqin](https://github.com/chundonglinlin): Focused on H.265, Prometheus Exporter, and API module. +- [Winlin](https://github.com/winlinvip): Founder of the project, focusing on ST and Issues/PR. Responsible for architecture and maintenance. +- [ZhaoWenjie](https://github.com/wenjiegit): One of the earliest contributors, focusing on HDS and Windows. Has expertise in client technology. +- [ShiWei](https://github.com/runner365): Specializes in SRT and H.265, maintaining SRT and FLV patches for FFmpeg. An expert in codecs and FFmpeg. +- [XiaoZhihong](https://github.com/xiaozhihong): Concentrates on WebRTC/QUIC and SRT, with expertise in network QoS. Contributed to ARM on ST and was the original contributor for WebRTC. +- [WuPengqiang](https://github.com/Bepartofyou): Focused on H.265, initially contributed to the FFmpeg module in SRS for transcoding AAC with OPUS for WebRTC. +- [XiaLixin](https://github.com/xialixin): Specializes in GB28181, with expertise in live streaming and WebRTC. +- [LiPeng](https://github.com/lipeng19811218): Concentrates on WebRTC and contributes to memory management and smart pointers. +- [ChenGuanghua](https://github.com/chen-guanghua): Focused on WebRTC/QoS and introduced the Asan toolchain to SRS. +- [ChenHaibo](https://github.com/duiniuluantanqin): Specializes in GB28181 and HTTP API, contributing to patches for FFmpeg with WHIP. +- [ZhangJunqin](https://github.com/chundonglinlin): Focused on H.265, Prometheus Exporter, and API module. A huge `THANK YOU` goes out to: -* All the [contributors](trunk/AUTHORS.md#contributors) of SRS. -* All the friends of SRS who gave [big support](https://ossrs.net/lts/zh-cn/product). -* [Genes](http://sourceforge.net/users/genes), [Mabbott](http://sourceforge.net/users/mabbott), and [Michael Talyanksy](https://github.com/michaeltalyansky) for making and sharing [State Threads](https://github.com/ossrs/state-threads/tree/srs). +- All the [contributors](trunk/AUTHORS.md#contributors) of SRS. +- All the friends of SRS who gave [big support](https://ossrs.net/lts/zh-cn/product). +- [Genes](http://sourceforge.net/users/genes), [Mabbott](http://sourceforge.net/users/mabbott), and [Michael Talyanksy](https://github.com/michaeltalyansky) for making and sharing [State Threads](https://github.com/ossrs/state-threads/tree/srs). -We're really thankful to everyone in the community for helping us find bugs and improve the project. +We're really thankful to everyone in the community for helping us find bugs and improve the project. To stay in touch and keep helping our community, please check out this [guide](https://github.com/ossrs/srs/contribute). ## LICENSE -[](https://app.fossa.com/projects/git%2Bgithub.com%2Fossrs%2Fsrs?ref=badge_small) +NPL ITP Intranet Livestream Server is a fork of SRS and also livenced under [MIT](https://github.com/PLK-NPL-ITP/livestream_server/blob/develop/LICENSE) -SRS is licenced under [MIT](https://github.com/ossrs/srs/blob/develop/LICENSE), and some third-party libraries are -distributed under their [licenses](https://ossrs.io/lts/en-us/license). - -[](https://app.fossa.com/projects/git%2Bgithub.com%2Fossrs%2Fsrs?ref=badge_large) +SRS is licenced under [MIT](https://github.com/ossrs/srs/blob/develop/LICENSE), and some third-party libraries are distributed under their [licenses](https://ossrs.io/lts/en-us/license). ## Releases -* 2025-05-03, [Release v6.0-a2](https://github.com/ossrs/srs/releases/tag/v6.0-a2), v6.0-a2, 6.0 alpha2, v6.0.165, 169712 lines. -* 2024-09-01, [Release v6.0-a1](https://github.com/ossrs/srs/releases/tag/v6.0-a1), v6.0-a1, 6.0 alpha1, v6.0.155, 169636 lines. -* 2024-07-27, [Release v6.0-a0](https://github.com/ossrs/srs/releases/tag/v6.0-a0), v6.0-a0, 6.0 alpha0, v6.0.145, 169259 lines. -* 2024-07-04, [Release v6.0-d6](https://github.com/ossrs/srs/releases/tag/v6.0-d6), v6.0-d6, 6.0 dev6, v6.0.134, 168904 lines. -* 2024-06-15, [Release v6.0-d5](https://github.com/ossrs/srs/releases/tag/v6.0-d5), v6.0-d5, 6.0 dev5, v6.0.129, 168454 lines. -* 2024-02-15, [Release v6.0-d4](https://github.com/ossrs/srs/releases/tag/v6.0-d4), v6.0-d4, 6.0 dev4, v6.0.113, 167695 lines. -* 2023-11-19, [Release v6.0-d3](https://github.com/ossrs/srs/releases/tag/v6.0-d3), v6.0-d3, 6.0 dev3, v6.0.101, 167560 lines. -* 2023-09-28, [Release v6.0-d2](https://github.com/ossrs/srs/releases/tag/v6.0-d2), v6.0-d2, 6.0 dev2, v6.0.85, 167509 lines. -* 2023-08-31, [Release v6.0-d1](https://github.com/ossrs/srs/releases/tag/v6.0-d1), v6.0-d1, 6.0 dev1, v6.0.72, 167135 lines. -* 2023-07-09, [Release v6.0-d0](https://github.com/ossrs/srs/releases/tag/v6.0-d0), v6.0-d0, 6.0 dev0, v6.0.59, 166739 lines. -* 2024-06-15, [Release v5.0-r3](https://github.com/ossrs/srs/releases/tag/v5.0-r3), v5.0-r3, 5.0 release3, v5.0.213, 163585 lines. -* 2024-04-03, [Release v5.0-r2](https://github.com/ossrs/srs/releases/tag/v5.0-r2), v5.0-r2, 5.0 release2, v5.0.210, 163515 lines. -* 2024-02-15, [Release v5.0-r1](https://github.com/ossrs/srs/releases/tag/v5.0-r1), v5.0-r1, 5.0 release1, v5.0.208, 163441 lines. -* 2023-12-30, [Release v5.0-r0](https://github.com/ossrs/srs/releases/tag/v5.0-r0), v5.0-r0, 5.0 release0, v5.0.205, 163363 lines. -* 2023-11-19, [Release v5.0-b7](https://github.com/ossrs/srs/releases/tag/v5.0-b7), v5.0-b7, 5.0 beta7, v5.0.200, 163305 lines. -* 2023-10-25, [Release v5.0-b6](https://github.com/ossrs/srs/releases/tag/v5.0-b6), v5.0-b6, 5.0 beta6, v5.0.195, 163303 lines. -* 2023-09-28, [Release v5.0-b5](https://github.com/ossrs/srs/releases/tag/v5.0-b5), v5.0-b5, 5.0 beta5, v5.0.185, 163254 lines. -* 2023-08-31, [Release v5.0-b4](https://github.com/ossrs/srs/releases/tag/v5.0-b4), v5.0-b4, 5.0 beta4, v5.0.176, 162919 lines. -* 2023-08-02, [Release v5.0-b3](https://github.com/ossrs/srs/releases/tag/v5.0-b3), v5.0-b3, 5.0 beta3, v5.0.170, 162704 lines. -* 2023-07-09, [Release v5.0-b2](https://github.com/ossrs/srs/releases/tag/v5.0-b2), v5.0-b2, 5.0 beta2, v5.0.166, 162520 lines. -* 2023-06-11, [Release v5.0-b1](https://github.com/ossrs/srs/releases/tag/v5.0-b1), v5.0-b1, 5.0 beta1, v5.0.157, 162494 lines. -* 2023-05-14, [Release v5.0-b0](https://github.com/ossrs/srs/releases/tag/v5.0-b0), v5.0-b0, 5.0 beta0, v5.0.155, 162600 lines. -* 2023-03-23, [Release v5.0-a5](https://github.com/ossrs/srs/releases/tag/v5.0-a5), v5.0-a5, 5.0 alpha5, v5.0.148, 162066 lines. -* 2023-02-12, [Release v5.0-a4](https://github.com/ossrs/srs/releases/tag/v5.0-a4), v5.0-a4, 5.0 alpha4, v5.0.141, 161897 lines. -* 2023-01-02, [Release v5.0-a3](https://github.com/ossrs/srs/releases/tag/v5.0-a3), v5.0-a3, 5.0 alpha3, v5.0.128, 161327 lines. -* 2022-12-18, [Release v5.0-a2](https://github.com/ossrs/srs/releases/tag/v5.0-a2), v5.0-a2, 5.0 alpha2, v5.0.112, 161233 lines. -* 2022-12-01, [Release v5.0-a1](https://github.com/ossrs/srs/releases/tag/v5.0-a1), v5.0-a1, 5.0 alpha1, v5.0.100, 160817 lines. -* 2022-11-25, [Release v5.0-a0](https://github.com/ossrs/srs/releases/tag/v5.0-a0), v5.0-a0, 5.0 alpha0, v5.0.98, 159813 lines. -* 2022-11-22, Release [v4.0-r4](https://github.com/ossrs/srs/releases/tag/v4.0-r4), v4.0-r4, 4.0 release4, v4.0.268, 145482 lines. -* 2022-09-16, Release [v4.0-r3](https://github.com/ossrs/srs/releases/tag/v4.0-r3), v4.0-r3, 4.0 release3, v4.0.265, 145328 lines. -* 2022-08-24, Release [v4.0-r2](https://github.com/ossrs/srs/releases/tag/v4.0-r2), v4.0-r2, 4.0 release2, v4.0.257, 144890 lines. -* 2022-06-29, Release [v4.0-r1](https://github.com/ossrs/srs/releases/tag/v4.0-r1), v4.0-r1, 4.0 release1, v4.0.253, 144680 lines. -* 2022-06-11, Release [v4.0-r0](https://github.com/ossrs/srs/releases/tag/v4.0-r0), v4.0-r0, 4.0 release0, v4.0.252, 144680 lines. -* 2020-06-27, [Release v3.0-r0](https://github.com/ossrs/srs/releases/tag/v3.0-r0), 3.0 release0, 3.0.141, 122674 lines. -* 2020-02-02, [Release v3.0-b0](https://github.com/ossrs/srs/releases/tag/v3.0-b0), 3.0 beta0, 3.0.112, 121709 lines. -* 2019-10-04, [Release v3.0-a0](https://github.com/ossrs/srs/releases/tag/v3.0-a0), 3.0 alpha0, 3.0.56, 107946 lines. -* 2017-03-03, [Release v2.0-r0](https://github.com/ossrs/srs/releases/tag/v2.0-r0), 2.0 release0, 2.0.234, 86373 lines. -* 2016-08-06, [Release v2.0-b0](https://github.com/ossrs/srs/releases/tag/v2.0-b0), 2.0 beta0, 2.0.210, 89704 lines. -* 2015-08-23, [Release v2.0-a0](https://github.com/ossrs/srs/releases/tag/v2.0-a0), 2.0 alpha0, 2.0.185, 89022 lines. -* 2014-12-05, [Release v1.0-r0](https://github.com/ossrs/srs/releases/tag/v1.0-r0), all bug fixed, 1.0.10, 59391 lines. -* 2014-10-09, [Release v0.9.8](https://github.com/ossrs/srs/releases/tag/v0.9.8), all bug fixed, 1.0.0, 59316 lines. -* 2014-04-07, [Release v0.9.1](https://github.com/ossrs/srs/releases/tag/v0.9.1), live streaming. 30000 lines. -* 2013-10-23, [Release v0.1.0](https://github.com/ossrs/srs/releases/tag/v0.1.0), rtmp. 8287 lines. -* 2013-10-17, Created. - -## Features - -Please read [FEATURES](trunk/doc/Features.md#features). - - -## Changelog - -Please read [CHANGELOG](trunk/doc/CHANGELOG.md#changelog). - -## Performance - -Please read [PERFORMANCE](trunk/doc/PERFORMANCE.md#performance). - -## Architecture - -Please read [ARCHITECTURE](trunk/doc/Architecture.md#architecture). - -## Ports - -Please read [PORTS](trunk/doc/Resources.md#ports). - -## APIs - -Please read [APIS](trunk/doc/Resources.md#apis). - -## Mirrors - -Please read [MIRRORS](trunk/doc/Resources.md#mirrors). - -## Dockers - -Please read [DOCKERS](trunk/doc/Dockers.md). - -Beijing, 2013.10 -Winlin +Bold text is the release from the contribution of NPL ITP Development Group! +- **2025-05-13, [Release v6.0.166.2b](), v6.** +- 2025-05-03, [Release v6.0-a2](https://github.com/ossrs/srs/releases/tag/v6.0-a2), v6.0-a2, 6.0 alpha2, v6.0.165, 169712 lines. +- 2024-09-01, [Release v6.0-a1](https://github.com/ossrs/srs/releases/tag/v6.0-a1), v6.0-a1, 6.0 alpha1, v6.0.155, 169636 lines. +- 2024-07-27, [Release v6.0-a0](https://github.com/ossrs/srs/releases/tag/v6.0-a0), v6.0-a0, 6.0 alpha0, v6.0.145, 169259 lines. +- 2024-07-04, [Release v6.0-d6](https://github.com/ossrs/srs/releases/tag/v6.0-d6), v6.0-d6, 6.0 dev6, v6.0.134, 168904 lines. +- 2024-06-15, [Release v6.0-d5](https://github.com/ossrs/srs/releases/tag/v6.0-d5), v6.0-d5, 6.0 dev5, v6.0.129, 168454 lines. +- 2024-02-15, [Release v6.0-d4](https://github.com/ossrs/srs/releases/tag/v6.0-d4), v6.0-d4, 6.0 dev4, v6.0.113, 167695 lines. +- 2023-11-19, [Release v6.0-d3](https://github.com/ossrs/srs/releases/tag/v6.0-d3), v6.0-d3, 6.0 dev3, v6.0.101, 167560 lines. +- 2023-09-28, [Release v6.0-d2](https://github.com/ossrs/srs/releases/tag/v6.0-d2), v6.0-d2, 6.0 dev2, v6.0.85, 167509 lines. +- 2023-08-31, [Release v6.0-d1](https://github.com/ossrs/srs/releases/tag/v6.0-d1), v6.0-d1, 6.0 dev1, v6.0.72, 167135 lines. +- 2023-07-09, [Release v6.0-d0](https://github.com/ossrs/srs/releases/tag/v6.0-d0), v6.0-d0, 6.0 dev0, v6.0.59, 166739 lines. +- 2024-06-15, [Release v5.0-r3](https://github.com/ossrs/srs/releases/tag/v5.0-r3), v5.0-r3, 5.0 release3, v5.0.213, 163585 lines. +- 2024-04-03, [Release v5.0-r2](https://github.com/ossrs/srs/releases/tag/v5.0-r2), v5.0-r2, 5.0 release2, v5.0.210, 163515 lines. +- 2024-02-15, [Release v5.0-r1](https://github.com/ossrs/srs/releases/tag/v5.0-r1), v5.0-r1, 5.0 release1, v5.0.208, 163441 lines. +- 2023-12-30, [Release v5.0-r0](https://github.com/ossrs/srs/releases/tag/v5.0-r0), v5.0-r0, 5.0 release0, v5.0.205, 163363 lines. +- 2023-11-19, [Release v5.0-b7](https://github.com/ossrs/srs/releases/tag/v5.0-b7), v5.0-b7, 5.0 beta7, v5.0.200, 163305 lines. +- 2023-10-25, [Release v5.0-b6](https://github.com/ossrs/srs/releases/tag/v5.0-b6), v5.0-b6, 5.0 beta6, v5.0.195, 163303 lines. +- 2023-09-28, [Release v5.0-b5](https://github.com/ossrs/srs/releases/tag/v5.0-b5), v5.0-b5, 5.0 beta5, v5.0.185, 163254 lines. +- 2023-08-31, [Release v5.0-b4](https://github.com/ossrs/srs/releases/tag/v5.0-b4), v5.0-b4, 5.0 beta4, v5.0.176, 162919 lines. +- 2023-08-02, [Release v5.0-b3](https://github.com/ossrs/srs/releases/tag/v5.0-b3), v5.0-b3, 5.0 beta3, v5.0.170, 162704 lines. +- 2023-07-09, [Release v5.0-b2](https://github.com/ossrs/srs/releases/tag/v5.0-b2), v5.0-b2, 5.0 beta2, v5.0.166, 162520 lines. +- 2023-06-11, [Release v5.0-b1](https://github.com/ossrs/srs/releases/tag/v5.0-b1), v5.0-b1, 5.0 beta1, v5.0.157, 162494 lines. +- 2023-05-14, [Release v5.0-b0](https://github.com/ossrs/srs/releases/tag/v5.0-b0), v5.0-b0, 5.0 beta0, v5.0.155, 162600 lines. +- 2023-03-23, [Release v5.0-a5](https://github.com/ossrs/srs/releases/tag/v5.0-a5), v5.0-a5, 5.0 alpha5, v5.0.148, 162066 lines. +- 2023-02-12, [Release v5.0-a4](https://github.com/ossrs/srs/releases/tag/v5.0-a4), v5.0-a4, 5.0 alpha4, v5.0.141, 161897 lines. +- 2023-01-02, [Release v5.0-a3](https://github.com/ossrs/srs/releases/tag/v5.0-a3), v5.0-a3, 5.0 alpha3, v5.0.128, 161327 lines. +- 2022-12-18, [Release v5.0-a2](https://github.com/ossrs/srs/releases/tag/v5.0-a2), v5.0-a2, 5.0 alpha2, v5.0.112, 161233 lines. +- 2022-12-01, [Release v5.0-a1](https://github.com/ossrs/srs/releases/tag/v5.0-a1), v5.0-a1, 5.0 alpha1, v5.0.100, 160817 lines. +- 2022-11-25, [Release v5.0-a0](https://github.com/ossrs/srs/releases/tag/v5.0-a0), v5.0-a0, 5.0 alpha0, v5.0.98, 159813 lines. +- 2022-11-22, Release [v4.0-r4](https://github.com/ossrs/srs/releases/tag/v4.0-r4), v4.0-r4, 4.0 release4, v4.0.268, 145482 lines. +- 2022-09-16, Release [v4.0-r3](https://github.com/ossrs/srs/releases/tag/v4.0-r3), v4.0-r3, 4.0 release3, v4.0.265, 145328 lines. +- 2022-08-24, Release [v4.0-r2](https://github.com/ossrs/srs/releases/tag/v4.0-r2), v4.0-r2, 4.0 release2, v4.0.257, 144890 lines. +- 2022-06-29, Release [v4.0-r1](https://github.com/ossrs/srs/releases/tag/v4.0-r1), v4.0-r1, 4.0 release1, v4.0.253, 144680 lines. +- 2022-06-11, Release [v4.0-r0](https://github.com/ossrs/srs/releases/tag/v4.0-r0), v4.0-r0, 4.0 release0, v4.0.252, 144680 lines. +- 2020-06-27, [Release v3.0-r0](https://github.com/ossrs/srs/releases/tag/v3.0-r0), 3.0 release0, 3.0.141, 122674 lines. +- 2020-02-02, [Release v3.0-b0](https://github.com/ossrs/srs/releases/tag/v3.0-b0), 3.0 beta0, 3.0.112, 121709 lines. +- 2019-10-04, [Release v3.0-a0](https://github.com/ossrs/srs/releases/tag/v3.0-a0), 3.0 alpha0, 3.0.56, 107946 lines. +- 2017-03-03, [Release v2.0-r0](https://github.com/ossrs/srs/releases/tag/v2.0-r0), 2.0 release0, 2.0.234, 86373 lines. +- 2016-08-06, [Release v2.0-b0](https://github.com/ossrs/srs/releases/tag/v2.0-b0), 2.0 beta0, 2.0.210, 89704 lines. +- 2015-08-23, [Release v2.0-a0](https://github.com/ossrs/srs/releases/tag/v2.0-a0), 2.0 alpha0, 2.0.185, 89022 lines. +- 2014-12-05, [Release v1.0-r0](https://github.com/ossrs/srs/releases/tag/v1.0-r0), all bug fixed, 1.0.10, 59391 lines. +- 2014-10-09, [Release v0.9.8](https://github.com/ossrs/srs/releases/tag/v0.9.8), all bug fixed, 1.0.0, 59316 lines. +- 2014-04-07, [Release v0.9.1](https://github.com/ossrs/srs/releases/tag/v0.9.1), live streaming. 30000 lines. +- 2013-10-23, [Release v0.1.0](https://github.com/ossrs/srs/releases/tag/v0.1.0), rtmp. 8287 lines. +- 2013-10-17, Created. diff --git a/SECURITY.md b/SECURITY.md deleted file mode 100644 index 91045ff9f..000000000 --- a/SECURITY.md +++ /dev/null @@ -1,8 +0,0 @@ -# Security Policy - -We appreciate work to discover security vulnerabilities, but as SRS is entirely volunteer driven, -so we might not be able to respond to issues in time. - -Please click [here](https://github.com/ossrs/srs/security/advisories) to report a vulnerability. - - diff --git a/docker-compose.yaml b/docker-compose.yaml new file mode 100644 index 000000000..b3e4d2df2 --- /dev/null +++ b/docker-compose.yaml @@ -0,0 +1,28 @@ +name: OSSR-SRS + +services: + srs: + container_name: SRS-Streaming-Server + # image: ossrs/srs:v6.0.166 + # image: itprefects/srs:v6.0.166.1h + image: itprefects/srs:v6.0.166.2b + restart: unless-stopped + environment: + - SRS_DAEMON=off + - SRS_IN_DOCKER=on + - CANDIDATE=127.0.0.1 + working_dir: /usr/local/srs + ports: + - "10080:10080/udp" + - "1935:1935" + - "1985:1985" + - "1990:1990" + - "5060:5060" + - "8000:8000/udp" + - "8080:8080" + - "8088:8088" + - "9000:9000" + volumes: + - ./docker_data/config:/usr/local/srs/conf + - ./docker_data/DVR_Record:/usr/local/srs/DVR_Record + - ./docker_data/objects:/usr/local/srs/objs diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 000000000..1ea8fb6d4 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,27 @@ +{ + "name": "livestream_server", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "devDependencies": { + "prettier": "^3.5.3" + } + }, + "node_modules/prettier": { + "version": "3.5.3", + "resolved": "https://mirrors.huaweicloud.com/repository/npm/prettier/-/prettier-3.5.3.tgz", + "integrity": "sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw==", + "dev": true, + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 000000000..1b53ca166 --- /dev/null +++ b/package.json @@ -0,0 +1,5 @@ +{ + "devDependencies": { + "prettier": "^3.5.3" + } +} diff --git a/trunk/AUTHORS.md b/trunk/AUTHORS.md deleted file mode 100644 index 2426c9930..000000000 --- a/trunk/AUTHORS.md +++ /dev/null @@ -1,173 +0,0 @@ -## AUTHORS - -The authors and administrators of SRS, ordered by first contribution: - -- `Winlin` -- `XiaoZhihong` - -## TOC - -The TOC(Technical Oversight Committee), ordered by first contribution: - -- `Winlin` -- `ZhaoWenjie` -- `ShiWei` -- `XiaoZhihong` -- `WuPengqiang` -- `XiaLixin` -- `LiPeng` -- `ChenGuanghua` -- `ChenHaibo` -- `ZhangJunqin` - -## CONTRIBUTORS - -CONTRIBUTORS ordered by first contribution. - -* `Winlin` -* `Winlin` -* `Winlin` -* `ZhaoWenjie` -* `ZhaoWenjie<740936897@qq.com>` -* `ZhaoWenjie` -* `xiangcheng.liu` -* `naijia.liu` -* `alcoholyi` -* `byteman` -* `chad.wang` -* `suhetao` -* `Johnny` -* `karthikeyan` -* `StevenLiu` -* `StevenLiu` -* `StevenLiu` -* `zhengfl` -* `tufang14` -* `allspace` -* `niesongsong` -* `rudeb0t` -* `CallMeNP` -* `synote` -* `lovecat` -* `panda1986<542638787@qq.com>` -* `YueHonghui` -* `ThomasDreibholz` -* `JuntaoLiu` -* `RocFang` -* `MakarovYaroslav` -* `MirkoVelic` -* `HuiZhang(huzhang2)` -* `OtterWa` -* `walkermi<172192667@qq.com>` -* `haofz` -* `ME_Kun_Han` -* `ljx0305` -* `cenxinwei` -* `StarBrilliant` -* `xubin` -* `intliang` -* `flowerwrong` -* `YLX<568414379@qq.com>` -* `J` -* `Harlan` -* `hankun` -* `JonathanBarratt` -* `KeeganH` -* `liuxc0116` -* `ChengdongZhang` -* `lovacat` -* `qiang.li` -* `HungMingWu` -* `Himer` -* `XiaLixin` -* `XiaLixin<68469352@qq.com>` -* `XiaLixin` -* `XiaLixin` -* `alphonsetai` -* `Michael.Ma` -* `lam2003` -* `ShiWei` -* `ShiWei` -* `ShiWei` -* `XiaofengWang` -* `XiaoZhihong` -* `XiaoZhihong` -* `XiaoZhihong` -* `yanghuiwen` -* `WuPengqiang<309554135@qq.com>` -* `WuPengqiang` -* `l<22312935+lam2003@users.noreply.github.com>` -* `xfalcon` -* `ChenGuanghua` -* `ChenGuanghua` -* `LiPeng` -* `LiPeng` -* `yajun18` -* `liulichuan` -* `yapingcat` -* `chenchengbin` -* `ChenHaibo<495810242@qq.com>` -* `ChenHaibo` -* `jasongwq` -* `yinjiaoyuan` -* `PieerePi` -* `JesseXi` -* `PieerePi<40780488+PieerePi@users.noreply.github.com>` -* `ghostsf` -* `xbpeng121<53243357+xbpeng121@users.noreply.github.com>` -* `Johzzy` -* `stone` -* `cfw11<34058899+cfw11@users.noreply.github.com>` -* `Hung-YiChen` -* `long` -* `matthew1838<77285055+matthew1838@users.noreply.github.com>` -* `rise` -* `pyw` -* `MatheusMacabu` -* `Alex.CR` -* `Zhouxiaojun2008<279686030@qq.com>` -* `Zhouxiaojun2008 <31402829+zhouxiaojun2008@users.noreply.github.com>` -* `Pengfei.ma` -* `Pengfei.ma<52305649+mapengfei53@users.noreply.github.com>` -* `ZhangJunqin` -* `ZhangJunqin` -* `AbrarAhmed<13979201+abrar71@users.noreply.github.com>` -* `BoringWednesday<2651933495@qq.com>` -* `liuxiaoliang<37902979+liuxiaoliang8@users.noreply.github.com>` -* `qingfuliao<45161976+qingfuliao@users.noreply.github.com>` -* `along` -* `akanchi` -* `HuachaoMao` -* `James` -* `lvndry` -* `马文武` -* `PurpleGrape` -* `xmedia-systems` -* `MatinZadehDolatabad` -* `zozobreakzou` -* `mingo-wu<57790355+mingo-wu1@users.noreply.github.com>` -* `CommanderRoot` -* `dev-clavis` -* `everything411` -* `faicker` -* `Matthew` -* `simon1tan1<107955289+simon1tan1@users.noreply.github.com>` -* `feng<308276366@qq.com>` -* `wangzhen` -* `yashwardhan-jyani<100014271+yashwardhan-jyani@users.noreply.github.com>` -* `qyt<486179@qq.com>` -* `Kazuo` -* `MarkCao` -* `Mr.Li` -* `Loken` -* `JacobSu` -* `terrencetang2023` -* `jb-alvarado<2212056+jb-alvarado@users.noreply.github.com>` -* `Jay<39650910+w41203208@users.noreply.github.com>` -* `Arjen10<47875127+Arjen10@users.noreply.github.com>` -* `Lukas<89481353+Lukas-Kaufmann@users.noreply.github.com>` -* `VampireAchao` -* `Laurentiu` -* `Bahamut` -* `MarcOlzheim` - diff --git a/trunk/AUTHORS.txt b/trunk/AUTHORS.txt deleted file mode 120000 index 36adef640..000000000 --- a/trunk/AUTHORS.txt +++ /dev/null @@ -1 +0,0 @@ -AUTHORS.md \ No newline at end of file diff --git a/trunk/doc/CHANGELOG.md b/trunk/doc/CHANGELOG.md index d165b6e63..d3c31a9f4 100644 --- a/trunk/doc/CHANGELOG.md +++ b/trunk/doc/CHANGELOG.md @@ -7,7 +7,6 @@ The changelog for SRS. ## SRS 7.0 Changelog -* v7.0, 2025-05-13, Merge [#4289](https://github.com/ossrs/srs/pull/4289): rtmp2rtc: Support HEVC. v7.0.33 (#4289) * v7.0, 2025-04-30, Merge [#4308](https://github.com/ossrs/srs/pull/4308): Fix memory leaks from errors skipping resource release. v7.0.32 (#4308) * v7.0, 2025-04-26, Merge [#4292](https://github.com/ossrs/srs/pull/4309): Support custom deleter for SrsUniquePtr. v7.0.31 (#4309) * v7.0, 2025-03-21, Merge [#4292](https://github.com/ossrs/srs/pull/4292): Typo: "forked" process in log output. v7.0.30 (#4292) diff --git a/trunk/doc/source.flv b/trunk/doc/source.flv deleted file mode 120000 index 32d9ecfc2..000000000 --- a/trunk/doc/source.flv +++ /dev/null @@ -1 +0,0 @@ -source.200kbps.768x320.flv \ No newline at end of file diff --git a/trunk/doc/source.flv b/trunk/doc/source.flv new file mode 100644 index 000000000..32d9ecfc2 --- /dev/null +++ b/trunk/doc/source.flv @@ -0,0 +1 @@ +source.200kbps.768x320.flv \ No newline at end of file diff --git a/trunk/research/api-server/static-dir/favicon.ico b/trunk/research/api-server/static-dir/favicon.ico deleted file mode 120000 index 251568d4d..000000000 --- a/trunk/research/api-server/static-dir/favicon.ico +++ /dev/null @@ -1 +0,0 @@ -../../favicon.ico \ No newline at end of file diff --git a/trunk/research/api-server/static-dir/favicon.ico b/trunk/research/api-server/static-dir/favicon.ico new file mode 100644 index 000000000..251568d4d --- /dev/null +++ b/trunk/research/api-server/static-dir/favicon.ico @@ -0,0 +1 @@ +../../favicon.ico \ No newline at end of file diff --git a/trunk/research/api-server/static-dir/index.html b/trunk/research/api-server/static-dir/index.html deleted file mode 120000 index c90ed45dd..000000000 --- a/trunk/research/api-server/static-dir/index.html +++ /dev/null @@ -1 +0,0 @@ -../../index.html \ No newline at end of file diff --git a/trunk/research/api-server/static-dir/index.html b/trunk/research/api-server/static-dir/index.html new file mode 100644 index 000000000..c90ed45dd --- /dev/null +++ b/trunk/research/api-server/static-dir/index.html @@ -0,0 +1 @@ +../../index.html \ No newline at end of file diff --git a/trunk/research/players/css/bootstrap.min.css b/trunk/research/players/css/bootstrap.min.css index df96c8648..d62114183 100755 --- a/trunk/research/players/css/bootstrap.min.css +++ b/trunk/research/players/css/bootstrap.min.css @@ -6,4 +6,6161 @@ * http://www.apache.org/licenses/LICENSE-2.0 * * Designed and built with all the love in the world by @mdo and @fat. - */.clearfix{*zoom:1}.clearfix:before,.clearfix:after{display:table;line-height:0;content:""}.clearfix:after{clear:both}.hide-text{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.input-block-level{display:block;width:100%;min-height:30px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}article,aside,details,figcaption,figure,footer,header,hgroup,nav,section{display:block}audio,canvas,video{display:inline-block;*display:inline;*zoom:1}audio:not([controls]){display:none}html{font-size:100%;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}a:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}a:hover,a:active{outline:0}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sup{top:-0.5em}sub{bottom:-0.25em}img{width:auto\9;height:auto;max-width:100%;vertical-align:middle;border:0;-ms-interpolation-mode:bicubic}#map_canvas img,.google-maps img{max-width:none}button,input,select,textarea{margin:0;font-size:100%;vertical-align:middle}button,input{*overflow:visible;line-height:normal}button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0}button,html input[type="button"],input[type="reset"],input[type="submit"]{cursor:pointer;-webkit-appearance:button}label,select,button,input[type="button"],input[type="reset"],input[type="submit"],input[type="radio"],input[type="checkbox"]{cursor:pointer}input[type="search"]{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;-webkit-appearance:textfield}input[type="search"]::-webkit-search-decoration,input[type="search"]::-webkit-search-cancel-button{-webkit-appearance:none}textarea{overflow:auto;vertical-align:top}@media print{*{color:#000!important;text-shadow:none!important;background:transparent!important;box-shadow:none!important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100%!important}@page{margin:.5cm}p,h2,h3{orphans:3;widows:3}h2,h3{page-break-after:avoid}}body{margin:0;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:20px;color:#333;background-color:#fff}a{color:#08c;text-decoration:none}a:hover,a:focus{color:#005580;text-decoration:underline}.img-rounded{-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px}.img-polaroid{padding:4px;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.2);-webkit-box-shadow:0 1px 3px rgba(0,0,0,0.1);-moz-box-shadow:0 1px 3px rgba(0,0,0,0.1);box-shadow:0 1px 3px rgba(0,0,0,0.1)}.img-circle{-webkit-border-radius:500px;-moz-border-radius:500px;border-radius:500px}.row{margin-left:-20px;*zoom:1}.row:before,.row:after{display:table;line-height:0;content:""}.row:after{clear:both}[class*="span"]{float:left;min-height:1px;margin-left:20px}.container,.navbar-static-top .container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:940px}.span12{width:940px}.span11{width:860px}.span10{width:780px}.span9{width:700px}.span8{width:620px}.span7{width:540px}.span6{width:460px}.span5{width:380px}.span4{width:300px}.span3{width:220px}.span2{width:140px}.span1{width:60px}.offset12{margin-left:980px}.offset11{margin-left:900px}.offset10{margin-left:820px}.offset9{margin-left:740px}.offset8{margin-left:660px}.offset7{margin-left:580px}.offset6{margin-left:500px}.offset5{margin-left:420px}.offset4{margin-left:340px}.offset3{margin-left:260px}.offset2{margin-left:180px}.offset1{margin-left:100px}.row-fluid{width:100%;*zoom:1}.row-fluid:before,.row-fluid:after{display:table;line-height:0;content:""}.row-fluid:after{clear:both}.row-fluid [class*="span"]{display:block;float:left;width:100%;min-height:30px;margin-left:2.127659574468085%;*margin-left:2.074468085106383%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.row-fluid [class*="span"]:first-child{margin-left:0}.row-fluid .controls-row [class*="span"]+[class*="span"]{margin-left:2.127659574468085%}.row-fluid .span12{width:100%;*width:99.94680851063829%}.row-fluid .span11{width:91.48936170212765%;*width:91.43617021276594%}.row-fluid .span10{width:82.97872340425532%;*width:82.92553191489361%}.row-fluid .span9{width:74.46808510638297%;*width:74.41489361702126%}.row-fluid .span8{width:65.95744680851064%;*width:65.90425531914893%}.row-fluid .span7{width:57.44680851063829%;*width:57.39361702127659%}.row-fluid .span6{width:48.93617021276595%;*width:48.88297872340425%}.row-fluid .span5{width:40.42553191489362%;*width:40.37234042553192%}.row-fluid .span4{width:31.914893617021278%;*width:31.861702127659576%}.row-fluid .span3{width:23.404255319148934%;*width:23.351063829787233%}.row-fluid .span2{width:14.893617021276595%;*width:14.840425531914894%}.row-fluid .span1{width:6.382978723404255%;*width:6.329787234042553%}.row-fluid .offset12{margin-left:104.25531914893617%;*margin-left:104.14893617021275%}.row-fluid .offset12:first-child{margin-left:102.12765957446808%;*margin-left:102.02127659574467%}.row-fluid .offset11{margin-left:95.74468085106382%;*margin-left:95.6382978723404%}.row-fluid .offset11:first-child{margin-left:93.61702127659574%;*margin-left:93.51063829787232%}.row-fluid .offset10{margin-left:87.23404255319149%;*margin-left:87.12765957446807%}.row-fluid .offset10:first-child{margin-left:85.1063829787234%;*margin-left:84.99999999999999%}.row-fluid .offset9{margin-left:78.72340425531914%;*margin-left:78.61702127659572%}.row-fluid .offset9:first-child{margin-left:76.59574468085106%;*margin-left:76.48936170212764%}.row-fluid .offset8{margin-left:70.2127659574468%;*margin-left:70.10638297872339%}.row-fluid .offset8:first-child{margin-left:68.08510638297872%;*margin-left:67.9787234042553%}.row-fluid .offset7{margin-left:61.70212765957446%;*margin-left:61.59574468085106%}.row-fluid .offset7:first-child{margin-left:59.574468085106375%;*margin-left:59.46808510638297%}.row-fluid .offset6{margin-left:53.191489361702125%;*margin-left:53.085106382978715%}.row-fluid .offset6:first-child{margin-left:51.063829787234035%;*margin-left:50.95744680851063%}.row-fluid .offset5{margin-left:44.68085106382979%;*margin-left:44.57446808510638%}.row-fluid .offset5:first-child{margin-left:42.5531914893617%;*margin-left:42.4468085106383%}.row-fluid .offset4{margin-left:36.170212765957444%;*margin-left:36.06382978723405%}.row-fluid .offset4:first-child{margin-left:34.04255319148936%;*margin-left:33.93617021276596%}.row-fluid .offset3{margin-left:27.659574468085104%;*margin-left:27.5531914893617%}.row-fluid .offset3:first-child{margin-left:25.53191489361702%;*margin-left:25.425531914893618%}.row-fluid .offset2{margin-left:19.148936170212764%;*margin-left:19.04255319148936%}.row-fluid .offset2:first-child{margin-left:17.02127659574468%;*margin-left:16.914893617021278%}.row-fluid .offset1{margin-left:10.638297872340425%;*margin-left:10.53191489361702%}.row-fluid .offset1:first-child{margin-left:8.51063829787234%;*margin-left:8.404255319148938%}[class*="span"].hide,.row-fluid [class*="span"].hide{display:none}[class*="span"].pull-right,.row-fluid [class*="span"].pull-right{float:right}.container{margin-right:auto;margin-left:auto;*zoom:1}.container:before,.container:after{display:table;line-height:0;content:""}.container:after{clear:both}.container-fluid{padding-right:20px;padding-left:20px;*zoom:1}.container-fluid:before,.container-fluid:after{display:table;line-height:0;content:""}.container-fluid:after{clear:both}p{margin:0 0 10px}.lead{margin-bottom:20px;font-size:21px;font-weight:200;line-height:30px}small{font-size:85%}strong{font-weight:bold}em{font-style:italic}cite{font-style:normal}.muted{color:#999}a.muted:hover,a.muted:focus{color:#808080}.text-warning{color:#c09853}a.text-warning:hover,a.text-warning:focus{color:#a47e3c}.text-error{color:#b94a48}a.text-error:hover,a.text-error:focus{color:#953b39}.text-info{color:#3a87ad}a.text-info:hover,a.text-info:focus{color:#2d6987}.text-success{color:#468847}a.text-success:hover,a.text-success:focus{color:#356635}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}h1,h2,h3,h4,h5,h6{margin:10px 0;font-family:inherit;font-weight:bold;line-height:20px;color:inherit;text-rendering:optimizelegibility}h1 small,h2 small,h3 small,h4 small,h5 small,h6 small{font-weight:normal;line-height:1;color:#999}h1,h2,h3{line-height:40px}h1{font-size:38.5px}h2{font-size:31.5px}h3{font-size:24.5px}h4{font-size:17.5px}h5{font-size:14px}h6{font-size:11.9px}h1 small{font-size:24.5px}h2 small{font-size:17.5px}h3 small{font-size:14px}h4 small{font-size:14px}.page-header{padding-bottom:9px;margin:20px 0 30px;border-bottom:1px solid #eee}ul,ol{padding:0;margin:0 0 10px 25px}ul ul,ul ol,ol ol,ol ul{margin-bottom:0}li{line-height:20px}ul.unstyled,ol.unstyled{margin-left:0;list-style:none}ul.inline,ol.inline{margin-left:0;list-style:none}ul.inline>li,ol.inline>li{display:inline-block;*display:inline;padding-right:5px;padding-left:5px;*zoom:1}dl{margin-bottom:20px}dt,dd{line-height:20px}dt{font-weight:bold}dd{margin-left:10px}.dl-horizontal{*zoom:1}.dl-horizontal:before,.dl-horizontal:after{display:table;line-height:0;content:""}.dl-horizontal:after{clear:both}.dl-horizontal dt{float:left;width:160px;overflow:hidden;clear:left;text-align:right;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}hr{margin:20px 0;border:0;border-top:1px solid #eee;border-bottom:1px solid #fff}abbr[title],abbr[data-original-title]{cursor:help;border-bottom:1px dotted #999}abbr.initialism{font-size:90%;text-transform:uppercase}blockquote{padding:0 0 0 15px;margin:0 0 20px;border-left:5px solid #eee}blockquote p{margin-bottom:0;font-size:17.5px;font-weight:300;line-height:1.25}blockquote small{display:block;line-height:20px;color:#999}blockquote small:before{content:'\2014 \00A0'}blockquote.pull-right{float:right;padding-right:15px;padding-left:0;border-right:5px solid #eee;border-left:0}blockquote.pull-right p,blockquote.pull-right small{text-align:right}blockquote.pull-right small:before{content:''}blockquote.pull-right small:after{content:'\00A0 \2014'}q:before,q:after,blockquote:before,blockquote:after{content:""}address{display:block;margin-bottom:20px;font-style:normal;line-height:20px}code,pre{padding:0 3px 2px;font-family:Monaco,Menlo,Consolas,"Courier New",monospace;font-size:12px;color:#333;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}code{padding:2px 4px;color:#d14;white-space:nowrap;background-color:#f7f7f9;border:1px solid #e1e1e8}pre{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;line-height:20px;word-break:break-all;word-wrap:break-word;white-space:pre;white-space:pre-wrap;background-color:#f5f5f5;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.15);-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}pre.prettyprint{margin-bottom:20px}pre code{padding:0;color:inherit;white-space:pre;white-space:pre-wrap;background-color:transparent;border:0}.pre-scrollable{max-height:340px;overflow-y:scroll}form{margin:0 0 20px}fieldset{padding:0;margin:0;border:0}legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:21px;line-height:40px;color:#333;border:0;border-bottom:1px solid #e5e5e5}legend small{font-size:15px;color:#999}label,input,button,select,textarea{font-size:14px;font-weight:normal;line-height:20px}input,button,select,textarea{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif}label{display:block;margin-bottom:5px}select,textarea,input[type="text"],input[type="password"],input[type="datetime"],input[type="datetime-local"],input[type="date"],input[type="month"],input[type="time"],input[type="week"],input[type="number"],input[type="email"],input[type="url"],input[type="search"],input[type="tel"],input[type="color"],.uneditable-input{display:inline-block;height:20px;padding:4px 6px;margin-bottom:10px;font-size:14px;line-height:20px;color:#555;vertical-align:middle;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}input,textarea,.uneditable-input{width:206px}textarea{height:auto}textarea,input[type="text"],input[type="password"],input[type="datetime"],input[type="datetime-local"],input[type="date"],input[type="month"],input[type="time"],input[type="week"],input[type="number"],input[type="email"],input[type="url"],input[type="search"],input[type="tel"],input[type="color"],.uneditable-input{background-color:#fff;border:1px solid #ccc;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-webkit-transition:border linear .2s,box-shadow linear .2s;-moz-transition:border linear .2s,box-shadow linear .2s;-o-transition:border linear .2s,box-shadow linear .2s;transition:border linear .2s,box-shadow linear .2s}textarea:focus,input[type="text"]:focus,input[type="password"]:focus,input[type="datetime"]:focus,input[type="datetime-local"]:focus,input[type="date"]:focus,input[type="month"]:focus,input[type="time"]:focus,input[type="week"]:focus,input[type="number"]:focus,input[type="email"]:focus,input[type="url"]:focus,input[type="search"]:focus,input[type="tel"]:focus,input[type="color"]:focus,.uneditable-input:focus{border-color:rgba(82,168,236,0.8);outline:0;outline:thin dotted \9;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(82,168,236,0.6);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(82,168,236,0.6);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(82,168,236,0.6)}input[type="radio"],input[type="checkbox"]{margin:4px 0 0;margin-top:1px \9;*margin-top:0;line-height:normal}input[type="file"],input[type="image"],input[type="submit"],input[type="reset"],input[type="button"],input[type="radio"],input[type="checkbox"]{width:auto}select,input[type="file"]{height:30px;*margin-top:4px;line-height:30px}select{width:220px;background-color:#fff;border:1px solid #ccc}select[multiple],select[size]{height:auto}select:focus,input[type="file"]:focus,input[type="radio"]:focus,input[type="checkbox"]:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.uneditable-input,.uneditable-textarea{color:#999;cursor:not-allowed;background-color:#fcfcfc;border-color:#ccc;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.025);-moz-box-shadow:inset 0 1px 2px rgba(0,0,0,0.025);box-shadow:inset 0 1px 2px rgba(0,0,0,0.025)}.uneditable-input{overflow:hidden;white-space:nowrap}.uneditable-textarea{width:auto;height:auto}input:-moz-placeholder,textarea:-moz-placeholder{color:#999}input:-ms-input-placeholder,textarea:-ms-input-placeholder{color:#999}input::-webkit-input-placeholder,textarea::-webkit-input-placeholder{color:#999}.radio,.checkbox{min-height:20px;padding-left:20px}.radio input[type="radio"],.checkbox input[type="checkbox"]{float:left;margin-left:-20px}.controls>.radio:first-child,.controls>.checkbox:first-child{padding-top:5px}.radio.inline,.checkbox.inline{display:inline-block;padding-top:5px;margin-bottom:0;vertical-align:middle}.radio.inline+.radio.inline,.checkbox.inline+.checkbox.inline{margin-left:10px}.input-mini{width:60px}.input-small{width:90px}.input-medium{width:150px}.input-large{width:210px}.input-xlarge{width:270px}.input-xxlarge{width:530px}input[class*="span"],select[class*="span"],textarea[class*="span"],.uneditable-input[class*="span"],.row-fluid input[class*="span"],.row-fluid select[class*="span"],.row-fluid textarea[class*="span"],.row-fluid .uneditable-input[class*="span"]{float:none;margin-left:0}.input-append input[class*="span"],.input-append .uneditable-input[class*="span"],.input-prepend input[class*="span"],.input-prepend .uneditable-input[class*="span"],.row-fluid input[class*="span"],.row-fluid select[class*="span"],.row-fluid textarea[class*="span"],.row-fluid .uneditable-input[class*="span"],.row-fluid .input-prepend [class*="span"],.row-fluid .input-append [class*="span"]{display:inline-block}input,textarea,.uneditable-input{margin-left:0}.controls-row [class*="span"]+[class*="span"]{margin-left:20px}input.span12,textarea.span12,.uneditable-input.span12{width:926px}input.span11,textarea.span11,.uneditable-input.span11{width:846px}input.span10,textarea.span10,.uneditable-input.span10{width:766px}input.span9,textarea.span9,.uneditable-input.span9{width:686px}input.span8,textarea.span8,.uneditable-input.span8{width:606px}input.span7,textarea.span7,.uneditable-input.span7{width:526px}input.span6,textarea.span6,.uneditable-input.span6{width:446px}input.span5,textarea.span5,.uneditable-input.span5{width:366px}input.span4,textarea.span4,.uneditable-input.span4{width:286px}input.span3,textarea.span3,.uneditable-input.span3{width:206px}input.span2,textarea.span2,.uneditable-input.span2{width:126px}input.span1,textarea.span1,.uneditable-input.span1{width:46px}.controls-row{*zoom:1}.controls-row:before,.controls-row:after{display:table;line-height:0;content:""}.controls-row:after{clear:both}.controls-row [class*="span"],.row-fluid .controls-row [class*="span"]{float:left}.controls-row .checkbox[class*="span"],.controls-row .radio[class*="span"]{padding-top:5px}input[disabled],select[disabled],textarea[disabled],input[readonly],select[readonly],textarea[readonly]{cursor:not-allowed;background-color:#eee}input[type="radio"][disabled],input[type="checkbox"][disabled],input[type="radio"][readonly],input[type="checkbox"][readonly]{background-color:transparent}.control-group.warning .control-label,.control-group.warning .help-block,.control-group.warning .help-inline{color:#c09853}.control-group.warning .checkbox,.control-group.warning .radio,.control-group.warning input,.control-group.warning select,.control-group.warning textarea{color:#c09853}.control-group.warning input,.control-group.warning select,.control-group.warning textarea{border-color:#c09853;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.control-group.warning input:focus,.control-group.warning select:focus,.control-group.warning textarea:focus{border-color:#a47e3c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #dbc59e;-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #dbc59e;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #dbc59e}.control-group.warning .input-prepend .add-on,.control-group.warning .input-append .add-on{color:#c09853;background-color:#fcf8e3;border-color:#c09853}.control-group.error .control-label,.control-group.error .help-block,.control-group.error .help-inline{color:#b94a48}.control-group.error .checkbox,.control-group.error .radio,.control-group.error input,.control-group.error select,.control-group.error textarea{color:#b94a48}.control-group.error input,.control-group.error select,.control-group.error textarea{border-color:#b94a48;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.control-group.error input:focus,.control-group.error select:focus,.control-group.error textarea:focus{border-color:#953b39;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #d59392;-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #d59392;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #d59392}.control-group.error .input-prepend .add-on,.control-group.error .input-append .add-on{color:#b94a48;background-color:#f2dede;border-color:#b94a48}.control-group.success .control-label,.control-group.success .help-block,.control-group.success .help-inline{color:#468847}.control-group.success .checkbox,.control-group.success .radio,.control-group.success input,.control-group.success select,.control-group.success textarea{color:#468847}.control-group.success input,.control-group.success select,.control-group.success textarea{border-color:#468847;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.control-group.success input:focus,.control-group.success select:focus,.control-group.success textarea:focus{border-color:#356635;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7aba7b;-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7aba7b;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7aba7b}.control-group.success .input-prepend .add-on,.control-group.success .input-append .add-on{color:#468847;background-color:#dff0d8;border-color:#468847}.control-group.info .control-label,.control-group.info .help-block,.control-group.info .help-inline{color:#3a87ad}.control-group.info .checkbox,.control-group.info .radio,.control-group.info input,.control-group.info select,.control-group.info textarea{color:#3a87ad}.control-group.info input,.control-group.info select,.control-group.info textarea{border-color:#3a87ad;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.control-group.info input:focus,.control-group.info select:focus,.control-group.info textarea:focus{border-color:#2d6987;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7ab5d3;-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7ab5d3;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7ab5d3}.control-group.info .input-prepend .add-on,.control-group.info .input-append .add-on{color:#3a87ad;background-color:#d9edf7;border-color:#3a87ad}input:focus:invalid,textarea:focus:invalid,select:focus:invalid{color:#b94a48;border-color:#ee5f5b}input:focus:invalid:focus,textarea:focus:invalid:focus,select:focus:invalid:focus{border-color:#e9322d;-webkit-box-shadow:0 0 6px #f8b9b7;-moz-box-shadow:0 0 6px #f8b9b7;box-shadow:0 0 6px #f8b9b7}.form-actions{padding:19px 20px 20px;margin-top:20px;margin-bottom:20px;background-color:#f5f5f5;border-top:1px solid #e5e5e5;*zoom:1}.form-actions:before,.form-actions:after{display:table;line-height:0;content:""}.form-actions:after{clear:both}.help-block,.help-inline{color:#595959}.help-block{display:block;margin-bottom:10px}.help-inline{display:inline-block;*display:inline;padding-left:5px;vertical-align:middle;*zoom:1}.input-append,.input-prepend{display:inline-block;margin-bottom:10px;font-size:0;white-space:nowrap;vertical-align:middle}.input-append input,.input-prepend input,.input-append select,.input-prepend select,.input-append .uneditable-input,.input-prepend .uneditable-input,.input-append .dropdown-menu,.input-prepend .dropdown-menu,.input-append .popover,.input-prepend .popover{font-size:14px}.input-append input,.input-prepend input,.input-append select,.input-prepend select,.input-append .uneditable-input,.input-prepend .uneditable-input{position:relative;margin-bottom:0;*margin-left:0;vertical-align:top;-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0}.input-append input:focus,.input-prepend input:focus,.input-append select:focus,.input-prepend select:focus,.input-append .uneditable-input:focus,.input-prepend .uneditable-input:focus{z-index:2}.input-append .add-on,.input-prepend .add-on{display:inline-block;width:auto;height:20px;min-width:16px;padding:4px 5px;font-size:14px;font-weight:normal;line-height:20px;text-align:center;text-shadow:0 1px 0 #fff;background-color:#eee;border:1px solid #ccc}.input-append .add-on,.input-prepend .add-on,.input-append .btn,.input-prepend .btn,.input-append .btn-group>.dropdown-toggle,.input-prepend .btn-group>.dropdown-toggle{vertical-align:top;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.input-append .active,.input-prepend .active{background-color:#a9dba9;border-color:#46a546}.input-prepend .add-on,.input-prepend .btn{margin-right:-1px}.input-prepend .add-on:first-child,.input-prepend .btn:first-child{-webkit-border-radius:4px 0 0 4px;-moz-border-radius:4px 0 0 4px;border-radius:4px 0 0 4px}.input-append input,.input-append select,.input-append .uneditable-input{-webkit-border-radius:4px 0 0 4px;-moz-border-radius:4px 0 0 4px;border-radius:4px 0 0 4px}.input-append input+.btn-group .btn:last-child,.input-append select+.btn-group .btn:last-child,.input-append .uneditable-input+.btn-group .btn:last-child{-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0}.input-append .add-on,.input-append .btn,.input-append .btn-group{margin-left:-1px}.input-append .add-on:last-child,.input-append .btn:last-child,.input-append .btn-group:last-child>.dropdown-toggle{-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0}.input-prepend.input-append input,.input-prepend.input-append select,.input-prepend.input-append .uneditable-input{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.input-prepend.input-append input+.btn-group .btn,.input-prepend.input-append select+.btn-group .btn,.input-prepend.input-append .uneditable-input+.btn-group .btn{-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0}.input-prepend.input-append .add-on:first-child,.input-prepend.input-append .btn:first-child{margin-right:-1px;-webkit-border-radius:4px 0 0 4px;-moz-border-radius:4px 0 0 4px;border-radius:4px 0 0 4px}.input-prepend.input-append .add-on:last-child,.input-prepend.input-append .btn:last-child{margin-left:-1px;-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0}.input-prepend.input-append .btn-group:first-child{margin-left:0}input.search-query{padding-right:14px;padding-right:4px \9;padding-left:14px;padding-left:4px \9;margin-bottom:0;-webkit-border-radius:15px;-moz-border-radius:15px;border-radius:15px}.form-search .input-append .search-query,.form-search .input-prepend .search-query{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.form-search .input-append .search-query{-webkit-border-radius:14px 0 0 14px;-moz-border-radius:14px 0 0 14px;border-radius:14px 0 0 14px}.form-search .input-append .btn{-webkit-border-radius:0 14px 14px 0;-moz-border-radius:0 14px 14px 0;border-radius:0 14px 14px 0}.form-search .input-prepend .search-query{-webkit-border-radius:0 14px 14px 0;-moz-border-radius:0 14px 14px 0;border-radius:0 14px 14px 0}.form-search .input-prepend .btn{-webkit-border-radius:14px 0 0 14px;-moz-border-radius:14px 0 0 14px;border-radius:14px 0 0 14px}.form-search input,.form-inline input,.form-horizontal input,.form-search textarea,.form-inline textarea,.form-horizontal textarea,.form-search select,.form-inline select,.form-horizontal select,.form-search .help-inline,.form-inline .help-inline,.form-horizontal .help-inline,.form-search .uneditable-input,.form-inline .uneditable-input,.form-horizontal .uneditable-input,.form-search .input-prepend,.form-inline .input-prepend,.form-horizontal .input-prepend,.form-search .input-append,.form-inline .input-append,.form-horizontal .input-append{display:inline-block;*display:inline;margin-bottom:0;vertical-align:middle;*zoom:1}.form-search .hide,.form-inline .hide,.form-horizontal .hide{display:none}.form-search label,.form-inline label,.form-search .btn-group,.form-inline .btn-group{display:inline-block}.form-search .input-append,.form-inline .input-append,.form-search .input-prepend,.form-inline .input-prepend{margin-bottom:0}.form-search .radio,.form-search .checkbox,.form-inline .radio,.form-inline .checkbox{padding-left:0;margin-bottom:0;vertical-align:middle}.form-search .radio input[type="radio"],.form-search .checkbox input[type="checkbox"],.form-inline .radio input[type="radio"],.form-inline .checkbox input[type="checkbox"]{float:left;margin-right:3px;margin-left:0}.control-group{margin-bottom:10px}legend+.control-group{margin-top:20px;-webkit-margin-top-collapse:separate}.form-horizontal .control-group{margin-bottom:20px;*zoom:1}.form-horizontal .control-group:before,.form-horizontal .control-group:after{display:table;line-height:0;content:""}.form-horizontal .control-group:after{clear:both}.form-horizontal .control-label{float:left;width:160px;padding-top:5px;text-align:right}.form-horizontal .controls{*display:inline-block;*padding-left:20px;margin-left:180px;*margin-left:0}.form-horizontal .controls:first-child{*padding-left:180px}.form-horizontal .help-block{margin-bottom:0}.form-horizontal input+.help-block,.form-horizontal select+.help-block,.form-horizontal textarea+.help-block,.form-horizontal .uneditable-input+.help-block,.form-horizontal .input-prepend+.help-block,.form-horizontal .input-append+.help-block{margin-top:10px}.form-horizontal .form-actions{padding-left:180px}table{max-width:100%;background-color:transparent;border-collapse:collapse;border-spacing:0}.table{width:100%;margin-bottom:20px}.table th,.table td{padding:8px;line-height:20px;text-align:left;vertical-align:top;border-top:1px solid #ddd}.table th{font-weight:bold}.table thead th{vertical-align:bottom}.table caption+thead tr:first-child th,.table caption+thead tr:first-child td,.table colgroup+thead tr:first-child th,.table colgroup+thead tr:first-child td,.table thead:first-child tr:first-child th,.table thead:first-child tr:first-child td{border-top:0}.table tbody+tbody{border-top:2px solid #ddd}.table .table{background-color:#fff}.table-condensed th,.table-condensed td{padding:4px 5px}.table-bordered{border:1px solid #ddd;border-collapse:separate;*border-collapse:collapse;border-left:0;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.table-bordered th,.table-bordered td{border-left:1px solid #ddd}.table-bordered caption+thead tr:first-child th,.table-bordered caption+tbody tr:first-child th,.table-bordered caption+tbody tr:first-child td,.table-bordered colgroup+thead tr:first-child th,.table-bordered colgroup+tbody tr:first-child th,.table-bordered colgroup+tbody tr:first-child td,.table-bordered thead:first-child tr:first-child th,.table-bordered tbody:first-child tr:first-child th,.table-bordered tbody:first-child tr:first-child td{border-top:0}.table-bordered thead:first-child tr:first-child>th:first-child,.table-bordered tbody:first-child tr:first-child>td:first-child,.table-bordered tbody:first-child tr:first-child>th:first-child{-webkit-border-top-left-radius:4px;border-top-left-radius:4px;-moz-border-radius-topleft:4px}.table-bordered thead:first-child tr:first-child>th:last-child,.table-bordered tbody:first-child tr:first-child>td:last-child,.table-bordered tbody:first-child tr:first-child>th:last-child{-webkit-border-top-right-radius:4px;border-top-right-radius:4px;-moz-border-radius-topright:4px}.table-bordered thead:last-child tr:last-child>th:first-child,.table-bordered tbody:last-child tr:last-child>td:first-child,.table-bordered tbody:last-child tr:last-child>th:first-child,.table-bordered tfoot:last-child tr:last-child>td:first-child,.table-bordered tfoot:last-child tr:last-child>th:first-child{-webkit-border-bottom-left-radius:4px;border-bottom-left-radius:4px;-moz-border-radius-bottomleft:4px}.table-bordered thead:last-child tr:last-child>th:last-child,.table-bordered tbody:last-child tr:last-child>td:last-child,.table-bordered tbody:last-child tr:last-child>th:last-child,.table-bordered tfoot:last-child tr:last-child>td:last-child,.table-bordered tfoot:last-child tr:last-child>th:last-child{-webkit-border-bottom-right-radius:4px;border-bottom-right-radius:4px;-moz-border-radius-bottomright:4px}.table-bordered tfoot+tbody:last-child tr:last-child td:first-child{-webkit-border-bottom-left-radius:0;border-bottom-left-radius:0;-moz-border-radius-bottomleft:0}.table-bordered tfoot+tbody:last-child tr:last-child td:last-child{-webkit-border-bottom-right-radius:0;border-bottom-right-radius:0;-moz-border-radius-bottomright:0}.table-bordered caption+thead tr:first-child th:first-child,.table-bordered caption+tbody tr:first-child td:first-child,.table-bordered colgroup+thead tr:first-child th:first-child,.table-bordered colgroup+tbody tr:first-child td:first-child{-webkit-border-top-left-radius:4px;border-top-left-radius:4px;-moz-border-radius-topleft:4px}.table-bordered caption+thead tr:first-child th:last-child,.table-bordered caption+tbody tr:first-child td:last-child,.table-bordered colgroup+thead tr:first-child th:last-child,.table-bordered colgroup+tbody tr:first-child td:last-child{-webkit-border-top-right-radius:4px;border-top-right-radius:4px;-moz-border-radius-topright:4px}.table-striped tbody>tr:nth-child(odd)>td,.table-striped tbody>tr:nth-child(odd)>th{background-color:#f9f9f9}.table-hover tbody tr:hover>td,.table-hover tbody tr:hover>th{background-color:#f5f5f5}table td[class*="span"],table th[class*="span"],.row-fluid table td[class*="span"],.row-fluid table th[class*="span"]{display:table-cell;float:none;margin-left:0}.table td.span1,.table th.span1{float:none;width:44px;margin-left:0}.table td.span2,.table th.span2{float:none;width:124px;margin-left:0}.table td.span3,.table th.span3{float:none;width:204px;margin-left:0}.table td.span4,.table th.span4{float:none;width:284px;margin-left:0}.table td.span5,.table th.span5{float:none;width:364px;margin-left:0}.table td.span6,.table th.span6{float:none;width:444px;margin-left:0}.table td.span7,.table th.span7{float:none;width:524px;margin-left:0}.table td.span8,.table th.span8{float:none;width:604px;margin-left:0}.table td.span9,.table th.span9{float:none;width:684px;margin-left:0}.table td.span10,.table th.span10{float:none;width:764px;margin-left:0}.table td.span11,.table th.span11{float:none;width:844px;margin-left:0}.table td.span12,.table th.span12{float:none;width:924px;margin-left:0}.table tbody tr.success>td{background-color:#dff0d8}.table tbody tr.error>td{background-color:#f2dede}.table tbody tr.warning>td{background-color:#fcf8e3}.table tbody tr.info>td{background-color:#d9edf7}.table-hover tbody tr.success:hover>td{background-color:#d0e9c6}.table-hover tbody tr.error:hover>td{background-color:#ebcccc}.table-hover tbody tr.warning:hover>td{background-color:#faf2cc}.table-hover tbody tr.info:hover>td{background-color:#c4e3f3}[class^="icon-"],[class*=" icon-"]{display:inline-block;width:14px;height:14px;margin-top:1px;*margin-right:.3em;line-height:14px;vertical-align:text-top;background-image:url("../img/glyphicons-halflings.png");background-position:14px 14px;background-repeat:no-repeat}.icon-white,.nav-pills>.active>a>[class^="icon-"],.nav-pills>.active>a>[class*=" icon-"],.nav-list>.active>a>[class^="icon-"],.nav-list>.active>a>[class*=" icon-"],.navbar-inverse .nav>.active>a>[class^="icon-"],.navbar-inverse .nav>.active>a>[class*=" icon-"],.dropdown-menu>li>a:hover>[class^="icon-"],.dropdown-menu>li>a:focus>[class^="icon-"],.dropdown-menu>li>a:hover>[class*=" icon-"],.dropdown-menu>li>a:focus>[class*=" icon-"],.dropdown-menu>.active>a>[class^="icon-"],.dropdown-menu>.active>a>[class*=" icon-"],.dropdown-submenu:hover>a>[class^="icon-"],.dropdown-submenu:focus>a>[class^="icon-"],.dropdown-submenu:hover>a>[class*=" icon-"],.dropdown-submenu:focus>a>[class*=" icon-"]{background-image:url("../img/glyphicons-halflings-white.png")}.icon-glass{background-position:0 0}.icon-music{background-position:-24px 0}.icon-search{background-position:-48px 0}.icon-envelope{background-position:-72px 0}.icon-heart{background-position:-96px 0}.icon-star{background-position:-120px 0}.icon-star-empty{background-position:-144px 0}.icon-user{background-position:-168px 0}.icon-film{background-position:-192px 0}.icon-th-large{background-position:-216px 0}.icon-th{background-position:-240px 0}.icon-th-list{background-position:-264px 0}.icon-ok{background-position:-288px 0}.icon-remove{background-position:-312px 0}.icon-zoom-in{background-position:-336px 0}.icon-zoom-out{background-position:-360px 0}.icon-off{background-position:-384px 0}.icon-signal{background-position:-408px 0}.icon-cog{background-position:-432px 0}.icon-trash{background-position:-456px 0}.icon-home{background-position:0 -24px}.icon-file{background-position:-24px -24px}.icon-time{background-position:-48px -24px}.icon-road{background-position:-72px -24px}.icon-download-alt{background-position:-96px -24px}.icon-download{background-position:-120px -24px}.icon-upload{background-position:-144px -24px}.icon-inbox{background-position:-168px -24px}.icon-play-circle{background-position:-192px -24px}.icon-repeat{background-position:-216px -24px}.icon-refresh{background-position:-240px -24px}.icon-list-alt{background-position:-264px -24px}.icon-lock{background-position:-287px -24px}.icon-flag{background-position:-312px -24px}.icon-headphones{background-position:-336px -24px}.icon-volume-off{background-position:-360px -24px}.icon-volume-down{background-position:-384px -24px}.icon-volume-up{background-position:-408px -24px}.icon-qrcode{background-position:-432px -24px}.icon-barcode{background-position:-456px -24px}.icon-tag{background-position:0 -48px}.icon-tags{background-position:-25px -48px}.icon-book{background-position:-48px -48px}.icon-bookmark{background-position:-72px -48px}.icon-print{background-position:-96px -48px}.icon-camera{background-position:-120px -48px}.icon-font{background-position:-144px -48px}.icon-bold{background-position:-167px -48px}.icon-italic{background-position:-192px -48px}.icon-text-height{background-position:-216px -48px}.icon-text-width{background-position:-240px -48px}.icon-align-left{background-position:-264px -48px}.icon-align-center{background-position:-288px -48px}.icon-align-right{background-position:-312px -48px}.icon-align-justify{background-position:-336px -48px}.icon-list{background-position:-360px -48px}.icon-indent-left{background-position:-384px -48px}.icon-indent-right{background-position:-408px -48px}.icon-facetime-video{background-position:-432px -48px}.icon-picture{background-position:-456px -48px}.icon-pencil{background-position:0 -72px}.icon-map-marker{background-position:-24px -72px}.icon-adjust{background-position:-48px -72px}.icon-tint{background-position:-72px -72px}.icon-edit{background-position:-96px -72px}.icon-share{background-position:-120px -72px}.icon-check{background-position:-144px -72px}.icon-move{background-position:-168px -72px}.icon-step-backward{background-position:-192px -72px}.icon-fast-backward{background-position:-216px -72px}.icon-backward{background-position:-240px -72px}.icon-play{background-position:-264px -72px}.icon-pause{background-position:-288px -72px}.icon-stop{background-position:-312px -72px}.icon-forward{background-position:-336px -72px}.icon-fast-forward{background-position:-360px -72px}.icon-step-forward{background-position:-384px -72px}.icon-eject{background-position:-408px -72px}.icon-chevron-left{background-position:-432px -72px}.icon-chevron-right{background-position:-456px -72px}.icon-plus-sign{background-position:0 -96px}.icon-minus-sign{background-position:-24px -96px}.icon-remove-sign{background-position:-48px -96px}.icon-ok-sign{background-position:-72px -96px}.icon-question-sign{background-position:-96px -96px}.icon-info-sign{background-position:-120px -96px}.icon-screenshot{background-position:-144px -96px}.icon-remove-circle{background-position:-168px -96px}.icon-ok-circle{background-position:-192px -96px}.icon-ban-circle{background-position:-216px -96px}.icon-arrow-left{background-position:-240px -96px}.icon-arrow-right{background-position:-264px -96px}.icon-arrow-up{background-position:-289px -96px}.icon-arrow-down{background-position:-312px -96px}.icon-share-alt{background-position:-336px -96px}.icon-resize-full{background-position:-360px -96px}.icon-resize-small{background-position:-384px -96px}.icon-plus{background-position:-408px -96px}.icon-minus{background-position:-433px -96px}.icon-asterisk{background-position:-456px -96px}.icon-exclamation-sign{background-position:0 -120px}.icon-gift{background-position:-24px -120px}.icon-leaf{background-position:-48px -120px}.icon-fire{background-position:-72px -120px}.icon-eye-open{background-position:-96px -120px}.icon-eye-close{background-position:-120px -120px}.icon-warning-sign{background-position:-144px -120px}.icon-plane{background-position:-168px -120px}.icon-calendar{background-position:-192px -120px}.icon-random{width:16px;background-position:-216px -120px}.icon-comment{background-position:-240px -120px}.icon-magnet{background-position:-264px -120px}.icon-chevron-up{background-position:-288px -120px}.icon-chevron-down{background-position:-313px -119px}.icon-retweet{background-position:-336px -120px}.icon-shopping-cart{background-position:-360px -120px}.icon-folder-close{width:16px;background-position:-384px -120px}.icon-folder-open{width:16px;background-position:-408px -120px}.icon-resize-vertical{background-position:-432px -119px}.icon-resize-horizontal{background-position:-456px -118px}.icon-hdd{background-position:0 -144px}.icon-bullhorn{background-position:-24px -144px}.icon-bell{background-position:-48px -144px}.icon-certificate{background-position:-72px -144px}.icon-thumbs-up{background-position:-96px -144px}.icon-thumbs-down{background-position:-120px -144px}.icon-hand-right{background-position:-144px -144px}.icon-hand-left{background-position:-168px -144px}.icon-hand-up{background-position:-192px -144px}.icon-hand-down{background-position:-216px -144px}.icon-circle-arrow-right{background-position:-240px -144px}.icon-circle-arrow-left{background-position:-264px -144px}.icon-circle-arrow-up{background-position:-288px -144px}.icon-circle-arrow-down{background-position:-312px -144px}.icon-globe{background-position:-336px -144px}.icon-wrench{background-position:-360px -144px}.icon-tasks{background-position:-384px -144px}.icon-filter{background-position:-408px -144px}.icon-briefcase{background-position:-432px -144px}.icon-fullscreen{background-position:-456px -144px}.dropup,.dropdown{position:relative}.dropdown-toggle{*margin-bottom:-3px}.dropdown-toggle:active,.open .dropdown-toggle{outline:0}.caret{display:inline-block;width:0;height:0;vertical-align:top;border-top:4px solid #000;border-right:4px solid transparent;border-left:4px solid transparent;content:""}.dropdown .caret{margin-top:8px;margin-left:2px}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:160px;padding:5px 0;margin:2px 0 0;list-style:none;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.2);*border-right-width:2px;*border-bottom-width:2px;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,0.2);-moz-box-shadow:0 5px 10px rgba(0,0,0,0.2);box-shadow:0 5px 10px rgba(0,0,0,0.2);-webkit-background-clip:padding-box;-moz-background-clip:padding;background-clip:padding-box}.dropdown-menu.pull-right{right:0;left:auto}.dropdown-menu .divider{*width:100%;height:1px;margin:9px 1px;*margin:-5px 0 5px;overflow:hidden;background-color:#e5e5e5;border-bottom:1px solid #fff}.dropdown-menu>li>a{display:block;padding:3px 20px;clear:both;font-weight:normal;line-height:20px;color:#333;white-space:nowrap}.dropdown-menu>li>a:hover,.dropdown-menu>li>a:focus,.dropdown-submenu:hover>a,.dropdown-submenu:focus>a{color:#fff;text-decoration:none;background-color:#0081c2;background-image:-moz-linear-gradient(top,#08c,#0077b3);background-image:-webkit-gradient(linear,0 0,0 100%,from(#08c),to(#0077b3));background-image:-webkit-linear-gradient(top,#08c,#0077b3);background-image:-o-linear-gradient(top,#08c,#0077b3);background-image:linear-gradient(to bottom,#08c,#0077b3);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc',endColorstr='#ff0077b3',GradientType=0)}.dropdown-menu>.active>a,.dropdown-menu>.active>a:hover,.dropdown-menu>.active>a:focus{color:#fff;text-decoration:none;background-color:#0081c2;background-image:-moz-linear-gradient(top,#08c,#0077b3);background-image:-webkit-gradient(linear,0 0,0 100%,from(#08c),to(#0077b3));background-image:-webkit-linear-gradient(top,#08c,#0077b3);background-image:-o-linear-gradient(top,#08c,#0077b3);background-image:linear-gradient(to bottom,#08c,#0077b3);background-repeat:repeat-x;outline:0;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc',endColorstr='#ff0077b3',GradientType=0)}.dropdown-menu>.disabled>a,.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{color:#999}.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{text-decoration:none;cursor:default;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.open{*z-index:1000}.open>.dropdown-menu{display:block}.dropdown-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:990}.pull-right>.dropdown-menu{right:0;left:auto}.dropup .caret,.navbar-fixed-bottom .dropdown .caret{border-top:0;border-bottom:4px solid #000;content:""}.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:1px}.dropdown-submenu{position:relative}.dropdown-submenu>.dropdown-menu{top:0;left:100%;margin-top:-6px;margin-left:-1px;-webkit-border-radius:0 6px 6px 6px;-moz-border-radius:0 6px 6px 6px;border-radius:0 6px 6px 6px}.dropdown-submenu:hover>.dropdown-menu{display:block}.dropup .dropdown-submenu>.dropdown-menu{top:auto;bottom:0;margin-top:0;margin-bottom:-2px;-webkit-border-radius:5px 5px 5px 0;-moz-border-radius:5px 5px 5px 0;border-radius:5px 5px 5px 0}.dropdown-submenu>a:after{display:block;float:right;width:0;height:0;margin-top:5px;margin-right:-10px;border-color:transparent;border-left-color:#ccc;border-style:solid;border-width:5px 0 5px 5px;content:" "}.dropdown-submenu:hover>a:after{border-left-color:#fff}.dropdown-submenu.pull-left{float:none}.dropdown-submenu.pull-left>.dropdown-menu{left:-100%;margin-left:10px;-webkit-border-radius:6px 0 6px 6px;-moz-border-radius:6px 0 6px 6px;border-radius:6px 0 6px 6px}.dropdown .dropdown-menu .nav-header{padding-right:20px;padding-left:20px}.typeahead{z-index:1051;margin-top:2px;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #e3e3e3;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.05);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.05);box-shadow:inset 0 1px 1px rgba(0,0,0,0.05)}.well blockquote{border-color:#ddd;border-color:rgba(0,0,0,0.15)}.well-large{padding:24px;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px}.well-small{padding:9px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.fade{opacity:0;-webkit-transition:opacity .15s linear;-moz-transition:opacity .15s linear;-o-transition:opacity .15s linear;transition:opacity .15s linear}.fade.in{opacity:1}.collapse{position:relative;height:0;overflow:hidden;-webkit-transition:height .35s ease;-moz-transition:height .35s ease;-o-transition:height .35s ease;transition:height .35s ease}.collapse.in{height:auto}.close{float:right;font-size:20px;font-weight:bold;line-height:20px;color:#000;text-shadow:0 1px 0 #fff;opacity:.2;filter:alpha(opacity=20)}.close:hover,.close:focus{color:#000;text-decoration:none;cursor:pointer;opacity:.4;filter:alpha(opacity=40)}button.close{padding:0;cursor:pointer;background:transparent;border:0;-webkit-appearance:none}.btn{display:inline-block;*display:inline;padding:4px 12px;margin-bottom:0;*margin-left:.3em;font-size:14px;line-height:20px;color:#333;text-align:center;text-shadow:0 1px 1px rgba(255,255,255,0.75);vertical-align:middle;cursor:pointer;background-color:#f5f5f5;*background-color:#e6e6e6;background-image:-moz-linear-gradient(top,#fff,#e6e6e6);background-image:-webkit-gradient(linear,0 0,0 100%,from(#fff),to(#e6e6e6));background-image:-webkit-linear-gradient(top,#fff,#e6e6e6);background-image:-o-linear-gradient(top,#fff,#e6e6e6);background-image:linear-gradient(to bottom,#fff,#e6e6e6);background-repeat:repeat-x;border:1px solid #ccc;*border:0;border-color:#e6e6e6 #e6e6e6 #bfbfbf;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);border-bottom-color:#b3b3b3;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff',endColorstr='#ffe6e6e6',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);*zoom:1;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05)}.btn:hover,.btn:focus,.btn:active,.btn.active,.btn.disabled,.btn[disabled]{color:#333;background-color:#e6e6e6;*background-color:#d9d9d9}.btn:active,.btn.active{background-color:#ccc \9}.btn:first-child{*margin-left:0}.btn:hover,.btn:focus{color:#333;text-decoration:none;background-position:0 -15px;-webkit-transition:background-position .1s linear;-moz-transition:background-position .1s linear;-o-transition:background-position .1s linear;transition:background-position .1s linear}.btn:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn.active,.btn:active{background-image:none;outline:0;-webkit-box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05)}.btn.disabled,.btn[disabled]{cursor:default;background-image:none;opacity:.65;filter:alpha(opacity=65);-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}.btn-large{padding:11px 19px;font-size:17.5px;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px}.btn-large [class^="icon-"],.btn-large [class*=" icon-"]{margin-top:4px}.btn-small{padding:2px 10px;font-size:11.9px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.btn-small [class^="icon-"],.btn-small [class*=" icon-"]{margin-top:0}.btn-mini [class^="icon-"],.btn-mini [class*=" icon-"]{margin-top:-1px}.btn-mini{padding:0 6px;font-size:10.5px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.btn-block{display:block;width:100%;padding-right:0;padding-left:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.btn-block+.btn-block{margin-top:5px}input[type="submit"].btn-block,input[type="reset"].btn-block,input[type="button"].btn-block{width:100%}.btn-primary.active,.btn-warning.active,.btn-danger.active,.btn-success.active,.btn-info.active,.btn-inverse.active{color:rgba(255,255,255,0.75)}.btn-primary{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#006dcc;*background-color:#04c;background-image:-moz-linear-gradient(top,#08c,#04c);background-image:-webkit-gradient(linear,0 0,0 100%,from(#08c),to(#04c));background-image:-webkit-linear-gradient(top,#08c,#04c);background-image:-o-linear-gradient(top,#08c,#04c);background-image:linear-gradient(to bottom,#08c,#04c);background-repeat:repeat-x;border-color:#04c #04c #002a80;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc',endColorstr='#ff0044cc',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-primary:hover,.btn-primary:focus,.btn-primary:active,.btn-primary.active,.btn-primary.disabled,.btn-primary[disabled]{color:#fff;background-color:#04c;*background-color:#003bb3}.btn-primary:active,.btn-primary.active{background-color:#039 \9}.btn-warning{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#faa732;*background-color:#f89406;background-image:-moz-linear-gradient(top,#fbb450,#f89406);background-image:-webkit-gradient(linear,0 0,0 100%,from(#fbb450),to(#f89406));background-image:-webkit-linear-gradient(top,#fbb450,#f89406);background-image:-o-linear-gradient(top,#fbb450,#f89406);background-image:linear-gradient(to bottom,#fbb450,#f89406);background-repeat:repeat-x;border-color:#f89406 #f89406 #ad6704;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450',endColorstr='#fff89406',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-warning:hover,.btn-warning:focus,.btn-warning:active,.btn-warning.active,.btn-warning.disabled,.btn-warning[disabled]{color:#fff;background-color:#f89406;*background-color:#df8505}.btn-warning:active,.btn-warning.active{background-color:#c67605 \9}.btn-danger{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#da4f49;*background-color:#bd362f;background-image:-moz-linear-gradient(top,#ee5f5b,#bd362f);background-image:-webkit-gradient(linear,0 0,0 100%,from(#ee5f5b),to(#bd362f));background-image:-webkit-linear-gradient(top,#ee5f5b,#bd362f);background-image:-o-linear-gradient(top,#ee5f5b,#bd362f);background-image:linear-gradient(to bottom,#ee5f5b,#bd362f);background-repeat:repeat-x;border-color:#bd362f #bd362f #802420;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b',endColorstr='#ffbd362f',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-danger:hover,.btn-danger:focus,.btn-danger:active,.btn-danger.active,.btn-danger.disabled,.btn-danger[disabled]{color:#fff;background-color:#bd362f;*background-color:#a9302a}.btn-danger:active,.btn-danger.active{background-color:#942a25 \9}.btn-success{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#5bb75b;*background-color:#51a351;background-image:-moz-linear-gradient(top,#62c462,#51a351);background-image:-webkit-gradient(linear,0 0,0 100%,from(#62c462),to(#51a351));background-image:-webkit-linear-gradient(top,#62c462,#51a351);background-image:-o-linear-gradient(top,#62c462,#51a351);background-image:linear-gradient(to bottom,#62c462,#51a351);background-repeat:repeat-x;border-color:#51a351 #51a351 #387038;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462',endColorstr='#ff51a351',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-success:hover,.btn-success:focus,.btn-success:active,.btn-success.active,.btn-success.disabled,.btn-success[disabled]{color:#fff;background-color:#51a351;*background-color:#499249}.btn-success:active,.btn-success.active{background-color:#408140 \9}.btn-info{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#49afcd;*background-color:#2f96b4;background-image:-moz-linear-gradient(top,#5bc0de,#2f96b4);background-image:-webkit-gradient(linear,0 0,0 100%,from(#5bc0de),to(#2f96b4));background-image:-webkit-linear-gradient(top,#5bc0de,#2f96b4);background-image:-o-linear-gradient(top,#5bc0de,#2f96b4);background-image:linear-gradient(to bottom,#5bc0de,#2f96b4);background-repeat:repeat-x;border-color:#2f96b4 #2f96b4 #1f6377;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de',endColorstr='#ff2f96b4',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-info:hover,.btn-info:focus,.btn-info:active,.btn-info.active,.btn-info.disabled,.btn-info[disabled]{color:#fff;background-color:#2f96b4;*background-color:#2a85a0}.btn-info:active,.btn-info.active{background-color:#24748c \9}.btn-inverse{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#363636;*background-color:#222;background-image:-moz-linear-gradient(top,#444,#222);background-image:-webkit-gradient(linear,0 0,0 100%,from(#444),to(#222));background-image:-webkit-linear-gradient(top,#444,#222);background-image:-o-linear-gradient(top,#444,#222);background-image:linear-gradient(to bottom,#444,#222);background-repeat:repeat-x;border-color:#222 #222 #000;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff444444',endColorstr='#ff222222',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-inverse:hover,.btn-inverse:focus,.btn-inverse:active,.btn-inverse.active,.btn-inverse.disabled,.btn-inverse[disabled]{color:#fff;background-color:#222;*background-color:#151515}.btn-inverse:active,.btn-inverse.active{background-color:#080808 \9}button.btn,input[type="submit"].btn{*padding-top:3px;*padding-bottom:3px}button.btn::-moz-focus-inner,input[type="submit"].btn::-moz-focus-inner{padding:0;border:0}button.btn.btn-large,input[type="submit"].btn.btn-large{*padding-top:7px;*padding-bottom:7px}button.btn.btn-small,input[type="submit"].btn.btn-small{*padding-top:3px;*padding-bottom:3px}button.btn.btn-mini,input[type="submit"].btn.btn-mini{*padding-top:1px;*padding-bottom:1px}.btn-link,.btn-link:active,.btn-link[disabled]{background-color:transparent;background-image:none;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}.btn-link{color:#08c;cursor:pointer;border-color:transparent;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.btn-link:hover,.btn-link:focus{color:#005580;text-decoration:underline;background-color:transparent}.btn-link[disabled]:hover,.btn-link[disabled]:focus{color:#333;text-decoration:none}.btn-group{position:relative;display:inline-block;*display:inline;*margin-left:.3em;font-size:0;white-space:nowrap;vertical-align:middle;*zoom:1}.btn-group:first-child{*margin-left:0}.btn-group+.btn-group{margin-left:5px}.btn-toolbar{margin-top:10px;margin-bottom:10px;font-size:0}.btn-toolbar>.btn+.btn,.btn-toolbar>.btn-group+.btn,.btn-toolbar>.btn+.btn-group{margin-left:5px}.btn-group>.btn{position:relative;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.btn-group>.btn+.btn{margin-left:-1px}.btn-group>.btn,.btn-group>.dropdown-menu,.btn-group>.popover{font-size:14px}.btn-group>.btn-mini{font-size:10.5px}.btn-group>.btn-small{font-size:11.9px}.btn-group>.btn-large{font-size:17.5px}.btn-group>.btn:first-child{margin-left:0;-webkit-border-bottom-left-radius:4px;border-bottom-left-radius:4px;-webkit-border-top-left-radius:4px;border-top-left-radius:4px;-moz-border-radius-bottomleft:4px;-moz-border-radius-topleft:4px}.btn-group>.btn:last-child,.btn-group>.dropdown-toggle{-webkit-border-top-right-radius:4px;border-top-right-radius:4px;-webkit-border-bottom-right-radius:4px;border-bottom-right-radius:4px;-moz-border-radius-topright:4px;-moz-border-radius-bottomright:4px}.btn-group>.btn.large:first-child{margin-left:0;-webkit-border-bottom-left-radius:6px;border-bottom-left-radius:6px;-webkit-border-top-left-radius:6px;border-top-left-radius:6px;-moz-border-radius-bottomleft:6px;-moz-border-radius-topleft:6px}.btn-group>.btn.large:last-child,.btn-group>.large.dropdown-toggle{-webkit-border-top-right-radius:6px;border-top-right-radius:6px;-webkit-border-bottom-right-radius:6px;border-bottom-right-radius:6px;-moz-border-radius-topright:6px;-moz-border-radius-bottomright:6px}.btn-group>.btn:hover,.btn-group>.btn:focus,.btn-group>.btn:active,.btn-group>.btn.active{z-index:2}.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0}.btn-group>.btn+.dropdown-toggle{*padding-top:5px;padding-right:8px;*padding-bottom:5px;padding-left:8px;-webkit-box-shadow:inset 1px 0 0 rgba(255,255,255,0.125),inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:inset 1px 0 0 rgba(255,255,255,0.125),inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 1px 0 0 rgba(255,255,255,0.125),inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05)}.btn-group>.btn-mini+.dropdown-toggle{*padding-top:2px;padding-right:5px;*padding-bottom:2px;padding-left:5px}.btn-group>.btn-small+.dropdown-toggle{*padding-top:5px;*padding-bottom:4px}.btn-group>.btn-large+.dropdown-toggle{*padding-top:7px;padding-right:12px;*padding-bottom:7px;padding-left:12px}.btn-group.open .dropdown-toggle{background-image:none;-webkit-box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05)}.btn-group.open .btn.dropdown-toggle{background-color:#e6e6e6}.btn-group.open .btn-primary.dropdown-toggle{background-color:#04c}.btn-group.open .btn-warning.dropdown-toggle{background-color:#f89406}.btn-group.open .btn-danger.dropdown-toggle{background-color:#bd362f}.btn-group.open .btn-success.dropdown-toggle{background-color:#51a351}.btn-group.open .btn-info.dropdown-toggle{background-color:#2f96b4}.btn-group.open .btn-inverse.dropdown-toggle{background-color:#222}.btn .caret{margin-top:8px;margin-left:0}.btn-large .caret{margin-top:6px}.btn-large .caret{border-top-width:5px;border-right-width:5px;border-left-width:5px}.btn-mini .caret,.btn-small .caret{margin-top:8px}.dropup .btn-large .caret{border-bottom-width:5px}.btn-primary .caret,.btn-warning .caret,.btn-danger .caret,.btn-info .caret,.btn-success .caret,.btn-inverse .caret{border-top-color:#fff;border-bottom-color:#fff}.btn-group-vertical{display:inline-block;*display:inline;*zoom:1}.btn-group-vertical>.btn{display:block;float:none;max-width:100%;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.btn-group-vertical>.btn+.btn{margin-top:-1px;margin-left:0}.btn-group-vertical>.btn:first-child{-webkit-border-radius:4px 4px 0 0;-moz-border-radius:4px 4px 0 0;border-radius:4px 4px 0 0}.btn-group-vertical>.btn:last-child{-webkit-border-radius:0 0 4px 4px;-moz-border-radius:0 0 4px 4px;border-radius:0 0 4px 4px}.btn-group-vertical>.btn-large:first-child{-webkit-border-radius:6px 6px 0 0;-moz-border-radius:6px 6px 0 0;border-radius:6px 6px 0 0}.btn-group-vertical>.btn-large:last-child{-webkit-border-radius:0 0 6px 6px;-moz-border-radius:0 0 6px 6px;border-radius:0 0 6px 6px}.alert{padding:8px 35px 8px 14px;margin-bottom:20px;text-shadow:0 1px 0 rgba(255,255,255,0.5);background-color:#fcf8e3;border:1px solid #fbeed5;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.alert,.alert h4{color:#c09853}.alert h4{margin:0}.alert .close{position:relative;top:-2px;right:-21px;line-height:20px}.alert-success{color:#468847;background-color:#dff0d8;border-color:#d6e9c6}.alert-success h4{color:#468847}.alert-danger,.alert-error{color:#b94a48;background-color:#f2dede;border-color:#eed3d7}.alert-danger h4,.alert-error h4{color:#b94a48}.alert-info{color:#3a87ad;background-color:#d9edf7;border-color:#bce8f1}.alert-info h4{color:#3a87ad}.alert-block{padding-top:14px;padding-bottom:14px}.alert-block>p,.alert-block>ul{margin-bottom:0}.alert-block p+p{margin-top:5px}.nav{margin-bottom:20px;margin-left:0;list-style:none}.nav>li>a{display:block}.nav>li>a:hover,.nav>li>a:focus{text-decoration:none;background-color:#eee}.nav>li>a>img{max-width:none}.nav>.pull-right{float:right}.nav-header{display:block;padding:3px 15px;font-size:11px;font-weight:bold;line-height:20px;color:#999;text-shadow:0 1px 0 rgba(255,255,255,0.5);text-transform:uppercase}.nav li+.nav-header{margin-top:9px}.nav-list{padding-right:15px;padding-left:15px;margin-bottom:0}.nav-list>li>a,.nav-list .nav-header{margin-right:-15px;margin-left:-15px;text-shadow:0 1px 0 rgba(255,255,255,0.5)}.nav-list>li>a{padding:3px 15px}.nav-list>.active>a,.nav-list>.active>a:hover,.nav-list>.active>a:focus{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.2);background-color:#08c}.nav-list [class^="icon-"],.nav-list [class*=" icon-"]{margin-right:2px}.nav-list .divider{*width:100%;height:1px;margin:9px 1px;*margin:-5px 0 5px;overflow:hidden;background-color:#e5e5e5;border-bottom:1px solid #fff}.nav-tabs,.nav-pills{*zoom:1}.nav-tabs:before,.nav-pills:before,.nav-tabs:after,.nav-pills:after{display:table;line-height:0;content:""}.nav-tabs:after,.nav-pills:after{clear:both}.nav-tabs>li,.nav-pills>li{float:left}.nav-tabs>li>a,.nav-pills>li>a{padding-right:12px;padding-left:12px;margin-right:2px;line-height:14px}.nav-tabs{border-bottom:1px solid #ddd}.nav-tabs>li{margin-bottom:-1px}.nav-tabs>li>a{padding-top:8px;padding-bottom:8px;line-height:20px;border:1px solid transparent;-webkit-border-radius:4px 4px 0 0;-moz-border-radius:4px 4px 0 0;border-radius:4px 4px 0 0}.nav-tabs>li>a:hover,.nav-tabs>li>a:focus{border-color:#eee #eee #ddd}.nav-tabs>.active>a,.nav-tabs>.active>a:hover,.nav-tabs>.active>a:focus{color:#555;cursor:default;background-color:#fff;border:1px solid #ddd;border-bottom-color:transparent}.nav-pills>li>a{padding-top:8px;padding-bottom:8px;margin-top:2px;margin-bottom:2px;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px}.nav-pills>.active>a,.nav-pills>.active>a:hover,.nav-pills>.active>a:focus{color:#fff;background-color:#08c}.nav-stacked>li{float:none}.nav-stacked>li>a{margin-right:0}.nav-tabs.nav-stacked{border-bottom:0}.nav-tabs.nav-stacked>li>a{border:1px solid #ddd;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.nav-tabs.nav-stacked>li:first-child>a{-webkit-border-top-right-radius:4px;border-top-right-radius:4px;-webkit-border-top-left-radius:4px;border-top-left-radius:4px;-moz-border-radius-topright:4px;-moz-border-radius-topleft:4px}.nav-tabs.nav-stacked>li:last-child>a{-webkit-border-bottom-right-radius:4px;border-bottom-right-radius:4px;-webkit-border-bottom-left-radius:4px;border-bottom-left-radius:4px;-moz-border-radius-bottomright:4px;-moz-border-radius-bottomleft:4px}.nav-tabs.nav-stacked>li>a:hover,.nav-tabs.nav-stacked>li>a:focus{z-index:2;border-color:#ddd}.nav-pills.nav-stacked>li>a{margin-bottom:3px}.nav-pills.nav-stacked>li:last-child>a{margin-bottom:1px}.nav-tabs .dropdown-menu{-webkit-border-radius:0 0 6px 6px;-moz-border-radius:0 0 6px 6px;border-radius:0 0 6px 6px}.nav-pills .dropdown-menu{-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px}.nav .dropdown-toggle .caret{margin-top:6px;border-top-color:#08c;border-bottom-color:#08c}.nav .dropdown-toggle:hover .caret,.nav .dropdown-toggle:focus .caret{border-top-color:#005580;border-bottom-color:#005580}.nav-tabs .dropdown-toggle .caret{margin-top:8px}.nav .active .dropdown-toggle .caret{border-top-color:#fff;border-bottom-color:#fff}.nav-tabs .active .dropdown-toggle .caret{border-top-color:#555;border-bottom-color:#555}.nav>.dropdown.active>a:hover,.nav>.dropdown.active>a:focus{cursor:pointer}.nav-tabs .open .dropdown-toggle,.nav-pills .open .dropdown-toggle,.nav>li.dropdown.open.active>a:hover,.nav>li.dropdown.open.active>a:focus{color:#fff;background-color:#999;border-color:#999}.nav li.dropdown.open .caret,.nav li.dropdown.open.active .caret,.nav li.dropdown.open a:hover .caret,.nav li.dropdown.open a:focus .caret{border-top-color:#fff;border-bottom-color:#fff;opacity:1;filter:alpha(opacity=100)}.tabs-stacked .open>a:hover,.tabs-stacked .open>a:focus{border-color:#999}.tabbable{*zoom:1}.tabbable:before,.tabbable:after{display:table;line-height:0;content:""}.tabbable:after{clear:both}.tab-content{overflow:auto}.tabs-below>.nav-tabs,.tabs-right>.nav-tabs,.tabs-left>.nav-tabs{border-bottom:0}.tab-content>.tab-pane,.pill-content>.pill-pane{display:none}.tab-content>.active,.pill-content>.active{display:block}.tabs-below>.nav-tabs{border-top:1px solid #ddd}.tabs-below>.nav-tabs>li{margin-top:-1px;margin-bottom:0}.tabs-below>.nav-tabs>li>a{-webkit-border-radius:0 0 4px 4px;-moz-border-radius:0 0 4px 4px;border-radius:0 0 4px 4px}.tabs-below>.nav-tabs>li>a:hover,.tabs-below>.nav-tabs>li>a:focus{border-top-color:#ddd;border-bottom-color:transparent}.tabs-below>.nav-tabs>.active>a,.tabs-below>.nav-tabs>.active>a:hover,.tabs-below>.nav-tabs>.active>a:focus{border-color:transparent #ddd #ddd #ddd}.tabs-left>.nav-tabs>li,.tabs-right>.nav-tabs>li{float:none}.tabs-left>.nav-tabs>li>a,.tabs-right>.nav-tabs>li>a{min-width:74px;margin-right:0;margin-bottom:3px}.tabs-left>.nav-tabs{float:left;margin-right:19px;border-right:1px solid #ddd}.tabs-left>.nav-tabs>li>a{margin-right:-1px;-webkit-border-radius:4px 0 0 4px;-moz-border-radius:4px 0 0 4px;border-radius:4px 0 0 4px}.tabs-left>.nav-tabs>li>a:hover,.tabs-left>.nav-tabs>li>a:focus{border-color:#eee #ddd #eee #eee}.tabs-left>.nav-tabs .active>a,.tabs-left>.nav-tabs .active>a:hover,.tabs-left>.nav-tabs .active>a:focus{border-color:#ddd transparent #ddd #ddd;*border-right-color:#fff}.tabs-right>.nav-tabs{float:right;margin-left:19px;border-left:1px solid #ddd}.tabs-right>.nav-tabs>li>a{margin-left:-1px;-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0}.tabs-right>.nav-tabs>li>a:hover,.tabs-right>.nav-tabs>li>a:focus{border-color:#eee #eee #eee #ddd}.tabs-right>.nav-tabs .active>a,.tabs-right>.nav-tabs .active>a:hover,.tabs-right>.nav-tabs .active>a:focus{border-color:#ddd #ddd #ddd transparent;*border-left-color:#fff}.nav>.disabled>a{color:#999}.nav>.disabled>a:hover,.nav>.disabled>a:focus{text-decoration:none;cursor:default;background-color:transparent}.navbar{*position:relative;*z-index:2;margin-bottom:20px;overflow:visible}.navbar-inner{min-height:40px;padding-right:20px;padding-left:20px;background-color:#fafafa;background-image:-moz-linear-gradient(top,#fff,#f2f2f2);background-image:-webkit-gradient(linear,0 0,0 100%,from(#fff),to(#f2f2f2));background-image:-webkit-linear-gradient(top,#fff,#f2f2f2);background-image:-o-linear-gradient(top,#fff,#f2f2f2);background-image:linear-gradient(to bottom,#fff,#f2f2f2);background-repeat:repeat-x;border:1px solid #d4d4d4;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff',endColorstr='#fff2f2f2',GradientType=0);*zoom:1;-webkit-box-shadow:0 1px 4px rgba(0,0,0,0.065);-moz-box-shadow:0 1px 4px rgba(0,0,0,0.065);box-shadow:0 1px 4px rgba(0,0,0,0.065)}.navbar-inner:before,.navbar-inner:after{display:table;line-height:0;content:""}.navbar-inner:after{clear:both}.navbar .container{width:auto}.nav-collapse.collapse{height:auto;overflow:visible}.navbar .brand{display:block;float:left;padding:10px 20px 10px;margin-left:-20px;font-size:20px;font-weight:200;color:#777;text-shadow:0 1px 0 #fff}.navbar .brand:hover,.navbar .brand:focus{text-decoration:none}.navbar-text{margin-bottom:0;line-height:40px;color:#777}.navbar-link{color:#777}.navbar-link:hover,.navbar-link:focus{color:#333}.navbar .divider-vertical{height:40px;margin:0 9px;border-right:1px solid #fff;border-left:1px solid #f2f2f2}.navbar .btn,.navbar .btn-group{margin-top:5px}.navbar .btn-group .btn,.navbar .input-prepend .btn,.navbar .input-append .btn,.navbar .input-prepend .btn-group,.navbar .input-append .btn-group{margin-top:0}.navbar-form{margin-bottom:0;*zoom:1}.navbar-form:before,.navbar-form:after{display:table;line-height:0;content:""}.navbar-form:after{clear:both}.navbar-form input,.navbar-form select,.navbar-form .radio,.navbar-form .checkbox{margin-top:5px}.navbar-form input,.navbar-form select,.navbar-form .btn{display:inline-block;margin-bottom:0}.navbar-form input[type="image"],.navbar-form input[type="checkbox"],.navbar-form input[type="radio"]{margin-top:3px}.navbar-form .input-append,.navbar-form .input-prepend{margin-top:5px;white-space:nowrap}.navbar-form .input-append input,.navbar-form .input-prepend input{margin-top:0}.navbar-search{position:relative;float:left;margin-top:5px;margin-bottom:0}.navbar-search .search-query{padding:4px 14px;margin-bottom:0;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:13px;font-weight:normal;line-height:1;-webkit-border-radius:15px;-moz-border-radius:15px;border-radius:15px}.navbar-static-top{position:static;margin-bottom:0}.navbar-static-top .navbar-inner{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.navbar-fixed-top,.navbar-fixed-bottom{position:fixed;right:0;left:0;z-index:1030;margin-bottom:0}.navbar-fixed-top .navbar-inner,.navbar-static-top .navbar-inner{border-width:0 0 1px}.navbar-fixed-bottom .navbar-inner{border-width:1px 0 0}.navbar-fixed-top .navbar-inner,.navbar-fixed-bottom .navbar-inner{padding-right:0;padding-left:0;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.navbar-static-top .container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:940px}.navbar-fixed-top{top:0}.navbar-fixed-top .navbar-inner,.navbar-static-top .navbar-inner{-webkit-box-shadow:0 1px 10px rgba(0,0,0,0.1);-moz-box-shadow:0 1px 10px rgba(0,0,0,0.1);box-shadow:0 1px 10px rgba(0,0,0,0.1)}.navbar-fixed-bottom{bottom:0}.navbar-fixed-bottom .navbar-inner{-webkit-box-shadow:0 -1px 10px rgba(0,0,0,0.1);-moz-box-shadow:0 -1px 10px rgba(0,0,0,0.1);box-shadow:0 -1px 10px rgba(0,0,0,0.1)}.navbar .nav{position:relative;left:0;display:block;float:left;margin:0 10px 0 0}.navbar .nav.pull-right{float:right;margin-right:0}.navbar .nav>li{float:left}.navbar .nav>li>a{float:none;padding:10px 15px 10px;color:#777;text-decoration:none;text-shadow:0 1px 0 #fff}.navbar .nav .dropdown-toggle .caret{margin-top:8px}.navbar .nav>li>a:focus,.navbar .nav>li>a:hover{color:#333;text-decoration:none;background-color:transparent}.navbar .nav>.active>a,.navbar .nav>.active>a:hover,.navbar .nav>.active>a:focus{color:#555;text-decoration:none;background-color:#e5e5e5;-webkit-box-shadow:inset 0 3px 8px rgba(0,0,0,0.125);-moz-box-shadow:inset 0 3px 8px rgba(0,0,0,0.125);box-shadow:inset 0 3px 8px rgba(0,0,0,0.125)}.navbar .btn-navbar{display:none;float:right;padding:7px 10px;margin-right:5px;margin-left:5px;color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#ededed;*background-color:#e5e5e5;background-image:-moz-linear-gradient(top,#f2f2f2,#e5e5e5);background-image:-webkit-gradient(linear,0 0,0 100%,from(#f2f2f2),to(#e5e5e5));background-image:-webkit-linear-gradient(top,#f2f2f2,#e5e5e5);background-image:-o-linear-gradient(top,#f2f2f2,#e5e5e5);background-image:linear-gradient(to bottom,#f2f2f2,#e5e5e5);background-repeat:repeat-x;border-color:#e5e5e5 #e5e5e5 #bfbfbf;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2f2f2',endColorstr='#ffe5e5e5',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.075);-moz-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.075);box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.075)}.navbar .btn-navbar:hover,.navbar .btn-navbar:focus,.navbar .btn-navbar:active,.navbar .btn-navbar.active,.navbar .btn-navbar.disabled,.navbar .btn-navbar[disabled]{color:#fff;background-color:#e5e5e5;*background-color:#d9d9d9}.navbar .btn-navbar:active,.navbar .btn-navbar.active{background-color:#ccc \9}.navbar .btn-navbar .icon-bar{display:block;width:18px;height:2px;background-color:#f5f5f5;-webkit-border-radius:1px;-moz-border-radius:1px;border-radius:1px;-webkit-box-shadow:0 1px 0 rgba(0,0,0,0.25);-moz-box-shadow:0 1px 0 rgba(0,0,0,0.25);box-shadow:0 1px 0 rgba(0,0,0,0.25)}.btn-navbar .icon-bar+.icon-bar{margin-top:3px}.navbar .nav>li>.dropdown-menu:before{position:absolute;top:-7px;left:9px;display:inline-block;border-right:7px solid transparent;border-bottom:7px solid #ccc;border-left:7px solid transparent;border-bottom-color:rgba(0,0,0,0.2);content:''}.navbar .nav>li>.dropdown-menu:after{position:absolute;top:-6px;left:10px;display:inline-block;border-right:6px solid transparent;border-bottom:6px solid #fff;border-left:6px solid transparent;content:''}.navbar-fixed-bottom .nav>li>.dropdown-menu:before{top:auto;bottom:-7px;border-top:7px solid #ccc;border-bottom:0;border-top-color:rgba(0,0,0,0.2)}.navbar-fixed-bottom .nav>li>.dropdown-menu:after{top:auto;bottom:-6px;border-top:6px solid #fff;border-bottom:0}.navbar .nav li.dropdown>a:hover .caret,.navbar .nav li.dropdown>a:focus .caret{border-top-color:#333;border-bottom-color:#333}.navbar .nav li.dropdown.open>.dropdown-toggle,.navbar .nav li.dropdown.active>.dropdown-toggle,.navbar .nav li.dropdown.open.active>.dropdown-toggle{color:#555;background-color:#e5e5e5}.navbar .nav li.dropdown>.dropdown-toggle .caret{border-top-color:#777;border-bottom-color:#777}.navbar .nav li.dropdown.open>.dropdown-toggle .caret,.navbar .nav li.dropdown.active>.dropdown-toggle .caret,.navbar .nav li.dropdown.open.active>.dropdown-toggle .caret{border-top-color:#555;border-bottom-color:#555}.navbar .pull-right>li>.dropdown-menu,.navbar .nav>li>.dropdown-menu.pull-right{right:0;left:auto}.navbar .pull-right>li>.dropdown-menu:before,.navbar .nav>li>.dropdown-menu.pull-right:before{right:12px;left:auto}.navbar .pull-right>li>.dropdown-menu:after,.navbar .nav>li>.dropdown-menu.pull-right:after{right:13px;left:auto}.navbar .pull-right>li>.dropdown-menu .dropdown-menu,.navbar .nav>li>.dropdown-menu.pull-right .dropdown-menu{right:100%;left:auto;margin-right:-1px;margin-left:0;-webkit-border-radius:6px 0 6px 6px;-moz-border-radius:6px 0 6px 6px;border-radius:6px 0 6px 6px}.navbar-inverse .navbar-inner{background-color:#1b1b1b;background-image:-moz-linear-gradient(top,#222,#111);background-image:-webkit-gradient(linear,0 0,0 100%,from(#222),to(#111));background-image:-webkit-linear-gradient(top,#222,#111);background-image:-o-linear-gradient(top,#222,#111);background-image:linear-gradient(to bottom,#222,#111);background-repeat:repeat-x;border-color:#252525;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222',endColorstr='#ff111111',GradientType=0)}.navbar-inverse .brand,.navbar-inverse .nav>li>a{color:#999;text-shadow:0 -1px 0 rgba(0,0,0,0.25)}.navbar-inverse .brand:hover,.navbar-inverse .nav>li>a:hover,.navbar-inverse .brand:focus,.navbar-inverse .nav>li>a:focus{color:#fff}.navbar-inverse .brand{color:#999}.navbar-inverse .navbar-text{color:#999}.navbar-inverse .nav>li>a:focus,.navbar-inverse .nav>li>a:hover{color:#fff;background-color:transparent}.navbar-inverse .nav .active>a,.navbar-inverse .nav .active>a:hover,.navbar-inverse .nav .active>a:focus{color:#fff;background-color:#111}.navbar-inverse .navbar-link{color:#999}.navbar-inverse .navbar-link:hover,.navbar-inverse .navbar-link:focus{color:#fff}.navbar-inverse .divider-vertical{border-right-color:#222;border-left-color:#111}.navbar-inverse .nav li.dropdown.open>.dropdown-toggle,.navbar-inverse .nav li.dropdown.active>.dropdown-toggle,.navbar-inverse .nav li.dropdown.open.active>.dropdown-toggle{color:#fff;background-color:#111}.navbar-inverse .nav li.dropdown>a:hover .caret,.navbar-inverse .nav li.dropdown>a:focus .caret{border-top-color:#fff;border-bottom-color:#fff}.navbar-inverse .nav li.dropdown>.dropdown-toggle .caret{border-top-color:#999;border-bottom-color:#999}.navbar-inverse .nav li.dropdown.open>.dropdown-toggle .caret,.navbar-inverse .nav li.dropdown.active>.dropdown-toggle .caret,.navbar-inverse .nav li.dropdown.open.active>.dropdown-toggle .caret{border-top-color:#fff;border-bottom-color:#fff}.navbar-inverse .navbar-search .search-query{color:#fff;background-color:#515151;border-color:#111;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1),0 1px 0 rgba(255,255,255,0.15);-moz-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1),0 1px 0 rgba(255,255,255,0.15);box-shadow:inset 0 1px 2px rgba(0,0,0,0.1),0 1px 0 rgba(255,255,255,0.15);-webkit-transition:none;-moz-transition:none;-o-transition:none;transition:none}.navbar-inverse .navbar-search .search-query:-moz-placeholder{color:#ccc}.navbar-inverse .navbar-search .search-query:-ms-input-placeholder{color:#ccc}.navbar-inverse .navbar-search .search-query::-webkit-input-placeholder{color:#ccc}.navbar-inverse .navbar-search .search-query:focus,.navbar-inverse .navbar-search .search-query.focused{padding:5px 15px;color:#333;text-shadow:0 1px 0 #fff;background-color:#fff;border:0;outline:0;-webkit-box-shadow:0 0 3px rgba(0,0,0,0.15);-moz-box-shadow:0 0 3px rgba(0,0,0,0.15);box-shadow:0 0 3px rgba(0,0,0,0.15)}.navbar-inverse .btn-navbar{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#0e0e0e;*background-color:#040404;background-image:-moz-linear-gradient(top,#151515,#040404);background-image:-webkit-gradient(linear,0 0,0 100%,from(#151515),to(#040404));background-image:-webkit-linear-gradient(top,#151515,#040404);background-image:-o-linear-gradient(top,#151515,#040404);background-image:linear-gradient(to bottom,#151515,#040404);background-repeat:repeat-x;border-color:#040404 #040404 #000;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff151515',endColorstr='#ff040404',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.navbar-inverse .btn-navbar:hover,.navbar-inverse .btn-navbar:focus,.navbar-inverse .btn-navbar:active,.navbar-inverse .btn-navbar.active,.navbar-inverse .btn-navbar.disabled,.navbar-inverse .btn-navbar[disabled]{color:#fff;background-color:#040404;*background-color:#000}.navbar-inverse .btn-navbar:active,.navbar-inverse .btn-navbar.active{background-color:#000 \9}.breadcrumb{padding:8px 15px;margin:0 0 20px;list-style:none;background-color:#f5f5f5;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.breadcrumb>li{display:inline-block;*display:inline;text-shadow:0 1px 0 #fff;*zoom:1}.breadcrumb>li>.divider{padding:0 5px;color:#ccc}.breadcrumb>.active{color:#999}.pagination{margin:20px 0}.pagination ul{display:inline-block;*display:inline;margin-bottom:0;margin-left:0;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;*zoom:1;-webkit-box-shadow:0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:0 1px 2px rgba(0,0,0,0.05);box-shadow:0 1px 2px rgba(0,0,0,0.05)}.pagination ul>li{display:inline}.pagination ul>li>a,.pagination ul>li>span{float:left;padding:4px 12px;line-height:20px;text-decoration:none;background-color:#fff;border:1px solid #ddd;border-left-width:0}.pagination ul>li>a:hover,.pagination ul>li>a:focus,.pagination ul>.active>a,.pagination ul>.active>span{background-color:#f5f5f5}.pagination ul>.active>a,.pagination ul>.active>span{color:#999;cursor:default}.pagination ul>.disabled>span,.pagination ul>.disabled>a,.pagination ul>.disabled>a:hover,.pagination ul>.disabled>a:focus{color:#999;cursor:default;background-color:transparent}.pagination ul>li:first-child>a,.pagination ul>li:first-child>span{border-left-width:1px;-webkit-border-bottom-left-radius:4px;border-bottom-left-radius:4px;-webkit-border-top-left-radius:4px;border-top-left-radius:4px;-moz-border-radius-bottomleft:4px;-moz-border-radius-topleft:4px}.pagination ul>li:last-child>a,.pagination ul>li:last-child>span{-webkit-border-top-right-radius:4px;border-top-right-radius:4px;-webkit-border-bottom-right-radius:4px;border-bottom-right-radius:4px;-moz-border-radius-topright:4px;-moz-border-radius-bottomright:4px}.pagination-centered{text-align:center}.pagination-right{text-align:right}.pagination-large ul>li>a,.pagination-large ul>li>span{padding:11px 19px;font-size:17.5px}.pagination-large ul>li:first-child>a,.pagination-large ul>li:first-child>span{-webkit-border-bottom-left-radius:6px;border-bottom-left-radius:6px;-webkit-border-top-left-radius:6px;border-top-left-radius:6px;-moz-border-radius-bottomleft:6px;-moz-border-radius-topleft:6px}.pagination-large ul>li:last-child>a,.pagination-large ul>li:last-child>span{-webkit-border-top-right-radius:6px;border-top-right-radius:6px;-webkit-border-bottom-right-radius:6px;border-bottom-right-radius:6px;-moz-border-radius-topright:6px;-moz-border-radius-bottomright:6px}.pagination-mini ul>li:first-child>a,.pagination-small ul>li:first-child>a,.pagination-mini ul>li:first-child>span,.pagination-small ul>li:first-child>span{-webkit-border-bottom-left-radius:3px;border-bottom-left-radius:3px;-webkit-border-top-left-radius:3px;border-top-left-radius:3px;-moz-border-radius-bottomleft:3px;-moz-border-radius-topleft:3px}.pagination-mini ul>li:last-child>a,.pagination-small ul>li:last-child>a,.pagination-mini ul>li:last-child>span,.pagination-small ul>li:last-child>span{-webkit-border-top-right-radius:3px;border-top-right-radius:3px;-webkit-border-bottom-right-radius:3px;border-bottom-right-radius:3px;-moz-border-radius-topright:3px;-moz-border-radius-bottomright:3px}.pagination-small ul>li>a,.pagination-small ul>li>span{padding:2px 10px;font-size:11.9px}.pagination-mini ul>li>a,.pagination-mini ul>li>span{padding:0 6px;font-size:10.5px}.pager{margin:20px 0;text-align:center;list-style:none;*zoom:1}.pager:before,.pager:after{display:table;line-height:0;content:""}.pager:after{clear:both}.pager li{display:inline}.pager li>a,.pager li>span{display:inline-block;padding:5px 14px;background-color:#fff;border:1px solid #ddd;-webkit-border-radius:15px;-moz-border-radius:15px;border-radius:15px}.pager li>a:hover,.pager li>a:focus{text-decoration:none;background-color:#f5f5f5}.pager .next>a,.pager .next>span{float:right}.pager .previous>a,.pager .previous>span{float:left}.pager .disabled>a,.pager .disabled>a:hover,.pager .disabled>a:focus,.pager .disabled>span{color:#999;cursor:default;background-color:#fff}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:#000}.modal-backdrop.fade{opacity:0}.modal-backdrop,.modal-backdrop.fade.in{opacity:.8;filter:alpha(opacity=80)}.modal{position:fixed;top:10%;left:50%;z-index:1050;width:560px;margin-left:-280px;background-color:#fff;border:1px solid #999;border:1px solid rgba(0,0,0,0.3);*border:1px solid #999;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;outline:0;-webkit-box-shadow:0 3px 7px rgba(0,0,0,0.3);-moz-box-shadow:0 3px 7px rgba(0,0,0,0.3);box-shadow:0 3px 7px rgba(0,0,0,0.3);-webkit-background-clip:padding-box;-moz-background-clip:padding-box;background-clip:padding-box}.modal.fade{top:-25%;-webkit-transition:opacity .3s linear,top .3s ease-out;-moz-transition:opacity .3s linear,top .3s ease-out;-o-transition:opacity .3s linear,top .3s ease-out;transition:opacity .3s linear,top .3s ease-out}.modal.fade.in{top:10%}.modal-header{padding:9px 15px;border-bottom:1px solid #eee}.modal-header .close{margin-top:2px}.modal-header h3{margin:0;line-height:30px}.modal-body{position:relative;max-height:400px;padding:15px;overflow-y:auto}.modal-form{margin-bottom:0}.modal-footer{padding:14px 15px 15px;margin-bottom:0;text-align:right;background-color:#f5f5f5;border-top:1px solid #ddd;-webkit-border-radius:0 0 6px 6px;-moz-border-radius:0 0 6px 6px;border-radius:0 0 6px 6px;*zoom:1;-webkit-box-shadow:inset 0 1px 0 #fff;-moz-box-shadow:inset 0 1px 0 #fff;box-shadow:inset 0 1px 0 #fff}.modal-footer:before,.modal-footer:after{display:table;line-height:0;content:""}.modal-footer:after{clear:both}.modal-footer .btn+.btn{margin-bottom:0;margin-left:5px}.modal-footer .btn-group .btn+.btn{margin-left:-1px}.modal-footer .btn-block+.btn-block{margin-left:0}.tooltip{position:absolute;z-index:1030;display:block;font-size:11px;line-height:1.4;opacity:0;filter:alpha(opacity=0);visibility:visible}.tooltip.in{opacity:.8;filter:alpha(opacity=80)}.tooltip.top{padding:5px 0;margin-top:-3px}.tooltip.right{padding:0 5px;margin-left:3px}.tooltip.bottom{padding:5px 0;margin-top:3px}.tooltip.left{padding:0 5px;margin-left:-3px}.tooltip-inner{max-width:200px;padding:8px;color:#fff;text-align:center;text-decoration:none;background-color:#000;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid}.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-top-color:#000;border-width:5px 5px 0}.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-right-color:#000;border-width:5px 5px 5px 0}.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-left-color:#000;border-width:5px 0 5px 5px}.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-bottom-color:#000;border-width:0 5px 5px}.popover{position:absolute;top:0;left:0;z-index:1010;display:none;max-width:276px;padding:1px;text-align:left;white-space:normal;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.2);-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,0.2);-moz-box-shadow:0 5px 10px rgba(0,0,0,0.2);box-shadow:0 5px 10px rgba(0,0,0,0.2);-webkit-background-clip:padding-box;-moz-background-clip:padding;background-clip:padding-box}.popover.top{margin-top:-10px}.popover.right{margin-left:10px}.popover.bottom{margin-top:10px}.popover.left{margin-left:-10px}.popover-title{padding:8px 14px;margin:0;font-size:14px;font-weight:normal;line-height:18px;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;-webkit-border-radius:5px 5px 0 0;-moz-border-radius:5px 5px 0 0;border-radius:5px 5px 0 0}.popover-title:empty{display:none}.popover-content{padding:9px 14px}.popover .arrow,.popover .arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.popover .arrow{border-width:11px}.popover .arrow:after{border-width:10px;content:""}.popover.top .arrow{bottom:-11px;left:50%;margin-left:-11px;border-top-color:#999;border-top-color:rgba(0,0,0,0.25);border-bottom-width:0}.popover.top .arrow:after{bottom:1px;margin-left:-10px;border-top-color:#fff;border-bottom-width:0}.popover.right .arrow{top:50%;left:-11px;margin-top:-11px;border-right-color:#999;border-right-color:rgba(0,0,0,0.25);border-left-width:0}.popover.right .arrow:after{bottom:-10px;left:1px;border-right-color:#fff;border-left-width:0}.popover.bottom .arrow{top:-11px;left:50%;margin-left:-11px;border-bottom-color:#999;border-bottom-color:rgba(0,0,0,0.25);border-top-width:0}.popover.bottom .arrow:after{top:1px;margin-left:-10px;border-bottom-color:#fff;border-top-width:0}.popover.left .arrow{top:50%;right:-11px;margin-top:-11px;border-left-color:#999;border-left-color:rgba(0,0,0,0.25);border-right-width:0}.popover.left .arrow:after{right:1px;bottom:-10px;border-left-color:#fff;border-right-width:0}.thumbnails{margin-left:-20px;list-style:none;*zoom:1}.thumbnails:before,.thumbnails:after{display:table;line-height:0;content:""}.thumbnails:after{clear:both}.row-fluid .thumbnails{margin-left:0}.thumbnails>li{float:left;margin-bottom:20px;margin-left:20px}.thumbnail{display:block;padding:4px;line-height:20px;border:1px solid #ddd;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-webkit-box-shadow:0 1px 3px rgba(0,0,0,0.055);-moz-box-shadow:0 1px 3px rgba(0,0,0,0.055);box-shadow:0 1px 3px rgba(0,0,0,0.055);-webkit-transition:all .2s ease-in-out;-moz-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out}a.thumbnail:hover,a.thumbnail:focus{border-color:#08c;-webkit-box-shadow:0 1px 4px rgba(0,105,214,0.25);-moz-box-shadow:0 1px 4px rgba(0,105,214,0.25);box-shadow:0 1px 4px rgba(0,105,214,0.25)}.thumbnail>img{display:block;max-width:100%;margin-right:auto;margin-left:auto}.thumbnail .caption{padding:9px;color:#555}.media,.media-body{overflow:hidden;*overflow:visible;zoom:1}.media,.media .media{margin-top:15px}.media:first-child{margin-top:0}.media-object{display:block}.media-heading{margin:0 0 5px}.media>.pull-left{margin-right:10px}.media>.pull-right{margin-left:10px}.media-list{margin-left:0;list-style:none}.label,.badge{display:inline-block;padding:2px 4px;font-size:11.844px;font-weight:bold;line-height:14px;color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);white-space:nowrap;vertical-align:baseline;background-color:#999}.label{-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.badge{padding-right:9px;padding-left:9px;-webkit-border-radius:9px;-moz-border-radius:9px;border-radius:9px}.label:empty,.badge:empty{display:none}a.label:hover,a.label:focus,a.badge:hover,a.badge:focus{color:#fff;text-decoration:none;cursor:pointer}.label-important,.badge-important{background-color:#b94a48}.label-important[href],.badge-important[href]{background-color:#953b39}.label-warning,.badge-warning{background-color:#f89406}.label-warning[href],.badge-warning[href]{background-color:#c67605}.label-success,.badge-success{background-color:#468847}.label-success[href],.badge-success[href]{background-color:#356635}.label-info,.badge-info{background-color:#3a87ad}.label-info[href],.badge-info[href]{background-color:#2d6987}.label-inverse,.badge-inverse{background-color:#333}.label-inverse[href],.badge-inverse[href]{background-color:#1a1a1a}.btn .label,.btn .badge{position:relative;top:-1px}.btn-mini .label,.btn-mini .badge{top:0}@-webkit-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-moz-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-ms-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-o-keyframes progress-bar-stripes{from{background-position:0 0}to{background-position:40px 0}}@keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}.progress{height:20px;margin-bottom:20px;overflow:hidden;background-color:#f7f7f7;background-image:-moz-linear-gradient(top,#f5f5f5,#f9f9f9);background-image:-webkit-gradient(linear,0 0,0 100%,from(#f5f5f5),to(#f9f9f9));background-image:-webkit-linear-gradient(top,#f5f5f5,#f9f9f9);background-image:-o-linear-gradient(top,#f5f5f5,#f9f9f9);background-image:linear-gradient(to bottom,#f5f5f5,#f9f9f9);background-repeat:repeat-x;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5',endColorstr='#fff9f9f9',GradientType=0);-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1);-moz-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1);box-shadow:inset 0 1px 2px rgba(0,0,0,0.1)}.progress .bar{float:left;width:0;height:100%;font-size:12px;color:#fff;text-align:center;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#0e90d2;background-image:-moz-linear-gradient(top,#149bdf,#0480be);background-image:-webkit-gradient(linear,0 0,0 100%,from(#149bdf),to(#0480be));background-image:-webkit-linear-gradient(top,#149bdf,#0480be);background-image:-o-linear-gradient(top,#149bdf,#0480be);background-image:linear-gradient(to bottom,#149bdf,#0480be);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff149bdf',endColorstr='#ff0480be',GradientType=0);-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);-moz-box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-transition:width .6s ease;-moz-transition:width .6s ease;-o-transition:width .6s ease;transition:width .6s ease}.progress .bar+.bar{-webkit-box-shadow:inset 1px 0 0 rgba(0,0,0,0.15),inset 0 -1px 0 rgba(0,0,0,0.15);-moz-box-shadow:inset 1px 0 0 rgba(0,0,0,0.15),inset 0 -1px 0 rgba(0,0,0,0.15);box-shadow:inset 1px 0 0 rgba(0,0,0,0.15),inset 0 -1px 0 rgba(0,0,0,0.15)}.progress-striped .bar{background-color:#149bdf;background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);-webkit-background-size:40px 40px;-moz-background-size:40px 40px;-o-background-size:40px 40px;background-size:40px 40px}.progress.active .bar{-webkit-animation:progress-bar-stripes 2s linear infinite;-moz-animation:progress-bar-stripes 2s linear infinite;-ms-animation:progress-bar-stripes 2s linear infinite;-o-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.progress-danger .bar,.progress .bar-danger{background-color:#dd514c;background-image:-moz-linear-gradient(top,#ee5f5b,#c43c35);background-image:-webkit-gradient(linear,0 0,0 100%,from(#ee5f5b),to(#c43c35));background-image:-webkit-linear-gradient(top,#ee5f5b,#c43c35);background-image:-o-linear-gradient(top,#ee5f5b,#c43c35);background-image:linear-gradient(to bottom,#ee5f5b,#c43c35);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b',endColorstr='#ffc43c35',GradientType=0)}.progress-danger.progress-striped .bar,.progress-striped .bar-danger{background-color:#ee5f5b;background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent)}.progress-success .bar,.progress .bar-success{background-color:#5eb95e;background-image:-moz-linear-gradient(top,#62c462,#57a957);background-image:-webkit-gradient(linear,0 0,0 100%,from(#62c462),to(#57a957));background-image:-webkit-linear-gradient(top,#62c462,#57a957);background-image:-o-linear-gradient(top,#62c462,#57a957);background-image:linear-gradient(to bottom,#62c462,#57a957);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462',endColorstr='#ff57a957',GradientType=0)}.progress-success.progress-striped .bar,.progress-striped .bar-success{background-color:#62c462;background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent)}.progress-info .bar,.progress .bar-info{background-color:#4bb1cf;background-image:-moz-linear-gradient(top,#5bc0de,#339bb9);background-image:-webkit-gradient(linear,0 0,0 100%,from(#5bc0de),to(#339bb9));background-image:-webkit-linear-gradient(top,#5bc0de,#339bb9);background-image:-o-linear-gradient(top,#5bc0de,#339bb9);background-image:linear-gradient(to bottom,#5bc0de,#339bb9);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de',endColorstr='#ff339bb9',GradientType=0)}.progress-info.progress-striped .bar,.progress-striped .bar-info{background-color:#5bc0de;background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent)}.progress-warning .bar,.progress .bar-warning{background-color:#faa732;background-image:-moz-linear-gradient(top,#fbb450,#f89406);background-image:-webkit-gradient(linear,0 0,0 100%,from(#fbb450),to(#f89406));background-image:-webkit-linear-gradient(top,#fbb450,#f89406);background-image:-o-linear-gradient(top,#fbb450,#f89406);background-image:linear-gradient(to bottom,#fbb450,#f89406);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450',endColorstr='#fff89406',GradientType=0)}.progress-warning.progress-striped .bar,.progress-striped .bar-warning{background-color:#fbb450;background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent)}.accordion{margin-bottom:20px}.accordion-group{margin-bottom:2px;border:1px solid #e5e5e5;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.accordion-heading{border-bottom:0}.accordion-heading .accordion-toggle{display:block;padding:8px 15px}.accordion-toggle{cursor:pointer}.accordion-inner{padding:9px 15px;border-top:1px solid #e5e5e5}.carousel{position:relative;margin-bottom:20px;line-height:1}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-inner>.item{position:relative;display:none;-webkit-transition:.6s ease-in-out left;-moz-transition:.6s ease-in-out left;-o-transition:.6s ease-in-out left;transition:.6s ease-in-out left}.carousel-inner>.item>img,.carousel-inner>.item>a>img{display:block;line-height:1}.carousel-inner>.active,.carousel-inner>.next,.carousel-inner>.prev{display:block}.carousel-inner>.active{left:0}.carousel-inner>.next,.carousel-inner>.prev{position:absolute;top:0;width:100%}.carousel-inner>.next{left:100%}.carousel-inner>.prev{left:-100%}.carousel-inner>.next.left,.carousel-inner>.prev.right{left:0}.carousel-inner>.active.left{left:-100%}.carousel-inner>.active.right{left:100%}.carousel-control{position:absolute;top:40%;left:15px;width:40px;height:40px;margin-top:-20px;font-size:60px;font-weight:100;line-height:30px;color:#fff;text-align:center;background:#222;border:3px solid #fff;-webkit-border-radius:23px;-moz-border-radius:23px;border-radius:23px;opacity:.5;filter:alpha(opacity=50)}.carousel-control.right{right:15px;left:auto}.carousel-control:hover,.carousel-control:focus{color:#fff;text-decoration:none;opacity:.9;filter:alpha(opacity=90)}.carousel-indicators{position:absolute;top:15px;right:15px;z-index:5;margin:0;list-style:none}.carousel-indicators li{display:block;float:left;width:10px;height:10px;margin-left:5px;text-indent:-999px;background-color:#ccc;background-color:rgba(255,255,255,0.25);border-radius:5px}.carousel-indicators .active{background-color:#fff}.carousel-caption{position:absolute;right:0;bottom:0;left:0;padding:15px;background:#333;background:rgba(0,0,0,0.75)}.carousel-caption h4,.carousel-caption p{line-height:20px;color:#fff}.carousel-caption h4{margin:0 0 5px}.carousel-caption p{margin-bottom:0}.hero-unit{padding:60px;margin-bottom:30px;font-size:18px;font-weight:200;line-height:30px;color:inherit;background-color:#eee;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px}.hero-unit h1{margin-bottom:0;font-size:60px;line-height:1;letter-spacing:-1px;color:inherit}.hero-unit li{line-height:30px}.pull-right{float:right}.pull-left{float:left}.hide{display:none}.show{display:block}.invisible{visibility:hidden}.affix{position:fixed} + */ +.clearfix { + *zoom: 1 +} + +.clearfix:before, +.clearfix:after { + display: table; + line-height: 0; + content: "" +} + +.clearfix:after { + clear: both +} + +.hide-text { + font: 0/0 a; + color: transparent; + text-shadow: none; + background-color: transparent; + border: 0 +} + +.input-block-level { + display: block; + width: 100%; + min-height: 30px; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box +} + +article, +aside, +details, +figcaption, +figure, +footer, +header, +hgroup, +nav, +section { + display: block +} + +audio, +canvas, +video { + display: inline-block; + *display: inline; + *zoom: 1 +} + +audio:not([controls]) { + display: none +} + +html { + font-size: 100%; + -webkit-text-size-adjust: 100%; + -ms-text-size-adjust: 100% +} + +a:focus { + outline: thin dotted #333; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px +} + +a:hover, +a:active { + outline: 0 +} + +sub, +sup { + position: relative; + font-size: 75%; + line-height: 0; + vertical-align: baseline +} + +sup { + top: -0.5em +} + +sub { + bottom: -0.25em +} + +img { + width: auto\9; + height: auto; + max-width: 100%; + vertical-align: middle; + border: 0; + -ms-interpolation-mode: bicubic +} + +#map_canvas img, +.google-maps img { + max-width: none +} + +button, +input, +select, +textarea { + margin: 0; + font-size: 100%; + vertical-align: middle +} + +button, +input { + *overflow: visible; + line-height: normal +} + +button::-moz-focus-inner, +input::-moz-focus-inner { + padding: 0; + border: 0 +} + +button, +html input[type="button"], +input[type="reset"], +input[type="submit"] { + cursor: pointer; + -webkit-appearance: button +} + +label, +select, +button, +input[type="button"], +input[type="reset"], +input[type="submit"], +input[type="radio"], +input[type="checkbox"] { + cursor: pointer +} + +input[type="search"] { + -webkit-box-sizing: content-box; + -moz-box-sizing: content-box; + box-sizing: content-box; + -webkit-appearance: textfield +} + +input[type="search"]::-webkit-search-decoration, +input[type="search"]::-webkit-search-cancel-button { + -webkit-appearance: none +} + +textarea { + overflow: auto; + vertical-align: top +} + +@media print { + * { + color: #000 !important; + text-shadow: none !important; + background: transparent !important; + box-shadow: none !important + } + + a, + a:visited { + text-decoration: underline + } + + a[href]:after { + content: " (" attr(href) ")" + } + + abbr[title]:after { + content: " (" attr(title) ")" + } + + .ir a:after, + a[href^="javascript:"]:after, + a[href^="#"]:after { + content: "" + } + + pre, + blockquote { + border: 1px solid #999; + page-break-inside: avoid + } + + thead { + display: table-header-group + } + + tr, + img { + page-break-inside: avoid + } + + img { + max-width: 100% !important + } + + @page { + margin: .5cm + } + + p, + h2, + h3 { + orphans: 3; + widows: 3 + } + + h2, + h3 { + page-break-after: avoid + } +} + +body { + margin: 0; + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 14px; + line-height: 20px; + color: #333; + background-color: #fff +} + +a { + color: #08c; + text-decoration: none +} + +a:hover, +a:focus { + color: #005580; + text-decoration: underline +} + +.img-rounded { + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px +} + +.img-polaroid { + padding: 4px; + background-color: #fff; + border: 1px solid #ccc; + border: 1px solid rgba(0, 0, 0, 0.2); + -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); + -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1) +} + +.img-circle { + -webkit-border-radius: 500px; + -moz-border-radius: 500px; + border-radius: 500px +} + +.row { + margin-left: -20px; + *zoom: 1 +} + +.row:before, +.row:after { + display: table; + line-height: 0; + content: "" +} + +.row:after { + clear: both +} + +[class*="span"] { + float: left; + min-height: 1px; + margin-left: 20px +} + +.container, +.navbar-static-top .container, +.navbar-fixed-top .container, +.navbar-fixed-bottom .container { + width: 940px +} + +.span12 { + width: 940px +} + +.span11 { + width: 860px +} + +.span10 { + width: 780px +} + +.span9 { + width: 700px +} + +.span8 { + width: 620px +} + +.span7 { + width: 540px +} + +.span6 { + width: 460px +} + +.span5 { + width: 380px +} + +.span4 { + width: 300px +} + +.span3 { + width: 220px +} + +.span2 { + width: 140px +} + +.span1 { + width: 60px +} + +.offset12 { + margin-left: 980px +} + +.offset11 { + margin-left: 900px +} + +.offset10 { + margin-left: 820px +} + +.offset9 { + margin-left: 740px +} + +.offset8 { + margin-left: 660px +} + +.offset7 { + margin-left: 580px +} + +.offset6 { + margin-left: 500px +} + +.offset5 { + margin-left: 420px +} + +.offset4 { + margin-left: 340px +} + +.offset3 { + margin-left: 260px +} + +.offset2 { + margin-left: 180px +} + +.offset1 { + margin-left: 100px +} + +.row-fluid { + width: 100%; + *zoom: 1 +} + +.row-fluid:before, +.row-fluid:after { + display: table; + line-height: 0; + content: "" +} + +.row-fluid:after { + clear: both +} + +.row-fluid [class*="span"] { + display: block; + float: left; + width: 100%; + min-height: 30px; + margin-left: 2.127659574468085%; + *margin-left: 2.074468085106383%; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box +} + +.row-fluid [class*="span"]:first-child { + margin-left: 0 +} + +.row-fluid .controls-row [class*="span"]+[class*="span"] { + margin-left: 2.127659574468085% +} + +.row-fluid .span12 { + width: 100%; + *width: 99.94680851063829% +} + +.row-fluid .span11 { + width: 91.48936170212765%; + *width: 91.43617021276594% +} + +.row-fluid .span10 { + width: 82.97872340425532%; + *width: 82.92553191489361% +} + +.row-fluid .span9 { + width: 74.46808510638297%; + *width: 74.41489361702126% +} + +.row-fluid .span8 { + width: 65.95744680851064%; + *width: 65.90425531914893% +} + +.row-fluid .span7 { + width: 57.44680851063829%; + *width: 57.39361702127659% +} + +.row-fluid .span6 { + width: 48.93617021276595%; + *width: 48.88297872340425% +} + +.row-fluid .span5 { + width: 40.42553191489362%; + *width: 40.37234042553192% +} + +.row-fluid .span4 { + width: 31.914893617021278%; + *width: 31.861702127659576% +} + +.row-fluid .span3 { + width: 23.404255319148934%; + *width: 23.351063829787233% +} + +.row-fluid .span2 { + width: 14.893617021276595%; + *width: 14.840425531914894% +} + +.row-fluid .span1 { + width: 6.382978723404255%; + *width: 6.329787234042553% +} + +.row-fluid .offset12 { + margin-left: 104.25531914893617%; + *margin-left: 104.14893617021275% +} + +.row-fluid .offset12:first-child { + margin-left: 102.12765957446808%; + *margin-left: 102.02127659574467% +} + +.row-fluid .offset11 { + margin-left: 95.74468085106382%; + *margin-left: 95.6382978723404% +} + +.row-fluid .offset11:first-child { + margin-left: 93.61702127659574%; + *margin-left: 93.51063829787232% +} + +.row-fluid .offset10 { + margin-left: 87.23404255319149%; + *margin-left: 87.12765957446807% +} + +.row-fluid .offset10:first-child { + margin-left: 85.1063829787234%; + *margin-left: 84.99999999999999% +} + +.row-fluid .offset9 { + margin-left: 78.72340425531914%; + *margin-left: 78.61702127659572% +} + +.row-fluid .offset9:first-child { + margin-left: 76.59574468085106%; + *margin-left: 76.48936170212764% +} + +.row-fluid .offset8 { + margin-left: 70.2127659574468%; + *margin-left: 70.10638297872339% +} + +.row-fluid .offset8:first-child { + margin-left: 68.08510638297872%; + *margin-left: 67.9787234042553% +} + +.row-fluid .offset7 { + margin-left: 61.70212765957446%; + *margin-left: 61.59574468085106% +} + +.row-fluid .offset7:first-child { + margin-left: 59.574468085106375%; + *margin-left: 59.46808510638297% +} + +.row-fluid .offset6 { + margin-left: 53.191489361702125%; + *margin-left: 53.085106382978715% +} + +.row-fluid .offset6:first-child { + margin-left: 51.063829787234035%; + *margin-left: 50.95744680851063% +} + +.row-fluid .offset5 { + margin-left: 44.68085106382979%; + *margin-left: 44.57446808510638% +} + +.row-fluid .offset5:first-child { + margin-left: 42.5531914893617%; + *margin-left: 42.4468085106383% +} + +.row-fluid .offset4 { + margin-left: 36.170212765957444%; + *margin-left: 36.06382978723405% +} + +.row-fluid .offset4:first-child { + margin-left: 34.04255319148936%; + *margin-left: 33.93617021276596% +} + +.row-fluid .offset3 { + margin-left: 27.659574468085104%; + *margin-left: 27.5531914893617% +} + +.row-fluid .offset3:first-child { + margin-left: 25.53191489361702%; + *margin-left: 25.425531914893618% +} + +.row-fluid .offset2 { + margin-left: 19.148936170212764%; + *margin-left: 19.04255319148936% +} + +.row-fluid .offset2:first-child { + margin-left: 17.02127659574468%; + *margin-left: 16.914893617021278% +} + +.row-fluid .offset1 { + margin-left: 10.638297872340425%; + *margin-left: 10.53191489361702% +} + +.row-fluid .offset1:first-child { + margin-left: 8.51063829787234%; + *margin-left: 8.404255319148938% +} + +[class*="span"].hide, +.row-fluid [class*="span"].hide { + display: none +} + +[class*="span"].pull-right, +.row-fluid [class*="span"].pull-right { + float: right +} + +.container { + margin-right: auto; + margin-left: auto; + *zoom: 1 +} + +.container:before, +.container:after { + display: table; + line-height: 0; + content: "" +} + +.container:after { + clear: both +} + +.container-fluid { + padding-right: 20px; + padding-left: 20px; + *zoom: 1 +} + +.container-fluid:before, +.container-fluid:after { + display: table; + line-height: 0; + content: "" +} + +.container-fluid:after { + clear: both +} + +p { + margin: 0 0 10px +} + +.lead { + margin-bottom: 20px; + font-size: 21px; + font-weight: 200; + line-height: 30px +} + +small { + font-size: 85% +} + +strong { + font-weight: bold +} + +em { + font-style: italic +} + +cite { + font-style: normal +} + +.muted { + color: #999 +} + +a.muted:hover, +a.muted:focus { + color: #808080 +} + +.text-warning { + color: #c09853 +} + +a.text-warning:hover, +a.text-warning:focus { + color: #a47e3c +} + +.text-error { + color: #b94a48 +} + +a.text-error:hover, +a.text-error:focus { + color: #953b39 +} + +.text-info { + color: #3a87ad +} + +a.text-info:hover, +a.text-info:focus { + color: #2d6987 +} + +.text-success { + color: #468847 +} + +a.text-success:hover, +a.text-success:focus { + color: #356635 +} + +.text-left { + text-align: left +} + +.text-right { + text-align: right +} + +.text-center { + text-align: center +} + +h1, +h2, +h3, +h4, +h5, +h6 { + margin: 10px 0; + font-family: inherit; + font-weight: bold; + line-height: 20px; + color: inherit; + text-rendering: optimizelegibility +} + +h1 small, +h2 small, +h3 small, +h4 small, +h5 small, +h6 small { + font-weight: normal; + line-height: 1; + color: #999 +} + +h1, +h2, +h3 { + line-height: 40px +} + +h1 { + font-size: 38.5px +} + +h2 { + font-size: 31.5px +} + +h3 { + font-size: 24.5px +} + +h4 { + font-size: 17.5px +} + +h5 { + font-size: 14px +} + +h6 { + font-size: 11.9px +} + +h1 small { + font-size: 24.5px +} + +h2 small { + font-size: 17.5px +} + +h3 small { + font-size: 14px +} + +h4 small { + font-size: 14px +} + +.page-header { + padding-bottom: 9px; + margin: 20px 0 30px; + border-bottom: 1px solid #eee +} + +ul, +ol { + padding: 0; + margin: 0 0 10px 25px +} + +ul ul, +ul ol, +ol ol, +ol ul { + margin-bottom: 0 +} + +li { + line-height: 20px +} + +ul.unstyled, +ol.unstyled { + margin-left: 0; + list-style: none +} + +ul.inline, +ol.inline { + margin-left: 0; + list-style: none +} + +ul.inline>li, +ol.inline>li { + display: inline-block; + *display: inline; + padding-right: 5px; + padding-left: 5px; + *zoom: 1 +} + +dl { + margin-bottom: 20px +} + +dt, +dd { + line-height: 20px +} + +dt { + font-weight: bold +} + +dd { + margin-left: 10px +} + +.dl-horizontal { + *zoom: 1 +} + +.dl-horizontal:before, +.dl-horizontal:after { + display: table; + line-height: 0; + content: "" +} + +.dl-horizontal:after { + clear: both +} + +.dl-horizontal dt { + float: left; + width: 160px; + overflow: hidden; + clear: left; + text-align: right; + text-overflow: ellipsis; + white-space: nowrap +} + +.dl-horizontal dd { + margin-left: 180px +} + +hr { + margin: 20px 0; + border: 0; + border-top: 1px solid #eee; + border-bottom: 1px solid #fff +} + +abbr[title], +abbr[data-original-title] { + cursor: help; + border-bottom: 1px dotted #999 +} + +abbr.initialism { + font-size: 90%; + text-transform: uppercase +} + +blockquote { + padding: 0 0 0 15px; + margin: 0 0 20px; + border-left: 5px solid #eee +} + +blockquote p { + margin-bottom: 0; + font-size: 17.5px; + font-weight: 300; + line-height: 1.25 +} + +blockquote small { + display: block; + line-height: 20px; + color: #999 +} + +blockquote small:before { + content: '\2014 \00A0' +} + +blockquote.pull-right { + float: right; + padding-right: 15px; + padding-left: 0; + border-right: 5px solid #eee; + border-left: 0 +} + +blockquote.pull-right p, +blockquote.pull-right small { + text-align: right +} + +blockquote.pull-right small:before { + content: '' +} + +blockquote.pull-right small:after { + content: '\00A0 \2014' +} + +q:before, +q:after, +blockquote:before, +blockquote:after { + content: "" +} + +address { + display: block; + margin-bottom: 20px; + font-style: normal; + line-height: 20px +} + +code, +pre { + padding: 0 3px 2px; + font-family: Monaco, Menlo, Consolas, "Courier New", monospace; + font-size: 12px; + color: #333; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px +} + +code { + padding: 2px 4px; + color: #d14; + white-space: nowrap; + background-color: #f7f7f9; + border: 1px solid #e1e1e8 +} + +pre { + display: block; + padding: 9.5px; + margin: 0 0 10px; + font-size: 13px; + line-height: 20px; + word-break: break-all; + word-wrap: break-word; + white-space: pre; + white-space: pre-wrap; + background-color: #f5f5f5; + border: 1px solid #ccc; + border: 1px solid rgba(0, 0, 0, 0.15); + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px +} + +pre.prettyprint { + margin-bottom: 20px +} + +pre code { + padding: 0; + color: inherit; + white-space: pre; + white-space: pre-wrap; + background-color: transparent; + border: 0 +} + +.pre-scrollable { + max-height: 340px; + overflow-y: scroll +} + +form { + margin: 0 0 20px +} + +fieldset { + padding: 0; + margin: 0; + border: 0 +} + +legend { + display: block; + width: 100%; + padding: 0; + margin-bottom: 20px; + font-size: 21px; + line-height: 40px; + color: #333; + border: 0; + border-bottom: 1px solid #e5e5e5 +} + +legend small { + font-size: 15px; + color: #999 +} + +label, +input, +button, +select, +textarea { + font-size: 14px; + font-weight: normal; + line-height: 20px +} + +input, +button, +select, +textarea { + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif +} + +label { + display: block; + margin-bottom: 5px +} + +select, +textarea, +input[type="text"], +input[type="password"], +input[type="datetime"], +input[type="datetime-local"], +input[type="date"], +input[type="month"], +input[type="time"], +input[type="week"], +input[type="number"], +input[type="email"], +input[type="url"], +input[type="search"], +input[type="tel"], +input[type="color"], +.uneditable-input { + display: inline-block; + height: 20px; + padding: 4px 6px; + margin-bottom: 10px; + font-size: 14px; + line-height: 20px; + color: #555; + vertical-align: middle; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px +} + +input, +textarea, +.uneditable-input { + width: 206px +} + +textarea { + height: auto +} + +textarea, +input[type="text"], +input[type="password"], +input[type="datetime"], +input[type="datetime-local"], +input[type="date"], +input[type="month"], +input[type="time"], +input[type="week"], +input[type="number"], +input[type="email"], +input[type="url"], +input[type="search"], +input[type="tel"], +input[type="color"], +.uneditable-input { + background-color: #fff; + border: 1px solid #ccc; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + -webkit-transition: border linear .2s, box-shadow linear .2s; + -moz-transition: border linear .2s, box-shadow linear .2s; + -o-transition: border linear .2s, box-shadow linear .2s; + transition: border linear .2s, box-shadow linear .2s +} + +textarea:focus, +input[type="text"]:focus, +input[type="password"]:focus, +input[type="datetime"]:focus, +input[type="datetime-local"]:focus, +input[type="date"]:focus, +input[type="month"]:focus, +input[type="time"]:focus, +input[type="week"]:focus, +input[type="number"]:focus, +input[type="email"]:focus, +input[type="url"]:focus, +input[type="search"]:focus, +input[type="tel"]:focus, +input[type="color"]:focus, +.uneditable-input:focus { + border-color: rgba(82, 168, 236, 0.8); + outline: 0; + outline: thin dotted \9; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6); + -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6) +} + +input[type="radio"], +input[type="checkbox"] { + margin: 4px 0 0; + margin-top: 1px \9; + *margin-top: 0; + line-height: normal +} + +input[type="file"], +input[type="image"], +input[type="submit"], +input[type="reset"], +input[type="button"], +input[type="radio"], +input[type="checkbox"] { + width: auto +} + +select, +input[type="file"] { + height: 30px; + *margin-top: 4px; + line-height: 30px +} + +select { + width: 220px; + background-color: #fff; + border: 1px solid #ccc +} + +select[multiple], +select[size] { + height: auto +} + +select:focus, +input[type="file"]:focus, +input[type="radio"]:focus, +input[type="checkbox"]:focus { + outline: thin dotted #333; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px +} + +.uneditable-input, +.uneditable-textarea { + color: #999; + cursor: not-allowed; + background-color: #fcfcfc; + border-color: #ccc; + -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025); + -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025); + box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025) +} + +.uneditable-input { + overflow: hidden; + white-space: nowrap +} + +.uneditable-textarea { + width: auto; + height: auto +} + +input:-moz-placeholder, +textarea:-moz-placeholder { + color: #999 +} + +input:-ms-input-placeholder, +textarea:-ms-input-placeholder { + color: #999 +} + +input::-webkit-input-placeholder, +textarea::-webkit-input-placeholder { + color: #999 +} + +.radio, +.checkbox { + min-height: 20px; + padding-left: 20px +} + +.radio input[type="radio"], +.checkbox input[type="checkbox"] { + float: left; + margin-left: -20px +} + +.controls>.radio:first-child, +.controls>.checkbox:first-child { + padding-top: 5px +} + +.radio.inline, +.checkbox.inline { + display: inline-block; + padding-top: 5px; + margin-bottom: 0; + vertical-align: middle +} + +.radio.inline+.radio.inline, +.checkbox.inline+.checkbox.inline { + margin-left: 10px +} + +.input-mini { + width: 60px +} + +.input-small { + width: 90px +} + +.input-medium { + width: 150px +} + +.input-large { + width: 210px +} + +.input-xlarge { + width: 270px +} + +.input-xxlarge { + width: 530px +} + +input[class*="span"], +select[class*="span"], +textarea[class*="span"], +.uneditable-input[class*="span"], +.row-fluid input[class*="span"], +.row-fluid select[class*="span"], +.row-fluid textarea[class*="span"], +.row-fluid .uneditable-input[class*="span"] { + float: none; + margin-left: 0 +} + +.input-append input[class*="span"], +.input-append .uneditable-input[class*="span"], +.input-prepend input[class*="span"], +.input-prepend .uneditable-input[class*="span"], +.row-fluid input[class*="span"], +.row-fluid select[class*="span"], +.row-fluid textarea[class*="span"], +.row-fluid .uneditable-input[class*="span"], +.row-fluid .input-prepend [class*="span"], +.row-fluid .input-append [class*="span"] { + display: inline-block +} + +input, +textarea, +.uneditable-input { + margin-left: 0 +} + +.controls-row [class*="span"]+[class*="span"] { + margin-left: 20px +} + +input.span12, +textarea.span12, +.uneditable-input.span12 { + width: 926px +} + +input.span11, +textarea.span11, +.uneditable-input.span11 { + width: 846px +} + +input.span10, +textarea.span10, +.uneditable-input.span10 { + width: 766px +} + +input.span9, +textarea.span9, +.uneditable-input.span9 { + width: 686px +} + +input.span8, +textarea.span8, +.uneditable-input.span8 { + width: 606px +} + +input.span7, +textarea.span7, +.uneditable-input.span7 { + width: 526px +} + +input.span6, +textarea.span6, +.uneditable-input.span6 { + width: 446px +} + +input.span5, +textarea.span5, +.uneditable-input.span5 { + width: 366px +} + +input.span4, +textarea.span4, +.uneditable-input.span4 { + width: 286px +} + +input.span3, +textarea.span3, +.uneditable-input.span3 { + width: 206px +} + +input.span2, +textarea.span2, +.uneditable-input.span2 { + width: 126px +} + +input.span1, +textarea.span1, +.uneditable-input.span1 { + width: 46px +} + +.controls-row { + *zoom: 1 +} + +.controls-row:before, +.controls-row:after { + display: table; + line-height: 0; + content: "" +} + +.controls-row:after { + clear: both +} + +.controls-row [class*="span"], +.row-fluid .controls-row [class*="span"] { + float: left +} + +.controls-row .checkbox[class*="span"], +.controls-row .radio[class*="span"] { + padding-top: 5px +} + +input[disabled], +select[disabled], +textarea[disabled], +input[readonly], +select[readonly], +textarea[readonly] { + cursor: not-allowed; + background-color: #eee +} + +input[type="radio"][disabled], +input[type="checkbox"][disabled], +input[type="radio"][readonly], +input[type="checkbox"][readonly] { + background-color: transparent +} + +.control-group.warning .control-label, +.control-group.warning .help-block, +.control-group.warning .help-inline { + color: #c09853 +} + +.control-group.warning .checkbox, +.control-group.warning .radio, +.control-group.warning input, +.control-group.warning select, +.control-group.warning textarea { + color: #c09853 +} + +.control-group.warning input, +.control-group.warning select, +.control-group.warning textarea { + border-color: #c09853; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075) +} + +.control-group.warning input:focus, +.control-group.warning select:focus, +.control-group.warning textarea:focus { + border-color: #a47e3c; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e; + -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e +} + +.control-group.warning .input-prepend .add-on, +.control-group.warning .input-append .add-on { + color: #c09853; + background-color: #fcf8e3; + border-color: #c09853 +} + +.control-group.error .control-label, +.control-group.error .help-block, +.control-group.error .help-inline { + color: #b94a48 +} + +.control-group.error .checkbox, +.control-group.error .radio, +.control-group.error input, +.control-group.error select, +.control-group.error textarea { + color: #b94a48 +} + +.control-group.error input, +.control-group.error select, +.control-group.error textarea { + border-color: #b94a48; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075) +} + +.control-group.error input:focus, +.control-group.error select:focus, +.control-group.error textarea:focus { + border-color: #953b39; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392; + -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392 +} + +.control-group.error .input-prepend .add-on, +.control-group.error .input-append .add-on { + color: #b94a48; + background-color: #f2dede; + border-color: #b94a48 +} + +.control-group.success .control-label, +.control-group.success .help-block, +.control-group.success .help-inline { + color: #468847 +} + +.control-group.success .checkbox, +.control-group.success .radio, +.control-group.success input, +.control-group.success select, +.control-group.success textarea { + color: #468847 +} + +.control-group.success input, +.control-group.success select, +.control-group.success textarea { + border-color: #468847; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075) +} + +.control-group.success input:focus, +.control-group.success select:focus, +.control-group.success textarea:focus { + border-color: #356635; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b; + -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b +} + +.control-group.success .input-prepend .add-on, +.control-group.success .input-append .add-on { + color: #468847; + background-color: #dff0d8; + border-color: #468847 +} + +.control-group.info .control-label, +.control-group.info .help-block, +.control-group.info .help-inline { + color: #3a87ad +} + +.control-group.info .checkbox, +.control-group.info .radio, +.control-group.info input, +.control-group.info select, +.control-group.info textarea { + color: #3a87ad +} + +.control-group.info input, +.control-group.info select, +.control-group.info textarea { + border-color: #3a87ad; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075) +} + +.control-group.info input:focus, +.control-group.info select:focus, +.control-group.info textarea:focus { + border-color: #2d6987; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3; + -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3 +} + +.control-group.info .input-prepend .add-on, +.control-group.info .input-append .add-on { + color: #3a87ad; + background-color: #d9edf7; + border-color: #3a87ad +} + +input:focus:invalid, +textarea:focus:invalid, +select:focus:invalid { + color: #b94a48; + border-color: #ee5f5b +} + +input:focus:invalid:focus, +textarea:focus:invalid:focus, +select:focus:invalid:focus { + border-color: #e9322d; + -webkit-box-shadow: 0 0 6px #f8b9b7; + -moz-box-shadow: 0 0 6px #f8b9b7; + box-shadow: 0 0 6px #f8b9b7 +} + +.form-actions { + padding: 19px 20px 20px; + margin-top: 20px; + margin-bottom: 20px; + background-color: #f5f5f5; + border-top: 1px solid #e5e5e5; + *zoom: 1 +} + +.form-actions:before, +.form-actions:after { + display: table; + line-height: 0; + content: "" +} + +.form-actions:after { + clear: both +} + +.help-block, +.help-inline { + color: #595959 +} + +.help-block { + display: block; + margin-bottom: 10px +} + +.help-inline { + display: inline-block; + *display: inline; + padding-left: 5px; + vertical-align: middle; + *zoom: 1 +} + +.input-append, +.input-prepend { + display: inline-block; + margin-bottom: 10px; + font-size: 0; + white-space: nowrap; + vertical-align: middle +} + +.input-append input, +.input-prepend input, +.input-append select, +.input-prepend select, +.input-append .uneditable-input, +.input-prepend .uneditable-input, +.input-append .dropdown-menu, +.input-prepend .dropdown-menu, +.input-append .popover, +.input-prepend .popover { + font-size: 14px +} + +.input-append input, +.input-prepend input, +.input-append select, +.input-prepend select, +.input-append .uneditable-input, +.input-prepend .uneditable-input { + position: relative; + margin-bottom: 0; + *margin-left: 0; + vertical-align: top; + -webkit-border-radius: 0 4px 4px 0; + -moz-border-radius: 0 4px 4px 0; + border-radius: 0 4px 4px 0 +} + +.input-append input:focus, +.input-prepend input:focus, +.input-append select:focus, +.input-prepend select:focus, +.input-append .uneditable-input:focus, +.input-prepend .uneditable-input:focus { + z-index: 2 +} + +.input-append .add-on, +.input-prepend .add-on { + display: inline-block; + width: auto; + height: 20px; + min-width: 16px; + padding: 4px 5px; + font-size: 14px; + font-weight: normal; + line-height: 20px; + text-align: center; + text-shadow: 0 1px 0 #fff; + background-color: #eee; + border: 1px solid #ccc +} + +.input-append .add-on, +.input-prepend .add-on, +.input-append .btn, +.input-prepend .btn, +.input-append .btn-group>.dropdown-toggle, +.input-prepend .btn-group>.dropdown-toggle { + vertical-align: top; + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0 +} + +.input-append .active, +.input-prepend .active { + background-color: #a9dba9; + border-color: #46a546 +} + +.input-prepend .add-on, +.input-prepend .btn { + margin-right: -1px +} + +.input-prepend .add-on:first-child, +.input-prepend .btn:first-child { + -webkit-border-radius: 4px 0 0 4px; + -moz-border-radius: 4px 0 0 4px; + border-radius: 4px 0 0 4px +} + +.input-append input, +.input-append select, +.input-append .uneditable-input { + -webkit-border-radius: 4px 0 0 4px; + -moz-border-radius: 4px 0 0 4px; + border-radius: 4px 0 0 4px +} + +.input-append input+.btn-group .btn:last-child, +.input-append select+.btn-group .btn:last-child, +.input-append .uneditable-input+.btn-group .btn:last-child { + -webkit-border-radius: 0 4px 4px 0; + -moz-border-radius: 0 4px 4px 0; + border-radius: 0 4px 4px 0 +} + +.input-append .add-on, +.input-append .btn, +.input-append .btn-group { + margin-left: -1px +} + +.input-append .add-on:last-child, +.input-append .btn:last-child, +.input-append .btn-group:last-child>.dropdown-toggle { + -webkit-border-radius: 0 4px 4px 0; + -moz-border-radius: 0 4px 4px 0; + border-radius: 0 4px 4px 0 +} + +.input-prepend.input-append input, +.input-prepend.input-append select, +.input-prepend.input-append .uneditable-input { + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0 +} + +.input-prepend.input-append input+.btn-group .btn, +.input-prepend.input-append select+.btn-group .btn, +.input-prepend.input-append .uneditable-input+.btn-group .btn { + -webkit-border-radius: 0 4px 4px 0; + -moz-border-radius: 0 4px 4px 0; + border-radius: 0 4px 4px 0 +} + +.input-prepend.input-append .add-on:first-child, +.input-prepend.input-append .btn:first-child { + margin-right: -1px; + -webkit-border-radius: 4px 0 0 4px; + -moz-border-radius: 4px 0 0 4px; + border-radius: 4px 0 0 4px +} + +.input-prepend.input-append .add-on:last-child, +.input-prepend.input-append .btn:last-child { + margin-left: -1px; + -webkit-border-radius: 0 4px 4px 0; + -moz-border-radius: 0 4px 4px 0; + border-radius: 0 4px 4px 0 +} + +.input-prepend.input-append .btn-group:first-child { + margin-left: 0 +} + +input.search-query { + padding-right: 14px; + padding-right: 4px \9; + padding-left: 14px; + padding-left: 4px \9; + margin-bottom: 0; + -webkit-border-radius: 15px; + -moz-border-radius: 15px; + border-radius: 15px +} + +.form-search .input-append .search-query, +.form-search .input-prepend .search-query { + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0 +} + +.form-search .input-append .search-query { + -webkit-border-radius: 14px 0 0 14px; + -moz-border-radius: 14px 0 0 14px; + border-radius: 14px 0 0 14px +} + +.form-search .input-append .btn { + -webkit-border-radius: 0 14px 14px 0; + -moz-border-radius: 0 14px 14px 0; + border-radius: 0 14px 14px 0 +} + +.form-search .input-prepend .search-query { + -webkit-border-radius: 0 14px 14px 0; + -moz-border-radius: 0 14px 14px 0; + border-radius: 0 14px 14px 0 +} + +.form-search .input-prepend .btn { + -webkit-border-radius: 14px 0 0 14px; + -moz-border-radius: 14px 0 0 14px; + border-radius: 14px 0 0 14px +} + +.form-search input, +.form-inline input, +.form-horizontal input, +.form-search textarea, +.form-inline textarea, +.form-horizontal textarea, +.form-search select, +.form-inline select, +.form-horizontal select, +.form-search .help-inline, +.form-inline .help-inline, +.form-horizontal .help-inline, +.form-search .uneditable-input, +.form-inline .uneditable-input, +.form-horizontal .uneditable-input, +.form-search .input-prepend, +.form-inline .input-prepend, +.form-horizontal .input-prepend, +.form-search .input-append, +.form-inline .input-append, +.form-horizontal .input-append { + display: inline-block; + *display: inline; + margin-bottom: 0; + vertical-align: middle; + *zoom: 1 +} + +.form-search .hide, +.form-inline .hide, +.form-horizontal .hide { + display: none +} + +.form-search label, +.form-inline label, +.form-search .btn-group, +.form-inline .btn-group { + display: inline-block +} + +.form-search .input-append, +.form-inline .input-append, +.form-search .input-prepend, +.form-inline .input-prepend { + margin-bottom: 0 +} + +.form-search .radio, +.form-search .checkbox, +.form-inline .radio, +.form-inline .checkbox { + padding-left: 0; + margin-bottom: 0; + vertical-align: middle +} + +.form-search .radio input[type="radio"], +.form-search .checkbox input[type="checkbox"], +.form-inline .radio input[type="radio"], +.form-inline .checkbox input[type="checkbox"] { + float: left; + margin-right: 3px; + margin-left: 0 +} + +.control-group { + margin-bottom: 10px +} + +legend+.control-group { + margin-top: 20px; + -webkit-margin-top-collapse: separate +} + +.form-horizontal .control-group { + margin-bottom: 20px; + *zoom: 1 +} + +.form-horizontal .control-group:before, +.form-horizontal .control-group:after { + display: table; + line-height: 0; + content: "" +} + +.form-horizontal .control-group:after { + clear: both +} + +.form-horizontal .control-label { + float: left; + width: 160px; + padding-top: 5px; + text-align: right +} + +.form-horizontal .controls { + *display: inline-block; + *padding-left: 20px; + margin-left: 180px; + *margin-left: 0 +} + +.form-horizontal .controls:first-child { + *padding-left: 180px +} + +.form-horizontal .help-block { + margin-bottom: 0 +} + +.form-horizontal input+.help-block, +.form-horizontal select+.help-block, +.form-horizontal textarea+.help-block, +.form-horizontal .uneditable-input+.help-block, +.form-horizontal .input-prepend+.help-block, +.form-horizontal .input-append+.help-block { + margin-top: 10px +} + +.form-horizontal .form-actions { + padding-left: 180px +} + +table { + max-width: 100%; + background-color: transparent; + border-collapse: collapse; + border-spacing: 0 +} + +.table { + width: 100%; + margin-bottom: 20px +} + +.table th, +.table td { + padding: 8px; + line-height: 20px; + text-align: left; + vertical-align: top; + border-top: 1px solid #ddd +} + +.table th { + font-weight: bold +} + +.table thead th { + vertical-align: bottom +} + +.table caption+thead tr:first-child th, +.table caption+thead tr:first-child td, +.table colgroup+thead tr:first-child th, +.table colgroup+thead tr:first-child td, +.table thead:first-child tr:first-child th, +.table thead:first-child tr:first-child td { + border-top: 0 +} + +.table tbody+tbody { + border-top: 2px solid #ddd +} + +.table .table { + background-color: #fff +} + +.table-condensed th, +.table-condensed td { + padding: 4px 5px +} + +.table-bordered { + border: 1px solid #ddd; + border-collapse: separate; + *border-collapse: collapse; + border-left: 0; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px +} + +.table-bordered th, +.table-bordered td { + border-left: 1px solid #ddd +} + +.table-bordered caption+thead tr:first-child th, +.table-bordered caption+tbody tr:first-child th, +.table-bordered caption+tbody tr:first-child td, +.table-bordered colgroup+thead tr:first-child th, +.table-bordered colgroup+tbody tr:first-child th, +.table-bordered colgroup+tbody tr:first-child td, +.table-bordered thead:first-child tr:first-child th, +.table-bordered tbody:first-child tr:first-child th, +.table-bordered tbody:first-child tr:first-child td { + border-top: 0 +} + +.table-bordered thead:first-child tr:first-child>th:first-child, +.table-bordered tbody:first-child tr:first-child>td:first-child, +.table-bordered tbody:first-child tr:first-child>th:first-child { + -webkit-border-top-left-radius: 4px; + border-top-left-radius: 4px; + -moz-border-radius-topleft: 4px +} + +.table-bordered thead:first-child tr:first-child>th:last-child, +.table-bordered tbody:first-child tr:first-child>td:last-child, +.table-bordered tbody:first-child tr:first-child>th:last-child { + -webkit-border-top-right-radius: 4px; + border-top-right-radius: 4px; + -moz-border-radius-topright: 4px +} + +.table-bordered thead:last-child tr:last-child>th:first-child, +.table-bordered tbody:last-child tr:last-child>td:first-child, +.table-bordered tbody:last-child tr:last-child>th:first-child, +.table-bordered tfoot:last-child tr:last-child>td:first-child, +.table-bordered tfoot:last-child tr:last-child>th:first-child { + -webkit-border-bottom-left-radius: 4px; + border-bottom-left-radius: 4px; + -moz-border-radius-bottomleft: 4px +} + +.table-bordered thead:last-child tr:last-child>th:last-child, +.table-bordered tbody:last-child tr:last-child>td:last-child, +.table-bordered tbody:last-child tr:last-child>th:last-child, +.table-bordered tfoot:last-child tr:last-child>td:last-child, +.table-bordered tfoot:last-child tr:last-child>th:last-child { + -webkit-border-bottom-right-radius: 4px; + border-bottom-right-radius: 4px; + -moz-border-radius-bottomright: 4px +} + +.table-bordered tfoot+tbody:last-child tr:last-child td:first-child { + -webkit-border-bottom-left-radius: 0; + border-bottom-left-radius: 0; + -moz-border-radius-bottomleft: 0 +} + +.table-bordered tfoot+tbody:last-child tr:last-child td:last-child { + -webkit-border-bottom-right-radius: 0; + border-bottom-right-radius: 0; + -moz-border-radius-bottomright: 0 +} + +.table-bordered caption+thead tr:first-child th:first-child, +.table-bordered caption+tbody tr:first-child td:first-child, +.table-bordered colgroup+thead tr:first-child th:first-child, +.table-bordered colgroup+tbody tr:first-child td:first-child { + -webkit-border-top-left-radius: 4px; + border-top-left-radius: 4px; + -moz-border-radius-topleft: 4px +} + +.table-bordered caption+thead tr:first-child th:last-child, +.table-bordered caption+tbody tr:first-child td:last-child, +.table-bordered colgroup+thead tr:first-child th:last-child, +.table-bordered colgroup+tbody tr:first-child td:last-child { + -webkit-border-top-right-radius: 4px; + border-top-right-radius: 4px; + -moz-border-radius-topright: 4px +} + +.table-striped tbody>tr:nth-child(odd)>td, +.table-striped tbody>tr:nth-child(odd)>th { + background-color: #f9f9f9 +} + +.table-hover tbody tr:hover>td, +.table-hover tbody tr:hover>th { + background-color: #f5f5f5 +} + +table td[class*="span"], +table th[class*="span"], +.row-fluid table td[class*="span"], +.row-fluid table th[class*="span"] { + display: table-cell; + float: none; + margin-left: 0 +} + +.table td.span1, +.table th.span1 { + float: none; + width: 44px; + margin-left: 0 +} + +.table td.span2, +.table th.span2 { + float: none; + width: 124px; + margin-left: 0 +} + +.table td.span3, +.table th.span3 { + float: none; + width: 204px; + margin-left: 0 +} + +.table td.span4, +.table th.span4 { + float: none; + width: 284px; + margin-left: 0 +} + +.table td.span5, +.table th.span5 { + float: none; + width: 364px; + margin-left: 0 +} + +.table td.span6, +.table th.span6 { + float: none; + width: 444px; + margin-left: 0 +} + +.table td.span7, +.table th.span7 { + float: none; + width: 524px; + margin-left: 0 +} + +.table td.span8, +.table th.span8 { + float: none; + width: 604px; + margin-left: 0 +} + +.table td.span9, +.table th.span9 { + float: none; + width: 684px; + margin-left: 0 +} + +.table td.span10, +.table th.span10 { + float: none; + width: 764px; + margin-left: 0 +} + +.table td.span11, +.table th.span11 { + float: none; + width: 844px; + margin-left: 0 +} + +.table td.span12, +.table th.span12 { + float: none; + width: 924px; + margin-left: 0 +} + +.table tbody tr.success>td { + background-color: #dff0d8 +} + +.table tbody tr.error>td { + background-color: #f2dede +} + +.table tbody tr.warning>td { + background-color: #fcf8e3 +} + +.table tbody tr.info>td { + background-color: #d9edf7 +} + +.table-hover tbody tr.success:hover>td { + background-color: #d0e9c6 +} + +.table-hover tbody tr.error:hover>td { + background-color: #ebcccc +} + +.table-hover tbody tr.warning:hover>td { + background-color: #faf2cc +} + +.table-hover tbody tr.info:hover>td { + background-color: #c4e3f3 +} + +[class^="icon-"], +[class*=" icon-"] { + display: inline-block; + width: 14px; + height: 14px; + margin-top: 1px; + *margin-right: .3em; + line-height: 14px; + vertical-align: text-top; + background-image: url("../img/glyphicons-halflings.png"); + background-position: 14px 14px; + background-repeat: no-repeat +} + +.icon-white, +.nav-pills>.active>a>[class^="icon-"], +.nav-pills>.active>a>[class*=" icon-"], +.nav-list>.active>a>[class^="icon-"], +.nav-list>.active>a>[class*=" icon-"], +.navbar-inverse .nav>.active>a>[class^="icon-"], +.navbar-inverse .nav>.active>a>[class*=" icon-"], +.dropdown-menu>li>a:hover>[class^="icon-"], +.dropdown-menu>li>a:focus>[class^="icon-"], +.dropdown-menu>li>a:hover>[class*=" icon-"], +.dropdown-menu>li>a:focus>[class*=" icon-"], +.dropdown-menu>.active>a>[class^="icon-"], +.dropdown-menu>.active>a>[class*=" icon-"], +.dropdown-submenu:hover>a>[class^="icon-"], +.dropdown-submenu:focus>a>[class^="icon-"], +.dropdown-submenu:hover>a>[class*=" icon-"], +.dropdown-submenu:focus>a>[class*=" icon-"] { + background-image: url("../img/glyphicons-halflings-white.png") +} + +.icon-glass { + background-position: 0 0 +} + +.icon-music { + background-position: -24px 0 +} + +.icon-search { + background-position: -48px 0 +} + +.icon-envelope { + background-position: -72px 0 +} + +.icon-heart { + background-position: -96px 0 +} + +.icon-star { + background-position: -120px 0 +} + +.icon-star-empty { + background-position: -144px 0 +} + +.icon-user { + background-position: -168px 0 +} + +.icon-film { + background-position: -192px 0 +} + +.icon-th-large { + background-position: -216px 0 +} + +.icon-th { + background-position: -240px 0 +} + +.icon-th-list { + background-position: -264px 0 +} + +.icon-ok { + background-position: -288px 0 +} + +.icon-remove { + background-position: -312px 0 +} + +.icon-zoom-in { + background-position: -336px 0 +} + +.icon-zoom-out { + background-position: -360px 0 +} + +.icon-off { + background-position: -384px 0 +} + +.icon-signal { + background-position: -408px 0 +} + +.icon-cog { + background-position: -432px 0 +} + +.icon-trash { + background-position: -456px 0 +} + +.icon-home { + background-position: 0 -24px +} + +.icon-file { + background-position: -24px -24px +} + +.icon-time { + background-position: -48px -24px +} + +.icon-road { + background-position: -72px -24px +} + +.icon-download-alt { + background-position: -96px -24px +} + +.icon-download { + background-position: -120px -24px +} + +.icon-upload { + background-position: -144px -24px +} + +.icon-inbox { + background-position: -168px -24px +} + +.icon-play-circle { + background-position: -192px -24px +} + +.icon-repeat { + background-position: -216px -24px +} + +.icon-refresh { + background-position: -240px -24px +} + +.icon-list-alt { + background-position: -264px -24px +} + +.icon-lock { + background-position: -287px -24px +} + +.icon-flag { + background-position: -312px -24px +} + +.icon-headphones { + background-position: -336px -24px +} + +.icon-volume-off { + background-position: -360px -24px +} + +.icon-volume-down { + background-position: -384px -24px +} + +.icon-volume-up { + background-position: -408px -24px +} + +.icon-qrcode { + background-position: -432px -24px +} + +.icon-barcode { + background-position: -456px -24px +} + +.icon-tag { + background-position: 0 -48px +} + +.icon-tags { + background-position: -25px -48px +} + +.icon-book { + background-position: -48px -48px +} + +.icon-bookmark { + background-position: -72px -48px +} + +.icon-print { + background-position: -96px -48px +} + +.icon-camera { + background-position: -120px -48px +} + +.icon-font { + background-position: -144px -48px +} + +.icon-bold { + background-position: -167px -48px +} + +.icon-italic { + background-position: -192px -48px +} + +.icon-text-height { + background-position: -216px -48px +} + +.icon-text-width { + background-position: -240px -48px +} + +.icon-align-left { + background-position: -264px -48px +} + +.icon-align-center { + background-position: -288px -48px +} + +.icon-align-right { + background-position: -312px -48px +} + +.icon-align-justify { + background-position: -336px -48px +} + +.icon-list { + background-position: -360px -48px +} + +.icon-indent-left { + background-position: -384px -48px +} + +.icon-indent-right { + background-position: -408px -48px +} + +.icon-facetime-video { + background-position: -432px -48px +} + +.icon-picture { + background-position: -456px -48px +} + +.icon-pencil { + background-position: 0 -72px +} + +.icon-map-marker { + background-position: -24px -72px +} + +.icon-adjust { + background-position: -48px -72px +} + +.icon-tint { + background-position: -72px -72px +} + +.icon-edit { + background-position: -96px -72px +} + +.icon-share { + background-position: -120px -72px +} + +.icon-check { + background-position: -144px -72px +} + +.icon-move { + background-position: -168px -72px +} + +.icon-step-backward { + background-position: -192px -72px +} + +.icon-fast-backward { + background-position: -216px -72px +} + +.icon-backward { + background-position: -240px -72px +} + +.icon-play { + background-position: -264px -72px +} + +.icon-pause { + background-position: -288px -72px +} + +.icon-stop { + background-position: -312px -72px +} + +.icon-forward { + background-position: -336px -72px +} + +.icon-fast-forward { + background-position: -360px -72px +} + +.icon-step-forward { + background-position: -384px -72px +} + +.icon-eject { + background-position: -408px -72px +} + +.icon-chevron-left { + background-position: -432px -72px +} + +.icon-chevron-right { + background-position: -456px -72px +} + +.icon-plus-sign { + background-position: 0 -96px +} + +.icon-minus-sign { + background-position: -24px -96px +} + +.icon-remove-sign { + background-position: -48px -96px +} + +.icon-ok-sign { + background-position: -72px -96px +} + +.icon-question-sign { + background-position: -96px -96px +} + +.icon-info-sign { + background-position: -120px -96px +} + +.icon-screenshot { + background-position: -144px -96px +} + +.icon-remove-circle { + background-position: -168px -96px +} + +.icon-ok-circle { + background-position: -192px -96px +} + +.icon-ban-circle { + background-position: -216px -96px +} + +.icon-arrow-left { + background-position: -240px -96px +} + +.icon-arrow-right { + background-position: -264px -96px +} + +.icon-arrow-up { + background-position: -289px -96px +} + +.icon-arrow-down { + background-position: -312px -96px +} + +.icon-share-alt { + background-position: -336px -96px +} + +.icon-resize-full { + background-position: -360px -96px +} + +.icon-resize-small { + background-position: -384px -96px +} + +.icon-plus { + background-position: -408px -96px +} + +.icon-minus { + background-position: -433px -96px +} + +.icon-asterisk { + background-position: -456px -96px +} + +.icon-exclamation-sign { + background-position: 0 -120px +} + +.icon-gift { + background-position: -24px -120px +} + +.icon-leaf { + background-position: -48px -120px +} + +.icon-fire { + background-position: -72px -120px +} + +.icon-eye-open { + background-position: -96px -120px +} + +.icon-eye-close { + background-position: -120px -120px +} + +.icon-warning-sign { + background-position: -144px -120px +} + +.icon-plane { + background-position: -168px -120px +} + +.icon-calendar { + background-position: -192px -120px +} + +.icon-random { + width: 16px; + background-position: -216px -120px +} + +.icon-comment { + background-position: -240px -120px +} + +.icon-magnet { + background-position: -264px -120px +} + +.icon-chevron-up { + background-position: -288px -120px +} + +.icon-chevron-down { + background-position: -313px -119px +} + +.icon-retweet { + background-position: -336px -120px +} + +.icon-shopping-cart { + background-position: -360px -120px +} + +.icon-folder-close { + width: 16px; + background-position: -384px -120px +} + +.icon-folder-open { + width: 16px; + background-position: -408px -120px +} + +.icon-resize-vertical { + background-position: -432px -119px +} + +.icon-resize-horizontal { + background-position: -456px -118px +} + +.icon-hdd { + background-position: 0 -144px +} + +.icon-bullhorn { + background-position: -24px -144px +} + +.icon-bell { + background-position: -48px -144px +} + +.icon-certificate { + background-position: -72px -144px +} + +.icon-thumbs-up { + background-position: -96px -144px +} + +.icon-thumbs-down { + background-position: -120px -144px +} + +.icon-hand-right { + background-position: -144px -144px +} + +.icon-hand-left { + background-position: -168px -144px +} + +.icon-hand-up { + background-position: -192px -144px +} + +.icon-hand-down { + background-position: -216px -144px +} + +.icon-circle-arrow-right { + background-position: -240px -144px +} + +.icon-circle-arrow-left { + background-position: -264px -144px +} + +.icon-circle-arrow-up { + background-position: -288px -144px +} + +.icon-circle-arrow-down { + background-position: -312px -144px +} + +.icon-globe { + background-position: -336px -144px +} + +.icon-wrench { + background-position: -360px -144px +} + +.icon-tasks { + background-position: -384px -144px +} + +.icon-filter { + background-position: -408px -144px +} + +.icon-briefcase { + background-position: -432px -144px +} + +.icon-fullscreen { + background-position: -456px -144px +} + +.dropup, +.dropdown { + position: relative +} + +.dropdown-toggle { + *margin-bottom: -3px +} + +.dropdown-toggle:active, +.open .dropdown-toggle { + outline: 0 +} + +.caret { + display: inline-block; + width: 0; + height: 0; + vertical-align: top; + border-top: 4px solid #000; + border-right: 4px solid transparent; + border-left: 4px solid transparent; + content: "" +} + +.dropdown .caret { + margin-top: 8px; + margin-left: 2px +} + +.dropdown-menu { + position: absolute; + top: 100%; + left: 0; + z-index: 1000; + display: none; + float: left; + min-width: 160px; + padding: 5px 0; + margin: 2px 0 0; + list-style: none; + background-color: #fff; + border: 1px solid #ccc; + border: 1px solid rgba(0, 0, 0, 0.2); + *border-right-width: 2px; + *border-bottom-width: 2px; + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; + -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); + -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); + box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); + -webkit-background-clip: padding-box; + -moz-background-clip: padding; + background-clip: padding-box +} + +.dropdown-menu.pull-right { + right: 0; + left: auto +} + +.dropdown-menu .divider { + *width: 100%; + height: 1px; + margin: 9px 1px; + *margin: -5px 0 5px; + overflow: hidden; + background-color: #e5e5e5; + border-bottom: 1px solid #fff +} + +.dropdown-menu>li>a { + display: block; + padding: 3px 20px; + clear: both; + font-weight: normal; + line-height: 20px; + color: #333; + white-space: nowrap +} + +.dropdown-menu>li>a:hover, +.dropdown-menu>li>a:focus, +.dropdown-submenu:hover>a, +.dropdown-submenu:focus>a { + color: #fff; + text-decoration: none; + background-color: #0081c2; + background-image: -moz-linear-gradient(top, #08c, #0077b3); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#08c), to(#0077b3)); + background-image: -webkit-linear-gradient(top, #08c, #0077b3); + background-image: -o-linear-gradient(top, #08c, #0077b3); + background-image: linear-gradient(to bottom, #08c, #0077b3); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0) +} + +.dropdown-menu>.active>a, +.dropdown-menu>.active>a:hover, +.dropdown-menu>.active>a:focus { + color: #fff; + text-decoration: none; + background-color: #0081c2; + background-image: -moz-linear-gradient(top, #08c, #0077b3); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#08c), to(#0077b3)); + background-image: -webkit-linear-gradient(top, #08c, #0077b3); + background-image: -o-linear-gradient(top, #08c, #0077b3); + background-image: linear-gradient(to bottom, #08c, #0077b3); + background-repeat: repeat-x; + outline: 0; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0) +} + +.dropdown-menu>.disabled>a, +.dropdown-menu>.disabled>a:hover, +.dropdown-menu>.disabled>a:focus { + color: #999 +} + +.dropdown-menu>.disabled>a:hover, +.dropdown-menu>.disabled>a:focus { + text-decoration: none; + cursor: default; + background-color: transparent; + background-image: none; + filter: progid:DXImageTransform.Microsoft.gradient(enabled=false) +} + +.open { + *z-index: 1000 +} + +.open>.dropdown-menu { + display: block +} + +.dropdown-backdrop { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 990 +} + +.pull-right>.dropdown-menu { + right: 0; + left: auto +} + +.dropup .caret, +.navbar-fixed-bottom .dropdown .caret { + border-top: 0; + border-bottom: 4px solid #000; + content: "" +} + +.dropup .dropdown-menu, +.navbar-fixed-bottom .dropdown .dropdown-menu { + top: auto; + bottom: 100%; + margin-bottom: 1px +} + +.dropdown-submenu { + position: relative +} + +.dropdown-submenu>.dropdown-menu { + top: 0; + left: 100%; + margin-top: -6px; + margin-left: -1px; + -webkit-border-radius: 0 6px 6px 6px; + -moz-border-radius: 0 6px 6px 6px; + border-radius: 0 6px 6px 6px +} + +.dropdown-submenu:hover>.dropdown-menu { + display: block +} + +.dropup .dropdown-submenu>.dropdown-menu { + top: auto; + bottom: 0; + margin-top: 0; + margin-bottom: -2px; + -webkit-border-radius: 5px 5px 5px 0; + -moz-border-radius: 5px 5px 5px 0; + border-radius: 5px 5px 5px 0 +} + +.dropdown-submenu>a:after { + display: block; + float: right; + width: 0; + height: 0; + margin-top: 5px; + margin-right: -10px; + border-color: transparent; + border-left-color: #ccc; + border-style: solid; + border-width: 5px 0 5px 5px; + content: " " +} + +.dropdown-submenu:hover>a:after { + border-left-color: #fff +} + +.dropdown-submenu.pull-left { + float: none +} + +.dropdown-submenu.pull-left>.dropdown-menu { + left: -100%; + margin-left: 10px; + -webkit-border-radius: 6px 0 6px 6px; + -moz-border-radius: 6px 0 6px 6px; + border-radius: 6px 0 6px 6px +} + +.dropdown .dropdown-menu .nav-header { + padding-right: 20px; + padding-left: 20px +} + +.typeahead { + z-index: 1051; + margin-top: 2px; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px +} + +.well { + min-height: 20px; + padding: 19px; + margin-bottom: 20px; + background-color: #f5f5f5; + border: 1px solid #e3e3e3; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); + -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05) +} + +.well blockquote { + border-color: #ddd; + border-color: rgba(0, 0, 0, 0.15) +} + +.well-large { + padding: 24px; + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px +} + +.well-small { + padding: 9px; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px +} + +.fade { + opacity: 0; + -webkit-transition: opacity .15s linear; + -moz-transition: opacity .15s linear; + -o-transition: opacity .15s linear; + transition: opacity .15s linear +} + +.fade.in { + opacity: 1 +} + +.collapse { + position: relative; + height: 0; + overflow: hidden; + -webkit-transition: height .35s ease; + -moz-transition: height .35s ease; + -o-transition: height .35s ease; + transition: height .35s ease +} + +.collapse.in { + height: auto +} + +.close { + float: right; + font-size: 20px; + font-weight: bold; + line-height: 20px; + color: #000; + text-shadow: 0 1px 0 #fff; + opacity: .2; + filter: alpha(opacity=20) +} + +.close:hover, +.close:focus { + color: #000; + text-decoration: none; + cursor: pointer; + opacity: .4; + filter: alpha(opacity=40) +} + +button.close { + padding: 0; + cursor: pointer; + background: transparent; + border: 0; + -webkit-appearance: none +} + +.btn { + display: inline-block; + *display: inline; + padding: 4px 12px; + margin-bottom: 0; + *margin-left: .3em; + font-size: 14px; + line-height: 20px; + color: #333; + text-align: center; + text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75); + vertical-align: middle; + cursor: pointer; + background-color: #f5f5f5; + *background-color: #e6e6e6; + background-image: -moz-linear-gradient(top, #fff, #e6e6e6); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fff), to(#e6e6e6)); + background-image: -webkit-linear-gradient(top, #fff, #e6e6e6); + background-image: -o-linear-gradient(top, #fff, #e6e6e6); + background-image: linear-gradient(to bottom, #fff, #e6e6e6); + background-repeat: repeat-x; + border: 1px solid #ccc; + *border: 0; + border-color: #e6e6e6 #e6e6e6 #bfbfbf; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + border-bottom-color: #b3b3b3; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe6e6e6', GradientType=0); + filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); + *zoom: 1; + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); + -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05) +} + +.btn:hover, +.btn:focus, +.btn:active, +.btn.active, +.btn.disabled, +.btn[disabled] { + color: #333; + background-color: #e6e6e6; + *background-color: #d9d9d9 +} + +.btn:active, +.btn.active { + background-color: #ccc \9 +} + +.btn:first-child { + *margin-left: 0 +} + +.btn:hover, +.btn:focus { + color: #333; + text-decoration: none; + background-position: 0 -15px; + -webkit-transition: background-position .1s linear; + -moz-transition: background-position .1s linear; + -o-transition: background-position .1s linear; + transition: background-position .1s linear +} + +.btn:focus { + outline: thin dotted #333; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px +} + +.btn.active, +.btn:active { + background-image: none; + outline: 0; + -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); + -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); + box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05) +} + +.btn.disabled, +.btn[disabled] { + cursor: default; + background-image: none; + opacity: .65; + filter: alpha(opacity=65); + -webkit-box-shadow: none; + -moz-box-shadow: none; + box-shadow: none +} + +.btn-large { + padding: 11px 19px; + font-size: 17.5px; + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px +} + +.btn-large [class^="icon-"], +.btn-large [class*=" icon-"] { + margin-top: 4px +} + +.btn-small { + padding: 2px 10px; + font-size: 11.9px; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px +} + +.btn-small [class^="icon-"], +.btn-small [class*=" icon-"] { + margin-top: 0 +} + +.btn-mini [class^="icon-"], +.btn-mini [class*=" icon-"] { + margin-top: -1px +} + +.btn-mini { + padding: 0 6px; + font-size: 10.5px; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px +} + +.btn-block { + display: block; + width: 100%; + padding-right: 0; + padding-left: 0; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box +} + +.btn-block+.btn-block { + margin-top: 5px +} + +input[type="submit"].btn-block, +input[type="reset"].btn-block, +input[type="button"].btn-block { + width: 100% +} + +.btn-primary.active, +.btn-warning.active, +.btn-danger.active, +.btn-success.active, +.btn-info.active, +.btn-inverse.active { + color: rgba(255, 255, 255, 0.75) +} + +.btn-primary { + color: #fff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + background-color: #006dcc; + *background-color: #04c; + background-image: -moz-linear-gradient(top, #08c, #04c); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#08c), to(#04c)); + background-image: -webkit-linear-gradient(top, #08c, #04c); + background-image: -o-linear-gradient(top, #08c, #04c); + background-image: linear-gradient(to bottom, #08c, #04c); + background-repeat: repeat-x; + border-color: #04c #04c #002a80; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0044cc', GradientType=0); + filter: progid:DXImageTransform.Microsoft.gradient(enabled=false) +} + +.btn-primary:hover, +.btn-primary:focus, +.btn-primary:active, +.btn-primary.active, +.btn-primary.disabled, +.btn-primary[disabled] { + color: #fff; + background-color: #04c; + *background-color: #003bb3 +} + +.btn-primary:active, +.btn-primary.active { + background-color: #039 \9 +} + +.btn-warning { + color: #fff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + background-color: #faa732; + *background-color: #f89406; + background-image: -moz-linear-gradient(top, #fbb450, #f89406); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406)); + background-image: -webkit-linear-gradient(top, #fbb450, #f89406); + background-image: -o-linear-gradient(top, #fbb450, #f89406); + background-image: linear-gradient(to bottom, #fbb450, #f89406); + background-repeat: repeat-x; + border-color: #f89406 #f89406 #ad6704; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0); + filter: progid:DXImageTransform.Microsoft.gradient(enabled=false) +} + +.btn-warning:hover, +.btn-warning:focus, +.btn-warning:active, +.btn-warning.active, +.btn-warning.disabled, +.btn-warning[disabled] { + color: #fff; + background-color: #f89406; + *background-color: #df8505 +} + +.btn-warning:active, +.btn-warning.active { + background-color: #c67605 \9 +} + +.btn-danger { + color: #fff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + background-color: #da4f49; + *background-color: #bd362f; + background-image: -moz-linear-gradient(top, #ee5f5b, #bd362f); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#bd362f)); + background-image: -webkit-linear-gradient(top, #ee5f5b, #bd362f); + background-image: -o-linear-gradient(top, #ee5f5b, #bd362f); + background-image: linear-gradient(to bottom, #ee5f5b, #bd362f); + background-repeat: repeat-x; + border-color: #bd362f #bd362f #802420; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffbd362f', GradientType=0); + filter: progid:DXImageTransform.Microsoft.gradient(enabled=false) +} + +.btn-danger:hover, +.btn-danger:focus, +.btn-danger:active, +.btn-danger.active, +.btn-danger.disabled, +.btn-danger[disabled] { + color: #fff; + background-color: #bd362f; + *background-color: #a9302a +} + +.btn-danger:active, +.btn-danger.active { + background-color: #942a25 \9 +} + +.btn-success { + color: #fff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + background-color: #5bb75b; + *background-color: #51a351; + background-image: -moz-linear-gradient(top, #62c462, #51a351); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#51a351)); + background-image: -webkit-linear-gradient(top, #62c462, #51a351); + background-image: -o-linear-gradient(top, #62c462, #51a351); + background-image: linear-gradient(to bottom, #62c462, #51a351); + background-repeat: repeat-x; + border-color: #51a351 #51a351 #387038; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff51a351', GradientType=0); + filter: progid:DXImageTransform.Microsoft.gradient(enabled=false) +} + +.btn-success:hover, +.btn-success:focus, +.btn-success:active, +.btn-success.active, +.btn-success.disabled, +.btn-success[disabled] { + color: #fff; + background-color: #51a351; + *background-color: #499249 +} + +.btn-success:active, +.btn-success.active { + background-color: #408140 \9 +} + +.btn-info { + color: #fff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + background-color: #49afcd; + *background-color: #2f96b4; + background-image: -moz-linear-gradient(top, #5bc0de, #2f96b4); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#2f96b4)); + background-image: -webkit-linear-gradient(top, #5bc0de, #2f96b4); + background-image: -o-linear-gradient(top, #5bc0de, #2f96b4); + background-image: linear-gradient(to bottom, #5bc0de, #2f96b4); + background-repeat: repeat-x; + border-color: #2f96b4 #2f96b4 #1f6377; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2f96b4', GradientType=0); + filter: progid:DXImageTransform.Microsoft.gradient(enabled=false) +} + +.btn-info:hover, +.btn-info:focus, +.btn-info:active, +.btn-info.active, +.btn-info.disabled, +.btn-info[disabled] { + color: #fff; + background-color: #2f96b4; + *background-color: #2a85a0 +} + +.btn-info:active, +.btn-info.active { + background-color: #24748c \9 +} + +.btn-inverse { + color: #fff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + background-color: #363636; + *background-color: #222; + background-image: -moz-linear-gradient(top, #444, #222); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#444), to(#222)); + background-image: -webkit-linear-gradient(top, #444, #222); + background-image: -o-linear-gradient(top, #444, #222); + background-image: linear-gradient(to bottom, #444, #222); + background-repeat: repeat-x; + border-color: #222 #222 #000; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff444444', endColorstr='#ff222222', GradientType=0); + filter: progid:DXImageTransform.Microsoft.gradient(enabled=false) +} + +.btn-inverse:hover, +.btn-inverse:focus, +.btn-inverse:active, +.btn-inverse.active, +.btn-inverse.disabled, +.btn-inverse[disabled] { + color: #fff; + background-color: #222; + *background-color: #151515 +} + +.btn-inverse:active, +.btn-inverse.active { + background-color: #080808 \9 +} + +button.btn, +input[type="submit"].btn { + *padding-top: 3px; + *padding-bottom: 3px +} + +button.btn::-moz-focus-inner, +input[type="submit"].btn::-moz-focus-inner { + padding: 0; + border: 0 +} + +button.btn.btn-large, +input[type="submit"].btn.btn-large { + *padding-top: 7px; + *padding-bottom: 7px +} + +button.btn.btn-small, +input[type="submit"].btn.btn-small { + *padding-top: 3px; + *padding-bottom: 3px +} + +button.btn.btn-mini, +input[type="submit"].btn.btn-mini { + *padding-top: 1px; + *padding-bottom: 1px +} + +.btn-link, +.btn-link:active, +.btn-link[disabled] { + background-color: transparent; + background-image: none; + -webkit-box-shadow: none; + -moz-box-shadow: none; + box-shadow: none +} + +.btn-link { + color: #08c; + cursor: pointer; + border-color: transparent; + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0 +} + +.btn-link:hover, +.btn-link:focus { + color: #005580; + text-decoration: underline; + background-color: transparent +} + +.btn-link[disabled]:hover, +.btn-link[disabled]:focus { + color: #333; + text-decoration: none +} + +.btn-group { + position: relative; + display: inline-block; + *display: inline; + *margin-left: .3em; + font-size: 0; + white-space: nowrap; + vertical-align: middle; + *zoom: 1 +} + +.btn-group:first-child { + *margin-left: 0 +} + +.btn-group+.btn-group { + margin-left: 5px +} + +.btn-toolbar { + margin-top: 10px; + margin-bottom: 10px; + font-size: 0 +} + +.btn-toolbar>.btn+.btn, +.btn-toolbar>.btn-group+.btn, +.btn-toolbar>.btn+.btn-group { + margin-left: 5px +} + +.btn-group>.btn { + position: relative; + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0 +} + +.btn-group>.btn+.btn { + margin-left: -1px +} + +.btn-group>.btn, +.btn-group>.dropdown-menu, +.btn-group>.popover { + font-size: 14px +} + +.btn-group>.btn-mini { + font-size: 10.5px +} + +.btn-group>.btn-small { + font-size: 11.9px +} + +.btn-group>.btn-large { + font-size: 17.5px +} + +.btn-group>.btn:first-child { + margin-left: 0; + -webkit-border-bottom-left-radius: 4px; + border-bottom-left-radius: 4px; + -webkit-border-top-left-radius: 4px; + border-top-left-radius: 4px; + -moz-border-radius-bottomleft: 4px; + -moz-border-radius-topleft: 4px +} + +.btn-group>.btn:last-child, +.btn-group>.dropdown-toggle { + -webkit-border-top-right-radius: 4px; + border-top-right-radius: 4px; + -webkit-border-bottom-right-radius: 4px; + border-bottom-right-radius: 4px; + -moz-border-radius-topright: 4px; + -moz-border-radius-bottomright: 4px +} + +.btn-group>.btn.large:first-child { + margin-left: 0; + -webkit-border-bottom-left-radius: 6px; + border-bottom-left-radius: 6px; + -webkit-border-top-left-radius: 6px; + border-top-left-radius: 6px; + -moz-border-radius-bottomleft: 6px; + -moz-border-radius-topleft: 6px +} + +.btn-group>.btn.large:last-child, +.btn-group>.large.dropdown-toggle { + -webkit-border-top-right-radius: 6px; + border-top-right-radius: 6px; + -webkit-border-bottom-right-radius: 6px; + border-bottom-right-radius: 6px; + -moz-border-radius-topright: 6px; + -moz-border-radius-bottomright: 6px +} + +.btn-group>.btn:hover, +.btn-group>.btn:focus, +.btn-group>.btn:active, +.btn-group>.btn.active { + z-index: 2 +} + +.btn-group .dropdown-toggle:active, +.btn-group.open .dropdown-toggle { + outline: 0 +} + +.btn-group>.btn+.dropdown-toggle { + *padding-top: 5px; + padding-right: 8px; + *padding-bottom: 5px; + padding-left: 8px; + -webkit-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); + -moz-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); + box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05) +} + +.btn-group>.btn-mini+.dropdown-toggle { + *padding-top: 2px; + padding-right: 5px; + *padding-bottom: 2px; + padding-left: 5px +} + +.btn-group>.btn-small+.dropdown-toggle { + *padding-top: 5px; + *padding-bottom: 4px +} + +.btn-group>.btn-large+.dropdown-toggle { + *padding-top: 7px; + padding-right: 12px; + *padding-bottom: 7px; + padding-left: 12px +} + +.btn-group.open .dropdown-toggle { + background-image: none; + -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); + -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); + box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05) +} + +.btn-group.open .btn.dropdown-toggle { + background-color: #e6e6e6 +} + +.btn-group.open .btn-primary.dropdown-toggle { + background-color: #04c +} + +.btn-group.open .btn-warning.dropdown-toggle { + background-color: #f89406 +} + +.btn-group.open .btn-danger.dropdown-toggle { + background-color: #bd362f +} + +.btn-group.open .btn-success.dropdown-toggle { + background-color: #51a351 +} + +.btn-group.open .btn-info.dropdown-toggle { + background-color: #2f96b4 +} + +.btn-group.open .btn-inverse.dropdown-toggle { + background-color: #222 +} + +.btn .caret { + margin-top: 8px; + margin-left: 0 +} + +.btn-large .caret { + margin-top: 6px +} + +.btn-large .caret { + border-top-width: 5px; + border-right-width: 5px; + border-left-width: 5px +} + +.btn-mini .caret, +.btn-small .caret { + margin-top: 8px +} + +.dropup .btn-large .caret { + border-bottom-width: 5px +} + +.btn-primary .caret, +.btn-warning .caret, +.btn-danger .caret, +.btn-info .caret, +.btn-success .caret, +.btn-inverse .caret { + border-top-color: #fff; + border-bottom-color: #fff +} + +.btn-group-vertical { + display: inline-block; + *display: inline; + *zoom: 1 +} + +.btn-group-vertical>.btn { + display: block; + float: none; + max-width: 100%; + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0 +} + +.btn-group-vertical>.btn+.btn { + margin-top: -1px; + margin-left: 0 +} + +.btn-group-vertical>.btn:first-child { + -webkit-border-radius: 4px 4px 0 0; + -moz-border-radius: 4px 4px 0 0; + border-radius: 4px 4px 0 0 +} + +.btn-group-vertical>.btn:last-child { + -webkit-border-radius: 0 0 4px 4px; + -moz-border-radius: 0 0 4px 4px; + border-radius: 0 0 4px 4px +} + +.btn-group-vertical>.btn-large:first-child { + -webkit-border-radius: 6px 6px 0 0; + -moz-border-radius: 6px 6px 0 0; + border-radius: 6px 6px 0 0 +} + +.btn-group-vertical>.btn-large:last-child { + -webkit-border-radius: 0 0 6px 6px; + -moz-border-radius: 0 0 6px 6px; + border-radius: 0 0 6px 6px +} + +.alert { + padding: 8px 35px 8px 14px; + margin-bottom: 20px; + text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); + background-color: #fcf8e3; + border: 1px solid #fbeed5; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px +} + +.alert, +.alert h4 { + color: #c09853 +} + +.alert h4 { + margin: 0 +} + +.alert .close { + position: relative; + top: -2px; + right: -21px; + line-height: 20px +} + +.alert-success { + color: #468847; + background-color: #dff0d8; + border-color: #d6e9c6 +} + +.alert-success h4 { + color: #468847 +} + +.alert-danger, +.alert-error { + color: #b94a48; + background-color: #f2dede; + border-color: #eed3d7 +} + +.alert-danger h4, +.alert-error h4 { + color: #b94a48 +} + +.alert-info { + color: #3a87ad; + background-color: #d9edf7; + border-color: #bce8f1 +} + +.alert-info h4 { + color: #3a87ad +} + +.alert-block { + padding-top: 14px; + padding-bottom: 14px +} + +.alert-block>p, +.alert-block>ul { + margin-bottom: 0 +} + +.alert-block p+p { + margin-top: 5px +} + +.nav { + margin-bottom: 20px; + margin-left: 0; + list-style: none +} + +.nav>li>a { + display: block +} + +.nav>li>a:hover, +.nav>li>a:focus { + text-decoration: none; + background-color: #eee +} + +.nav>li>a>img { + max-width: none +} + +.nav>.pull-right { + float: right +} + +.nav-header { + display: block; + padding: 3px 15px; + font-size: 11px; + font-weight: bold; + line-height: 20px; + color: #999; + text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); + text-transform: uppercase +} + +.nav li+.nav-header { + margin-top: 9px +} + +.nav-list { + padding-right: 15px; + padding-left: 15px; + margin-bottom: 0 +} + +.nav-list>li>a, +.nav-list .nav-header { + margin-right: -15px; + margin-left: -15px; + text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5) +} + +.nav-list>li>a { + padding: 3px 15px +} + +.nav-list>.active>a, +.nav-list>.active>a:hover, +.nav-list>.active>a:focus { + color: #fff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2); + background-color: #08c +} + +.nav-list [class^="icon-"], +.nav-list [class*=" icon-"] { + margin-right: 2px +} + +.nav-list .divider { + *width: 100%; + height: 1px; + margin: 9px 1px; + *margin: -5px 0 5px; + overflow: hidden; + background-color: #e5e5e5; + border-bottom: 1px solid #fff +} + +.nav-tabs, +.nav-pills { + *zoom: 1 +} + +.nav-tabs:before, +.nav-pills:before, +.nav-tabs:after, +.nav-pills:after { + display: table; + line-height: 0; + content: "" +} + +.nav-tabs:after, +.nav-pills:after { + clear: both +} + +.nav-tabs>li, +.nav-pills>li { + float: left +} + +.nav-tabs>li>a, +.nav-pills>li>a { + padding-right: 12px; + padding-left: 12px; + margin-right: 2px; + line-height: 14px +} + +.nav-tabs { + border-bottom: 1px solid #ddd +} + +.nav-tabs>li { + margin-bottom: -1px +} + +.nav-tabs>li>a { + padding-top: 8px; + padding-bottom: 8px; + line-height: 20px; + border: 1px solid transparent; + -webkit-border-radius: 4px 4px 0 0; + -moz-border-radius: 4px 4px 0 0; + border-radius: 4px 4px 0 0 +} + +.nav-tabs>li>a:hover, +.nav-tabs>li>a:focus { + border-color: #eee #eee #ddd +} + +.nav-tabs>.active>a, +.nav-tabs>.active>a:hover, +.nav-tabs>.active>a:focus { + color: #555; + cursor: default; + background-color: #fff; + border: 1px solid #ddd; + border-bottom-color: transparent +} + +.nav-pills>li>a { + padding-top: 8px; + padding-bottom: 8px; + margin-top: 2px; + margin-bottom: 2px; + -webkit-border-radius: 5px; + -moz-border-radius: 5px; + border-radius: 5px +} + +.nav-pills>.active>a, +.nav-pills>.active>a:hover, +.nav-pills>.active>a:focus { + color: #fff; + background-color: #08c +} + +.nav-stacked>li { + float: none +} + +.nav-stacked>li>a { + margin-right: 0 +} + +.nav-tabs.nav-stacked { + border-bottom: 0 +} + +.nav-tabs.nav-stacked>li>a { + border: 1px solid #ddd; + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0 +} + +.nav-tabs.nav-stacked>li:first-child>a { + -webkit-border-top-right-radius: 4px; + border-top-right-radius: 4px; + -webkit-border-top-left-radius: 4px; + border-top-left-radius: 4px; + -moz-border-radius-topright: 4px; + -moz-border-radius-topleft: 4px +} + +.nav-tabs.nav-stacked>li:last-child>a { + -webkit-border-bottom-right-radius: 4px; + border-bottom-right-radius: 4px; + -webkit-border-bottom-left-radius: 4px; + border-bottom-left-radius: 4px; + -moz-border-radius-bottomright: 4px; + -moz-border-radius-bottomleft: 4px +} + +.nav-tabs.nav-stacked>li>a:hover, +.nav-tabs.nav-stacked>li>a:focus { + z-index: 2; + border-color: #ddd +} + +.nav-pills.nav-stacked>li>a { + margin-bottom: 3px +} + +.nav-pills.nav-stacked>li:last-child>a { + margin-bottom: 1px +} + +.nav-tabs .dropdown-menu { + -webkit-border-radius: 0 0 6px 6px; + -moz-border-radius: 0 0 6px 6px; + border-radius: 0 0 6px 6px +} + +.nav-pills .dropdown-menu { + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px +} + +.nav .dropdown-toggle .caret { + margin-top: 6px; + border-top-color: #08c; + border-bottom-color: #08c +} + +.nav .dropdown-toggle:hover .caret, +.nav .dropdown-toggle:focus .caret { + border-top-color: #005580; + border-bottom-color: #005580 +} + +.nav-tabs .dropdown-toggle .caret { + margin-top: 8px +} + +.nav .active .dropdown-toggle .caret { + border-top-color: #fff; + border-bottom-color: #fff +} + +.nav-tabs .active .dropdown-toggle .caret { + border-top-color: #555; + border-bottom-color: #555 +} + +.nav>.dropdown.active>a:hover, +.nav>.dropdown.active>a:focus { + cursor: pointer +} + +.nav-tabs .open .dropdown-toggle, +.nav-pills .open .dropdown-toggle, +.nav>li.dropdown.open.active>a:hover, +.nav>li.dropdown.open.active>a:focus { + color: #fff; + background-color: #999; + border-color: #999 +} + +.nav li.dropdown.open .caret, +.nav li.dropdown.open.active .caret, +.nav li.dropdown.open a:hover .caret, +.nav li.dropdown.open a:focus .caret { + border-top-color: #fff; + border-bottom-color: #fff; + opacity: 1; + filter: alpha(opacity=100) +} + +.tabs-stacked .open>a:hover, +.tabs-stacked .open>a:focus { + border-color: #999 +} + +.tabbable { + *zoom: 1 +} + +.tabbable:before, +.tabbable:after { + display: table; + line-height: 0; + content: "" +} + +.tabbable:after { + clear: both +} + +.tab-content { + overflow: auto +} + +.tabs-below>.nav-tabs, +.tabs-right>.nav-tabs, +.tabs-left>.nav-tabs { + border-bottom: 0 +} + +.tab-content>.tab-pane, +.pill-content>.pill-pane { + display: none +} + +.tab-content>.active, +.pill-content>.active { + display: block +} + +.tabs-below>.nav-tabs { + border-top: 1px solid #ddd +} + +.tabs-below>.nav-tabs>li { + margin-top: -1px; + margin-bottom: 0 +} + +.tabs-below>.nav-tabs>li>a { + -webkit-border-radius: 0 0 4px 4px; + -moz-border-radius: 0 0 4px 4px; + border-radius: 0 0 4px 4px +} + +.tabs-below>.nav-tabs>li>a:hover, +.tabs-below>.nav-tabs>li>a:focus { + border-top-color: #ddd; + border-bottom-color: transparent +} + +.tabs-below>.nav-tabs>.active>a, +.tabs-below>.nav-tabs>.active>a:hover, +.tabs-below>.nav-tabs>.active>a:focus { + border-color: transparent #ddd #ddd #ddd +} + +.tabs-left>.nav-tabs>li, +.tabs-right>.nav-tabs>li { + float: none +} + +.tabs-left>.nav-tabs>li>a, +.tabs-right>.nav-tabs>li>a { + min-width: 74px; + margin-right: 0; + margin-bottom: 3px +} + +.tabs-left>.nav-tabs { + float: left; + margin-right: 19px; + border-right: 1px solid #ddd +} + +.tabs-left>.nav-tabs>li>a { + margin-right: -1px; + -webkit-border-radius: 4px 0 0 4px; + -moz-border-radius: 4px 0 0 4px; + border-radius: 4px 0 0 4px +} + +.tabs-left>.nav-tabs>li>a:hover, +.tabs-left>.nav-tabs>li>a:focus { + border-color: #eee #ddd #eee #eee +} + +.tabs-left>.nav-tabs .active>a, +.tabs-left>.nav-tabs .active>a:hover, +.tabs-left>.nav-tabs .active>a:focus { + border-color: #ddd transparent #ddd #ddd; + *border-right-color: #fff +} + +.tabs-right>.nav-tabs { + float: right; + margin-left: 19px; + border-left: 1px solid #ddd +} + +.tabs-right>.nav-tabs>li>a { + margin-left: -1px; + -webkit-border-radius: 0 4px 4px 0; + -moz-border-radius: 0 4px 4px 0; + border-radius: 0 4px 4px 0 +} + +.tabs-right>.nav-tabs>li>a:hover, +.tabs-right>.nav-tabs>li>a:focus { + border-color: #eee #eee #eee #ddd +} + +.tabs-right>.nav-tabs .active>a, +.tabs-right>.nav-tabs .active>a:hover, +.tabs-right>.nav-tabs .active>a:focus { + border-color: #ddd #ddd #ddd transparent; + *border-left-color: #fff +} + +.nav>.disabled>a { + color: #999 +} + +.nav>.disabled>a:hover, +.nav>.disabled>a:focus { + text-decoration: none; + cursor: default; + background-color: transparent +} + +.navbar { + *position: relative; + *z-index: 2; + margin-bottom: 20px; + overflow: visible +} + +.navbar-inner { + min-height: 40px; + padding-right: 20px; + padding-left: 20px; + background-color: #fafafa; + background-image: -moz-linear-gradient(top, #fff, #f2f2f2); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fff), to(#f2f2f2)); + background-image: -webkit-linear-gradient(top, #fff, #f2f2f2); + background-image: -o-linear-gradient(top, #fff, #f2f2f2); + background-image: linear-gradient(to bottom, #fff, #f2f2f2); + background-repeat: repeat-x; + border: 1px solid #d4d4d4; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff2f2f2', GradientType=0); + *zoom: 1; + -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065); + -moz-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065); + box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065) +} + +.navbar-inner:before, +.navbar-inner:after { + display: table; + line-height: 0; + content: "" +} + +.navbar-inner:after { + clear: both +} + +.navbar .container { + width: auto +} + +.nav-collapse.collapse { + height: auto; + overflow: visible +} + +.navbar .brand { + display: block; + float: left; + padding: 10px 20px 10px; + margin-left: -20px; + font-size: 20px; + font-weight: 200; + color: #777; + text-shadow: 0 1px 0 #fff +} + +.navbar .brand:hover, +.navbar .brand:focus { + text-decoration: none +} + +.navbar-text { + margin-bottom: 0; + line-height: 40px; + color: #777 +} + +.navbar-link { + color: #777 +} + +.navbar-link:hover, +.navbar-link:focus { + color: #333 +} + +.navbar .divider-vertical { + height: 40px; + margin: 0 9px; + border-right: 1px solid #fff; + border-left: 1px solid #f2f2f2 +} + +.navbar .btn, +.navbar .btn-group { + margin-top: 5px +} + +.navbar .btn-group .btn, +.navbar .input-prepend .btn, +.navbar .input-append .btn, +.navbar .input-prepend .btn-group, +.navbar .input-append .btn-group { + margin-top: 0 +} + +.navbar-form { + margin-bottom: 0; + *zoom: 1 +} + +.navbar-form:before, +.navbar-form:after { + display: table; + line-height: 0; + content: "" +} + +.navbar-form:after { + clear: both +} + +.navbar-form input, +.navbar-form select, +.navbar-form .radio, +.navbar-form .checkbox { + margin-top: 5px +} + +.navbar-form input, +.navbar-form select, +.navbar-form .btn { + display: inline-block; + margin-bottom: 0 +} + +.navbar-form input[type="image"], +.navbar-form input[type="checkbox"], +.navbar-form input[type="radio"] { + margin-top: 3px +} + +.navbar-form .input-append, +.navbar-form .input-prepend { + margin-top: 5px; + white-space: nowrap +} + +.navbar-form .input-append input, +.navbar-form .input-prepend input { + margin-top: 0 +} + +.navbar-search { + position: relative; + float: left; + margin-top: 5px; + margin-bottom: 0 +} + +.navbar-search .search-query { + padding: 4px 14px; + margin-bottom: 0; + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 13px; + font-weight: normal; + line-height: 1; + -webkit-border-radius: 15px; + -moz-border-radius: 15px; + border-radius: 15px +} + +.navbar-static-top { + position: static; + margin-bottom: 0 +} + +.navbar-static-top .navbar-inner { + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0 +} + +.navbar-fixed-top, +.navbar-fixed-bottom { + position: fixed; + right: 0; + left: 0; + z-index: 1030; + margin-bottom: 0 +} + +.navbar-fixed-top .navbar-inner, +.navbar-static-top .navbar-inner { + border-width: 0 0 1px +} + +.navbar-fixed-bottom .navbar-inner { + border-width: 1px 0 0 +} + +.navbar-fixed-top .navbar-inner, +.navbar-fixed-bottom .navbar-inner { + padding-right: 0; + padding-left: 0; + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0 +} + +.navbar-static-top .container, +.navbar-fixed-top .container, +.navbar-fixed-bottom .container { + width: 940px +} + +.navbar-fixed-top { + top: 0 +} + +.navbar-fixed-top .navbar-inner, +.navbar-static-top .navbar-inner { + -webkit-box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1); + -moz-box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1); + box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1) +} + +.navbar-fixed-bottom { + bottom: 0 +} + +.navbar-fixed-bottom .navbar-inner { + -webkit-box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1); + -moz-box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1); + box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1) +} + +.navbar .nav { + position: relative; + left: 0; + display: block; + float: left; + margin: 0 10px 0 0 +} + +.navbar .nav.pull-right { + float: right; + margin-right: 0 +} + +.navbar .nav>li { + float: left +} + +.navbar .nav>li>a { + float: none; + padding: 10px 15px 10px; + color: #777; + text-decoration: none; + text-shadow: 0 1px 0 #fff +} + +.navbar .nav .dropdown-toggle .caret { + margin-top: 8px +} + +.navbar .nav>li>a:focus, +.navbar .nav>li>a:hover { + color: #333; + text-decoration: none; + background-color: transparent +} + +.navbar .nav>.active>a, +.navbar .nav>.active>a:hover, +.navbar .nav>.active>a:focus { + color: #555; + text-decoration: none; + background-color: #e5e5e5; + -webkit-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125); + -moz-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125); + box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125) +} + +.navbar .btn-navbar { + display: none; + float: right; + padding: 7px 10px; + margin-right: 5px; + margin-left: 5px; + color: #fff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + background-color: #ededed; + *background-color: #e5e5e5; + background-image: -moz-linear-gradient(top, #f2f2f2, #e5e5e5); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f2f2f2), to(#e5e5e5)); + background-image: -webkit-linear-gradient(top, #f2f2f2, #e5e5e5); + background-image: -o-linear-gradient(top, #f2f2f2, #e5e5e5); + background-image: linear-gradient(to bottom, #f2f2f2, #e5e5e5); + background-repeat: repeat-x; + border-color: #e5e5e5 #e5e5e5 #bfbfbf; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2f2f2', endColorstr='#ffe5e5e5', GradientType=0); + filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075); + -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075) +} + +.navbar .btn-navbar:hover, +.navbar .btn-navbar:focus, +.navbar .btn-navbar:active, +.navbar .btn-navbar.active, +.navbar .btn-navbar.disabled, +.navbar .btn-navbar[disabled] { + color: #fff; + background-color: #e5e5e5; + *background-color: #d9d9d9 +} + +.navbar .btn-navbar:active, +.navbar .btn-navbar.active { + background-color: #ccc \9 +} + +.navbar .btn-navbar .icon-bar { + display: block; + width: 18px; + height: 2px; + background-color: #f5f5f5; + -webkit-border-radius: 1px; + -moz-border-radius: 1px; + border-radius: 1px; + -webkit-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25); + -moz-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25); + box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25) +} + +.btn-navbar .icon-bar+.icon-bar { + margin-top: 3px +} + +.navbar .nav>li>.dropdown-menu:before { + position: absolute; + top: -7px; + left: 9px; + display: inline-block; + border-right: 7px solid transparent; + border-bottom: 7px solid #ccc; + border-left: 7px solid transparent; + border-bottom-color: rgba(0, 0, 0, 0.2); + content: '' +} + +.navbar .nav>li>.dropdown-menu:after { + position: absolute; + top: -6px; + left: 10px; + display: inline-block; + border-right: 6px solid transparent; + border-bottom: 6px solid #fff; + border-left: 6px solid transparent; + content: '' +} + +.navbar-fixed-bottom .nav>li>.dropdown-menu:before { + top: auto; + bottom: -7px; + border-top: 7px solid #ccc; + border-bottom: 0; + border-top-color: rgba(0, 0, 0, 0.2) +} + +.navbar-fixed-bottom .nav>li>.dropdown-menu:after { + top: auto; + bottom: -6px; + border-top: 6px solid #fff; + border-bottom: 0 +} + +.navbar .nav li.dropdown>a:hover .caret, +.navbar .nav li.dropdown>a:focus .caret { + border-top-color: #333; + border-bottom-color: #333 +} + +.navbar .nav li.dropdown.open>.dropdown-toggle, +.navbar .nav li.dropdown.active>.dropdown-toggle, +.navbar .nav li.dropdown.open.active>.dropdown-toggle { + color: #555; + background-color: #e5e5e5 +} + +.navbar .nav li.dropdown>.dropdown-toggle .caret { + border-top-color: #777; + border-bottom-color: #777 +} + +.navbar .nav li.dropdown.open>.dropdown-toggle .caret, +.navbar .nav li.dropdown.active>.dropdown-toggle .caret, +.navbar .nav li.dropdown.open.active>.dropdown-toggle .caret { + border-top-color: #555; + border-bottom-color: #555 +} + +.navbar .pull-right>li>.dropdown-menu, +.navbar .nav>li>.dropdown-menu.pull-right { + right: 0; + left: auto +} + +.navbar .pull-right>li>.dropdown-menu:before, +.navbar .nav>li>.dropdown-menu.pull-right:before { + right: 12px; + left: auto +} + +.navbar .pull-right>li>.dropdown-menu:after, +.navbar .nav>li>.dropdown-menu.pull-right:after { + right: 13px; + left: auto +} + +.navbar .pull-right>li>.dropdown-menu .dropdown-menu, +.navbar .nav>li>.dropdown-menu.pull-right .dropdown-menu { + right: 100%; + left: auto; + margin-right: -1px; + margin-left: 0; + -webkit-border-radius: 6px 0 6px 6px; + -moz-border-radius: 6px 0 6px 6px; + border-radius: 6px 0 6px 6px +} + +.navbar-inverse .navbar-inner { + background-color: #1b1b1b; + background-image: -moz-linear-gradient(top, #222, #111); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#222), to(#111)); + background-image: -webkit-linear-gradient(top, #222, #111); + background-image: -o-linear-gradient(top, #222, #111); + background-image: linear-gradient(to bottom, #222, #111); + background-repeat: repeat-x; + border-color: #252525; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff111111', GradientType=0) +} + +.navbar-inverse .brand, +.navbar-inverse .nav>li>a { + color: #999; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25) +} + +.navbar-inverse .brand:hover, +.navbar-inverse .nav>li>a:hover, +.navbar-inverse .brand:focus, +.navbar-inverse .nav>li>a:focus { + color: #fff +} + +.navbar-inverse .brand { + color: #999 +} + +.navbar-inverse .navbar-text { + color: #999 +} + +.navbar-inverse .nav>li>a:focus, +.navbar-inverse .nav>li>a:hover { + color: #fff; + background-color: transparent +} + +.navbar-inverse .nav .active>a, +.navbar-inverse .nav .active>a:hover, +.navbar-inverse .nav .active>a:focus { + color: #fff; + background-color: #111 +} + +.navbar-inverse .navbar-link { + color: #999 +} + +.navbar-inverse .navbar-link:hover, +.navbar-inverse .navbar-link:focus { + color: #fff +} + +.navbar-inverse .divider-vertical { + border-right-color: #222; + border-left-color: #111 +} + +.navbar-inverse .nav li.dropdown.open>.dropdown-toggle, +.navbar-inverse .nav li.dropdown.active>.dropdown-toggle, +.navbar-inverse .nav li.dropdown.open.active>.dropdown-toggle { + color: #fff; + background-color: #111 +} + +.navbar-inverse .nav li.dropdown>a:hover .caret, +.navbar-inverse .nav li.dropdown>a:focus .caret { + border-top-color: #fff; + border-bottom-color: #fff +} + +.navbar-inverse .nav li.dropdown>.dropdown-toggle .caret { + border-top-color: #999; + border-bottom-color: #999 +} + +.navbar-inverse .nav li.dropdown.open>.dropdown-toggle .caret, +.navbar-inverse .nav li.dropdown.active>.dropdown-toggle .caret, +.navbar-inverse .nav li.dropdown.open.active>.dropdown-toggle .caret { + border-top-color: #fff; + border-bottom-color: #fff +} + +.navbar-inverse .navbar-search .search-query { + color: #fff; + background-color: #515151; + border-color: #111; + -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15); + -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15); + box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15); + -webkit-transition: none; + -moz-transition: none; + -o-transition: none; + transition: none +} + +.navbar-inverse .navbar-search .search-query:-moz-placeholder { + color: #ccc +} + +.navbar-inverse .navbar-search .search-query:-ms-input-placeholder { + color: #ccc +} + +.navbar-inverse .navbar-search .search-query::-webkit-input-placeholder { + color: #ccc +} + +.navbar-inverse .navbar-search .search-query:focus, +.navbar-inverse .navbar-search .search-query.focused { + padding: 5px 15px; + color: #333; + text-shadow: 0 1px 0 #fff; + background-color: #fff; + border: 0; + outline: 0; + -webkit-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15); + -moz-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15); + box-shadow: 0 0 3px rgba(0, 0, 0, 0.15) +} + +.navbar-inverse .btn-navbar { + color: #fff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + background-color: #0e0e0e; + *background-color: #040404; + background-image: -moz-linear-gradient(top, #151515, #040404); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#151515), to(#040404)); + background-image: -webkit-linear-gradient(top, #151515, #040404); + background-image: -o-linear-gradient(top, #151515, #040404); + background-image: linear-gradient(to bottom, #151515, #040404); + background-repeat: repeat-x; + border-color: #040404 #040404 #000; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff151515', endColorstr='#ff040404', GradientType=0); + filter: progid:DXImageTransform.Microsoft.gradient(enabled=false) +} + +.navbar-inverse .btn-navbar:hover, +.navbar-inverse .btn-navbar:focus, +.navbar-inverse .btn-navbar:active, +.navbar-inverse .btn-navbar.active, +.navbar-inverse .btn-navbar.disabled, +.navbar-inverse .btn-navbar[disabled] { + color: #fff; + background-color: #040404; + *background-color: #000 +} + +.navbar-inverse .btn-navbar:active, +.navbar-inverse .btn-navbar.active { + background-color: #000 \9 +} + +.breadcrumb { + padding: 8px 15px; + margin: 0 0 20px; + list-style: none; + background-color: #f5f5f5; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px +} + +.breadcrumb>li { + display: inline-block; + *display: inline; + text-shadow: 0 1px 0 #fff; + *zoom: 1 +} + +.breadcrumb>li>.divider { + padding: 0 5px; + color: #ccc +} + +.breadcrumb>.active { + color: #999 +} + +.pagination { + margin: 20px 0 +} + +.pagination ul { + display: inline-block; + *display: inline; + margin-bottom: 0; + margin-left: 0; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + *zoom: 1; + -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); + -moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05) +} + +.pagination ul>li { + display: inline +} + +.pagination ul>li>a, +.pagination ul>li>span { + float: left; + padding: 4px 12px; + line-height: 20px; + text-decoration: none; + background-color: #fff; + border: 1px solid #ddd; + border-left-width: 0 +} + +.pagination ul>li>a:hover, +.pagination ul>li>a:focus, +.pagination ul>.active>a, +.pagination ul>.active>span { + background-color: #f5f5f5 +} + +.pagination ul>.active>a, +.pagination ul>.active>span { + color: #999; + cursor: default +} + +.pagination ul>.disabled>span, +.pagination ul>.disabled>a, +.pagination ul>.disabled>a:hover, +.pagination ul>.disabled>a:focus { + color: #999; + cursor: default; + background-color: transparent +} + +.pagination ul>li:first-child>a, +.pagination ul>li:first-child>span { + border-left-width: 1px; + -webkit-border-bottom-left-radius: 4px; + border-bottom-left-radius: 4px; + -webkit-border-top-left-radius: 4px; + border-top-left-radius: 4px; + -moz-border-radius-bottomleft: 4px; + -moz-border-radius-topleft: 4px +} + +.pagination ul>li:last-child>a, +.pagination ul>li:last-child>span { + -webkit-border-top-right-radius: 4px; + border-top-right-radius: 4px; + -webkit-border-bottom-right-radius: 4px; + border-bottom-right-radius: 4px; + -moz-border-radius-topright: 4px; + -moz-border-radius-bottomright: 4px +} + +.pagination-centered { + text-align: center +} + +.pagination-right { + text-align: right +} + +.pagination-large ul>li>a, +.pagination-large ul>li>span { + padding: 11px 19px; + font-size: 17.5px +} + +.pagination-large ul>li:first-child>a, +.pagination-large ul>li:first-child>span { + -webkit-border-bottom-left-radius: 6px; + border-bottom-left-radius: 6px; + -webkit-border-top-left-radius: 6px; + border-top-left-radius: 6px; + -moz-border-radius-bottomleft: 6px; + -moz-border-radius-topleft: 6px +} + +.pagination-large ul>li:last-child>a, +.pagination-large ul>li:last-child>span { + -webkit-border-top-right-radius: 6px; + border-top-right-radius: 6px; + -webkit-border-bottom-right-radius: 6px; + border-bottom-right-radius: 6px; + -moz-border-radius-topright: 6px; + -moz-border-radius-bottomright: 6px +} + +.pagination-mini ul>li:first-child>a, +.pagination-small ul>li:first-child>a, +.pagination-mini ul>li:first-child>span, +.pagination-small ul>li:first-child>span { + -webkit-border-bottom-left-radius: 3px; + border-bottom-left-radius: 3px; + -webkit-border-top-left-radius: 3px; + border-top-left-radius: 3px; + -moz-border-radius-bottomleft: 3px; + -moz-border-radius-topleft: 3px +} + +.pagination-mini ul>li:last-child>a, +.pagination-small ul>li:last-child>a, +.pagination-mini ul>li:last-child>span, +.pagination-small ul>li:last-child>span { + -webkit-border-top-right-radius: 3px; + border-top-right-radius: 3px; + -webkit-border-bottom-right-radius: 3px; + border-bottom-right-radius: 3px; + -moz-border-radius-topright: 3px; + -moz-border-radius-bottomright: 3px +} + +.pagination-small ul>li>a, +.pagination-small ul>li>span { + padding: 2px 10px; + font-size: 11.9px +} + +.pagination-mini ul>li>a, +.pagination-mini ul>li>span { + padding: 0 6px; + font-size: 10.5px +} + +.pager { + margin: 20px 0; + text-align: center; + list-style: none; + *zoom: 1 +} + +.pager:before, +.pager:after { + display: table; + line-height: 0; + content: "" +} + +.pager:after { + clear: both +} + +.pager li { + display: inline +} + +.pager li>a, +.pager li>span { + display: inline-block; + padding: 5px 14px; + background-color: #fff; + border: 1px solid #ddd; + -webkit-border-radius: 15px; + -moz-border-radius: 15px; + border-radius: 15px +} + +.pager li>a:hover, +.pager li>a:focus { + text-decoration: none; + background-color: #f5f5f5 +} + +.pager .next>a, +.pager .next>span { + float: right +} + +.pager .previous>a, +.pager .previous>span { + float: left +} + +.pager .disabled>a, +.pager .disabled>a:hover, +.pager .disabled>a:focus, +.pager .disabled>span { + color: #999; + cursor: default; + background-color: #fff +} + +.modal-backdrop { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 1040; + background-color: #000 +} + +.modal-backdrop.fade { + opacity: 0 +} + +.modal-backdrop, +.modal-backdrop.fade.in { + opacity: .8; + filter: alpha(opacity=80) +} + +.modal { + position: fixed; + top: 10%; + left: 50%; + z-index: 1050; + width: 560px; + margin-left: -280px; + background-color: #fff; + border: 1px solid #999; + border: 1px solid rgba(0, 0, 0, 0.3); + *border: 1px solid #999; + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; + outline: 0; + -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); + -moz-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); + box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); + -webkit-background-clip: padding-box; + -moz-background-clip: padding-box; + background-clip: padding-box +} + +.modal.fade { + top: -25%; + -webkit-transition: opacity .3s linear, top .3s ease-out; + -moz-transition: opacity .3s linear, top .3s ease-out; + -o-transition: opacity .3s linear, top .3s ease-out; + transition: opacity .3s linear, top .3s ease-out +} + +.modal.fade.in { + top: 10% +} + +.modal-header { + padding: 9px 15px; + border-bottom: 1px solid #eee +} + +.modal-header .close { + margin-top: 2px +} + +.modal-header h3 { + margin: 0; + line-height: 30px +} + +.modal-body { + position: relative; + max-height: 400px; + padding: 15px; + overflow-y: auto +} + +.modal-form { + margin-bottom: 0 +} + +.modal-footer { + padding: 14px 15px 15px; + margin-bottom: 0; + text-align: right; + background-color: #f5f5f5; + border-top: 1px solid #ddd; + -webkit-border-radius: 0 0 6px 6px; + -moz-border-radius: 0 0 6px 6px; + border-radius: 0 0 6px 6px; + *zoom: 1; + -webkit-box-shadow: inset 0 1px 0 #fff; + -moz-box-shadow: inset 0 1px 0 #fff; + box-shadow: inset 0 1px 0 #fff +} + +.modal-footer:before, +.modal-footer:after { + display: table; + line-height: 0; + content: "" +} + +.modal-footer:after { + clear: both +} + +.modal-footer .btn+.btn { + margin-bottom: 0; + margin-left: 5px +} + +.modal-footer .btn-group .btn+.btn { + margin-left: -1px +} + +.modal-footer .btn-block+.btn-block { + margin-left: 0 +} + +.tooltip { + position: absolute; + z-index: 1030; + display: block; + font-size: 11px; + line-height: 1.4; + opacity: 0; + filter: alpha(opacity=0); + visibility: visible +} + +.tooltip.in { + opacity: .8; + filter: alpha(opacity=80) +} + +.tooltip.top { + padding: 5px 0; + margin-top: -3px +} + +.tooltip.right { + padding: 0 5px; + margin-left: 3px +} + +.tooltip.bottom { + padding: 5px 0; + margin-top: 3px +} + +.tooltip.left { + padding: 0 5px; + margin-left: -3px +} + +.tooltip-inner { + max-width: 200px; + padding: 8px; + color: #fff; + text-align: center; + text-decoration: none; + background-color: #000; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px +} + +.tooltip-arrow { + position: absolute; + width: 0; + height: 0; + border-color: transparent; + border-style: solid +} + +.tooltip.top .tooltip-arrow { + bottom: 0; + left: 50%; + margin-left: -5px; + border-top-color: #000; + border-width: 5px 5px 0 +} + +.tooltip.right .tooltip-arrow { + top: 50%; + left: 0; + margin-top: -5px; + border-right-color: #000; + border-width: 5px 5px 5px 0 +} + +.tooltip.left .tooltip-arrow { + top: 50%; + right: 0; + margin-top: -5px; + border-left-color: #000; + border-width: 5px 0 5px 5px +} + +.tooltip.bottom .tooltip-arrow { + top: 0; + left: 50%; + margin-left: -5px; + border-bottom-color: #000; + border-width: 0 5px 5px +} + +.popover { + position: absolute; + top: 0; + left: 0; + z-index: 1010; + display: none; + max-width: 276px; + padding: 1px; + text-align: left; + white-space: normal; + background-color: #fff; + border: 1px solid #ccc; + border: 1px solid rgba(0, 0, 0, 0.2); + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; + -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); + -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); + box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); + -webkit-background-clip: padding-box; + -moz-background-clip: padding; + background-clip: padding-box +} + +.popover.top { + margin-top: -10px +} + +.popover.right { + margin-left: 10px +} + +.popover.bottom { + margin-top: 10px +} + +.popover.left { + margin-left: -10px +} + +.popover-title { + padding: 8px 14px; + margin: 0; + font-size: 14px; + font-weight: normal; + line-height: 18px; + background-color: #f7f7f7; + border-bottom: 1px solid #ebebeb; + -webkit-border-radius: 5px 5px 0 0; + -moz-border-radius: 5px 5px 0 0; + border-radius: 5px 5px 0 0 +} + +.popover-title:empty { + display: none +} + +.popover-content { + padding: 9px 14px +} + +.popover .arrow, +.popover .arrow:after { + position: absolute; + display: block; + width: 0; + height: 0; + border-color: transparent; + border-style: solid +} + +.popover .arrow { + border-width: 11px +} + +.popover .arrow:after { + border-width: 10px; + content: "" +} + +.popover.top .arrow { + bottom: -11px; + left: 50%; + margin-left: -11px; + border-top-color: #999; + border-top-color: rgba(0, 0, 0, 0.25); + border-bottom-width: 0 +} + +.popover.top .arrow:after { + bottom: 1px; + margin-left: -10px; + border-top-color: #fff; + border-bottom-width: 0 +} + +.popover.right .arrow { + top: 50%; + left: -11px; + margin-top: -11px; + border-right-color: #999; + border-right-color: rgba(0, 0, 0, 0.25); + border-left-width: 0 +} + +.popover.right .arrow:after { + bottom: -10px; + left: 1px; + border-right-color: #fff; + border-left-width: 0 +} + +.popover.bottom .arrow { + top: -11px; + left: 50%; + margin-left: -11px; + border-bottom-color: #999; + border-bottom-color: rgba(0, 0, 0, 0.25); + border-top-width: 0 +} + +.popover.bottom .arrow:after { + top: 1px; + margin-left: -10px; + border-bottom-color: #fff; + border-top-width: 0 +} + +.popover.left .arrow { + top: 50%; + right: -11px; + margin-top: -11px; + border-left-color: #999; + border-left-color: rgba(0, 0, 0, 0.25); + border-right-width: 0 +} + +.popover.left .arrow:after { + right: 1px; + bottom: -10px; + border-left-color: #fff; + border-right-width: 0 +} + +.thumbnails { + margin-left: -20px; + list-style: none; + *zoom: 1 +} + +.thumbnails:before, +.thumbnails:after { + display: table; + line-height: 0; + content: "" +} + +.thumbnails:after { + clear: both +} + +.row-fluid .thumbnails { + margin-left: 0 +} + +.thumbnails>li { + float: left; + margin-bottom: 20px; + margin-left: 20px +} + +.thumbnail { + display: block; + padding: 4px; + line-height: 20px; + border: 1px solid #ddd; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055); + -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055); + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055); + -webkit-transition: all .2s ease-in-out; + -moz-transition: all .2s ease-in-out; + -o-transition: all .2s ease-in-out; + transition: all .2s ease-in-out +} + +a.thumbnail:hover, +a.thumbnail:focus { + border-color: #08c; + -webkit-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25); + -moz-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25); + box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25) +} + +.thumbnail>img { + display: block; + max-width: 100%; + margin-right: auto; + margin-left: auto +} + +.thumbnail .caption { + padding: 9px; + color: #555 +} + +.media, +.media-body { + overflow: hidden; + *overflow: visible; + zoom: 1 +} + +.media, +.media .media { + margin-top: 15px +} + +.media:first-child { + margin-top: 0 +} + +.media-object { + display: block +} + +.media-heading { + margin: 0 0 5px +} + +.media>.pull-left { + margin-right: 10px +} + +.media>.pull-right { + margin-left: 10px +} + +.media-list { + margin-left: 0; + list-style: none +} + +.label, +.badge { + display: inline-block; + padding: 2px 4px; + font-size: 11.844px; + font-weight: bold; + line-height: 14px; + color: #fff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + white-space: nowrap; + vertical-align: baseline; + background-color: #999 +} + +.label { + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px +} + +.badge { + padding-right: 9px; + padding-left: 9px; + -webkit-border-radius: 9px; + -moz-border-radius: 9px; + border-radius: 9px +} + +.label:empty, +.badge:empty { + display: none +} + +a.label:hover, +a.label:focus, +a.badge:hover, +a.badge:focus { + color: #fff; + text-decoration: none; + cursor: pointer +} + +.label-important, +.badge-important { + background-color: #b94a48 +} + +.label-important[href], +.badge-important[href] { + background-color: #953b39 +} + +.label-warning, +.badge-warning { + background-color: #f89406 +} + +.label-warning[href], +.badge-warning[href] { + background-color: #c67605 +} + +.label-success, +.badge-success { + background-color: #468847 +} + +.label-success[href], +.badge-success[href] { + background-color: #356635 +} + +.label-info, +.badge-info { + background-color: #3a87ad +} + +.label-info[href], +.badge-info[href] { + background-color: #2d6987 +} + +.label-inverse, +.badge-inverse { + background-color: #333 +} + +.label-inverse[href], +.badge-inverse[href] { + background-color: #1a1a1a +} + +.btn .label, +.btn .badge { + position: relative; + top: -1px +} + +.btn-mini .label, +.btn-mini .badge { + top: 0 +} + +@-webkit-keyframes progress-bar-stripes { + from { + background-position: 40px 0 + } + + to { + background-position: 0 0 + } +} + +@-moz-keyframes progress-bar-stripes { + from { + background-position: 40px 0 + } + + to { + background-position: 0 0 + } +} + +@-ms-keyframes progress-bar-stripes { + from { + background-position: 40px 0 + } + + to { + background-position: 0 0 + } +} + +@-o-keyframes progress-bar-stripes { + from { + background-position: 0 0 + } + + to { + background-position: 40px 0 + } +} + +@keyframes progress-bar-stripes { + from { + background-position: 40px 0 + } + + to { + background-position: 0 0 + } +} + +.progress { + height: 20px; + margin-bottom: 20px; + overflow: hidden; + background-color: #f7f7f7; + background-image: -moz-linear-gradient(top, #f5f5f5, #f9f9f9); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f5f5f5), to(#f9f9f9)); + background-image: -webkit-linear-gradient(top, #f5f5f5, #f9f9f9); + background-image: -o-linear-gradient(top, #f5f5f5, #f9f9f9); + background-image: linear-gradient(to bottom, #f5f5f5, #f9f9f9); + background-repeat: repeat-x; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#fff9f9f9', GradientType=0); + -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); + -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); + box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1) +} + +.progress .bar { + float: left; + width: 0; + height: 100%; + font-size: 12px; + color: #fff; + text-align: center; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + background-color: #0e90d2; + background-image: -moz-linear-gradient(top, #149bdf, #0480be); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#149bdf), to(#0480be)); + background-image: -webkit-linear-gradient(top, #149bdf, #0480be); + background-image: -o-linear-gradient(top, #149bdf, #0480be); + background-image: linear-gradient(to bottom, #149bdf, #0480be); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff149bdf', endColorstr='#ff0480be', GradientType=0); + -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); + -moz-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); + box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + -webkit-transition: width .6s ease; + -moz-transition: width .6s ease; + -o-transition: width .6s ease; + transition: width .6s ease +} + +.progress .bar+.bar { + -webkit-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15); + -moz-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15); + box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15) +} + +.progress-striped .bar { + background-color: #149bdf; + background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + -webkit-background-size: 40px 40px; + -moz-background-size: 40px 40px; + -o-background-size: 40px 40px; + background-size: 40px 40px +} + +.progress.active .bar { + -webkit-animation: progress-bar-stripes 2s linear infinite; + -moz-animation: progress-bar-stripes 2s linear infinite; + -ms-animation: progress-bar-stripes 2s linear infinite; + -o-animation: progress-bar-stripes 2s linear infinite; + animation: progress-bar-stripes 2s linear infinite +} + +.progress-danger .bar, +.progress .bar-danger { + background-color: #dd514c; + background-image: -moz-linear-gradient(top, #ee5f5b, #c43c35); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#c43c35)); + background-image: -webkit-linear-gradient(top, #ee5f5b, #c43c35); + background-image: -o-linear-gradient(top, #ee5f5b, #c43c35); + background-image: linear-gradient(to bottom, #ee5f5b, #c43c35); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffc43c35', GradientType=0) +} + +.progress-danger.progress-striped .bar, +.progress-striped .bar-danger { + background-color: #ee5f5b; + background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent) +} + +.progress-success .bar, +.progress .bar-success { + background-color: #5eb95e; + background-image: -moz-linear-gradient(top, #62c462, #57a957); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#57a957)); + background-image: -webkit-linear-gradient(top, #62c462, #57a957); + background-image: -o-linear-gradient(top, #62c462, #57a957); + background-image: linear-gradient(to bottom, #62c462, #57a957); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff57a957', GradientType=0) +} + +.progress-success.progress-striped .bar, +.progress-striped .bar-success { + background-color: #62c462; + background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent) +} + +.progress-info .bar, +.progress .bar-info { + background-color: #4bb1cf; + background-image: -moz-linear-gradient(top, #5bc0de, #339bb9); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#339bb9)); + background-image: -webkit-linear-gradient(top, #5bc0de, #339bb9); + background-image: -o-linear-gradient(top, #5bc0de, #339bb9); + background-image: linear-gradient(to bottom, #5bc0de, #339bb9); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff339bb9', GradientType=0) +} + +.progress-info.progress-striped .bar, +.progress-striped .bar-info { + background-color: #5bc0de; + background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent) +} + +.progress-warning .bar, +.progress .bar-warning { + background-color: #faa732; + background-image: -moz-linear-gradient(top, #fbb450, #f89406); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406)); + background-image: -webkit-linear-gradient(top, #fbb450, #f89406); + background-image: -o-linear-gradient(top, #fbb450, #f89406); + background-image: linear-gradient(to bottom, #fbb450, #f89406); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0) +} + +.progress-warning.progress-striped .bar, +.progress-striped .bar-warning { + background-color: #fbb450; + background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent) +} + +.accordion { + margin-bottom: 20px +} + +.accordion-group { + margin-bottom: 2px; + border: 1px solid #e5e5e5; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px +} + +.accordion-heading { + border-bottom: 0 +} + +.accordion-heading .accordion-toggle { + display: block; + padding: 8px 15px +} + +.accordion-toggle { + cursor: pointer +} + +.accordion-inner { + padding: 9px 15px; + border-top: 1px solid #e5e5e5 +} + +.carousel { + position: relative; + margin-bottom: 20px; + line-height: 1 +} + +.carousel-inner { + position: relative; + width: 100%; + overflow: hidden +} + +.carousel-inner>.item { + position: relative; + display: none; + -webkit-transition: .6s ease-in-out left; + -moz-transition: .6s ease-in-out left; + -o-transition: .6s ease-in-out left; + transition: .6s ease-in-out left +} + +.carousel-inner>.item>img, +.carousel-inner>.item>a>img { + display: block; + line-height: 1 +} + +.carousel-inner>.active, +.carousel-inner>.next, +.carousel-inner>.prev { + display: block +} + +.carousel-inner>.active { + left: 0 +} + +.carousel-inner>.next, +.carousel-inner>.prev { + position: absolute; + top: 0; + width: 100% +} + +.carousel-inner>.next { + left: 100% +} + +.carousel-inner>.prev { + left: -100% +} + +.carousel-inner>.next.left, +.carousel-inner>.prev.right { + left: 0 +} + +.carousel-inner>.active.left { + left: -100% +} + +.carousel-inner>.active.right { + left: 100% +} + +.carousel-control { + position: absolute; + top: 40%; + left: 15px; + width: 40px; + height: 40px; + margin-top: -20px; + font-size: 60px; + font-weight: 100; + line-height: 30px; + color: #fff; + text-align: center; + background: #222; + border: 3px solid #fff; + -webkit-border-radius: 23px; + -moz-border-radius: 23px; + border-radius: 23px; + opacity: .5; + filter: alpha(opacity=50) +} + +.carousel-control.right { + right: 15px; + left: auto +} + +.carousel-control:hover, +.carousel-control:focus { + color: #fff; + text-decoration: none; + opacity: .9; + filter: alpha(opacity=90) +} + +.carousel-indicators { + position: absolute; + top: 15px; + right: 15px; + z-index: 5; + margin: 0; + list-style: none +} + +.carousel-indicators li { + display: block; + float: left; + width: 10px; + height: 10px; + margin-left: 5px; + text-indent: -999px; + background-color: #ccc; + background-color: rgba(255, 255, 255, 0.25); + border-radius: 5px +} + +.carousel-indicators .active { + background-color: #fff +} + +.carousel-caption { + position: absolute; + right: 0; + bottom: 0; + left: 0; + padding: 15px; + background: #333; + background: rgba(0, 0, 0, 0.75) +} + +.carousel-caption h4, +.carousel-caption p { + line-height: 20px; + color: #fff +} + +.carousel-caption h4 { + margin: 0 0 5px +} + +.carousel-caption p { + margin-bottom: 0 +} + +.hero-unit { + padding: 60px; + margin-bottom: 30px; + font-size: 18px; + font-weight: 200; + line-height: 30px; + color: inherit; + background-color: #eee; + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px +} + +.hero-unit h1 { + margin-bottom: 0; + font-size: 60px; + line-height: 1; + letter-spacing: -1px; + color: inherit +} + +.hero-unit li { + line-height: 30px +} + +.pull-right { + float: right +} + +.pull-left { + float: left +} + +.hide { + display: none +} + +.show { + display: block +} + +.invisible { + visibility: hidden +} + +.affix { + position: fixed +} \ No newline at end of file diff --git a/trunk/research/players/css/homepage_main.css b/trunk/research/players/css/homepage_main.css new file mode 100644 index 000000000..0febf238a --- /dev/null +++ b/trunk/research/players/css/homepage_main.css @@ -0,0 +1,135 @@ + + +nav { + display: flex; + justify-content: space-between; + align-items: center; + padding: 1rem 2rem; + background: white; + box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1); +} + +.logo { + display: flex; + align-items: center; + gap: 0.8rem; +} +.logo img { + width: 40px; + height: 40px; +} + +.nav-button { + background: #4285f4; + color: white; + padding: 0.8rem 1.5rem; + border: none; + border-radius: 24px; + cursor: pointer; + transition: all 0.3s ease; +} + +.nav-button:hover { + background: #357abd; +} + +main { + padding: 4rem 2rem; + max-width: 1200px; + margin: 0 auto; +} + +.hero-section { + margin-top: 3rem; +} + +h1 { + font-size: 2.5rem; + color: #202124; + margin-bottom: 1.5rem; + line-height: 1.3; +} + +.subtitle { + font-size: 1.2rem; + color: #5f6368; + margin-bottom: 3rem; + max-width: 600px; +} + +.join-container { + display: flex; + gap: 1rem; + max-width: 500px; +} + +.code-box { + margin: 0; + display: flex; + flex-direction: column; + /* gap: 30px; */ + position: relative; + width: 250px; + justify-content: center; +} + +#code-input { + padding: 10px; + border: 1px solid rgba(0, 0, 0, 0.5); + background: white; + border-radius: 8px; + outline: none; + color: #000000; + font-size: 1em; + transition: 0.5s; +} +#code-span { + position: absolute; + left: 0; + padding: 0 10px; + pointer-events: none; + font-size: 1em; + color: rgba(0, 0, 0, 0.5); + text-transform: uppercase; + transition: all 0.5s; +} +#code-input:valid ~ #code-span, +#code-input:focus ~ #code-span { + color: #4285f4; + transform: translateX(-15px) translateY(-18px) scale(0.7); + /* font-size: 0.65em; */ + padding: 0 10px; + background: white; + border-left: 3px solid #4285f4; + border-right: 3px solid #4285f4; + /* letter-spacing: .2em; */ +} +#code-input:valid, #code-input:focus { + border: 3px solid #4285f4; +} + +.join-button { + background: linear-gradient(135deg, #4285f4, #34a853); + color: white; + padding: 1rem 2rem; + border: none; + border-radius: 8px; + font-size: 1rem; + cursor: pointer; + transition: all 0.3s ease; +} + +.join-button:hover { + opacity: 0.9; + transform: translateY(-1px); +} + +@media (max-width: 768px) { + h1 { + font-size: 2rem; + } + + .join-container { + flex-direction: column; + } +} \ No newline at end of file diff --git a/trunk/research/players/css/whep_main.css b/trunk/research/players/css/whep_main.css new file mode 100644 index 000000000..51c8f3804 --- /dev/null +++ b/trunk/research/players/css/whep_main.css @@ -0,0 +1,309 @@ +/*=============== VARIABLES CSS ===============*/ +@import url('https://fonts.googleapis.com/css2?family=Quicksand:wght@300..700&display=swap'); + +:root { + /*========== Colors ==========*/ + /*Color mode HSL(hue, saturation, lightness)*/ + --background-color: rgb(255, 255, 255); + --preloader-background-color: rgb(255, 255, 255); + --preloader-text-color: hsl(210, 30%, 10%); + --secondary-color: hsl(0, 0%, 65%); + + /*========== Font and typography ==========*/ + /*.5rem = 8px | 1rem = 16px ...*/ + --body-font: "Quicksand", sans-serif; + --second-font: Serif; + --h3-font-size: 1rem; + + /*========== z index ==========*/ + --z-tooltip: 10; + --z-fixed: 100; +} + +body { + margin: 0; + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 14px; + line-height: 20px; + color: #333; + background-color: #fff; + overflow: hidden; + height: 100vh; + display: flex; + justify-content: center; + align-items: center; +} + +#rtc_media_player { + max-width: 95%; + max-height: 95vh; + border-radius: 18px; + box-shadow: 0 8px 30px rgba(0, 0, 0, 0.12); + background: #000000; + transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); + overflow: hidden; + cursor: pointer; + object-fit: contain; +} + +*, +*::after, +*::before { + margin: 0; + padding: 0; + box-sizing: inherit; +} + +.form { + max-width: 60rem; +} + +.form__radios { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(20rem, 1fr)); + gap: 2rem; +} + +.form__radio { + display: grid; + grid-template-columns: auto 1fr; + column-gap: 2rem; + row-gap: .8rem; + margin-top: 1rem; +} + +.form__radio p { + grid-column: 1 / -1; +} + +.form__inputs { + display: flex; + flex-direction: column; + gap: .8rem; + margin-top: 4rem; +} + +.form__inputs input, +.form__radios input { + margin-bottom: 1rem; + background-color: #556; + border: none; + padding: 1rem 1.5rem; + color: inherit; + outline: transparent; +} + +.form__buttons { + margin-top: 4rem; + display: grid; + grid-template-columns: repeat(auto-fit, minmax(20rem, 2fr)); + gap: 1rem 2rem; +} + +.toast .btn { + background-color: #778; + color: inherit; + border: none; + padding: 1rem 1.5rem; + cursor: pointer; +} + +.btn:hover { + background-color: #556; +} + +.btn--success { + background-color: rgb(21, 173, 89); +} + +.btn--success:hover { + background-color: rgb(12, 134, 67); +} + +.btn--error { + background-color: rgb(199, 29, 66); +} + +.btn--error:hover { + background-color: rgb(158, 16, 47); +} + +.btn--warning { + background-color: rgb(232, 172, 21); + color: #222226; +} + +.btn--warning:hover { + background-color: rgb(199, 141, 15); +} + + +/* THE ACTUAL TOAST NOTIFICATIONS */ +.toast { + position: fixed; + top: 0; + right: 0; + margin: 0.7rem; + display: flex; + flex-direction: column; + gap: 1rem; + max-width: 90%; +} + +.toast__message { + position: relative; + color: #EEE; + background-color: #334; + width: 25rem; + max-width: 100%; + max-width: 100%; + padding: 1rem; + display: grid; + grid-template-columns: auto 1fr; + gap: 1.1rem; + align-items: center; + font-size: 0.85rem; + border-left: 3px solid #EEE; + animation: toast 6s cubic-bezier(0.075, 0.82, 0.165, 1) forwards; +} + +.toast__icon { + background-color: rgb(21, 173, 89); + width: 1.95rem; + height: 1.95rem; + border-radius: 50%; + color: #222226; + display: grid; + place-items: center; +} + +.toast__icon svg { + height: 1.3rem; + width: 1.3rem; +} + +.toast__buttons { + display: grid; + /* flex-direction: row; */ + grid-template-columns: 1fr 1fr; + gap: 1rem; + margin-top: 1rem; + justify-content: stretch; +} + +.toast__buttons button { + background-color: rgba(255, 255, 255, .1); + border: none; + color: inherit; + padding: .5rem 1rem; + cursor: pointer; +} + +.toast__buttons button:hover { + background-color: rgba(255, 255, 255, .2); +} + +.toast__close { + position: absolute; + top: 1rem; + right: 2rem; + font-size: 1.5rem; + font-weight: 100; + color: #888; + cursor: pointer; +} + + +/* ERROR MESSAGES */ +.toast__message--error { + background-color: #334; + background-image: linear-gradient(to right, + rgba(136, 7, 35, 0.3), + rgba(136, 7, 35, 0) 30%); + border-left: 3px solid rgb(199, 29, 66); +} + +.toast__message--error .toast__icon { + background-color: rgb(199, 29, 66); +} + +.toast__message--error .toast__icon svg { + height: 1.5rem; + width: 1.5rem; +} + +.toast__message--error .toast__heading { + color: rgb(199, 29, 66); + margin: 0; +} + + +/* WARNING MESSAGES */ +.toast__message--warning { + background-color: #334; + background-image: linear-gradient(to right, + rgba(145, 93, 10, 0.3), + rgba(145, 93, 10, 0) 30%); + border-left: 3px solid rgb(232, 172, 21); +} + +.toast__message--warning .toast__icon { + background-color: rgb(232, 172, 21); +} + +.toast__message--warning .toast__icon svg { + height: 1.5rem; + width: 1.5rem; +} + +.toast__message--warning .toast__heading { + color: rgb(232, 172, 21); + margin: 0; +} +.toast__message p { + margin: 0; +} + + +/* SUCCESS MESSAGES */ +.toast__message--success { + background-color: #334; + background-image: linear-gradient(to right, + rgba(12, 100, 52, 0.3), + rgba(12, 100, 52, 0) 30%); + border-left: 3px solid rgb(21, 173, 89); +} + +.toast__message--success .toast__icon { + background-color: rgb(21, 173, 89); +} + +.toast__message--success .toast__icon svg { + height: 1.5rem; + width: 1.5rem; +} + +.toast__message--success .toast__heading { + color: rgb(21, 173, 89); + margin-top: 0.8rem; + margin-bottom: 0; +} + +@keyframes toast { + 0% { + transform: translateY(150%); + opacity: 0; + } + + 10%, + 90% { + transform: translateY(0); + opacity: 1; + } + + 100% { + transform: translateY(100%); + opacity: 0; + } +} + diff --git a/trunk/research/players/homepage.html b/trunk/research/players/homepage.html new file mode 100644 index 000000000..bba38c271 --- /dev/null +++ b/trunk/research/players/homepage.html @@ -0,0 +1,330 @@ + + + + + + + NPL ITP Intranet Livestream Channel + + + + + + + + + + + + + + + NPL ITP + Intranet Livestream Channel + Connecting to the SRS Server ... + Loading... + + + + + + + + + NPL ITP Intranet Channel + + 首页 + + + + + 内联网人人都可以用的超低延迟直播服务 + 借助SRS服务和WebRTC连接协议,随时观看直播 + + + + + Enter the Stream Code + + Enter + + + + + + + + \ No newline at end of file diff --git a/trunk/research/players/img/school_logo.png b/trunk/research/players/img/school_logo.png new file mode 100644 index 000000000..2074e5774 Binary files /dev/null and b/trunk/research/players/img/school_logo.png differ diff --git a/trunk/research/players/img/school_logo_text.png b/trunk/research/players/img/school_logo_text.png new file mode 100644 index 000000000..1acea0585 Binary files /dev/null and b/trunk/research/players/img/school_logo_text.png differ diff --git a/trunk/research/players/js/anime.js b/trunk/research/players/js/anime.js new file mode 100644 index 000000000..4f57877f1 --- /dev/null +++ b/trunk/research/players/js/anime.js @@ -0,0 +1,8 @@ +/* + * anime.js v3.1.0 + * (c) 2019 Julian Garnier + * Released under the MIT license + * animejs.com + */ + +!function (n, e) { "object" == typeof exports && "undefined" != typeof module ? module.exports = e() : "function" == typeof define && define.amd ? define(e) : n.anime = e() }(this, function () { "use strict"; var n = { update: null, begin: null, loopBegin: null, changeBegin: null, change: null, changeComplete: null, loopComplete: null, complete: null, loop: 1, direction: "normal", autoplay: !0, timelineOffset: 0 }, e = { duration: 1e3, delay: 0, endDelay: 0, easing: "easeOutElastic(1, .5)", round: 0 }, r = ["translateX", "translateY", "translateZ", "rotate", "rotateX", "rotateY", "rotateZ", "scale", "scaleX", "scaleY", "scaleZ", "skew", "skewX", "skewY", "perspective"], t = { CSS: {}, springs: {} }; function a(n, e, r) { return Math.min(Math.max(n, e), r) } function o(n, e) { return n.indexOf(e) > -1 } function u(n, e) { return n.apply(null, e) } var i = { arr: function (n) { return Array.isArray(n) }, obj: function (n) { return o(Object.prototype.toString.call(n), "Object") }, pth: function (n) { return i.obj(n) && n.hasOwnProperty("totalLength") }, svg: function (n) { return n instanceof SVGElement }, inp: function (n) { return n instanceof HTMLInputElement }, dom: function (n) { return n.nodeType || i.svg(n) }, str: function (n) { return "string" == typeof n }, fnc: function (n) { return "function" == typeof n }, und: function (n) { return void 0 === n }, hex: function (n) { return /(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i.test(n) }, rgb: function (n) { return /^rgb/.test(n) }, hsl: function (n) { return /^hsl/.test(n) }, col: function (n) { return i.hex(n) || i.rgb(n) || i.hsl(n) }, key: function (r) { return !n.hasOwnProperty(r) && !e.hasOwnProperty(r) && "targets" !== r && "keyframes" !== r } }; function c(n) { var e = /\(([^)]+)\)/.exec(n); return e ? e[1].split(",").map(function (n) { return parseFloat(n) }) : [] } function s(n, e) { var r = c(n), o = a(i.und(r[0]) ? 1 : r[0], .1, 100), u = a(i.und(r[1]) ? 100 : r[1], .1, 100), s = a(i.und(r[2]) ? 10 : r[2], .1, 100), f = a(i.und(r[3]) ? 0 : r[3], .1, 100), l = Math.sqrt(u / o), d = s / (2 * Math.sqrt(u * o)), p = d < 1 ? l * Math.sqrt(1 - d * d) : 0, h = 1, v = d < 1 ? (d * l - f) / p : -f + l; function g(n) { var r = e ? e * n / 1e3 : n; return r = d < 1 ? Math.exp(-r * d * l) * (h * Math.cos(p * r) + v * Math.sin(p * r)) : (h + v * r) * Math.exp(-r * l), 0 === n || 1 === n ? n : 1 - r } return e ? g : function () { var e = t.springs[n]; if (e) return e; for (var r = 0, a = 0; ;)if (1 === g(r += 1 / 6)) { if (++a >= 16) break } else a = 0; var o = r * (1 / 6) * 1e3; return t.springs[n] = o, o } } function f(n) { return void 0 === n && (n = 10), function (e) { return Math.round(e * n) * (1 / n) } } var l, d, p = function () { var n = 11, e = 1 / (n - 1); function r(n, e) { return 1 - 3 * e + 3 * n } function t(n, e) { return 3 * e - 6 * n } function a(n) { return 3 * n } function o(n, e, o) { return ((r(e, o) * n + t(e, o)) * n + a(e)) * n } function u(n, e, o) { return 3 * r(e, o) * n * n + 2 * t(e, o) * n + a(e) } return function (r, t, a, i) { if (0 <= r && r <= 1 && 0 <= a && a <= 1) { var c = new Float32Array(n); if (r !== t || a !== i) for (var s = 0; s < n; ++s)c[s] = o(s * e, r, a); return function (n) { return r === t && a === i ? n : 0 === n || 1 === n ? n : o(f(n), t, i) } } function f(t) { for (var i = 0, s = 1, f = n - 1; s !== f && c[s] <= t; ++s)i += e; var l = i + (t - c[--s]) / (c[s + 1] - c[s]) * e, d = u(l, r, a); return d >= .001 ? function (n, e, r, t) { for (var a = 0; a < 4; ++a) { var i = u(e, r, t); if (0 === i) return e; e -= (o(e, r, t) - n) / i } return e }(t, l, r, a) : 0 === d ? l : function (n, e, r, t, a) { for (var u, i, c = 0; (u = o(i = e + (r - e) / 2, t, a) - n) > 0 ? r = i : e = i, Math.abs(u) > 1e-7 && ++c < 10;); return i }(t, i, i + e, r, a) } } }(), h = (l = { linear: function () { return function (n) { return n } } }, d = { Sine: function () { return function (n) { return 1 - Math.cos(n * Math.PI / 2) } }, Circ: function () { return function (n) { return 1 - Math.sqrt(1 - n * n) } }, Back: function () { return function (n) { return n * n * (3 * n - 2) } }, Bounce: function () { return function (n) { for (var e, r = 4; n < ((e = Math.pow(2, --r)) - 1) / 11;); return 1 / Math.pow(4, 3 - r) - 7.5625 * Math.pow((3 * e - 2) / 22 - n, 2) } }, Elastic: function (n, e) { void 0 === n && (n = 1), void 0 === e && (e = .5); var r = a(n, 1, 10), t = a(e, .1, 2); return function (n) { return 0 === n || 1 === n ? n : -r * Math.pow(2, 10 * (n - 1)) * Math.sin((n - 1 - t / (2 * Math.PI) * Math.asin(1 / r)) * (2 * Math.PI) / t) } } }, ["Quad", "Cubic", "Quart", "Quint", "Expo"].forEach(function (n, e) { d[n] = function () { return function (n) { return Math.pow(n, e + 2) } } }), Object.keys(d).forEach(function (n) { var e = d[n]; l["easeIn" + n] = e, l["easeOut" + n] = function (n, r) { return function (t) { return 1 - e(n, r)(1 - t) } }, l["easeInOut" + n] = function (n, r) { return function (t) { return t < .5 ? e(n, r)(2 * t) / 2 : 1 - e(n, r)(-2 * t + 2) / 2 } } }), l); function v(n, e) { if (i.fnc(n)) return n; var r = n.split("(")[0], t = h[r], a = c(n); switch (r) { case "spring": return s(n, e); case "cubicBezier": return u(p, a); case "steps": return u(f, a); default: return u(t, a) } } function g(n) { try { return document.querySelectorAll(n) } catch (n) { return } } function m(n, e) { for (var r = n.length, t = arguments.length >= 2 ? arguments[1] : void 0, a = [], o = 0; o < r; o++)if (o in n) { var u = n[o]; e.call(t, u, o, n) && a.push(u) } return a } function y(n) { return n.reduce(function (n, e) { return n.concat(i.arr(e) ? y(e) : e) }, []) } function b(n) { return i.arr(n) ? n : (i.str(n) && (n = g(n) || n), n instanceof NodeList || n instanceof HTMLCollection ? [].slice.call(n) : [n]) } function M(n, e) { return n.some(function (n) { return n === e }) } function x(n) { var e = {}; for (var r in n) e[r] = n[r]; return e } function w(n, e) { var r = x(n); for (var t in n) r[t] = e.hasOwnProperty(t) ? e[t] : n[t]; return r } function k(n, e) { var r = x(n); for (var t in e) r[t] = i.und(n[t]) ? e[t] : n[t]; return r } function O(n) { return i.rgb(n) ? (r = /rgb\((\d+,\s*[\d]+,\s*[\d]+)\)/g.exec(e = n)) ? "rgba(" + r[1] + ",1)" : e : i.hex(n) ? (t = n.replace(/^#?([a-f\d])([a-f\d])([a-f\d])$/i, function (n, e, r, t) { return e + e + r + r + t + t }), a = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(t), "rgba(" + parseInt(a[1], 16) + "," + parseInt(a[2], 16) + "," + parseInt(a[3], 16) + ",1)") : i.hsl(n) ? function (n) { var e, r, t, a = /hsl\((\d+),\s*([\d.]+)%,\s*([\d.]+)%\)/g.exec(n) || /hsla\((\d+),\s*([\d.]+)%,\s*([\d.]+)%,\s*([\d.]+)\)/g.exec(n), o = parseInt(a[1], 10) / 360, u = parseInt(a[2], 10) / 100, i = parseInt(a[3], 10) / 100, c = a[4] || 1; function s(n, e, r) { return r < 0 && (r += 1), r > 1 && (r -= 1), r < 1 / 6 ? n + 6 * (e - n) * r : r < .5 ? e : r < 2 / 3 ? n + (e - n) * (2 / 3 - r) * 6 : n } if (0 == u) e = r = t = i; else { var f = i < .5 ? i * (1 + u) : i + u - i * u, l = 2 * i - f; e = s(l, f, o + 1 / 3), r = s(l, f, o), t = s(l, f, o - 1 / 3) } return "rgba(" + 255 * e + "," + 255 * r + "," + 255 * t + "," + c + ")" }(n) : void 0; var e, r, t, a } function C(n) { var e = /[+-]?\d*\.?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?(%|px|pt|em|rem|in|cm|mm|ex|ch|pc|vw|vh|vmin|vmax|deg|rad|turn)?$/.exec(n); if (e) return e[1] } function B(n, e) { return i.fnc(n) ? n(e.target, e.id, e.total) : n } function P(n, e) { return n.getAttribute(e) } function I(n, e, r) { if (M([r, "deg", "rad", "turn"], C(e))) return e; var a = t.CSS[e + r]; if (!i.und(a)) return a; var o = document.createElement(n.tagName), u = n.parentNode && n.parentNode !== document ? n.parentNode : document.body; u.appendChild(o), o.style.position = "absolute", o.style.width = 100 + r; var c = 100 / o.offsetWidth; u.removeChild(o); var s = c * parseFloat(e); return t.CSS[e + r] = s, s } function T(n, e, r) { if (e in n.style) { var t = e.replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase(), a = n.style[e] || getComputedStyle(n).getPropertyValue(t) || "0"; return r ? I(n, a, r) : a } } function D(n, e) { return i.dom(n) && !i.inp(n) && (P(n, e) || i.svg(n) && n[e]) ? "attribute" : i.dom(n) && M(r, e) ? "transform" : i.dom(n) && "transform" !== e && T(n, e) ? "css" : null != n[e] ? "object" : void 0 } function E(n) { if (i.dom(n)) { for (var e, r = n.style.transform || "", t = /(\w+)\(([^)]*)\)/g, a = new Map; e = t.exec(r);)a.set(e[1], e[2]); return a } } function F(n, e, r, t) { var a, u = o(e, "scale") ? 1 : 0 + (o(a = e, "translate") || "perspective" === a ? "px" : o(a, "rotate") || o(a, "skew") ? "deg" : void 0), i = E(n).get(e) || u; return r && (r.transforms.list.set(e, i), r.transforms.last = e), t ? I(n, i, t) : i } function N(n, e, r, t) { switch (D(n, e)) { case "transform": return F(n, e, t, r); case "css": return T(n, e, r); case "attribute": return P(n, e); default: return n[e] || 0 } } function A(n, e) { var r = /^(\*=|\+=|-=)/.exec(n); if (!r) return n; var t = C(n) || 0, a = parseFloat(e), o = parseFloat(n.replace(r[0], "")); switch (r[0][0]) { case "+": return a + o + t; case "-": return a - o + t; case "*": return a * o + t } } function L(n, e) { if (i.col(n)) return O(n); if (/\s/g.test(n)) return n; var r = C(n), t = r ? n.substr(0, n.length - r.length) : n; return e ? t + e : t } function j(n, e) { return Math.sqrt(Math.pow(e.x - n.x, 2) + Math.pow(e.y - n.y, 2)) } function S(n) { for (var e, r = n.points, t = 0, a = 0; a < r.numberOfItems; a++) { var o = r.getItem(a); a > 0 && (t += j(e, o)), e = o } return t } function q(n) { if (n.getTotalLength) return n.getTotalLength(); switch (n.tagName.toLowerCase()) { case "circle": return o = n, 2 * Math.PI * P(o, "r"); case "rect": return 2 * P(a = n, "width") + 2 * P(a, "height"); case "line": return j({ x: P(t = n, "x1"), y: P(t, "y1") }, { x: P(t, "x2"), y: P(t, "y2") }); case "polyline": return S(n); case "polygon": return r = (e = n).points, S(e) + j(r.getItem(r.numberOfItems - 1), r.getItem(0)) }var e, r, t, a, o } function $(n, e) { var r = e || {}, t = r.el || function (n) { for (var e = n.parentNode; i.svg(e) && i.svg(e.parentNode);)e = e.parentNode; return e }(n), a = t.getBoundingClientRect(), o = P(t, "viewBox"), u = a.width, c = a.height, s = r.viewBox || (o ? o.split(" ") : [0, 0, u, c]); return { el: t, viewBox: s, x: s[0] / 1, y: s[1] / 1, w: u / s[2], h: c / s[3] } } function X(n, e) { function r(r) { void 0 === r && (r = 0); var t = e + r >= 1 ? e + r : 0; return n.el.getPointAtLength(t) } var t = $(n.el, n.svg), a = r(), o = r(-1), u = r(1); switch (n.property) { case "x": return (a.x - t.x) * t.w; case "y": return (a.y - t.y) * t.h; case "angle": return 180 * Math.atan2(u.y - o.y, u.x - o.x) / Math.PI } } function Y(n, e) { var r = /[+-]?\d*\.?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?/g, t = L(i.pth(n) ? n.totalLength : n, e) + ""; return { original: t, numbers: t.match(r) ? t.match(r).map(Number) : [0], strings: i.str(n) || e ? t.split(r) : [] } } function Z(n) { return m(n ? y(i.arr(n) ? n.map(b) : b(n)) : [], function (n, e, r) { return r.indexOf(n) === e }) } function Q(n) { var e = Z(n); return e.map(function (n, r) { return { target: n, id: r, total: e.length, transforms: { list: E(n) } } }) } function V(n, e) { var r = x(e); if (/^spring/.test(r.easing) && (r.duration = s(r.easing)), i.arr(n)) { var t = n.length; 2 === t && !i.obj(n[0]) ? n = { value: n } : i.fnc(e.duration) || (r.duration = e.duration / t) } var a = i.arr(n) ? n : [n]; return a.map(function (n, r) { var t = i.obj(n) && !i.pth(n) ? n : { value: n }; return i.und(t.delay) && (t.delay = r ? 0 : e.delay), i.und(t.endDelay) && (t.endDelay = r === a.length - 1 ? e.endDelay : 0), t }).map(function (n) { return k(n, r) }) } function z(n, e) { var r = [], t = e.keyframes; for (var a in t && (e = k(function (n) { for (var e = m(y(n.map(function (n) { return Object.keys(n) })), function (n) { return i.key(n) }).reduce(function (n, e) { return n.indexOf(e) < 0 && n.push(e), n }, []), r = {}, t = function (t) { var a = e[t]; r[a] = n.map(function (n) { var e = {}; for (var r in n) i.key(r) ? r == a && (e.value = n[r]) : e[r] = n[r]; return e }) }, a = 0; a < e.length; a++)t(a); return r }(t), e)), e) i.key(a) && r.push({ name: a, tweens: V(e[a], n) }); return r } function H(n, e) { var r; return n.tweens.map(function (t) { var a = function (n, e) { var r = {}; for (var t in n) { var a = B(n[t], e); i.arr(a) && 1 === (a = a.map(function (n) { return B(n, e) })).length && (a = a[0]), r[t] = a } return r.duration = parseFloat(r.duration), r.delay = parseFloat(r.delay), r }(t, e), o = a.value, u = i.arr(o) ? o[1] : o, c = C(u), s = N(e.target, n.name, c, e), f = r ? r.to.original : s, l = i.arr(o) ? o[0] : f, d = C(l) || C(s), p = c || d; return i.und(u) && (u = f), a.from = Y(l, p), a.to = Y(A(u, l), p), a.start = r ? r.end : 0, a.end = a.start + a.delay + a.duration + a.endDelay, a.easing = v(a.easing, a.duration), a.isPath = i.pth(o), a.isColor = i.col(a.from.original), a.isColor && (a.round = 1), r = a, a }) } var G = { css: function (n, e, r) { return n.style[e] = r }, attribute: function (n, e, r) { return n.setAttribute(e, r) }, object: function (n, e, r) { return n[e] = r }, transform: function (n, e, r, t, a) { if (t.list.set(e, r), e === t.last || a) { var o = ""; t.list.forEach(function (n, e) { o += e + "(" + n + ") " }), n.style.transform = o } } }; function R(n, e) { Q(n).forEach(function (n) { for (var r in e) { var t = B(e[r], n), a = n.target, o = C(t), u = N(a, r, o, n), i = A(L(t, o || C(u)), u), c = D(a, r); G[c](a, r, i, n.transforms, !0) } }) } function W(n, e) { return m(y(n.map(function (n) { return e.map(function (e) { return function (n, e) { var r = D(n.target, e.name); if (r) { var t = H(e, n), a = t[t.length - 1]; return { type: r, property: e.name, animatable: n, tweens: t, duration: a.end, delay: t[0].delay, endDelay: a.endDelay } } }(n, e) }) })), function (n) { return !i.und(n) }) } function J(n, e) { var r = n.length, t = function (n) { return n.timelineOffset ? n.timelineOffset : 0 }, a = {}; return a.duration = r ? Math.max.apply(Math, n.map(function (n) { return t(n) + n.duration })) : e.duration, a.delay = r ? Math.min.apply(Math, n.map(function (n) { return t(n) + n.delay })) : e.delay, a.endDelay = r ? a.duration - Math.max.apply(Math, n.map(function (n) { return t(n) + n.duration - n.endDelay })) : e.endDelay, a } var K = 0; var U, _ = [], nn = [], en = function () { function n() { U = requestAnimationFrame(e) } function e(e) { var r = _.length; if (r) { for (var t = 0; t < r;) { var a = _[t]; if (a.paused) { var o = _.indexOf(a); o > -1 && (_.splice(o, 1), r = _.length) } else a.tick(e); t++ } n() } else U = cancelAnimationFrame(U) } return n }(); function rn(r) { void 0 === r && (r = {}); var t, o = 0, u = 0, i = 0, c = 0, s = null; function f(n) { var e = window.Promise && new Promise(function (n) { return s = n }); return n.finished = e, e } var l, d, p, h, v, g, y, b, M = (d = w(n, l = r), p = w(e, l), h = z(p, l), v = Q(l.targets), g = W(v, h), y = J(g, p), b = K, K++, k(d, { id: b, children: [], animatables: v, animations: g, duration: y.duration, delay: y.delay, endDelay: y.endDelay })); f(M); function x() { var n = M.direction; "alternate" !== n && (M.direction = "normal" !== n ? "normal" : "reverse"), M.reversed = !M.reversed, t.forEach(function (n) { return n.reversed = M.reversed }) } function O(n) { return M.reversed ? M.duration - n : n } function C() { o = 0, u = O(M.currentTime) * (1 / rn.speed) } function B(n, e) { e && e.seek(n - e.timelineOffset) } function P(n) { for (var e = 0, r = M.animations, t = r.length; e < t;) { var o = r[e], u = o.animatable, i = o.tweens, c = i.length - 1, s = i[c]; c && (s = m(i, function (e) { return n < e.end })[0] || s); for (var f = a(n - s.start - s.delay, 0, s.duration) / s.duration, l = isNaN(f) ? 1 : s.easing(f), d = s.to.strings, p = s.round, h = [], v = s.to.numbers.length, g = void 0, y = 0; y < v; y++) { var b = void 0, x = s.to.numbers[y], w = s.from.numbers[y] || 0; b = s.isPath ? X(s.value, l * x) : w + l * (x - w), p && (s.isColor && y > 2 || (b = Math.round(b * p) / p)), h.push(b) } var k = d.length; if (k) { g = d[0]; for (var O = 0; O < k; O++) { d[O]; var C = d[O + 1], B = h[O]; isNaN(B) || (g += C ? B + C : B + " ") } } else g = h[0]; G[o.type](u.target, o.property, g, u.transforms), o.currentValue = g, e++ } } function I(n) { M[n] && !M.passThrough && M[n](M) } function T(n) { var e = M.duration, r = M.delay, l = e - M.endDelay, d = O(n); M.progress = a(d / e * 100, 0, 100), M.reversePlayback = d < M.currentTime, t && function (n) { if (M.reversePlayback) for (var e = c; e--;)B(n, t[e]); else for (var r = 0; r < c; r++)B(n, t[r]) }(d), !M.began && M.currentTime > 0 && (M.began = !0, I("begin")), !M.loopBegan && M.currentTime > 0 && (M.loopBegan = !0, I("loopBegin")), d <= r && 0 !== M.currentTime && P(0), (d >= l && M.currentTime !== e || !e) && P(e), d > r && d < l ? (M.changeBegan || (M.changeBegan = !0, M.changeCompleted = !1, I("changeBegin")), I("change"), P(d)) : M.changeBegan && (M.changeCompleted = !0, M.changeBegan = !1, I("changeComplete")), M.currentTime = a(d, 0, e), M.began && I("update"), n >= e && (u = 0, M.remaining && !0 !== M.remaining && M.remaining--, M.remaining ? (o = i, I("loopComplete"), M.loopBegan = !1, "alternate" === M.direction && x()) : (M.paused = !0, M.completed || (M.completed = !0, I("loopComplete"), I("complete"), !M.passThrough && "Promise" in window && (s(), f(M))))) } return M.reset = function () { var n = M.direction; M.passThrough = !1, M.currentTime = 0, M.progress = 0, M.paused = !0, M.began = !1, M.loopBegan = !1, M.changeBegan = !1, M.completed = !1, M.changeCompleted = !1, M.reversePlayback = !1, M.reversed = "reverse" === n, M.remaining = M.loop, t = M.children; for (var e = c = t.length; e--;)M.children[e].reset(); (M.reversed && !0 !== M.loop || "alternate" === n && 1 === M.loop) && M.remaining++, P(M.reversed ? M.duration : 0) }, M.set = function (n, e) { return R(n, e), M }, M.tick = function (n) { i = n, o || (o = i), T((i + (u - o)) * rn.speed) }, M.seek = function (n) { T(O(n)) }, M.pause = function () { M.paused = !0, C() }, M.play = function () { M.paused && (M.completed && M.reset(), M.paused = !1, _.push(M), C(), U || en()) }, M.reverse = function () { x(), C() }, M.restart = function () { M.reset(), M.play() }, M.reset(), M.autoplay && M.play(), M } function tn(n, e) { for (var r = e.length; r--;)M(n, e[r].animatable.target) && e.splice(r, 1) } return "undefined" != typeof document && document.addEventListener("visibilitychange", function () { document.hidden ? (_.forEach(function (n) { return n.pause() }), nn = _.slice(0), rn.running = _ = []) : nn.forEach(function (n) { return n.play() }) }), rn.version = "3.1.0", rn.speed = 1, rn.running = _, rn.remove = function (n) { for (var e = Z(n), r = _.length; r--;) { var t = _[r], a = t.animations, o = t.children; tn(e, a); for (var u = o.length; u--;) { var i = o[u], c = i.animations; tn(e, c), c.length || i.children.length || o.splice(u, 1) } a.length || o.length || t.pause() } }, rn.get = N, rn.set = R, rn.convertPx = I, rn.path = function (n, e) { var r = i.str(n) ? g(n)[0] : n, t = e || 100; return function (n) { return { property: n, el: r, svg: $(r), totalLength: q(r) * (t / 100) } } }, rn.setDashoffset = function (n) { var e = q(n); return n.setAttribute("stroke-dasharray", e), e }, rn.stagger = function (n, e) { void 0 === e && (e = {}); var r = e.direction || "normal", t = e.easing ? v(e.easing) : null, a = e.grid, o = e.axis, u = e.from || 0, c = "first" === u, s = "center" === u, f = "last" === u, l = i.arr(n), d = l ? parseFloat(n[0]) : parseFloat(n), p = l ? parseFloat(n[1]) : 0, h = C(l ? n[1] : n) || 0, g = e.start || 0 + (l ? d : 0), m = [], y = 0; return function (n, e, i) { if (c && (u = 0), s && (u = (i - 1) / 2), f && (u = i - 1), !m.length) { for (var v = 0; v < i; v++) { if (a) { var b = s ? (a[0] - 1) / 2 : u % a[0], M = s ? (a[1] - 1) / 2 : Math.floor(u / a[0]), x = b - v % a[0], w = M - Math.floor(v / a[0]), k = Math.sqrt(x * x + w * w); "x" === o && (k = -x), "y" === o && (k = -w), m.push(k) } else m.push(Math.abs(u - v)); y = Math.max.apply(Math, m) } t && (m = m.map(function (n) { return t(n / y) * y })), "reverse" === r && (m = m.map(function (n) { return o ? n < 0 ? -1 * n : -n : Math.abs(y - n) })) } return g + (l ? (p - d) / y : d) * (Math.round(100 * m[e]) / 100) + h } }, rn.timeline = function (n) { void 0 === n && (n = {}); var r = rn(n); return r.duration = 0, r.add = function (t, a) { var o = _.indexOf(r), u = r.children; function c(n) { n.passThrough = !0 } o > -1 && _.splice(o, 1); for (var s = 0; s < u.length; s++)c(u[s]); var f = k(t, w(e, n)); f.targets = f.targets || n.targets; var l = r.duration; f.autoplay = !1, f.direction = r.direction, f.timelineOffset = i.und(a) ? l : A(a, l), c(r), r.seek(f.timelineOffset); var d = rn(f); c(d), u.push(d); var p = J(u, n); return r.delay = p.delay, r.endDelay = p.endDelay, r.duration = p.duration, r.seek(0), r.reset(), r.autoplay && r.play(), r }, r }, rn.easing = v, rn.penner = h, rn.random = function (n, e) { return Math.floor(Math.random() * (e - n + 1)) + n }, rn }); \ No newline at end of file diff --git a/trunk/research/players/js/srs.page.js b/trunk/research/players/js/srs.page.js index 520491e48..04021abf9 100755 --- a/trunk/research/players/js/srs.page.js +++ b/trunk/research/players/js/srs.page.js @@ -129,7 +129,7 @@ function build_default_whip_whep_url(query, apiPath) { var vhost = (!query.vhost)? window.location.hostname:query.vhost; var app = (!query.app)? "live":query.app; var stream = (!query.stream)? "livestream":query.stream; - var api = ':' + (query.api || (window.location.protocol === 'http:' ? '1985' : '1990')); + var api = ':' + (query.api || (query.schema === 'http' ? '1985' : '1990')); const realApiPath = query.path || apiPath; var queries = []; @@ -141,7 +141,9 @@ function build_default_whip_whep_url(query, apiPath) { } queries = user_extra_params(query, queries, true); - var uri = window.location.protocol + "//" + server + api + realApiPath + "?app=" + app + "&stream=" + stream + "&" + queries.join('&'); + schema = query.schema || window.location.protocol.slice(0, -1); + + var uri = schema + "://" + server + api + realApiPath + "?app=" + app + "&stream=" + stream + "&" + queries.join('&'); while (uri.lastIndexOf("?") === uri.length - 1) { uri = uri.slice(0, uri.length - 1); } @@ -180,3 +182,7 @@ function srs_init_whep(id, query) { update_nav(); $(id).val(build_default_whip_whep_url(query, '/rtc/v1/whep/')); } + +function srs_get_whep(query) { + return build_default_whip_whep_url(query, '/rtc/v1/whep/'); +} diff --git a/trunk/research/players/js/srs.sdk.js b/trunk/research/players/js/srs.sdk.js index e86e46813..8770310f8 100644 --- a/trunk/research/players/js/srs.sdk.js +++ b/trunk/research/players/js/srs.sdk.js @@ -574,7 +574,7 @@ function SrsRtcWhipWhepAsync() { userStream.getTracks().forEach(function (track) { self.pc.addTrack(track); // Notify about local track when stream is ok. - self.ontrack && self.ontrack({track: track}); + // self.ontrack && self.ontrack({track: track}); }); } @@ -602,6 +602,13 @@ function SrsRtcWhipWhepAsync() { return self.__internal.parseId(url, offer.sdp, answer); }; + // 新增回调函数 + self.onconnected = null; // 连接成功回调 + self.onfirstvideo = null; // 收到第一个视频包回调 + self.oninactivevideo = null; // 视频流中断回调 + self.onvideoresume = null; // 视频流恢复回调 + self.onconnectionlost = null; // 连接永久丢失回调 + // See https://datatracker.ietf.org/doc/draft-ietf-wish-whip/ // @url The WebRTC url to play with, for example: // http://localhost:1985/rtc/v1/whep/?app=live&stream=livestream @@ -614,6 +621,19 @@ function SrsRtcWhipWhepAsync() { if (!options?.videoOnly) self.pc.addTransceiver("audio", {direction: "recvonly"}); if (!options?.audioOnly) self.pc.addTransceiver("video", {direction: "recvonly"}); + + if (options.onconnected) self.onconnected = options.onconnected; + if (options.onfirstvideo) self.onfirstvideo = options.onfirstvideo; + if (options.oninactivevideo) self.oninactivevideo = options.oninactivevideo; + if (options.onvideoresume) self.onvideoresume = options.onvideoresume; + if (options.onconnectionlost) self.onconnectionlost = options.onconnectionlost; + + // 监听ICE连接状态 + self.pc.oniceconnectionstatechange = function () { + if (self.pc.iceConnectionState === 'connected') { + self.onconnected && self.onconnected(); + } + }; var offer = await self.pc.createOffer(); await self.pc.setLocalDescription(offer); @@ -641,15 +661,114 @@ function SrsRtcWhipWhepAsync() { // Close the publisher. self.close = function () { - self.pc && self.pc.close(); - self.pc = null; + // 清理所有计时器 + clearInterval(self.__internal.checkInterval); + clearTimeout(self.__internal.inactiveTimer); + + // 重置状态 + self.__internal.checkInterval = null; + self.__internal.inactiveTimer = null; + self.__internal.videoState = 'closed'; + + // 关闭PeerConnection + if (self.pc) { + self.pc.close(); + self.pc = null; + } + }; + + const handleVideoState = { + init: async () => { + const stats = await self.pc.getStats(self.__internal.currentTrack); + stats.forEach(report => { + if (report.type === 'inbound-rtp' && report.kind === 'video') { + if (report.bytesReceived > 0) { + self.__internal.videoState = 'active'; + self.onfirstvideo && self.onfirstvideo(); + } + } + }); + }, + + // 检测中状态 + checking: async () => { + const stats = await self.pc.getStats(self.__internal.currentTrack); + stats.forEach(report => { + if (report.type === 'inbound-rtp' && report.kind === 'video') { + if (report.bytesReceived > self.__internal.lastBytes) { + self.__internal.videoState = 'active'; + self.__internal.lastBytes = report.bytesReceived; + self.__internal.lastActiveTime = Date.now(); + // self.onfirstvideo && self.onfirstvideo(); + self.onvideoresume && self.onvideoresume(); + console.log('🎬 视频流恢复'); + } + } + }); + }, + + active: async () => { + const stats = await self.pc.getStats(self.__internal.currentTrack); + let bytesUpdated = false; + + stats.forEach(report => { + if (report.type === 'inbound-rtp' && report.kind === 'video') { + const currentBytes = report.bytesReceived; + if (currentBytes > self.__internal.lastBytes) { + self.__internal.lastBytes = currentBytes; + self.__internal.lastActiveTime = Date.now(); + bytesUpdated = true; + } + } + }); + + if (!bytesUpdated && Date.now() - self.__internal.lastActiveTime > 3000) { + self.__internal.videoState = 'inactive'; + self.oninactivevideo && self.oninactivevideo(); + + // 启动15秒断开倒计时 + self.__internal.inactiveTimer = setTimeout(() => { + self.onconnectionlost && self.onconnectionlost(); + self.close(); + }, 10000); + } + }, + + inactive: async () => { + const stats = await self.pc.getStats(self.__internal.currentTrack); + stats.forEach(report => { + if (report.type === 'inbound-rtp' && report.kind === 'video') { + if (report.bytesReceived > self.__internal.lastBytes) { + // 清除断开计时器 + clearTimeout(self.__internal.inactiveTimer); + self.__internal.inactiveTimer = null; + + self.__internal.videoState = 'checking'; + } + } + }); + } }; // The callback when got local stream. // @see https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/addStream#Migrating_to_addTrack self.ontrack = function (event) { - // Add track to stream of SDK. self.stream.addTrack(event.track); + + if (event.track.kind === 'video') { + self.__internal.currentTrack = event.track; + + // 启动状态检测引擎 + self.__internal.checkInterval = setInterval(() => { + if (!self.__internal.currentTrack) return; + + // 执行状态机转换 + handleVideoState[self.__internal.videoState]?.(); + }, 1000); // 每秒检测一次 + + // 初始状态转换 + self.__internal.videoState = 'init'; + } }; self.pc = new RTCPeerConnection(null); @@ -661,6 +780,13 @@ function SrsRtcWhipWhepAsync() { // Internal APIs. self.__internal = { + videoState: 'init', + checkInterval: null, + inactiveTimer: null, // 新增断开计时器 + lastBytes: 0, + lastActiveTime: 0, + currentTrack: null, + parseId: (url, offer, answer) => { let sessionid = offer.substr(offer.indexOf('a=ice-ufrag:') + 'a=ice-ufrag:'.length); sessionid = sessionid.substr(0, sessionid.indexOf('\n') - 1) + ':'; diff --git a/trunk/research/players/js/whep_main.js b/trunk/research/players/js/whep_main.js new file mode 100644 index 000000000..37454140f --- /dev/null +++ b/trunk/research/players/js/whep_main.js @@ -0,0 +1,66 @@ +const btns = document.querySelectorAll('.btn'); +const toastContainer = document.querySelector('.toast'); +const buttonYes = document.querySelector('#buttonsYes'); +const buttonNo = document.querySelector('#buttonsNo'); +const buttonsContainer = document.querySelector('#buttonsDiv'); + +const options = { + regular: { + heading: 'This is a Regular notification', + paragraph: 'This toast message notifies you of something. Whatever that may be.', + svg: '' + }, + success: { + heading: 'This is a Success notification', + paragraph: 'This toast message notifies you of all your great successes. You rock!', + svg: '' + }, + error: { + heading: 'This is an Error notification', + paragraph: 'This toast message notifies you of an Error. Don\'t worry it\'s probably not your fault.', + svg: '' + }, + warning: { + heading: 'This is a Warning notification', + paragraph: 'This toast message notifies you of a Warning. Who knows what might have happened.', + svg: '' + } +} + +function createToast({type='regular', buttons='false', close='true', heading='', paragraph='', button1='', button2=''}) { + const html = ` + + ${options[type].svg} + + + ${heading ? heading : options[type].heading} + + + ${paragraph ? paragraph : options[type].paragraph} + + + ${close === 'true' ? `×` : ''} + + + `; + toastContainer.insertAdjacentHTML('beforeend', html); + + const toast = toastContainer.lastElementChild; + toast.addEventListener('animationend', () => toast.remove()); +} + +function resetForm() { + document.querySelector('#heading').value = ''; + document.querySelector('#paragraph').value = ''; +} + +btns.forEach(btn => btn.addEventListener('click', function(e) { + e.preventDefault(); + const close = document.querySelector('input[name=close]:checked').value; + const heading = document.querySelector('#heading').value; + const paragraph = document.querySelector('#paragraph').value; + resetForm(); + createToast({type: this.value, close, heading, paragraph}); +})); + + diff --git a/trunk/research/players/whep.html b/trunk/research/players/whep.html deleted file mode 100644 index a1939e86a..000000000 --- a/trunk/research/players/whep.html +++ /dev/null @@ -1,131 +0,0 @@ - - - - SRS - - - - - - - - - - - - - - - SRS - - - LivePlayer - - - WHIP - WHEP - iOS/Andriod - - - - - - - - - - - - - - × - Usage: Enter the WebRTC WHEP URL and click "Play" to start playing. - - - URL: - - Play - - - - - - - - Controls: - - Video Only - - - Audio Only - - - - SessionID: - - - Simulator: Drop - - - - - - - diff --git a/trunk/research/players/whep_itp.html b/trunk/research/players/whep_itp.html new file mode 100644 index 000000000..430991083 --- /dev/null +++ b/trunk/research/players/whep_itp.html @@ -0,0 +1,371 @@ + + + + + + NPL ITP Intranet Livestream Channel + + + + + + + + + + + + + + NPL ITP + Intranet Livestream Channel + Connecting to the SRS Server ... + Loading... + + + + + + + + + + + + diff --git a/trunk/src/app/srs_app_config.cpp b/trunk/src/app/srs_app_config.cpp index d74f4b410..5f6fb7791 100644 --- a/trunk/src/app/srs_app_config.cpp +++ b/trunk/src/app/srs_app_config.cpp @@ -23,6 +23,7 @@ #include #include +#include using namespace std; #include @@ -333,12 +334,30 @@ bool srs_config_apply_filter(SrsConfDirective* dvr_apply, SrsRequest* req) if (args.size() == 1 && dvr_apply->arg0() == "all") { return true; } - + string id = req->app + "/" + req->stream; if (std::find(args.begin(), args.end(), id) != args.end()) { return true; } - + + for (const string& pattern : args) { + // 如果模式以/开始和结束,则视为正则表达式 + if (pattern.size() >= 2 && pattern.front() == '/' && pattern.back() == '/') { + try { + std::regex re(pattern.substr(1, pattern.size() - 2)); + if (std::regex_match(id, re)) { + return true; + } + } catch (const std::regex_error&) { + // 正则表达式无效,跳过这条规则 + continue; + } + } else if (pattern == id) { + // 普通字符串匹配 + return true; + } + } + return false; } diff --git a/trunk/src/app/srs_app_config.hpp b/trunk/src/app/srs_app_config.hpp index bfb87445f..cfc875d73 100644 --- a/trunk/src/app/srs_app_config.hpp +++ b/trunk/src/app/srs_app_config.hpp @@ -14,6 +14,7 @@ #include #include #include +#include #include #include diff --git a/trunk/src/app/srs_app_hls.cpp b/trunk/src/app/srs_app_hls.cpp index 1a4f9f7f7..47022b9ae 100644 --- a/trunk/src/app/srs_app_hls.cpp +++ b/trunk/src/app/srs_app_hls.cpp @@ -1068,7 +1068,7 @@ srs_error_t SrsHlsController::write_video(SrsVideoFrame* frame, int64_t dts) // Refresh the codec ASAP. if (muxer->latest_vcodec() != frame->vcodec()->id) { - srs_trace("HLS: Switch video codec %d(%s) to %d(%s)", muxer->latest_vcodec(), srs_video_codec_id2str(muxer->latest_vcodec()).c_str(), + srs_trace("HLS: Switch video codec %d(%s) to %d(%s)", muxer->latest_acodec(), srs_video_codec_id2str(muxer->latest_vcodec()).c_str(), frame->vcodec()->id, srs_video_codec_id2str(frame->vcodec()->id).c_str()); muxer->set_latest_vcodec(frame->vcodec()->id); } diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index 410db4185..af2fbcfdc 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -2598,51 +2598,6 @@ bool srs_sdp_has_h264_profile(const SrsSdp& sdp, const string& profile) return false; } -bool srs_sdp_has_h265_profile(const SrsMediaPayloadType& payload_type, const string& profile) -{ - srs_error_t err = srs_success; - - if (payload_type.format_specific_param_.empty()) { - return false; - } - - H265SpecificParam h265_param; - if ((err = srs_parse_h265_fmtp(payload_type.format_specific_param_, h265_param)) != srs_success) { - srs_error_reset(err); - return false; - } - - if (h265_param.profile_id == profile) { - return true; - } - - return false; -} - -bool srs_sdp_has_h265_profile(const SrsSdp& sdp, const string& profile) -{ - for (size_t i = 0; i < sdp.media_descs_.size(); ++i) { - const SrsMediaDesc& desc = sdp.media_descs_[i]; - if (!desc.is_video()) { - continue; - } - - std::vector payloads = desc.find_media_with_encoding_name("H265"); - if (payloads.empty()) { - continue; - } - - for (std::vector::iterator it = payloads.begin(); it != payloads.end(); ++it) { - const SrsMediaPayloadType& payload_type = *it; - if (srs_sdp_has_h265_profile(payload_type, profile)) { - return true; - } - } - } - - return false; -} - srs_error_t SrsRtcConnection::negotiate_publish_capability(SrsRtcUserConfig* ruc, SrsRtcSourceDescription* stream_desc) { srs_error_t err = srs_success; @@ -3086,6 +3041,8 @@ srs_error_t SrsRtcConnection::negotiate_play_capability(SrsRtcUserConfig* ruc, s bool nack_enabled = _srs_config->get_rtc_nack_enabled(req->vhost); bool twcc_enabled = _srs_config->get_rtc_twcc_enabled(req->vhost); + // TODO: FIME: Should check packetization-mode=1 also. + bool has_42e01f = srs_sdp_has_h264_profile(remote_sdp, "42e01f"); SrsSharedPtr source; if ((err = _srs_rtc_sources->fetch_or_create(req, source)) != srs_success) { @@ -3126,87 +3083,56 @@ srs_error_t SrsRtcConnection::negotiate_play_capability(SrsRtcUserConfig* ruc, s remote_payload = payloads.at(0); track_descs = source->get_track_desc("audio", "opus"); + } else if (remote_media_desc.is_video() && ruc->codec_ == "av1") { + std::vector payloads = remote_media_desc.find_media_with_encoding_name("AV1"); + if (payloads.empty()) { + // Be compatible with the Chrome M96, still check the AV1X encoding name + // @see https://bugs.chromium.org/p/webrtc/issues/detail?id=13166 + payloads = remote_media_desc.find_media_with_encoding_name("AV1X"); + } + if (payloads.empty()) { + return srs_error_new(ERROR_RTC_SDP_EXCHANGE, "no found valid AV1 payload type"); + } + + remote_payload = payloads.at(0); + track_descs = source->get_track_desc("video", "AV1"); + if (track_descs.empty()) { + // Be compatible with the Chrome M96, still check the AV1X encoding name + // @see https://bugs.chromium.org/p/webrtc/issues/detail?id=13166 + track_descs = source->get_track_desc("video", "AV1X"); + } + } else if (remote_media_desc.is_video() && ruc->codec_ == "hevc") { + std::vector payloads = remote_media_desc.find_media_with_encoding_name("H265"); + if (payloads.empty()) { + return srs_error_new(ERROR_RTC_SDP_EXCHANGE, "no valid found h265 payload type"); + } + + remote_payload = payloads.at(0); + + // TODO: FIXME: pick up a profile for HEVC. + // @see https://www.rfc-editor.org/rfc/rfc7798#section-7.2.1 + + track_descs = source->get_track_desc("video", "H265"); } else if (remote_media_desc.is_video()) { - std::string prefer_codec = ruc->codec_; - if (prefer_codec.empty()) { - // Get the source codec if not specified. - std::vector track_descs = source->get_track_desc("video", ""); - if (!track_descs.empty()) { - std::string codec_name = track_descs.at(0)->media_->name_; - std::transform(codec_name.begin(), codec_name.end(), codec_name.begin(), ::tolower); - if (codec_name == "h265") { - prefer_codec = "hevc"; - } else { - prefer_codec = codec_name; - } - } else { - return srs_error_new(ERROR_RTC_SDP_EXCHANGE, "no video track in source"); - } + // TODO: check opus format specific param + vector payloads = remote_media_desc.find_media_with_encoding_name("H264"); + if (payloads.empty()) { + return srs_error_new(ERROR_RTC_SDP_EXCHANGE, "no valid found h264 payload type"); } - if (prefer_codec == "av1") { - std::vector payloads = remote_media_desc.find_media_with_encoding_name("AV1"); - if (payloads.empty()) { - // Be compatible with the Chrome M96, still check the AV1X encoding name - // @see https://bugs.chromium.org/p/webrtc/issues/detail?id=13166 - payloads = remote_media_desc.find_media_with_encoding_name("AV1X"); - } - if (payloads.empty()) { - return srs_error_new(ERROR_RTC_SDP_EXCHANGE, "no found valid AV1 payload type"); - } - - remote_payload = payloads.at(0); - track_descs = source->get_track_desc("video", "AV1"); - if (track_descs.empty()) { - // Be compatible with the Chrome M96, still check the AV1X encoding name - // @see https://bugs.chromium.org/p/webrtc/issues/detail?id=13166 - track_descs = source->get_track_desc("video", "AV1X"); - } - } else if (prefer_codec == "hevc") { - std::vector payloads = remote_media_desc.find_media_with_encoding_name("H265"); - if (payloads.empty()) { - return srs_error_new(ERROR_RTC_SDP_EXCHANGE, "no valid found h265 payload type"); - } - - // @see https://www.rfc-editor.org/rfc/rfc7798#section-7.2.1 - bool has_main_profile = srs_sdp_has_h265_profile(remote_sdp, "1"); - remote_payload = payloads.at(0); - - for (int j = 0; j < (int)payloads.size(); j++) { - const SrsMediaPayloadType& payload = payloads.at(j); - - // For H.265, we only check if profile-id=1 (Main Profile) - // Format example: level-id=180;profile-id=1;tier-flag=0;tx-mode=SRST - if (!has_main_profile || srs_sdp_has_h265_profile(payload, "1")) { - remote_payload = payload; - break; - } - } - - track_descs = source->get_track_desc("video", "H265"); - } else { - vector payloads = remote_media_desc.find_media_with_encoding_name("H264"); - if (payloads.empty()) { - return srs_error_new(ERROR_RTC_SDP_EXCHANGE, "no valid found h264 payload type"); - } + remote_payload = payloads.at(0); + for (int j = 0; j < (int)payloads.size(); j++) { + const SrsMediaPayloadType& payload = payloads.at(j); + // If exists 42e01f profile, choose it; otherwise, use the first payload. // TODO: FIME: Should check packetization-mode=1 also. - bool has_42e01f = srs_sdp_has_h264_profile(remote_sdp, "42e01f"); - - remote_payload = payloads.at(0); - for (int j = 0; j < (int)payloads.size(); j++) { - const SrsMediaPayloadType& payload = payloads.at(j); - - // If exists 42e01f profile, choose it; otherwise, use the first payload. - // TODO: FIME: Should check packetization-mode=1 also. - if (!has_42e01f || srs_sdp_has_h264_profile(payload, "42e01f")) { - remote_payload = payload; - break; - } + if (!has_42e01f || srs_sdp_has_h264_profile(payload, "42e01f")) { + remote_payload = payload; + break; } - - track_descs = source->get_track_desc("video", "H264"); } + + track_descs = source->get_track_desc("video", "H264"); } for (int j = 0; j < (int)track_descs.size(); ++j) { @@ -3312,11 +3238,7 @@ void video_track_generate_play_offer(SrsRtcTrackDescription* track, string mid, SrsVideoPayload* payload = (SrsVideoPayload*)track->media_; - if (payload->name_ == "H265") { - local_media_desc.payload_types_.push_back(payload->generate_media_payload_type_h265()); - } else { - local_media_desc.payload_types_.push_back(payload->generate_media_payload_type()); - } + local_media_desc.payload_types_.push_back(payload->generate_media_payload_type()); if (track->red_) { SrsRedPayload* red_payload = (SrsRedPayload*)track->red_; diff --git a/trunk/src/app/srs_app_rtc_sdp.cpp b/trunk/src/app/srs_app_rtc_sdp.cpp index d87c5e097..e6f298a4e 100644 --- a/trunk/src/app/srs_app_rtc_sdp.cpp +++ b/trunk/src/app/srs_app_rtc_sdp.cpp @@ -92,42 +92,6 @@ srs_error_t srs_parse_h264_fmtp(const std::string& fmtp, H264SpecificParam& h264 return err; } -srs_error_t srs_parse_h265_fmtp(const std::string& fmtp, H265SpecificParam& h265_param) -{ - srs_error_t err = srs_success; - - std::vector vec = srs_string_split(fmtp, ";"); - for (size_t i = 0; i < vec.size(); ++i) { - std::vector kv = srs_string_split(vec[i], "="); - if (kv.size() != 2) continue; - - if (kv[0] == "level-id") { - h265_param.level_id = kv[1]; - } else if (kv[0] == "profile-id") { - h265_param.profile_id = kv[1]; - } else if (kv[0] == "tier-flag") { - h265_param.tier_flag = kv[1]; - } else if (kv[0] == "tx-mode") { - h265_param.tx_mode = kv[1]; - } - } - - if (h265_param.level_id.empty()) { - return srs_error_new(ERROR_RTC_SDP_DECODE, "no h265 param: level-id"); - } - if (h265_param.profile_id.empty()) { - return srs_error_new(ERROR_RTC_SDP_DECODE, "no h265 param: profile-id"); - } - if (h265_param.tier_flag.empty()) { - return srs_error_new(ERROR_RTC_SDP_DECODE, "no h265 param: tier-flag"); - } - if (h265_param.tx_mode.empty()) { - return srs_error_new(ERROR_RTC_SDP_DECODE, "no h265 param: tx-mode"); - } - - return err; -} - SrsSessionInfo::SrsSessionInfo() { } diff --git a/trunk/src/app/srs_app_rtc_sdp.hpp b/trunk/src/app/srs_app_rtc_sdp.hpp index 39dbb8f0d..d2aba8a48 100644 --- a/trunk/src/app/srs_app_rtc_sdp.hpp +++ b/trunk/src/app/srs_app_rtc_sdp.hpp @@ -97,16 +97,8 @@ struct H264SpecificParam std::string level_asymmerty_allow; }; -struct H265SpecificParam -{ - std::string level_id; - std::string profile_id; - std::string tier_flag; - std::string tx_mode; -}; - extern srs_error_t srs_parse_h264_fmtp(const std::string& fmtp, H264SpecificParam& h264_param); -extern srs_error_t srs_parse_h265_fmtp(const std::string& fmtp, H265SpecificParam& h265_param); + class SrsMediaPayloadType { public: diff --git a/trunk/src/app/srs_app_rtc_source.cpp b/trunk/src/app/srs_app_rtc_source.cpp index 1e5deef0d..9292ccc1b 100644 --- a/trunk/src/app/srs_app_rtc_source.cpp +++ b/trunk/src/app/srs_app_rtc_source.cpp @@ -785,15 +785,7 @@ std::vector SrsRtcSource::get_track_desc(std::string ty if (type == "video") { std::vector::iterator it = stream_desc_->video_track_descs_.begin(); while (it != stream_desc_->video_track_descs_.end() ){ - if (media_name.empty()) { - track_descs.push_back(*it); - } else { - string name = (*it)->media_->name_; - std::transform(name.begin(), name.end(), name.begin(), static_cast(std::toupper)); - if (name == media_name) { - track_descs.push_back(*it); - } - } + track_descs.push_back(*it); ++it; } } @@ -1082,15 +1074,10 @@ srs_error_t SrsRtcRtpBuilder::on_video(SrsSharedPtrMessage* msg) return err; } - // support video codec: h264/h265 - SrsVideoCodecId vcodec = format->vcodec->id; - if (vcodec != SrsVideoCodecIdAVC && vcodec != SrsVideoCodecIdHEVC) { - return err; - } - + // WebRTC does NOT support HEVC. #ifdef SRS_H265 - if ((err = bridge_->update_codec(vcodec)) != srs_success) { - return srs_error_wrap(err, "update codec"); + if (format->vcodec->id == SrsVideoCodecIdHEVC) { + return err; } #endif @@ -1174,16 +1161,10 @@ srs_error_t SrsRtcRtpBuilder::filter(SrsSharedPtrMessage* msg, SrsFormat* format // Because RTC does not support B-frame, so we will drop them. // TODO: Drop B-frame in better way, which not cause picture corruption. - if (!keep_bframe) { - bool is_b_frame = false; - if (format->vcodec->id == SrsVideoCodecIdAVC) { - if ((err = SrsVideoFrame::parse_avc_bframe(sample, is_b_frame)) != srs_success) { - return srs_error_wrap(err, "parse bframe"); - } - } else if (format->vcodec->id == SrsVideoCodecIdHEVC) { - if ((err = SrsVideoFrame::parse_hevc_bframe(sample, format, is_b_frame)) != srs_success) { - return srs_error_wrap(err, "parse bframe"); - } + if (!keep_bframe && format->vcodec->id == SrsVideoCodecIdAVC) { + bool is_b_frame; + if ((err = SrsVideoFrame::parse_avc_b_frame(sample, is_b_frame)) != srs_success) { + return srs_error_wrap(err, "parse bframe"); } if (is_b_frame) { continue; @@ -1205,60 +1186,53 @@ srs_error_t SrsRtcRtpBuilder::package_stap_a(SrsSharedPtrMessage* msg, SrsRtpPac return err; } + // Note that the sps/pps may change, so we should copy it. + const vector& sps = format->vcodec->sequenceParameterSetNALUnit; + const vector& pps = format->vcodec->pictureParameterSetNALUnit; + if (sps.empty() || pps.empty()) { + return srs_error_new(ERROR_RTC_RTP_MUXER, "sps/pps empty"); + } + pkt->header.set_payload_type(video_payload_type_); pkt->header.set_ssrc(video_ssrc_); pkt->frame_type = SrsFrameTypeVideo; + pkt->nalu_type = (SrsAvcNaluType)kStapA; pkt->header.set_marker(false); pkt->header.set_sequence(video_sequence++); pkt->header.set_timestamp(msg->timestamp * 90); - ISrsRtpPayloader* stap = NULL; - vector*> params; - int size = 0; - if (format->vcodec->id == SrsVideoCodecIdHEVC) { - for (size_t i = 0; i < format->vcodec->hevc_dec_conf_record_.nalu_vec.size(); i++) { - if (format->vcodec->hevc_dec_conf_record_.nalu_vec[i].nal_unit_type == SrsHevcNaluType_VPS - || format->vcodec->hevc_dec_conf_record_.nalu_vec[i].nal_unit_type == SrsHevcNaluType_SPS - || format->vcodec->hevc_dec_conf_record_.nalu_vec[i].nal_unit_type == SrsHevcNaluType_PPS) { - vector& nalu = (vector&)format->vcodec->hevc_dec_conf_record_.nalu_vec[i].nal_data_vec[0].nal_unit_data; - params.push_back(&nalu); - size += format->vcodec->hevc_dec_conf_record_.nalu_vec[i].nal_data_vec[0].nal_unit_length; - } - } + SrsRtpSTAPPayload* stap = new SrsRtpSTAPPayload(); + pkt->set_payload(stap, SrsRtspPacketPayloadTypeSTAP); - stap = new SrsRtpSTAPPayloadHevc(); - pkt->set_payload(stap, SrsRtspPacketPayloadTypeSTAPHevc); - pkt->nalu_type = kStapHevc; - } else if (format->vcodec->id == SrsVideoCodecIdAVC) { - params.push_back(&format->vcodec->sequenceParameterSetNALUnit); - params.push_back(&format->vcodec->pictureParameterSetNALUnit); - size = format->vcodec->sequenceParameterSetNALUnit.size() + format->vcodec->pictureParameterSetNALUnit.size(); + uint8_t header = sps[0]; + stap->nri = (SrsAvcNaluType)header; - stap = new SrsRtpSTAPPayload(); - pkt->set_payload(stap, SrsRtspPacketPayloadTypeSTAP); - pkt->nalu_type = kStapA; - } - - if (size == 0) { - return srs_error_new(ERROR_RTC_RTP_MUXER, "vps/sps/pps empty"); - } + // Copy the SPS/PPS bytes, because it may change. + int size = (int)(sps.size() + pps.size()); char* payload = pkt->wrap(size); - for (vector*>::iterator it = params.begin(); it != params.end(); ++it) { - vector* param = *it; + if (true) { SrsSample* sample = new SrsSample(); sample->bytes = payload; - sample->size = param->size(); - if (format->vcodec->id == SrsVideoCodecIdHEVC) { - static_cast(stap)->nalus.push_back(sample); - } else { - static_cast(stap)->nalus.push_back(sample); - } + sample->size = (int)sps.size(); + stap->nalus.push_back(sample); - memcpy(payload, (char*)param->data(), param->size()); - payload += (int)param->size(); + memcpy(payload, (char*)&sps[0], sps.size()); + payload += (int)sps.size(); } + if (true) { + SrsSample* sample = new SrsSample(); + sample->bytes = payload; + sample->size = (int)pps.size(); + stap->nalus.push_back(sample); + + memcpy(payload, (char*)&pps[0], pps.size()); + payload += (int)pps.size(); + } + + srs_info("RTC STAP-A seq=%u, sps %d, pps %d bytes", pkt->header.get_sequence(), sps.size(), pps.size()); + return err; } @@ -1266,14 +1240,8 @@ srs_error_t SrsRtcRtpBuilder::package_nalus(SrsSharedPtrMessage* msg, const vect { srs_error_t err = srs_success; - SrsFormat* format = meta->vsh_format(); - if (!format || !format->vcodec) { - return err; - } - bool is_hevc = format->vcodec->id == SrsVideoCodecIdHEVC; - SrsRtpRawNALUs* raw_raw = new SrsRtpRawNALUs(); - uint8_t first_nalu_type = 0; + SrsAvcNaluType first_nalu_type = SrsAvcNaluTypeReserved; for (int i = 0; i < (int)samples.size(); i++) { SrsSample* sample = samples[i]; @@ -1282,8 +1250,8 @@ srs_error_t SrsRtcRtpBuilder::package_nalus(SrsSharedPtrMessage* msg, const vect continue; } - if (first_nalu_type == 0) { - first_nalu_type = is_hevc ? uint8_t(SrsHevcNaluTypeParse(sample->bytes[0])) : uint8_t(SrsAvcNaluTypeParse(sample->bytes[0])); + if (first_nalu_type == SrsAvcNaluTypeReserved) { + first_nalu_type = SrsAvcNaluType((uint8_t)(sample->bytes[0] & kNalTypeMask)); } raw_raw->push_back(sample->copy()); @@ -1304,7 +1272,7 @@ srs_error_t SrsRtcRtpBuilder::package_nalus(SrsSharedPtrMessage* msg, const vect pkt->header.set_payload_type(video_payload_type_); pkt->header.set_ssrc(video_ssrc_); pkt->frame_type = SrsFrameTypeVideo; - pkt->nalu_type = first_nalu_type; + pkt->nalu_type = (SrsAvcNaluType)first_nalu_type; pkt->header.set_sequence(video_sequence++); pkt->header.set_timestamp(msg->timestamp * 90); pkt->set_payload(raw_raw, SrsRtspPacketPayloadTypeNALU); @@ -1314,54 +1282,40 @@ srs_error_t SrsRtcRtpBuilder::package_nalus(SrsSharedPtrMessage* msg, const vect // because more than one RTP packet will refer to it. SrsUniquePtr raw(raw_raw); - int header_size = is_hevc ? SrsHevcNaluHeaderSize : SrsAvcNaluHeaderSize; - // Package NALUs in FU-A RTP packets. int fu_payload_size = kRtpMaxPayloadSize; // The first byte is store in FU-A header. - uint8_t header = raw->skip_bytes(header_size); - - int nb_left = nn_bytes - header_size; + uint8_t header = raw->skip_first_byte(); + uint8_t nal_type = header & kNalTypeMask; + int nb_left = nn_bytes - 1; int num_of_packet = 1 + (nn_bytes - 1) / fu_payload_size; for (int i = 0; i < num_of_packet; ++i) { int packet_size = srs_min(nb_left, fu_payload_size); + SrsRtpFUAPayload* fua = new SrsRtpFUAPayload(); + if ((err = raw->read_samples(fua->nalus, packet_size)) != srs_success) { + srs_freep(fua); + return srs_error_wrap(err, "read samples %d bytes, left %d, total %d", packet_size, nb_left, nn_bytes); + } + SrsRtpPacket* pkt = new SrsRtpPacket(); pkts.push_back(pkt); pkt->header.set_payload_type(video_payload_type_); pkt->header.set_ssrc(video_ssrc_); pkt->frame_type = SrsFrameTypeVideo; - pkt->nalu_type = kFuA; + pkt->nalu_type = (SrsAvcNaluType)kFuA; pkt->header.set_sequence(video_sequence++); pkt->header.set_timestamp(msg->timestamp * 90); - if (is_hevc) { - SrsRtpFUAPayloadHevc* fua = new SrsRtpFUAPayloadHevc(); - if ((err = raw->read_samples(fua->nalus, packet_size)) != srs_success) { - srs_freep(fua); - return srs_error_wrap(err, "read hevc samples %d bytes, left %d, total %d", packet_size, nb_left, nn_bytes); - } - fua->nalu_type = SrsHevcNaluTypeParse(header); - fua->start = bool(i == 0); - fua->end = bool(i == num_of_packet - 1); - - pkt->set_payload(fua, SrsRtspPacketPayloadTypeFUAHevc); - } else { - SrsRtpFUAPayload* fua = new SrsRtpFUAPayload(); - if ((err = raw->read_samples(fua->nalus, packet_size)) != srs_success) { - srs_freep(fua); - return srs_error_wrap(err, "read samples %d bytes, left %d, total %d", packet_size, nb_left, nn_bytes); - } - fua->nalu_type = SrsAvcNaluTypeParse(header); - fua->start = bool(i == 0); - fua->end = bool(i == num_of_packet - 1); - - pkt->set_payload(fua, SrsRtspPacketPayloadTypeFUA); - } + fua->nri = (SrsAvcNaluType)header; + fua->nalu_type = (SrsAvcNaluType)nal_type; + fua->start = bool(i == 0); + fua->end = bool(i == num_of_packet - 1); + pkt->set_payload(fua, SrsRtspPacketPayloadTypeFUA); pkt->wrap(msg); nb_left -= packet_size; @@ -1400,19 +1354,11 @@ srs_error_t SrsRtcRtpBuilder::package_fu_a(SrsSharedPtrMessage* msg, SrsSample* { srs_error_t err = srs_success; - SrsFormat* format = meta->vsh_format(); - if (!format || !format->vcodec) { - return err; - } - - bool is_hevc = format->vcodec->id == SrsVideoCodecIdHEVC; - int header_size = is_hevc ? SrsHevcNaluHeaderSize : SrsAvcNaluHeaderSize; - srs_assert(sample->size >= header_size); - - char* p = sample->bytes + header_size; - int nb_left = sample->size - header_size; + char* p = sample->bytes + 1; + int nb_left = sample->size - 1; uint8_t header = sample->bytes[0]; - + uint8_t nal_type = header & kNalTypeMask; + int num_of_packet = 1 + (nb_left - 1) / fu_payload_size; for (int i = 0; i < num_of_packet; ++i) { int packet_size = srs_min(nb_left, fu_payload_size); @@ -1425,32 +1371,17 @@ srs_error_t SrsRtcRtpBuilder::package_fu_a(SrsSharedPtrMessage* msg, SrsSample* pkt->frame_type = SrsFrameTypeVideo; pkt->header.set_sequence(video_sequence++); pkt->header.set_timestamp(msg->timestamp * 90); - pkt->nalu_type = is_hevc ? kFuHevc : kFuA; - if (is_hevc) { - // H265 FU-A header - SrsRtpFUAPayloadHevc2* fua = new SrsRtpFUAPayloadHevc2(); - pkt->set_payload(fua, SrsRtspPacketPayloadTypeFUAHevc2); + SrsRtpFUAPayload2* fua = new SrsRtpFUAPayload2(); + pkt->set_payload(fua, SrsRtspPacketPayloadTypeFUA2); - fua->nalu_type = SrsHevcNaluTypeParse(header); - fua->start = bool(i == 0); - fua->end = bool(i == num_of_packet - 1); + fua->nri = (SrsAvcNaluType)header; + fua->nalu_type = (SrsAvcNaluType)nal_type; + fua->start = bool(i == 0); + fua->end = bool(i == num_of_packet - 1); - fua->payload = p; - fua->size = packet_size; - } else { - // H264 FU-A header - SrsRtpFUAPayload2* fua = new SrsRtpFUAPayload2(); - pkt->set_payload(fua, SrsRtspPacketPayloadTypeFUA2); - - fua->nri = (SrsAvcNaluType)header; - fua->nalu_type = SrsAvcNaluTypeParse(header); - fua->start = bool(i == 0); - fua->end = bool(i == num_of_packet - 1); - - fua->payload = p; - fua->size = packet_size; - } + fua->payload = p; + fua->size = packet_size; pkt->wrap(msg); @@ -2134,7 +2065,6 @@ SrsVideoPayload* SrsVideoPayload::copy() cp->sample_ = sample_; cp->rtcp_fbs_ = rtcp_fbs_; cp->h264_param_ = h264_param_; - cp->h265_param_ = h265_param_; return cp; } @@ -2148,55 +2078,14 @@ SrsMediaPayloadType SrsVideoPayload::generate_media_payload_type() media_payload_type.rtcp_fb_ = rtcp_fbs_; std::ostringstream format_specific_param; - bool has_param = false; - if (!h264_param_.level_asymmerty_allow.empty()) { format_specific_param << "level-asymmetry-allowed=" << h264_param_.level_asymmerty_allow; - has_param = true; } if (!h264_param_.packetization_mode.empty()) { - if (has_param) format_specific_param << ";"; - format_specific_param << "packetization-mode=" << h264_param_.packetization_mode; - has_param = true; + format_specific_param << ";packetization-mode=" << h264_param_.packetization_mode; } if (!h264_param_.profile_level_id.empty()) { - if (has_param) format_specific_param << ";"; - format_specific_param << "profile-level-id=" << h264_param_.profile_level_id; - } - - media_payload_type.format_specific_param_ = format_specific_param.str(); - - return media_payload_type; -} - -SrsMediaPayloadType SrsVideoPayload::generate_media_payload_type_h265() -{ - SrsMediaPayloadType media_payload_type(pt_); - - media_payload_type.encoding_name_ = name_; - media_payload_type.clock_rate_ = sample_; - media_payload_type.rtcp_fb_ = rtcp_fbs_; - - std::ostringstream format_specific_param; - bool has_param = false; - - if (!h265_param_.level_id.empty()) { - format_specific_param << "level-id=" << h265_param_.level_id; - has_param = true; - } - if (!h265_param_.profile_id.empty()) { - if (has_param) format_specific_param << ";"; - format_specific_param << "profile-id=" << h265_param_.profile_id; - has_param = true; - } - if (!h265_param_.tier_flag.empty()) { - if (has_param) format_specific_param << ";"; - format_specific_param << "tier-flag=" << h265_param_.tier_flag; - has_param = true; - } - if (!h265_param_.tx_mode.empty()) { - if (has_param) format_specific_param << ";"; - format_specific_param << "tx-mode=" << h265_param_.tx_mode; + format_specific_param << ";profile-level-id=" << h264_param_.profile_level_id; } media_payload_type.format_specific_param_ = format_specific_param.str(); @@ -2241,31 +2130,6 @@ srs_error_t SrsVideoPayload::set_h264_param_desc(std::string fmtp) return err; } -// level-id=180;profile-id=1;tier-flag=0;tx-mode=SRST -srs_error_t SrsVideoPayload::set_h265_param_desc(std::string fmtp) -{ - std::vector attributes = split_str(fmtp, ";"); - for (size_t i = 0; i < attributes.size(); ++i) { - std::string attribute = attributes.at(i); - std::vector kv = split_str(attribute, "="); - if (kv.size() != 2) { - return srs_error_new(ERROR_RTC_SDP_DECODE, "invalid h265 param=%s", attribute.c_str()); - } - if (kv[0] == "level-id") { - h265_param_.level_id = kv[1]; - } else if (kv[0] == "profile-id") { - h265_param_.profile_id = kv[1]; - } else if (kv[0] == "tier-flag") { - h265_param_.tier_flag = kv[1]; - } else if (kv[0] == "tx-mode") { - h265_param_.tx_mode = kv[1]; - } else { - return srs_error_new(ERROR_RTC_SDP_DECODE, "invalid h265 param=%s", kv[0].c_str()); - } - } - return srs_success; -} - SrsAudioPayload::SrsAudioPayload() { channel_ = 0; @@ -2858,7 +2722,7 @@ void SrsRtcVideoRecvTrack::on_before_decode_payload(SrsRtpPacket* pkt, SrsBuffer } uint8_t v = (uint8_t)(buf->head()[0] & kNalTypeMask); - pkt->nalu_type = v; + pkt->nalu_type = SrsAvcNaluType(v); if (v == kStapA) { *ppayload = new SrsRtpSTAPPayload(); diff --git a/trunk/src/app/srs_app_rtc_source.hpp b/trunk/src/app/srs_app_rtc_source.hpp index 13e03efb0..3efe3904d 100644 --- a/trunk/src/app/srs_app_rtc_source.hpp +++ b/trunk/src/app/srs_app_rtc_source.hpp @@ -396,7 +396,6 @@ class SrsVideoPayload : public SrsCodecPayload { public: H264SpecificParam h264_param_; - H265SpecificParam h265_param_; public: SrsVideoPayload(); @@ -405,10 +404,8 @@ public: public: virtual SrsVideoPayload* copy(); virtual SrsMediaPayloadType generate_media_payload_type(); - virtual SrsMediaPayloadType generate_media_payload_type_h265(); public: srs_error_t set_h264_param_desc(std::string fmtp); - srs_error_t set_h265_param_desc(std::string fmtp); }; // TODO: FIXME: Rename it. diff --git a/trunk/src/app/srs_app_stream_bridge.cpp b/trunk/src/app/srs_app_stream_bridge.cpp index 80e0b999b..de2915d92 100644 --- a/trunk/src/app/srs_app_stream_bridge.cpp +++ b/trunk/src/app/srs_app_stream_bridge.cpp @@ -85,7 +85,7 @@ SrsFrameToRtcBridge::SrsFrameToRtcBridge(SrsSharedPtr source) // video track ssrc if (true) { - std::vector descs = source->get_track_desc("video", ""); + std::vector descs = source->get_track_desc("video", "H264"); if (!descs.empty()) { video_ssrc = descs.at(0)->ssrc_; } @@ -95,8 +95,6 @@ SrsFrameToRtcBridge::SrsFrameToRtcBridge(SrsSharedPtr source) rtp_builder_ = new SrsRtcRtpBuilder(this, audio_ssrc, audio_payload_type, video_ssrc, video_payload_type); #endif - - video_codec_id_ = SrsVideoCodecIdReserved; } SrsFrameToRtcBridge::~SrsFrameToRtcBridge() @@ -157,39 +155,6 @@ srs_error_t SrsFrameToRtcBridge::on_rtp(SrsRtpPacket* pkt) { return source_->on_rtp(pkt); } - -srs_error_t SrsFrameToRtcBridge::update_codec(SrsVideoCodecId id) -{ - srs_error_t err = srs_success; - - if (video_codec_id_ == id) { - return err; - } - - std::vector video_track_descs = source_->get_track_desc("video", ""); - if (video_track_descs.empty()) { - return srs_error_new(ERROR_RTC_NO_TRACK, "no track found for conversion"); - } - - SrsRtcTrackDescription* video_track_desc = video_track_descs.at(0); - SrsVideoPayload* video_payload = (SrsVideoPayload*)video_track_desc->media_; - - if (id == SrsVideoCodecIdHEVC) { - video_payload->name_ = "H265"; - video_payload->set_h265_param_desc("level-id=180;profile-id=1;tier-flag=0;tx-mode=SRST"); - } else { - video_payload->name_ = "H264"; - video_payload->set_h264_param_desc("level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42e01f"); - } - - srs_trace("RTC: Switch video codec %d(%s) to %d(%s)", video_codec_id_, srs_video_codec_id2str(video_codec_id_).c_str(), - id, srs_video_codec_id2str(id).c_str()); - - video_codec_id_ = id; - - return err; -} - #endif SrsCompositeBridge::SrsCompositeBridge() diff --git a/trunk/src/app/srs_app_stream_bridge.hpp b/trunk/src/app/srs_app_stream_bridge.hpp index d5391c97c..dfa4857c8 100644 --- a/trunk/src/app/srs_app_stream_bridge.hpp +++ b/trunk/src/app/srs_app_stream_bridge.hpp @@ -65,8 +65,6 @@ private: #if defined(SRS_FFMPEG_FIT) SrsRtcRtpBuilder* rtp_builder_; #endif -private: - SrsVideoCodecId video_codec_id_; public: SrsFrameToRtcBridge(SrsSharedPtr source); virtual ~SrsFrameToRtcBridge(); @@ -76,7 +74,6 @@ public: virtual void on_unpublish(); virtual srs_error_t on_frame(SrsSharedPtrMessage* frame); srs_error_t on_rtp(SrsRtpPacket* pkt); - srs_error_t update_codec(SrsVideoCodecId id); }; #endif diff --git a/trunk/src/core/srs_core_version7.hpp b/trunk/src/core/srs_core_version7.hpp index 6e9507f88..ae5fb1d33 100644 --- a/trunk/src/core/srs_core_version7.hpp +++ b/trunk/src/core/srs_core_version7.hpp @@ -9,6 +9,6 @@ #define VERSION_MAJOR 7 #define VERSION_MINOR 0 -#define VERSION_REVISION 33 +#define VERSION_REVISION 32 #endif \ No newline at end of file diff --git a/trunk/src/kernel/srs_kernel_codec.cpp b/trunk/src/kernel/srs_kernel_codec.cpp index f1a73ae32..ba0257382 100644 --- a/trunk/src/kernel/srs_kernel_codec.cpp +++ b/trunk/src/kernel/srs_kernel_codec.cpp @@ -676,7 +676,7 @@ srs_error_t SrsVideoFrame::add_sample(char* bytes, int size) // By default, use AVC(H.264) to parse NALU. // For video, parse the nalu type, set the IDR flag. - SrsAvcNaluType nal_unit_type = SrsAvcNaluTypeParse(bytes[0]); + SrsAvcNaluType nal_unit_type = (SrsAvcNaluType)(bytes[0] & 0x1f); if (nal_unit_type == SrsAvcNaluTypeIDR) { has_idr = true; @@ -703,25 +703,29 @@ srs_error_t SrsVideoFrame::parse_avc_nalu_type(const SrsSample* sample, SrsAvcNa srs_error_t err = srs_success; if (sample == NULL || sample->size < 1) { - return srs_error_new(ERROR_NALU_EMPTY, "empty nalu"); + return srs_error_new(ERROR_AVC_NALU_EMPTY, "empty nalu"); } uint8_t header = sample->bytes[0]; - avc_nalu_type = SrsAvcNaluTypeParse(header); + avc_nalu_type = (SrsAvcNaluType)(header & kNalTypeMask); return err; } -srs_error_t SrsVideoFrame::parse_avc_bframe(const SrsSample* sample, bool& is_b_frame) +srs_error_t SrsVideoFrame::parse_avc_b_frame(const SrsSample* sample, bool& is_b_frame) { srs_error_t err = srs_success; + if (sample == NULL || sample->size < 1) { + return srs_error_new(ERROR_AVC_NALU_EMPTY, "empty nalu"); + } + SrsAvcNaluType nalu_type; if ((err = parse_avc_nalu_type(sample, nalu_type)) != srs_success) { return srs_error_wrap(err, "parse avc nalu type error"); } - if (nalu_type == SrsAvcNaluTypeIDR || nalu_type == SrsAvcNaluTypeSPS || nalu_type == SrsAvcNaluTypePPS) { + if (nalu_type != SrsAvcNaluTypeNonIDR && nalu_type != SrsAvcNaluTypeDataPartitionA && nalu_type != SrsAvcNaluTypeIDR) { is_b_frame = false; return err; } @@ -751,87 +755,6 @@ srs_error_t SrsVideoFrame::parse_avc_bframe(const SrsSample* sample, bool& is_b_ return err; } -srs_error_t SrsVideoFrame::parse_hevc_nalu_type(const SrsSample* sample, SrsHevcNaluType& hevc_nalu_type) -{ - srs_error_t err = srs_success; - - if (sample == NULL || sample->size < 1) { - return srs_error_new(ERROR_NALU_EMPTY, "empty hevc nalu"); - } - - uint8_t header = sample->bytes[0]; - hevc_nalu_type = SrsHevcNaluTypeParse(header); - - return err; -} - -srs_error_t SrsVideoFrame::parse_hevc_bframe(const SrsSample* sample, SrsFormat *format, bool& is_b_frame) -{ - srs_error_t err = srs_success; - - SrsHevcNaluType nalu_type; - if ((err = parse_hevc_nalu_type(sample, nalu_type)) != srs_success) { - return srs_error_wrap(err, "parse hevc nalu type error"); - } - - if (nalu_type > SrsHevcNaluType_CODED_SLICE_TFD) { - is_b_frame = false; - return err; - } - - SrsUniquePtr stream(new SrsBuffer(sample->bytes, sample->size)); - stream->skip(2); - - // @see 7.3.6.1 General slice segment header syntax - // @doc ITU-T-H.265-2021.pdf, page 66. - SrsBitBuffer bs(stream.get()); - - uint8_t first_slice_segment_in_pic_flag = bs.read_bit(); - - uint32_t slice_pic_parameter_set_id; - if ((err = bs.read_bits_ue(slice_pic_parameter_set_id)) != srs_success) { - return srs_error_wrap(err, "read slice pic parameter set id"); - } - - if (slice_pic_parameter_set_id >= SrsHevcMax_PPS_COUNT) { - return srs_error_new(ERROR_HEVC_DECODE_ERROR, "slice pic parameter set id out of range: %d", slice_pic_parameter_set_id); - } - - SrsHevcRbspPps *pps = &(format->vcodec->hevc_dec_conf_record_.pps_table[slice_pic_parameter_set_id]); - if (!pps) { - return srs_error_new(ERROR_HEVC_DECODE_ERROR, "pps not found"); - } - - uint8_t dependent_slice_segment_flag = 0; - if (!first_slice_segment_in_pic_flag) { - if (pps->dependent_slice_segments_enabled_flag) { - dependent_slice_segment_flag = bs.read_bit(); - } - } - - if (dependent_slice_segment_flag) { - return srs_error_new(ERROR_HEVC_DECODE_ERROR, "dependent slice segment flag is not supported"); - } - - for (int i = 0; i < pps->num_extra_slice_header_bits; i++) { - bs.skip_bits(1); - } - - uint32_t slice_type; - if ((err = bs.read_bits_ue(slice_type)) != srs_success) { - return srs_error_wrap(err, "read slice type"); - } - - is_b_frame = slice_type == SrsHevcSliceTypeB; - if (is_b_frame) { - srs_verbose("nalu_type=%d, slice type=%d", nalu_type, slice_type); - } - - // no need to evaluate the rest - - return err; -} - SrsFormat::SrsFormat() { acodec = NULL; @@ -2340,7 +2263,7 @@ srs_error_t SrsFormat::avc_demux_sps() // 7.4.1 NAL unit semantics // ISO_IEC_14496-10-AVC-2012.pdf, page 61. // nal_unit_type specifies the type of RBSP data structure contained in the NAL unit as specified in Table 7-1. - SrsAvcNaluType nal_unit_type = SrsAvcNaluTypeParse(nutv); + SrsAvcNaluType nal_unit_type = (SrsAvcNaluType)(nutv & 0x1f); if (nal_unit_type != 7) { return srs_error_new(ERROR_HLS_DECODE_ERROR, "for sps, nal_unit_type shall be equal to 7"); } diff --git a/trunk/src/kernel/srs_kernel_codec.hpp b/trunk/src/kernel/srs_kernel_codec.hpp index f267fdc01..9899271b6 100644 --- a/trunk/src/kernel/srs_kernel_codec.hpp +++ b/trunk/src/kernel/srs_kernel_codec.hpp @@ -14,12 +14,6 @@ class SrsBuffer; class SrsBitBuffer; -class SrsFormat; - -// @see: https://datatracker.ietf.org/doc/html/rfc6184#section-1.3 -const int SrsAvcNaluHeaderSize = 1; -// @see: https://datatracker.ietf.org/doc/html/rfc7798#section-1.1.4 -const int SrsHevcNaluHeaderSize = 2; /** * The video codec id. @@ -427,8 +421,6 @@ enum SrsAvcNaluType // Coded slice extension slice_layer_extension_rbsp( ) SrsAvcNaluTypeCodedSliceExt = 20, }; -// @see https://datatracker.ietf.org/doc/html/rfc6184#section-1.3 -#define SrsAvcNaluTypeParse(code) (SrsAvcNaluType)(code & 0x1F) std::string srs_avc_nalu2str(SrsAvcNaluType nalu_type); #ifdef SRS_H265 @@ -504,19 +496,8 @@ enum SrsHevcNaluType { SrsHevcNaluType_UNSPECIFIED_63, SrsHevcNaluType_INVALID, }; -// @see https://datatracker.ietf.org/doc/html/rfc7798#section-1.1.4 #define SrsHevcNaluTypeParse(code) (SrsHevcNaluType)((code & 0x7E) >> 1) -/** - * @see Table 7-7 – Name association to slice_type - * @doc ITU-T-H.265-2021.pdf, page 116. - */ -enum SrsHevcSliceType { - SrsHevcSliceTypeB = 0, - SrsHevcSliceTypeP = 1, - SrsHevcSliceTypeI = 2, -}; - struct SrsHevcNalData { uint16_t nal_unit_length; std::vector nal_unit_data; @@ -1339,10 +1320,7 @@ public: virtual SrsVideoCodecConfig* vcodec(); public: static srs_error_t parse_avc_nalu_type(const SrsSample* sample, SrsAvcNaluType& avc_nalu_type); - static srs_error_t parse_avc_bframe(const SrsSample* sample, bool& is_b_frame); - - static srs_error_t parse_hevc_nalu_type(const SrsSample* sample, SrsHevcNaluType& hevc_nalu_type); - static srs_error_t parse_hevc_bframe(const SrsSample* sample, SrsFormat* format, bool& is_b_frame); + static srs_error_t parse_avc_b_frame(const SrsSample* sample, bool& is_b_frame); }; /** diff --git a/trunk/src/kernel/srs_kernel_error.hpp b/trunk/src/kernel/srs_kernel_error.hpp index afc7f904f..69a14a590 100644 --- a/trunk/src/kernel/srs_kernel_error.hpp +++ b/trunk/src/kernel/srs_kernel_error.hpp @@ -279,7 +279,7 @@ XX(ERROR_HEVC_DECODE_ERROR , 3099, "HevcDecode", "HEVC decode av stream failed") \ XX(ERROR_MP4_HVCC_CHANGE , 3100, "Mp4HvcCChange", "MP4 does not support video HvcC change") \ XX(ERROR_HEVC_API_NO_PREFIXED , 3101, "HevcAnnexbPrefix", "No annexb prefix for HEVC decoder") \ - XX(ERROR_NALU_EMPTY , 3102, "NaluEmpty", "NALU is empty") + XX(ERROR_AVC_NALU_EMPTY , 3102, "AvcNaluEmpty", "AVC NALU is empty") /**************************************************/ /* HTTP/StreamConverter protocol error. */ diff --git a/trunk/src/kernel/srs_kernel_rtc_rtp.cpp b/trunk/src/kernel/srs_kernel_rtc_rtp.cpp index 1b1d91b15..7b08532d9 100644 --- a/trunk/src/kernel/srs_kernel_rtc_rtp.cpp +++ b/trunk/src/kernel/srs_kernel_rtc_rtp.cpp @@ -758,7 +758,7 @@ SrsRtpPacket::SrsRtpPacket() shared_buffer_ = NULL; actual_buffer_size_ = 0; - nalu_type = 0; + nalu_type = SrsAvcNaluTypeReserved; frame_type = SrsFrameTypeReserved; cached_payload_size = 0; decode_handler = NULL; @@ -961,23 +961,6 @@ bool SrsRtpPacket::is_keyframe() if((SrsAvcNaluTypeIDR == nalu_type) || (SrsAvcNaluTypeSPS == nalu_type) || (SrsAvcNaluTypePPS == nalu_type)) { return true; } -#ifdef SRS_H265 - if(nalu_type == kStapHevc) { - SrsRtpSTAPPayloadHevc* stap_payload = dynamic_cast(payload_); - if(NULL != stap_payload->get_vps() || NULL != stap_payload->get_sps() || NULL != stap_payload->get_pps()) { - return true; - } - } else if(nalu_type == kFuHevc) { - SrsRtpFUAPayloadHevc2* fua_payload = dynamic_cast(payload_); - if(fua_payload->nalu_type >= SrsHevcNaluType_CODED_SLICE_BLA && fua_payload->nalu_type <= SrsHevcNaluType_RESERVED_23) { - return true; - } - } else { - if((SrsHevcNaluType_VPS == nalu_type) || (SrsHevcNaluType_SPS == nalu_type) || (SrsHevcNaluType_PPS == nalu_type)) { - return true; - } - } -#endif } return false; @@ -1081,10 +1064,10 @@ void SrsRtpRawNALUs::push_back(SrsSample* sample) nalus.push_back(sample); } -uint8_t SrsRtpRawNALUs::skip_bytes(int count) +uint8_t SrsRtpRawNALUs::skip_first_byte() { - srs_assert (cursor >= 0 && nn_bytes > 0 && cursor + count < nn_bytes); - cursor += count; + srs_assert (cursor >= 0 && nn_bytes > 0 && cursor < nn_bytes); + cursor++; return uint8_t(nalus[0]->bytes[0]); } @@ -1211,7 +1194,7 @@ SrsSample* SrsRtpSTAPPayload::get_sps() continue; } - SrsAvcNaluType nalu_type = SrsAvcNaluTypeParse(p->bytes[0]); + SrsAvcNaluType nalu_type = (SrsAvcNaluType)(p->bytes[0] & kNalTypeMask); if (nalu_type == SrsAvcNaluTypeSPS) { return p; } @@ -1229,7 +1212,7 @@ SrsSample* SrsRtpSTAPPayload::get_pps() continue; } - SrsAvcNaluType nalu_type = SrsAvcNaluTypeParse(p->bytes[0]); + SrsAvcNaluType nalu_type = (SrsAvcNaluType)(p->bytes[0] & kNalTypeMask); if (nalu_type == SrsAvcNaluTypePPS) { return p; } @@ -1415,7 +1398,7 @@ srs_error_t SrsRtpFUAPayload::decode(SrsBuffer* buf) v = buf->read_1bytes(); start = v & kStart; end = v & kEnd; - nalu_type = SrsAvcNaluTypeParse(v); + nalu_type = SrsAvcNaluType(v & kNalTypeMask); if (!buf->require(1)) { return srs_error_new(ERROR_RTC_RTP_MUXER, "requires %d bytes", 1); @@ -1516,7 +1499,7 @@ srs_error_t SrsRtpFUAPayload2::decode(SrsBuffer* buf) v = buf->read_1bytes(); start = v & kStart; end = v & kEnd; - nalu_type = SrsAvcNaluTypeParse(v); + nalu_type = SrsAvcNaluType(v & kNalTypeMask); if (!buf->require(1)) { return srs_error_new(ERROR_RTC_RTP_MUXER, "requires %d bytes", 1); @@ -1542,362 +1525,3 @@ ISrsRtpPayloader* SrsRtpFUAPayload2::copy() return cp; } - -SrsRtpSTAPPayloadHevc::SrsRtpSTAPPayloadHevc() -{ - ++_srs_pps_objs_rothers->sugar; -} - -SrsRtpSTAPPayloadHevc::~SrsRtpSTAPPayloadHevc() -{ - int nn_nalus = (int)nalus.size(); - for (int i = 0; i < nn_nalus; i++) { - SrsSample* p = nalus[i]; - srs_freep(p); - } -} - -SrsSample* SrsRtpSTAPPayloadHevc::get_vps() -{ - int nn_nalus = (int)nalus.size(); - for (int i = 0; i < nn_nalus; i++) { - SrsSample* p = nalus[i]; - if (!p || !p->size) { - continue; - } - - SrsHevcNaluType nalu_type = SrsHevcNaluTypeParse(p->bytes[0]); - if (nalu_type == SrsHevcNaluType_VPS) { - return p; - } - } - - return NULL; -} - -SrsSample* SrsRtpSTAPPayloadHevc::get_sps() -{ - int nn_nalus = (int)nalus.size(); - for (int i = 0; i < nn_nalus; i++) { - SrsSample* p = nalus[i]; - if (!p || !p->size) { - continue; - } - - SrsHevcNaluType nalu_type = SrsHevcNaluTypeParse(p->bytes[0]); - if (nalu_type == SrsHevcNaluType_SPS) { - return p; - } - } - - return NULL; -} - -SrsSample* SrsRtpSTAPPayloadHevc::get_pps() -{ - int nn_nalus = (int)nalus.size(); - for (int i = 0; i < nn_nalus; i++) { - SrsSample* p = nalus[i]; - if (!p || !p->size) { - continue; - } - - SrsHevcNaluType nalu_type = SrsHevcNaluTypeParse(p->bytes[0]); - if (nalu_type == SrsHevcNaluType_PPS) { - return p; - } - } - - return NULL; -} - -uint64_t SrsRtpSTAPPayloadHevc::nb_bytes() -{ - int size = 2; - - int nn_nalus = (int)nalus.size(); - for (int i = 0; i < nn_nalus; i++) { - SrsSample* p = nalus[i]; - size += 2 + p->size; - } - - return size; -} - -srs_error_t SrsRtpSTAPPayloadHevc::encode(SrsBuffer* buf) -{ - if (!buf->require(2)) { - return srs_error_new(ERROR_RTC_RTP_MUXER, "requires %d bytes", 2); - } - - // STAP header, RTP payload format for aggregation packets - // @see https://datatracker.ietf.org/doc/html/rfc7798#section-4.4.2 - buf->write_1bytes(kStapHevc << 1); - buf->write_1bytes(1); - - // NALUs. - int nn_nalus = (int)nalus.size(); - for (int i = 0; i < nn_nalus; i++) { - SrsSample* p = nalus[i]; - - if (!buf->require(2 + p->size)) { - return srs_error_new(ERROR_RTC_RTP_MUXER, "requires %d bytes", 2 + p->size); - } - - buf->write_2bytes(p->size); - buf->write_bytes(p->bytes, p->size); - } - - return srs_success; -} - -srs_error_t SrsRtpSTAPPayloadHevc::decode(SrsBuffer* buf) -{ - if (!buf->require(2)) { - return srs_error_new(ERROR_RTC_RTP_MUXER, "requires %d bytes", 2); - } - - // STAP header, RTP payload format for aggregation packets - // @see https://datatracker.ietf.org/doc/html/rfc7798#section-4.4.2 - uint8_t v = buf->read_1bytes(); - buf->skip(1); - - // forbidden_zero_bit shoul be zero. - // @see https://datatracker.ietf.org/doc/html/rfc7798#section-4.4.2 - uint8_t f = (v & 0x80); - if (f == 0x80) { - return srs_error_new(ERROR_RTC_RTP_MUXER, "forbidden_zero_bit should be zero"); - } - - // NALUs. - while (!buf->empty()) { - if (!buf->require(2)) { - return srs_error_new(ERROR_RTC_RTP_MUXER, "requires %d bytes", 2); - } - - int size = buf->read_2bytes(); - if (!buf->require(size)) { - return srs_error_new(ERROR_RTC_RTP_MUXER, "requires %d bytes", size); - } - - SrsSample* sample = new SrsSample(); - sample->bytes = buf->head(); - sample->size = size; - buf->skip(size); - - nalus.push_back(sample); - } - - return srs_success; -} - -ISrsRtpPayloader* SrsRtpSTAPPayloadHevc::copy() -{ - SrsRtpSTAPPayloadHevc* cp = new SrsRtpSTAPPayloadHevc(); - - int nn_nalus = (int)nalus.size(); - for (int i = 0; i < nn_nalus; i++) { - SrsSample* p = nalus[i]; - cp->nalus.push_back(p->copy()); - } - - return cp; -} - -SrsRtpFUAPayloadHevc::SrsRtpFUAPayloadHevc() -{ - start = end = false; - nalu_type = (SrsHevcNaluType)0; - - ++_srs_pps_objs_rothers->sugar; -} - -SrsRtpFUAPayloadHevc::~SrsRtpFUAPayloadHevc() -{ - int nn_nalus = (int)nalus.size(); - for (int i = 0; i < nn_nalus; i++) { - SrsSample* p = nalus[i]; - srs_freep(p); - } -} - -uint64_t SrsRtpFUAPayloadHevc::nb_bytes() -{ - int size = 3; - - int nn_nalus = (int)nalus.size(); - for (int i = 0; i < nn_nalus; i++) { - SrsSample* p = nalus[i]; - size += p->size; - } - - return size; -} - -srs_error_t SrsRtpFUAPayloadHevc::encode(SrsBuffer* buf) -{ - if (!buf->require(3)) { - return srs_error_new(ERROR_RTC_RTP_MUXER, "requires %d bytes", 3); - } - - // PayloadHdr, @see: https://datatracker.ietf.org/doc/html/rfc7798#section-4.4.3 - buf->write_1bytes(kFuHevc << 1); - buf->write_1bytes(1); - - // FU header, @see https://datatracker.ietf.org/doc/html/rfc7798#section-4.4.3 - uint8_t fu_header = (start ? kStart : 0) | (end ? kEnd : 0); - fu_header |= nalu_type; - buf->write_1bytes(fu_header); - - int nn_nalus = (int)nalus.size(); - for (int i = 0; i < nn_nalus; i++) { - SrsSample* p = nalus[i]; - - if (!buf->require(p->size)) { - return srs_error_new(ERROR_RTC_RTP_MUXER, "requires %d bytes", p->size); - } - - buf->write_bytes(p->bytes, p->size); - } - - return srs_success; -} - -srs_error_t SrsRtpFUAPayloadHevc::decode(SrsBuffer* buf) -{ - if (!buf->require(3)) { - return srs_error_new(ERROR_RTC_RTP_MUXER, "requires %d bytes", 3); - } - - // skip PayloadHdr, 2 bytes - buf->skip(2); - - uint8_t fu_header = buf->read_1bytes(); - start = fu_header & kStart; - end = fu_header & kEnd; - nalu_type = SrsHevcNaluType(fu_header & 0x3F); - if (!buf->require(1)) { - return srs_error_new(ERROR_RTC_RTP_MUXER, "requires %d bytes", 1); - } - - SrsSample* sample = new SrsSample(); - sample->bytes = buf->head(); - sample->size = buf->left(); - buf->skip(sample->size); - - nalus.push_back(sample); - - return srs_success; -} - -ISrsRtpPayloader* SrsRtpFUAPayloadHevc::copy() -{ - SrsRtpFUAPayloadHevc* cp = new SrsRtpFUAPayloadHevc(); - - cp->start = start; - cp->end = end; - cp->nalu_type = nalu_type; - - int nn_nalus = (int)nalus.size(); - for (int i = 0; i < nn_nalus; i++) { - SrsSample* p = nalus[i]; - cp->nalus.push_back(p->copy()); - } - - return cp; -} - -SrsRtpFUAPayloadHevc2::SrsRtpFUAPayloadHevc2() -{ - start = end = false; - nalu_type = (SrsHevcNaluType)0; - - payload = NULL; - size = 0; - - ++_srs_pps_objs_rfua->sugar; -} - -SrsRtpFUAPayloadHevc2::~SrsRtpFUAPayloadHevc2() -{ -} - -uint64_t SrsRtpFUAPayloadHevc2::nb_bytes() -{ - // PayloadHdr(2) + FU header(1) - return 3 + size; -} - -srs_error_t SrsRtpFUAPayloadHevc2::encode(SrsBuffer* buf) -{ - if (!buf->require(3 + size)) { - return srs_error_new(ERROR_RTC_RTP_MUXER, "requires %d bytes", 3 + size); - } - - // Fast encoding. - char* p = buf->head(); - - // PayloadHdr, @see: https://datatracker.ietf.org/doc/html/rfc7798#section-4.4.3 - /* - * create the HEVC payload header and transmit the buffer as fragmentation units (FU) - * - * 0 1 - * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * |F| Type | LayerId | TID | - * +-------------+-----------------+ - * - * F = 0 - * Type = 49 (fragmentation unit (FU)) - * LayerId = 0 - * TID = 1 - */ - *p++ = kFuHevc << 1; - *p++ = 1; - - // FU header, @see https://datatracker.ietf.org/doc/html/rfc7798#section-4.4.3 - uint8_t fu_header = (start ? kStart : 0) | (end ? kEnd : 0); - fu_header |= nalu_type; - *p++ = fu_header; - - memcpy(p, payload, size); - - // Consume bytes. - buf->skip(3 + size); - - return srs_success; -} - -srs_error_t SrsRtpFUAPayloadHevc2::decode(SrsBuffer* buf) -{ - if (!buf->require(3)) { - return srs_error_new(ERROR_RTC_RTP_MUXER, "requires 3 bytes"); - } - - // skip PayloadHdr, 2 bytes - buf->skip(2); - - uint8_t fu_header = buf->read_1bytes(); - start = fu_header & kStart; - end = fu_header & kEnd; - nalu_type = SrsHevcNaluType(fu_header & 0x3F); - - payload = buf->head(); - size = buf->left(); - buf->skip(size); - - return srs_success; -} - -ISrsRtpPayloader* SrsRtpFUAPayloadHevc2::copy() -{ - SrsRtpFUAPayloadHevc2* cp = new SrsRtpFUAPayloadHevc2(); - - cp->start = start; - cp->end = end; - cp->nalu_type = nalu_type; - cp->payload = payload; - cp->size = size; - - return cp; -} diff --git a/trunk/src/kernel/srs_kernel_rtc_rtp.hpp b/trunk/src/kernel/srs_kernel_rtc_rtp.hpp index ff731db0b..b417208fb 100644 --- a/trunk/src/kernel/srs_kernel_rtc_rtp.hpp +++ b/trunk/src/kernel/srs_kernel_rtc_rtp.hpp @@ -29,14 +29,10 @@ const uint8_t kNalTypeMask = 0x1F; // @see: https://tools.ietf.org/html/rfc6184#section-5.2 const uint8_t kStapA = 24; + // @see: https://tools.ietf.org/html/rfc6184#section-5.2 const uint8_t kFuA = 28; -// @see: https://datatracker.ietf.org/doc/html/rfc7798#section-4.4.2 -const uint8_t kStapHevc = 48; -// @see: https://datatracker.ietf.org/doc/html/rfc7798#section-4.4.3 -const uint8_t kFuHevc = 49; - // @see: https://tools.ietf.org/html/rfc6184#section-5.8 const uint8_t kStart = 0x80; // Fu-header start bit const uint8_t kEnd = 0x40; // Fu-header end bit @@ -257,12 +253,9 @@ enum SrsRtspPacketPayloadType { SrsRtspPacketPayloadTypeRaw, SrsRtspPacketPayloadTypeFUA2, - SrsRtspPacketPayloadTypeFUAHevc2, SrsRtspPacketPayloadTypeFUA, - SrsRtspPacketPayloadTypeFUAHevc, SrsRtspPacketPayloadTypeNALU, SrsRtspPacketPayloadTypeSTAP, - SrsRtspPacketPayloadTypeSTAPHevc, SrsRtspPacketPayloadTypeUnknown, }; @@ -296,7 +289,7 @@ private: // Helper fields. public: // The first byte as nalu type, for video decoder only. - uint8_t nalu_type; + SrsAvcNaluType nalu_type; // The frame type, for RTMP bridge or SFU source. SrsFrameType frame_type; // Fast cache for performance. @@ -383,7 +376,7 @@ public: public: void push_back(SrsSample* sample); public: - uint8_t skip_bytes(int count); + uint8_t skip_first_byte(); // We will manage the returned samples, if user want to manage it, please copy it. srs_error_t read_samples(std::vector& samples, int packet_size); // interface ISrsRtpPayloader @@ -467,68 +460,4 @@ public: virtual ISrsRtpPayloader* copy(); }; -class SrsRtpSTAPPayloadHevc : public ISrsRtpPayloader -{ -public: - // The NALU samples, we will manage the samples. - // @remark We only refer to the memory, user must free its bytes. - std::vector nalus; -public: - SrsRtpSTAPPayloadHevc(); - virtual ~SrsRtpSTAPPayloadHevc(); -public: - SrsSample* get_vps(); - SrsSample* get_sps(); - SrsSample* get_pps(); -// interface ISrsRtpPayloader -public: - virtual uint64_t nb_bytes(); - virtual srs_error_t encode(SrsBuffer* buf); - virtual srs_error_t decode(SrsBuffer* buf); - virtual ISrsRtpPayloader* copy(); -}; - -// FU, for one NALU with multiple fragments. -// With more than one payload for HEVC. -class SrsRtpFUAPayloadHevc : public ISrsRtpPayloader -{ -public: - // The FUA header. - bool start; - bool end; - SrsHevcNaluType nalu_type; - // The NALU samples, we manage the samples. - // @remark We only refer to the memory, user must free its bytes. - std::vector nalus; -public: - SrsRtpFUAPayloadHevc(); - virtual ~SrsRtpFUAPayloadHevc(); -// interface ISrsRtpPayloader -public: - virtual uint64_t nb_bytes(); - virtual srs_error_t encode(SrsBuffer* buf); - virtual srs_error_t decode(SrsBuffer* buf); - virtual ISrsRtpPayloader* copy(); -}; - -// FU, for one NALU with multiple fragments. -// With only one payload for HEVC. -class SrsRtpFUAPayloadHevc2 : public ISrsRtpPayloader -{ -public: - bool start; - bool end; - SrsHevcNaluType nalu_type; - char* payload; - int size; -public: - SrsRtpFUAPayloadHevc2(); - virtual ~SrsRtpFUAPayloadHevc2(); -public: - virtual uint64_t nb_bytes(); - virtual srs_error_t encode(SrsBuffer* buf); - virtual srs_error_t decode(SrsBuffer* buf); - virtual ISrsRtpPayloader* copy(); -}; - #endif diff --git a/trunk/src/utest/srs_utest_kernel.cpp b/trunk/src/utest/srs_utest_kernel.cpp index 7b0b51a65..b0d428aa7 100644 --- a/trunk/src/utest/srs_utest_kernel.cpp +++ b/trunk/src/utest/srs_utest_kernel.cpp @@ -3567,204 +3567,6 @@ VOID TEST(KernelCodecTest, AVFrameNoConfig) HELPER_EXPECT_SUCCESS(f.add_sample((char*)"\x05", 1)); } } -VOID TEST(KernelCodecTest, VideoFrameH264) -{ - srs_error_t err; - - if (true) { - // I Frame - uint8_t data[] = {0x05, 0x00, 0x00, 0x00}; - SrsSample sample((char*)data, sizeof(data)); - - SrsAvcNaluType nalu_type = SrsAvcNaluTypeForbidden; - HELPER_EXPECT_SUCCESS(SrsVideoFrame::parse_avc_nalu_type(&sample, nalu_type)); - EXPECT_EQ(nalu_type, SrsAvcNaluTypeIDR); - - // P Frame - uint8_t data2[] = {0x01, 0x00, 0x00, 0x00}; - SrsSample sample2((char*)data2, sizeof(data2)); - - nalu_type = SrsAvcNaluTypeForbidden; - HELPER_EXPECT_SUCCESS(SrsVideoFrame::parse_avc_nalu_type(&sample2, nalu_type)); - EXPECT_EQ(nalu_type, SrsAvcNaluTypeNonIDR); - - // SPS - uint8_t data3[] = {0x07, 0x00, 0x00, 0x00}; - SrsSample sample3((char*)data3, sizeof(data3)); - - nalu_type = SrsAvcNaluTypeForbidden; - HELPER_EXPECT_SUCCESS(SrsVideoFrame::parse_avc_nalu_type(&sample3, nalu_type)); - EXPECT_EQ(nalu_type, SrsAvcNaluTypeSPS); - - // PPS - uint8_t data4[] = {0x08, 0x00, 0x00, 0x00}; - SrsSample sample4((char*)data4, sizeof(data4)); - - nalu_type = SrsAvcNaluTypeForbidden; - HELPER_EXPECT_SUCCESS(SrsVideoFrame::parse_avc_nalu_type(&sample4, nalu_type)); - EXPECT_EQ(nalu_type, SrsAvcNaluTypePPS); - - // Empty Sample - SrsSample empty_sample(NULL, 0); - HELPER_EXPECT_FAILED(SrsVideoFrame::parse_avc_nalu_type(&empty_sample, nalu_type)); - } - - if (true) { - // B Frame, slice_type=1(B Frame) - uint8_t data[] = {0x01, 0xA8, 0x00, 0x00}; - SrsSample sample((char*)data, sizeof(data)); - - bool is_b_frame = false; - HELPER_EXPECT_SUCCESS(SrsVideoFrame::parse_avc_bframe(&sample, is_b_frame)); - EXPECT_TRUE(is_b_frame); - - // Non-B Frame, slice_type=0(P Frame) - uint8_t data2[] = {0x01, 0x88, 0x00, 0x00}; - SrsSample sample2((char*)data2, sizeof(data2)); - - is_b_frame = true; - HELPER_EXPECT_SUCCESS(SrsVideoFrame::parse_avc_bframe(&sample2, is_b_frame)); - EXPECT_FALSE(is_b_frame); - - // SPS - uint8_t data3[] = {0x07, 0xA8, 0x00, 0x00}; - SrsSample sample3((char*)data3, sizeof(data3)); - - is_b_frame = true; - HELPER_EXPECT_SUCCESS(SrsVideoFrame::parse_avc_bframe(&sample3, is_b_frame)); - EXPECT_FALSE(is_b_frame); - - // PPS - uint8_t data4[] = {0x08, 0xA8, 0x00, 0x00}; - SrsSample sample4((char*)data4, sizeof(data4)); - - is_b_frame = true; - HELPER_EXPECT_SUCCESS(SrsVideoFrame::parse_avc_bframe(&sample4, is_b_frame)); - EXPECT_FALSE(is_b_frame); - - // IDR - uint8_t data5[] = {0x05, 0xA8, 0x00, 0x00}; - SrsSample sample5((char*)data5, sizeof(data5)); - - is_b_frame = true; - HELPER_EXPECT_SUCCESS(SrsVideoFrame::parse_avc_bframe(&sample5, is_b_frame)); - EXPECT_FALSE(is_b_frame); - - // Empty Sample - SrsSample empty_sample(NULL, 0); - HELPER_EXPECT_FAILED(SrsVideoFrame::parse_avc_bframe(&empty_sample, is_b_frame)); - } -} - -#ifdef SRS_H265 -VOID TEST(KernelCodecTest, VideoFrameH265) -{ - srs_error_t err; - - if (true) { - // I Frame - uint8_t data[] = {0x26, 0x01, 0x00, 0x00}; - SrsSample sample((char*)data, sizeof(data)); - - SrsHevcNaluType nalu_type = SrsHevcNaluType_INVALID; - HELPER_EXPECT_SUCCESS(SrsVideoFrame::parse_hevc_nalu_type(&sample, nalu_type)); - EXPECT_EQ(nalu_type, SrsHevcNaluType_CODED_SLICE_IDR); - - // P Frame - uint8_t data2[] = {0x02, 0x01, 0x00, 0x00}; - SrsSample sample2((char*)data2, sizeof(data2)); - - nalu_type = SrsHevcNaluType_INVALID; - HELPER_EXPECT_SUCCESS(SrsVideoFrame::parse_hevc_nalu_type(&sample2, nalu_type)); - EXPECT_EQ(nalu_type, SrsHevcNaluType_CODED_SLICE_TRAIL_R); - - // VPS - uint8_t data3[] = {0x40, 0x01, 0x00, 0x00}; - SrsSample sample3((char*)data3, sizeof(data3)); - - nalu_type = SrsHevcNaluType_INVALID; - HELPER_EXPECT_SUCCESS(SrsVideoFrame::parse_hevc_nalu_type(&sample3, nalu_type)); - EXPECT_EQ(nalu_type, SrsHevcNaluType_VPS); - - // SPS - uint8_t data4[] = {0x42, 0x01, 0x00, 0x00}; - SrsSample sample4((char*)data4, sizeof(data4)); - - nalu_type = SrsHevcNaluType_INVALID; - HELPER_EXPECT_SUCCESS(SrsVideoFrame::parse_hevc_nalu_type(&sample4, nalu_type)); - EXPECT_EQ(nalu_type, SrsHevcNaluType_SPS); - - // PPS - uint8_t data5[] = {0x44, 0x01, 0x00, 0x00}; - SrsSample sample5((char*)data5, sizeof(data5)); - - nalu_type = SrsHevcNaluType_INVALID; - HELPER_EXPECT_SUCCESS(SrsVideoFrame::parse_hevc_nalu_type(&sample5, nalu_type)); - EXPECT_EQ(nalu_type, SrsHevcNaluType_PPS); - - // Empty Sample - SrsSample empty_sample(NULL, 0); - HELPER_EXPECT_FAILED(SrsVideoFrame::parse_hevc_nalu_type(&empty_sample, nalu_type)); - } - - if (true) { - SrsFormat format; - HELPER_EXPECT_SUCCESS(format.initialize()); - - // B Frame, slice_type=0(B Frame) - uint8_t data[] = {0x02, 0x01, 0xE0, 0x44}; - SrsSample sample((char*)data, sizeof(data)); - - bool is_b_frame = false; - HELPER_EXPECT_SUCCESS(SrsVideoFrame::parse_hevc_bframe(&sample, &format, is_b_frame)); - EXPECT_TRUE(is_b_frame); - - // Non-B Frame, slice_type=1(P Frame) - uint8_t data2[] = {0x02, 0x01, 0xD0, 0x30}; - SrsSample sample2((char*)data2, sizeof(data2)); - - is_b_frame = true; - HELPER_EXPECT_SUCCESS(SrsVideoFrame::parse_hevc_bframe(&sample2, &format, is_b_frame)); - EXPECT_FALSE(is_b_frame); - - // VPS - uint8_t data3[] = {0x40, 0x01, 0xE0, 0x44}; - SrsSample sample3((char*)data3, sizeof(data3)); - - is_b_frame = true; - HELPER_EXPECT_SUCCESS(SrsVideoFrame::parse_hevc_bframe(&sample3, &format, is_b_frame)); - EXPECT_FALSE(is_b_frame); - - // SPS - uint8_t data4[] = {0x42, 0x01, 0xE0, 0x44}; - SrsSample sample4((char*)data4, sizeof(data4)); - - is_b_frame = true; - HELPER_EXPECT_SUCCESS(SrsVideoFrame::parse_hevc_bframe(&sample4, &format, is_b_frame)); - EXPECT_FALSE(is_b_frame); - - // PPS - uint8_t data5[] = {0x44, 0x01, 0xE0, 0x44}; - SrsSample sample5((char*)data5, sizeof(data5)); - - is_b_frame = true; - HELPER_EXPECT_SUCCESS(SrsVideoFrame::parse_hevc_bframe(&sample5, &format, is_b_frame)); - EXPECT_FALSE(is_b_frame); - - // IDR - uint8_t data6[] = {0x26, 0x01, 0xE0, 0x44}; - SrsSample sample6((char*)data6, sizeof(data6)); - - is_b_frame = true; - HELPER_EXPECT_SUCCESS(SrsVideoFrame::parse_hevc_bframe(&sample6, &format, is_b_frame)); - EXPECT_FALSE(is_b_frame); - - // Empty Sample - SrsSample empty_sample(NULL, 0); - HELPER_EXPECT_FAILED(SrsVideoFrame::parse_hevc_bframe(&empty_sample, &format, is_b_frame)); - } -} -#endif VOID TEST(KernelCodecTest, IsSequenceHeaderSpecial) { @@ -4419,7 +4221,7 @@ VOID TEST(KernelCodecTest, HevcVideoFormat) if (true) { SrsFormat f; HELPER_EXPECT_SUCCESS(f.initialize()); - + // firstly demux sequence header HELPER_EXPECT_SUCCESS(f.on_video(0, (char*)ext_vps_sps_pps, sizeof(ext_vps_sps_pps))); EXPECT_EQ(1, f.video->frame_type); diff --git a/trunk/src/utest/srs_utest_rtc.cpp b/trunk/src/utest/srs_utest_rtc.cpp index 9603c512c..b40679008 100644 --- a/trunk/src/utest/srs_utest_rtc.cpp +++ b/trunk/src/utest/srs_utest_rtc.cpp @@ -62,7 +62,7 @@ VOID TEST(KernelRTCTest, RtpSTAPPayloadException) SrsAvcNaluType nalu_type = SrsAvcNaluTypeReserved; // Try to parse the NALU type for video decoder. if (!buf.empty()) { - nalu_type = SrsAvcNaluTypeParse(buf.head()[0]); + nalu_type = SrsAvcNaluType((uint8_t)(buf.head()[0] & kNalTypeMask)); } EXPECT_TRUE(nalu_type == kStapA);
借助SRS服务和WebRTC连接协议,随时观看直播
+ ${paragraph ? paragraph : options[type].paragraph} +