text:
#ifndef _CRT_SECURE_NO_WARNING
#define _CRT_SECURE_NO_WARNING // C-style memmove
#endif

#include "sn_CommonHeader.h"
#include "sn_Builtin.hpp"
#include "sn_Log.hpp"
#include "sn_Thread.hpp"

namespace sn_Stream {

	namespace stream {
		using sn_Builtin::reference_counter::IR_ptr;
		using sn_Builtin::reference_counter::IWR_ptr;
		using std::min;
		using std::max;
		enum class seek_t {
			begin, current, end,
		};

		//TODO: deal with offset overflow;
		class IStream : public sn_Builtin::reference_counter::IReferenceCounter {
		public:
			enum {
				defaultCopyBufferSize = 1024,
			};

			using len_t = uint64_t;
			using byte_t = uint8_t;
			using byteptr_t = observer_ptr<byte_t>;
			using length_type = uint64_t;
			using byte_type = uint8_t;

			virtual ~IStream() {}

			virtual bool can_write() const = 0;
			virtual bool can_read() const = 0;
			virtual bool can_resize() const = 0;
			virtual bool can_seek() const = 0;
			virtual bool is_end_of_stream() const = 0;
			virtual len_t get_size() const = 0;
			virtual void set_size(len_t) = 0;
			virtual len_t get_position() const = 0;
			virtual void set_position(seek_t origin, len_t offset) = 0;
			virtual void flush() = 0;

			virtual len_t read_bytes(byteptr_t data, len_t length) = 0;
			virtual len_t write_bytes(const byteptr_t data, len_t length) = 0;

			virtual byte_t read_byte() {
				byte_t byte;
				if (read_bytes(&byte, 1) == 1)
					return byte;
				SN_LOG_ERROR_WITH_THROW("Unable to read byte.");
			}

			virtual void force_read_bytes(byteptr_t data, len_t length) {
				len_t total_bytes_len{ 0 };
				do {
					const auto current_bytes_len = read_bytes(data + total_bytes_len, length - total_bytes_len);
					if (!current_bytes_len)
						SN_LOG_ERROR_WITH_THROW("Unexpected end of stream");
					total_bytes_len += current_bytes_len;
				} while (total_bytes_len < length);
			}

			virtual std::future<len_t> read_bytes_async(byteptr_t data, len_t length) {
				return std::async(std::launch::async, [=] {
					return read_bytes(data, length);
				});
			}

			virtual void write_byte(byte_t byte) {
				if (write_bytes(&byte, 1) != 1)
					SN_LOG_ERROR_WITH_THROW("Unable to write byte.");
			}

			virtual void force_write_bytes(const byteptr_t data, len_t length) {
				len_t total_bytes_len{ 0 };
				do {
					const auto current_bytes_len = write_bytes(data + total_bytes_len, length - total_bytes_len);
					if (!current_bytes_len)
						SN_LOG_ERROR_WITH_THROW("Unexpected end of stream");
					total_bytes_len += current_bytes_len;
				} while (total_bytes_len < length);
			}

			virtual std::future<len_t> write_bytes_async(const byteptr_t data, len_t length) {
				return std::async(std::launch::async, [=] {
					return write_bytes(data, length);
				});
			}

			virtual len_t copy_to(const IR_ptr<IStream> rhs) {
				assert(rhs && "Copy source should be not nullptr");

				byte_t buffer[defaultCopyBufferSize];
				len_t read_bytes_len{ 0 }, total_bytes_len{ 0 };
				while (true) {
					read_bytes_len = read_bytes(buffer, sizeof(buffer));
					total_bytes_len += read_bytes_len;
					if (!read_bytes_len)
						break;
					rhs->write_bytes(buffer, read_bytes_len);
				}
				return total_bytes_len;
			}
		};

		class StreamSpan : public sn_Builtin::reference_counter::ReferenceCounter<IStream> {
		public:
			StreamSpan(IR_ptr<IStream> stream, len_t start_pos, len_t end_pos) : m_internalStream{ stream }, m_startPos{ start_pos }, m_endPos{ end_pos }, m_currentPos{ start_pos } {
				if (!m_internalStream->can_seek())
					SN_LOG_ERROR_WTL(sn_Error::InvalidArgs, "Should be seekable stream.");
				if (start_pos > end_pos)
					SN_LOG_ERROR_WTL(sn_Error::OutofRange, "Start position should have operator<= with end position");
				if (m_internalStream->get_size() < end_pos)
					SN_LOG_ERROR_WTL(sn_Error::OutofRange, "Stream size should be less than end position");
				m_internalStream->set_position(seek_t::begin, start_pos);
			}
			~StreamSpan() {}

			IR_ptr<IStream> get_underlying_stream() const noexcept {
				return m_internalStream;
			}

			bool can_write() const {
				return m_internalStream->can_write();
			}

			bool can_read() const {
				return m_internalStream->can_read();
			}

			bool can_seek() const {
				return m_internalStream->can_seek();
			}

			bool can_resize() const {
				return m_internalStream->can_resize();
			}

			bool is_end_of_stream() const {
				return m_internalStream->is_end_of_stream();
			}

			len_t get_size() const {
				return m_endPos - m_startPos;
			}

			void set_size(len_t size) const {
				SN_LOG_ERROR_WTL(sn_Error::NotSupported, "Span of stream can't set size.");
			}

			len_t get_position() const {
				return m_currentPos;
			}

			len_t get_seek_position(seek_t origin) const {
				switch (origin) {
				case seek_t::begin:
					return m_startPos;
					break;
				case seek_t::current:
					return m_currentPos;
					break;
				case seek_t::end:
					return m_endPos;
					break;
				default:
					SN_LOG_ERROR_WTL(sn_Error::InvalidArgs, "Invalid seek argument.");
				}
			}

			void set_position(seek_t origin, len_t offset) {
				len_t pos{ 0 };
				pos = get_seek_position(origin) + offset;
				if (pos < m_startPos || pos > m_endPos)
					SN_LOG_ERROR_WTL(sn_Error::OutofRange, "Position out of range");
				m_currentPos = pos;
				adjust_position();
			}

			byte_t read_byte() {
				if (!m_internalStream->can_read())
					SN_LOG_ERROR_WTL(sn_Error::NotSupported, "Underlying stream cannot read.");
				if (m_currentPos >= m_endPos)
					SN_LOG_ERROR_WTL(sn_Error::OutofRange, "Reaches the end of stream.");
				adjust_position();
				return m_internalStream->read_byte();
			}

			len_t read_bytes(byteptr_t data, len_t length) {
				if (!m_internalStream->can_read())
					SN_LOG_ERROR_WTL(sn_Error::NotSupported, "Underlying stream cannot read.");
				const auto can_read_len = std::min(length, m_endPos - m_startPos);
				adjust_position();
				return m_internalStream->read_bytes(data, can_read_len);
			}

			std::future<len_t> read_bytes_async(byteptr_t data, len_t length) {
				if (!m_internalStream->can_read())
					SN_LOG_ERROR_WTL(sn_Error::NotSupported, "Underlying stream cannot read.");
				const auto can_read_len = std::min(length, m_endPos - m_startPos);
				adjust_position();
				return m_internalStream->read_bytes_async(data, can_read_len);
			}

			void write_byte(byte_t byte) {
				if (!m_internalStream->can_write())
					SN_LOG_ERROR_WTL(sn_Error::NotSupported, "Underlying stream cannot write.");
				if (m_currentPos >= m_endPos)
					SN_LOG_ERROR_WTL(sn_Error::OutofRange, "Reaches the end of stream.");
				adjust_position();
				m_internalStream->write_byte(byte);
			}

			len_t write_bytes(const byteptr_t data, len_t length) {
				if (!m_internalStream->can_write())
					SN_LOG_ERROR_WTL(sn_Error::NotSupported, "Underlying stream cannot write.");
				const auto can_write_len = std::min(length, m_endPos - m_startPos);
				adjust_position();
				return m_internalStream->write_bytes(data, can_write_len);
			}

			std::future<len_t> write_bytes_async(const byteptr_t data, len_t length) {
				if (!m_internalStream->can_write())
					SN_LOG_ERROR_WTL(sn_Error::NotSupported, "Underlying stream cannot write.");
				const auto can_write_len = std::min(length, m_endPos - m_startPos);
				adjust_position();
				return m_internalStream->write_bytes_async(data, can_write_len);
			}

			void flush() {
				m_internalStream->flush();
			}

		private:
			const IR_ptr<IStream> m_internalStream;
			const len_t m_startPos;
			const len_t m_endPos;
			len_t m_currentPos;

			void adjust_position() {
				assert(m_currentPos >= m_startPos && m_currentPos <= m_endPos);
				if (m_currentPos == m_internalStream->get_position())
					return;
				//deal with overflow;
				m_internalStream->set_position(seek_t::begin, m_currentPos);
			}

			void check_position() {
				if (m_currentPos < m_startPos || m_currentPos > m_endPos)
					SN_LOG_ERROR_WTL(sn_Error::OutofRange, "Current position is out of range.");
				if (m_currentPos != m_internalStream->get_position())
					SN_LOG_ERROR_WTL(sn_Error::IllegalState, "Current position doesn't equal the real position.");
			}
		};

		class MemoryStream : public sn_Builtin::reference_counter::ReferenceCounter<IStream> {
		public:
			MemoryStream(const byteptr_t data, len_t length, bool readable, bool writable, bool autoresize) noexcept :
				m_data{ nullptr }, m_currentPos{ 0 }, m_size{ 0 }, m_capacity{ 0 },
				m_readable{ readable }, m_writable{ writable }, m_autoResize{ autoresize } {
				reserve(length);
				m_size = length;
				if (data)
					std::memmove(m_data, data, static_cast<std::size_t>(length));
			}
			MemoryStream(len_t length, bool readable, bool writable, bool autoresize) noexcept : MemoryStream(nullptr, length, readable, writable, autoresize) {}

