├── .gitignore ├── LICENSE ├── README ├── autobuilder.sh ├── branches.sh ├── build.sh.example ├── changed-revs.sh ├── changelog-email ├── maxtime ├── next-rev.sh ├── revdetail.sh ├── revlist.sh ├── rsync-to ├── run-build.sh ├── runlock ├── runtee ├── start ├── stop └── viewer ├── Autobuilder.pm ├── index.cgi ├── log.cgi ├── rebuild.tmpl.html ├── rss.cgi ├── run.py └── static ├── bootstrap-responsive.css ├── bootstrap.css ├── docs.css ├── feed-icon-14x14.png ├── feed-icon-28x28.png ├── grid-18px-masked.png ├── index.css └── log.css /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | /out/fail 3 | /out/pass 4 | /out/refs 5 | /out/ignore 6 | /out/lastlog 7 | /out/revcache 8 | /out/errcache 9 | /out/describe 10 | /build 11 | *.lock 12 | /branches-local 13 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (C) 2008-2009 Versabanq Innovations, Inc. 2 | 3 | gitbuilder is free software; you can redistribute it and/or modify it under 4 | the terms of the GNU General Public License as published by the Free 5 | Software Foundation; either version 2, or (at your option) any later 6 | version. 7 | 8 | gitbuilder is distributed in the hope that it will be useful, but WITHOUT 9 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11 | more details. 12 | 13 | A copy of the GNU General Public License is attached below. 14 | 15 | 16 | 17 | 18 | 19 | 20 | GNU GENERAL PUBLIC LICENSE 21 | Version 2, June 1991 22 | 23 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 24 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 25 | Everyone is permitted to copy and distribute verbatim copies 26 | of this license document, but changing it is not allowed. 27 | 28 | Preamble 29 | 30 | The licenses for most software are designed to take away your 31 | freedom to share and change it. By contrast, the GNU General Public 32 | License is intended to guarantee your freedom to share and change free 33 | software--to make sure the software is free for all its users. This 34 | General Public License applies to most of the Free Software 35 | Foundation's software and to any other program whose authors commit to 36 | using it. (Some other Free Software Foundation software is covered by 37 | the GNU Lesser General Public License instead.) You can apply it to 38 | your programs, too. 39 | 40 | When we speak of free software, we are referring to freedom, not 41 | price. Our General Public Licenses are designed to make sure that you 42 | have the freedom to distribute copies of free software (and charge for 43 | this service if you wish), that you receive source code or can get it 44 | if you want it, that you can change the software or use pieces of it 45 | in new free programs; and that you know you can do these things. 46 | 47 | To protect your rights, we need to make restrictions that forbid 48 | anyone to deny you these rights or to ask you to surrender the rights. 49 | These restrictions translate to certain responsibilities for you if you 50 | distribute copies of the software, or if you modify it. 51 | 52 | For example, if you distribute copies of such a program, whether 53 | gratis or for a fee, you must give the recipients all the rights that 54 | you have. You must make sure that they, too, receive or can get the 55 | source code. And you must show them these terms so they know their 56 | rights. 57 | 58 | We protect your rights with two steps: (1) copyright the software, and 59 | (2) offer you this license which gives you legal permission to copy, 60 | distribute and/or modify the software. 61 | 62 | Also, for each author's protection and ours, we want to make certain 63 | that everyone understands that there is no warranty for this free 64 | software. If the software is modified by someone else and passed on, we 65 | want its recipients to know that what they have is not the original, so 66 | that any problems introduced by others will not reflect on the original 67 | authors' reputations. 68 | 69 | Finally, any free program is threatened constantly by software 70 | patents. We wish to avoid the danger that redistributors of a free 71 | program will individually obtain patent licenses, in effect making the 72 | program proprietary. To prevent this, we have made it clear that any 73 | patent must be licensed for everyone's free use or not licensed at all. 74 | 75 | The precise terms and conditions for copying, distribution and 76 | modification follow. 77 | 78 | GNU GENERAL PUBLIC LICENSE 79 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 80 | 81 | 0. This License applies to any program or other work which contains 82 | a notice placed by the copyright holder saying it may be distributed 83 | under the terms of this General Public License. The "Program", below, 84 | refers to any such program or work, and a "work based on the Program" 85 | means either the Program or any derivative work under copyright law: 86 | that is to say, a work containing the Program or a portion of it, 87 | either verbatim or with modifications and/or translated into another 88 | language. (Hereinafter, translation is included without limitation in 89 | the term "modification".) Each licensee is addressed as "you". 90 | 91 | Activities other than copying, distribution and modification are not 92 | covered by this License; they are outside its scope. The act of 93 | running the Program is not restricted, and the output from the Program 94 | is covered only if its contents constitute a work based on the 95 | Program (independent of having been made by running the Program). 96 | Whether that is true depends on what the Program does. 97 | 98 | 1. You may copy and distribute verbatim copies of the Program's 99 | source code as you receive it, in any medium, provided that you 100 | conspicuously and appropriately publish on each copy an appropriate 101 | copyright notice and disclaimer of warranty; keep intact all the 102 | notices that refer to this License and to the absence of any warranty; 103 | and give any other recipients of the Program a copy of this License 104 | along with the Program. 105 | 106 | You may charge a fee for the physical act of transferring a copy, and 107 | you may at your option offer warranty protection in exchange for a fee. 108 | 109 | 2. You may modify your copy or copies of the Program or any portion 110 | of it, thus forming a work based on the Program, and copy and 111 | distribute such modifications or work under the terms of Section 1 112 | above, provided that you also meet all of these conditions: 113 | 114 | a) You must cause the modified files to carry prominent notices 115 | stating that you changed the files and the date of any change. 116 | 117 | b) You must cause any work that you distribute or publish, that in 118 | whole or in part contains or is derived from the Program or any 119 | part thereof, to be licensed as a whole at no charge to all third 120 | parties under the terms of this License. 121 | 122 | c) If the modified program normally reads commands interactively 123 | when run, you must cause it, when started running for such 124 | interactive use in the most ordinary way, to print or display an 125 | announcement including an appropriate copyright notice and a 126 | notice that there is no warranty (or else, saying that you provide 127 | a warranty) and that users may redistribute the program under 128 | these conditions, and telling the user how to view a copy of this 129 | License. (Exception: if the Program itself is interactive but 130 | does not normally print such an announcement, your work based on 131 | the Program is not required to print an announcement.) 132 | 133 | These requirements apply to the modified work as a whole. If 134 | identifiable sections of that work are not derived from the Program, 135 | and can be reasonably considered independent and separate works in 136 | themselves, then this License, and its terms, do not apply to those 137 | sections when you distribute them as separate works. But when you 138 | distribute the same sections as part of a whole which is a work based 139 | on the Program, the distribution of the whole must be on the terms of 140 | this License, whose permissions for other licensees extend to the 141 | entire whole, and thus to each and every part regardless of who wrote it. 142 | 143 | Thus, it is not the intent of this section to claim rights or contest 144 | your rights to work written entirely by you; rather, the intent is to 145 | exercise the right to control the distribution of derivative or 146 | collective works based on the Program. 147 | 148 | In addition, mere aggregation of another work not based on the Program 149 | with the Program (or with a work based on the Program) on a volume of 150 | a storage or distribution medium does not bring the other work under 151 | the scope of this License. 152 | 153 | 3. You may copy and distribute the Program (or a work based on it, 154 | under Section 2) in object code or executable form under the terms of 155 | Sections 1 and 2 above provided that you also do one of the following: 156 | 157 | a) Accompany it with the complete corresponding machine-readable 158 | source code, which must be distributed under the terms of Sections 159 | 1 and 2 above on a medium customarily used for software interchange; or, 160 | 161 | b) Accompany it with a written offer, valid for at least three 162 | years, to give any third party, for a charge no more than your 163 | cost of physically performing source distribution, a complete 164 | machine-readable copy of the corresponding source code, to be 165 | distributed under the terms of Sections 1 and 2 above on a medium 166 | customarily used for software interchange; or, 167 | 168 | c) Accompany it with the information you received as to the offer 169 | to distribute corresponding source code. (This alternative is 170 | allowed only for noncommercial distribution and only if you 171 | received the program in object code or executable form with such 172 | an offer, in accord with Subsection b above.) 173 | 174 | The source code for a work means the preferred form of the work for 175 | making modifications to it. For an executable work, complete source 176 | code means all the source code for all modules it contains, plus any 177 | associated interface definition files, plus the scripts used to 178 | control compilation and installation of the executable. However, as a 179 | special exception, the source code distributed need not include 180 | anything that is normally distributed (in either source or binary 181 | form) with the major components (compiler, kernel, and so on) of the 182 | operating system on which the executable runs, unless that component 183 | itself accompanies the executable. 184 | 185 | If distribution of executable or object code is made by offering 186 | access to copy from a designated place, then offering equivalent 187 | access to copy the source code from the same place counts as 188 | distribution of the source code, even though third parties are not 189 | compelled to copy the source along with the object code. 190 | 191 | 4. You may not copy, modify, sublicense, or distribute the Program 192 | except as expressly provided under this License. Any attempt 193 | otherwise to copy, modify, sublicense or distribute the Program is 194 | void, and will automatically terminate your rights under this License. 195 | However, parties who have received copies, or rights, from you under 196 | this License will not have their licenses terminated so long as such 197 | parties remain in full compliance. 198 | 199 | 5. You are not required to accept this License, since you have not 200 | signed it. However, nothing else grants you permission to modify or 201 | distribute the Program or its derivative works. These actions are 202 | prohibited by law if you do not accept this License. Therefore, by 203 | modifying or distributing the Program (or any work based on the 204 | Program), you indicate your acceptance of this License to do so, and 205 | all its terms and conditions for copying, distributing or modifying 206 | the Program or works based on it. 207 | 208 | 6. Each time you redistribute the Program (or any work based on the 209 | Program), the recipient automatically receives a license from the 210 | original licensor to copy, distribute or modify the Program subject to 211 | these terms and conditions. You may not impose any further 212 | restrictions on the recipients' exercise of the rights granted herein. 213 | You are not responsible for enforcing compliance by third parties to 214 | this License. 215 | 216 | 7. If, as a consequence of a court judgment or allegation of patent 217 | infringement or for any other reason (not limited to patent issues), 218 | conditions are imposed on you (whether by court order, agreement or 219 | otherwise) that contradict the conditions of this License, they do not 220 | excuse you from the conditions of this License. If you cannot 221 | distribute so as to satisfy simultaneously your obligations under this 222 | License and any other pertinent obligations, then as a consequence you 223 | may not distribute the Program at all. For example, if a patent 224 | license would not permit royalty-free redistribution of the Program by 225 | all those who receive copies directly or indirectly through you, then 226 | the only way you could satisfy both it and this License would be to 227 | refrain entirely from distribution of the Program. 228 | 229 | If any portion of this section is held invalid or unenforceable under 230 | any particular circumstance, the balance of the section is intended to 231 | apply and the section as a whole is intended to apply in other 232 | circumstances. 233 | 234 | It is not the purpose of this section to induce you to infringe any 235 | patents or other property right claims or to contest validity of any 236 | such claims; this section has the sole purpose of protecting the 237 | integrity of the free software distribution system, which is 238 | implemented by public license practices. Many people have made 239 | generous contributions to the wide range of software distributed 240 | through that system in reliance on consistent application of that 241 | system; it is up to the author/donor to decide if he or she is willing 242 | to distribute software through any other system and a licensee cannot 243 | impose that choice. 244 | 245 | This section is intended to make thoroughly clear what is believed to 246 | be a consequence of the rest of this License. 247 | 248 | 8. If the distribution and/or use of the Program is restricted in 249 | certain countries either by patents or by copyrighted interfaces, the 250 | original copyright holder who places the Program under this License 251 | may add an explicit geographical distribution limitation excluding 252 | those countries, so that distribution is permitted only in or among 253 | countries not thus excluded. In such case, this License incorporates 254 | the limitation as if written in the body of this License. 255 | 256 | 9. The Free Software Foundation may publish revised and/or new versions 257 | of the General Public License from time to time. Such new versions will 258 | be similar in spirit to the present version, but may differ in detail to 259 | address new problems or concerns. 260 | 261 | Each version is given a distinguishing version number. If the Program 262 | specifies a version number of this License which applies to it and "any 263 | later version", you have the option of following the terms and conditions 264 | either of that version or of any later version published by the Free 265 | Software Foundation. If the Program does not specify a version number of 266 | this License, you may choose any version ever published by the Free Software 267 | Foundation. 268 | 269 | 10. If you wish to incorporate parts of the Program into other free 270 | programs whose distribution conditions are different, write to the author 271 | to ask for permission. For software which is copyrighted by the Free 272 | Software Foundation, write to the Free Software Foundation; we sometimes 273 | make exceptions for this. Our decision will be guided by the two goals 274 | of preserving the free status of all derivatives of our free software and 275 | of promoting the sharing and reuse of software generally. 276 | 277 | NO WARRANTY 278 | 279 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 280 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 281 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 282 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 283 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 284 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 285 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 286 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 287 | REPAIR OR CORRECTION. 288 | 289 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 290 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 291 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 292 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 293 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 294 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 295 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 296 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 297 | POSSIBILITY OF SUCH DAMAGES. 298 | 299 | END OF TERMS AND CONDITIONS 300 | 301 | How to Apply These Terms to Your New Programs 302 | 303 | If you develop a new program, and you want it to be of the greatest 304 | possible use to the public, the best way to achieve this is to make it 305 | free software which everyone can redistribute and change under these terms. 306 | 307 | To do so, attach the following notices to the program. It is safest 308 | to attach them to the start of each source file to most effectively 309 | convey the exclusion of warranty; and each file should have at least 310 | the "copyright" line and a pointer to where the full notice is found. 311 | 312 | 313 | Copyright (C) 314 | 315 | This program is free software; you can redistribute it and/or modify 316 | it under the terms of the GNU General Public License as published by 317 | the Free Software Foundation; either version 2 of the License, or 318 | (at your option) any later version. 319 | 320 | This program is distributed in the hope that it will be useful, 321 | but WITHOUT ANY WARRANTY; without even the implied warranty of 322 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 323 | GNU General Public License for more details. 324 | 325 | You should have received a copy of the GNU General Public License along 326 | with this program; if not, write to the Free Software Foundation, Inc., 327 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 328 | 329 | Also add information on how to contact you by electronic and paper mail. 330 | 331 | If the program is interactive, make it output a short notice like this 332 | when it starts in an interactive mode: 333 | 334 | Gnomovision version 69, Copyright (C) year name of author 335 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 336 | This is free software, and you are welcome to redistribute it 337 | under certain conditions; type `show c' for details. 338 | 339 | The hypothetical commands `show w' and `show c' should show the appropriate 340 | parts of the General Public License. Of course, the commands you use may 341 | be called something other than `show w' and `show c'; they could even be 342 | mouse-clicks or menu items--whatever suits your program. 343 | 344 | You should also get your employer (if you work as a programmer) or your 345 | school, if any, to sign a "copyright disclaimer" for the program, if 346 | necessary. Here is a sample; alter the names: 347 | 348 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 349 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 350 | 351 | , 1 April 1989 352 | Ty Coon, President of Vice 353 | 354 | This General Public License does not permit incorporating your program into 355 | proprietary programs. If your program is a subroutine library, you may 356 | consider it more useful to permit linking proprietary applications with the 357 | library. If this is what you want to do, use the GNU Lesser General 358 | Public License instead of this License. 359 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | Welcome to gitbuilder, an autobuilder tool for your favourite git-managed 2 | development project. 3 | 4 | 5 | WHAT IT DOES 6 | ============ 7 | 8 | gitbuilder retrieves the latest version of your project from its git 9 | repository, then builds the most recent versions of all the tags and all the 10 | branches in the entire repository. If any of them have build failures, it 11 | automatically does a "git bisect" style operation to try to track down the 12 | most recent version that compiled successfully. With that information, you 13 | should be able to identify exactly which commit caused the problem, as well 14 | as exactly who was responsible. 15 | 16 | gitbuilder's results are available via the web and via an RSS feed. To see 17 | what the results look like, visit the gitbuilder site for the Versaplex 18 | project: 19 | 20 | http://www.versabanq.com/demo/vxautobuilder/ 21 | 22 | or its RSS feed: 23 | 24 | http://www.versabanq.com/demo/vxautobuilder/rss.cgi 25 | 26 | 27 | INSTALLING 28 | ========== 29 | 30 | Installing gitbuilder is supposed to be easy. It should run on any system 31 | with perl, bash, and git installed. Follow these steps to get started: 32 | 33 | 1. Get a copy of the latest gitbuilder repository. (If you're reading this, 34 | maybe you already did this step!): 35 | 36 | git clone git://github.com/apenwarr/gitbuilder.git 37 | 38 | 2. Go into the gitbuilder directory and clone a copy of the application to 39 | test. For your convenience, we made a handy test project that you can use 40 | to try out gitbuilder's features, which you can clone with a command like 41 | the following: 42 | 43 | cd gitbuilder 44 | git clone git://github.com/apenwarr/builder-test.git build 45 | 46 | !!NOTE!! See the third word on the second line? You have to clone your 47 | project into a directory called 'build', not the normal directory git 48 | would assign it by default. Otherwise gitbuilder wouldn't know how to 49 | build it! 50 | 51 | 3. Make a build.sh script with the instructions required to build your 52 | project. It would sure be nice if everyone's project could just be built 53 | by checking it out and typing "make", right? But we know that's not the 54 | case, because there are often things like autoconf involved. Luckily, 55 | we provided a handy sample build.sh script to go with the handy sample 56 | project: 57 | 58 | cp build.sh.example build.sh 59 | 60 | 4. To see gitbuilder's output, you'll need a web server configured to run 61 | .cgi scripts properly. Configuring your web server is beyond the scope 62 | of this document, but if you already have such a server, maybe something 63 | like this will work for you: 64 | 65 | ln -s $PWD/out ~/public_html/gitbuilder 66 | 67 | If it worked, you should now be able to go to this page in your web 68 | browser: 69 | 70 | http://localhost/~YOUR_USERNAME_GOES_HERE/gitbuilder/ 71 | 72 | (where YOUR_USERNAME_GOES_HERE is replaced with your actual username, of 73 | course.) 74 | 75 | 5. Okay, we're ready to go! Start the autobuilder process! 76 | 77 | ./start 78 | 79 | 6. Now you can go back to your web browser and reload the page repeatedly. 80 | If you're using the sample builder-test project, you should see 81 | gitbuilder do some simple bisection across a few branches as it tries 82 | to track down the broken and non-broken versions automatically. 83 | 84 | 85 | SHARING YOUR AUTOBUILDER RESULTS WITH THE PUBLIC 86 | ================================================= 87 | 88 | Now, maybe the computer you use for autobuilding is wide open on the 89 | Internet, so your internal web server can be shared with everyone. In that 90 | case, congratulations! You're done. Just send the URL to all your friends. 91 | 92 | But if you like to have a little bit of security between your development 93 | network and the Internet, you'll need to do one more step. You can rsync 94 | the gitbuilder output files to your favourite public Internet server. 95 | (Bonus: the public server doesn't need to have git or a compiler installed!) 96 | We provided a handy script to do this for you automatically: 97 | 98 | ./rsync-to my-public-server:public_html/gitbuilder 99 | 100 | 101 | SETTING UP AN AUTOBUILDER IN CRON 102 | ================================= 103 | 104 | Now that your gitbuilder is working, you probably want to have it continue 105 | to building new versions automatically. gitbuilder is designed to make it 106 | safe to do that. Try adding a line like this to your crontab (using crontab 107 | -e): 108 | 109 | * * * * * nice ~/src/gitbuilder/start >/dev/null 2>&1 110 | 111 | This restarts the autobuilder every minute, in case it had stopped in the 112 | meantime. If it was already running, the "start" script is smart enough not 113 | to start it again. Of course, you can change the cron settings to run less 114 | often if that's what you want. 115 | 116 | If you're using recent Linux 2.6.x kernels and you want to eliminate the 117 | effect on your CPU and disk of running gitbuilder in the background, you 118 | should try out ionice. You can change your cron command to something like 119 | this: 120 | 121 | * * * * * ionice -c3 nice -20 ~/src/gitbuilder/start >/dev/null 2>&1 122 | 123 | ionice is extremely powerful; if your system supports it the above command 124 | will make it so that your gitbuilder will *only* use the disk if nobody else 125 | is using it right now. On my system, this makes gitbuilder completely 126 | unnoticeable, even though it spends most of its time building in the 127 | background. Cool! 128 | 129 | Note: in the above, we redirected the output to /dev/null because otherwise 130 | you'd get an email every minute. But redirecting your error output isn't a 131 | very safe thing to do; how will you know if something actually goes wrong? 132 | 133 | If you want a better way to monitor your cron jobs, try out my cron2rss 134 | project: 135 | 136 | http://github.com/apenwarr/cron2rss/ 137 | 138 | 139 | DETAILED COMMANDS 140 | ================= 141 | 142 | gitbuilder is a collection of several tiny scripts that do simple things. 143 | You might want to know about these scripts in case you want to customize how 144 | gitbuilder works. Here we go: 145 | 146 | start: just basically runs this command: 147 | ./runlock lock ./autobuilder.sh 148 | 149 | stop: stop the autobuilder, basically by running: 150 | kill $(cat lock.lock) 151 | 152 | runlock: runs a program only if the given lockfile isn't locked. 153 | This is how we ensure that the autobuilder script doesn't run 154 | more than once simultaneously. 155 | 156 | lock.lock: the file created by runlock if the first parameter is 157 | 'lock'. 158 | 159 | autobuilder.sh: fetches your build/ directory, chooses branches with 160 | branches.sh, chooses revisions to build on each branch with 161 | next-rev.sh, and then runs run-build.sh on each selected revision. 162 | 163 | run-build.sh: checks out a given revision from git in the build/ 164 | directory, then runs build.sh. 165 | 166 | build.sh: a script provided *by you* that builds your application. 167 | See build.sh.example. 168 | 169 | branches.sh: get a list of interesting branches in the build/ 170 | directory. 171 | 172 | revlist.sh: given a branch name, gets a list of all the revisions 173 | starting from that branch's HEAD and stopping at the first 174 | revision that has been built successfully in the past. Basically, 175 | this lists all the recent revisions on a branch that haven't been 176 | built successfully yet. 177 | 178 | next-rev.sh: given a branch name, picks out exactly one revision 179 | from revlist.sh's output that will most help narrow down where any 180 | problems might have come from. 181 | 182 | rsync-to: a simple script to rsync the out/ directory to a web 183 | server somewhere so you can show it to the public. 184 | 185 | out/index.cgi: the main script for generating an HTML view of your 186 | autobuilder. 187 | 188 | out/rss.cgi: the main script for generating an RSS view of your 189 | autobuilder. 190 | 191 | out/log.cgi: a simple script for highlighting and viewing build log 192 | output. 193 | 194 | 195 | DATA FORMAT 196 | =========== 197 | 198 | gitbuilder's output data format is very simple. It consists of files in the 199 | out/pass/, out/fail/, and out/ignore/ directories. 200 | 201 | out/pass/: files in here are named after the SHA-1 of the git commit 202 | that we tried to build. If a particular commit shows up here, it 203 | means that we've successfully build that version in the past, so we 204 | don't need to try building it anymore. The content of each file 205 | is the stdout/stderr of build.sh on the successful run. 206 | 207 | out/fail/: just like out/pass/, only for failed builds. 208 | 209 | out/ignore/: this directory is never written to by gitbuilder, but 210 | you can create files here yourself (using the 'touch' command), 211 | named after the SHA-1 of commits you want to ignore. For example, 212 | if you have a tag that you're tired of seeing in the autobuilder 213 | output, you can get its SHA-1 (available by running 214 | ./branches.sh | grep BRANCHNAME) and create a file here. 215 | 216 | Or maybe you know that your project simply never builds successfully 217 | before a particular revision. For example, maybe build.sh tries 218 | to do "make test", but your project didn't have "make test" 219 | before last week, so all the builds before that will surely fail. 220 | In that case, you can pick the version before you added "make 221 | test" and reference it in the out/ignore/ directory. gitbuilder 222 | will then happily ignore all the versions before that one when 223 | it tries to track down problems. 224 | 225 | HINT: Did you screw up your build.sh and end up with a lot of incorrect 226 | pass/fail indicators? It's safe to just "rm out/pass/* out/fail/*" 227 | and let gitbuilder start over again. 228 | 229 | 230 | Good luck, and let me know how it works for you! 231 | 232 | -- Avery 233 | -------------------------------------------------------------------------------- /autobuilder.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | DIR="$(dirname $0)" 4 | cd "$DIR" 5 | 6 | if [ ! -d build/. ]; then 7 | echo >&2 8 | echo "We need a directory named build/ in this directory." >&2 9 | echo "You should 'git clone' the project you want to test," >&2 10 | echo "like this:" >&2 11 | echo >&2 12 | echo " git clone /path/to/myproject.git build" >&2 13 | echo >&2 14 | exit 2 15 | fi 16 | 17 | if [ -e build.sh -a ! -x build.sh ]; then 18 | chmod a+x build.sh 19 | fi 20 | 21 | if [ ! -x build.sh ]; then 22 | echo >&2 23 | echo "We need an executable file named build.sh in this directory" >&2 24 | echo "in order to run the autobuilder." >&2 25 | echo >&2 26 | echo "Try copying build.sh.example as a starting point." >&2 27 | echo >&2 28 | exit 1 29 | fi 30 | 31 | mkdir -p out/pass out/fail out/ignore out/errcache 32 | chmod a+w out/errcache 33 | 34 | build() { 35 | local ref="$1" 36 | 37 | if [ -z "$ref" ]; then 38 | echo "$branch: already up to date." 39 | return 40 | fi 41 | if [ -e "out/pass/$ref" -o -e "out/fail/$ref" ]; then 42 | return 43 | fi 44 | did_something=1 45 | echo "Building $branch: $ref" 46 | set -m 47 | ./runtee out/log ./run-build.sh $ref || true & 48 | XPID=$! 49 | trap "echo 'Killing (SIGINT)'; kill -TERM -$XPID; exit 1" SIGINT 50 | trap "echo 'Killing (SIGTERM)'; kill -TERM -$XPID; exit 1" SIGTERM 51 | wait; wait 52 | } 53 | 54 | did_something=1 55 | while [ -n "$did_something" ]; do 56 | ( cd build && 57 | git remote show | ../maxtime 60 xargs git remote prune && 58 | ../maxtime 60 git remote update ) 59 | did_something= 60 | 61 | # Build top of every branch first of all 62 | branches=$(./branches.sh) 63 | for branch in $branches; do 64 | xref=$(cd build && git rev-parse "$branch~0") 65 | build "$xref" 66 | done 67 | 68 | # Only then do we try bisecting other branches 69 | for branch in $branches; do 70 | xref=$(./next-rev.sh $branch) 71 | build "$xref" 72 | done 73 | 74 | sleep 5 75 | done 76 | 77 | exit 0 78 | -------------------------------------------------------------------------------- /branches.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | DIR=$(dirname $0) 3 | cd "$DIR/build" 4 | 5 | if [ -e ../branches-local ]; then 6 | exec ../branches-local "$@" 7 | fi 8 | 9 | if [ "$1" = "-v" ]; then 10 | VERBOSE=1 11 | else 12 | VERBOSE= 13 | fi 14 | 15 | refs=$(git show-ref -d) 16 | 17 | (echo "$refs" | grep -E 'main|master'; # build main and master first 18 | echo "$refs" | grep -vE 'main|master') | 19 | grep -v ' refs/heads/' | 20 | grep -v '/HEAD$' | 21 | grep -v '\.trac$' | 22 | grep -v ' refs/stash$' | 23 | sed -e 's, [^/]*/[^/]*/, ,' -e 's,\^{},,' | 24 | tac | 25 | while read commit branch; do 26 | pb="$lb" 27 | lb="$branch" 28 | if [ -e ../out/ignore/$commit -o "$pb" = "$branch" ]; then 29 | continue 30 | fi 31 | [ -n "$VERBOSE" ] && echo -n "$commit " 32 | echo "$branch" 33 | done | 34 | tac 35 | -------------------------------------------------------------------------------- /build.sh.example: -------------------------------------------------------------------------------- 1 | #!/bin/bash -x 2 | # 3 | # Copy this file to build.sh so that gitbuilder can run it. 4 | # 5 | # What happens is that gitbuilder will checkout the revision of your software 6 | # it wants to build in the directory called gitbuilder/build/. Then it 7 | # does "cd build" and then "../build.sh" to run your script. 8 | # 9 | # You might want to run ./configure here, make, make test, etc. 10 | # 11 | 12 | # Don't forget to run autoconf and ./configure, if that's what your project 13 | # needs. 14 | [ ! -x autogen.sh ] || ./autogen.sh || exit 1 15 | autoconf || true 16 | [ ! -x configure ] || ./configure || exit 2 17 | 18 | # Actually build the project 19 | make || exit 3 20 | 21 | # Only run the unit tests if the 'make test' target exists. Make will 22 | # return 1 if a target exists but isn't up-to-date, or 2 on error. 23 | make -q tests 24 | if [ "$?" = 1 ]; then 25 | # run "make test", but give it a time limit in case a test gets stuck 26 | ../maxtime 1800 make test || exit 4 27 | fi 28 | 29 | exit 0 30 | -------------------------------------------------------------------------------- /changed-revs.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | DIR=$(dirname $0) 3 | cd "$DIR/build" 4 | 5 | git rev-list --first-parent --pretty='format:%H %ce %s' "$@" | 6 | while read commit email comment; do 7 | [ "$commit" = "commit" ] && continue 8 | if [ -f ../out/lastlog/$commit ]; then 9 | # we've already printed a changelog for this one 10 | break; 11 | fi 12 | echo "$commit $email $comment" 13 | done 14 | -------------------------------------------------------------------------------- /changelog-email: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | DIR=$(dirname $0) 3 | cd "$DIR" || exit 5 4 | 5 | 6 | EMAIL=$(git var GIT_AUTHOR_IDENT | sed 's/^.*<\(.*\)>.*$/\1/') 7 | if [ -r out/changelog-email-from ]; then 8 | EMAIL=$(cat out/changelog-email-from) 9 | fi 10 | 11 | PROJ=Git 12 | if [ -r out/project-name ]; then 13 | PROJ=$(cat out/project-name) 14 | fi 15 | 16 | DATE=$(date +%Y-%m-%d) 17 | 18 | cat <<-EOF 19 | From: ChangeLog Script <$EMAIL> 20 | To: (undisclosed recipients); 21 | Subject: Changes in $PROJ for $DATE 22 | MIME-Version: 1.0 23 | Content-Type: text/html; charset=utf-8 24 | Precedence: bulk 25 | Importance: low 26 | X-This-Is-Git-Changelog: yes 27 | List-id: 28 | 29 | EOF 30 | 31 | cd out || exit 6 32 | exec ./changelog.pl "$@" 33 | -------------------------------------------------------------------------------- /maxtime: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl -w 2 | use strict; 3 | 4 | if (@ARGV < 2) { 5 | print STDERR "Usage: $0 \n"; 6 | print STDERR " Run a program, killing it after maxtime-seconds.\n"; 7 | exit 127; 8 | } 9 | 10 | my $maxtime = shift @ARGV; 11 | 12 | my $pid = fork(); 13 | if ($pid) { 14 | # parent 15 | local $SIG{INT} = sub { kill 2, -$pid; }; 16 | local $SIG{TERM} = sub { kill 15, -$pid; }; 17 | local $SIG{ALRM} = sub { kill 15, -$pid; sleep 1; kill 9, -$pid; exit 98; }; 18 | alarm $maxtime; 19 | my $newpid = waitpid($pid, 0); 20 | if ($newpid != $pid) { 21 | die("waitpid returned '$newpid', expected '$pid'\n"); 22 | } 23 | my $ret = $?; 24 | exit $? >> 8; 25 | } else { 26 | # child 27 | setpgrp(0,0); 28 | exec(@ARGV); 29 | } 30 | 31 | # NOTREACHED 32 | exit 99; 33 | -------------------------------------------------------------------------------- /next-rev.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | DIR=$(dirname $0) 3 | cd "$DIR/build" 4 | 5 | bisect() 6 | { 7 | (git rev-list --first-parent --bisect-all "$@" || 8 | git rev-list --first-parent "$@" ) | 9 | while read x y; do 10 | [ -e ../out/pass/$x -o -e ../out/fail/$x ] && continue 11 | echo $x 12 | exit 0 13 | done 14 | } 15 | 16 | ../revlist.sh "$@" | ( 17 | pass= 18 | firstfail= 19 | fail= 20 | pending= 21 | while read commit junk; do 22 | if [ -e "../out/pass/$commit" ]; then 23 | # only a maximum of one pass is ever received 24 | pass=$commit 25 | elif [ -e "../out/fail/$commit" ]; then 26 | # there might be more than one fail; we want the 27 | # last one, so that we can figure out where things 28 | # started to go wrong. 29 | fail=$commit 30 | [ -n "$firstfail" ] || firstfail=$commit 31 | elif [ -z "$pending" -a -z "$fail" ]; then 32 | # and we only want the first pending build, 33 | # and only if it's *not* following a failed build 34 | pending=$commit 35 | fi 36 | last=$commit 37 | done 38 | 39 | if [ -n "$pending" ]; then 40 | # if a pending build came before the first failed build, 41 | # then we need to build it first. 42 | echo "$pending" 43 | elif [ -n "$fail" ]; then 44 | # If there were no passing tests, just use the last one as 45 | # a reference. 46 | [ -n "$pass" ] || pass=$last 47 | 48 | # First, we want to bisect to find the *last* failure before 49 | # the first pass. That is, the commit where failures were 50 | # introduced. 51 | try=$(bisect "$fail^" "^$pass") 52 | 53 | # But if there's nothing left to try (we tested it already), 54 | # let's keep building the other commits in between, just in 55 | # case one of the intermediate ones passes. (This can happen 56 | # if commits are failing for two different reasons, sigh.) 57 | if [ -z "$try" ]; then 58 | try=$(bisect "$firstfail^" "^$pass") 59 | fi 60 | if [ -n "$try" ]; then 61 | echo "$try" 62 | fi 63 | fi 64 | 65 | # if we don't print anything at all, it means there's nothing to build! 66 | ) 67 | -------------------------------------------------------------------------------- /revdetail.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | DIR=$(dirname $0) 3 | cd "$DIR/build" 4 | 5 | git log --first-parent --name-only --pretty=raw --no-walk "$@" -- | cat 6 | -------------------------------------------------------------------------------- /revlist.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | DIR=$(dirname $0) 3 | cd "$DIR/build" 4 | 5 | #ls ../out/pass/* | 6 | # sed -e 's,^\(.*/\)*\([0-9a-f]*\).*$,^\2^,g' | 7 | git rev-list --first-parent --pretty='format:%H %ce %s' "$@" | 8 | while read commit email comment; do 9 | [ "$commit" = "commit" ] && continue 10 | if [ -f ../out/ignore/$commit ]; then 11 | # never print an ignored commit 12 | exit 0; 13 | fi 14 | echo "$commit $email $comment" 15 | if [ -f ../out/pass/$commit ]; then 16 | # print the first passing commit, then done 17 | exit 0; 18 | fi 19 | done 20 | -------------------------------------------------------------------------------- /rsync-to: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | DIR="$(dirname $0)" 3 | cd "$DIR" 4 | if [ -z "$1" ]; then 5 | echo "Usage: $0 " >&2 6 | exit 1 7 | fi 8 | chmod a+rX -R out 2>/dev/null 9 | 10 | echo "Generating branch list..." >&2 11 | rm -f out/revcache 12 | ./branches.sh -v | while read commit branch junk; do 13 | echo ":$commit $branch" 14 | ./revlist.sh $branch 15 | done >out/revcache 16 | 17 | echo "Describing..." >&2 18 | mkdir -p out/describe 19 | ( 20 | cd build 21 | for d in ../out/pass/* ../out/fail/*; do 22 | b=$(basename $d) 23 | git describe --all --contains --always $b >../out/describe/$b 24 | done 25 | ) 26 | 27 | echo "Rsyncing..." >&2 28 | exec rsync -zvaP --no-owner --exclude '*~' \ 29 | out viewer \ 30 | "$1" 31 | -------------------------------------------------------------------------------- /run-build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ -z "$1" ]; then 4 | echo "Usage: $0 " >&2 5 | echo " Build the tree in build/ as of the given commitid." 6 | exit 1 7 | fi 8 | 9 | ref="$1" 10 | 11 | mkdir -p out/fail out/pass 12 | chmod 777 out/fail 13 | 14 | log() 15 | { 16 | (echo; echo ">>> $@") # log file 17 | } 18 | 19 | _run() 20 | { 21 | log "Starting at: $(date)" 22 | commit="$1" 23 | log "Commit: $commit" 24 | 25 | cd build || return 10 26 | 27 | log "Removing submodules..." 28 | git submodule foreach git clean -q -f -x -d && 29 | git submodule deinit --all --force && 30 | git ls-files --others | ( 31 | # 'git clean' refuses to delete sub-repositories (anything containing 32 | # a .git dir) and there's no way to change its mind, so we occasionally 33 | # have to do it the hard way. 34 | while read -r name; do 35 | rm -rf "./$name" 36 | done 37 | ) || return 15 38 | 39 | log "Switching git branch..." 40 | git checkout --detach && 41 | git reset --hard "$commit" 2>&1 | grep -v 'warning:' || return 20 42 | 43 | log "Cleaning..." 44 | git clean -q -f -x -d || return 30 45 | 46 | log "Building..." 47 | ../build.sh 2>&1 || return 40 48 | 49 | log "Done at: $(date)" 50 | return 0 51 | } 52 | 53 | run() 54 | { 55 | ( _run "$@" ) 56 | CODE=$? 57 | log "Result code: $CODE" 58 | return $CODE 59 | } 60 | 61 | go() 62 | { 63 | echo $ref >out/.doing 64 | rm -f out/pass/$ref out/fail/$ref 65 | run $ref 66 | CODE=${PIPESTATUS[0]} 67 | 68 | # This whole program's output is being dumped in log.out. Unix 69 | # lets us rename open files, so we can do that here. 70 | # FIXME: it would be cleaner if the caller renamed the output 71 | # file based on our result code, however. 72 | if [ "$CODE" = 0 ]; then 73 | echo PASS 74 | mv -v out/log out/pass/$ref 75 | else 76 | echo FAIL 77 | mv -v out/log out/fail/$ref 78 | fi 79 | 80 | echo "Done: $ref" 81 | rm -f out/.doing 82 | return $CODE 83 | } 84 | 85 | set -m 86 | go & 87 | XPID=$! 88 | trap "echo 'Killing (SIGINT)'; kill -TERM -$XPID; exit 1" SIGINT 89 | trap "echo 'Killing (SIGTERM)'; kill -TERM -$XPID; exit 1" SIGTERM 90 | wait $XPID 91 | # return exit code from previous command 92 | -------------------------------------------------------------------------------- /runlock: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl -w 2 | # 3 | # A simple script that runs the specified command only if the given lockfile 4 | # is not locked. If it *is* locked, we just return 0, considering that 5 | # a success (after all, the command probably is running successfully; it's 6 | # just not us that ran it!) 7 | # 8 | # If it is *not* currently locked, we lock it, run the command, and return 9 | # its result. 10 | # 11 | # We also make an extra effort to handle signals correctly and cleanup our 12 | # subprocess and lock file when we receive one. 13 | # 14 | use strict; 15 | use LockFile::Simple; 16 | 17 | if (@ARGV < 2) { 18 | print STDERR "Usage: $0 \n"; 19 | exit 127; 20 | } 21 | 22 | my $lm = LockFile::Simple->make(-stale=>1, -hold=>0) 23 | or die("makelock: $!\n"); 24 | my $filename = shift @ARGV; 25 | 26 | my $lock = $lm->trylock($filename); 27 | if (defined($lock)) { 28 | my $pid = fork(); 29 | if ($pid) { 30 | # parent 31 | local $SIG{INT} = sub { kill 2, $pid; }; 32 | local $SIG{TERM} = sub { kill 15, $pid; }; 33 | my $newpid = waitpid($pid, 0); 34 | if ($newpid != $pid) { 35 | die("waitpid returned '$newpid', expected '$pid'\n"); 36 | } 37 | my $ret = $?; 38 | $lock->release; 39 | exit $ret >> 8; 40 | } else { 41 | # child 42 | exec(@ARGV); 43 | } 44 | 45 | # NOTREACHED 46 | } 47 | 48 | # didn't obtain lock, so didn't run; call that success, so we don't pop up 49 | # annoying messages in cron. 50 | print STDERR "Still locked.\n"; 51 | exit 0; 52 | -------------------------------------------------------------------------------- /runtee: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl -w 2 | # 3 | # A variant of 'tee' that runs a command and stops when that command finishes. 4 | # This is needed instead of 'tee' because sometimes, the command ends up 5 | # (probably accidentally) forking more subprocesses, which might continue 6 | # living beyond the lifetime of the original process we started. But 'tee' 7 | # will keep on going until *all* the processes die that have stdout connected 8 | # to its stdin pipe, which is no good. 9 | # 10 | # runtee starts its own subprocess, so it can monitor to see when that 11 | # subprocess dies, and clean up accordingly at that time. 12 | # 13 | # Like 'tee', we write to the given file *and* to stdout. Unlike 'tee', 14 | # we capture both stdout and stderr from the program. 15 | # 16 | use strict; 17 | use IO::Select; 18 | use POSIX ":sys_wait_h"; 19 | $| = 1; 20 | 21 | if (@ARGV < 2) { 22 | print STDERR "Usage: $0 \n"; 23 | exit 127; 24 | } 25 | 26 | my $logname = shift @ARGV; 27 | open(my $log, ">$logname") or die("Can't open $logname: $!\n"); 28 | 29 | my $pid = open(my $fh, "-|"); 30 | my $done = 0; 31 | if ($pid) { 32 | # parent 33 | local $SIG{INT} = sub { kill 2, $pid; }; 34 | local $SIG{TERM} = sub { kill 15, $pid; }; 35 | local $SIG{CHLD} = sub { 36 | $done = 1; 37 | }; 38 | my $s = IO::Select->new($fh); 39 | while (1) { 40 | if ($s->can_read($done ? 0 : 5)) { 41 | my $buf; 42 | my $len = sysread($fh, $buf, 1024); 43 | last if ($len == 0); # EOF, definitely done 44 | print STDOUT $buf; 45 | print $log $buf; 46 | } elsif ($done) { 47 | # only honour $done if the input buffer is empty 48 | last; 49 | } 50 | } 51 | my $newpid = waitpid($pid, 0); 52 | if ($newpid != $pid) { 53 | die("waitpid returned '$newpid', expected '$pid'\n"); 54 | } 55 | exit $? >> 8; 56 | } else { 57 | # child 58 | open STDERR, '>&STDOUT' or die("Can't dup stdout: $!\n"); 59 | exec(@ARGV); 60 | exit 126; # just in case 61 | } 62 | 63 | # NOTREACHED 64 | exit 125; 65 | -------------------------------------------------------------------------------- /start: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | DIR="$(dirname $0)" 3 | cd "$DIR" 4 | exec ./runlock lock ./autobuilder.sh 5 | -------------------------------------------------------------------------------- /stop: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | if [ ! -e lock.lock ]; then 3 | echo "Not running; lock.lock doesn't exist." 4 | exit 1 5 | fi 6 | 7 | kill $(cat lock.lock) 8 | -------------------------------------------------------------------------------- /viewer/Autobuilder.pm: -------------------------------------------------------------------------------- 1 | package Autobuilder; 2 | require Exporter; 3 | @ISA = qw(Exporter); 4 | @EXPORT = qw(find_errors squish_log mtime catfile basename stripwhite 5 | shorten git_describe project_name gitweb_url autobuilder_url commitlink); 6 | 7 | use strict; 8 | 9 | sub _cat_line($) 10 | { 11 | my $filename = shift; 12 | if (-r $filename) { 13 | my $s = catfile($filename); 14 | $s =~ s/^\s*//; 15 | $s =~ s/\s*$//; 16 | return $s; 17 | } 18 | return undef; 19 | } 20 | 21 | sub project_name() 22 | { 23 | return _cat_line('../project-name'); 24 | } 25 | 26 | my $outdir = '../out'; 27 | 28 | my $gitweb_url; 29 | sub gitweb_url() 30 | { 31 | return $gitweb_url; 32 | } 33 | $gitweb_url = _cat_line('../gitweb-url'); 34 | 35 | my $autobuilder_url; 36 | sub autobuilder_url() 37 | { 38 | return $autobuilder_url; 39 | } 40 | $autobuilder_url = _cat_line('../autobuilder-url') 41 | and $autobuilder_url =~ s{/$}{}; 42 | 43 | sub commitlink($$) 44 | { 45 | my ($commit, $text) = @_; 46 | my $gitweb_url = gitweb_url(); 47 | if ($gitweb_url) { 48 | return "" 49 | . $text 50 | . ""; 51 | } 52 | return $text; 53 | } 54 | 55 | my $err_tail = ""; 56 | sub _find_errors($$) 57 | { 58 | my $rev = shift; 59 | my $filename = shift; 60 | my $out = ""; 61 | my $warnings = 0; 62 | my $errors = 0; 63 | my $testsfailed = 0; 64 | my $overallfail = 0; 65 | my $ignore_warnings = 0; 66 | my @tail = (); 67 | 68 | if (-e "$outdir/fail/$rev") { 69 | $overallfail = 1; 70 | } 71 | 72 | open my $fh, "<$filename" 73 | or die("Can't open $filename: $!\n"); 74 | while (defined(my $s = <$fh>)) { 75 | chomp $s; 76 | if ($s =~ /--START-IGNORE-WARNINGS/) { 77 | $ignore_warnings++; 78 | } elsif ($s =~ /--STOP-IGNORE-WARNINGS/) { 79 | if ($ignore_warnings <= 0) { 80 | $out .= "WARNING: Mismatched STOP-IGNORE-WARNINGS
\n"; 81 | } else { 82 | $ignore_warnings--; 83 | } 84 | } elsif ($s =~ /^\s*(make: \*\*\* .*)/) { 85 | $out .= "$1
\n"; 86 | # $errors++; # the result code should be enough... 87 | } elsif ($s =~ /^\s*(\S*)\s*(hint|warning|error|fatal)\s*:\s*(.*)/i) { 88 | my $type = $2; 89 | my $s = "$type: $1 $3
\n"; 90 | if ($type =~ /(error|fatal)/i) { 91 | $out .= $s; 92 | $errors++; 93 | } else { 94 | if ($ignore_warnings == 0) { 95 | $out .= $s; 96 | $warnings++; 97 | } 98 | } 99 | } elsif ($s =~ /^\s*(\S*)\s*(hint|warning)\s*:\s*(.*)/i) { 100 | $out .= "$2: $1 $3
\n"; 101 | $warnings++; 102 | } elsif ($s =~ /^!\s*(.*?)\s+(\S+)\s*$/) { 103 | if ($2 ne "ok") { 104 | $out .= "! $1 $2
\n"; 105 | $testsfailed++; 106 | } 107 | } 108 | push @tail, "$s
\n"; 109 | if (@tail > 25) { 110 | shift @tail; 111 | } 112 | } 113 | 114 | if ($ignore_warnings > 0) { 115 | $out .= "WARNING: Mismatched START-IGNORE-WARNINGS
\n"; 116 | } 117 | 118 | close $fh; 119 | $err_tail = "