			MemoryStream(const MemoryStream& rhs) noexcept : MemoryStream(nullptr, 0, false, false, false) {
				*this = rhs;
			}
			MemoryStream& operator=(const MemoryStream& rhs) noexcept {
				if (this == &rhs)
					return *this;
				std::lock_guard<std::recursive_mutex> self_lock{ m_mutex };
				std::lock_guard<std::recursive_mutex> rhs_lock{ rhs.m_mutex };

				if (rhs.m_size >= m_capacity) {
					auto storage = new byte_t[static_cast<std::size_t>(rhs.m_size)];
					std::swap(m_data, storage);
					delete[] storage;
				}

				if (rhs.m_data)
					std::memmove(m_data, rhs.m_data, static_cast<std::size_t>(rhs.m_size));

				m_size = rhs.m_size;
				m_capacity = rhs.m_capacity;
				m_currentPos = rhs.m_currentPos;
				m_readable = rhs.m_readable;
				m_writable = rhs.m_writable;
				m_autoResize = rhs.m_autoResize;

				return *this;
			}
			MemoryStream(const MemoryStream&& rhs) noexcept : MemoryStream(nullptr, 0, false, false, false) {
				*this = std::move(rhs);
			}
			MemoryStream& operator=(MemoryStream&& rhs) noexcept {
				if (this == &rhs)
					return *this;
				std::lock_guard<std::recursive_mutex> self_lock{ m_mutex };
				std::lock_guard<std::recursive_mutex> rhs_lock{ rhs.m_mutex };

				m_data = std::move(rhs.m_data);
				m_size = std::move(rhs.m_size);
				m_capacity = std::move(rhs.m_capacity);
				m_currentPos = std::move(rhs.m_currentPos);
				m_readable = std::move(rhs.m_readable);
				m_writable = std::move(rhs.m_writable);
				m_autoResize = std::move(rhs.m_autoResize);

				return *this;
			}

			MemoryStream(MemoryStream&& rhs) noexcept : MemoryStream(nullptr, 0, false, false, false) {
				*this = std::move(rhs);
			}

			bool can_read() const {
				return m_readable;
			}

			bool can_write() const {
				return m_writable;
			}

			bool can_resize() const {
				return true;
			}

			bool can_seek() const {
				return true;
			}

			bool is_end_of_stream() const {
				return m_currentPos >= m_capacity;
			}

			len_t get_size() const {
				return m_size;
			}

			void set_size(len_t size) {
				reserve(size);
				m_size = size;
				m_currentPos = std::min(m_currentPos, m_size);
			}

			len_t get_position() const {
				return m_currentPos;
			}

			void set_position(seek_t origin, len_t offset) {
				switch (origin) {
				case seek_t::begin:
					if (offset < 0 || m_capacity < offset)
						SN_LOG_ERROR_WTL(sn_Error::OutofRange, "Position out of range.");
					m_currentPos = offset;
					break;
				case seek_t::current:
					if ((offset < 0 && m_currentPos + offset < 0) || m_capacity < offset + m_currentPos)
						SN_LOG_ERROR_WTL(sn_Error::OutofRange, "Position out of range.");
					m_currentPos = m_currentPos + offset;
					break;
				case seek_t::end:
					if (offset > 0 || (m_capacity + offset < 0))
						SN_LOG_ERROR_WTL(sn_Error::OutofRange, "Position out of range.");
					m_currentPos = m_capacity + offset;
					break;
				default:
					SN_LOG_ERROR_WTL(sn_Error::InvalidArgs, "Invalid seek argument.");
				}
			}

			byte_t read_byte() {
				if (m_currentPos >= m_size)
					SN_LOG_ERROR_WTL(sn_Error::OutofRange, "Current position out of range.");
				return m_data[m_currentPos++];
			}

			len_t read_bytes(byteptr_t data, len_t length) {
				assert(m_data && "Data should not be nullptr.");
				len_t avail_read_len = 0;
				if (!m_readable)
					SN_LOG_ERROR_WTL(sn_Error::IllegalState, "Stream cannot be read");
				if (length == 0)
					return avail_read_len;

				guard_t guard(m_mutex);
				avail_read_len = std::min(length, m_size - m_currentPos);
				memmove(data + m_currentPos, m_data, static_cast<std::size_t>(avail_read_len));
				m_currentPos += avail_read_len;
				return avail_read_len;
			}

			std::future<len_t> read_bytes_async(byteptr_t data, len_t length) {
				return std::async(std::launch::async, [=] {
					return read_bytes(data, length);
				});
			}

			void write_byte(byte_t byte) {
				if (m_size >= m_capacity)
					SN_LOG_ERROR_WTL(sn_Error::OutofRange, "Stream cannot be larger than capacity.");
				if (m_currentPos >= m_capacity)
					SN_LOG_ERROR_WTL(sn_Error::OutofRange, "Reached the end of stream.");
				m_data[m_currentPos++] = byte;
				m_size = std::max(m_currentPos, m_size);
			}

			len_t write_bytes(const byteptr_t data, len_t length) {
				assert(m_data && "Data should not be nullptr.");
				len_t avail_write_len = 0;
				if (!m_writable)
					SN_LOG_ERROR_WTL(sn_Error::IllegalState, "Stream cannot be written");
				if (length == 0)
					return avail_write_len;

				guard_t guard(m_mutex);
				if (length > m_capacity - m_currentPos) {
					if (m_autoResize) {
						reserve(length * 2);
						avail_write_len = length;
					}
					else {
						avail_write_len = m_capacity - m_currentPos;
					}
				}
				memmove(m_data + m_currentPos, data, static_cast<std::size_t>(avail_write_len));
				m_currentPos += avail_write_len;
				m_size = std::max(m_currentPos, m_size);
				return avail_write_len;
			}

			std::future<len_t> write_bytes_async(const byteptr_t data, len_t length) {
				return std::async(std::launch::async, [=] {
					return write_bytes(data, length);
				});
			}

			void flush() {}

			byteptr_t get_internal_buffer() noexcept {
				return m_data;
			}

			const byteptr_t get_internal_buffer() const noexcept {
				return m_data;
			}

			len_t get_capacity() const noexcept {
				return m_capacity;
			}

			~MemoryStream() {
				if (m_data)
					delete[] m_data;
			}

			void reserve(len_t cap) {
				if (cap > 0 && cap <= m_capacity)
					return;
				m_capacity = cap;
				auto storage = new byte_t[static_cast<std::size_t>(cap)];
				const auto deleter = sn_Thread::scope_guard::make_scope([&storage] {
					delete[] storage;
				});

				if (m_size > 0 && m_data)
					std::memmove(storage, m_data, static_cast<std::size_t>(m_size));

				std::swap(m_data, storage);
			}

		private:
			mutable std::recursive_mutex m_mutex;
			using guard_t = std::lock_guard<std::recursive_mutex>;
			byteptr_t m_data;
			len_t m_size;
			len_t m_capacity;
			len_t m_currentPos;
			bool m_readable;
			bool m_writable;
			bool m_autoResize;
		};

		class FixedMemoryStream : public sn_Builtin::reference_counter::ReferenceCounter<IStream> {
		public:

			FixedMemoryStream(byteptr_t data, len_t size, bool readable, bool writable) noexcept : m_data{ data }, m_size{ size }, m_currentPos{ 0 }, m_readable{ readable }, m_writable{ writable } {}
			FixedMemoryStream(const byteptr_t data, len_t size, bool readable) noexcept : m_data{ const_cast<byteptr_t>(data) }, m_size{ size }, m_currentPos{ 0 }, m_readable{ readable }, m_writable{ false } {}

			template <std::size_t N>
			FixedMemoryStream(byte_t(&arr)[N], bool readable, bool writable) noexcept : MemoryStream(arr, N, readable, writable) {}
			template <std::size_t N>
			FixedMemoryStream(byte_t(&arr)[N], bool readable) noexcept : MemoryStream(arr, N, readable) {}

			~FixedMemoryStream() {}

			bool can_read() const {
				return m_readable;
			}

			bool can_write() const {
				return m_writable;
			}

			bool can_resize() const {
				return false;
			}

			bool can_seek() const {
				return true;
			}

			bool is_end_of_stream() const {
				return m_currentPos == m_size;
			}

			len_t get_size() const {
				return m_size;
			}

			void set_size(len_t size) {
				SN_LOG_ERROR_WTL(sn_Error::NotSupported, "Fixed stream cannot set size.");
			}

			len_t get_position() const {
				return m_currentPos;
			}

			void set_position(seek_t origin, len_t offset) {
				switch (origin) {
				case seek_t::begin:
					if (offset < 0 || m_size < offset)
						SN_LOG_ERROR_WTL(sn_Error::OutofRange, "Position out of range.");
					m_currentPos = offset;
					break;
				case seek_t::current:
					if ((offset < 0 && m_currentPos + offset < 0) || m_size < offset + m_currentPos)
						SN_LOG_ERROR_WTL(sn_Error::OutofRange, "Position out of range.");
					m_currentPos = m_currentPos + offset;
					break;
				case seek_t::end:
					if (offset > 0 || (m_size + offset < 0))
						SN_LOG_ERROR_WTL(sn_Error::OutofRange, "Position out of range.");
					m_currentPos = m_size + offset;
					break;
				default:
					SN_LOG_ERROR_WTL(sn_Error::InvalidArgs, "Invalid seek argument.");
				}
			}

			byte_t read_byte() {
				if (m_currentPos >= m_size)
					SN_LOG_ERROR_WTL(sn_Error::OutofRange, "Current position out of range.");
				return m_data[m_currentPos++];
			}

			len_t read_bytes(byteptr_t data, len_t length) {
				assert(m_data && "Data should not be nullptr.");
				len_t avail_read_len = 0;
				if (!m_readable)
					SN_LOG_ERROR_WTL(sn_Error::IllegalState, "Stream cannot be read");
				if (length == 0)
					return avail_read_len;

				avail_read_len = std::min(length, m_size - m_currentPos);
				memmove(data + m_currentPos, m_data, static_cast<std::size_t>(avail_read_len));
				m_currentPos += avail_read_len;
				return avail_read_len;
			}

			std::future<len_t> read_bytes_async(byteptr_t data, len_t length) {
				return std::async(std::launch::async, [=] {
					return read_bytes(data, length);
				});
			}

			void write_byte(byte_t byte) {
				if (m_currentPos >= m_size)
					SN_LOG_ERROR_WTL(sn_Error::OutofRange, "Reached the end of stream.");
				m_data[m_currentPos++] = byte;
			}

			len_t write_bytes(const byteptr_t data, len_t length) {
				assert(m_data && "Data should not be nullptr.");
				len_t avail_write_len = 0;
				if (!m_writable)
					SN_LOG_ERROR_WTL(sn_Error::IllegalState, "Stream cannot be written");
				if (length == 0)
					return avail_write_len;

				avail_write_len = std::min(length, m_size - m_currentPos);
				memmove(m_data + m_currentPos, data, static_cast<std::size_t>(avail_write_len));
				m_currentPos += avail_write_len;
				return avail_write_len;
			}

			std::future<len_t> write_bytes_async(const byteptr_t data, len_t length) {
				return std::async(std::launch::async, [=] {
					return write_bytes(data, length);
				});
			}

			void flush() {}

			byteptr_t get_internal_buffer() noexcept {
				return m_data;
			}

		private:
			const byteptr_t m_data;
			const len_t m_size;
			len_t m_currentPos;
			const bool m_readable;
			const bool m_writable;
		};

		class FileStream : public sn_Builtin::reference_counter::ReferenceCounter<IStream> {
		public:
#if defined(SN_CONFIG_OS_WIN)
		using handle_t = HANDLE;
#else
			using handle_t = int;
#endif

#ifdef _WIN32
			FileStream(std::string filename, bool readable, bool writable, bool isasync = false, bool truncate = false) :
				m_mappedFile{ NULL }, m_dispose{ true }, m_isAsync{ isasync }, m_filename{ filename }, m_readable{ readable }, m_writable{ writable } {
				if (truncate && (readable || !writable))
					SN_LOG_ERROR_WTL(sn_Error::InvalidArgs, "File should be writable and not readable while truncated.");
				m_file = CreateFile(filename.c_str(),
					truncate ? GENERIC_WRITE : ((readable ? GENERIC_READ : 0) | (writable ? GENERIC_WRITE : 0)),
					FILE_SHARE_READ, NULL,
					truncate ? TRUNCATE_EXISTING : (writable ? OPEN_ALWAYS : OPEN_EXISTING),
					FILE_ATTRIBUTE_NORMAL | (isasync ? FILE_FLAG_OVERLAPPED : 0),
					NULL);

				if (!m_file || m_file == INVALID_HANDLE_VALUE)
					SN_LOG_ERROR_WTL(sn_Error::CheckFailed, "Open file failed.");
			}

			FileStream(handle_t handle, bool readable, bool writable, bool transowner, bool isasync) :
				m_file{ handle }, m_mappedFile { NULL }, m_dispose{ transowner }, m_isAsync{ isasync }, m_readable{ readable }, m_writable{ writable } {

				if (!m_file || m_file == INVALID_HANDLE_VALUE)
					SN_LOG_ERROR_WTL(sn_Error::CheckFailed, "Open file failed.");
			}

			len_t get_size() const {
				LARGE_INTEGER tmpSize{};
				if (!GetFileSizeEx(m_file, &tmpSize))
					SN_LOG_ERROR_WTL(sn_Error::CheckFailed, "GetFileSizeEx failed.");
				return static_cast<len_t>(tmpSize.QuadPart);
			}

			void set_size(len_t size) {
				if (!m_writable)
					SN_LOG_ERROR_WTL(sn_Error::IllegalState, "Stream cannot be written.");
				LARGE_INTEGER tVal;
				tVal.QuadPart = size;

				if (SetFilePointer(m_file, tVal.LowPart, &tVal.HighPart, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
					SN_LOG_ERROR_WTL(sn_Error::CheckFailed, "SetFilePointer failed.");
				if (SetEndOfFile(m_file) == FALSE)
					SN_LOG_ERROR_WTL(sn_Error::CheckFailed, "SetEndOfFile failed.");

				set_position(seek_t::begin, 0);
			}

			len_t get_position() const {
				LARGE_INTEGER tVal;
				tVal.QuadPart = 0;

				tVal.LowPart = SetFilePointer(m_file, tVal.LowPart, &tVal.HighPart, FILE_CURRENT);
				return tVal.QuadPart;
			}

			void set_position(seek_t origin, len_t offset) {
				std::size_t tOrigin;
				switch (origin) {
				case seek_t::begin:
					tOrigin = FILE_BEGIN;
					break;
				case seek_t::current:
					tOrigin = FILE_CURRENT;
					break;
				case seek_t::end:
					tOrigin = FILE_END;
					break;
				default:
					SN_LOG_ERROR_WTL(sn_Error::InvalidArgs, "Invalid origin.");
				}

				LARGE_INTEGER tVal;
				tVal.QuadPart = offset;

				if (SetFilePointer(m_file, tVal.LowPart, &tVal.HighPart, tOrigin) == INVALID_SET_FILE_POINTER)
					SN_LOG_ERROR_WTL(sn_Error::CheckFailed, "SetFilePointer failed.");
			}

			bool is_end_of_stream() const {
				return get_size() == get_position();
			}

			// data should be pre-allocated, byteptr_t data = new byte_t[size];
			len_t read_bytes(byteptr_t data, len_t length) {
				if (m_isAsync)
					return read_bytes_async(data, length).get();

				DWORD avail_read_len = 0;
				if (!m_readable)
					SN_LOG_ERROR_WTL(sn_Error::IllegalState, "Stream cannot be read");
				if (length == 0)
					return avail_read_len;
				if (data == nullptr)
					SN_LOG_ERROR_WTL(sn_Error::InvalidArgs, "Data cannot be nullptr.");

				if (FALSE == ReadFile(m_file, data, static_cast<DWORD>(length), &avail_read_len, NULL))
					SN_LOG_ERROR_WTL(sn_Error::APIFailed, "ReadFile failed.");
				return avail_read_len;
			}

			len_t write_bytes(const byteptr_t data, len_t length) {
				if (m_isAsync)
					return write_bytes_async(data, length).get();

				DWORD avail_write_len = 0;
				if (!m_writable)
					SN_LOG_ERROR_WTL(sn_Error::IllegalState, "Stream cannot be written");
				if (length == 0)
					return avail_write_len;
				if (data == nullptr)
					SN_LOG_ERROR_WTL(sn_Error::InvalidArgs, "Data cannot be nullptr.");

				if (FALSE == WriteFile(m_file, data, static_cast<DWORD>(length), &avail_write_len, NULL))
					SN_LOG_ERROR_WTL(sn_Error::APIFailed, "WriteFile failed.");
				return avail_write_len;
			}

			std::future<len_t> read_bytes_async(byteptr_t data, len_t length) {
				if (m_isAsync) {
					if (!m_readable)
						SN_LOG_ERROR_WTL(sn_Error::IllegalState, "Stream cannot be read");
					if (length == 0) {
						std::promise<len_t> dummy;
						dummy.set_value(0);
						return dummy.get_future();
					}
					if (data == nullptr)
						SN_LOG_ERROR_WTL(sn_Error::InvalidArgs, "Data cannot be nullptr.");

					auto olp = std::make_unique<OVERLAPPED>();

					if (FALSE == ReadFile(m_file, data, static_cast<DWORD>(length), NULL, olp.get())) {
						auto lastError = GetLastError();
						if (lastError != ERROR_IO_PENDING) {
							SN_LOG_ERROR_WTL(sn_Error::APIFailed, "ReadFile failed.");
						}
					}

					return std::async(std::launch::deferred, [olp = move(olp), this]()->len_t {
						DWORD avail_read_len;
						if (!GetOverlappedResult(m_file, olp.get(), &avail_read_len, TRUE))
							SN_LOG_ERROR_WTL(sn_Error::APIFailed, "GetOverlappedResult failed.");
						return avail_read_len;
					});
				}

				return std::async(std::launch::async, [=] {
					return read_bytes(data, length);
				});

			}

			std::future<len_t> write_bytes_async(const byteptr_t data, len_t length) {
				if (m_isAsync) {
					if (!m_writable)
						SN_LOG_ERROR_WTL(sn_Error::IllegalState, "Stream cannot be written");
					if (length == 0) {
						std::promise<len_t> dummy;
						dummy.set_value(0);
						return dummy.get_future();
					}
					if (data == nullptr)
						SN_LOG_ERROR_WTL(sn_Error::InvalidArgs, "Data cannot be nullptr.");

					auto olp = std::make_unique<OVERLAPPED>();

					if (FALSE == WriteFile(m_file, data, static_cast<DWORD>(length), NULL, olp.get())) {
						auto lastError = GetLastError();
						if (lastError != ERROR_IO_PENDING) {
							SN_LOG_ERROR_WTL(sn_Error::APIFailed, "ReadFile failed.");
						}
					}

					return std::async(std::launch::deferred, [olp = move(olp), this]()->len_t {
						DWORD avail_write_len;
						if (!GetOverlappedResult(m_file, olp.get(), &avail_write_len, TRUE))
							SN_LOG_ERROR_WTL(sn_Error::APIFailed, "GetOverlappedResult failed.");
						return avail_write_len;
					});
				}

				return std::async(std::launch::async, [=] {
					return write_bytes(data, length);
				});

			}

			void flush() {
				if (m_mappedStream)
					FlushViewOfFile(m_mappedStream->get_internal_buffer(), static_cast<SIZE_T>(get_size()));
				FlushFileBuffers(m_file);
			}

			IR_ptr<FixedMemoryStream> map_to_memory_stream() {
				if (m_mappedStream)
					return m_mappedStream;
				m_mappedFile = CreateFileMapping(m_file, NULL,
					m_writable ? PAGE_READWRITE : PAGE_READONLY,
					0, 0, NULL);
				if (!m_mappedFile || m_mappedFile == INVALID_HANDLE_VALUE)
					SN_LOG_ERROR_WTL(sn_Error::APIFailed, "CreateFileMapping failed.");

				auto pFile = MapViewOfFile(m_mappedFile,
					(m_readable ? FILE_MAP_READ : 0) | (m_writable ? FILE_MAP_WRITE : 0),
					0, 0, 0);
				if (!pFile)
					SN_LOG_ERROR_WTL(sn_Error::APIFailed, "MapViewOfFile failed.");

				m_mappedStream = sn_Builtin::reference_counter::make_ref_ptr<FixedMemoryStream>(static_cast<byteptr_t>(pFile), get_size(), m_readable, m_writable);

				return m_mappedStream;
			}

			~FileStream() {
				CloseHandle(m_mappedFile);
				if (m_dispose)
					CloseHandle(m_file);
			}
#else
			FileStream(std::string filename, bool readable, bool writable, bool truncate) :
				m_file{}, m_dispose{ true }, m_isEndOfFile{}, m_filename{ filename }, m_readable{ readable }, m_writable{ writable } {
				int mode = 0;
				if (readable && writable)
					mode = O_RDWR;
				else if (readable)
					mode = O_RDONLY;
				else
					mode = O_WRONLY | O_CREAT;

				if (truncate)
					mode |= O_TRUNC;

				m_file = open(filename.c_str(), mode, S_IRWXU | S_IRWXG | S_IRWXO);
				if (!m_file)
					SN_LOG_ERROR_WTL(sn_Error::InternalError, "Cannot open file.");
			}

			bool is_end_of_stream() const {
				return m_isEndOfFile;
			}

			len_t get_size() const {
				const auto currentPos = lseek(m_file, 0, SEEK_CUR);
				lseek(m_file, 0, SEEK_SET);
				const auto beginPos = lseek(m_file, 0, SEEK_CUR);
				lseek(m_file, 0, SEEK_END);
				const auto totalSize = lseek(m_file, 0, SEEK_CUR) - beginPos;
				lseek(m_file, currentPos, SEEK_SET);
				return static_cast<len_t>(totalSize);
			}

			void set_size(len_t size) {
				if (!m_writable)
					SN_LOG_ERROR_WTL(sn_Error::IllegalState, "Stream cannot be writtern.");
				if (ftruncate(m_file, static_cast<off_t>(size)))
					SN_LOG_ERROR_WTL(sn_Error::APIFailed, sn_Log::logstream::Fmt("ftruncate failed (errno = %d).", errno));
			}

			len_t get_position() const {
				return static_cast<len_t>(lseek(m_file, 0, SEEK_CUR));
			}

			void set_position(seek_t origin, len_t offset) {
				int tOrigin;
				switch (origin) {
				case seek_t::begin:
					tOrigin = SEEK_SET;
					break;
				case seek_t::current:
					tOrigin = SEEK_CUR;
					break;
				case seek_t::end:
					tOrigin = SEEK_END;
					break;
				default:
					SN_LOG_ERROR_WTL(sn_Error::InvalidArgs, "Invalid origin.");
				}
				lseek(m_file, static_cast<off_t>(offset), tOrigin);
			}

			len_t read_bytes(byteptr_t data, len_t length) {
				if (!m_readable)
					SN_LOG_ERROR_WTL(sn_Error::IllegalState, "Stream cannot be read");
				if (length == 0)
					return 0;
				if (data == nullptr)
					SN_LOG_ERROR_WTL(sn_Error::InvalidArgs, "Data cannot be nullptr.");
				const auto ret = read(m_file, data, static_cast<std::size_t>(length));
				if (ret < 0)
					SN_LOG_ERROR_WTL(sn_Error::APIFailed, "read file failed.");

				m_isEndOfFile = !ret;
				return static_cast<len_t>(ret);
			}

			len_t write_bytes(const byteptr_t data, len_t length) {
				if (!m_writable)
					SN_LOG_ERROR_WTL(sn_Error::IllegalState, "Stream cannot be written");
				if (length == 0)
					return 0;
				if (data == nullptr)
					SN_LOG_ERROR_WTL(sn_Error::InvalidArgs, "Data cannot be nullptr.");
				const auto ret = write(m_file, data, static_cast<std::size_t>(length));
				if (ret < 0)
					SN_LOG_ERROR_WTL(sn_Error::APIFailed, "write file failed.");

				return static_cast<len_t>(ret);
			}

			void flush() {}

			~FileStream() {
				if (m_dispose)
					close(m_file);
			}

#endif
			bool can_write() const {
				return m_writable;
			}

			bool can_read() const {
				return m_readable;
			}

			bool can_resize() const {
				return m_writable;
			}

			bool can_seek() const {
				return true;
			}

			virtual byte_t read_byte() {
				byte_t byte;
				if (read_bytes(&byte, 1) == 1)
					return byte;
				SN_LOG_ERROR_WTL(sn_Error::InternalError, "Unable to read byte.");
			}

			virtual void write_byte(byte_t byte) {
				if (write_bytes(&byte, 1) != 1)
					SN_LOG_ERROR_WTL(sn_Error::InternalError, "Unable to write byte.");
			}

			std::string get_filename() const noexcept {
				return m_filename;
			}

			handle_t get_handle() const noexcept {
				return m_file;
			}

		private:
			handle_t m_file;
			const bool m_dispose;
			std::string m_filename;
			bool m_readable;
			bool m_writable;

#ifdef _WIN32
			handle_t m_mappedFile;
			IR_ptr<FixedMemoryStream> m_mappedStream;
			const bool m_isAsync;
#else
			bool m_isEndOfFile;
#endif

		};

	}

#if defined(SN_CONFIG_OS_LINUX)
	// @ref: https://www.zhihu.com/question/49272859
	// #include <sys/stat.h>
	// #include <sys/mman.h>
	class BufferedInputStream {
		char* buf, *p;
		int file_sz;
		constexpr static const size_t PREFETCH_WORD = 32;
	public:
		BufferedInputStream() {
			int fd = fileno(stdin);
			struct stat sb;
			fstat(fd, &sb);
			file_sz = sb.st_size;
			buf = reinterpret_cast<char*>(mmap(0, file_sz, PROT_READ, MAP_PRIVATE, fd, 0));
			p = buf;
			madvise((void*)buf, file_sz, MADV_WILLNEED || MADV_SEQUENTIAL);
		}