\n\nLast few messages:

\n\n@tail\n"; 120 | my @msg = (); 121 | if ($warnings) { 122 | push @msg, "Warnings($warnings)"; 123 | } 124 | if ($errors || ($overallfail && !$testsfailed)) { 125 | if ($errors > 0) { 126 | push @msg, "Errors($errors)"; 127 | } else { 128 | push @msg, "Errors"; 129 | } 130 | } 131 | if ($testsfailed) { 132 | push @msg, "Failures($testsfailed)"; 133 | } 134 | if (!@msg) { 135 | push @msg, "ok"; 136 | } 137 | return join("/", @msg), $out; 138 | } 139 | 140 | sub age($) 141 | { 142 | my $filename = shift; 143 | return -M $filename; 144 | } 145 | 146 | sub find_errors($) 147 | { 148 | my $rev = shift; 149 | my $fn; 150 | 151 | if (-e "$outdir/pass/$rev") { 152 | $fn = "$outdir/pass/$rev"; 153 | } elsif (-e "$outdir/fail/$rev") { 154 | $fn = "$outdir/fail/$rev"; 155 | } else { 156 | return undef, undef; 157 | } 158 | 159 | if (-r "$outdir/errcache/$rev" && age("$outdir/errcache/$rev") < age($fn)) { 160 | return _find_errors($rev, "$outdir/errcache/$rev"); 161 | } else { 162 | my ($warnmsg, $errs) = _find_errors($rev, $fn); 163 | if (defined($warnmsg)) { 164 | mkdir "errcache"; 165 | open my $outf, ">$outdir/errcache/$rev"; 166 | print $outf $errs; 167 | close $outf; 168 | } 169 | return $warnmsg, $errs; 170 | } 171 | } 172 | 173 | sub squish_log($) 174 | { 175 | my $rev = shift; 176 | my ($msg, $out) = find_errors($rev); 177 | return $out . $err_tail; 178 | } 179 | 180 | sub mtime($) 181 | { 182 | my $filename = shift @_; 183 | my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size, 184 | $atime,$mtime,$ctime,$blksize,$blocks) = stat($filename) 185 | or die("stat $filename: $!\n"); 186 | return $mtime; 187 | } 188 | 189 | sub catfile(@) 190 | { 191 | my @list = (); 192 | foreach my $file (@_) { 193 | open my $fh, "<$file" or die("$file: $!\n"); 194 | push @list, <$fh>; 195 | close $fh; 196 | } 197 | return join('', @list); 198 | } 199 | 200 | sub basename($) 201 | { 202 | my $filename = shift @_; 203 | $filename =~ m{.*/([^/]+)} && ($filename = $1); 204 | return $filename; 205 | } 206 | 207 | sub stripwhite($) 208 | { 209 | my $s = shift @_; 210 | $s =~ s/^\s+//mg; 211 | $s =~ s/\s+$//mg; 212 | return $s; 213 | } 214 | 215 | sub shorten($$@) 216 | { 217 | my ($s, $len, $suffix) = @_; 218 | if (!defined($suffix)) { 219 | $suffix = "..."; 220 | } 221 | if (length($s) > $len) { 222 | return substr($s, 0, $len) . $suffix; 223 | } else { 224 | return $s; 225 | } 226 | } 227 | 228 | sub git_describe($) 229 | { 230 | my $commit = shift; 231 | if (-d '../build/.') { 232 | return stripwhite( 233 | `cd ../build && git describe --contains --all $commit`); 234 | } else { 235 | return stripwhite(catfile("../out/describe/$commit")); 236 | } 237 | } 238 | 239 | 1; 240 | -------------------------------------------------------------------------------- /viewer/index.cgi: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl -w 2 | use strict; 3 | use CGI qw/:standard *table start_ul start_div end_div/; 4 | use POSIX qw(strftime); 5 | 6 | use lib "."; 7 | use Autobuilder; 8 | 9 | my @branches = (); 10 | my %revs = (); 11 | 12 | sub load_revcache() 13 | { 14 | open my $fh, "<../out/revcache" 15 | or return; # try to survive without it, then 16 | my $branch; 17 | my @list; 18 | while (<$fh>) { 19 | chomp; 20 | if (/^\:(.*)/) { 21 | my ($topcommit, $newbranch) = split(" ", $1, 2); 22 | if ($branch) { 23 | $revs{$branch} = join("\n", @list); 24 | } 25 | push @branches, "$topcommit $newbranch"; 26 | $branch = $newbranch; 27 | @list = (); 28 | } else { 29 | push @list, $_; 30 | } 31 | } 32 | if ($branch) { 33 | $revs{$branch} = join("\n", @list); 34 | } 35 | close $fh; 36 | } 37 | load_revcache(); 38 | 39 | my $currently_doing = (-f '../out/.doing') && stripwhite(catfile("../out/.doing")) || ""; 40 | 41 | sub run_cmd(@) 42 | { 43 | my @cmdline = @_; 44 | 45 | open(my $fh, "-|", @cmdline) 46 | or die("Can't run $cmdline[0]: $!\n"); 47 | my @out = <$fh>; 48 | chomp @out; 49 | close $fh; 50 | return @out; 51 | } 52 | 53 | sub revs_for_branch($) 54 | { 55 | my $branch = shift; 56 | if (-x '../revlist.sh') { 57 | return run_cmd("../revlist.sh", $branch); 58 | } else { 59 | return split("\n", $revs{$branch}); 60 | } 61 | } 62 | 63 | sub _list_branches() 64 | { 65 | if (-x '../branches.sh') { 66 | return run_cmd("../branches.sh", "-v"); 67 | } else { 68 | return @branches; 69 | } 70 | } 71 | 72 | 73 | sub list_branches() 74 | { 75 | my @out = (); 76 | foreach my $line (_list_branches()) 77 | { 78 | my ($commit, $branch) = split(" ", $line, 2); 79 | my $branchword = $branch; 80 | next if $branchword =~ /@/; 81 | $branchword =~ s{^.*/}{}; 82 | push @out, "$branchword $branch $commit"; 83 | } 84 | return @out; 85 | } 86 | 87 | my $title = "Autobuilder results"; 88 | my $project_name = project_name(); 89 | if ($project_name) { 90 | $title .= " for $project_name"; 91 | } 92 | 93 | print header(-type => 'text/html; charset=utf-8'), 94 | start_html( 95 | -title => $title, 96 | -style => [ 97 | {-src => "/bootstrap.css"}, 98 | {-src => "/bootstrap-responsive.css"}, 99 | {-src => "/docs.css"}, 100 | {-src => "/index.css"},], 101 | ); 102 | 103 | print Link({-rel=>"alternate", -title=>$title, 104 | -href=>"rss.cgi", -type=>"application/rss+xml"}); 105 | 106 | print div({-class=>"logo"}, "compiled by ", 107 | a({-href=>"http://github.com/apenwarr/gitbuilder/"}, 108 | "gitbuilder")); 109 | 110 | print h1($title, 111 | a({-href=>"rss.cgi",-title=>"Subscribe via RSS"}, 112 | img({-src=>"/feed-icon-28x28.png",-alt=>"[RSS]"})), 113 | ); 114 | 115 | my @branchlist = list_branches(); 116 | 117 | sub branch_age($) 118 | { 119 | my ($branchword, $branch, $topcommit) = split(" ", shift, 3); 120 | if (-f "../out/fail/$topcommit") { 121 | return -M "../out/fail/$topcommit"; 122 | } elsif (-f "../out/pass/$topcommit") { 123 | return -M "../out/pass/$topcommit"; 124 | } else { 125 | return -1; 126 | } 127 | } 128 | 129 | sub fixbranchprint($) 130 | { 131 | my $branchprint = shift; 132 | $branchprint =~ s{^origin/}{}; 133 | $branchprint =~ s{(.*/?)(.*)}{$1$2}; 134 | return $branchprint; 135 | } 136 | 137 | sub status_to_statcode($) 138 | { 139 | my $status = shift; 140 | if (!defined($status)) { 141 | return "pending"; 142 | } elsif ($status eq "ok") { 143 | return "ok"; 144 | } elsif ($status eq "BUILDING") { 145 | return "pending"; 146 | } elsif ($status eq "(Pending)") { 147 | return "pending"; 148 | } elsif ($status =~ m{^W[^/]*$}) { 149 | return "warn"; 150 | } else { 151 | # some kind of FAIL marker by default 152 | return "err"; 153 | } 154 | } 155 | 156 | print start_div({id=>"most_recent"}), 157 | "Most Recent:", 158 | start_ul({id=>"most_recent_list"}); 159 | for my $bpb (sort { branch_age($a) <=> branch_age($b) } @branchlist) { 160 | my ($branchword, $branch, $topcommit) = split(" ", $bpb, 3); 161 | my $branchprint = fixbranchprint($branch); 162 | my $fn; 163 | 164 | next if (-f "ignore/$topcommit"); 165 | 166 | my ($warnmsg, $errs) = find_errors($topcommit); 167 | my $statcode = status_to_statcode($warnmsg); 168 | print li(a({href=>"#$branch"}, 169 | span({class=>"status branch status-$statcode"}, $branchprint))); 170 | 171 | last if (branch_age($bpb) > 30); 172 | } 173 | print end_ul, end_div; 174 | 175 | 176 | print start_table({class=>"table-bordered results",align=>"center"}); 177 | print Tr({class=>"resultheader"}, 178 | th({style=>'text-align: right'}, "Branch"), 179 | th("Status"), th("Commit"), th("Who"), th("Result")); 180 | 181 | sub spacer() 182 | { 183 | return Tr({class=>"spacer"}, td({colspan=>6}, "")); 184 | } 185 | 186 | my $last_ended_in_spacer = 0; 187 | for my $bpb (sort { lc($a) cmp lc($b) } @branchlist) { 188 | our ($branchword, $branch, $topcommit) = split(" ", $bpb, 3); 189 | our $branchprint = fixbranchprint($branch); 190 | 191 | our $last_was_pending = 0; 192 | our $print_pending = 1; 193 | 194 | my @branchout = (); 195 | 196 | sub do_pending_dots(\@) 197 | { 198 | my $_branchout = shift; 199 | if ($last_was_pending > $print_pending) { 200 | $last_was_pending -= $print_pending; 201 | $print_pending = 0; 202 | push @{$_branchout}, Tr( 203 | td($branchprint), 204 | td({class=>"status"}, "...$last_was_pending..."), 205 | td(""), td(""), td("")); 206 | $branchprint = ""; 207 | } 208 | $last_was_pending = 0; 209 | } 210 | 211 | foreach my $rev (revs_for_branch($branch)) { 212 | my ($commit, $email, $comment) = split(" ", $rev, 3); 213 | 214 | my $failed; 215 | my $logcgi = "log/$commit"; 216 | my $rebuildcgi = "rebuild/$commit"; 217 | $email =~ s/\@.*//; 218 | my $commitlink = commitlink($commit, shorten($commit, 7, "")); 219 | $comment =~ s/^\s*-?\s*//; 220 | 221 | sub pushrow(\@$$$$$$$) 222 | { 223 | my ($_branchout, $status, $commitlink, 224 | $email, $codestr, $comment, $logcgi, $rebuildcgi) = @_; 225 | 226 | my $statcode = status_to_statcode($status); 227 | 228 | do_pending_dots(@{$_branchout}); 229 | push @{$_branchout}, 230 | Tr({class=>"result"}, 231 | td({class=>"branch"}, 232 | $branchprint), 233 | td({class=>"status status-$statcode"}, $status), 234 | td({class=>"commit"}, $commitlink), 235 | td({class=>"committer"}, $email), 236 | td({class=>"details"}, 237 | a({class=>"hyper", name=>$branch}, "") . div( 238 | span({class=>"codestr"}, 239 | $logcgi ? a({-href=>$logcgi}, $codestr) : $codestr), 240 | span({class=>"comment"}, $comment, 241 | ("$statcode" eq "err" || "$statcode" eq "warn") ? "(" . 242 | a({-href=>"$rebuildcgi"}, "Force Rebuild") . ")" : "") 243 | )) 244 | ); 245 | $branchprint = ""; 246 | } 247 | 248 | if (-f "../out/pass/$commit") { 249 | $failed = 0; 250 | # fall through 251 | } elsif (-f "../out/fail/$commit") { 252 | $failed = 1; 253 | # fall through 254 | } elsif ($commit eq $currently_doing) { 255 | # currently building this one 256 | pushrow(@branchout, "BUILDING", 257 | $commitlink, $email, "", $comment, "", ""); 258 | next; 259 | } elsif ($last_was_pending == 0 && $print_pending) { 260 | # first pending in a group: print (Pending) 261 | pushrow(@branchout, "(Pending)", 262 | $commitlink, $email, "", $comment, "", ""); 263 | $last_was_pending = 1; 264 | next; 265 | } else { 266 | # no info yet: just count, don't print 267 | $last_was_pending++; 268 | next; 269 | } 270 | 271 | my ($warnmsg, $errs) = find_errors($commit); 272 | my $status = ($warnmsg eq "ok") ? "ok" 273 | : ($warnmsg =~ /^Warnings\(\d+\)$/) ? "Warn" : "FAIL"; 274 | pushrow(@branchout, $status, 275 | $commitlink, $email, $warnmsg, $comment, $logcgi, $rebuildcgi); 276 | } 277 | 278 | do_pending_dots(@branchout); 279 | 280 | if (@branchout > 1) { 281 | if (!$last_ended_in_spacer) { 282 | print spacer; 283 | } 284 | print @branchout, spacer; 285 | $last_ended_in_spacer = 1; 286 | } else { 287 | print @branchout; 288 | $last_ended_in_spacer = 0; 289 | } 290 | } 291 | 292 | print end_table(); 293 | print div({class=>"extraspace"}, " "); 294 | print end_html; 295 | exit 0; 296 | -------------------------------------------------------------------------------- /viewer/log.cgi: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl -w 2 | use strict; 3 | use CGI qw/:standard *table start_ul end_ul start_li end_li/; 4 | use lib "."; 5 | use Autobuilder; 6 | 7 | my $commit = param('log'); 8 | $commit =~ s/[^0-9A-Za-z]/_/g; 9 | $commit =~ s/^\./_/; 10 | 11 | print header(-type => 'text/html; charset=utf-8'), 12 | start_html( 13 | -title => "$commit - Autobuilder log", 14 | -style => [ 15 | {-src => "/bootstrap.css"}, 16 | {-src => "/bootstrap-responsive.css"}, 17 | {-src => "/docs.css"}, 18 | {-src => "/log.css"},], 19 | ); 20 | 21 | print div({-style=>'float: right'}, a({-href=>"."}, "<< index")); 22 | my $name = git_describe($commit); 23 | my $commitlink = commitlink($commit, $commit); 24 | print h1("Autobuilder log for $name
($commitlink):"); 25 | print "(", a({-href=>"/rebuild/$commitlink"}, "Force Rebuild"), ")"; 26 | 27 | my $fn; 28 | if (-f "../out/pass/$commit") { 29 | $fn = "../out/pass/$commit"; 30 | } elsif (-f "../out/fail/$commit") { 31 | $fn = "../out/fail/$commit"; 32 | } else { 33 | print h2("No log with that id."); 34 | exit 1; 35 | } 36 | 37 | open my $fh, "<$fn" 38 | or die("$fn: $!\n"); 39 | 40 | my $in = 0; 41 | my $ignore_warnings = 0; 42 | while (defined(my $s = <$fh>)) 43 | { 44 | chomp $s; 45 | 46 | $s =~ s/^\s+//g; 47 | $s =~ s/\s+$//g; 48 | 49 | $s =~ s{c:\\build\\tmp\\}{}ig; 50 | $s =~ s{c:\\cygwin\\.*tmp\\}{}ig; 51 | 52 | $s =~ s{^c:\\.*\\dcc32.exe}{...\\dcc32.exe}i; 53 | $s =~ s{^c:\\.*Borland.Delphi.Targets[^:]*: }{: }gi; 54 | 55 | my $class='debug'; 56 | if ($s eq "") { 57 | print p($s); 58 | next; 59 | } elsif ($s =~ /--START-IGNORE-WARNINGS/) { 60 | $ignore_warnings++; 61 | } elsif ($s =~ /--STOP-IGNORE-WARNINGS/) { 62 | $ignore_warnings--; 63 | } elsif ($s =~ /^>>>/) { 64 | $class = "buildscript"; 65 | if ($in) { 66 | print end_ul; 67 | $in = 0; 68 | } 69 | } elsif ($s =~ /^Project ".*"/ || $s =~ /^---/ || $s =~ /^-->/ 70 | || $s =~ /^Testing ".*" in .*:\s*/) { 71 | $class = "msbuild"; 72 | if ($in) { 73 | print end_ul; 74 | } 75 | if ($s =~ /^Project "(.*)" is building "(.*)"/) { 76 | print div({-class=>'msbuild'}, "Building $2:"); 77 | } else { 78 | print div({-class=>'msbuild'}, $s); 79 | } 80 | print start_ul; 81 | $in = 1; 82 | next; 83 | } elsif ($s =~ /^\s*(\S*)\s*(hint|warning|error|fatal)\s*:\s*(.*)/i) { 84 | my $xclass = lc $2; 85 | $s = ul("$2: $1 $3"); 86 | if ($ignore_warnings <= 0 || $xclass !~ /(hint|warning)/i) { 87 | $class = $xclass; 88 | } 89 | } elsif ($s =~ /^(\s*.*\.go:\d+:\d+: .*)/i) { 90 | # errors from go compiler 91 | $class = "error"; 92 | $s = ul($1); 93 | } elsif ($s =~ /^(FAIL(\t.*\d+s|$))/) { 94 | # errors from go tests 95 | $class = "error"; 96 | $s = ul($1); 97 | } elsif ($s =~ /^\s*(make: \*\*\* .*)/) { 98 | # errors from GNU make 99 | $class = "error"; 100 | $s = ul($1); 101 | } elsif ($s =~ /^(redo \s*\S.* \(exit .*)/) { 102 | # errors from redo build system 103 | $class = "error"; 104 | $s = ul($1); 105 | } elsif ($s =~ /^(redo \s*\S.*)/) { 106 | $class = "redo"; 107 | $s = $1; 108 | } elsif ($s =~ /^!\s*(.*?)\s+(\S+)\s*$/) { 109 | $class = ($2 ne "ok") ? 'error' : 'buildscript'; 110 | } 111 | 112 | print div({-class=>$class}, $s); 113 | } 114 | 115 | close $fh; 116 | -------------------------------------------------------------------------------- /viewer/rebuild.tmpl.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |

Do you really want to rebuild commit {{logid}}?

5 |
6 | 7 |
8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /viewer/rss.cgi: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl -w 2 | use strict; 3 | use CGI qw/:standard/; 4 | use POSIX qw(strftime); 5 | 6 | use lib "."; 7 | use Autobuilder; 8 | 9 | my $url = url(); 10 | my $relative = url(-relative=>1); 11 | $url =~ s{/$relative$}{}; 12 | 13 | print "Content-Type: text/xml\n"; 14 | print "\n"; 15 | 16 | my $title = "Autobuilder"; 17 | my $project_name = project_name(); 18 | if ($project_name) { 19 | # use the shortest name possible because some RSS readers don't leave much 20 | # room for the name. Also make sure the critical text comes at the start. 21 | $title = "$project_name Builder"; 22 | } 23 | 24 | print qq{ 25 | 26 | $title 27 | Autobuilder results via gitbuilder 28 | $url 29 | 30 | en-ca 31 | CGI 32 | http://blogs.law.harvard.edu/tech/rss 33 | }; 34 | 35 | my @all = (glob("../out/pass/*"), glob("../out/fail/*")); 36 | my $i = 0; 37 | for my $path (sort { mtime($b) cmp mtime($a) } @all) { 38 | last if ++$i > 20; 39 | my $commit = basename($path); 40 | my $name = git_describe($commit); 41 | $name =~ s{^remotes/}{}; 42 | $name =~ s{^origin/}{}; 43 | 44 | my $filename; 45 | my $failed; 46 | if (-f "../out/pass/$commit") { 47 | $filename = "../out/pass/$commit"; 48 | $failed = 0; 49 | } elsif (-f "../out/fail/$commit") { 50 | $filename = "../out/fail/$commit"; 51 | $failed = 1; 52 | } else { 53 | die("No commit $commit found?!\n"); 54 | next; 55 | } 56 | 57 | my ($warnmsg, $errs) = find_errors($commit); 58 | my $codestr = $warnmsg; 59 | $codestr =~ s/([A-Z])[a-z]*/$1/g; 60 | 61 | my $longstr = "$warnmsg: $commit

\n\n" . squish_log($commit); 62 | $longstr =~ s/\&/\&/g; 63 | $longstr =~ s/ 73 | $codestr: $name 74 | $date 75 | $url/$logcgi 76 | $url/$logcgi#$mtime 77 | $longstr 78 | 79 | }; 80 | } 81 | 82 | print ""; 83 | -------------------------------------------------------------------------------- /viewer/run.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import asyncio 4 | import os 5 | import re 6 | import subprocess 7 | import sys 8 | import time 9 | import tornado.httpserver 10 | import tornado.ioloop 11 | import tornado.template 12 | import tornado.web 13 | 14 | def log(fmt, *args): 15 | if not args: 16 | sys.stderr.write(str(fmt) + '\n') 17 | else: 18 | sys.stderr.write((str(fmt) % args) + '\n') 19 | 20 | 21 | async def run_cgi(self, args, env=None): 22 | if env: 23 | genv = dict(os.environ) 24 | genv.update(env) 25 | else: 26 | genv = None 27 | p = await asyncio.create_subprocess_exec( 28 | *args, 29 | env=genv, 30 | stdout=asyncio.subprocess.PIPE, 31 | ) 32 | 33 | # Skip headers section 34 | while 1: 35 | line = await p.stdout.readline() 36 | if not line.strip(): 37 | break 38 | 39 | # Forward actual content bytes 40 | while 1: 41 | b = await p.stdout.read(1024) 42 | if not b: 43 | break 44 | self.write(b) 45 | self.flush() 46 | await p.wait() 47 | 48 | 49 | class IndexHandler(tornado.web.RequestHandler): 50 | async def get(self): 51 | await run_cgi(self, ['./index.cgi']) 52 | 53 | 54 | class RssHandler(tornado.web.RequestHandler): 55 | async def get(self): 56 | self.set_header('Content-type', 'text/xml') 57 | await run_cgi(self, ['./rss.cgi']) 58 | 59 | 60 | class LogsHandler(tornado.web.RequestHandler): 61 | async def get(self, logid): 62 | await run_cgi(self, ['./log.cgi'], env={ 63 | 'REQUEST_METHOD': 'GET', 64 | 'QUERY_STRING': 'log=%s' % logid, 65 | }) 66 | 67 | 68 | def unlink(name): 69 | try: 70 | os.unlink(name) 71 | except FileNotFoundError: 72 | pass 73 | 74 | 75 | class RebuildHandler(tornado.web.RequestHandler): 76 | def get(self, logid): 77 | self.render('rebuild.tmpl.html', logid=logid) 78 | 79 | def post(self, logid): 80 | assert re.match(r'^[0-9a-f]+$', logid) 81 | unlink(os.path.join('../out/pass', logid)) 82 | unlink(os.path.join('../out/fail', logid)) 83 | unlink(os.path.join('../out/errcache', logid)) 84 | self.redirect('/') 85 | 86 | def main(): 87 | debug = True if os.getenv('DEBUG') else False 88 | 89 | settings = { 90 | 'autoreload': True, 91 | 'compress_response': True, 92 | 'debug': debug, 93 | 'template_whitespace': 'all' 94 | } 95 | 96 | STATICDIR = os.path.join(os.path.dirname(__file__), 'static') 97 | 98 | app = tornado.web.Application([ 99 | (r'/', IndexHandler), 100 | (r'/rss', RssHandler), 101 | (r'/log/([0-9a-f]+)$', LogsHandler), 102 | (r'/rebuild/([0-9a-f]+)$', RebuildHandler), 103 | (r'/(.*)', tornado.web.StaticFileHandler, dict(path=STATICDIR)), 104 | ], **settings) 105 | 106 | http_server = tornado.httpserver.HTTPServer(app, xheaders=True) 107 | addr = '0.0.0.0' if debug else '127.0.0.1' 108 | PORT = 8014 109 | print('Listening on %s:%d' % (addr, PORT)) 110 | http_server.listen(PORT, address=addr) 111 | tornado.ioloop.IOLoop.current().start() 112 | 113 | if __name__ == '__main__': 114 | main() 115 | -------------------------------------------------------------------------------- /viewer/static/bootstrap-responsive.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap Responsive v2.0.1 3 | * 4 | * Copyright 2012 Twitter, Inc 5 | * Licensed under the Apache License v2.0 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * 8 | * Designed and built with all the love in the world @twitter by @mdo and @fat. 9 | */ 10 | .clearfix { 11 | *zoom: 1; 12 | } 13 | .clearfix:before, .clearfix:after { 14 | display: table; 15 | content: ""; 16 | } 17 | .clearfix:after { 18 | clear: both; 19 | } 20 | .hidden { 21 | display: none; 22 | visibility: hidden; 23 | } 24 | @media (max-width: 480px) { 25 | .nav-collapse { 26 | -webkit-transform: translate3d(0, 0, 0); 27 | } 28 | .page-header h1 small { 29 | display: block; 30 | line-height: 18px; 31 | } 32 | input[class*="span"], 33 | select[class*="span"], 34 | textarea[class*="span"], 35 | .uneditable-input { 36 | display: block; 37 | width: 100%; 38 | min-height: 28px; 39 | /* Make inputs at least the height of their button counterpart */ 40 | 41 | /* Makes inputs behave like true block-level elements */ 42 | 43 | -webkit-box-sizing: border-box; 44 | /* Older Webkit */ 45 | 46 | -moz-box-sizing: border-box; 47 | /* Older FF */ 48 | 49 | -ms-box-sizing: border-box; 50 | /* IE8 */ 51 | 52 | box-sizing: border-box; 53 | /* CSS3 spec*/ 54 | 55 | } 56 | .input-prepend input[class*="span"], .input-append input[class*="span"] { 57 | width: auto; 58 | } 59 | input[type="checkbox"], input[type="radio"] { 60 | border: 1px solid #ccc; 61 | } 62 | .form-horizontal .control-group > label { 63 | float: none; 64 | width: auto; 65 | padding-top: 0; 66 | text-align: left; 67 | } 68 | .form-horizontal .controls { 69 | margin-left: 0; 70 | } 71 | .form-horizontal .control-list { 72 | padding-top: 0; 73 | } 74 | .form-horizontal .form-actions { 75 | padding-left: 10px; 76 | padding-right: 10px; 77 | } 78 | .modal { 79 | position: absolute; 80 | top: 10px; 81 | left: 10px; 82 | right: 10px; 83 | width: auto; 84 | margin: 0; 85 | } 86 | .modal.fade.in { 87 | top: auto; 88 | } 89 | .modal-header .close { 90 | padding: 10px; 91 | margin: -10px; 92 | } 93 | .carousel-caption { 94 | position: static; 95 | } 96 | } 97 | @media (max-width: 767px) { 98 | .container { 99 | width: auto; 100 | padding: 0 20px; 101 | } 102 | .row-fluid { 103 | width: 100%; 104 | } 105 | .row { 106 | margin-left: 0; 107 | } 108 | .row > [class*="span"], .row-fluid > [class*="span"] { 109 | float: none; 110 | display: block; 111 | width: auto; 112 | margin: 0; 113 | } 114 | } 115 | @media (min-width: 768px) and (max-width: 979px) { 116 | .row { 117 | margin-left: -20px; 118 | *zoom: 1; 119 | } 120 | .row:before, .row:after { 121 | display: table; 122 | content: ""; 123 | } 124 | .row:after { 125 | clear: both; 126 | } 127 | [class*="span"] { 128 | float: left; 129 | margin-left: 20px; 130 | } 131 | .span1 { 132 | width: 42px; 133 | } 134 | .span2 { 135 | width: 104px; 136 | } 137 | .span3 { 138 | width: 166px; 139 | } 140 | .span4 { 141 | width: 228px; 142 | } 143 | .span5 { 144 | width: 290px; 145 | } 146 | .span6 { 147 | width: 352px; 148 | } 149 | .span7 { 150 | width: 414px; 151 | } 152 | .span8 { 153 | width: 476px; 154 | } 155 | .span9 { 156 | width: 538px; 157 | } 158 | .span10 { 159 | width: 600px; 160 | } 161 | .span11 { 162 | width: 662px; 163 | } 164 | .span12, .container { 165 | width: 724px; 166 | } 167 | .offset1 { 168 | margin-left: 82px; 169 | } 170 | .offset2 { 171 | margin-left: 144px; 172 | } 173 | .offset3 { 174 | margin-left: 206px; 175 | } 176 | .offset4 { 177 | margin-left: 268px; 178 | } 179 | .offset5 { 180 | margin-left: 330px; 181 | } 182 | .offset6 { 183 | margin-left: 392px; 184 | } 185 | .offset7 { 186 | margin-left: 454px; 187 | } 188 | .offset8 { 189 | margin-left: 516px; 190 | } 191 | .offset9 { 192 | margin-left: 578px; 193 | } 194 | .offset10 { 195 | margin-left: 640px; 196 | } 197 | .offset11 { 198 | margin-left: 702px; 199 | } 200 | .row-fluid { 201 | width: 100%; 202 | *zoom: 1; 203 | } 204 | .row-fluid:before, .row-fluid:after { 205 | display: table; 206 | content: ""; 207 | } 208 | .row-fluid:after { 209 | clear: both; 210 | } 211 | .row-fluid > [class*="span"] { 212 | float: left; 213 | margin-left: 2.762430939%; 214 | } 215 | .row-fluid > [class*="span"]:first-child { 216 | margin-left: 0; 217 | } 218 | .row-fluid > .span1 { 219 | width: 5.801104972%; 220 | } 221 | .row-fluid > .span2 { 222 | width: 14.364640883%; 223 | } 224 | .row-fluid > .span3 { 225 | width: 22.928176794%; 226 | } 227 | .row-fluid > .span4 { 228 | width: 31.491712705%; 229 | } 230 | .row-fluid > .span5 { 231 | width: 40.055248616%; 232 | } 233 | .row-fluid > .span6 { 234 | width: 48.618784527%; 235 | } 236 | .row-fluid > .span7 { 237 | width: 57.182320438000005%; 238 | } 239 | .row-fluid > .span8 { 240 | width: 65.74585634900001%; 241 | } 242 | .row-fluid > .span9 { 243 | width: 74.30939226%; 244 | } 245 | .row-fluid > .span10 { 246 | width: 82.87292817100001%; 247 | } 248 | .row-fluid > .span11 { 249 | width: 91.436464082%; 250 | } 251 | .row-fluid > .span12 { 252 | width: 99.999999993%; 253 | } 254 | input.span1, textarea.span1, .uneditable-input.span1 { 255 | width: 32px; 256 | } 257 | input.span2, textarea.span2, .uneditable-input.span2 { 258 | width: 94px; 259 | } 260 | input.span3, textarea.span3, .uneditable-input.span3 { 261 | width: 156px; 262 | } 263 | input.span4, textarea.span4, .uneditable-input.span4 { 264 | width: 218px; 265 | } 266 | input.span5, textarea.span5, .uneditable-input.span5 { 267 | width: 280px; 268 | } 269 | input.span6, textarea.span6, .uneditable-input.span6 { 270 | width: 342px; 271 | } 272 | input.span7, textarea.span7, .uneditable-input.span7 { 273 | width: 404px; 274 | } 275 | input.span8, textarea.span8, .uneditable-input.span8 { 276 | width: 466px; 277 | } 278 | input.span9, textarea.span9, .uneditable-input.span9 { 279 | width: 528px; 280 | } 281 | input.span10, textarea.span10, .uneditable-input.span10 { 282 | width: 590px; 283 | } 284 | input.span11, textarea.span11, .uneditable-input.span11 { 285 | width: 652px; 286 | } 287 | input.span12, textarea.span12, .uneditable-input.span12 { 288 | width: 714px; 289 | } 290 | } 291 | @media (max-width: 979px) { 292 | body { 293 | padding-top: 0; 294 | } 295 | .navbar-fixed-top { 296 | position: static; 297 | margin-bottom: 18px; 298 | } 299 | .navbar-fixed-top .navbar-inner { 300 | padding: 5px; 301 | } 302 | .navbar .container { 303 | width: auto; 304 | padding: 0; 305 | } 306 | .navbar .brand { 307 | padding-left: 10px; 308 | padding-right: 10px; 309 | margin: 0 0 0 -5px; 310 | } 311 | .navbar .nav-collapse { 312 | clear: left; 313 | } 314 | .navbar .nav { 315 | float: none; 316 | margin: 0 0 9px; 317 | } 318 | .navbar .nav > li { 319 | float: none; 320 | } 321 | .navbar .nav > li > a { 322 | margin-bottom: 2px; 323 | } 324 | .navbar .nav > .divider-vertical { 325 | display: none; 326 | } 327 | .navbar .nav .nav-header { 328 | color: #999999; 329 | text-shadow: none; 330 | } 331 | .navbar .nav > li > a, .navbar .dropdown-menu a { 332 | padding: 6px 15px; 333 | font-weight: bold; 334 | color: #999999; 335 | -webkit-border-radius: 3px; 336 | -moz-border-radius: 3px; 337 | border-radius: 3px; 338 | } 339 | .navbar .dropdown-menu li + li a { 340 | margin-bottom: 2px; 341 | } 342 | .navbar .nav > li > a:hover, .navbar .dropdown-menu a:hover { 343 | background-color: #222222; 344 | } 345 | .navbar .dropdown-menu { 346 | position: static; 347 | top: auto; 348 | left: auto; 349 | float: none; 350 | display: block; 351 | max-width: none; 352 | margin: 0 15px; 353 | padding: 0; 354 | background-color: transparent; 355 | border: none; 356 | -webkit-border-radius: 0; 357 | -moz-border-radius: 0; 358 | border-radius: 0; 359 | -webkit-box-shadow: none; 360 | -moz-box-shadow: none; 361 | box-shadow: none; 362 | } 363 | .navbar .dropdown-menu:before, .navbar .dropdown-menu:after { 364 | display: none; 365 | } 366 | .navbar .dropdown-menu .divider { 367 | display: none; 368 | } 369 | .navbar-form, .navbar-search { 370 | float: none; 371 | padding: 9px 15px; 372 | margin: 9px 0; 373 | border-top: 1px solid #222222; 374 | border-bottom: 1px solid #222222; 375 | -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1); 376 | -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1); 377 | box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1); 378 | } 379 | .navbar .nav.pull-right { 380 | float: none; 381 | margin-left: 0; 382 | } 383 | .navbar-static .navbar-inner { 384 | padding-left: 10px; 385 | padding-right: 10px; 386 | } 387 | .btn-navbar { 388 | display: block; 389 | } 390 | .nav-collapse { 391 | overflow: hidden; 392 | height: 0; 393 | } 394 | } 395 | @media (min-width: 980px) { 396 | .nav-collapse.collapse { 397 | height: auto !important; 398 | } 399 | } 400 | @media (min-width: 1200px) { 401 | .row { 402 | margin-left: -30px; 403 | *zoom: 1; 404 | } 405 | .row:before, .row:after { 406 | display: table; 407 | content: ""; 408 | } 409 | .row:after { 410 | clear: both; 411 | } 412 | [class*="span"] { 413 | float: left; 414 | margin-left: 30px; 415 | } 416 | .span1 { 417 | width: 70px; 418 | } 419 | .span2 { 420 | width: 170px; 421 | } 422 | .span3 { 423 | width: 270px; 424 | } 425 | .span4 { 426 | width: 370px; 427 | } 428 | .span5 { 429 | width: 470px; 430 | } 431 | .span6 { 432 | width: 570px; 433 | } 434 | .span7 { 435 | width: 670px; 436 | } 437 | .span8 { 438 | width: 770px; 439 | } 440 | .span9 { 441 | width: 870px; 442 | } 443 | .span10 { 444 | width: 970px; 445 | } 446 | .span11 { 447 | width: 1070px; 448 | } 449 | .span12, .container { 450 | width: 1170px; 451 | } 452 | .offset1 { 453 | margin-left: 130px; 454 | } 455 | .offset2 { 456 | margin-left: 230px; 457 | } 458 | .offset3 { 459 | margin-left: 330px; 460 | } 461 | .offset4 { 462 | margin-left: 430px; 463 | } 464 | .offset5 { 465 | margin-left: 530px; 466 | } 467 | .offset6 { 468 | margin-left: 630px; 469 | } 470 | .offset7 { 471 | margin-left: 730px; 472 | } 473 | .offset8 { 474 | margin-left: 830px; 475 | } 476 | .offset9 { 477 | margin-left: 930px; 478 | } 479 | .offset10 { 480 | margin-left: 1030px; 481 | } 482 | .offset11 { 483 | margin-left: 1130px; 484 | } 485 | .row-fluid { 486 | width: 100%; 487 | *zoom: 1; 488 | } 489 | .row-fluid:before, .row-fluid:after { 490 | display: table; 491 | content: ""; 492 | } 493 | .row-fluid:after { 494 | clear: both; 495 | } 496 | .row-fluid > [class*="span"] { 497 | float: left; 498 | margin-left: 2.564102564%; 499 | } 500 | .row-fluid > [class*="span"]:first-child { 501 | margin-left: 0; 502 | } 503 | .row-fluid > .span1 { 504 | width: 5.982905983%; 505 | } 506 | .row-fluid > .span2 { 507 | width: 14.529914530000001%; 508 | } 509 | .row-fluid > .span3 { 510 | width: 23.076923077%; 511 | } 512 | .row-fluid > .span4 { 513 | width: 31.623931624%; 514 | } 515 | .row-fluid > .span5 { 516 | width: 40.170940171000005%; 517 | } 518 | .row-fluid > .span6 { 519 | width: 48.717948718%; 520 | } 521 | .row-fluid > .span7 { 522 | width: 57.264957265%; 523 | } 524 | .row-fluid > .span8 { 525 | width: 65.81196581200001%; 526 | } 527 | .row-fluid > .span9 { 528 | width: 74.358974359%; 529 | } 530 | .row-fluid > .span10 { 531 | width: 82.905982906%; 532 | } 533 | .row-fluid > .span11 { 534 | width: 91.45299145300001%; 535 | } 536 | .row-fluid > .span12 { 537 | width: 100%; 538 | } 539 | input.span1, textarea.span1, .uneditable-input.span1 { 540 | width: 60px; 541 | } 542 | input.span2, textarea.span2, .uneditable-input.span2 { 543 | width: 160px; 544 | } 545 | input.span3, textarea.span3, .uneditable-input.span3 { 546 | width: 260px; 547 | } 548 | input.span4, textarea.span4, .uneditable-input.span4 { 549 | width: 360px; 550 | } 551 | input.span5, textarea.span5, .uneditable-input.span5 { 552 | width: 460px; 553 | } 554 | input.span6, textarea.span6, .uneditable-input.span6 { 555 | width: 560px; 556 | } 557 | input.span7, textarea.span7, .uneditable-input.span7 { 558 | width: 660px; 559 | } 560 | input.span8, textarea.span8, .uneditable-input.span8 { 561 | width: 760px; 562 | } 563 | input.span9, textarea.span9, .uneditable-input.span9 { 564 | width: 860px; 565 | } 566 | input.span10, textarea.span10, .uneditable-input.span10 { 567 | width: 960px; 568 | } 569 | input.span11, textarea.span11, .uneditable-input.span11 { 570 | width: 1060px; 571 | } 572 | input.span12, textarea.span12, .uneditable-input.span12 { 573 | width: 1160px; 574 | } 575 | .thumbnails { 576 | margin-left: -30px; 577 | } 578 | .thumbnails > li { 579 | margin-left: 30px; 580 | } 581 | } 582 | -------------------------------------------------------------------------------- /viewer/static/bootstrap.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap v2.0.1 3 | * 4 | * Copyright 2012 Twitter, Inc 5 | * Licensed under the Apache License v2.0 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * 8 | * Designed and built with all the love in the world @twitter by @mdo and @fat. 9 | */ 10 | article, 11 | aside, 12 | details, 13 | figcaption, 14 | figure, 15 | footer, 16 | header, 17 | hgroup, 18 | nav, 19 | section { 20 | display: block; 21 | } 22 | audio, canvas, video { 23 | display: inline-block; 24 | *display: inline; 25 | *zoom: 1; 26 | } 27 | audio:not([controls]) { 28 | display: none; 29 | } 30 | html { 31 | font-size: 100%; 32 | -webkit-text-size-adjust: 100%; 33 | -ms-text-size-adjust: 100%; 34 | } 35 | a:focus { 36 | outline: thin dotted #333; 37 | outline: 5px auto -webkit-focus-ring-color; 38 | outline-offset: -2px; 39 | } 40 | a:hover, a:active { 41 | outline: 0; 42 | } 43 | sub, sup { 44 | position: relative; 45 | font-size: 75%; 46 | line-height: 0; 47 | vertical-align: baseline; 48 | } 49 | sup { 50 | top: -0.5em; 51 | } 52 | sub { 53 | bottom: -0.25em; 54 | } 55 | img { 56 | max-width: 100%; 57 | height: auto; 58 | border: 0; 59 | -ms-interpolation-mode: bicubic; 60 | } 61 | button, 62 | input, 63 | select, 64 | textarea { 65 | margin: 0; 66 | font-size: 100%; 67 | vertical-align: middle; 68 | } 69 | button, input { 70 | *overflow: visible; 71 | line-height: normal; 72 | } 73 | button::-moz-focus-inner, input::-moz-focus-inner { 74 | padding: 0; 75 | border: 0; 76 | } 77 | button, 78 | input[type="button"], 79 | input[type="reset"], 80 | input[type="submit"] { 81 | cursor: pointer; 82 | -webkit-appearance: button; 83 | } 84 | input[type="search"] { 85 | -webkit-appearance: textfield; 86 | -webkit-box-sizing: content-box; 87 | -moz-box-sizing: content-box; 88 | box-sizing: content-box; 89 | } 90 | input[type="search"]::-webkit-search-decoration, input[type="search"]::-webkit-search-cancel-button { 91 | -webkit-appearance: none; 92 | } 93 | textarea { 94 | overflow: auto; 95 | vertical-align: top; 96 | } 97 | .clearfix { 98 | *zoom: 1; 99 | } 100 | .clearfix:before, .clearfix:after { 101 | display: table; 102 | content: ""; 103 | } 104 | .clearfix:after { 105 | clear: both; 106 | } 107 | body { 108 | margin: 0; 109 | font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; 110 | font-size: 13px; 111 | line-height: 18px; 112 | color: #333333; 113 | background-color: #ffffff; 114 | } 115 | a { 116 | color: #0088cc; 117 | text-decoration: none; 118 | } 119 | a:hover { 120 | color: #005580; 121 | text-decoration: underline; 122 | } 123 | .row { 124 | margin-left: -20px; 125 | *zoom: 1; 126 | } 127 | .row:before, .row:after { 128 | display: table; 129 | content: ""; 130 | } 131 | .row:after { 132 | clear: both; 133 | } 134 | [class*="span"] { 135 | float: left; 136 | margin-left: 20px; 137 | } 138 | .span1 { 139 | width: 60px; 140 | } 141 | .span2 { 142 | width: 140px; 143 | } 144 | .span3 { 145 | width: 220px; 146 | } 147 | .span4 { 148 | width: 300px; 149 | } 150 | .span5 { 151 | width: 380px; 152 | } 153 | .span6 { 154 | width: 460px; 155 | } 156 | .span7 { 157 | width: 540px; 158 | } 159 | .span8 { 160 | width: 620px; 161 | } 162 | .span9 { 163 | width: 700px; 164 | } 165 | .span10 { 166 | width: 780px; 167 | } 168 | .span11 { 169 | width: 860px; 170 | } 171 | .span12, .container { 172 | width: 940px; 173 | } 174 | .offset1 { 175 | margin-left: 100px; 176 | } 177 | .offset2 { 178 | margin-left: 180px; 179 | } 180 | .offset3 { 181 | margin-left: 260px; 182 | } 183 | .offset4 { 184 | margin-left: 340px; 185 | } 186 | .offset5 { 187 | margin-left: 420px; 188 | } 189 | .offset6 { 190 | margin-left: 500px; 191 | } 192 | .offset7 { 193 | margin-left: 580px; 194 | } 195 | .offset8 { 196 | margin-left: 660px; 197 | } 198 | .offset9 { 199 | margin-left: 740px; 200 | } 201 | .offset10 { 202 | margin-left: 820px; 203 | } 204 | .offset11 { 205 | margin-left: 900px; 206 | } 207 | .row-fluid { 208 | width: 100%; 209 | *zoom: 1; 210 | } 211 | .row-fluid:before, .row-fluid:after { 212 | display: table; 213 | content: ""; 214 | } 215 | .row-fluid:after { 216 | clear: both; 217 | } 218 | .row-fluid > [class*="span"] { 219 | float: left; 220 | margin-left: 2.127659574%; 221 | } 222 | .row-fluid > [class*="span"]:first-child { 223 | margin-left: 0; 224 | } 225 | .row-fluid > .span1 { 226 | width: 6.382978723%; 227 | } 228 | .row-fluid > .span2 { 229 | width: 14.89361702%; 230 | } 231 | .row-fluid > .span3 { 232 | width: 23.404255317%; 233 | } 234 | .row-fluid > .span4 { 235 | width: 31.914893614%; 236 | } 237 | .row-fluid > .span5 { 238 | width: 40.425531911%; 239 | } 240 | .row-fluid > .span6 { 241 | width: 48.93617020799999%; 242 | } 243 | .row-fluid > .span7 { 244 | width: 57.446808505%; 245 | } 246 | .row-fluid > .span8 { 247 | width: 65.95744680199999%; 248 | } 249 | .row-fluid > .span9 { 250 | width: 74.468085099%; 251 | } 252 | .row-fluid > .span10 { 253 | width: 82.97872339599999%; 254 | } 255 | .row-fluid > .span11 { 256 | width: 91.489361693%; 257 | } 258 | .row-fluid > .span12 { 259 | width: 99.99999998999999%; 260 | } 261 | .container { 262 | width: 940px; 263 | margin-left: auto; 264 | margin-right: auto; 265 | *zoom: 1; 266 | } 267 | .container:before, .container:after { 268 | display: table; 269 | content: ""; 270 | } 271 | .container:after { 272 | clear: both; 273 | } 274 | .container-fluid { 275 | padding-left: 20px; 276 | padding-right: 20px; 277 | *zoom: 1; 278 | } 279 | .container-fluid:before, .container-fluid:after { 280 | display: table; 281 | content: ""; 282 | } 283 | .container-fluid:after { 284 | clear: both; 285 | } 286 | p { 287 | margin: 0 0 9px; 288 | font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; 289 | font-size: 13px; 290 | line-height: 18px; 291 | } 292 | p small { 293 | font-size: 11px; 294 | color: #999999; 295 | } 296 | .lead { 297 | margin-bottom: 18px; 298 | font-size: 20px; 299 | font-weight: 200; 300 | line-height: 27px; 301 | } 302 | h1, 303 | h2, 304 | h3, 305 | h4, 306 | h5, 307 | h6 { 308 | margin: 0; 309 | font-weight: bold; 310 | color: #333333; 311 | text-rendering: optimizelegibility; 312 | } 313 | h1 small, 314 | h2 small, 315 | h3 small, 316 | h4 small, 317 | h5 small, 318 | h6 small { 319 | font-weight: normal; 320 | color: #999999; 321 | } 322 | h1 { 323 | font-size: 30px; 324 | line-height: 36px; 325 | } 326 | h1 small { 327 | font-size: 18px; 328 | } 329 | h2 { 330 | font-size: 24px; 331 | line-height: 36px; 332 | } 333 | h2 small { 334 | font-size: 18px; 335 | } 336 | h3 { 337 | line-height: 27px; 338 | font-size: 18px; 339 | } 340 | h3 small { 341 | font-size: 14px; 342 | } 343 | h4, h5, h6 { 344 | line-height: 18px; 345 | } 346 | h4 { 347 | font-size: 14px; 348 | } 349 | h4 small { 350 | font-size: 12px; 351 | } 352 | h5 { 353 | font-size: 12px; 354 | } 355 | h6 { 356 | font-size: 11px; 357 | color: #999999; 358 | text-transform: uppercase; 359 | } 360 | .page-header { 361 | padding-bottom: 17px; 362 | margin: 18px 0; 363 | border-bottom: 1px solid #eeeeee; 364 | } 365 | .page-header h1 { 366 | line-height: 1; 367 | } 368 | ul, ol { 369 | padding: 0; 370 | margin: 0 0 9px 25px; 371 | } 372 | ul ul, 373 | ul ol, 374 | ol ol, 375 | ol ul { 376 | margin-bottom: 0; 377 | } 378 | ul { 379 | list-style: disc; 380 | } 381 | ol { 382 | list-style: decimal; 383 | } 384 | li { 385 | line-height: 18px; 386 | } 387 | ul.unstyled, ol.unstyled { 388 | margin-left: 0; 389 | list-style: none; 390 | } 391 | dl { 392 | margin-bottom: 18px; 393 | } 394 | dt, dd { 395 | line-height: 18px; 396 | } 397 | dt { 398 | font-weight: bold; 399 | } 400 | dd { 401 | margin-left: 9px; 402 | } 403 | hr { 404 | margin: 18px 0; 405 | border: 0; 406 | border-top: 1px solid #eeeeee; 407 | border-bottom: 1px solid #ffffff; 408 | } 409 | strong { 410 | font-weight: bold; 411 | } 412 | em { 413 | font-style: italic; 414 | } 415 | .muted { 416 | color: #999999; 417 | } 418 | abbr { 419 | font-size: 90%; 420 | text-transform: uppercase; 421 | border-bottom: 1px dotted #ddd; 422 | cursor: help; 423 | } 424 | blockquote { 425 | padding: 0 0 0 15px; 426 | margin: 0 0 18px; 427 | border-left: 5px solid #eeeeee; 428 | } 429 | blockquote p { 430 | margin-bottom: 0; 431 | font-size: 16px; 432 | font-weight: 300; 433 | line-height: 22.5px; 434 | } 435 | blockquote small { 436 | display: block; 437 | line-height: 18px; 438 | color: #999999; 439 | } 440 | blockquote small:before { 441 | content: '\2014 \00A0'; 442 | } 443 | blockquote.pull-right { 444 | float: right; 445 | padding-left: 0; 446 | padding-right: 15px; 447 | border-left: 0; 448 | border-right: 5px solid #eeeeee; 449 | } 450 | blockquote.pull-right p, blockquote.pull-right small { 451 | text-align: right; 452 | } 453 | q:before, 454 | q:after, 455 | blockquote:before, 456 | blockquote:after { 457 | content: ""; 458 | } 459 | address { 460 | display: block; 461 | margin-bottom: 18px; 462 | line-height: 18px; 463 | font-style: normal; 464 | } 465 | small { 466 | font-size: 100%; 467 | } 468 | cite { 469 | font-style: normal; 470 | } 471 | code, pre { 472 | padding: 0 3px 2px; 473 | font-family: Menlo, Monaco, "Courier New", monospace; 474 | font-size: 12px; 475 | color: #333333; 476 | -webkit-border-radius: 3px; 477 | -moz-border-radius: 3px; 478 | border-radius: 3px; 479 | } 480 | code { 481 | padding: 3px 4px; 482 | color: #d14; 483 | background-color: #f7f7f9; 484 | border: 1px solid #e1e1e8; 485 | } 486 | pre { 487 | display: block; 488 | padding: 8.5px; 489 | margin: 0 0 9px; 490 | font-size: 12px; 491 | line-height: 18px; 492 | background-color: #f5f5f5; 493 | border: 1px solid #ccc; 494 | border: 1px solid rgba(0, 0, 0, 0.15); 495 | -webkit-border-radius: 4px; 496 | -moz-border-radius: 4px; 497 | border-radius: 4px; 498 | white-space: pre; 499 | white-space: pre-wrap; 500 | word-break: break-all; 501 | word-wrap: break-word; 502 | } 503 | pre.prettyprint { 504 | margin-bottom: 18px; 505 | } 506 | pre code { 507 | padding: 0; 508 | color: inherit; 509 | background-color: transparent; 510 | border: 0; 511 | } 512 | .pre-scrollable { 513 | max-height: 340px; 514 | overflow-y: scroll; 515 | } 516 | form { 517 | margin: 0 0 18px; 518 | } 519 | fieldset { 520 | padding: 0; 521 | margin: 0; 522 | border: 0; 523 | } 524 | legend { 525 | display: block; 526 | width: 100%; 527 | padding: 0; 528 | margin-bottom: 27px; 529 | font-size: 19.5px; 530 | line-height: 36px; 531 | color: #333333; 532 | border: 0; 533 | border-bottom: 1px solid #eee; 534 | } 535 | legend small { 536 | font-size: 13.5px; 537 | color: #999999; 538 | } 539 | label, 540 | input, 541 | button, 542 | select, 543 | textarea { 544 | font-size: 13px; 545 | font-weight: normal; 546 | line-height: 18px; 547 | } 548 | input, 549 | button, 550 | select, 551 | textarea { 552 | font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; 553 | } 554 | label { 555 | display: block; 556 | margin-bottom: 5px; 557 | color: #333333; 558 | } 559 | input, 560 | textarea, 561 | select, 562 | .uneditable-input { 563 | display: inline-block; 564 | width: 210px; 565 | height: 18px; 566 | padding: 4px; 567 | margin-bottom: 9px; 568 | font-size: 13px; 569 | line-height: 18px; 570 | color: #555555; 571 | border: 1px solid #ccc; 572 | -webkit-border-radius: 3px; 573 | -moz-border-radius: 3px; 574 | border-radius: 3px; 575 | } 576 | .uneditable-textarea { 577 | width: auto; 578 | height: auto; 579 | } 580 | label input, label textarea, label select { 581 | display: block; 582 | } 583 | input[type="image"], input[type="checkbox"], input[type="radio"] { 584 | width: auto; 585 | height: auto; 586 | padding: 0; 587 | margin: 3px 0; 588 | *margin-top: 0; 589 | /* IE7 */ 590 | 591 | line-height: normal; 592 | cursor: pointer; 593 | -webkit-border-radius: 0; 594 | -moz-border-radius: 0; 595 | border-radius: 0; 596 | border: 0 \9; 597 | /* IE9 and down */ 598 | 599 | } 600 | input[type="image"] { 601 | border: 0; 602 | } 603 | input[type="file"] { 604 | width: auto; 605 | padding: initial; 606 | line-height: initial; 607 | border: initial; 608 | background-color: #ffffff; 609 | background-color: initial; 610 | -webkit-box-shadow: none; 611 | -moz-box-shadow: none; 612 | box-shadow: none; 613 | } 614 | input[type="button"], input[type="reset"], input[type="submit"] { 615 | width: auto; 616 | height: auto; 617 | } 618 | select, input[type="file"] { 619 | height: 28px; 620 | /* In IE7, the height of the select element cannot be changed by height, only font-size */ 621 | 622 | *margin-top: 4px; 623 | /* For IE7, add top margin to align select with labels */ 624 | 625 | line-height: 28px; 626 | } 627 | input[type="file"] { 628 | line-height: 18px \9; 629 | } 630 | select { 631 | width: 220px; 632 | background-color: #ffffff; 633 | } 634 | select[multiple], select[size] { 635 | height: auto; 636 | } 637 | input[type="image"] { 638 | -webkit-box-shadow: none; 639 | -moz-box-shadow: none; 640 | box-shadow: none; 641 | } 642 | textarea { 643 | height: auto; 644 | } 645 | input[type="hidden"] { 646 | display: none; 647 | } 648 | .radio, .checkbox { 649 | padding-left: 18px; 650 | } 651 | .radio input[type="radio"], .checkbox input[type="checkbox"] { 652 | float: left; 653 | margin-left: -18px; 654 | } 655 | .controls > .radio:first-child, .controls > .checkbox:first-child { 656 | padding-top: 5px; 657 | } 658 | .radio.inline, .checkbox.inline { 659 | display: inline-block; 660 | padding-top: 5px; 661 | margin-bottom: 0; 662 | vertical-align: middle; 663 | } 664 | .radio.inline + .radio.inline, .checkbox.inline + .checkbox.inline { 665 | margin-left: 10px; 666 | } 667 | input, textarea { 668 | -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); 669 | -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); 670 | box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); 671 | -webkit-transition: border linear 0.2s, box-shadow linear 0.2s; 672 | -moz-transition: border linear 0.2s, box-shadow linear 0.2s; 673 | -ms-transition: border linear 0.2s, box-shadow linear 0.2s; 674 | -o-transition: border linear 0.2s, box-shadow linear 0.2s; 675 | transition: border linear 0.2s, box-shadow linear 0.2s; 676 | } 677 | input:focus, textarea:focus { 678 | border-color: rgba(82, 168, 236, 0.8); 679 | -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6); 680 | -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6); 681 | box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6); 682 | outline: 0; 683 | outline: thin dotted \9; 684 | /* IE6-9 */ 685 | 686 | } 687 | input[type="file"]:focus, 688 | input[type="radio"]:focus, 689 | input[type="checkbox"]:focus, 690 | select:focus { 691 | -webkit-box-shadow: none; 692 | -moz-box-shadow: none; 693 | box-shadow: none; 694 | outline: thin dotted #333; 695 | outline: 5px auto -webkit-focus-ring-color; 696 | outline-offset: -2px; 697 | } 698 | .input-mini { 699 | width: 60px; 700 | } 701 | .input-small { 702 | width: 90px; 703 | } 704 | .input-medium { 705 | width: 150px; 706 | } 707 | .input-large { 708 | width: 210px; 709 | } 710 | .input-xlarge { 711 | width: 270px; 712 | } 713 | .input-xxlarge { 714 | width: 530px; 715 | } 716 | input[class*="span"], 717 | select[class*="span"], 718 | textarea[class*="span"], 719 | .uneditable-input { 720 | float: none; 721 | margin-left: 0; 722 | } 723 | input.span1, textarea.span1, .uneditable-input.span1 { 724 | width: 50px; 725 | } 726 | input.span2, textarea.span2, .uneditable-input.span2 { 727 | width: 130px; 728 | } 729 | input.span3, textarea.span3, .uneditable-input.span3 { 730 | width: 210px; 731 | } 732 | input.span4, textarea.span4, .uneditable-input.span4 { 733 | width: 290px; 734 | } 735 | input.span5, textarea.span5, .uneditable-input.span5 { 736 | width: 370px; 737 | } 738 | input.span6, textarea.span6, .uneditable-input.span6 { 739 | width: 450px; 740 | } 741 | input.span7, textarea.span7, .uneditable-input.span7 { 742 | width: 530px; 743 | } 744 | input.span8, textarea.span8, .uneditable-input.span8 { 745 | width: 610px; 746 | } 747 | input.span9, textarea.span9, .uneditable-input.span9 { 748 | width: 690px; 749 | } 750 | input.span10, textarea.span10, .uneditable-input.span10 { 751 | width: 770px; 752 | } 753 | input.span11, textarea.span11, .uneditable-input.span11 { 754 | width: 850px; 755 | } 756 | input.span12, textarea.span12, .uneditable-input.span12 { 757 | width: 930px; 758 | } 759 | input[disabled], 760 | select[disabled], 761 | textarea[disabled], 762 | input[readonly], 763 | select[readonly], 764 | textarea[readonly] { 765 | background-color: #f5f5f5; 766 | border-color: #ddd; 767 | cursor: not-allowed; 768 | } 769 | .control-group.warning > label, .control-group.warning .help-block, .control-group.warning .help-inline { 770 | color: #c09853; 771 | } 772 | .control-group.warning input, .control-group.warning select, .control-group.warning textarea { 773 | color: #c09853; 774 | border-color: #c09853; 775 | } 776 | .control-group.warning input:focus, .control-group.warning select:focus, .control-group.warning textarea:focus { 777 | border-color: #a47e3c; 778 | -webkit-box-shadow: 0 0 6px #dbc59e; 779 | -moz-box-shadow: 0 0 6px #dbc59e; 780 | box-shadow: 0 0 6px #dbc59e; 781 | } 782 | .control-group.warning .input-prepend .add-on, .control-group.warning .input-append .add-on { 783 | color: #c09853; 784 | background-color: #fcf8e3; 785 | border-color: #c09853; 786 | } 787 | .control-group.error > label, .control-group.error .help-block, .control-group.error .help-inline { 788 | color: #b94a48; 789 | } 790 | .control-group.error input, .control-group.error select, .control-group.error textarea { 791 | color: #b94a48; 792 | border-color: #b94a48; 793 | } 794 | .control-group.error input:focus, .control-group.error select:focus, .control-group.error textarea:focus { 795 | border-color: #953b39; 796 | -webkit-box-shadow: 0 0 6px #d59392; 797 | -moz-box-shadow: 0 0 6px #d59392; 798 | box-shadow: 0 0 6px #d59392; 799 | } 800 | .control-group.error .input-prepend .add-on, .control-group.error .input-append .add-on { 801 | color: #b94a48; 802 | background-color: #f2dede; 803 | border-color: #b94a48; 804 | } 805 | .control-group.success > label, .control-group.success .help-block, .control-group.success .help-inline { 806 | color: #468847; 807 | } 808 | .control-group.success input, .control-group.success select, .control-group.success textarea { 809 | color: #468847; 810 | border-color: #468847; 811 | } 812 | .control-group.success input:focus, .control-group.success select:focus, .control-group.success textarea:focus { 813 | border-color: #356635; 814 | -webkit-box-shadow: 0 0 6px #7aba7b; 815 | -moz-box-shadow: 0 0 6px #7aba7b; 816 | box-shadow: 0 0 6px #7aba7b; 817 | } 818 | .control-group.success .input-prepend .add-on, .control-group.success .input-append .add-on { 819 | color: #468847; 820 | background-color: #dff0d8; 821 | border-color: #468847; 822 | } 823 | input:focus:required:invalid, textarea:focus:required:invalid, select:focus:required:invalid { 824 | color: #b94a48; 825 | border-color: #ee5f5b; 826 | } 827 | input:focus:required:invalid:focus, textarea:focus:required:invalid:focus, select:focus:required:invalid:focus { 828 | border-color: #e9322d; 829 | -webkit-box-shadow: 0 0 6px #f8b9b7; 830 | -moz-box-shadow: 0 0 6px #f8b9b7; 831 | box-shadow: 0 0 6px #f8b9b7; 832 | } 833 | .form-actions { 834 | padding: 17px 20px 18px; 835 | margin-top: 18px; 836 | margin-bottom: 18px; 837 | background-color: #f5f5f5; 838 | border-top: 1px solid #ddd; 839 | } 840 | .uneditable-input { 841 | display: block; 842 | background-color: #ffffff; 843 | border-color: #eee; 844 | -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025); 845 | -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025); 846 | box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025); 847 | cursor: not-allowed; 848 | } 849 | :-moz-placeholder { 850 | color: #999999; 851 | } 852 | ::-webkit-input-placeholder { 853 | color: #999999; 854 | } 855 | .help-block { 856 | display: block; 857 | margin-top: 5px; 858 | margin-bottom: 0; 859 | color: #999999; 860 | } 861 | .help-inline { 862 | display: inline-block; 863 | *display: inline; 864 | /* IE7 inline-block hack */ 865 | 866 | *zoom: 1; 867 | margin-bottom: 9px; 868 | vertical-align: middle; 869 | padding-left: 5px; 870 | } 871 | .input-prepend, .input-append { 872 | margin-bottom: 5px; 873 | *zoom: 1; 874 | } 875 | .input-prepend:before, 876 | .input-append:before, 877 | .input-prepend:after, 878 | .input-append:after { 879 | display: table; 880 | content: ""; 881 | } 882 | .input-prepend:after, .input-append:after { 883 | clear: both; 884 | } 885 | .input-prepend input, 886 | .input-append input, 887 | .input-prepend .uneditable-input, 888 | .input-append .uneditable-input { 889 | -webkit-border-radius: 0 3px 3px 0; 890 | -moz-border-radius: 0 3px 3px 0; 891 | border-radius: 0 3px 3px 0; 892 | } 893 | .input-prepend input:focus, 894 | .input-append input:focus, 895 | .input-prepend .uneditable-input:focus, 896 | .input-append .uneditable-input:focus { 897 | position: relative; 898 | z-index: 2; 899 | } 900 | .input-prepend .uneditable-input, .input-append .uneditable-input { 901 | border-left-color: #ccc; 902 | } 903 | .input-prepend .add-on, .input-append .add-on { 904 | float: left; 905 | display: block; 906 | width: auto; 907 | min-width: 16px; 908 | height: 18px; 909 | margin-right: -1px; 910 | padding: 4px 5px; 911 | font-weight: normal; 912 | line-height: 18px; 913 | color: #999999; 914 | text-align: center; 915 | text-shadow: 0 1px 0 #ffffff; 916 | background-color: #f5f5f5; 917 | border: 1px solid #ccc; 918 | -webkit-border-radius: 3px 0 0 3px; 919 | -moz-border-radius: 3px 0 0 3px; 920 | border-radius: 3px 0 0 3px; 921 | } 922 | .input-prepend .active, .input-append .active { 923 | background-color: #a9dba9; 924 | border-color: #46a546; 925 | } 926 | .input-prepend .add-on { 927 | *margin-top: 1px; 928 | /* IE6-7 */ 929 | 930 | } 931 | .input-append input, .input-append .uneditable-input { 932 | float: left; 933 | -webkit-border-radius: 3px 0 0 3px; 934 | -moz-border-radius: 3px 0 0 3px; 935 | border-radius: 3px 0 0 3px; 936 | } 937 | .input-append .uneditable-input { 938 | border-left-color: #eee; 939 | border-right-color: #ccc; 940 | } 941 | .input-append .add-on { 942 | margin-right: 0; 943 | margin-left: -1px; 944 | -webkit-border-radius: 0 3px 3px 0; 945 | -moz-border-radius: 0 3px 3px 0; 946 | border-radius: 0 3px 3px 0; 947 | } 948 | .input-append input:first-child { 949 | *margin-left: -160px; 950 | } 951 | .input-append input:first-child + .add-on { 952 | *margin-left: -21px; 953 | } 954 | .search-query { 955 | padding-left: 14px; 956 | padding-right: 14px; 957 | margin-bottom: 0; 958 | -webkit-border-radius: 14px; 959 | -moz-border-radius: 14px; 960 | border-radius: 14px; 961 | } 962 | .form-search input, 963 | .form-inline input, 964 | .form-horizontal input, 965 | .form-search textarea, 966 | .form-inline textarea, 967 | .form-horizontal textarea, 968 | .form-search select, 969 | .form-inline select, 970 | .form-horizontal select, 971 | .form-search .help-inline, 972 | .form-inline .help-inline, 973 | .form-horizontal .help-inline, 974 | .form-search .uneditable-input, 975 | .form-inline .uneditable-input, 976 | .form-horizontal .uneditable-input { 977 | display: inline-block; 978 | margin-bottom: 0; 979 | } 980 | .form-search .hide, .form-inline .hide, .form-horizontal .hide { 981 | display: none; 982 | } 983 | .form-search label, 984 | .form-inline label, 985 | .form-search .input-append, 986 | .form-inline .input-append, 987 | .form-search .input-prepend, 988 | .form-inline .input-prepend { 989 | display: inline-block; 990 | } 991 | .form-search .input-append .add-on, 992 | .form-inline .input-prepend .add-on, 993 | .form-search .input-append .add-on, 994 | .form-inline .input-prepend .add-on { 995 | vertical-align: middle; 996 | } 997 | .form-search .radio, 998 | .form-inline .radio, 999 | .form-search .checkbox, 1000 | .form-inline .checkbox { 1001 | margin-bottom: 0; 1002 | vertical-align: middle; 1003 | } 1004 | .control-group { 1005 | margin-bottom: 9px; 1006 | } 1007 | legend + .control-group { 1008 | margin-top: 18px; 1009 | -webkit-margin-top-collapse: separate; 1010 | } 1011 | .form-horizontal .control-group { 1012 | margin-bottom: 18px; 1013 | *zoom: 1; 1014 | } 1015 | .form-horizontal .control-group:before, .form-horizontal .control-group:after { 1016 | display: table; 1017 | content: ""; 1018 | } 1019 | .form-horizontal .control-group:after { 1020 | clear: both; 1021 | } 1022 | .form-horizontal .control-label { 1023 | float: left; 1024 | width: 140px; 1025 | padding-top: 5px; 1026 | text-align: right; 1027 | } 1028 | .form-horizontal .controls { 1029 | margin-left: 160px; 1030 | } 1031 | .form-horizontal .form-actions { 1032 | padding-left: 160px; 1033 | } 1034 | table { 1035 | max-width: 100%; 1036 | border-collapse: collapse; 1037 | border-spacing: 0; 1038 | } 1039 | .table { 1040 | width: 100%; 1041 | margin-bottom: 18px; 1042 | } 1043 | .table th, .table td { 1044 | padding: 8px; 1045 | line-height: 18px; 1046 | text-align: left; 1047 | vertical-align: top; 1048 | border-top: 1px solid #ddd; 1049 | } 1050 | .table th { 1051 | font-weight: bold; 1052 | } 1053 | .table thead th { 1054 | vertical-align: bottom; 1055 | } 1056 | .table thead:first-child tr th, .table thead:first-child tr td { 1057 | border-top: 0; 1058 | } 1059 | .table tbody + tbody { 1060 | border-top: 2px solid #ddd; 1061 | } 1062 | .table-condensed th, .table-condensed td { 1063 | padding: 4px 5px; 1064 | } 1065 | .table-bordered { 1066 | border: 1px solid #ddd; 1067 | border-collapse: separate; 1068 | *border-collapse: collapsed; 1069 | -webkit-border-radius: 4px; 1070 | -moz-border-radius: 4px; 1071 | border-radius: 4px; 1072 | } 1073 | .table-bordered th + th, 1074 | .table-bordered td + td, 1075 | .table-bordered th + td, 1076 | .table-bordered td + th { 1077 | border-left: 1px solid #ddd; 1078 | } 1079 | .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 { 1080 | border-top: 0; 1081 | } 1082 | .table-bordered thead:first-child tr:first-child th:first-child, .table-bordered tbody:first-child tr:first-child td:first-child { 1083 | -webkit-border-radius: 4px 0 0 0; 1084 | -moz-border-radius: 4px 0 0 0; 1085 | border-radius: 4px 0 0 0; 1086 | } 1087 | .table-bordered thead:first-child tr:first-child th:last-child, .table-bordered tbody:first-child tr:first-child td:last-child { 1088 | -webkit-border-radius: 0 4px 0 0; 1089 | -moz-border-radius: 0 4px 0 0; 1090 | border-radius: 0 4px 0 0; 1091 | } 1092 | .table-bordered thead:last-child tr:last-child th:first-child, .table-bordered tbody:last-child tr:last-child td:first-child { 1093 | -webkit-border-radius: 0 0 0 4px; 1094 | -moz-border-radius: 0 0 0 4px; 1095 | border-radius: 0 0 0 4px; 1096 | } 1097 | .table-bordered thead:last-child tr:last-child th:last-child, .table-bordered tbody:last-child tr:last-child td:last-child { 1098 | -webkit-border-radius: 0 0 4px 0; 1099 | -moz-border-radius: 0 0 4px 0; 1100 | border-radius: 0 0 4px 0; 1101 | } 1102 | .table-striped tbody tr:nth-child(odd) td, .table-striped tbody tr:nth-child(odd) th { 1103 | background-color: #f9f9f9; 1104 | } 1105 | .table tbody tr:hover td, .table tbody tr:hover th { 1106 | background-color: #f5f5f5; 1107 | } 1108 | table .span1 { 1109 | float: none; 1110 | width: 44px; 1111 | margin-left: 0; 1112 | } 1113 | table .span2 { 1114 | float: none; 1115 | width: 124px; 1116 | margin-left: 0; 1117 | } 1118 | table .span3 { 1119 | float: none; 1120 | width: 204px; 1121 | margin-left: 0; 1122 | } 1123 | table .span4 { 1124 | float: none; 1125 | width: 284px; 1126 | margin-left: 0; 1127 | } 1128 | table .span5 { 1129 | float: none; 1130 | width: 364px; 1131 | margin-left: 0; 1132 | } 1133 | table .span6 { 1134 | float: none; 1135 | width: 444px; 1136 | margin-left: 0; 1137 | } 1138 | table .span7 { 1139 | float: none; 1140 | width: 524px; 1141 | margin-left: 0; 1142 | } 1143 | table .span8 { 1144 | float: none; 1145 | width: 604px; 1146 | margin-left: 0; 1147 | } 1148 | table .span9 { 1149 | float: none; 1150 | width: 684px; 1151 | margin-left: 0; 1152 | } 1153 | table .span10 { 1154 | float: none; 1155 | width: 764px; 1156 | margin-left: 0; 1157 | } 1158 | table .span11 { 1159 | float: none; 1160 | width: 844px; 1161 | margin-left: 0; 1162 | } 1163 | table .span12 { 1164 | float: none; 1165 | width: 924px; 1166 | margin-left: 0; 1167 | } 1168 | [class^="icon-"], [class*=" icon-"] { 1169 | display: inline-block; 1170 | width: 14px; 1171 | height: 14px; 1172 | line-height: 14px; 1173 | vertical-align: text-top; 1174 | background-image: url("../img/glyphicons-halflings.png"); 1175 | background-position: 14px 14px; 1176 | background-repeat: no-repeat; 1177 | *margin-right: .3em; 1178 | } 1179 | [class^="icon-"]:last-child, [class*=" icon-"]:last-child { 1180 | *margin-left: 0; 1181 | } 1182 | .icon-white { 1183 | background-image: url("../img/glyphicons-halflings-white.png"); 1184 | } 1185 | .icon-glass { 1186 | background-position: 0 0; 1187 | } 1188 | .icon-music { 1189 | background-position: -24px 0; 1190 | } 1191 | .icon-search { 1192 | background-position: -48px 0; 1193 | } 1194 | .icon-envelope { 1195 | background-position: -72px 0; 1196 | } 1197 | .icon-heart { 1198 | background-position: -96px 0; 1199 | } 1200 | .icon-star { 1201 | background-position: -120px 0; 1202 | } 1203 | .icon-star-empty { 1204 | background-position: -144px 0; 1205 | } 1206 | .icon-user { 1207 | background-position: -168px 0; 1208 | } 1209 | .icon-film { 1210 | background-position: -192px 0; 1211 | } 1212 | .icon-th-large { 1213 | background-position: -216px 0; 1214 | } 1215 | .icon-th { 1216 | background-position: -240px 0; 1217 | } 1218 | .icon-th-list { 1219 | background-position: -264px 0; 1220 | } 1221 | .icon-ok { 1222 | background-position: -288px 0; 1223 | } 1224 | .icon-remove { 1225 | background-position: -312px 0; 1226 | } 1227 | .icon-zoom-in { 1228 | background-position: -336px 0; 1229 | } 1230 | .icon-zoom-out { 1231 | background-position: -360px 0; 1232 | } 1233 | .icon-off { 1234 | background-position: -384px 0; 1235 | } 1236 | .icon-signal { 1237 | background-position: -408px 0; 1238 | } 1239 | .icon-cog { 1240 | background-position: -432px 0; 1241 | } 1242 | .icon-trash { 1243 | background-position: -456px 0; 1244 | } 1245 | .icon-home { 1246 | background-position: 0 -24px; 1247 | } 1248 | .icon-file { 1249 | background-position: -24px -24px; 1250 | } 1251 | .icon-time { 1252 | background-position: -48px -24px; 1253 | } 1254 | .icon-road { 1255 | background-position: -72px -24px; 1256 | } 1257 | .icon-download-alt { 1258 | background-position: -96px -24px; 1259 | } 1260 | .icon-download { 1261 | background-position: -120px -24px; 1262 | } 1263 | .icon-upload { 1264 | background-position: -144px -24px; 1265 | } 1266 | .icon-inbox { 1267 | background-position: -168px -24px; 1268 | } 1269 | .icon-play-circle { 1270 | background-position: -192px -24px; 1271 | } 1272 | .icon-repeat { 1273 | background-position: -216px -24px; 1274 | } 1275 | .icon-refresh { 1276 | background-position: -240px -24px; 1277 | } 1278 | .icon-list-alt { 1279 | background-position: -264px -24px; 1280 | } 1281 | .icon-lock { 1282 | background-position: -287px -24px; 1283 | } 1284 | .icon-flag { 1285 | background-position: -312px -24px; 1286 | } 1287 | .icon-headphones { 1288 | background-position: -336px -24px; 1289 | } 1290 | .icon-volume-off { 1291 | background-position: -360px -24px; 1292 | } 1293 | .icon-volume-down { 1294 | background-position: -384px -24px; 1295 | } 1296 | .icon-volume-up { 1297 | background-position: -408px -24px; 1298 | } 1299 | .icon-qrcode { 1300 | background-position: -432px -24px; 1301 | } 1302 | .icon-barcode { 1303 | background-position: -456px -24px; 1304 | } 1305 | .icon-tag { 1306 | background-position: 0 -48px; 1307 | } 1308 | .icon-tags { 1309 | background-position: -25px -48px; 1310 | } 1311 | .icon-book { 1312 | background-position: -48px -48px; 1313 | } 1314 | .icon-bookmark { 1315 | background-position: -72px -48px; 1316 | } 1317 | .icon-print { 1318 | background-position: -96px -48px; 1319 | } 1320 | .icon-camera { 1321 | background-position: -120px -48px; 1322 | } 1323 | .icon-font { 1324 | background-position: -144px -48px; 1325 | } 1326 | .icon-bold { 1327 | background-position: -167px -48px; 1328 | } 1329 | .icon-italic { 1330 | background-position: -192px -48px; 1331 | } 1332 | .icon-text-height { 1333 | background-position: -216px -48px; 1334 | } 1335 | .icon-text-width { 1336 | background-position: -240px -48px; 1337 | } 1338 | .icon-align-left { 1339 | background-position: -264px -48px; 1340 | } 1341 | .icon-align-center { 1342 | background-position: -288px -48px; 1343 | } 1344 | .icon-align-right { 1345 | background-position: -312px -48px; 1346 | } 1347 | .icon-align-justify { 1348 | background-position: -336px -48px; 1349 | } 1350 | .icon-list { 1351 | background-position: -360px -48px; 1352 | } 1353 | .icon-indent-left { 1354 | background-position: -384px -48px; 1355 | } 1356 | .icon-indent-right { 1357 | background-position: -408px -48px; 1358 | } 1359 | .icon-facetime-video { 1360 | background-position: -432px -48px; 1361 | } 1362 | .icon-picture { 1363 | background-position: -456px -48px; 1364 | } 1365 | .icon-pencil { 1366 | background-position: 0 -72px; 1367 | } 1368 | .icon-map-marker { 1369 | background-position: -24px -72px; 1370 | } 1371 | .icon-adjust { 1372 | background-position: -48px -72px; 1373 | } 1374 | .icon-tint { 1375 | background-position: -72px -72px; 1376 | } 1377 | .icon-edit { 1378 | background-position: -96px -72px; 1379 | } 1380 | .icon-share { 1381 | background-position: -120px -72px; 1382 | } 1383 | .icon-check { 1384 | background-position: -144px -72px; 1385 | } 1386 | .icon-move { 1387 | background-position: -168px -72px; 1388 | } 1389 | .icon-step-backward { 1390 | background-position: -192px -72px; 1391 | } 1392 | .icon-fast-backward { 1393 | background-position: -216px -72px; 1394 | } 1395 | .icon-backward { 1396 | background-position: -240px -72px; 1397 | } 1398 | .icon-play { 1399 | background-position: -264px -72px; 1400 | } 1401 | .icon-pause { 1402 | background-position: -288px -72px; 1403 | } 1404 | .icon-stop { 1405 | background-position: -312px -72px; 1406 | } 1407 | .icon-forward { 1408 | background-position: -336px -72px; 1409 | } 1410 | .icon-fast-forward { 1411 | background-position: -360px -72px; 1412 | } 1413 | .icon-step-forward { 1414 | background-position: -384px -72px; 1415 | } 1416 | .icon-eject { 1417 | background-position: -408px -72px; 1418 | } 1419 | .icon-chevron-left { 1420 | background-position: -432px -72px; 1421 | } 1422 | .icon-chevron-right { 1423 | background-position: -456px -72px; 1424 | } 1425 | .icon-plus-sign { 1426 | background-position: 0 -96px; 1427 | } 1428 | .icon-minus-sign { 1429 | background-position: -24px -96px; 1430 | } 1431 | .icon-remove-sign { 1432 | background-position: -48px -96px; 1433 | } 1434 | .icon-ok-sign { 1435 | background-position: -72px -96px; 1436 | } 1437 | .icon-question-sign { 1438 | background-position: -96px -96px; 1439 | } 1440 | .icon-info-sign { 1441 | background-position: -120px -96px; 1442 | } 1443 | .icon-screenshot { 1444 | background-position: -144px -96px; 1445 | } 1446 | .icon-remove-circle { 1447 | background-position: -168px -96px; 1448 | } 1449 | .icon-ok-circle { 1450 | background-position: -192px -96px; 1451 | } 1452 | .icon-ban-circle { 1453 | background-position: -216px -96px; 1454 | } 1455 | .icon-arrow-left { 1456 | background-position: -240px -96px; 1457 | } 1458 | .icon-arrow-right { 1459 | background-position: -264px -96px; 1460 | } 1461 | .icon-arrow-up { 1462 | background-position: -289px -96px; 1463 | } 1464 | .icon-arrow-down { 1465 | background-position: -312px -96px; 1466 | } 1467 | .icon-share-alt { 1468 | background-position: -336px -96px; 1469 | } 1470 | .icon-resize-full { 1471 | background-position: -360px -96px; 1472 | } 1473 | .icon-resize-small { 1474 | background-position: -384px -96px; 1475 | } 1476 | .icon-plus { 1477 | background-position: -408px -96px; 1478 | } 1479 | .icon-minus { 1480 | background-position: -433px -96px; 1481 | } 1482 | .icon-asterisk { 1483 | background-position: -456px -96px; 1484 | } 1485 | .icon-exclamation-sign { 1486 | background-position: 0 -120px; 1487 | } 1488 | .icon-gift { 1489 | background-position: -24px -120px; 1490 | } 1491 | .icon-leaf { 1492 | background-position: -48px -120px; 1493 | } 1494 | .icon-fire { 1495 | background-position: -72px -120px; 1496 | } 1497 | .icon-eye-open { 1498 | background-position: -96px -120px; 1499 | } 1500 | .icon-eye-close { 1501 | background-position: -120px -120px; 1502 | } 1503 | .icon-warning-sign { 1504 | background-position: -144px -120px; 1505 | } 1506 | .icon-plane { 1507 | background-position: -168px -120px; 1508 | } 1509 | .icon-calendar { 1510 | background-position: -192px -120px; 1511 | } 1512 | .icon-random { 1513 | background-position: -216px -120px; 1514 | } 1515 | .icon-comment { 1516 | background-position: -240px -120px; 1517 | } 1518 | .icon-magnet { 1519 | background-position: -264px -120px; 1520 | } 1521 | .icon-chevron-up { 1522 | background-position: -288px -120px; 1523 | } 1524 | .icon-chevron-down { 1525 | background-position: -313px -119px; 1526 | } 1527 | .icon-retweet { 1528 | background-position: -336px -120px; 1529 | } 1530 | .icon-shopping-cart { 1531 | background-position: -360px -120px; 1532 | } 1533 | .icon-folder-close { 1534 | background-position: -384px -120px; 1535 | } 1536 | .icon-folder-open { 1537 | background-position: -408px -120px; 1538 | } 1539 | .icon-resize-vertical { 1540 | background-position: -432px -119px; 1541 | } 1542 | .icon-resize-horizontal { 1543 | background-position: -456px -118px; 1544 | } 1545 | .dropdown { 1546 | position: relative; 1547 | } 1548 | .dropdown-toggle { 1549 | *margin-bottom: -3px; 1550 | } 1551 | .dropdown-toggle:active, .open .dropdown-toggle { 1552 | outline: 0; 1553 | } 1554 | .caret { 1555 | display: inline-block; 1556 | width: 0; 1557 | height: 0; 1558 | text-indent: -99999px; 1559 | *text-indent: 0; 1560 | vertical-align: top; 1561 | border-left: 4px solid transparent; 1562 | border-right: 4px solid transparent; 1563 | border-top: 4px solid #000000; 1564 | opacity: 0.3; 1565 | filter: alpha(opacity=30); 1566 | content: "\2193"; 1567 | } 1568 | .dropdown .caret { 1569 | margin-top: 8px; 1570 | margin-left: 2px; 1571 | } 1572 | .dropdown:hover .caret, .open.dropdown .caret { 1573 | opacity: 1; 1574 | filter: alpha(opacity=100); 1575 | } 1576 | .dropdown-menu { 1577 | position: absolute; 1578 | top: 100%; 1579 | left: 0; 1580 | z-index: 1000; 1581 | float: left; 1582 | display: none; 1583 | min-width: 160px; 1584 | _width: 160px; 1585 | padding: 4px 0; 1586 | margin: 0; 1587 | list-style: none; 1588 | background-color: #ffffff; 1589 | border-color: #ccc; 1590 | border-color: rgba(0, 0, 0, 0.2); 1591 | border-style: solid; 1592 | border-width: 1px; 1593 | -webkit-border-radius: 0 0 5px 5px; 1594 | -moz-border-radius: 0 0 5px 5px; 1595 | border-radius: 0 0 5px 5px; 1596 | -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); 1597 | -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); 1598 | box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); 1599 | -webkit-background-clip: padding-box; 1600 | -moz-background-clip: padding; 1601 | background-clip: padding-box; 1602 | *border-right-width: 2px; 1603 | *border-bottom-width: 2px; 1604 | } 1605 | .dropdown-menu.bottom-up { 1606 | top: auto; 1607 | bottom: 100%; 1608 | margin-bottom: 2px; 1609 | } 1610 | .dropdown-menu .divider { 1611 | height: 1px; 1612 | margin: 5px 1px; 1613 | overflow: hidden; 1614 | background-color: #e5e5e5; 1615 | border-bottom: 1px solid #ffffff; 1616 | *width: 100%; 1617 | *margin: -5px 0 5px; 1618 | } 1619 | .dropdown-menu a { 1620 | display: block; 1621 | padding: 3px 15px; 1622 | clear: both; 1623 | font-weight: normal; 1624 | line-height: 18px; 1625 | color: #555555; 1626 | white-space: nowrap; 1627 | } 1628 | .dropdown-menu li > a:hover, .dropdown-menu .active > a, .dropdown-menu .active > a:hover { 1629 | color: #ffffff; 1630 | text-decoration: none; 1631 | background-color: #0088cc; 1632 | } 1633 | .dropdown.open { 1634 | *z-index: 1000; 1635 | } 1636 | .dropdown.open .dropdown-toggle { 1637 | color: #ffffff; 1638 | background: #ccc; 1639 | background: rgba(0, 0, 0, 0.3); 1640 | } 1641 | .dropdown.open .dropdown-menu { 1642 | display: block; 1643 | } 1644 | .typeahead { 1645 | margin-top: 2px; 1646 | -webkit-border-radius: 4px; 1647 | -moz-border-radius: 4px; 1648 | border-radius: 4px; 1649 | } 1650 | .well { 1651 | min-height: 20px; 1652 | padding: 19px; 1653 | margin-bottom: 20px; 1654 | background-color: #f5f5f5; 1655 | border: 1px solid #eee; 1656 | border: 1px solid rgba(0, 0, 0, 0.05); 1657 | -webkit-border-radius: 4px; 1658 | -moz-border-radius: 4px; 1659 | border-radius: 4px; 1660 | -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); 1661 | -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); 1662 | box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); 1663 | } 1664 | .well blockquote { 1665 | border-color: #ddd; 1666 | border-color: rgba(0, 0, 0, 0.15); 1667 | } 1668 | .fade { 1669 | -webkit-transition: opacity 0.15s linear; 1670 | -moz-transition: opacity 0.15s linear; 1671 | -ms-transition: opacity 0.15s linear; 1672 | -o-transition: opacity 0.15s linear; 1673 | transition: opacity 0.15s linear; 1674 | opacity: 0; 1675 | } 1676 | .fade.in { 1677 | opacity: 1; 1678 | } 1679 | .collapse { 1680 | -webkit-transition: height 0.35s ease; 1681 | -moz-transition: height 0.35s ease; 1682 | -ms-transition: height 0.35s ease; 1683 | -o-transition: height 0.35s ease; 1684 | transition: height 0.35s ease; 1685 | position: relative; 1686 | overflow: hidden; 1687 | height: 0; 1688 | } 1689 | .collapse.in { 1690 | height: auto; 1691 | } 1692 | .close { 1693 | float: right; 1694 | font-size: 20px; 1695 | font-weight: bold; 1696 | line-height: 18px; 1697 | color: #000000; 1698 | text-shadow: 0 1px 0 #ffffff; 1699 | opacity: 0.2; 1700 | filter: alpha(opacity=20); 1701 | } 1702 | .close:hover { 1703 | color: #000000; 1704 | text-decoration: none; 1705 | opacity: 0.4; 1706 | filter: alpha(opacity=40); 1707 | cursor: pointer; 1708 | } 1709 | .btn { 1710 | display: inline-block; 1711 | padding: 4px 10px 4px; 1712 | margin-bottom: 0; 1713 | font-size: 13px; 1714 | line-height: 18px; 1715 | color: #333333; 1716 | text-align: center; 1717 | text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75); 1718 | vertical-align: middle; 1719 | background-color: #f5f5f5; 1720 | background-image: -moz-linear-gradient(top, #ffffff, #e6e6e6); 1721 | background-image: -ms-linear-gradient(top, #ffffff, #e6e6e6); 1722 | background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#e6e6e6)); 1723 | background-image: -webkit-linear-gradient(top, #ffffff, #e6e6e6); 1724 | background-image: -o-linear-gradient(top, #ffffff, #e6e6e6); 1725 | background-image: linear-gradient(top, #ffffff, #e6e6e6); 1726 | background-repeat: repeat-x; 1727 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#e6e6e6', GradientType=0); 1728 | border-color: #e6e6e6 #e6e6e6 #bfbfbf; 1729 | border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); 1730 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); 1731 | border: 1px solid #ccc; 1732 | border-bottom-color: #bbb; 1733 | -webkit-border-radius: 4px; 1734 | -moz-border-radius: 4px; 1735 | border-radius: 4px; 1736 | -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); 1737 | -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); 1738 | box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); 1739 | cursor: pointer; 1740 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); 1741 | *margin-left: .3em; 1742 | } 1743 | .btn:hover, 1744 | .btn:active, 1745 | .btn.active, 1746 | .btn.disabled, 1747 | .btn[disabled] { 1748 | background-color: #e6e6e6; 1749 | } 1750 | .btn:active, .btn.active { 1751 | background-color: #cccccc \9; 1752 | } 1753 | .btn:first-child { 1754 | *margin-left: 0; 1755 | } 1756 | .btn:hover { 1757 | color: #333333; 1758 | text-decoration: none; 1759 | background-color: #e6e6e6; 1760 | background-position: 0 -15px; 1761 | -webkit-transition: background-position 0.1s linear; 1762 | -moz-transition: background-position 0.1s linear; 1763 | -ms-transition: background-position 0.1s linear; 1764 | -o-transition: background-position 0.1s linear; 1765 | transition: background-position 0.1s linear; 1766 | } 1767 | .btn:focus { 1768 | outline: thin dotted #333; 1769 | outline: 5px auto -webkit-focus-ring-color; 1770 | outline-offset: -2px; 1771 | } 1772 | .btn.active, .btn:active { 1773 | background-image: none; 1774 | -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); 1775 | -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); 1776 | box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); 1777 | background-color: #e6e6e6; 1778 | background-color: #d9d9d9 \9; 1779 | outline: 0; 1780 | } 1781 | .btn.disabled, .btn[disabled] { 1782 | cursor: default; 1783 | background-image: none; 1784 | background-color: #e6e6e6; 1785 | opacity: 0.65; 1786 | filter: alpha(opacity=65); 1787 | -webkit-box-shadow: none; 1788 | -moz-box-shadow: none; 1789 | box-shadow: none; 1790 | } 1791 | .btn-large { 1792 | padding: 9px 14px; 1793 | font-size: 15px; 1794 | line-height: normal; 1795 | -webkit-border-radius: 5px; 1796 | -moz-border-radius: 5px; 1797 | border-radius: 5px; 1798 | } 1799 | .btn-large [class^="icon-"] { 1800 | margin-top: 1px; 1801 | } 1802 | .btn-small { 1803 | padding: 5px 9px; 1804 | font-size: 11px; 1805 | line-height: 16px; 1806 | } 1807 | .btn-small [class^="icon-"] { 1808 | margin-top: -1px; 1809 | } 1810 | .btn-mini { 1811 | padding: 2px 6px; 1812 | font-size: 11px; 1813 | line-height: 14px; 1814 | } 1815 | .btn-primary, 1816 | .btn-primary:hover, 1817 | .btn-warning, 1818 | .btn-warning:hover, 1819 | .btn-danger, 1820 | .btn-danger:hover, 1821 | .btn-success, 1822 | .btn-success:hover, 1823 | .btn-info, 1824 | .btn-info:hover, 1825 | .btn-inverse, 1826 | .btn-inverse:hover { 1827 | text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); 1828 | color: #ffffff; 1829 | } 1830 | .btn-primary.active, 1831 | .btn-warning.active, 1832 | .btn-danger.active, 1833 | .btn-success.active, 1834 | .btn-info.active, 1835 | .btn-dark.active { 1836 | color: rgba(255, 255, 255, 0.75); 1837 | } 1838 | .btn-primary { 1839 | background-color: #006dcc; 1840 | background-image: -moz-linear-gradient(top, #0088cc, #0044cc); 1841 | background-image: -ms-linear-gradient(top, #0088cc, #0044cc); 1842 | background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc)); 1843 | background-image: -webkit-linear-gradient(top, #0088cc, #0044cc); 1844 | background-image: -o-linear-gradient(top, #0088cc, #0044cc); 1845 | background-image: linear-gradient(top, #0088cc, #0044cc); 1846 | background-repeat: repeat-x; 1847 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#0088cc', endColorstr='#0044cc', GradientType=0); 1848 | border-color: #0044cc #0044cc #002a80; 1849 | border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); 1850 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); 1851 | } 1852 | .btn-primary:hover, 1853 | .btn-primary:active, 1854 | .btn-primary.active, 1855 | .btn-primary.disabled, 1856 | .btn-primary[disabled] { 1857 | background-color: #0044cc; 1858 | } 1859 | .btn-primary:active, .btn-primary.active { 1860 | background-color: #003399 \9; 1861 | } 1862 | .btn-warning { 1863 | background-color: #faa732; 1864 | background-image: -moz-linear-gradient(top, #fbb450, #f89406); 1865 | background-image: -ms-linear-gradient(top, #fbb450, #f89406); 1866 | background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406)); 1867 | background-image: -webkit-linear-gradient(top, #fbb450, #f89406); 1868 | background-image: -o-linear-gradient(top, #fbb450, #f89406); 1869 | background-image: linear-gradient(top, #fbb450, #f89406); 1870 | background-repeat: repeat-x; 1871 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fbb450', endColorstr='#f89406', GradientType=0); 1872 | border-color: #f89406 #f89406 #ad6704; 1873 | border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); 1874 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); 1875 | } 1876 | .btn-warning:hover, 1877 | .btn-warning:active, 1878 | .btn-warning.active, 1879 | .btn-warning.disabled, 1880 | .btn-warning[disabled] { 1881 | background-color: #f89406; 1882 | } 1883 | .btn-warning:active, .btn-warning.active { 1884 | background-color: #c67605 \9; 1885 | } 1886 | .btn-danger { 1887 | background-color: #da4f49; 1888 | background-image: -moz-linear-gradient(top, #ee5f5b, #bd362f); 1889 | background-image: -ms-linear-gradient(top, #ee5f5b, #bd362f); 1890 | background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#bd362f)); 1891 | background-image: -webkit-linear-gradient(top, #ee5f5b, #bd362f); 1892 | background-image: -o-linear-gradient(top, #ee5f5b, #bd362f); 1893 | background-image: linear-gradient(top, #ee5f5b, #bd362f); 1894 | background-repeat: repeat-x; 1895 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ee5f5b', endColorstr='#bd362f', GradientType=0); 1896 | border-color: #bd362f #bd362f #802420; 1897 | border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); 1898 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); 1899 | } 1900 | .btn-danger:hover, 1901 | .btn-danger:active, 1902 | .btn-danger.active, 1903 | .btn-danger.disabled, 1904 | .btn-danger[disabled] { 1905 | background-color: #bd362f; 1906 | } 1907 | .btn-danger:active, .btn-danger.active { 1908 | background-color: #942a25 \9; 1909 | } 1910 | .btn-success { 1911 | background-color: #5bb75b; 1912 | background-image: -moz-linear-gradient(top, #62c462, #51a351); 1913 | background-image: -ms-linear-gradient(top, #62c462, #51a351); 1914 | background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#51a351)); 1915 | background-image: -webkit-linear-gradient(top, #62c462, #51a351); 1916 | background-image: -o-linear-gradient(top, #62c462, #51a351); 1917 | background-image: linear-gradient(top, #62c462, #51a351); 1918 | background-repeat: repeat-x; 1919 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#62c462', endColorstr='#51a351', GradientType=0); 1920 | border-color: #51a351 #51a351 #387038; 1921 | border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); 1922 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); 1923 | } 1924 | .btn-success:hover, 1925 | .btn-success:active, 1926 | .btn-success.active, 1927 | .btn-success.disabled, 1928 | .btn-success[disabled] { 1929 | background-color: #51a351; 1930 | } 1931 | .btn-success:active, .btn-success.active { 1932 | background-color: #408140 \9; 1933 | } 1934 | .btn-info { 1935 | background-color: #49afcd; 1936 | background-image: -moz-linear-gradient(top, #5bc0de, #2f96b4); 1937 | background-image: -ms-linear-gradient(top, #5bc0de, #2f96b4); 1938 | background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#2f96b4)); 1939 | background-image: -webkit-linear-gradient(top, #5bc0de, #2f96b4); 1940 | background-image: -o-linear-gradient(top, #5bc0de, #2f96b4); 1941 | background-image: linear-gradient(top, #5bc0de, #2f96b4); 1942 | background-repeat: repeat-x; 1943 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#5bc0de', endColorstr='#2f96b4', GradientType=0); 1944 | border-color: #2f96b4 #2f96b4 #1f6377; 1945 | border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); 1946 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); 1947 | } 1948 | .btn-info:hover, 1949 | .btn-info:active, 1950 | .btn-info.active, 1951 | .btn-info.disabled, 1952 | .btn-info[disabled] { 1953 | background-color: #2f96b4; 1954 | } 1955 | .btn-info:active, .btn-info.active { 1956 | background-color: #24748c \9; 1957 | } 1958 | .btn-inverse { 1959 | background-color: #393939; 1960 | background-image: -moz-linear-gradient(top, #454545, #262626); 1961 | background-image: -ms-linear-gradient(top, #454545, #262626); 1962 | background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#454545), to(#262626)); 1963 | background-image: -webkit-linear-gradient(top, #454545, #262626); 1964 | background-image: -o-linear-gradient(top, #454545, #262626); 1965 | background-image: linear-gradient(top, #454545, #262626); 1966 | background-repeat: repeat-x; 1967 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#454545', endColorstr='#262626', GradientType=0); 1968 | border-color: #262626 #262626 #000000; 1969 | border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); 1970 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); 1971 | } 1972 | .btn-inverse:hover, 1973 | .btn-inverse:active, 1974 | .btn-inverse.active, 1975 | .btn-inverse.disabled, 1976 | .btn-inverse[disabled] { 1977 | background-color: #262626; 1978 | } 1979 | .btn-inverse:active, .btn-inverse.active { 1980 | background-color: #0c0c0c \9; 1981 | } 1982 | button.btn, input[type="submit"].btn { 1983 | *padding-top: 2px; 1984 | *padding-bottom: 2px; 1985 | } 1986 | button.btn::-moz-focus-inner, input[type="submit"].btn::-moz-focus-inner { 1987 | padding: 0; 1988 | border: 0; 1989 | } 1990 | button.btn.large, input[type="submit"].btn.large { 1991 | *padding-top: 7px; 1992 | *padding-bottom: 7px; 1993 | } 1994 | button.btn.small, input[type="submit"].btn.small { 1995 | *padding-top: 3px; 1996 | *padding-bottom: 3px; 1997 | } 1998 | .btn-group { 1999 | position: relative; 2000 | *zoom: 1; 2001 | *margin-left: .3em; 2002 | } 2003 | .btn-group:before, .btn-group:after { 2004 | display: table; 2005 | content: ""; 2006 | } 2007 | .btn-group:after { 2008 | clear: both; 2009 | } 2010 | .btn-group:first-child { 2011 | *margin-left: 0; 2012 | } 2013 | .btn-group + .btn-group { 2014 | margin-left: 5px; 2015 | } 2016 | .btn-toolbar { 2017 | margin-top: 9px; 2018 | margin-bottom: 9px; 2019 | } 2020 | .btn-toolbar .btn-group { 2021 | display: inline-block; 2022 | *display: inline; 2023 | /* IE7 inline-block hack */ 2024 | 2025 | *zoom: 1; 2026 | } 2027 | .btn-group .btn { 2028 | position: relative; 2029 | float: left; 2030 | margin-left: -1px; 2031 | -webkit-border-radius: 0; 2032 | -moz-border-radius: 0; 2033 | border-radius: 0; 2034 | } 2035 | .btn-group .btn:first-child { 2036 | margin-left: 0; 2037 | -webkit-border-top-left-radius: 4px; 2038 | -moz-border-radius-topleft: 4px; 2039 | border-top-left-radius: 4px; 2040 | -webkit-border-bottom-left-radius: 4px; 2041 | -moz-border-radius-bottomleft: 4px; 2042 | border-bottom-left-radius: 4px; 2043 | } 2044 | .btn-group .btn:last-child, .btn-group .dropdown-toggle { 2045 | -webkit-border-top-right-radius: 4px; 2046 | -moz-border-radius-topright: 4px; 2047 | border-top-right-radius: 4px; 2048 | -webkit-border-bottom-right-radius: 4px; 2049 | -moz-border-radius-bottomright: 4px; 2050 | border-bottom-right-radius: 4px; 2051 | } 2052 | .btn-group .btn.large:first-child { 2053 | margin-left: 0; 2054 | -webkit-border-top-left-radius: 6px; 2055 | -moz-border-radius-topleft: 6px; 2056 | border-top-left-radius: 6px; 2057 | -webkit-border-bottom-left-radius: 6px; 2058 | -moz-border-radius-bottomleft: 6px; 2059 | border-bottom-left-radius: 6px; 2060 | } 2061 | .btn-group .btn.large:last-child, .btn-group .large.dropdown-toggle { 2062 | -webkit-border-top-right-radius: 6px; 2063 | -moz-border-radius-topright: 6px; 2064 | border-top-right-radius: 6px; 2065 | -webkit-border-bottom-right-radius: 6px; 2066 | -moz-border-radius-bottomright: 6px; 2067 | border-bottom-right-radius: 6px; 2068 | } 2069 | .btn-group .btn:hover, 2070 | .btn-group .btn:focus, 2071 | .btn-group .btn:active, 2072 | .btn-group .btn.active { 2073 | z-index: 2; 2074 | } 2075 | .btn-group .dropdown-toggle:active, .btn-group.open .dropdown-toggle { 2076 | outline: 0; 2077 | } 2078 | .btn-group .dropdown-toggle { 2079 | padding-left: 8px; 2080 | padding-right: 8px; 2081 | -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); 2082 | -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); 2083 | 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); 2084 | *padding-top: 5px; 2085 | *padding-bottom: 5px; 2086 | } 2087 | .btn-group.open { 2088 | *z-index: 1000; 2089 | } 2090 | .btn-group.open .dropdown-menu { 2091 | display: block; 2092 | margin-top: 1px; 2093 | -webkit-border-radius: 5px; 2094 | -moz-border-radius: 5px; 2095 | border-radius: 5px; 2096 | } 2097 | .btn-group.open .dropdown-toggle { 2098 | background-image: none; 2099 | -webkit-box-shadow: inset 0 1px 6px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); 2100 | -moz-box-shadow: inset 0 1px 6px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); 2101 | box-shadow: inset 0 1px 6px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); 2102 | } 2103 | .btn .caret { 2104 | margin-top: 7px; 2105 | margin-left: 0; 2106 | } 2107 | .btn:hover .caret, .open.btn-group .caret { 2108 | opacity: 1; 2109 | filter: alpha(opacity=100); 2110 | } 2111 | .btn-primary .caret, 2112 | .btn-danger .caret, 2113 | .btn-info .caret, 2114 | .btn-success .caret, 2115 | .btn-inverse .caret { 2116 | border-top-color: #ffffff; 2117 | opacity: 0.75; 2118 | filter: alpha(opacity=75); 2119 | } 2120 | .btn-small .caret { 2121 | margin-top: 4px; 2122 | } 2123 | .alert { 2124 | padding: 8px 35px 8px 14px; 2125 | margin-bottom: 18px; 2126 | text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); 2127 | background-color: #fcf8e3; 2128 | border: 1px solid #fbeed5; 2129 | -webkit-border-radius: 4px; 2130 | -moz-border-radius: 4px; 2131 | border-radius: 4px; 2132 | } 2133 | .alert, .alert-heading { 2134 | color: #c09853; 2135 | } 2136 | .alert .close { 2137 | position: relative; 2138 | top: -2px; 2139 | right: -21px; 2140 | line-height: 18px; 2141 | } 2142 | .alert-success { 2143 | background-color: #dff0d8; 2144 | border-color: #d6e9c6; 2145 | } 2146 | .alert-success, .alert-success .alert-heading { 2147 | color: #468847; 2148 | } 2149 | .alert-danger, .alert-error { 2150 | background-color: #f2dede; 2151 | border-color: #eed3d7; 2152 | } 2153 | .alert-danger, 2154 | .alert-error, 2155 | .alert-danger .alert-heading, 2156 | .alert-error .alert-heading { 2157 | color: #b94a48; 2158 | } 2159 | .alert-info { 2160 | background-color: #d9edf7; 2161 | border-color: #bce8f1; 2162 | } 2163 | .alert-info, .alert-info .alert-heading { 2164 | color: #3a87ad; 2165 | } 2166 | .alert-block { 2167 | padding-top: 14px; 2168 | padding-bottom: 14px; 2169 | } 2170 | .alert-block > p, .alert-block > ul { 2171 | margin-bottom: 0; 2172 | } 2173 | .alert-block p + p { 2174 | margin-top: 5px; 2175 | } 2176 | .nav { 2177 | margin-left: 0; 2178 | margin-bottom: 18px; 2179 | list-style: none; 2180 | } 2181 | .nav > li > a { 2182 | display: block; 2183 | } 2184 | .nav > li > a:hover { 2185 | text-decoration: none; 2186 | background-color: #eeeeee; 2187 | } 2188 | .nav .nav-header { 2189 | display: block; 2190 | padding: 3px 15px; 2191 | font-size: 11px; 2192 | font-weight: bold; 2193 | line-height: 18px; 2194 | color: #999999; 2195 | text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); 2196 | text-transform: uppercase; 2197 | } 2198 | .nav li + .nav-header { 2199 | margin-top: 9px; 2200 | } 2201 | .nav-list { 2202 | padding-left: 14px; 2203 | padding-right: 14px; 2204 | margin-bottom: 0; 2205 | } 2206 | .nav-list > li > a, .nav-list .nav-header { 2207 | margin-left: -15px; 2208 | margin-right: -15px; 2209 | text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); 2210 | } 2211 | .nav-list > li > a { 2212 | padding: 3px 15px; 2213 | } 2214 | .nav-list .active > a, .nav-list .active > a:hover { 2215 | color: #ffffff; 2216 | text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2); 2217 | background-color: #0088cc; 2218 | } 2219 | .nav-list [class^="icon-"] { 2220 | margin-right: 2px; 2221 | } 2222 | .nav-tabs, .nav-pills { 2223 | *zoom: 1; 2224 | } 2225 | .nav-tabs:before, 2226 | .nav-pills:before, 2227 | .nav-tabs:after, 2228 | .nav-pills:after { 2229 | display: table; 2230 | content: ""; 2231 | } 2232 | .nav-tabs:after, .nav-pills:after { 2233 | clear: both; 2234 | } 2235 | .nav-tabs > li, .nav-pills > li { 2236 | float: left; 2237 | } 2238 | .nav-tabs > li > a, .nav-pills > li > a { 2239 | padding-right: 12px; 2240 | padding-left: 12px; 2241 | margin-right: 2px; 2242 | line-height: 14px; 2243 | } 2244 | .nav-tabs { 2245 | border-bottom: 1px solid #ddd; 2246 | } 2247 | .nav-tabs > li { 2248 | margin-bottom: -1px; 2249 | } 2250 | .nav-tabs > li > a { 2251 | padding-top: 9px; 2252 | padding-bottom: 9px; 2253 | border: 1px solid transparent; 2254 | -webkit-border-radius: 4px 4px 0 0; 2255 | -moz-border-radius: 4px 4px 0 0; 2256 | border-radius: 4px 4px 0 0; 2257 | } 2258 | .nav-tabs > li > a:hover { 2259 | border-color: #eeeeee #eeeeee #dddddd; 2260 | } 2261 | .nav-tabs > .active > a, .nav-tabs > .active > a:hover { 2262 | color: #555555; 2263 | background-color: #ffffff; 2264 | border: 1px solid #ddd; 2265 | border-bottom-color: transparent; 2266 | cursor: default; 2267 | } 2268 | .nav-pills > li > a { 2269 | padding-top: 8px; 2270 | padding-bottom: 8px; 2271 | margin-top: 2px; 2272 | margin-bottom: 2px; 2273 | -webkit-border-radius: 5px; 2274 | -moz-border-radius: 5px; 2275 | border-radius: 5px; 2276 | } 2277 | .nav-pills .active > a, .nav-pills .active > a:hover { 2278 | color: #ffffff; 2279 | background-color: #0088cc; 2280 | } 2281 | .nav-stacked > li { 2282 | float: none; 2283 | } 2284 | .nav-stacked > li > a { 2285 | margin-right: 0; 2286 | } 2287 | .nav-tabs.nav-stacked { 2288 | border-bottom: 0; 2289 | } 2290 | .nav-tabs.nav-stacked > li > a { 2291 | border: 1px solid #ddd; 2292 | -webkit-border-radius: 0; 2293 | -moz-border-radius: 0; 2294 | border-radius: 0; 2295 | } 2296 | .nav-tabs.nav-stacked > li:first-child > a { 2297 | -webkit-border-radius: 4px 4px 0 0; 2298 | -moz-border-radius: 4px 4px 0 0; 2299 | border-radius: 4px 4px 0 0; 2300 | } 2301 | .nav-tabs.nav-stacked > li:last-child > a { 2302 | -webkit-border-radius: 0 0 4px 4px; 2303 | -moz-border-radius: 0 0 4px 4px; 2304 | border-radius: 0 0 4px 4px; 2305 | } 2306 | .nav-tabs.nav-stacked > li > a:hover { 2307 | border-color: #ddd; 2308 | z-index: 2; 2309 | } 2310 | .nav-pills.nav-stacked > li > a { 2311 | margin-bottom: 3px; 2312 | } 2313 | .nav-pills.nav-stacked > li:last-child > a { 2314 | margin-bottom: 1px; 2315 | } 2316 | .nav-tabs .dropdown-menu, .nav-pills .dropdown-menu { 2317 | margin-top: 1px; 2318 | border-width: 1px; 2319 | } 2320 | .nav-pills .dropdown-menu { 2321 | -webkit-border-radius: 4px; 2322 | -moz-border-radius: 4px; 2323 | border-radius: 4px; 2324 | } 2325 | .nav-tabs .dropdown-toggle .caret, .nav-pills .dropdown-toggle .caret { 2326 | border-top-color: #0088cc; 2327 | margin-top: 6px; 2328 | } 2329 | .nav-tabs .dropdown-toggle:hover .caret, .nav-pills .dropdown-toggle:hover .caret { 2330 | border-top-color: #005580; 2331 | } 2332 | .nav-tabs .active .dropdown-toggle .caret, .nav-pills .active .dropdown-toggle .caret { 2333 | border-top-color: #333333; 2334 | } 2335 | .nav > .dropdown.active > a:hover { 2336 | color: #000000; 2337 | cursor: pointer; 2338 | } 2339 | .nav-tabs .open .dropdown-toggle, .nav-pills .open .dropdown-toggle, .nav > .open.active > a:hover { 2340 | color: #ffffff; 2341 | background-color: #999999; 2342 | border-color: #999999; 2343 | } 2344 | .nav .open .caret, .nav .open.active .caret, .nav .open a:hover .caret { 2345 | border-top-color: #ffffff; 2346 | opacity: 1; 2347 | filter: alpha(opacity=100); 2348 | } 2349 | .tabs-stacked .open > a:hover { 2350 | border-color: #999999; 2351 | } 2352 | .tabbable { 2353 | *zoom: 1; 2354 | } 2355 | .tabbable:before, .tabbable:after { 2356 | display: table; 2357 | content: ""; 2358 | } 2359 | .tabbable:after { 2360 | clear: both; 2361 | } 2362 | .tab-content { 2363 | overflow: hidden; 2364 | } 2365 | .tabs-below .nav-tabs, .tabs-right .nav-tabs, .tabs-left .nav-tabs { 2366 | border-bottom: 0; 2367 | } 2368 | .tab-content > .tab-pane, .pill-content > .pill-pane { 2369 | display: none; 2370 | } 2371 | .tab-content > .active, .pill-content > .active { 2372 | display: block; 2373 | } 2374 | .tabs-below .nav-tabs { 2375 | border-top: 1px solid #ddd; 2376 | } 2377 | .tabs-below .nav-tabs > li { 2378 | margin-top: -1px; 2379 | margin-bottom: 0; 2380 | } 2381 | .tabs-below .nav-tabs > li > a { 2382 | -webkit-border-radius: 0 0 4px 4px; 2383 | -moz-border-radius: 0 0 4px 4px; 2384 | border-radius: 0 0 4px 4px; 2385 | } 2386 | .tabs-below .nav-tabs > li > a:hover { 2387 | border-bottom-color: transparent; 2388 | border-top-color: #ddd; 2389 | } 2390 | .tabs-below .nav-tabs .active > a, .tabs-below .nav-tabs .active > a:hover { 2391 | border-color: transparent #ddd #ddd #ddd; 2392 | } 2393 | .tabs-left .nav-tabs > li, .tabs-right .nav-tabs > li { 2394 | float: none; 2395 | } 2396 | .tabs-left .nav-tabs > li > a, .tabs-right .nav-tabs > li > a { 2397 | min-width: 74px; 2398 | margin-right: 0; 2399 | margin-bottom: 3px; 2400 | } 2401 | .tabs-left .nav-tabs { 2402 | float: left; 2403 | margin-right: 19px; 2404 | border-right: 1px solid #ddd; 2405 | } 2406 | .tabs-left .nav-tabs > li > a { 2407 | margin-right: -1px; 2408 | -webkit-border-radius: 4px 0 0 4px; 2409 | -moz-border-radius: 4px 0 0 4px; 2410 | border-radius: 4px 0 0 4px; 2411 | } 2412 | .tabs-left .nav-tabs > li > a:hover { 2413 | border-color: #eeeeee #dddddd #eeeeee #eeeeee; 2414 | } 2415 | .tabs-left .nav-tabs .active > a, .tabs-left .nav-tabs .active > a:hover { 2416 | border-color: #ddd transparent #ddd #ddd; 2417 | *border-right-color: #ffffff; 2418 | } 2419 | .tabs-right .nav-tabs { 2420 | float: right; 2421 | margin-left: 19px; 2422 | border-left: 1px solid #ddd; 2423 | } 2424 | .tabs-right .nav-tabs > li > a { 2425 | margin-left: -1px; 2426 | -webkit-border-radius: 0 4px 4px 0; 2427 | -moz-border-radius: 0 4px 4px 0; 2428 | border-radius: 0 4px 4px 0; 2429 | } 2430 | .tabs-right .nav-tabs > li > a:hover { 2431 | border-color: #eeeeee #eeeeee #eeeeee #dddddd; 2432 | } 2433 | .tabs-right .nav-tabs .active > a, .tabs-right .nav-tabs .active > a:hover { 2434 | border-color: #ddd #ddd #ddd transparent; 2435 | *border-left-color: #ffffff; 2436 | } 2437 | .navbar { 2438 | overflow: visible; 2439 | margin-bottom: 18px; 2440 | } 2441 | .navbar-inner { 2442 | padding-left: 20px; 2443 | padding-right: 20px; 2444 | background-color: #2c2c2c; 2445 | background-image: -moz-linear-gradient(top, #333333, #222222); 2446 | background-image: -ms-linear-gradient(top, #333333, #222222); 2447 | background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#333333), to(#222222)); 2448 | background-image: -webkit-linear-gradient(top, #333333, #222222); 2449 | background-image: -o-linear-gradient(top, #333333, #222222); 2450 | background-image: linear-gradient(top, #333333, #222222); 2451 | background-repeat: repeat-x; 2452 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#333333', endColorstr='#222222', GradientType=0); 2453 | -webkit-border-radius: 4px; 2454 | -moz-border-radius: 4px; 2455 | border-radius: 4px; 2456 | -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25), inset 0 -1px 0 rgba(0, 0, 0, 0.1); 2457 | -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25), inset 0 -1px 0 rgba(0, 0, 0, 0.1); 2458 | box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25), inset 0 -1px 0 rgba(0, 0, 0, 0.1); 2459 | } 2460 | .btn-navbar { 2461 | display: none; 2462 | float: right; 2463 | padding: 7px 10px; 2464 | margin-left: 5px; 2465 | margin-right: 5px; 2466 | background-color: #2c2c2c; 2467 | background-image: -moz-linear-gradient(top, #333333, #222222); 2468 | background-image: -ms-linear-gradient(top, #333333, #222222); 2469 | background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#333333), to(#222222)); 2470 | background-image: -webkit-linear-gradient(top, #333333, #222222); 2471 | background-image: -o-linear-gradient(top, #333333, #222222); 2472 | background-image: linear-gradient(top, #333333, #222222); 2473 | background-repeat: repeat-x; 2474 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#333333', endColorstr='#222222', GradientType=0); 2475 | border-color: #222222 #222222 #000000; 2476 | border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); 2477 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); 2478 | -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075); 2479 | -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075); 2480 | box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075); 2481 | } 2482 | .btn-navbar:hover, 2483 | .btn-navbar:active, 2484 | .btn-navbar.active, 2485 | .btn-navbar.disabled, 2486 | .btn-navbar[disabled] { 2487 | background-color: #222222; 2488 | } 2489 | .btn-navbar:active, .btn-navbar.active { 2490 | background-color: #080808 \9; 2491 | } 2492 | .btn-navbar .icon-bar { 2493 | display: block; 2494 | width: 18px; 2495 | height: 2px; 2496 | background-color: #f5f5f5; 2497 | -webkit-border-radius: 1px; 2498 | -moz-border-radius: 1px; 2499 | border-radius: 1px; 2500 | -webkit-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25); 2501 | -moz-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25); 2502 | box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25); 2503 | } 2504 | .btn-navbar .icon-bar + .icon-bar { 2505 | margin-top: 3px; 2506 | } 2507 | .nav-collapse.collapse { 2508 | height: auto; 2509 | } 2510 | .navbar .brand:hover { 2511 | text-decoration: none; 2512 | } 2513 | .navbar .brand { 2514 | float: left; 2515 | display: block; 2516 | padding: 8px 20px 12px; 2517 | margin-left: -20px; 2518 | font-size: 20px; 2519 | font-weight: 200; 2520 | line-height: 1; 2521 | color: #ffffff; 2522 | } 2523 | .navbar .navbar-text { 2524 | margin-bottom: 0; 2525 | line-height: 40px; 2526 | color: #999999; 2527 | } 2528 | .navbar .navbar-text a:hover { 2529 | color: #ffffff; 2530 | background-color: transparent; 2531 | } 2532 | .navbar .btn, .navbar .btn-group { 2533 | margin-top: 5px; 2534 | } 2535 | .navbar .btn-group .btn { 2536 | margin-top: 0; 2537 | } 2538 | .navbar-form { 2539 | margin-bottom: 0; 2540 | *zoom: 1; 2541 | } 2542 | .navbar-form:before, .navbar-form:after { 2543 | display: table; 2544 | content: ""; 2545 | } 2546 | .navbar-form:after { 2547 | clear: both; 2548 | } 2549 | .navbar-form input, .navbar-form select { 2550 | display: inline-block; 2551 | margin-top: 5px; 2552 | margin-bottom: 0; 2553 | } 2554 | .navbar-form .radio, .navbar-form .checkbox { 2555 | margin-top: 5px; 2556 | } 2557 | .navbar-form input[type="image"], .navbar-form input[type="checkbox"], .navbar-form input[type="radio"] { 2558 | margin-top: 3px; 2559 | } 2560 | .navbar-form .input-append, .navbar-form .input-prepend { 2561 | margin-top: 6px; 2562 | white-space: nowrap; 2563 | } 2564 | .navbar-form .input-append input, .navbar-form .input-prepend input { 2565 | margin-top: 0; 2566 | } 2567 | .navbar-search { 2568 | position: relative; 2569 | float: left; 2570 | margin-top: 6px; 2571 | margin-bottom: 0; 2572 | } 2573 | .navbar-search .search-query { 2574 | padding: 4px 9px; 2575 | font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; 2576 | font-size: 13px; 2577 | font-weight: normal; 2578 | line-height: 1; 2579 | color: #ffffff; 2580 | color: rgba(255, 255, 255, 0.75); 2581 | background: #666; 2582 | background: rgba(255, 255, 255, 0.3); 2583 | border: 1px solid #111; 2584 | -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0px rgba(255, 255, 255, 0.15); 2585 | -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0px rgba(255, 255, 255, 0.15); 2586 | box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0px rgba(255, 255, 255, 0.15); 2587 | -webkit-transition: none; 2588 | -moz-transition: none; 2589 | -ms-transition: none; 2590 | -o-transition: none; 2591 | transition: none; 2592 | } 2593 | .navbar-search .search-query :-moz-placeholder { 2594 | color: #eeeeee; 2595 | } 2596 | .navbar-search .search-query::-webkit-input-placeholder { 2597 | color: #eeeeee; 2598 | } 2599 | .navbar-search .search-query:hover { 2600 | color: #ffffff; 2601 | background-color: #999999; 2602 | background-color: rgba(255, 255, 255, 0.5); 2603 | } 2604 | .navbar-search .search-query:focus, .navbar-search .search-query.focused { 2605 | padding: 5px 10px; 2606 | color: #333333; 2607 | text-shadow: 0 1px 0 #ffffff; 2608 | background-color: #ffffff; 2609 | border: 0; 2610 | -webkit-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15); 2611 | -moz-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15); 2612 | box-shadow: 0 0 3px rgba(0, 0, 0, 0.15); 2613 | outline: 0; 2614 | } 2615 | .navbar-fixed-top { 2616 | position: fixed; 2617 | top: 0; 2618 | right: 0; 2619 | left: 0; 2620 | z-index: 1030; 2621 | } 2622 | .navbar-fixed-top .navbar-inner { 2623 | padding-left: 0; 2624 | padding-right: 0; 2625 | -webkit-border-radius: 0; 2626 | -moz-border-radius: 0; 2627 | border-radius: 0; 2628 | } 2629 | .navbar .nav { 2630 | position: relative; 2631 | left: 0; 2632 | display: block; 2633 | float: left; 2634 | margin: 0 10px 0 0; 2635 | } 2636 | .navbar .nav.pull-right { 2637 | float: right; 2638 | } 2639 | .navbar .nav > li { 2640 | display: block; 2641 | float: left; 2642 | } 2643 | .navbar .nav > li > a { 2644 | float: none; 2645 | padding: 10px 10px 11px; 2646 | line-height: 19px; 2647 | color: #999999; 2648 | text-decoration: none; 2649 | text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); 2650 | } 2651 | .navbar .nav > li > a:hover { 2652 | background-color: transparent; 2653 | color: #ffffff; 2654 | text-decoration: none; 2655 | } 2656 | .navbar .nav .active > a, .navbar .nav .active > a:hover { 2657 | color: #ffffff; 2658 | text-decoration: none; 2659 | background-color: #222222; 2660 | } 2661 | .navbar .divider-vertical { 2662 | height: 40px; 2663 | width: 1px; 2664 | margin: 0 9px; 2665 | overflow: hidden; 2666 | background-color: #222222; 2667 | border-right: 1px solid #333333; 2668 | } 2669 | .navbar .nav.pull-right { 2670 | margin-left: 10px; 2671 | margin-right: 0; 2672 | } 2673 | .navbar .dropdown-menu { 2674 | margin-top: 1px; 2675 | -webkit-border-radius: 4px; 2676 | -moz-border-radius: 4px; 2677 | border-radius: 4px; 2678 | } 2679 | .navbar .dropdown-menu:before { 2680 | content: ''; 2681 | display: inline-block; 2682 | border-left: 7px solid transparent; 2683 | border-right: 7px solid transparent; 2684 | border-bottom: 7px solid #ccc; 2685 | border-bottom-color: rgba(0, 0, 0, 0.2); 2686 | position: absolute; 2687 | top: -7px; 2688 | left: 9px; 2689 | } 2690 | .navbar .dropdown-menu:after { 2691 | content: ''; 2692 | display: inline-block; 2693 | border-left: 6px solid transparent; 2694 | border-right: 6px solid transparent; 2695 | border-bottom: 6px solid #ffffff; 2696 | position: absolute; 2697 | top: -6px; 2698 | left: 10px; 2699 | } 2700 | .navbar .nav .dropdown-toggle .caret, .navbar .nav .open.dropdown .caret { 2701 | border-top-color: #ffffff; 2702 | } 2703 | .navbar .nav .active .caret { 2704 | opacity: 1; 2705 | filter: alpha(opacity=100); 2706 | } 2707 | .navbar .nav .open > .dropdown-toggle, .navbar .nav .active > .dropdown-toggle, .navbar .nav .open.active > .dropdown-toggle { 2708 | background-color: transparent; 2709 | } 2710 | .navbar .nav .active > .dropdown-toggle:hover { 2711 | color: #ffffff; 2712 | } 2713 | .navbar .nav.pull-right .dropdown-menu { 2714 | left: auto; 2715 | right: 0; 2716 | } 2717 | .navbar .nav.pull-right .dropdown-menu:before { 2718 | left: auto; 2719 | right: 12px; 2720 | } 2721 | .navbar .nav.pull-right .dropdown-menu:after { 2722 | left: auto; 2723 | right: 13px; 2724 | } 2725 | .breadcrumb { 2726 | padding: 7px 14px; 2727 | margin: 0 0 18px; 2728 | background-color: #fbfbfb; 2729 | background-image: -moz-linear-gradient(top, #ffffff, #f5f5f5); 2730 | background-image: -ms-linear-gradient(top, #ffffff, #f5f5f5); 2731 | background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#f5f5f5)); 2732 | background-image: -webkit-linear-gradient(top, #ffffff, #f5f5f5); 2733 | background-image: -o-linear-gradient(top, #ffffff, #f5f5f5); 2734 | background-image: linear-gradient(top, #ffffff, #f5f5f5); 2735 | background-repeat: repeat-x; 2736 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#f5f5f5', GradientType=0); 2737 | border: 1px solid #ddd; 2738 | -webkit-border-radius: 3px; 2739 | -moz-border-radius: 3px; 2740 | border-radius: 3px; 2741 | -webkit-box-shadow: inset 0 1px 0 #ffffff; 2742 | -moz-box-shadow: inset 0 1px 0 #ffffff; 2743 | box-shadow: inset 0 1px 0 #ffffff; 2744 | } 2745 | .breadcrumb li { 2746 | display: inline-block; 2747 | text-shadow: 0 1px 0 #ffffff; 2748 | } 2749 | .breadcrumb .divider { 2750 | padding: 0 5px; 2751 | color: #999999; 2752 | } 2753 | .breadcrumb .active a { 2754 | color: #333333; 2755 | } 2756 | .pagination { 2757 | height: 36px; 2758 | margin: 18px 0; 2759 | } 2760 | .pagination ul { 2761 | display: inline-block; 2762 | *display: inline; 2763 | /* IE7 inline-block hack */ 2764 | 2765 | *zoom: 1; 2766 | margin-left: 0; 2767 | margin-bottom: 0; 2768 | -webkit-border-radius: 3px; 2769 | -moz-border-radius: 3px; 2770 | border-radius: 3px; 2771 | -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); 2772 | -moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); 2773 | box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); 2774 | } 2775 | .pagination li { 2776 | display: inline; 2777 | } 2778 | .pagination a { 2779 | float: left; 2780 | padding: 0 14px; 2781 | line-height: 34px; 2782 | text-decoration: none; 2783 | border: 1px solid #ddd; 2784 | border-left-width: 0; 2785 | } 2786 | .pagination a:hover, .pagination .active a { 2787 | background-color: #f5f5f5; 2788 | } 2789 | .pagination .active a { 2790 | color: #999999; 2791 | cursor: default; 2792 | } 2793 | .pagination .disabled a, .pagination .disabled a:hover { 2794 | color: #999999; 2795 | background-color: transparent; 2796 | cursor: default; 2797 | } 2798 | .pagination li:first-child a { 2799 | border-left-width: 1px; 2800 | -webkit-border-radius: 3px 0 0 3px; 2801 | -moz-border-radius: 3px 0 0 3px; 2802 | border-radius: 3px 0 0 3px; 2803 | } 2804 | .pagination li:last-child a { 2805 | -webkit-border-radius: 0 3px 3px 0; 2806 | -moz-border-radius: 0 3px 3px 0; 2807 | border-radius: 0 3px 3px 0; 2808 | } 2809 | .pagination-centered { 2810 | text-align: center; 2811 | } 2812 | .pagination-right { 2813 | text-align: right; 2814 | } 2815 | .pager { 2816 | margin-left: 0; 2817 | margin-bottom: 18px; 2818 | list-style: none; 2819 | text-align: center; 2820 | *zoom: 1; 2821 | } 2822 | .pager:before, .pager:after { 2823 | display: table; 2824 | content: ""; 2825 | } 2826 | .pager:after { 2827 | clear: both; 2828 | } 2829 | .pager li { 2830 | display: inline; 2831 | } 2832 | .pager a { 2833 | display: inline-block; 2834 | padding: 5px 14px; 2835 | background-color: #fff; 2836 | border: 1px solid #ddd; 2837 | -webkit-border-radius: 15px; 2838 | -moz-border-radius: 15px; 2839 | border-radius: 15px; 2840 | } 2841 | .pager a:hover { 2842 | text-decoration: none; 2843 | background-color: #f5f5f5; 2844 | } 2845 | .pager .next a { 2846 | float: right; 2847 | } 2848 | .pager .previous a { 2849 | float: left; 2850 | } 2851 | .modal-open .dropdown-menu { 2852 | z-index: 2050; 2853 | } 2854 | .modal-open .dropdown.open { 2855 | *z-index: 2050; 2856 | } 2857 | .modal-open .popover { 2858 | z-index: 2060; 2859 | } 2860 | .modal-open .tooltip { 2861 | z-index: 2070; 2862 | } 2863 | .modal-backdrop { 2864 | position: fixed; 2865 | top: 0; 2866 | right: 0; 2867 | bottom: 0; 2868 | left: 0; 2869 | z-index: 1040; 2870 | background-color: #000000; 2871 | } 2872 | .modal-backdrop.fade { 2873 | opacity: 0; 2874 | } 2875 | .modal-backdrop, .modal-backdrop.fade.in { 2876 | opacity: 0.8; 2877 | filter: alpha(opacity=80); 2878 | } 2879 | .modal { 2880 | position: fixed; 2881 | top: 50%; 2882 | left: 50%; 2883 | z-index: 1050; 2884 | max-height: 500px; 2885 | overflow: auto; 2886 | width: 560px; 2887 | margin: -250px 0 0 -280px; 2888 | background-color: #ffffff; 2889 | border: 1px solid #999; 2890 | border: 1px solid rgba(0, 0, 0, 0.3); 2891 | *border: 1px solid #999; 2892 | /* IE6-7 */ 2893 | 2894 | -webkit-border-radius: 6px; 2895 | -moz-border-radius: 6px; 2896 | border-radius: 6px; 2897 | -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); 2898 | -moz-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); 2899 | box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); 2900 | -webkit-background-clip: padding-box; 2901 | -moz-background-clip: padding-box; 2902 | background-clip: padding-box; 2903 | } 2904 | .modal.fade { 2905 | -webkit-transition: opacity .3s linear, top .3s ease-out; 2906 | -moz-transition: opacity .3s linear, top .3s ease-out; 2907 | -ms-transition: opacity .3s linear, top .3s ease-out; 2908 | -o-transition: opacity .3s linear, top .3s ease-out; 2909 | transition: opacity .3s linear, top .3s ease-out; 2910 | top: -25%; 2911 | } 2912 | .modal.fade.in { 2913 | top: 50%; 2914 | } 2915 | .modal-header { 2916 | padding: 9px 15px; 2917 | border-bottom: 1px solid #eee; 2918 | } 2919 | .modal-header .close { 2920 | margin-top: 2px; 2921 | } 2922 | .modal-body { 2923 | padding: 15px; 2924 | } 2925 | .modal-body .modal-form { 2926 | margin-bottom: 0; 2927 | } 2928 | .modal-footer { 2929 | padding: 14px 15px 15px; 2930 | margin-bottom: 0; 2931 | background-color: #f5f5f5; 2932 | border-top: 1px solid #ddd; 2933 | -webkit-border-radius: 0 0 6px 6px; 2934 | -moz-border-radius: 0 0 6px 6px; 2935 | border-radius: 0 0 6px 6px; 2936 | -webkit-box-shadow: inset 0 1px 0 #ffffff; 2937 | -moz-box-shadow: inset 0 1px 0 #ffffff; 2938 | box-shadow: inset 0 1px 0 #ffffff; 2939 | *zoom: 1; 2940 | } 2941 | .modal-footer:before, .modal-footer:after { 2942 | display: table; 2943 | content: ""; 2944 | } 2945 | .modal-footer:after { 2946 | clear: both; 2947 | } 2948 | .modal-footer .btn { 2949 | float: right; 2950 | margin-left: 5px; 2951 | margin-bottom: 0; 2952 | } 2953 | .tooltip { 2954 | position: absolute; 2955 | z-index: 1020; 2956 | display: block; 2957 | visibility: visible; 2958 | padding: 5px; 2959 | font-size: 11px; 2960 | opacity: 0; 2961 | filter: alpha(opacity=0); 2962 | } 2963 | .tooltip.in { 2964 | opacity: 0.8; 2965 | filter: alpha(opacity=80); 2966 | } 2967 | .tooltip.top { 2968 | margin-top: -2px; 2969 | } 2970 | .tooltip.right { 2971 | margin-left: 2px; 2972 | } 2973 | .tooltip.bottom { 2974 | margin-top: 2px; 2975 | } 2976 | .tooltip.left { 2977 | margin-left: -2px; 2978 | } 2979 | .tooltip.top .tooltip-arrow { 2980 | bottom: 0; 2981 | left: 50%; 2982 | margin-left: -5px; 2983 | border-left: 5px solid transparent; 2984 | border-right: 5px solid transparent; 2985 | border-top: 5px solid #000000; 2986 | } 2987 | .tooltip.left .tooltip-arrow { 2988 | top: 50%; 2989 | right: 0; 2990 | margin-top: -5px; 2991 | border-top: 5px solid transparent; 2992 | border-bottom: 5px solid transparent; 2993 | border-left: 5px solid #000000; 2994 | } 2995 | .tooltip.bottom .tooltip-arrow { 2996 | top: 0; 2997 | left: 50%; 2998 | margin-left: -5px; 2999 | border-left: 5px solid transparent; 3000 | border-right: 5px solid transparent; 3001 | border-bottom: 5px solid #000000; 3002 | } 3003 | .tooltip.right .tooltip-arrow { 3004 | top: 50%; 3005 | left: 0; 3006 | margin-top: -5px; 3007 | border-top: 5px solid transparent; 3008 | border-bottom: 5px solid transparent; 3009 | border-right: 5px solid #000000; 3010 | } 3011 | .tooltip-inner { 3012 | max-width: 200px; 3013 | padding: 3px 8px; 3014 | color: #ffffff; 3015 | text-align: center; 3016 | text-decoration: none; 3017 | background-color: #000000; 3018 | -webkit-border-radius: 4px; 3019 | -moz-border-radius: 4px; 3020 | border-radius: 4px; 3021 | } 3022 | .tooltip-arrow { 3023 | position: absolute; 3024 | width: 0; 3025 | height: 0; 3026 | } 3027 | .popover { 3028 | position: absolute; 3029 | top: 0; 3030 | left: 0; 3031 | z-index: 1010; 3032 | display: none; 3033 | padding: 5px; 3034 | } 3035 | .popover.top { 3036 | margin-top: -5px; 3037 | } 3038 | .popover.right { 3039 | margin-left: 5px; 3040 | } 3041 | .popover.bottom { 3042 | margin-top: 5px; 3043 | } 3044 | .popover.left { 3045 | margin-left: -5px; 3046 | } 3047 | .popover.top .arrow { 3048 | bottom: 0; 3049 | left: 50%; 3050 | margin-left: -5px; 3051 | border-left: 5px solid transparent; 3052 | border-right: 5px solid transparent; 3053 | border-top: 5px solid #000000; 3054 | } 3055 | .popover.right .arrow { 3056 | top: 50%; 3057 | left: 0; 3058 | margin-top: -5px; 3059 | border-top: 5px solid transparent; 3060 | border-bottom: 5px solid transparent; 3061 | border-right: 5px solid #000000; 3062 | } 3063 | .popover.bottom .arrow { 3064 | top: 0; 3065 | left: 50%; 3066 | margin-left: -5px; 3067 | border-left: 5px solid transparent; 3068 | border-right: 5px solid transparent; 3069 | border-bottom: 5px solid #000000; 3070 | } 3071 | .popover.left .arrow { 3072 | top: 50%; 3073 | right: 0; 3074 | margin-top: -5px; 3075 | border-top: 5px solid transparent; 3076 | border-bottom: 5px solid transparent; 3077 | border-left: 5px solid #000000; 3078 | } 3079 | .popover .arrow { 3080 | position: absolute; 3081 | width: 0; 3082 | height: 0; 3083 | } 3084 | .popover-inner { 3085 | padding: 3px; 3086 | width: 280px; 3087 | overflow: hidden; 3088 | background: #000000; 3089 | background: rgba(0, 0, 0, 0.8); 3090 | -webkit-border-radius: 6px; 3091 | -moz-border-radius: 6px; 3092 | border-radius: 6px; 3093 | -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); 3094 | -moz-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); 3095 | box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); 3096 | } 3097 | .popover-title { 3098 | padding: 9px 15px; 3099 | line-height: 1; 3100 | background-color: #f5f5f5; 3101 | border-bottom: 1px solid #eee; 3102 | -webkit-border-radius: 3px 3px 0 0; 3103 | -moz-border-radius: 3px 3px 0 0; 3104 | border-radius: 3px 3px 0 0; 3105 | } 3106 | .popover-content { 3107 | padding: 14px; 3108 | background-color: #ffffff; 3109 | -webkit-border-radius: 0 0 3px 3px; 3110 | -moz-border-radius: 0 0 3px 3px; 3111 | border-radius: 0 0 3px 3px; 3112 | -webkit-background-clip: padding-box; 3113 | -moz-background-clip: padding-box; 3114 | background-clip: padding-box; 3115 | } 3116 | .popover-content p, .popover-content ul, .popover-content ol { 3117 | margin-bottom: 0; 3118 | } 3119 | .thumbnails { 3120 | margin-left: -20px; 3121 | list-style: none; 3122 | *zoom: 1; 3123 | } 3124 | .thumbnails:before, .thumbnails:after { 3125 | display: table; 3126 | content: ""; 3127 | } 3128 | .thumbnails:after { 3129 | clear: both; 3130 | } 3131 | .thumbnails > li { 3132 | float: left; 3133 | margin: 0 0 18px 20px; 3134 | } 3135 | .thumbnail { 3136 | display: block; 3137 | padding: 4px; 3138 | line-height: 1; 3139 | border: 1px solid #ddd; 3140 | -webkit-border-radius: 4px; 3141 | -moz-border-radius: 4px; 3142 | border-radius: 4px; 3143 | -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.075); 3144 | -moz-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.075); 3145 | box-shadow: 0 1px 1px rgba(0, 0, 0, 0.075); 3146 | } 3147 | a.thumbnail:hover { 3148 | border-color: #0088cc; 3149 | -webkit-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25); 3150 | -moz-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25); 3151 | box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25); 3152 | } 3153 | .thumbnail > img { 3154 | display: block; 3155 | max-width: 100%; 3156 | margin-left: auto; 3157 | margin-right: auto; 3158 | } 3159 | .thumbnail .caption { 3160 | padding: 9px; 3161 | } 3162 | .label { 3163 | padding: 2px 4px 3px; 3164 | font-size: 11.049999999999999px; 3165 | font-weight: bold; 3166 | color: #ffffff; 3167 | text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); 3168 | background-color: #999999; 3169 | -webkit-border-radius: 3px; 3170 | -moz-border-radius: 3px; 3171 | border-radius: 3px; 3172 | } 3173 | .label:hover { 3174 | color: #ffffff; 3175 | text-decoration: none; 3176 | } 3177 | .label-important { 3178 | background-color: #b94a48; 3179 | } 3180 | .label-important:hover { 3181 | background-color: #953b39; 3182 | } 3183 | .label-warning { 3184 | background-color: #f89406; 3185 | } 3186 | .label-warning:hover { 3187 | background-color: #c67605; 3188 | } 3189 | .label-success { 3190 | background-color: #468847; 3191 | } 3192 | .label-success:hover { 3193 | background-color: #356635; 3194 | } 3195 | .label-info { 3196 | background-color: #3a87ad; 3197 | } 3198 | .label-info:hover { 3199 | background-color: #2d6987; 3200 | } 3201 | @-webkit-keyframes progress-bar-stripes { 3202 | from { 3203 | background-position: 0 0; 3204 | } 3205 | to { 3206 | background-position: 40px 0; 3207 | } 3208 | } 3209 | @-moz-keyframes progress-bar-stripes { 3210 | from { 3211 | background-position: 0 0; 3212 | } 3213 | to { 3214 | background-position: 40px 0; 3215 | } 3216 | } 3217 | @keyframes progress-bar-stripes { 3218 | from { 3219 | background-position: 0 0; 3220 | } 3221 | to { 3222 | background-position: 40px 0; 3223 | } 3224 | } 3225 | .progress { 3226 | overflow: hidden; 3227 | height: 18px; 3228 | margin-bottom: 18px; 3229 | background-color: #f7f7f7; 3230 | background-image: -moz-linear-gradient(top, #f5f5f5, #f9f9f9); 3231 | background-image: -ms-linear-gradient(top, #f5f5f5, #f9f9f9); 3232 | background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f5f5f5), to(#f9f9f9)); 3233 | background-image: -webkit-linear-gradient(top, #f5f5f5, #f9f9f9); 3234 | background-image: -o-linear-gradient(top, #f5f5f5, #f9f9f9); 3235 | background-image: linear-gradient(top, #f5f5f5, #f9f9f9); 3236 | background-repeat: repeat-x; 3237 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#f5f5f5', endColorstr='#f9f9f9', GradientType=0); 3238 | -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); 3239 | -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); 3240 | box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); 3241 | -webkit-border-radius: 4px; 3242 | -moz-border-radius: 4px; 3243 | border-radius: 4px; 3244 | } 3245 | .progress .bar { 3246 | width: 0%; 3247 | height: 18px; 3248 | color: #ffffff; 3249 | font-size: 12px; 3250 | text-align: center; 3251 | text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); 3252 | background-color: #0e90d2; 3253 | background-image: -moz-linear-gradient(top, #149bdf, #0480be); 3254 | background-image: -ms-linear-gradient(top, #149bdf, #0480be); 3255 | background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#149bdf), to(#0480be)); 3256 | background-image: -webkit-linear-gradient(top, #149bdf, #0480be); 3257 | background-image: -o-linear-gradient(top, #149bdf, #0480be); 3258 | background-image: linear-gradient(top, #149bdf, #0480be); 3259 | background-repeat: repeat-x; 3260 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#149bdf', endColorstr='#0480be', GradientType=0); 3261 | -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); 3262 | -moz-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); 3263 | box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); 3264 | -webkit-box-sizing: border-box; 3265 | -moz-box-sizing: border-box; 3266 | box-sizing: border-box; 3267 | -webkit-transition: width 0.6s ease; 3268 | -moz-transition: width 0.6s ease; 3269 | -ms-transition: width 0.6s ease; 3270 | -o-transition: width 0.6s ease; 3271 | transition: width 0.6s ease; 3272 | } 3273 | .progress-striped .bar { 3274 | background-color: #62c462; 3275 | 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)); 3276 | 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); 3277 | 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); 3278 | background-image: -ms-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); 3279 | 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); 3280 | 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); 3281 | -webkit-background-size: 40px 40px; 3282 | -moz-background-size: 40px 40px; 3283 | -o-background-size: 40px 40px; 3284 | background-size: 40px 40px; 3285 | } 3286 | .progress.active .bar { 3287 | -webkit-animation: progress-bar-stripes 2s linear infinite; 3288 | -moz-animation: progress-bar-stripes 2s linear infinite; 3289 | animation: progress-bar-stripes 2s linear infinite; 3290 | } 3291 | .progress-danger .bar { 3292 | background-color: #dd514c; 3293 | background-image: -moz-linear-gradient(top, #ee5f5b, #c43c35); 3294 | background-image: -ms-linear-gradient(top, #ee5f5b, #c43c35); 3295 | background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#c43c35)); 3296 | background-image: -webkit-linear-gradient(top, #ee5f5b, #c43c35); 3297 | background-image: -o-linear-gradient(top, #ee5f5b, #c43c35); 3298 | background-image: linear-gradient(top, #ee5f5b, #c43c35); 3299 | background-repeat: repeat-x; 3300 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ee5f5b', endColorstr='#c43c35', GradientType=0); 3301 | } 3302 | .progress-danger.progress-striped .bar { 3303 | background-color: #ee5f5b; 3304 | 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)); 3305 | 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); 3306 | 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); 3307 | background-image: -ms-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); 3308 | 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); 3309 | 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); 3310 | } 3311 | .progress-success .bar { 3312 | background-color: #5eb95e; 3313 | background-image: -moz-linear-gradient(top, #62c462, #57a957); 3314 | background-image: -ms-linear-gradient(top, #62c462, #57a957); 3315 | background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#57a957)); 3316 | background-image: -webkit-linear-gradient(top, #62c462, #57a957); 3317 | background-image: -o-linear-gradient(top, #62c462, #57a957); 3318 | background-image: linear-gradient(top, #62c462, #57a957); 3319 | background-repeat: repeat-x; 3320 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#62c462', endColorstr='#57a957', GradientType=0); 3321 | } 3322 | .progress-success.progress-striped .bar { 3323 | background-color: #62c462; 3324 | 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)); 3325 | 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); 3326 | 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); 3327 | background-image: -ms-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); 3328 | 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); 3329 | 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); 3330 | } 3331 | .progress-info .bar { 3332 | background-color: #4bb1cf; 3333 | background-image: -moz-linear-gradient(top, #5bc0de, #339bb9); 3334 | background-image: -ms-linear-gradient(top, #5bc0de, #339bb9); 3335 | background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#339bb9)); 3336 | background-image: -webkit-linear-gradient(top, #5bc0de, #339bb9); 3337 | background-image: -o-linear-gradient(top, #5bc0de, #339bb9); 3338 | background-image: linear-gradient(top, #5bc0de, #339bb9); 3339 | background-repeat: repeat-x; 3340 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#5bc0de', endColorstr='#339bb9', GradientType=0); 3341 | } 3342 | .progress-info.progress-striped .bar { 3343 | background-color: #5bc0de; 3344 | 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)); 3345 | 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); 3346 | 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); 3347 | background-image: -ms-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); 3348 | 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); 3349 | 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); 3350 | } 3351 | .accordion { 3352 | margin-bottom: 18px; 3353 | } 3354 | .accordion-group { 3355 | margin-bottom: 2px; 3356 | border: 1px solid #e5e5e5; 3357 | -webkit-border-radius: 4px; 3358 | -moz-border-radius: 4px; 3359 | border-radius: 4px; 3360 | } 3361 | .accordion-heading { 3362 | border-bottom: 0; 3363 | } 3364 | .accordion-heading .accordion-toggle { 3365 | display: block; 3366 | padding: 8px 15px; 3367 | } 3368 | .accordion-inner { 3369 | padding: 9px 15px; 3370 | border-top: 1px solid #e5e5e5; 3371 | } 3372 | .carousel { 3373 | position: relative; 3374 | margin-bottom: 18px; 3375 | line-height: 1; 3376 | } 3377 | .carousel-inner { 3378 | overflow: hidden; 3379 | width: 100%; 3380 | position: relative; 3381 | } 3382 | .carousel .item { 3383 | display: none; 3384 | position: relative; 3385 | -webkit-transition: 0.6s ease-in-out left; 3386 | -moz-transition: 0.6s ease-in-out left; 3387 | -ms-transition: 0.6s ease-in-out left; 3388 | -o-transition: 0.6s ease-in-out left; 3389 | transition: 0.6s ease-in-out left; 3390 | } 3391 | .carousel .item > img { 3392 | display: block; 3393 | line-height: 1; 3394 | } 3395 | .carousel .active, .carousel .next, .carousel .prev { 3396 | display: block; 3397 | } 3398 | .carousel .active { 3399 | left: 0; 3400 | } 3401 | .carousel .next, .carousel .prev { 3402 | position: absolute; 3403 | top: 0; 3404 | width: 100%; 3405 | } 3406 | .carousel .next { 3407 | left: 100%; 3408 | } 3409 | .carousel .prev { 3410 | left: -100%; 3411 | } 3412 | .carousel .next.left, .carousel .prev.right { 3413 | left: 0; 3414 | } 3415 | .carousel .active.left { 3416 | left: -100%; 3417 | } 3418 | .carousel .active.right { 3419 | left: 100%; 3420 | } 3421 | .carousel-control { 3422 | position: absolute; 3423 | top: 40%; 3424 | left: 15px; 3425 | width: 40px; 3426 | height: 40px; 3427 | margin-top: -20px; 3428 | font-size: 60px; 3429 | font-weight: 100; 3430 | line-height: 30px; 3431 | color: #ffffff; 3432 | text-align: center; 3433 | background: #222222; 3434 | border: 3px solid #ffffff; 3435 | -webkit-border-radius: 23px; 3436 | -moz-border-radius: 23px; 3437 | border-radius: 23px; 3438 | opacity: 0.5; 3439 | filter: alpha(opacity=50); 3440 | } 3441 | .carousel-control.right { 3442 | left: auto; 3443 | right: 15px; 3444 | } 3445 | .carousel-control:hover { 3446 | color: #ffffff; 3447 | text-decoration: none; 3448 | opacity: 0.9; 3449 | filter: alpha(opacity=90); 3450 | } 3451 | .carousel-caption { 3452 | position: absolute; 3453 | left: 0; 3454 | right: 0; 3455 | bottom: 0; 3456 | padding: 10px 15px 5px; 3457 | background: #333333; 3458 | background: rgba(0, 0, 0, 0.75); 3459 | } 3460 | .carousel-caption h4, .carousel-caption p { 3461 | color: #ffffff; 3462 | } 3463 | .hero-unit { 3464 | padding: 60px; 3465 | margin-bottom: 30px; 3466 | background-color: #f5f5f5; 3467 | -webkit-border-radius: 6px; 3468 | -moz-border-radius: 6px; 3469 | border-radius: 6px; 3470 | } 3471 | .hero-unit h1 { 3472 | margin-bottom: 0; 3473 | font-size: 60px; 3474 | line-height: 1; 3475 | letter-spacing: -1px; 3476 | } 3477 | .hero-unit p { 3478 | font-size: 18px; 3479 | font-weight: 200; 3480 | line-height: 27px; 3481 | } 3482 | .pull-right { 3483 | float: right; 3484 | } 3485 | .pull-left { 3486 | float: left; 3487 | } 3488 | .hide { 3489 | display: none; 3490 | } 3491 | .show { 3492 | display: block; 3493 | } 3494 | .invisible { 3495 | visibility: hidden; 3496 | } 3497 | -------------------------------------------------------------------------------- /viewer/static/docs.css: -------------------------------------------------------------------------------- 1 | /* Add additional stylesheets below 2 | -------------------------------------------------- */ 3 | /* 4 | Bootstrap's documentation styles 5 | Special styles for presenting Bootstrap's documentation and examples 6 | */ 7 | 8 | 9 | /* Body and structure 10 | -------------------------------------------------- */ 11 | body { 12 | position: relative; 13 | padding-top: 90px; 14 | background-color: #fff; 15 | background-image: url(/grid-18px-masked.png); 16 | background-repeat: repeat-x; 17 | background-position: 0 40px; 18 | } 19 | 20 | 21 | /* Tweak navbar brand link to be super sleek 22 | -------------------------------------------------- */ 23 | .navbar-fixed-top .brand { 24 | padding-right: 0; 25 | padding-left: 0; 26 | margin-left: 20px; 27 | float: right; 28 | font-weight: bold; 29 | color: #000; 30 | text-shadow: 0 1px 0 rgba(255,255,255,.1), 0 0 30px rgba(255,255,255,.125); 31 | -webkit-transition: all .2s linear; 32 | -moz-transition: all .2s linear; 33 | transition: all .2s linear; 34 | } 35 | .navbar-fixed-top .brand:hover { 36 | text-decoration: none; 37 | } 38 | 39 | 40 | /* Space out sub-sections more 41 | -------------------------------------------------- */ 42 | section { 43 | padding-top: 60px; 44 | } 45 | 46 | /* Faded out hr */ 47 | hr.soften { 48 | height: 1px; 49 | margin: 54px 0; 50 | background-image: -webkit-linear-gradient(left, rgba(0,0,0,0), rgba(0,0,0,.1), rgba(0,0,0,0)); 51 | background-image: -moz-linear-gradient(left, rgba(0,0,0,0), rgba(0,0,0,.1), rgba(0,0,0,0)); 52 | background-image: -ms-linear-gradient(left, rgba(0,0,0,0), rgba(0,0,0,.1), rgba(0,0,0,0)); 53 | background-image: -o-linear-gradient(left, rgba(0,0,0,0), rgba(0,0,0,.1), rgba(0,0,0,0)); 54 | border: 0; 55 | } 56 | 57 | 58 | /* Jumbotrons 59 | -------------------------------------------------- */ 60 | .jumbotron { 61 | position: relative; 62 | } 63 | .jumbotron h1 { 64 | margin-bottom: 9px; 65 | font-size: 81px; 66 | letter-spacing: -1px; 67 | line-height: 1; 68 | } 69 | .jumbotron p { 70 | margin-bottom: 18px; 71 | font-weight: 300; 72 | } 73 | .jumbotron .btn-large { 74 | font-size: 20px; 75 | font-weight: normal; 76 | padding: 14px 24px; 77 | margin-right: 10px; 78 | -webkit-border-radius: 6px; 79 | -moz-border-radius: 6px; 80 | border-radius: 6px; 81 | } 82 | 83 | /* Masthead (docs home) */ 84 | .masthead { 85 | padding-top: 36px; 86 | margin-bottom: 72px; 87 | } 88 | .masthead h1, 89 | .masthead p { 90 | text-align: center; 91 | } 92 | .masthead h1 { 93 | margin-bottom: 18px; 94 | } 95 | .masthead p { 96 | margin-left: 5%; 97 | margin-right: 5%; 98 | font-size: 30px; 99 | line-height: 36px; 100 | } 101 | 102 | 103 | /* Specific jumbotrons 104 | ------------------------- */ 105 | /* supporting docs pages */ 106 | .subhead { 107 | padding-bottom: 0; 108 | margin-bottom: 9px; 109 | } 110 | .subhead h1 { 111 | font-size: 54px; 112 | } 113 | 114 | /* Subnav */ 115 | .subnav { 116 | width: 100%; 117 | height: 36px; 118 | background-color: #eeeeee; /* Old browsers */ 119 | background-repeat: repeat-x; /* Repeat the gradient */ 120 | background-image: -moz-linear-gradient(top, #f5f5f5 0%, #eeeeee 100%); /* FF3.6+ */ 121 | background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#f5f5f5), color-stop(100%,#eeeeee)); /* Chrome,Safari4+ */ 122 | background-image: -webkit-linear-gradient(top, #f5f5f5 0%,#eeeeee 100%); /* Chrome 10+,Safari 5.1+ */ 123 | background-image: -ms-linear-gradient(top, #f5f5f5 0%,#eeeeee 100%); /* IE10+ */ 124 | background-image: -o-linear-gradient(top, #f5f5f5 0%,#eeeeee 100%); /* Opera 11.10+ */ 125 | filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#f5f5f5', endColorstr='#eeeeee',GradientType=0 ); /* IE6-9 */ 126 | background-image: linear-gradient(top, #f5f5f5 0%,#eeeeee 100%); /* W3C */ 127 | border: 1px solid #e5e5e5; 128 | -webkit-border-radius: 4px; 129 | -moz-border-radius: 4px; 130 | border-radius: 4px; 131 | } 132 | .subnav .nav { 133 | margin-bottom: 0; 134 | } 135 | .subnav .nav > li > a { 136 | margin: 0; 137 | padding-top: 11px; 138 | padding-bottom: 11px; 139 | border-left: 1px solid #f5f5f5; 140 | border-right: 1px solid #e5e5e5; 141 | -webkit-border-radius: 0; 142 | -moz-border-radius: 0; 143 | border-radius: 0; 144 | } 145 | .subnav .nav > .active > a, 146 | .subnav .nav > .active > a:hover { 147 | padding-left: 13px; 148 | color: #777; 149 | background-color: #e9e9e9; 150 | border-right-color: #ddd; 151 | border-left: 0; 152 | -webkit-box-shadow: inset 0 3px 5px rgba(0,0,0,.05); 153 | -moz-box-shadow: inset 0 3px 5px rgba(0,0,0,.05); 154 | box-shadow: inset 0 3px 5px rgba(0,0,0,.05); 155 | } 156 | .subnav .nav > .active > a .caret, 157 | .subnav .nav > .active > a:hover .caret { 158 | border-top-color: #777; 159 | } 160 | .subnav .nav > li:first-child > a, 161 | .subnav .nav > li:first-child > a:hover { 162 | border-left: 0; 163 | padding-left: 12px; 164 | -webkit-border-radius: 4px 0 0 4px; 165 | -moz-border-radius: 4px 0 0 4px; 166 | border-radius: 4px 0 0 4px; 167 | } 168 | .subnav .nav > li:last-child > a { 169 | border-right: 0; 170 | } 171 | .subnav .dropdown-menu { 172 | -webkit-border-radius: 0 0 4px 4px; 173 | -moz-border-radius: 0 0 4px 4px; 174 | border-radius: 0 0 4px 4px; 175 | } 176 | 177 | /* Fixed subnav on scroll, but only for 980px and up (sorry IE!) */ 178 | @media (min-width: 980px) { 179 | .subnav-fixed { 180 | position: fixed; 181 | top: 40px; 182 | left: 0; 183 | right: 0; 184 | z-index: 1020; /* 10 less than .navbar-fixed to prevent any overlap */ 185 | border-color: #d5d5d5; 186 | border-width: 0 0 1px; /* drop the border on the fixed edges */ 187 | -webkit-border-radius: 0; 188 | -moz-border-radius: 0; 189 | border-radius: 0; 190 | -webkit-box-shadow: inset 0 1px 0 #fff, 0 1px 5px rgba(0,0,0,.1); 191 | -moz-box-shadow: inset 0 1px 0 #fff, 0 1px 5px rgba(0,0,0,.1); 192 | box-shadow: inset 0 1px 0 #fff, 0 1px 5px rgba(0,0,0,.1); 193 | filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); /* IE6-9 */ 194 | } 195 | .subnav-fixed .nav { 196 | width: 938px; 197 | margin: 0 auto; 198 | padding: 0 1px; 199 | } 200 | .subnav .nav > li:first-child > a, 201 | .subnav .nav > li:first-child > a:hover { 202 | -webkit-border-radius: 0; 203 | -moz-border-radius: 0; 204 | border-radius: 0; 205 | } 206 | } 207 | 208 | 209 | /* Quick links 210 | -------------------------------------------------- */ 211 | .quick-links { 212 | min-height: 30px; 213 | padding: 5px 20px; 214 | margin: 36px 0; 215 | list-style: none; 216 | text-align: center; 217 | overflow: hidden; 218 | } 219 | .quick-links li { 220 | display: inline; 221 | margin: 0 5px; 222 | color: #999; 223 | } 224 | .quick-links .github-btn, 225 | .quick-links .tweet-btn, 226 | .quick-links .follow-btn { 227 | position: relative; 228 | top: 5px; 229 | } 230 | 231 | 232 | /* Marketing section of Overview 233 | -------------------------------------------------- */ 234 | .marketing .row { 235 | margin-bottom: 9px; 236 | } 237 | .marketing h1 { 238 | margin: 36px 0 27px; 239 | font-size: 40px; 240 | font-weight: 300; 241 | text-align: center; 242 | } 243 | .marketing h2, 244 | .marketing h3 { 245 | font-weight: 300; 246 | } 247 | .marketing h2 { 248 | font-size: 22px; 249 | } 250 | .marketing p { 251 | margin-right: 10px; 252 | } 253 | .marketing .bs-icon { 254 | float: left; 255 | margin: 7px 10px 0 0; 256 | opacity: .8; 257 | } 258 | .marketing .small-bs-icon { 259 | float: left; 260 | margin: 4px 5px 0 0; 261 | } 262 | 263 | 264 | 265 | /* Footer 266 | -------------------------------------------------- */ 267 | .footer { 268 | margin-top: 45px; 269 | padding: 35px 0 36px; 270 | border-top: 1px solid #e5e5e5; 271 | } 272 | .footer p { 273 | margin-bottom: 0; 274 | color: #555; 275 | } 276 | 277 | 278 | 279 | /* Special grid styles 280 | -------------------------------------------------- */ 281 | .show-grid { 282 | margin-top: 10px; 283 | margin-bottom: 20px; 284 | } 285 | .show-grid [class*="span"] { 286 | background-color: #eee; 287 | text-align: center; 288 | -webkit-border-radius: 3px; 289 | -moz-border-radius: 3px; 290 | border-radius: 3px; 291 | min-height: 30px; 292 | line-height: 30px; 293 | } 294 | .show-grid:hover [class*="span"] { 295 | background: #ddd; 296 | } 297 | .show-grid .show-grid { 298 | margin-top: 0; 299 | margin-bottom: 0; 300 | } 301 | .show-grid .show-grid [class*="span"] { 302 | background-color: #ccc; 303 | } 304 | 305 | 306 | /* Render mini layout previews 307 | -------------------------------------------------- */ 308 | .mini-layout { 309 | border: 1px solid #ddd; 310 | -webkit-border-radius: 6px; 311 | -moz-border-radius: 6px; 312 | border-radius: 6px; 313 | -webkit-box-shadow: 0 1px 2px rgba(0,0,0,.075); 314 | -moz-box-shadow: 0 1px 2px rgba(0,0,0,.075); 315 | box-shadow: 0 1px 2px rgba(0,0,0,.075); 316 | } 317 | .mini-layout { 318 | height: 240px; 319 | margin-bottom: 20px; 320 | padding: 9px; 321 | } 322 | .mini-layout div { 323 | -webkit-border-radius: 3px; 324 | -moz-border-radius: 3px; 325 | border-radius: 3px; 326 | } 327 | .mini-layout .mini-layout-body { 328 | background-color: #dceaf4; 329 | margin: 0 auto; 330 | width: 70%; 331 | height: 240px; 332 | } 333 | .mini-layout.fluid .mini-layout-sidebar, 334 | .mini-layout.fluid .mini-layout-header, 335 | .mini-layout.fluid .mini-layout-body { 336 | float: left; 337 | } 338 | .mini-layout.fluid .mini-layout-sidebar { 339 | background-color: #bbd8e9; 340 | width: 20%; 341 | height: 240px; 342 | } 343 | .mini-layout.fluid .mini-layout-body { 344 | width: 77.5%; 345 | margin-left: 2.5%; 346 | } 347 | 348 | 349 | /* Popover docs 350 | -------------------------------------------------- */ 351 | .popover-well { 352 | min-height: 160px; 353 | } 354 | .popover-well .popover { 355 | display: block; 356 | } 357 | .popover-well .popover-wrapper { 358 | width: 50%; 359 | height: 160px; 360 | float: left; 361 | margin-left: 55px; 362 | position: relative; 363 | } 364 | .popover-well .popover-menu-wrapper { 365 | height: 80px; 366 | } 367 | .large-bird { 368 | margin: 5px 0 0 310px; 369 | opacity: .1; 370 | } 371 | 372 | 373 | /* Download page 374 | -------------------------------------------------- */ 375 | .download .page-header { 376 | margin-top: 36px; 377 | } 378 | .page-header .toggle-all { 379 | margin-top: 5px; 380 | } 381 | 382 | /* Space out h3s when following a section */ 383 | .download h3 { 384 | margin-bottom: 5px; 385 | } 386 | .download-builder input + h3, 387 | .download-builder .checkbox + h3 { 388 | margin-top: 9px; 389 | } 390 | 391 | /* Fields for variables */ 392 | .download-builder input[type=text] { 393 | margin-bottom: 9px; 394 | font-family: Menlo, Monaco, "Courier New", monospace; 395 | font-size: 12px; 396 | color: #d14; 397 | } 398 | .download-builder input[type=text]:focus { 399 | background-color: #fff; 400 | } 401 | 402 | /* Custom, larger checkbox labels */ 403 | .download .checkbox { 404 | padding: 6px 10px 6px 25px; 405 | color: #555; 406 | background-color: #f9f9f9; 407 | -webkit-border-radius: 3px; 408 | -moz-border-radius: 3px; 409 | border-radius: 3px; 410 | cursor: pointer; 411 | } 412 | .download .checkbox:hover { 413 | color: #333; 414 | background-color: #f5f5f5; 415 | } 416 | .download .checkbox small { 417 | font-size: 12px; 418 | color: #777; 419 | } 420 | 421 | /* Variables section */ 422 | #variables label { 423 | margin-bottom: 0; 424 | } 425 | 426 | /* Giant download button */ 427 | .download-btn { 428 | margin: 36px 0 108px; 429 | } 430 | .download p, 431 | .download h4 { 432 | max-width: 50%; 433 | margin: 0 auto; 434 | color: #999; 435 | text-align: center; 436 | } 437 | .download h4 { 438 | margin-bottom: 0; 439 | } 440 | .download p { 441 | margin-bottom: 18px; 442 | } 443 | .download-btn .btn { 444 | display: block; 445 | width: auto; 446 | padding: 19px 24px; 447 | margin-bottom: 27px; 448 | font-size: 30px; 449 | line-height: 1; 450 | text-align: center; 451 | -webkit-border-radius: 6px; 452 | -moz-border-radius: 6px; 453 | border-radius: 6px; 454 | } 455 | 456 | 457 | 458 | /* Color swatches on LESS docs page 459 | -------------------------------------------------- */ 460 | /* Sets the width of the td */ 461 | .swatch-col { 462 | width: 30px; 463 | } 464 | /* Le swatch */ 465 | .swatch { 466 | display: inline-block; 467 | width: 30px; 468 | height: 20px; 469 | margin: -6px 0; 470 | -webkit-border-radius: 3px; 471 | -moz-border-radius: 3px; 472 | border-radius: 3px; 473 | } 474 | /* For white swatches, give a border */ 475 | .swatch-bordered { 476 | width: 28px; 477 | height: 18px; 478 | border: 1px solid #eee; 479 | } 480 | 481 | 482 | /* Misc 483 | -------------------------------------------------- */ 484 | 485 | 486 | .browser-support { 487 | max-width: 100%; 488 | } 489 | 490 | /* Make tables spaced out a bit more */ 491 | h2 + table, 492 | h3 + table, 493 | h4 + table, 494 | h2 + .row { 495 | margin-top: 5px; 496 | } 497 | 498 | /* Example sites showcase */ 499 | .example-sites img { 500 | max-width: 100%; 501 | margin: 0 auto; 502 | } 503 | .marketing-byline { 504 | margin: -18px 0 27px; 505 | font-size: 18px; 506 | font-weight: 300; 507 | line-height: 24px; 508 | color: #999; 509 | text-align: center; 510 | } 511 | 512 | .scrollspy-example { 513 | height: 200px; 514 | overflow: auto; 515 | position: relative; 516 | } 517 | 518 | /* Remove bottom margin on example forms in wells */ 519 | form.well { 520 | padding: 14px; 521 | } 522 | 523 | /* Tighten up spacing */ 524 | .well hr { 525 | margin: 18px 0; 526 | } 527 | 528 | /* Fake the :focus state to demo it */ 529 | .focused { 530 | border-color: rgba(82,168,236,.8); 531 | -webkit-box-shadow: inset 0 1px 3px rgba(0,0,0,.1), 0 0 8px rgba(82,168,236,.6); 532 | -moz-box-shadow: inset 0 1px 3px rgba(0,0,0,.1), 0 0 8px rgba(82,168,236,.6); 533 | box-shadow: inset 0 1px 3px rgba(0,0,0,.1), 0 0 8px rgba(82,168,236,.6); 534 | outline: 0; 535 | } 536 | 537 | /* For input sizes, make them display block */ 538 | .docs-input-sizes select, 539 | .docs-input-sizes input[type=text] { 540 | display: block; 541 | margin-bottom: 9px; 542 | } 543 | 544 | /* Icons 545 | ------------------------- */ 546 | .the-icons { 547 | margin-left: 0; 548 | list-style: none; 549 | } 550 | .the-icons i:hover { 551 | background-color: rgba(255,0,0,.25); 552 | } 553 | 554 | /* Eaxmples page 555 | ------------------------- */ 556 | .bootstrap-examples .thumbnail { 557 | margin-bottom: 9px; 558 | background-color: #fff; 559 | } 560 | 561 | 562 | /* Responsive Docs 563 | -------------------------------------------------- */ 564 | @media (max-width: 480px) { 565 | 566 | /* Reduce padding above jumbotron */ 567 | body { 568 | padding-top: 70px; 569 | } 570 | 571 | /* Change up some type stuff */ 572 | h2 { 573 | margin-top: 27px; 574 | } 575 | h2 small { 576 | display: block; 577 | line-height: 18px; 578 | } 579 | h3 { 580 | margin-top: 18px; 581 | } 582 | 583 | /* Adjust the jumbotron */ 584 | .jumbotron h1, 585 | .jumbotron p { 586 | text-align: center; 587 | margin-right: 0; 588 | } 589 | .jumbotron h1 { 590 | font-size: 45px; 591 | margin-right: 0; 592 | } 593 | .jumbotron p { 594 | margin-right: 0; 595 | margin-left: 0; 596 | font-size: 18px; 597 | line-height: 24px; 598 | } 599 | .jumbotron .btn { 600 | display: block; 601 | font-size: 18px; 602 | padding: 10px 14px; 603 | margin: 0 auto 10px; 604 | } 605 | /* Masthead (home page jumbotron) */ 606 | .masthead { 607 | padding-top: 0; 608 | } 609 | 610 | /* Don't space out quick links so much */ 611 | .quick-links { 612 | margin: 40px 0 0; 613 | } 614 | /* hide the bullets on mobile since our horizontal space is limited */ 615 | .quick-links .divider { 616 | display: none; 617 | } 618 | 619 | /* center example sites */ 620 | .example-sites { 621 | margin-left: 0; 622 | } 623 | .example-sites > li { 624 | float: none; 625 | display: block; 626 | max-width: 280px; 627 | margin: 0 auto 18px; 628 | text-align: center; 629 | } 630 | .example-sites .thumbnail > img { 631 | max-width: 270px; 632 | } 633 | 634 | table code { 635 | white-space: normal; 636 | word-wrap: break-word; 637 | word-break: break-all; 638 | } 639 | 640 | /* Modal example */ 641 | .modal-example .modal { 642 | position: relative; 643 | top: auto; 644 | right: auto; 645 | bottom: auto; 646 | left: auto; 647 | } 648 | 649 | } 650 | 651 | 652 | @media (max-width: 768px) { 653 | 654 | /* Remove any padding from the body */ 655 | body { 656 | padding-top: 0; 657 | } 658 | 659 | /* Jumbotron buttons */ 660 | .jumbotron .btn { 661 | margin-bottom: 10px; 662 | } 663 | 664 | /* Subnav */ 665 | .subnav { 666 | position: static; 667 | top: auto; 668 | z-index: auto; 669 | width: auto; 670 | height: auto; 671 | background: #fff; /* whole background property since we use a background-image for gradient */ 672 | -webkit-box-shadow: none; 673 | -moz-box-shadow: none; 674 | box-shadow: none; 675 | } 676 | .subnav .nav > li { 677 | float: none; 678 | } 679 | .subnav .nav > li > a { 680 | border: 0; 681 | } 682 | .subnav .nav > li + li > a { 683 | border-top: 1px solid #e5e5e5; 684 | } 685 | .subnav .nav > li:first-child > a, 686 | .subnav .nav > li:first-child > a:hover { 687 | -webkit-border-radius: 4px 4px 0 0; 688 | -moz-border-radius: 4px 4px 0 0; 689 | border-radius: 4px 4px 0 0; 690 | } 691 | 692 | /* Popovers */ 693 | .large-bird { 694 | display: none; 695 | } 696 | .popover-well .popover-wrapper { 697 | margin-left: 0; 698 | } 699 | 700 | /* Space out the show-grid examples */ 701 | .show-grid [class*="span"] { 702 | margin-bottom: 5px; 703 | } 704 | 705 | /* Unfloat the back to top link in footer */ 706 | .footer .pull-right { 707 | float: none; 708 | } 709 | .footer p { 710 | margin-bottom: 9px; 711 | } 712 | 713 | } 714 | 715 | 716 | @media (min-width: 480px) and (max-width: 768px) { 717 | 718 | /* Scale down the jumbotron content */ 719 | .jumbotron h1 { 720 | font-size: 54px; 721 | } 722 | .jumbotron p { 723 | margin-right: 0; 724 | margin-left: 0; 725 | } 726 | 727 | } 728 | 729 | 730 | @media (min-width: 768px) and (max-width: 980px) { 731 | 732 | /* Remove any padding from the body */ 733 | body { 734 | padding-top: 0; 735 | } 736 | 737 | /* Scale down the jumbotron content */ 738 | .jumbotron h1 { 739 | font-size: 72px; 740 | } 741 | 742 | } 743 | 744 | 745 | @media (max-width: 980px) { 746 | 747 | /* Unfloat brand */ 748 | .navbar-fixed-top .brand { 749 | float: left; 750 | margin-left: 0; 751 | padding-left: 10px; 752 | padding-right: 10px; 753 | } 754 | 755 | /* Inline-block quick links for more spacing */ 756 | .quick-links li { 757 | display: inline-block; 758 | margin: 5px; 759 | } 760 | 761 | } 762 | 763 | 764 | /* LARGE DESKTOP SCREENS */ 765 | @media (min-width: 1210px) { 766 | 767 | /* Update subnav container */ 768 | .subnav-fixed .nav { 769 | width: 1168px; /* 2px less to account for left/right borders being removed when in fixed mode */ 770 | } 771 | 772 | } 773 | -------------------------------------------------------------------------------- /viewer/static/feed-icon-14x14.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apenwarr/gitbuilder/6d270befbf7dcbaeb283bf1769849a1ffaecb077/viewer/static/feed-icon-14x14.png -------------------------------------------------------------------------------- /viewer/static/feed-icon-28x28.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apenwarr/gitbuilder/6d270befbf7dcbaeb283bf1769849a1ffaecb077/viewer/static/feed-icon-28x28.png -------------------------------------------------------------------------------- /viewer/static/grid-18px-masked.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apenwarr/gitbuilder/6d270befbf7dcbaeb283bf1769849a1ffaecb077/viewer/static/grid-18px-masked.png -------------------------------------------------------------------------------- /viewer/static/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0.5em; 3 | padding: 0em; 4 | border: 1px solid white; 5 | } 6 | 7 | h1 { 8 | margin-top: 15pt; 9 | } 10 | 11 | div.logo { 12 | float: right; 13 | font-family: Times New Roman, Times, serif; 14 | color: #aaaaaa; 15 | margin: 0px; 16 | margin-top: 15pt; 17 | padding: 0px; 18 | text-align: right; 19 | } 20 | div.logo a { 21 | color: #888888; 22 | } 23 | 24 | div.extraspace { 25 | padding-bottom: 2in; 26 | } 27 | 28 | #most_recent { 29 | position: fixed; 30 | right: -1px; 31 | top: -1px; 32 | background: white; 33 | overflow: hidden; 34 | font-size: 10pt; 35 | width: 100%; 36 | height: 15pt; 37 | text-align: right; 38 | white-space: nowrap; 39 | } 40 | #most_recent ul { 41 | display: inline; 42 | margin: 0px; 43 | padding-left: 1em; 44 | font-size: 10pt; 45 | list-style-type: none; 46 | } 47 | #most_recent ul li { 48 | display: inline; 49 | margin-right: 0.5em; 50 | } 51 | 52 | table.results th { 53 | padding-right: 0.5em; 54 | padding-left: 0.5em; 55 | text-align: left; 56 | font-weight: bold; 57 | color: #666666; 58 | padding-bottom: 0.5em; 59 | } 60 | 61 | td { 62 | padding-right: 0.5em; 63 | padding-left: 0.5em; 64 | } 65 | 66 | table.results a { 67 | text-decoration: none; 68 | } 69 | a.hyper { 70 | float: left; 71 | display: block; 72 | padding: 0px; 73 | margin: 0px; 74 | padding-top: 15pt; 75 | margin-top: -15pt; 76 | width: 0px; 77 | height: 0px; 78 | } 79 | 80 | table.results a:hover { 81 | text-decoration: underline; 82 | } 83 | 84 | table.results td.loglink { 85 | background: white; 86 | visibility: hidden; 87 | white-space: nowrap; 88 | font-size: smaller; 89 | } 90 | 91 | table.results td.details { 92 | padding-left: 2em; 93 | text-indent: -2em; 94 | } 95 | 96 | .branch { 97 | color: #666666; 98 | text-align: right; 99 | } 100 | .branch b { 101 | color: black; 102 | font-weight: normal; 103 | } 104 | 105 | td.status { 106 | text-align: center; 107 | } 108 | span.status:hover { 109 | text-decoration: underline; 110 | } 111 | .status-ok { 112 | background: #ccffcc; 113 | } 114 | .status-warn { 115 | background: #ffffcc; 116 | } 117 | .status-err { 118 | background: #ffcccc; 119 | } 120 | td.status-warn, td.status-err { 121 | font-weight: bold; 122 | } 123 | 124 | td.committer { 125 | color: #666666; 126 | } 127 | 128 | span.codestr { 129 | color: black; 130 | } 131 | 132 | span.comment { 133 | color: #666666; 134 | font-size: small; 135 | } 136 | 137 | tr.spacer td { 138 | padding: 0.5em; 139 | } 140 | 141 | img { 142 | border: 0px; 143 | } 144 | 145 | -------------------------------------------------------------------------------- /viewer/static/log.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0.5em; 3 | padding: 0em; 4 | border: 1px solid white; 5 | } 6 | 7 | h1 { 8 | font-family: serif; 9 | font-weight: normal; 10 | } 11 | 12 | .debug, .warning, .error, .fatal { 13 | white-space: pre; 14 | font-family: monospace; 15 | } 16 | 17 | .warning ul, .error ul, .fatal ul { 18 | white-space: pre; 19 | font-weight: bold; 20 | } 21 | 22 | .hint, .warning { 23 | background: #ffff88; 24 | } 25 | 26 | .error, .fatal { 27 | background: #ffdddd; 28 | } 29 | 30 | .buildscript { 31 | color: green; 32 | font-weight: bold; 33 | } 34 | 35 | .redo, .msbuild { 36 | white-space: pre; 37 | font-family: monospace; 38 | font-weight: bold; 39 | } 40 | --------------------------------------------------------------------------------