		~BufferedInputStream() {
			madvise((void*)buf, file_sz, MADV_DONTNEED);
			// munmap(buf, file_sz);
		}

		char next() {
			return (p == buf + file_sz || *p == EOF) ? '\0' : *p++;
		}

		void readline(char* line, size_t sz) {
			size_t cnt = 0;
			line[cnt] = EOF;
			while (__builtin_expect(cnt < sz && line[cnt], 1)) {
#if defined(__GNUC__)
				// if (__builtin_expect((cnt % 16) == 0), 0) {
				if (!(cnt % 16)) {
					__builtin_prefetch(&line[cnt + PREFETCH_WORD], 1, 1);
				}
#endif
				line[cnt] = next();
				line[cnt + 1] = next();
				line[cnt + 2] = next();
				line[cnt + 3] = next();
				cnt += 4;
			}
		}
	};

#endif
}

#endif


text:
package org.apache.storm.kafka.trident;

import static org.apache.storm.kafka.spout.KafkaSpoutConfig.FirstPollOffsetStrategy.EARLIEST;

import java.io.Serializable;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;

import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.apache.storm.Config;
import org.apache.storm.StormSubmitter;
import org.apache.storm.generated.AlreadyAliveException;
import org.apache.storm.generated.AuthorizationException;
import org.apache.storm.generated.InvalidTopologyException;
import org.apache.storm.kafka.spout.Func;
import org.apache.storm.kafka.spout.KafkaSpoutConfig;
import org.apache.storm.kafka.spout.KafkaSpoutRetryExponentialBackoff;
import org.apache.storm.kafka.spout.KafkaSpoutRetryExponentialBackoff.TimeInterval;
import org.apache.storm.kafka.spout.KafkaSpoutRetryService;
import org.apache.storm.kafka.spout.trident.KafkaTridentSpoutOpaque;
import org.apache.storm.tuple.Fields;
import org.apache.storm.tuple.Values;

public class TridentKafkaClientWordCountNamedTopics {
    private static final String TOPIC_1 = "test-trident";
    private static final String TOPIC_2 = "test-trident-1";
    private static final String KAFKA_LOCAL_BROKER = "localhost:9092";

    private KafkaTridentSpoutOpaque<String, String> newKafkaTridentSpoutOpaque() {
        return new KafkaTridentSpoutOpaque<>(newKafkaSpoutConfig());
    }

    private static Func<ConsumerRecord<String, String>, List<Object>> JUST_VALUE_FUNC = new JustValueFunc();

    /**
     * Needs to be serializable
     */
    private static class JustValueFunc implements Func<ConsumerRecord<String, String>, List<Object>>, Serializable {
        @Override
        public List<Object> apply(ConsumerRecord<String, String> record) {
            return new Values(record.value());
        }
    }

    protected KafkaSpoutConfig<String,String> newKafkaSpoutConfig() {
        return KafkaSpoutConfig.builder(KAFKA_LOCAL_BROKER, TOPIC_1, TOPIC_2)
                .setGroupId("kafkaSpoutTestGroup_" + System.nanoTime())
                .setMaxPartitionFectchBytes(200)
                .setRecordTranslator(JUST_VALUE_FUNC, new Fields("str"))
                .setRetry(newRetryService())
                .setOffsetCommitPeriodMs(10_000)
                .setFirstPollOffsetStrategy(EARLIEST)
                .setMaxUncommittedOffsets(250)
                .build();
    }

    protected KafkaSpoutRetryService newRetryService() {
        return new KafkaSpoutRetryExponentialBackoff(new TimeInterval(500L, TimeUnit.MICROSECONDS),
                TimeInterval.milliSeconds(2), Integer.MAX_VALUE, TimeInterval.seconds(10));
    }

    public static void main(String[] args) throws Exception {
        new TridentKafkaClientWordCountNamedTopics().run(args);
    }

    protected void run(String[] args) throws AlreadyAliveException, InvalidTopologyException, AuthorizationException, InterruptedException {
        if (args.length > 0 && Arrays.stream(args).anyMatch(option -> option.equals("-h"))) {
            System.out.printf("Usage: java %s [%s] [%s] [%s] [%s]\n", getClass().getName(),
                    "broker_host:broker_port", "topic1", "topic2", "topology_name");
        } else {
            final String brokerUrl = args.length > 0 ? args[0] : KAFKA_LOCAL_BROKER;
            final String topic1 = args.length > 1 ? args[1] : TOPIC_1;
            final String topic2 = args.length > 2 ? args[2] : TOPIC_2;

            System.out.printf("Running with broker_url: [%s], topics: [%s, %s]\n", brokerUrl, topic1, topic2);

            Config tpConf = new Config();
            tpConf.setDebug(true);
            tpConf.setMaxSpoutPending(5);

            // Producers
            StormSubmitter.submitTopology(topic1 + "-producer", tpConf, KafkaProducerTopology.newTopology(brokerUrl, topic1));
            StormSubmitter.submitTopology(topic2 + "-producer", tpConf, KafkaProducerTopology.newTopology(brokerUrl, topic2));
            // Consumer
            StormSubmitter.submitTopology("topics-consumer", tpConf, TridentKafkaConsumerTopology.newTopology(newKafkaTridentSpoutOpaque()));

            // Print results to console, which also causes the print filter in the consumer topology to print the results in the worker log
            Thread.sleep(2000);
            DrpcResultsPrinter.remoteClient().printResults(60, 1, TimeUnit.SECONDS);
        }
        System.exit(0);     // Kill all the non daemon threads
    }
}

redpajama_set_name: RedPajamaGithub


text:
<?php
declare(strict_types = 1);

namespace App\Services\Game\Permissions\LuckPerms\Repository\Player;

use App\Services\Game\Permissions\LuckPerms\Entity\Player;
use Ramsey\Uuid\UuidInterface;

interface PlayerRepository
{
    public function create(Player $player): void;

    public function update(Player $player): void;

    public function deleteAll(): bool;

    public function findByUsername(string $username): ?Player;

    public function findByUuid(UuidInterface $uuid): ?Player;
}


text:
#include "staticelectricdata.h"
#include "staticelectricdb.h"
#include "electric_p.h"
#include "pricedata.h"
#include "elpricedb.h"
#include "electric.h"
#include "macros.h"

Electric::Electric(const DatabaseInfo& info)
    : EnergySource()
    , d_ptr(new ElectricP)
{
    d_ptr->dynamicDB = new ElPriceDB(info);
    d_ptr->staticDB = new StaticElectricDB(info);
}

Electric::~Electric()
{
    delete d_ptr->dynamicDB;
    delete d_ptr->staticDB;

    delete d_ptr;
    d_ptr = NULL;
}

QString Electric::switchDevice() const
{
    StaticElectricData data(d_ptr->staticDB->staticElectricData());
    return data.switchDevice();
}

QString Electric::switchValue() const
{
    StaticElectricData data(d_ptr->staticDB->staticElectricData());
    return data.switchValue();
}

QString Electric::powerDevice() const
{
    StaticElectricData data(d_ptr->staticDB->staticElectricData());
    return data.powerDevice();
}

QString Electric::powerValue() const
{
    StaticElectricData data(d_ptr->staticDB->staticElectricData());
    return data.powerValue();
}

PriceData Electric::priceDataAfterIncluding(const QDateTime& dateTime) const
{
    StaticElectricData staticData(d_ptr->staticDB->staticElectricData());

    PriceData priceData(d_ptr->dynamicDB->priceDataAfterIncluding(staticData.area(), dateTime));

    priceData.applyCosts(staticData.energyTaxDouble(),
                         staticData.transferDouble(), staticData.transferTaxDouble(),
                         staticData.premiumDouble(), staticData.premiumTaxDouble());
    return priceData;
}

void Electric::setStaticElectricData(const StaticElectricData& data)
{
    d_ptr->staticDB->setStaticElectricData(data);
}

StaticElectricData Electric::staticElectricData()
{
    return d_ptr->staticDB->staticElectricData();
}

/*
double Electric::pricePerKWh() const
{
    qDebug() << Q_FUNC_INFO;

    // Nordpool announces prices in stockholm time!!!

    double eurosPerMWh = 30.99; // € per MWh from nordpool
    double centsPerkWh = (eurosPerMWh / 1000) * 100; // 1000 kWh per 1 MWh, into cents

    double price = centsPerkWh + (centsPerkWh * m_energyTax);
    price += m_transferPrice + (m_transferPrice * m_transferTax);
    price += m_premiumPrice + (m_premiumPrice * m_premiumTax);

    return price;
}
*/


text:
set -x
echo "BEGIN: $(TZ=UTC date)"
export PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
export DEBIAN_FRONTEND=noninteractive
readonly EC2_METADATA_URL='http://169.254.169.254/latest/meta-data'

#Setup hosts file
# https://aws.amazon.com/premiumsupport/knowledge-center/linux-static-hostname/
echo "Updating hostname"
# domain name and resolv.conf ar managed through dhcp
IP=$(curl -s "${EC2_METADATA_URL}/local-ipv4")
TRUNC_INSTANCE_ID=$(curl -s "${EC2_METADATA_URL}/instance-id" | sed -e 's/^i-//')
if [[ -v OPG_ROLE ]]
then
  NEW_HOSTNAME=${OPG_ROLE}-${TRUNC_INSTANCE_ID}
else
  NEW_HOSTNAME=${TRUNC_INSTANCE_ID}
fi
echo "${IP} ${NEW_HOSTNAME} ${OPG_ROLE}" >> /etc/hosts
echo "${NEW_HOSTNAME}" > /etc/hostname
hostname ${NEW_HOSTNAME}
service rsyslog restart

# Make sure files are 644 and directories are 755.
umask 022

if [[ "${USE_SALT}" == "yes" ]]
then
################################################### salt stop
    echo "Ensuring salt is stopped"
    # Need to stop Salt services.
    for s in salt-{minion,master}; do
        if [[ -f /etc/init/${s}.conf ]]; then
            service $s stop || true

            # Stop with extreme prejudice.
            if pgrep -f $s &>dev/null; then
                pkill -9 -f $s
            fi

            # Purge any keys and/or SSL certificates
            # that might have linger behind.
            rm -rf /etc/salt/pki/${s##*-}
        fi
    done

    # Make sure that Minion will pick his new ID to
    # advertise use after the new host name was set.
    rm -f /etc/salt/minion_id

    # Make sure to remove any cache left by Salt, etc.
    rm -rf /var/{cache,log,run}/salt/*
fi

if [[ "${USE_DOCKER}" == "yes" ]]
then
################################################### docker stop
    echo "Ensuring docker is stopped"
    # Need to stop Docker in order to make sure that
    # the /srv/docker is not in use, as often "aufs"
    # and "devicemapper" drivers will be active on
    # boot causing "device or resource busy" errors.
    if docker --version &>/dev/null; then
        service docker stop || true

        # Disable the Docker service and switch it
        # off completely if requested to do so.
        if [[ "${DISABLE_DOCKER}" == 'yes' ]]; then
            for f in /etc/init/docker.conf /etc/init.d/docker; do
                dpkg-divert --rename $f
            done

            update-rc.d -f docker disable || true
        else
            export DOCKER='yes'
        fi
    fi
fi

#set default bash prompt
echo "Setting custom bash prompt"
cat <<'EOF' > /etc/profile.d/bash-prompt.sh

if [[ ${EUID} == 0 ]]
then
        PS1="${PS1}\w #\[\033[00m\]"
else
        PS1="${PS1}\w $\[\033[00m\]"
fi
EOF
OPG_STACK=$(echo "${OPG_STACK}"| tr -d '[:digit:]')
if [[ "${OPG_STACK}" =~ ^production ]]
then
    sed -i "1s/^/PS1=\"\\\[\\\033[01;31m\\\](${OPG_STACK}) \\\u@${OPG_ROLE}:\"\n/" /etc/profile.d/bash-prompt.sh
else
    sed -i "1s/^/PS1=\"\\\[\\\033[01;34m\\\](${OPG_STACK}) \\\u@${OPG_ROLE}:\"\n/" /etc/profile.d/bash-prompt.sh
fi

echo "Install support packages"
apt-get -y -qq update
apt-get -y -qq install joe git awscli


text:
/*

Maxim one page bootstrap template
@2013 by iWebStudio

/*
===========================
CONTENTS:

01 General
02 Typography
03 Non-semantic
04 Navbar
05 Page sections
06 Footer
07 Icons
08 Buttons
09 Media queries
===========================
*/
/* Import css */
/* Google font */
@import url("../../../../fonts.googleapis.com/css-family=Open+Sans-300,400,600,700.css")/*tpa=http://fonts.googleapis.com/css?family=Open+Sans:300,400,600,700*/;
/* bootstrap */
@import url("bootstrap.css")/*tpa=http://iweb-studio.com/wrapbootstrap/maxim/css/bootstrap.css*/;
/* bootstrap responsive */
@import url("bootstrap-responsive.css")/*tpa=http://iweb-studio.com/wrapbootstrap/maxim/css/bootstrap-responsive.css*/;
/* prettyPhoto */
@import url("prettyPhoto.css")/*tpa=http://iweb-studio.com/wrapbootstrap/maxim/css/prettyPhoto.css*/;
/* flexslider */
@import url("flexslider.css")/*tpa=http://iweb-studio.com/wrapbootstrap/maxim/css/flexslider.css*/;

/* font awesome */
@import url("font-awesome.css")/*tpa=http://iweb-studio.com/wrapbootstrap/maxim/css/font-awesome.css*/;
/* overwrite */
@import url("overwrite.css")/*tpa=http://iweb-studio.com/wrapbootstrap/maxim/css/overwrite.css*/;
/* animation */
@import url("animate.css")/*tpa=http://iweb-studio.com/wrapbootstrap/maxim/css/animate.css*/;

/* =========================================================
01. General
============================================================ */

div, article, section, header, footer, nav, li {
	position:relative;
}
.group:after {
	display:block;
	height:0;
	clear:both;
	content:".";
	visibility:hidden; /* For clearing */
}
body {
	background:#fff;
	color: #444;
	font-size: 16px;
	font-weight:300;
	font-family:'Open Sans', Arial, sans-serif;
}

body {
    padding-top: 60px; /* 60px to make the container go all the way to the bottom of the topbar */
}

::-moz-selection {
	color:#333;
}
::selection {
	color:#333;
}

/* scroll to top */
.scrollup{
    position:fixed;
	width:32px;
	height:32px;
    bottom:20px;
    right:20px;
}

a.scrollup {
	outline:0;
	text-decoration:none;
}

a.scrollup:hover,a.scrollup:active,a.scrollup:focus {
	opacity:1;
	text-decoration:none;
	-webkit-transition: all 400ms ease-out 0s;
	   -moz-transition: all 400ms ease-out 0s;
		 -o-transition: all 400ms ease-out 0s;
		    transition: all 400ms ease-out 0s;
}
a.scrollup i:hover {
	text-decoration:none;
}

.blankdivider10 {
	height: 10px;
	display: block;
}

.blankdivider20 {
	height: 20px;
	display: block;
}
.blankdivider30 {
	height: 30px;
	display: block;
}

.row {
	margin-bottom:30px;
}

.row .row{
	margin-bottom:30px;
}

.row.nomargin {
	margin-bottom:0;
}

/*---------- forms ----------*/

input[type=text], input[type=submit], textarea {
	width: 100%;
	padding: 0.5em;
	font-size: 1em;
	margin-bottom: 1.5em;
	box-sizing: border-box;
	-moz-box-sizing: border-box;
	-webkit-box-sizing: border-box;
}
input, button, select, textarea {
	font-family:'Open Sans', Arial, sans-serif;
}
/* =========================================================
02. Typography
============================================================ */

p {
	line-height: 1.6em;
	margin: 0 0 10px 0;
}

blockquote {
	font-size:18px;
	border:none;
	padding:0;
}

blockquote.large {
	font-size:36px;
	font-weight:700;
	line-height:1.1em;
}
blockquote.large:before {
	font-size:64px;
	font-family: FontAwesome;
	content: "\f10d";
	margin-right:20px;
}

blockquote cite 						{ display:block; font-size:12px;}
blockquote cite:before 					{ content:"\2014 \0020"; }
blockquote cite a,
blockquote cite a:visited,
blockquote cite a:visited 				{ color:#555; }

ul, ol {
	font-size: 1em; /* 16px */
	line-height: 1.5; /* 24px */
	margin: 0 0 1.5em 0;
}
body, input, textarea {
}

a {
  color: #454545;
  text-decoration: none;
}

a:hover, a:active {
	text-decoration: underline;
}
h1, h2, h3, h4, h5, h6 {
	font-weight: 400;
	color: #312f2b;
	line-height:1.1em;
	font-family:'Open Sans', Arial, sans-serif;
}
h1 {
	font-size: 36px;
	margin-bottom:20px;
}
h2 {
	font-size: 30px;
	margin-bottom:20px;
}
h3 {
	font-size: 26px;
	margin-bottom:20px;
}
h4 {
	font-size: 22px;
	margin-bottom:20px;
}
h5 {
	font-size: 18px;
	margin-bottom:15px;
}
h6 {
	font-size: 16px;
	margin-bottom:10px;
}
strong {
	font-weight:700;
	font-family: 'Open Sans', sans-serif;
}
small {
	font-size: 0.75em; /* 12px */
	line-height: 2; /* 24px */
	margin-top: 2em;
	margin-bottom: 0em;
}
em {
	font-style: normal;
	font-family: 'Open Sans';
}
.muted {
	color: #A5A5A2;
}
.impressed {
	text-shadow:
 -1px -1px 0 rgba(0, 0, 0, 0.5), /* shadow */  1px 1px 0 rgba(255, 255, 255, 0.9); /* highlight */
}

h2.pagetitle {
	color:#fff;
	font-size:46px;
}

/* =========================================================
03. Misc
============================================================ */

.hide-text {
	text-indent: 100%;
	white-space: nowrap;
	overflow: hidden;
	font-size: 1em;
}
.alignright {
	text-align: right;
}
.alignleft {
	text-align: left;
}
.aligncenter {
	text-align: center;
}
.medium {
	font-weight: normal;
}

/* =========================================================
04. Navigation
============================================================ */

.navbar-fixed-top .container {
/* Uncomment to make nav expand full width */
 /*	width: auto; */
}
.navbar .brand {
	margin-left:0;
	padding: 0;
	margin-top: 1.05em;
}
.navbar .brand a {
	padding: 0;
	color: #fff;
	font-size: 1.75em;
	margin-left: 0;
	font-weight: 400;
	text-transform:uppercase;
}
.navbar .brand a:hover {
	text-decoration: none;
 transition: color .15s linear;
 -webkit-transition: color .15s linear;
 -moz-transition: color .15s linear;
}
.navbar .brand a:focus {
	outline: none;
}
.navbar-inner {
	min-height: 4.75em;
}
.navbar-inverse .navbar-inner {
	background-repeat: repeat;
	background-color: #0b333f;
}
.navbar-wrapper {
	overflow:hidden;
}
#menu-main {
	margin-top: 1.125em;
}
ul#menu-main > li > a {
	font-weight: 600;
	color: #fff;
	font-size:14px;
	text-transform:uppercase;
}
ul#menu-main > li > a:hover {
	padding: 9px 15px;
	border-radius: 3px;
	-webkit-border-radius: 3px;
	-moz-border-radius: 3px;
}
ul#menu-main > li > a:focus {
	outline:0;
}

.navbar-inverse .brand, .navbar-inverse .nav > li > a {
	text-shadow: none;
}

/* =========================================================
05. Page sections
============================================================ */

/* === section header === */

#header-wrapper {
	width: 100%;
	min-height: 600px;
	margin-top: -60px;
	padding-top:160px;
	text-align:center;
}

#header-wrapper h1 {
	color: #FFFFFF;
	font-size: 4em;
	font-weight: 400;
	margin: 1em 0;
}
#header-wrapper h2 {
	color: #fff;
	font-family: 'Open Sans', sans serif;
	font-size: 2em;
	font-weight: normal;
	margin: 0.5em 0;
	text-shadow: 1px 1px 1px #333333;
}

header .logo {
	text-align:center;
	margin-bottom:30px;
}

/* --- Header slider --- */
#header-wrapper.header-slider {
	background: #444 url("../img/bg/bg-1.jpg")/*tpa=http://iweb-studio.com/wrapbootstrap/maxim/img/bg/bg-1.jpg*/ no-repeat center center fixed;
	-webkit-background-size: cover;
	-moz-background-size: cover;
	-o-background-size: cover;
	background-size: cover;
}

#main-flexslider ul.slides li p {
	font-size: 72px;
	text-transform: uppercase;
	position: relative;
	margin-bottom: 0px;
	text-align: center;
	line-height: 1;
	color:#fff;
}
#main-flexslider.flexslider {
		margin:0;
		background:none;
		border:none;
	-webkit-border-radius: 0;
	-moz-border-radius: 0;
	-o-border-radius: 0;
	border-radius: 0;
	box-shadow: none;
	-webkit-box-shadow: none;
	-moz-box-shadow: none;
	-o-box-shadow: none;
}

/* --- Header subscribe form --- */

#header-wrapper input[type=text] {
	background: rgba(227, 231, 228, 1);
	font-family: 'Open Sans', sans serif;
	font-size: 1.3125em;
	border: 0;
	text-align: center;
	vertical-align: middle;
	margin-bottom:0 !important;
}
#header-wrapper input[type=text]:focus {
	background: #43413e;
	color: #eff1ef;
	transition: background 0.25 ease-in;
	-moz-transition: background 0.25 ease-in;
	-webkit-transition: background 0.25 ease-in;
}
#header-wrapper input[type=text] {
	height: 2.9em;
	width:50%;
}
#header-wrapper input[type=submit] {
	color: #fff;
	width: 185px;
	height: 2.9em;
	font-size: 1.3125em; /* 21px */
	padding:0.5em;
	letter-spacing: 0.05em;
	margin: 0;
	border: 0;
	text-transform: none;
	border-radius: 3px;
	-moz-border-radius: 3px;
	-webkit-border-radius: 3px;
}
#header-wrapper input[type=submit]:hover, #header-wrapper input[type=submit]:active {
	background: #43413e !important;
}

section.section {
	padding: 100px 0 80px;
}
section.section h4 {
	text-align: center;
	margin-bottom: 40px;
	font-size: 46px;
	font-weight: 700;
	letter-spacing: -1px;
}
section.inner {
	padding: 50px 0 50px;
}

.section.orange h4 ,.section.green h4{
	color: #fcfcfc;
}
.section.orange p,.section.green p {
	color: #f7f7f7;
}

/* === section spacer === */

section.spacer {
	padding:90px 0 70px;
	color:#fcfcfc;
}

.spacer.green,.section.green {
	background:#1bac91;
}

.spacer.green,.section.green h4 {
	color:#fff;
}

.spacer.yellow,.section.yellow  {
	background:#ffe873;
}
.spacer.orange,.section.orange {
	background:#f36f36;
}

section.spacer.bg2 {
	background: url("../img/bg/bg-2.jpg")/*tpa=http://iweb-studio.com/wrapbootstrap/maxim/img/bg/bg-2.jpg*/ 50% 0 no-repeat fixed;
	width:100%;
	height:auto;
	margin:0;
}

section.spacer.bg3 {
	background: url("../img/bg/bg-3.jpg")/*tpa=http://iweb-studio.com/wrapbootstrap/maxim/img/bg/bg-3.jpg*/ 50% 0 no-repeat fixed;
	width:100%;
	height:auto;
	margin:0;
}

section.spacer blockquote.large:before {
	color:#eee;
	opacity:0.6;
}

section.spacer blockquote cite {
	color:#555;
}

/* === section works === */

#works h4 {
	margin-bottom:20px;
}

#portfolio {
	padding-bottom: 0;
}
/* === portfolio filter === */

#filters {
	margin-bottom: 0px;
	text-align: center;
	display: block;
	float: none;
	z-index: 2;
	position: relative;
}
#filters ul {
	margin: 0 0 20px;
	list-style: none;
	padding: 0;
}
#filters ul li {
	display: inline-block;
}
#filters ul li a {
	display: block;
	float: left;
	padding: 2px 5px;
	color: inherit;
	margin-right: 5px;
	margin-bottom: 5px;
	font-weight: 600;
}
#filters ul li a:hover,#filters ul li a:focus {
	text-decoration:none;
	outline:0;
}
#filters ul li a h5 {
	font-size: 14px;
	padding: 5px 10px 5px;
	border: 2px solid #f2f2f2;
}

#filters ul li a:hover h5, #filters ul li a.active h5 {
	color:#fcfcfc;
}

/* === portfolio wrap - grid === */
#portfolio-wrap {
	position: relative;
	padding: 0;
	width: 100.1%;
	margin: 0 auto;
	display: block;
}
#portfolio-wrap .grid {
	margin: 0;
	overflow: hidden;
	line-height: 0;
	width: 20%;
	border:0;
	padding: 0;
}
.portfolio-item.current {
	z-index: 101;
}
.portfolio-item {
	padding: 0;
	position: relative;
	overflow: hidden;
}
.portfolio-item .portfolio-image {
	overflow: hidden;
	display: block;
	position: relative;
}
.portfolio-item .portfolio-image img {
	width: 100%;
	height: auto;
}
.portfolio .portfolio-overlay {
	width: 100%;
	height: 100%;
	top: 0;
	left: 0;
	position: absolute;
	display: block;
	z-index: 4;
	opacity: 0;
	-moz-opacity: 0;
	filter: alpha(opacity=0);
	-webkit-transition: all 0.3s ease-in-out;
	-moz-transition: all 0.3s ease-in-out;
	-o-transition: all 0.3s ease-in-out;
	-ms-transition: all 0.3s ease-in-out;
	transition: all 0.3s ease-in-out;
}
.portfolio > a, .portfolio > a:hover {
	color: #ffffff;
}
.portfolio-item .portfolio > a:hover > .portfolio-overlay {
	opacity: 1;
	-moz-opacity: 1;
	filter: alpha(opacity=100);
}
.portfolio > a img {
	-webkit-transition: all 0.3s ease-in-out;
	-moz-transition: all 0.3s ease-in-out;
	-o-transition: all 0.3s ease-in-out;
	-ms-transition: all 0.3s ease-in-out;
	transition: all 0.3s ease-in-out;
}
.portfolio > a:hover img {
	-webkit-transition: all 0.3s ease-in-out;
	-moz-transition: all 0.3s ease-in-out;
	-o-transition: all 0.3s ease-in-out;
	-ms-transition: all 0.3s ease-in-out;
	transition: all 0.3s ease-in-out;
}
.portfolio .thumb-info {
	position: absolute;
	width: 100%;
	height: 100%;
	opacity: 0;
	-moz-opacity: 0;
	filter: alpha(opacity=0);
	-webkit-transition: all 0.3s ease-in-out;
	-moz-transition: all 0.3s ease-in-out;
	-o-transition: all 0.3s ease-in-out;
	-ms-transition: all 0.3s ease-in-out;
	transition: all 0.3s ease-in-out;
}
.portfolio a:hover .portfolio-overlay .thumb-info {
	opacity: 1;
	-moz-opacity: 1;
	filter: alpha(opacity=100);
}
.portfolio-overlay .thumb-info i {
	top: 50%;
}
.portfolio-overlay .thumb-info h5 {
	top: 20%;
	font-size: 18px;
}
.portfolio-overlay .thumb-info p {
	top: 50%;
	font-size: 13px;
}
.portfolio-overlay .thumb-info h5 {
	color: #ffffff;
	width: 100%;
	position: absolute;
	text-align: center;
}
.portfolio-overlay .thumb-info p {
	color: #ffffff;
	width: 100%;
	position: absolute;
	text-align: center;
	font-weight: bold;
}
.portfolio-overlay .thumb-info i {
	color: #ffffff;
	width: 100%;
	position: absolute;
	text-align: center;
	display: block;
}
/* === Isotope CSS3 transitions === */

.isotope, .isotope .isotope-item {
	-webkit-transition-duration: 0.8s;
	-moz-transition-duration: 0.8s;
	-ms-transition-duration: 0.8s;
	-o-transition-duration: 0.8s;
	transition-duration: 0.8s;
}
.isotope {
	-webkit-transition-property: height, width;
	-moz-transition-property: height, width;
	-ms-transition-property: height, width;
	-o-transition-property: height, width;
	transition-property: height, width;
}
.isotope .isotope-item {
	-webkit-transition-property: -webkit-transform, opacity;
	-moz-transition-property: -moz-transform, opacity;
	-ms-transition-property: -ms-transform, opacity;
	-o-transition-property: -o-transform, opacity;
	transition-property: transform, opacity;
}
/**** disabling Isotope CSS3 transitions ****/

.isotope.no-transition, .isotope.no-transition .isotope-item, .isotope .isotope-item.no-transition {
	-webkit-transition-duration: 0s;
	-moz-transition-duration: 0s;
	-ms-transition-duration: 0s;
	-o-transition-duration: 0s;
	transition-duration: 0s;
}

/* === section services === */

section#services h2 {
	font-size: 22px;
	margin-bottom: 15px;
	margin-top: 10px;
	text-align:center;
}
section#services p {
	margin:10px;
}

section#services .service-box {
	text-align: center;
	padding: 20px;
	-webkit-transition: all 0.3s ease-in-out;
	-moz-transition: all 0.3s ease-in-out;
	-o-transition: all 0.3s ease-in-out;
	-ms-transition: all 0.3s ease-in-out;
	transition: all 0.3s ease-in-out;
}
section#services .span3:hover {
	background:#e3e3e3;
}

section#services .service-box h2 {
	color: #f7f7f7;
	font-weight: 700;
}

section#services.section.orange .service-box:hover {
	background:#f36518;
}

/* === section blog === */

section#blog {
	background: #f2f2f2;
}

.home-post {
	background:#fff;

}

.home-post:hover {
	box-shadow: 0 0 16px rgba(0, 0, 0, 0.3);
	-moz-box-shadow: 0 0 16px rgba(0, 0, 0, 0.3);
	-webkit-box-shadow: 0 0 16px rgba(0, 0, 0, 0.3);
	-webkit-transition: all 0.4s ease-in-out;
	-moz-transition: all 0.4s ease-in-out;
	-o-transition: all 0.4s ease-in-out;
	-ms-transition: all 0.4s ease-in-out;
	transition: all 0.4s ease-in-out;
}

.home-post .entry-content {
	padding:20px;
}
.home-post .entry-content h5 a {
	font-size:22px;
}
.home-post .entry-content h5 a:hover {
	color:#312f2b;
	text-decoration:none;
}
.home-post .entry-content a.more {
	font-size:13px;
}
.home-post .post-meta {
	padding:20px;
	overflow:hidden;
	color:#fcfcfc;
}
.home-post .post-meta i {
	float:left;
	margin-right:20px;
}
.home-post .post-meta span {
	margin-top:10px;
}
.home-post .post-meta span.date {
	font-weight:700;
	font-size:13px;
	float:left;
}
.home-post .post-meta span.tags {
	font-weight:700;
	font-size:13px;
	float:right;
	color:#ddd;
}
.home-post .post-meta span.tags a {
	color:#fcfcfc;
}

/* === section about === */

section#about {
	background:#f2f2f2;
}

.people {
	text-align:center;
}

.people h3 {
	margin-bottom:10px;
	font-weight:700;
	letter-spacing:-1px;
}

.team-thumb {
	margin-top: 26px;
	text-align:center;
}

/* (spacer) latest tweet */
#tweet{
	text-align:center;
	margin:20px 0 0;
	font-size:20px;
	color:#fff;
}

#tweet ul{
	float:left;
	width:100%;
	text-align:center;
	list-style:none;
	margin:0;
	padding:0;
}

#tweet ul li{
	display: inline-block;
	list-style:none;
	margin:0 0 20px;
	padding:0 0 0 34px;
	font-size:20px;
	line-height:1.5em;
}

#tweet ul li:before {
	font-family: 'FontAwesome';
	speak: none;
	font-style: normal;
	font-weight: normal;
	font-variant: normal;
	text-transform: none;
	line-height: 1;
	-webkit-font-smoothing: antialiased;
	content: "\f099";
	margin-right:20px;
}

/* === Contact section === */

/* Contact Form */

.validation {
	display:none;
	margin: -10px 0 20px;
	color:#fff;
	font-weight:700;
	font-size:13px;
}

#sendmessage {
	border:1px solid #fff;
	display:none;
	text-align:center;
	padding:15px 12px 15px;
	margin:10px 0;
	font-weight:600;
	margin-bottom:30px;
}

#sendmessage.show,.show  {
	display:block;
}

#contact-form {
	position: relative;
	z-index: 999;
}

#contact-form input[type=text], .contactForm textarea {
	background: rgba(227, 231, 228, 1);
	font-family: 'Open Sans', sans serif;
	border: 0;
	font-size:16px;
	text-align: left;
	vertical-align: middle;
}
#contact-form input[type=text]:focus, .contactForm textarea:focus {
	background: rgba(101, 106, 100, 1);
	color: #eff1ef;
	box-shadow: none;
	-moz-box-shadow: none;
	-webkit-box-shadow: none;
	transition: background 0.25 ease-in;
	-moz-transition: background 0.25 ease-in;
	-webkit-transition: background 0.25 ease-in;
}
#contact-form input[type=text] {
	height: 60px;
	margin-bottom:30px;
}
#contact-form input[type=submit] {
	color: #fff;
	width: 185px;
	height: 60px;
	text-shadow: none;
	font-size: 16px;
	padding:0.5em;
	letter-spacing: 0.05em;
	margin: 0 0 20px 0;
	display: block;
	border: 0;
	text-transform: none;
	border-radius: 3px;
	-moz-border-radius: 3px;
	-webkit-border-radius: 3px;
	box-shadow: none;
	-moz-box-shadow: none;
	-webkit-box-shadow: none;
}
#contact-form input[type=submit]:hover, #contact-form input[type=submit]:active {
	background: #43413e !important;
}
#contact-form textarea {
	padding-top: 1em;
}
div.cform-response-output {
	max-width: 60%;
	text-align: center;
	margin-left: 40% !important;
	margin-top: 0.5em !important;
	padding: 0.5em !important;
	border-radius: 4px;
	-moz-border-radius: 4px;
	-webkit-border-radius: 4px;
}
.cform-not-valid-tip {
	color: #888;
	border: 1px dotted #ad3729 !important;
	width: 100% !important;
	left: 0 !important;
	padding: 0.5em !important;
	font-family: 'Open Sans', sans-serif;
	box-sizing: border-box;
	-moz-box-sizing: border-box;
	-webkit-box-sizing: border-box;
	border-radius: 4px;
	-moz-border-radius: 4px;
	-webkit-border-radius: 4px;
}

/* =========================================================
06. Footer
============================================================ */

footer {
	background: #2b2b2b;
	text-align: center;
	color: #5e5e5e;
	padding:50px 0 50px;
}

footer ul.social-networks {
	list-style:none;
}

footer ul.social-networks li {
	display:inline;
}

footer ul.social-networks li i {
	display:inline-block;
}

footer ul.social-networks li a {
	color: #5e5e5e;
	margin: 0 5px;
}

footer ul.social-networks li a:hover {
	text-decoration:none;
	-webkit-transition: all 0.4s ease-in-out;
	-moz-transition: all 0.4s ease-in-out;
	-o-transition: all 0.4s ease-in-out;
	-ms-transition: all 0.4s ease-in-out;
	transition: all 0.4s ease-in-out;
}

footer ul.social-networks li i.icon-bgdark {
	background:#414141;
	color: #656565;
}

footer ul.social-networks li a i.icon-instagram:hover {
	background: #ba7b3d;
	color: #fff;
}

footer ul.social-networks li a i.icon-twitter:hover {
	background: #5ad2eb;
	color: #fff;
}
footer ul.social-networks li a i.icon-dribbble:hover {
	background: #f57b71;
	color: #fff;
}
footer ul.social-networks li a i.icon-pinterest:hover {
	background: #d84848;
	color: #fff;
}

/* =========================================================
07. Icons
============================================================ */

/* bg */
i.icon-bglight {
	color: #444;
	background: #f7f7f7;
}
i.icon-bglight.active {
	color: #fff;
}

i.icon-bglight.active:hover{
	color: #444;
	background: #f7f7f7;
}

i.icon-bgdark {
	color: #f7f7f7;
	background: #333;
}
i.icon-bgdark:hover {
	color: #fff;
}
i.icon-bgdark.active:hover {
	color: #f7f7f7;
	background: #333;
}

/* square */
i.icon-square {
	display: inline-block;
	text-align: center;
	width: 24px !important;
	height: 24px !important;
	line-height: 24px !important;
}
i.icon-square.icon-2x{
	width: 48px !important;
	height: 48px !important;
	line-height: 48px !important;
}
i.icon-square.icon-3x{
	width: 72px !important;
	height: 72px !important;
	line-height: 72px !important;
}
i.icon-square.icon-4x{
	width: 96px !important;
	height: 96px !important;
	line-height: 96px !important;
}
i.icon-square.icon-5x{
	width: 120px !important;
	height: 120px !important;
	line-height: 120px !important;
}

/* rounded */
i.icon-rounded {
	display: inline-block;
	border-radius: 6px !important;
	-moz-border-radius: 6px !important;
	-webkit-border-radius: 6px !important;
	-o-border-radius: 6px !important;
	-ms-border-radius: 6px !important;
	text-align: center;
	width: 24px !important;
	height: 24px !important;
	line-height: 24px !important;
}

.icon-rounded.icon-2x{
	width: 48px !important;
	height: 48px !important;
	line-height: 48px !important;
}
.icon-rounded.icon-3x{
	width: 72px !important;
	height: 72px !important;
	line-height: 72px !important;
	border-radius: 8px !important;
	-moz-border-radius: 8px !important;
	-webkit-border-radius: 8px !important;
	-o-border-radius: 8px !important;
	-ms-border-radius: 8px !important;
}
.icon-rounded.icon-4x{
	width: 96px !important;
	height: 96px !important;
	line-height: 96px !important;
	border-radius: 10px !important;
	-moz-border-radius: 10px !important;
	-webkit-border-radius: 10px !important;
	-o-border-radius: 10px !important;
	-ms-border-radius: 10px !important;
}
.icon-rounded.icon-5x{
	width: 120px !important;
	height: 120px !important;
	line-height: 120px !important;
	border-radius: 12px !important;
	-moz-border-radius: 12px !important;
	-webkit-border-radius: 12px !important;
	-o-border-radius: 12px !important;
	-ms-border-radius: 12px !important;
}

/* circled */
i.icon-circled {
	display: inline-block;
	border-radius: 1000px !important;
	-moz-border-radius: 1000px !important;
	-webkit-border-radius: 1000px !important;
	-o-border-radius: 1000px !important;
	-ms-border-radius: 1000px !important;
	text-align: center;
	width: 24px !important;
	height: 24px !important;
	line-height: 24px !important;
}

.icon-circled.icon-2x{
	width: 48px !important;
	height: 48px !important;
	line-height: 48px !important;
}
.icon-circled.icon-3x{
	width: 72px !important;
	height: 72px !important;
	line-height: 72px !important;
}
.icon-circled.icon-4x{
	width: 96px !important;
	height: 96px !important;
	line-height: 96px !important;
}
.icon-circled.icon-5x{
	width: 120px !important;
	height: 120px !important;
	line-height: 120px !important;
}

i.icon-white {
	color:#fff;
}

/* more icon sizes for font-awesome icons */

.icon-6x {
  font-size: 6em;
}
.icon-6x.icon-border {
  border-width: 6px;
  -webkit-border-radius: 8px;
  -moz-border-radius: 8px;
  border-radius: 8px;
}

.icon-7x {
  font-size: 7em;
}
.icon-6x.icon-border {
  border-width: 6px;
  -webkit-border-radius: 8px;
  -moz-border-radius: 8px;
  border-radius: 8px;
}

.icon-8x {
  font-size: 8em;
}
.icon-6x.icon-border {
  border-width: 6px;
  -webkit-border-radius: 8px;
  -moz-border-radius: 8px;
  border-radius: 8px;
}

.icon-9x {
  font-size: 9em;
}
.icon-6x.icon-border {
  border-width: 6px;
  -webkit-border-radius: 8px;
  -moz-border-radius: 8px;
  border-radius: 8px;
}
.icon-10x {
  font-size: 10em;
}
.icon-6x.icon-border {
  border-width: 6px;
  -webkit-border-radius: 8px;
  -moz-border-radius: 8px;
  border-radius: 8px;
}

/* =========================================================
08. Buttons
============================================================ */

.btn {
	color: #fff;
	text-shadow: none;
	font-size: 16px;
	padding: 11px 19px;
	letter-spacing: 0.05em;
	border: 0;
	text-transform: none;
	border-radius: 3px;
	-moz-border-radius: 3px;
	-webkit-border-radius: 3px;
	box-shadow: none;
	-moz-box-shadow: none;
	-webkit-box-shadow: none;
  background-color: #545454;
  border-color: none;
  *background-color: #545454;
  background-image: none;
  /* Darken IE7 buttons by default so they stand out more given they won't have borders */
  filter: none;
  border: none;
  *border: 0;
  border-bottom-color: none;
}
.btn:link, .btn:visited {
	color: #fff;
}
.btn:hover {
	background: #333 !important;
}
.btn:hover,
.btn:focus,
.btn:active,
.btn.active,
.btn.disabled,
.btn[disabled] {
  color: #fff;
  background-color: #333;
  *background-color: #333;
}

.btn.btn-theme:hover {
	background: #333 !important;
}

/* size */
.btn-large {
  padding: 18px 25px;
  font-size: 24px;
  -webkit-border-radius: 0;
  -moz-border-radius: 0;
  border-radius: 0;
}

.btn-large [class^="icon-"],
.btn-large [class*=" icon-"] {
  margin-top: 4px;
}

.btn-small {
  padding: 6px 13px;
  font-size: 11.9px;
  -webkit-border-radius: 0;
  -moz-border-radius: 0;
  border-radius: 0;
}

.btn-small [class^="icon-"],
.btn-small [class*=" icon-"] {
  margin-top: 0;
}

.btn-mini [class^="icon-"],
.btn-mini [class*=" icon-"] {
  margin-top: -1px;
}

.btn-mini {
  padding: 0 6px;
  font-size: 10.5px;
  -webkit-border-radius: 0;
  -moz-border-radius: 0;
  border-radius: 0;
}

/* end size */

.btn-primary {
  color: #ffffff;
  text-shadow: none;
  background-color: #09828c;
  *background-color: #09828c;
  background-image: none;
  border-color: none;
  filter:none;
}

.btn-primary:hover,
.btn-primary:focus,
.btn-primary:active,
.btn-primary.active,
.btn-primary.disabled,
.btn-primary[disabled] {
  color: #ffffff;
  background: #065158;
  *background-color: #065158;
}

.btn-primary:active,
.btn-primary.active {
  background-color: #065158 \9;
}

.btn-warning {
  color: #ffffff;
  text-shadow: none;
  background-color: #ffe873;
  *background-color: #ffe873;
  background-image: none;
  border-color: none;
  filter:none;
}

.btn-warning:hover,
.btn-warning:focus,
.btn-warning:active,
.btn-warning.active,
.btn-warning.disabled,
.btn-warning[disabled] {
  color: #ffffff;
  background: #b88f22;
  *background: #b88f22;
}

.btn-warning:active,
.btn-warning.active {
  background: #b88f22 \9;
}

.btn-danger {
  color: #ffffff;
  text-shadow: none;
  background-color: #f36f36;
  *background-color: #f36f36;
  background-image: none;
  border-color: none;
  filter:none;
}

.btn-danger:hover,
.btn-danger:focus,
.btn-danger:active,
.btn-danger.active,
.btn-danger.disabled,
.btn-danger[disabled] {
  color: #ffffff;
  background: #db5f58;
  *background: #db5f58;
}

.btn-danger:active,
.btn-danger.active {
  background: #db5f58 \9;
}

.btn-success {
  color: #ffffff;
  text-shadow: none;
  background-color: #1bac91;
  *background-color: #1bac91;
  background-image: none;
  border-color: none;
  filter:none;
}

.btn-success:hover,
.btn-success:focus,
.btn-success:active,
.btn-success.active,
.btn-success.disabled,
.btn-success[disabled] {
  color: #ffffff;
  background: #55ba93;
  *background: #55ba93;
}

.btn-success:active,
.btn-success.active {
  background: #55ba93 \9;
}

.btn-info {
  color: #ffffff;
  text-shadow: none;
  background-color: #4dbdc6;
  *background-color: #4dbdc6;
  background-image: none;
  border-color: none;
  filter:none;
}

.btn-info:hover,
.btn-info:focus,
.btn-info:active,
.btn-info.active,
.btn-info.disabled,
.btn-info[disabled] {
  color: #ffffff;
  background: #6a9ad0;
  *background: #6a9ad0;
}

.btn-info:active,
.btn-info.active {
  background: #6a9ad0 \9;
}

.btn-inverse {
  color: #ffffff;
  text-shadow: none;
  background-color: #3c3c3c;
  *background-color: #3c3c3c;
  background-image: none;
  border-color: none;
  filter:none;
}

.btn-inverse:hover,
.btn-inverse:focus,
.btn-inverse:active,
.btn-inverse.active,
.btn-inverse.disabled,
.btn-inverse[disabled] {
  color: #ffffff;
  background: #2b2a2a;
  *background: #2b2a2a;
}

.btn-inverse:active,
.btn-inverse.active {
  background: #2b2a2a \9;
}

/* button flat */
.btn-flat {
  -webkit-border-radius: 0;
  -moz-border-radius: 0;
  border-radius: 0;
}

/* button rounded */
.btn-rounded {
  -webkit-border-radius: 20px;
  -moz-border-radius: 20px;
  border-radius: 20px;
}
.btn-large.btn-rounded {
  -webkit-border-radius: 28px;
  -moz-border-radius: 28px;
  border-radius: 28px;
}

.navbar-inverse .btn-navbar {
	width: auto;
	height: auto;
}

/* =========================================================
09. Media queries
============================================================ */

 @media (min-width: 768px) and (max-width: 979px) {
	body {
		padding-left:0 ;
		padding-right:0;
		padding:0;
	}

	.navbar-inner {
	 padding-right: 20px;
	 padding-left: 20px;
	}

	.navbar-inner h1.brand {
		margin-left:20px;
	}

	.navbar-inner .btn-navbar {
		margin:20px 20px 0;
	}

	.container {
	 padding-right: 20px;
	 padding-left: 20px;
	}
	.navbar-inverse .navbar-inner {
		padding:0 0 30px;
	}

	.nav-collapse {
		text-align:center;
		width:100%;
	}

}

@media (max-width: 767px) {
	body {
		padding-left:0 ;
		padding-right:0;
		padding:0;
	}
	.navbar-inner {
	 padding-right: 20px;
	 padding-left: 20px;
	}

	.navbar-inner h1.brand {
		margin-left:20px;
	}

	.navbar-inner .btn-navbar {
		margin:20px 20px 0;
	}

	.container {
	 padding-right: 20px;
	 padding-left: 20px;
	}
	.navbar-inverse .navbar-inner {
		padding:0 20px 30px;
	}

	.nav-collapse {
		text-align:center;
		width:100%;
	}
	#portfolio-wrap .grid {
		width: 25%;
	}
}

    /* Smaller screens ----------- */
@media (max-width : 480px) {
	#header-wrapper {
		padding-top:80px;
	}

	#team .team-thumb {
		 margin-right: auto;
		 margin-left: auto;
		 width: 150px;
		 display: block;
		 text-align:center;
	}

	#portfolio-wrap .grid {
		width: 50%;
	}

}

    /* Smartphones (portrait and landscape) ----------- */
@media only screen  and (min-device-width : 320px)  and (max-device-width : 480px) {

 section.section {
 padding: 1em 0;
}

 #works .container {
 top: 0 !important;
}

.max-img {
 width: 100%;
}
 .max-img {
 margin-right: auto;
 margin-left: auto;
 display: block;
}

 section#services h2 {
 margin-bottom: 0.25em;
}
 section#services h2, section#services ul {
 text-align: center;
}

/* team */

#team .team-thumb {
 margin-right: auto;
 margin-left: auto;
 width: 150px;
 display: block;
 text-align:center
}
 .job-position: {
 margin-bottom: 1.5em;
}
 .navbar-fixed-top, .navbar-fixed-bottom, .navbar-static-top {
 margin-left: auto;
 margin-right: auto;
}

/* Contact Form */
	#contact-form {
		overflow: hidden;
	}
	#contact-form input[type=submit] {
		width: 100%;
	}
}


text:
(function(){
	'use strict';

	var $html = $('html'), $win = $(window);

	$.support.touch                 = (
		('ontouchstart' in window && navigator.userAgent.toLowerCase().match(/mobile|tablet/)) ||
		(window.DocumentTouch && document instanceof window.DocumentTouch)  ||
		(window.navigator.msPointerEnabled && window.navigator.msMaxTouchPoints > 0) || //IE 10
		(window.navigator.pointerEnabled && window.navigator.maxTouchPoints > 0) || //IE >=11
		false
	);

	$html.addClass($.support.touch ? 'touch' : 'no-touch');

})();