This commit is contained in:
@@ -5303,6 +5303,9 @@
|
|||||||
.-mx-2 {
|
.-mx-2 {
|
||||||
margin-inline: calc(var(--spacing) * -2);
|
margin-inline: calc(var(--spacing) * -2);
|
||||||
}
|
}
|
||||||
|
.mx-6 {
|
||||||
|
margin-inline: calc(var(--spacing) * 6);
|
||||||
|
}
|
||||||
.mx-10 {
|
.mx-10 {
|
||||||
margin-inline: calc(var(--spacing) * 10);
|
margin-inline: calc(var(--spacing) * 10);
|
||||||
}
|
}
|
||||||
@@ -7949,6 +7952,9 @@
|
|||||||
.p-6 {
|
.p-6 {
|
||||||
padding: calc(var(--spacing) * 6);
|
padding: calc(var(--spacing) * 6);
|
||||||
}
|
}
|
||||||
|
.p-10 {
|
||||||
|
padding: calc(var(--spacing) * 10);
|
||||||
|
}
|
||||||
.menu-title {
|
.menu-title {
|
||||||
@layer daisyui.l1.l2.l3 {
|
@layer daisyui.l1.l2.l3 {
|
||||||
padding-inline: calc(0.25rem * 3);
|
padding-inline: calc(0.25rem * 3);
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ private let viewRouteMiddleware: [any Middleware] = [
|
|||||||
extension SiteRoute.View {
|
extension SiteRoute.View {
|
||||||
var middleware: [any Middleware]? {
|
var middleware: [any Middleware]? {
|
||||||
switch self {
|
switch self {
|
||||||
case .home, .login, .signup, .test, .ductulator:
|
case .home, .login, .signup, .test, .ductulator, .privacyPolicy:
|
||||||
return nil
|
return nil
|
||||||
case .project, .user:
|
case .project, .user:
|
||||||
return viewRouteMiddleware
|
return viewRouteMiddleware
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ extension SiteRoute {
|
|||||||
/// The routes return html.
|
/// The routes return html.
|
||||||
public enum View: Equatable, Sendable {
|
public enum View: Equatable, Sendable {
|
||||||
case home
|
case home
|
||||||
|
case privacyPolicy
|
||||||
case login(LoginRoute)
|
case login(LoginRoute)
|
||||||
case signup(SignupRoute)
|
case signup(SignupRoute)
|
||||||
case project(ProjectRoute)
|
case project(ProjectRoute)
|
||||||
@@ -25,6 +26,10 @@ extension SiteRoute {
|
|||||||
Route(.case(Self.home)) {
|
Route(.case(Self.home)) {
|
||||||
Method.get
|
Method.get
|
||||||
}
|
}
|
||||||
|
Route(.case(Self.privacyPolicy)) {
|
||||||
|
Path { "privacy-policy" }
|
||||||
|
Method.get
|
||||||
|
}
|
||||||
Route(.case(Self.login)) {
|
Route(.case(Self.login)) {
|
||||||
SiteRoute.View.LoginRoute.router
|
SiteRoute.View.LoginRoute.router
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,6 +22,10 @@ extension ViewController.Request {
|
|||||||
return await view {
|
return await view {
|
||||||
HomeView()
|
HomeView()
|
||||||
}
|
}
|
||||||
|
case .privacyPolicy:
|
||||||
|
return await view {
|
||||||
|
PrivacyPolicyView()
|
||||||
|
}
|
||||||
case .test:
|
case .test:
|
||||||
// let projectID = UUID(uuidString: "E796C96C-F527-4753-A00A-EBCF25630663")!
|
// let projectID = UUID(uuidString: "E796C96C-F527-4753-A00A-EBCF25630663")!
|
||||||
// return await view {
|
// return await view {
|
||||||
|
|||||||
699
Sources/ViewController/Views/PrivacyPolicy.swift
Normal file
699
Sources/ViewController/Views/PrivacyPolicy.swift
Normal file
@@ -0,0 +1,699 @@
|
|||||||
|
import Elementary
|
||||||
|
|
||||||
|
struct PrivacyPolicyView: HTML, Sendable {
|
||||||
|
|
||||||
|
var body: some HTML<HTMLTag.div> {
|
||||||
|
div(.class("p-10 space-y-4")) {
|
||||||
|
h1(.class("text-3xl font-bold")) { "Privacy Policy" }
|
||||||
|
p {
|
||||||
|
"Last updated: February 10, 2026"
|
||||||
|
}
|
||||||
|
p {
|
||||||
|
"""
|
||||||
|
This Privacy Policy describes Our policies and procedures on the collection, use and disclosure
|
||||||
|
of Your information when You use the Service and tells You about Your privacy rights and how the
|
||||||
|
law protects You.
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
p {
|
||||||
|
"""
|
||||||
|
We use Your Personal Data to provide and improve the Service. By using the Service, You agree
|
||||||
|
to the collection and use of information in accordance with this Privacy Policy. This Privacy
|
||||||
|
Policy has been created with the help of the
|
||||||
|
"""
|
||||||
|
a(
|
||||||
|
.href("https://www.termsfeed.com/privacy-policy-generator/"),
|
||||||
|
.target(.blank)
|
||||||
|
) {
|
||||||
|
" TermsFeed Privacy Policy Generator"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
h2(.class("text-2xl font-bold")) { "Interpretation and Definitions" }
|
||||||
|
h3(.class("text-xl font-bold")) { "Interpretation" }
|
||||||
|
|
||||||
|
p {
|
||||||
|
"""
|
||||||
|
The words whose initial letters are capitalized have meanings defined under the
|
||||||
|
following conditions. The following definitions shall have the same meaning
|
||||||
|
regardless of whether they appear in singular or in plural.
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
|
||||||
|
h3(.class("text-xl font-bold")) { "Definitions" }
|
||||||
|
|
||||||
|
p { "For the purposes of this Privacy Policy:" }
|
||||||
|
|
||||||
|
ul(.class("list-disc px-6 space-y-2")) {
|
||||||
|
li {
|
||||||
|
span(.class("font-bold")) {
|
||||||
|
"Account"
|
||||||
|
}
|
||||||
|
" means a unique account created for You to access our Service or parts of our Service."
|
||||||
|
}
|
||||||
|
li {
|
||||||
|
span(.class("font-bold")) {
|
||||||
|
"Affiliate"
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
means an entity that controls, is controlled by, or is under common control with a
|
||||||
|
party, where "control" means ownership of 50% or more of the shares, equity interest or other
|
||||||
|
securities entitled to vote for election of directors or other managing authority.
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
li {
|
||||||
|
span(.class("font-bold")) {
|
||||||
|
"Company"
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
(referred to as either "the Company", "We", "Us" or "Our" in this Privacy Policy)
|
||||||
|
refers to Duct Calc.
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
li {
|
||||||
|
span(.class("font-bold")) {
|
||||||
|
"Cookies"
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
are small files that are placed on Your computer, mobile device or any other device by
|
||||||
|
a website, containing the details of Your browsing history on that website among its many uses.
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
li {
|
||||||
|
span(.class("font-bold")) {
|
||||||
|
"Country"
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
refers to: Ohio, United States
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
li {
|
||||||
|
span(.class("font-bold")) {
|
||||||
|
"Device"
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
means any device that can access the Service such as a computer, a cell phone or a
|
||||||
|
digital tablet.
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
li {
|
||||||
|
span(.class("font-bold")) {
|
||||||
|
"Personal Data"
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
(or "Personal Information") is any information that relates to an identified or
|
||||||
|
identifiable individual.
|
||||||
|
|
||||||
|
We use "Personal Data" and "Personal Information" interchangeably unless a law uses a specific
|
||||||
|
term.
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
li {
|
||||||
|
span(.class("font-bold")) {
|
||||||
|
"Service"
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
refers to the Website.
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
li {
|
||||||
|
span(.class("font-bold")) {
|
||||||
|
"Service Provider"
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
means any natural or legal person who processes the data on behalf of the
|
||||||
|
Company. It refers to third-party companies or individuals employed by the Company to facilitate
|
||||||
|
the Service, to provide the Service on behalf of the Company, to perform services related to the
|
||||||
|
Service or to assist the Company in analyzing how the Service is used.
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
li {
|
||||||
|
span(.class("font-bold")) {
|
||||||
|
"Usage Data"
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
refers to data collected automatically, either generated by the use of the Service
|
||||||
|
or from the Service infrastructure itself (for example, the duration of a page visit).
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
li {
|
||||||
|
span(.class("font-bold")) {
|
||||||
|
"Website"
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
refers to Duct Calc, accessible from [https://ductcalc.pro](https://ductcalc.pro).
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
li {
|
||||||
|
span(.class("font-bold")) {
|
||||||
|
"You"
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
means the individual accessing or using the Service, or the company, or other legal entity
|
||||||
|
on behalf of which such individual is accessing or using the Service, as applicable.
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
h2(.class("text-2xl font-bold")) { "Collecting and Using Your Personal Data" }
|
||||||
|
h3(.class("text-xl font-bold")) { "Types of Data Collected" }
|
||||||
|
h4(.class("text-lg font-bold")) { "Personal Data" }
|
||||||
|
|
||||||
|
p {
|
||||||
|
"""
|
||||||
|
While using Our Service, We may ask You to provide Us with certain personally identifiable
|
||||||
|
information that can be used to contact or identify You. Personally identifiable information may
|
||||||
|
include, but is not limited to:
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
|
||||||
|
ul(.class("list-disc mx-6 space-y-2")) {
|
||||||
|
li { "Email address" }
|
||||||
|
li { "First and last name" }
|
||||||
|
li { "Phone number" }
|
||||||
|
li { "Address, State, Province, ZIP/Postal Code, City" }
|
||||||
|
}
|
||||||
|
|
||||||
|
h4(.class("text-lg font-bold")) { "Usage Data" }
|
||||||
|
p {
|
||||||
|
"""
|
||||||
|
Usage Data may include information such as Your Device's Internet Protocol address (e.g. IP
|
||||||
|
address), browser type, browser version, the pages of our Service that You visit, the time and date
|
||||||
|
of Your visit, the time spent on those pages, unique device identifiers and other diagnostic data.
|
||||||
|
|
||||||
|
When You access the Service by or through a mobile device, We may collect certain information
|
||||||
|
automatically, including, but not limited to, the type of mobile device You use, Your mobile
|
||||||
|
device's unique ID, the IP address of Your mobile device, Your mobile operating system, the type of
|
||||||
|
mobile Internet browser You use, unique device identifiers and other diagnostic data.
|
||||||
|
|
||||||
|
We may also collect information that Your browser sends whenever You visit Our Service or when You
|
||||||
|
access the Service by or through a mobile device.
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
|
||||||
|
h4(.class("text-lg font-bold")) { "Tracking Technologies and Cookies" }
|
||||||
|
p {
|
||||||
|
"""
|
||||||
|
We use Cookies and similar tracking technologies to track the activity on Our Service and store
|
||||||
|
certain information. Tracking technologies We use include beacons, tags, and scripts to collect and
|
||||||
|
track information and to improve and analyze Our Service. The technologies We use may include:
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
ul(.class("list-disc mx-6 space-y-2")) {
|
||||||
|
li {
|
||||||
|
span(.class("font-bold")) { "Cookies or Browser Cookies." }
|
||||||
|
"""
|
||||||
|
A cookie is a small file placed on Your Device. You can instruct
|
||||||
|
Your browser to refuse all Cookies or to indicate when a Cookie is being sent. However, if You do
|
||||||
|
not accept Cookies, You may not be able to use some parts of our Service.
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
li {
|
||||||
|
span(.class("font-bold")) { "Web Beacons" }
|
||||||
|
"""
|
||||||
|
Certain sections of our Service and our emails may contain small electronic files
|
||||||
|
known as web beacons (also referred to as clear gifs, pixel tags, and single-pixel gifs) that
|
||||||
|
permit the Company, for example, to count users who have visited those pages or opened an email
|
||||||
|
and for other related website statistics (for example, recording the popularity of a certain
|
||||||
|
section and verifying system and server integrity).
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
"""
|
||||||
|
|
||||||
|
Cookies can be "Persistent" or "Session" Cookies. Persistent Cookies remain on Your personal
|
||||||
|
computer or mobile device when You go offline, while Session Cookies are deleted as soon as You
|
||||||
|
close Your web browser.
|
||||||
|
|
||||||
|
Where required by law, we use non-essential cookies (such as analytics, advertising, and remarketing
|
||||||
|
cookies) only with Your consent. You can withdraw or change Your consent at any time using Our
|
||||||
|
cookie preferences tool (if available) or through Your browser/device settings. Withdrawing consent
|
||||||
|
does not affect the lawfulness of processing based on consent before its withdrawal.
|
||||||
|
|
||||||
|
We use both Session and Persistent Cookies for the purposes set out below:
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
|
||||||
|
ul(.class("list-disc mx-6 space-y-2")) {
|
||||||
|
li {
|
||||||
|
p(.class("font-bold")) { "Necessary / Essential Cookies" }
|
||||||
|
p(.class("mx-6")) {
|
||||||
|
"""
|
||||||
|
Type: Session Cookies
|
||||||
|
|
||||||
|
Administered by: Us
|
||||||
|
|
||||||
|
Purpose: These Cookies are essential to provide You with services available through the Website
|
||||||
|
and to enable You to use some of its features. They help to authenticate users and prevent
|
||||||
|
fraudulent use of user accounts. Without these Cookies, the services that You have asked for
|
||||||
|
cannot be provided, and We only use these Cookies to provide You with those services.
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
li {
|
||||||
|
p(.class("font-bold")) { "Functionality Cookies" }
|
||||||
|
p(.class("mx-6")) {
|
||||||
|
"""
|
||||||
|
Type: Persistent Cookies
|
||||||
|
|
||||||
|
Administered by: Us
|
||||||
|
|
||||||
|
Purpose: These Cookies allow Us to remember choices You make when You use the Website, such as
|
||||||
|
remembering your login details or language preference. The purpose of these Cookies is to
|
||||||
|
provide You with a more personal experience and to avoid You having to re-enter your preferences
|
||||||
|
every time You use the Website.
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
"""
|
||||||
|
For more information about the cookies we use and your choices regarding cookies, please visit our
|
||||||
|
Cookies Policy or the Cookies section of Our Privacy Policy.
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
|
||||||
|
h3(.class("text-2xl font-bold")) { "Use of Your Personal Data" }
|
||||||
|
p {
|
||||||
|
"The Company may use Personal Data for the following purposes:"
|
||||||
|
}
|
||||||
|
ul(.class("list-disc mx-6 space-y-2")) {
|
||||||
|
li {
|
||||||
|
span(.class("font-bold")) { "To provide and maintain our Service" }
|
||||||
|
"""
|
||||||
|
, including to monitor the usage of our Service.
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
li {
|
||||||
|
span(.class("font-bold")) { "To manage Your Account:" }
|
||||||
|
"""
|
||||||
|
to manage Your registration as a user of the Service. The Personal
|
||||||
|
Data You provide can give You access to different functionalities of the Service that are
|
||||||
|
available to You as a registered user.
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
li {
|
||||||
|
span(.class("font-bold")) { "For the performance of a contract:" }
|
||||||
|
"""
|
||||||
|
the development, compliance and undertaking of the purchase
|
||||||
|
contract for the products, items or services You have purchased or of any other contract with Us
|
||||||
|
through the Service.
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
li {
|
||||||
|
span(.class("font-bold")) { "To contact You:" }
|
||||||
|
"""
|
||||||
|
To contact You by email, telephone calls, SMS, or other equivalent forms of
|
||||||
|
electronic communication, such as a mobile application's push notifications regarding updates or
|
||||||
|
informative communications related to the functionalities, products or contracted services,
|
||||||
|
including the security updates, when necessary or reasonable for their implementation.
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
li {
|
||||||
|
span(.class("font-bold")) { "To provide You" }
|
||||||
|
"""
|
||||||
|
with news, special offers, and general information about other goods, services
|
||||||
|
and events which We offer that are similar to those that you have already purchased or inquired
|
||||||
|
about unless You have opted not to receive such information.
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
li {
|
||||||
|
span(.class("font-bold")) { "To manage Your requests:" }
|
||||||
|
"""
|
||||||
|
To attend and manage Your requests to Us.
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
li {
|
||||||
|
span(.class("font-bold")) { "For business transfers:" }
|
||||||
|
"""
|
||||||
|
We may use Your Personal Data to evaluate or conduct a merger,
|
||||||
|
divestiture, restructuring, reorganization, dissolution, or other sale or transfer of some or all
|
||||||
|
of Our assets, whether as a going concern or as part of bankruptcy, liquidation, or similar
|
||||||
|
proceeding, in which Personal Data held by Us about our Service users is among the assets
|
||||||
|
transferred.
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
li {
|
||||||
|
span(.class("font-bold")) { "For other purposes:" }
|
||||||
|
"""
|
||||||
|
We may use Your information for other purposes, such as data analysis,
|
||||||
|
identifying usage trends, determining the effectiveness of our promotional campaigns and to
|
||||||
|
evaluate and improve our Service, products, services, marketing and your experience.
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
p {
|
||||||
|
"We may share Your Personal Data in the following situations:"
|
||||||
|
}
|
||||||
|
ul(.class("list-disc mx-6 space-y-2")) {
|
||||||
|
li {
|
||||||
|
span(.class("font-bold")) { "With Service Providers:" }
|
||||||
|
"""
|
||||||
|
We may share Your Personal Data with Service Providers to monitor and
|
||||||
|
analyze the use of our Service, to contact You.
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
li {
|
||||||
|
span(.class("font-bold")) { "For business transfers:" }
|
||||||
|
"""
|
||||||
|
We may share or transfer Your Personal Data in connection with, or
|
||||||
|
during negotiations of, any merger, sale of Company assets, financing, or acquisition of all or a
|
||||||
|
portion of Our business to another company.
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
li {
|
||||||
|
span(.class("font-bold")) { "With Affiliates:" }
|
||||||
|
"""
|
||||||
|
We may share Your Personal Data with Our affiliates, in which case we will
|
||||||
|
require those affiliates to honor this Privacy Policy. Affiliates include Our parent company and
|
||||||
|
any other subsidiaries, joint venture partners or other companies that We control or that are
|
||||||
|
under common control with Us.
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
li {
|
||||||
|
span(.class("font-bold")) { "With business partners:" }
|
||||||
|
"""
|
||||||
|
We may share Your Personal Data with Our business partners to offer
|
||||||
|
You certain products, services or promotions.
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
li {
|
||||||
|
span(.class("font-bold")) { "With other users:" }
|
||||||
|
"""
|
||||||
|
If Our Service offers public areas, when You share Personal Data or
|
||||||
|
otherwise interact in the public areas with other users, such information may be viewed by all
|
||||||
|
users and may be publicly distributed outside.
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
li {
|
||||||
|
span(.class("font-bold")) { "With Your consent:" }
|
||||||
|
"""
|
||||||
|
We may disclose Your Personal Data for any other purpose with Your consent.
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
h3(.class("text-2xl font-bold")) { "Retention of Your Personal Data" }
|
||||||
|
p {
|
||||||
|
"""
|
||||||
|
The Company will retain Your Personal Data only for as long as is necessary for the purposes set out
|
||||||
|
in this Privacy Policy. We will retain and use Your Personal Data to the extent necessary to comply
|
||||||
|
with our legal obligations (for example, if We are required to retain Your data to comply with
|
||||||
|
applicable laws), resolve disputes, and enforce our legal agreements and policies.
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
p {
|
||||||
|
"""
|
||||||
|
Where possible, We apply shorter retention periods and/or reduce identifiability by deleting,
|
||||||
|
aggregating, or anonymizing data. Unless otherwise stated, the retention periods below are maximum
|
||||||
|
periods ("up to") and We may delete or anonymize data sooner when it is no longer needed for the
|
||||||
|
relevant purpose. We apply different retention periods to different categories of Personal Data
|
||||||
|
based on the purpose of processing and legal obligations:
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
ul(.class("list-disc mx-6 space-y-2")) {
|
||||||
|
li {
|
||||||
|
"Account Information"
|
||||||
|
ul(.class("list-disc mx-6 space-y-2")) {
|
||||||
|
li {
|
||||||
|
"""
|
||||||
|
User Accounts: retained for the duration of your account relationship plus up to 24 months
|
||||||
|
after account closure to handle any post-termination issues or resolve disputes.
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
li {
|
||||||
|
"Customer Support Data"
|
||||||
|
ul(.class("list-disc mx-6 space-y-2")) {
|
||||||
|
li {
|
||||||
|
"""
|
||||||
|
Support tickets and correspondence: up to 24 months from the date of ticket closure to resolve
|
||||||
|
follow-up inquiries, track service quality, and defend against potential legal claims.
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
li {
|
||||||
|
"""
|
||||||
|
Chat transcripts: up to 24 months for quality assurance and staff training purposes.
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
li {
|
||||||
|
"Usage Data"
|
||||||
|
ul(.class("list-disc mx-6 space-y-2")) {
|
||||||
|
li {
|
||||||
|
"""
|
||||||
|
Website analytics data (cookies, IP addresses, device identifiers): up to 24 months from the
|
||||||
|
date of collection, which allows us to analyze trends while respecting privacy principles.
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
li {
|
||||||
|
"""
|
||||||
|
Server logs (IP addresses, access times): up to 24 months for security monitoring and
|
||||||
|
troubleshooting purposes.
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
p {
|
||||||
|
"""
|
||||||
|
Usage Data is retained in accordance with the retention periods described above, and may be retained
|
||||||
|
longer only where necessary for security, fraud prevention, or legal compliance.
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
p {
|
||||||
|
"""
|
||||||
|
We may retain Personal Data beyond the periods stated above for different reasons:
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
ul(.class("list-disc mx-6 space-y-2")) {
|
||||||
|
li {
|
||||||
|
"""
|
||||||
|
Legal obligation: We are required by law to retain specific data (e.g., financial records for tax
|
||||||
|
authorities).
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
li {
|
||||||
|
"""
|
||||||
|
Legal claims: Data is necessary to establish, exercise, or defend legal claims.
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
li {
|
||||||
|
"""
|
||||||
|
Your explicit request: You ask Us to retain specific information.
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
li {
|
||||||
|
"""
|
||||||
|
Technical limitations: Data exists in backup systems that are scheduled for routine deletion.
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
p {
|
||||||
|
"""
|
||||||
|
You may request information about how long We will retain Your Personal Data by contacting Us.
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
p {
|
||||||
|
"""
|
||||||
|
When retention periods expire, We securely delete or anonymize Personal Data according to the
|
||||||
|
following procedures:
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
ul(.class("list-disc mx-6 space-y-2")) {
|
||||||
|
li {
|
||||||
|
"""
|
||||||
|
Deletion: Personal Data is removed from Our systems and no longer actively processed.
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
li {
|
||||||
|
"""
|
||||||
|
Backup retention: Residual copies may remain in encrypted backups for a limited period consistent
|
||||||
|
with our backup retention schedule and are not restored except where necessary for security,
|
||||||
|
disaster recovery, or legal compliance.
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
li {
|
||||||
|
"""
|
||||||
|
Anonymization: In some cases, We convert Personal Data into anonymous statistical data that cannot
|
||||||
|
be linked back to You. This anonymized data may be retained indefinitely for research and
|
||||||
|
analytics.
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
h3(.class("text-xl font-bold")) { "Transfer of Your Personal Data" }
|
||||||
|
p {
|
||||||
|
"""
|
||||||
|
Your information, including Personal Data, is processed at the Company's operating offices and in
|
||||||
|
any other places where the parties involved in the processing are located. It means that this
|
||||||
|
information may be transferred to — and maintained on — computers located outside of Your state,
|
||||||
|
province, country or other governmental jurisdiction where the data protection laws may differ from
|
||||||
|
those from Your jurisdiction.
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
p {
|
||||||
|
"""
|
||||||
|
Where required by applicable law, We will ensure that international transfers of Your Personal Data
|
||||||
|
are subject to appropriate safeguards and supplementary measures where appropriate. The Company will
|
||||||
|
take all steps reasonably necessary to ensure that Your data is treated securely and in accordance
|
||||||
|
with this Privacy Policy and no transfer of Your Personal Data will take place to an organization or
|
||||||
|
a country unless there are adequate controls in place including the security of Your data and other
|
||||||
|
personal information.
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
|
||||||
|
h3(.class("text-xl font-bold")) { "Delete Your Personal Data" }
|
||||||
|
p {
|
||||||
|
"""
|
||||||
|
You have the right to delete or request that We assist in deleting the Personal Data that We have
|
||||||
|
collected about You.
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
p {
|
||||||
|
"""
|
||||||
|
Our Service may give You the ability to delete certain information about You from within the
|
||||||
|
Service.
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
p {
|
||||||
|
"""
|
||||||
|
You may update, amend, or delete Your information at any time by signing in to Your Account, if you
|
||||||
|
have one, and visiting the account settings section that allows you to manage Your personal
|
||||||
|
information. You may also contact Us to request access to, correct, or delete any Personal Data that
|
||||||
|
You have provided to Us.
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
p {
|
||||||
|
"""
|
||||||
|
Please note, however, that We may need to retain certain information when we have a legal obligation
|
||||||
|
or lawful basis to do so.
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
|
||||||
|
h3(.class("text-xl font-bold")) { "Disclosure of Your Personal Data" }
|
||||||
|
|
||||||
|
h4(.class("text-lg font-bold")) { "Business Transactions" }
|
||||||
|
p {
|
||||||
|
"""
|
||||||
|
If the Company is involved in a merger, acquisition or asset sale, Your Personal Data may be
|
||||||
|
transferred. We will provide notice before Your Personal Data is transferred and becomes subject to
|
||||||
|
a different Privacy Policy.
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
|
||||||
|
h4(.class("text-lg font-bold")) { "Law enforcement" }
|
||||||
|
p {
|
||||||
|
"""
|
||||||
|
Under certain circumstances, the Company may be required to disclose Your Personal Data if required
|
||||||
|
to do so by law or in response to valid requests by public authorities (e.g. a court or a government
|
||||||
|
agency).
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
|
||||||
|
h4(.class("text-lg font-bold")) { "Other legal requirements" }
|
||||||
|
p {
|
||||||
|
"""
|
||||||
|
The Company may disclose Your Personal Data in the good faith belief that such action is necessary
|
||||||
|
to:
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
ul(.class("list-disc mx-6 space-y-2")) {
|
||||||
|
li { "Comply with a legal obligation" }
|
||||||
|
li { "Protect and defend the rights or property of the Company" }
|
||||||
|
li { "Prevent or investigate possible wrongdoing in connection with the Service" }
|
||||||
|
li { "Protect the personal safety of Users of the Service or the public" }
|
||||||
|
li { "Protect against legal liability" }
|
||||||
|
}
|
||||||
|
|
||||||
|
h3(.class("text-xl font-bold")) { "Security of Your Personal Data" }
|
||||||
|
p {
|
||||||
|
"""
|
||||||
|
The security of Your Personal Data is important to Us, but remember that no method of transmission
|
||||||
|
over the Internet, or method of electronic storage is 100% secure. While We strive to use
|
||||||
|
commercially reasonable means to protect Your Personal Data, We cannot guarantee its absolute
|
||||||
|
security.
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
|
||||||
|
h2(.class("text-2xl font-bold")) { "Children's Privacy" }
|
||||||
|
p {
|
||||||
|
"""
|
||||||
|
Our Service does not address anyone under the age of 16. We do not knowingly collect personally
|
||||||
|
identifiable information from anyone under the age of 16. If You are a parent or guardian and You
|
||||||
|
are aware that Your child has provided Us with Personal Data, please contact Us. If We become aware
|
||||||
|
that We have collected Personal Data from anyone under the age of 16 without verification of
|
||||||
|
parental consent, We take steps to remove that information from Our servers.
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
p {
|
||||||
|
"""
|
||||||
|
If We need to rely on consent as a legal basis for processing Your information and Your country
|
||||||
|
requires consent from a parent, We may require Your parent's consent before We collect and use that
|
||||||
|
information.
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
|
||||||
|
h2(.class("text-2xl font-bold")) { "Links to Other Websites" }
|
||||||
|
p {
|
||||||
|
"""
|
||||||
|
Our Service may contain links to other websites that are not operated by Us. If You click on a third
|
||||||
|
party link, You will be directed to that third party's site. We strongly advise You to review the
|
||||||
|
Privacy Policy of every site You visit.
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
p {
|
||||||
|
"""
|
||||||
|
We have no control over and assume no responsibility for the content, privacy policies or practices
|
||||||
|
of any third party sites or services.
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
|
||||||
|
h2(.class("text-2xl font-bold")) { "Changes to this Privacy Policy" }
|
||||||
|
p {
|
||||||
|
"""
|
||||||
|
We may update Our Privacy Policy from time to time. We will notify You of any changes by posting the
|
||||||
|
new Privacy Policy on this page.
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
p {
|
||||||
|
"""
|
||||||
|
We will let You know via email and/or a prominent notice on Our Service, prior to the change
|
||||||
|
becoming effective and update the "Last updated" date at the top of this Privacy Policy.
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
p {
|
||||||
|
"""
|
||||||
|
You are advised to review this Privacy Policy periodically for any changes. Changes to this Privacy
|
||||||
|
Policy are effective when they are posted on this page.
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
|
||||||
|
h2(.class("text-2xl font-bold")) { "Contact Us" }
|
||||||
|
p {
|
||||||
|
"""
|
||||||
|
If you have any questions about this Privacy Policy, You can contact us:
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
|
||||||
|
ul(.class("list-disc mx-6 space-y-2")) {
|
||||||
|
li {
|
||||||
|
span { "By email: " }
|
||||||
|
a(
|
||||||
|
.href("mailto://support@ductcalc.pro"),
|
||||||
|
.class("btn btn-link")
|
||||||
|
) {
|
||||||
|
"support@ductcalc.pro"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -22,7 +22,16 @@ struct LoginForm: HTML, Sendable {
|
|||||||
|
|
||||||
var body: some HTML {
|
var body: some HTML {
|
||||||
ModalForm(id: "loginForm", closeButton: false, dismiss: false) {
|
ModalForm(id: "loginForm", closeButton: false, dismiss: false) {
|
||||||
h1(.class("text-2xl font-bold mb-6")) { style.title }
|
Row {
|
||||||
|
h1(.class("text-2xl font-bold mb-6")) { style.title }
|
||||||
|
a(
|
||||||
|
.class("btn btn-link"),
|
||||||
|
.href(route: .privacyPolicy),
|
||||||
|
.target(.blank)
|
||||||
|
) {
|
||||||
|
"Privacy Policy"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
form(
|
form(
|
||||||
.method(.post),
|
.method(.post),
|
||||||
@@ -78,6 +87,7 @@ struct LoginForm: HTML, Sendable {
|
|||||||
"At least one uppercase letter"
|
"At least one uppercase letter"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
div(.class("flex")) {
|
div(.class("flex")) {
|
||||||
|
|||||||
3
TODO.md
3
TODO.md
@@ -20,3 +20,6 @@
|
|||||||
- [x] Update urls to point to public mirror of repository
|
- [x] Update urls to point to public mirror of repository
|
||||||
- [x] Add email to footer
|
- [x] Add email to footer
|
||||||
- [x] Validation errors, if they occur are vague in ResultView
|
- [x] Validation errors, if they occur are vague in ResultView
|
||||||
|
- [x] Privacy policy
|
||||||
|
- [ ] Update README
|
||||||
|
- [ ] Self hosting documentation
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ struct ViewControllerTests {
|
|||||||
$0.auth = .failing
|
$0.auth = .failing
|
||||||
} operation: {
|
} operation: {
|
||||||
@Dependency(\.viewController) var viewController
|
@Dependency(\.viewController) var viewController
|
||||||
|
|
||||||
let home = try await viewController.view(.test(.home))
|
let home = try await viewController.view(.test(.home))
|
||||||
assertSnapshot(of: home, as: .html)
|
assertSnapshot(of: home, as: .html)
|
||||||
}
|
}
|
||||||
@@ -39,6 +38,18 @@ struct ViewControllerTests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
func privacyPolicy() async throws {
|
||||||
|
try await withDependencies {
|
||||||
|
$0.viewController = .liveValue
|
||||||
|
$0.auth = .failing
|
||||||
|
} operation: {
|
||||||
|
@Dependency(\.viewController) var viewController
|
||||||
|
let view = try await viewController.view(.test(.privacyPolicy))
|
||||||
|
assertSnapshot(of: view, as: .html)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
func login() async throws {
|
func login() async throws {
|
||||||
try await withDependencies {
|
try await withDependencies {
|
||||||
|
|||||||
@@ -33,7 +33,10 @@
|
|||||||
<main class="flex flex-col min-h-screen min-w-full grow mb-auto">
|
<main class="flex flex-col min-h-screen min-w-full grow mb-auto">
|
||||||
<dialog id="loginForm" class="modal modal-open">
|
<dialog id="loginForm" class="modal modal-open">
|
||||||
<div class="modal-box">
|
<div class="modal-box">
|
||||||
<h1 class="text-2xl font-bold mb-6">Login</h1>
|
<div class="flex justify-between">
|
||||||
|
<h1 class="text-2xl font-bold mb-6">Login</h1>
|
||||||
|
Privacy Policy<a class="btn btn-link" href="/privacy-policy" target="_blank"></a>
|
||||||
|
</div>
|
||||||
<form method="post" class="space-y-4">
|
<form method="post" class="space-y-4">
|
||||||
<div>
|
<div>
|
||||||
<label class="input validator w-full"> <svg class="h-[1em] opacity-50" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
<label class="input validator w-full"> <svg class="h-[1em] opacity-50" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
||||||
|
|||||||
@@ -0,0 +1,475 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<title>Duct Calc</title>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<meta content="ductcalc.com" name="og:site_name">
|
||||||
|
<meta content="Duct Calc" name="og:title">
|
||||||
|
<meta content="Duct sizing based on ACCA, Manual-D." name="description">
|
||||||
|
<meta content="Duct sizing based on ACCA, Manual-D." name="og:description">
|
||||||
|
<meta content="/images/mand_logo.png" name="og:image">
|
||||||
|
<meta content="/images/mand_logo.png" name="twitter:image">
|
||||||
|
<meta content="Duct Calc" name="twitter:image:alt">
|
||||||
|
<meta content="summary_large_image" name="twitter:card">
|
||||||
|
<meta content="1536" name="og:image:width">
|
||||||
|
<meta content="1024" name="og:image:height">
|
||||||
|
<meta content="duct, hvac, duct-design, duct design, manual-d, manual d, design" name="keywords">
|
||||||
|
<script src="https://unpkg.com/htmx.org@2.0.8"></script>
|
||||||
|
<script src="/js/htmx-download.js"></script>
|
||||||
|
<script src="/js/main.js"></script>
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>
|
||||||
|
<link rel="stylesheet" href="/css/output.css">
|
||||||
|
<link rel="stylesheet" href="/css/htmx.css">
|
||||||
|
<link rel="icon" href="/images/favicon.ico" type="image/x-icon">
|
||||||
|
<link rel="icon" href="/images/favicon-32x32.png" type="image/png">
|
||||||
|
<link rel="icon" href="/images/favicon-16x16.png" type="image/png">
|
||||||
|
<link rel="apple-touch-icon" sizes="180x180" href="/images/apple-touch-icon.png">
|
||||||
|
<link rel="manifest" href="/site.webmanifest">
|
||||||
|
<script src="https://unpkg.com/htmx-remove@latest" crossorigin="anonymous" integrity="sha384-NwB2Xh66PNEYfVki0ao13UAFmdNtMIdBKZ8sNGRT6hKfCPaINuZ4ScxS6vVAycPT"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="flex flex-col min-h-screen min-w-full justify-between" data-theme="default">
|
||||||
|
<main class="flex flex-col min-h-screen min-w-full grow mb-auto">
|
||||||
|
<div class="p-10 space-y-4">
|
||||||
|
<h1 class="text-3xl font-bold">Privacy Policy</h1>
|
||||||
|
<p>Last updated: February 10, 2026</p>
|
||||||
|
<p>
|
||||||
|
This Privacy Policy describes Our policies and procedures on the collection, use and disclosure
|
||||||
|
of Your information when You use the Service and tells You about Your privacy rights and how the
|
||||||
|
law protects You.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
We use Your Personal Data to provide and improve the Service. By using the Service, You agree
|
||||||
|
to the collection and use of information in accordance with this Privacy Policy. This Privacy
|
||||||
|
Policy has been created with the help of the<a href="https://www.termsfeed.com/privacy-policy-generator/" target="_blank"> TermsFeed Privacy Policy Generator</a>
|
||||||
|
</p>
|
||||||
|
<h2 class="text-2xl font-bold">Interpretation and Definitions</h2>
|
||||||
|
<h3 class="text-xl font-bold">Interpretation</h3>
|
||||||
|
<p>
|
||||||
|
The words whose initial letters are capitalized have meanings defined under the
|
||||||
|
following conditions. The following definitions shall have the same meaning
|
||||||
|
regardless of whether they appear in singular or in plural.
|
||||||
|
</p>
|
||||||
|
<h3 class="text-xl font-bold">Definitions</h3>
|
||||||
|
<p>For the purposes of this Privacy Policy:</p>
|
||||||
|
<ul class="list-disc px-6 space-y-2">
|
||||||
|
<li><span class="font-bold">Account</span> means a unique account created for You to access our Service or parts of our Service.</li>
|
||||||
|
<li>
|
||||||
|
<span class="font-bold">Affiliate</span> means an entity that controls, is controlled by, or is under common control with a
|
||||||
|
party, where "control" means ownership of 50% or more of the shares, equity interest or other
|
||||||
|
securities entitled to vote for election of directors or other managing authority.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span class="font-bold">Company</span> (referred to as either "the Company", "We", "Us" or "Our" in this Privacy Policy)
|
||||||
|
refers to Duct Calc.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span class="font-bold">Cookies</span> are small files that are placed on Your computer, mobile device or any other device by
|
||||||
|
a website, containing the details of Your browsing history on that website among its many uses.
|
||||||
|
</li>
|
||||||
|
<li><span class="font-bold">Country</span> refers to: Ohio, United States</li>
|
||||||
|
<li>
|
||||||
|
<span class="font-bold">Device</span> means any device that can access the Service such as a computer, a cell phone or a
|
||||||
|
digital tablet.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span class="font-bold">Personal Data</span> (or "Personal Information") is any information that relates to an identified or
|
||||||
|
identifiable individual.
|
||||||
|
|
||||||
|
We use "Personal Data" and "Personal Information" interchangeably unless a law uses a specific
|
||||||
|
term.
|
||||||
|
</li>
|
||||||
|
<li><span class="font-bold">Service</span> refers to the Website.</li>
|
||||||
|
<li>
|
||||||
|
<span class="font-bold">Service Provider</span> means any natural or legal person who processes the data on behalf of the
|
||||||
|
Company. It refers to third-party companies or individuals employed by the Company to facilitate
|
||||||
|
the Service, to provide the Service on behalf of the Company, to perform services related to the
|
||||||
|
Service or to assist the Company in analyzing how the Service is used.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span class="font-bold">Usage Data</span> refers to data collected automatically, either generated by the use of the Service
|
||||||
|
or from the Service infrastructure itself (for example, the duration of a page visit).
|
||||||
|
</li>
|
||||||
|
<li><span class="font-bold">Website</span> refers to Duct Calc, accessible from [https://ductcalc.pro](https://ductcalc.pro).</li>
|
||||||
|
<li>
|
||||||
|
<span class="font-bold">You</span> means the individual accessing or using the Service, or the company, or other legal entity
|
||||||
|
on behalf of which such individual is accessing or using the Service, as applicable.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<h2 class="text-2xl font-bold">Collecting and Using Your Personal Data</h2>
|
||||||
|
<h3 class="text-xl font-bold">Types of Data Collected</h3>
|
||||||
|
<h4 class="text-lg font-bold">Personal Data</h4>
|
||||||
|
<p>
|
||||||
|
While using Our Service, We may ask You to provide Us with certain personally identifiable
|
||||||
|
information that can be used to contact or identify You. Personally identifiable information may
|
||||||
|
include, but is not limited to:
|
||||||
|
</p>
|
||||||
|
<ul class="list-disc mx-6 space-y-2">
|
||||||
|
<li>Email address</li>
|
||||||
|
<li>First and last name</li>
|
||||||
|
<li>Phone number</li>
|
||||||
|
<li>Address, State, Province, ZIP/Postal Code, City</li>
|
||||||
|
</ul>
|
||||||
|
<h4 class="text-lg font-bold">Usage Data</h4>
|
||||||
|
<p>
|
||||||
|
Usage Data may include information such as Your Device's Internet Protocol address (e.g. IP
|
||||||
|
address), browser type, browser version, the pages of our Service that You visit, the time and date
|
||||||
|
of Your visit, the time spent on those pages, unique device identifiers and other diagnostic data.
|
||||||
|
|
||||||
|
When You access the Service by or through a mobile device, We may collect certain information
|
||||||
|
automatically, including, but not limited to, the type of mobile device You use, Your mobile
|
||||||
|
device's unique ID, the IP address of Your mobile device, Your mobile operating system, the type of
|
||||||
|
mobile Internet browser You use, unique device identifiers and other diagnostic data.
|
||||||
|
|
||||||
|
We may also collect information that Your browser sends whenever You visit Our Service or when You
|
||||||
|
access the Service by or through a mobile device.
|
||||||
|
</p>
|
||||||
|
<h4 class="text-lg font-bold">Tracking Technologies and Cookies</h4>
|
||||||
|
<p>
|
||||||
|
We use Cookies and similar tracking technologies to track the activity on Our Service and store
|
||||||
|
certain information. Tracking technologies We use include beacons, tags, and scripts to collect and
|
||||||
|
track information and to improve and analyze Our Service. The technologies We use may include:
|
||||||
|
</p>
|
||||||
|
<ul class="list-disc mx-6 space-y-2">
|
||||||
|
<li>
|
||||||
|
<span class="font-bold">Cookies or Browser Cookies.</span> A cookie is a small file placed on Your Device. You can instruct
|
||||||
|
Your browser to refuse all Cookies or to indicate when a Cookie is being sent. However, if You do
|
||||||
|
not accept Cookies, You may not be able to use some parts of our Service.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span class="font-bold">Web Beacons</span> Certain sections of our Service and our emails may contain small electronic files
|
||||||
|
known as web beacons (also referred to as clear gifs, pixel tags, and single-pixel gifs) that
|
||||||
|
permit the Company, for example, to count users who have visited those pages or opened an email
|
||||||
|
and for other related website statistics (for example, recording the popularity of a certain
|
||||||
|
section and verifying system and server integrity).
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<p>
|
||||||
|
|
||||||
|
Cookies can be "Persistent" or "Session" Cookies. Persistent Cookies remain on Your personal
|
||||||
|
computer or mobile device when You go offline, while Session Cookies are deleted as soon as You
|
||||||
|
close Your web browser.
|
||||||
|
|
||||||
|
Where required by law, we use non-essential cookies (such as analytics, advertising, and remarketing
|
||||||
|
cookies) only with Your consent. You can withdraw or change Your consent at any time using Our
|
||||||
|
cookie preferences tool (if available) or through Your browser/device settings. Withdrawing consent
|
||||||
|
does not affect the lawfulness of processing based on consent before its withdrawal.
|
||||||
|
|
||||||
|
We use both Session and Persistent Cookies for the purposes set out below:
|
||||||
|
</p>
|
||||||
|
<ul class="list-disc mx-6 space-y-2">
|
||||||
|
<li>
|
||||||
|
<p class="font-bold">Necessary / Essential Cookies</p>
|
||||||
|
<p class="mx-6">
|
||||||
|
Type: Session Cookies
|
||||||
|
|
||||||
|
Administered by: Us
|
||||||
|
|
||||||
|
Purpose: These Cookies are essential to provide You with services available through the Website
|
||||||
|
and to enable You to use some of its features. They help to authenticate users and prevent
|
||||||
|
fraudulent use of user accounts. Without these Cookies, the services that You have asked for
|
||||||
|
cannot be provided, and We only use these Cookies to provide You with those services.
|
||||||
|
</p>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<p class="font-bold">Functionality Cookies</p>
|
||||||
|
<p class="mx-6">
|
||||||
|
Type: Persistent Cookies
|
||||||
|
|
||||||
|
Administered by: Us
|
||||||
|
|
||||||
|
Purpose: These Cookies allow Us to remember choices You make when You use the Website, such as
|
||||||
|
remembering your login details or language preference. The purpose of these Cookies is to
|
||||||
|
provide You with a more personal experience and to avoid You having to re-enter your preferences
|
||||||
|
every time You use the Website.
|
||||||
|
</p>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<p>
|
||||||
|
For more information about the cookies we use and your choices regarding cookies, please visit our
|
||||||
|
Cookies Policy or the Cookies section of Our Privacy Policy.
|
||||||
|
</p>
|
||||||
|
<h3 class="text-2xl font-bold">Use of Your Personal Data</h3>
|
||||||
|
<p>The Company may use Personal Data for the following purposes:</p>
|
||||||
|
<ul class="list-disc mx-6 space-y-2">
|
||||||
|
<li><span class="font-bold">To provide and maintain our Service</span>, including to monitor the usage of our Service.</li>
|
||||||
|
<li>
|
||||||
|
<span class="font-bold">To manage Your Account:</span> to manage Your registration as a user of the Service. The Personal
|
||||||
|
Data You provide can give You access to different functionalities of the Service that are
|
||||||
|
available to You as a registered user.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span class="font-bold">For the performance of a contract:</span> the development, compliance and undertaking of the purchase
|
||||||
|
contract for the products, items or services You have purchased or of any other contract with Us
|
||||||
|
through the Service.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span class="font-bold">To contact You:</span> To contact You by email, telephone calls, SMS, or other equivalent forms of
|
||||||
|
electronic communication, such as a mobile application's push notifications regarding updates or
|
||||||
|
informative communications related to the functionalities, products or contracted services,
|
||||||
|
including the security updates, when necessary or reasonable for their implementation.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span class="font-bold">To provide You</span> with news, special offers, and general information about other goods, services
|
||||||
|
and events which We offer that are similar to those that you have already purchased or inquired
|
||||||
|
about unless You have opted not to receive such information.
|
||||||
|
</li>
|
||||||
|
<li><span class="font-bold">To manage Your requests:</span> To attend and manage Your requests to Us.</li>
|
||||||
|
<li>
|
||||||
|
<span class="font-bold">For business transfers:</span> We may use Your Personal Data to evaluate or conduct a merger,
|
||||||
|
divestiture, restructuring, reorganization, dissolution, or other sale or transfer of some or all
|
||||||
|
of Our assets, whether as a going concern or as part of bankruptcy, liquidation, or similar
|
||||||
|
proceeding, in which Personal Data held by Us about our Service users is among the assets
|
||||||
|
transferred.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span class="font-bold">For other purposes:</span> We may use Your information for other purposes, such as data analysis,
|
||||||
|
identifying usage trends, determining the effectiveness of our promotional campaigns and to
|
||||||
|
evaluate and improve our Service, products, services, marketing and your experience.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<p>We may share Your Personal Data in the following situations:</p>
|
||||||
|
<ul class="list-disc mx-6 space-y-2">
|
||||||
|
<li>
|
||||||
|
<span class="font-bold">With Service Providers:</span> We may share Your Personal Data with Service Providers to monitor and
|
||||||
|
analyze the use of our Service, to contact You.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span class="font-bold">For business transfers:</span> We may share or transfer Your Personal Data in connection with, or
|
||||||
|
during negotiations of, any merger, sale of Company assets, financing, or acquisition of all or a
|
||||||
|
portion of Our business to another company.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span class="font-bold">With Affiliates:</span> We may share Your Personal Data with Our affiliates, in which case we will
|
||||||
|
require those affiliates to honor this Privacy Policy. Affiliates include Our parent company and
|
||||||
|
any other subsidiaries, joint venture partners or other companies that We control or that are
|
||||||
|
under common control with Us.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span class="font-bold">With business partners:</span> We may share Your Personal Data with Our business partners to offer
|
||||||
|
You certain products, services or promotions.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span class="font-bold">With other users:</span> If Our Service offers public areas, when You share Personal Data or
|
||||||
|
otherwise interact in the public areas with other users, such information may be viewed by all
|
||||||
|
users and may be publicly distributed outside.
|
||||||
|
</li>
|
||||||
|
<li><span class="font-bold">With Your consent:</span> We may disclose Your Personal Data for any other purpose with Your consent.</li>
|
||||||
|
</ul>
|
||||||
|
<h3 class="text-2xl font-bold">Retention of Your Personal Data</h3>
|
||||||
|
<p>
|
||||||
|
The Company will retain Your Personal Data only for as long as is necessary for the purposes set out
|
||||||
|
in this Privacy Policy. We will retain and use Your Personal Data to the extent necessary to comply
|
||||||
|
with our legal obligations (for example, if We are required to retain Your data to comply with
|
||||||
|
applicable laws), resolve disputes, and enforce our legal agreements and policies.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Where possible, We apply shorter retention periods and/or reduce identifiability by deleting,
|
||||||
|
aggregating, or anonymizing data. Unless otherwise stated, the retention periods below are maximum
|
||||||
|
periods ("up to") and We may delete or anonymize data sooner when it is no longer needed for the
|
||||||
|
relevant purpose. We apply different retention periods to different categories of Personal Data
|
||||||
|
based on the purpose of processing and legal obligations:
|
||||||
|
</p>
|
||||||
|
<ul class="list-disc mx-6 space-y-2">
|
||||||
|
<li>
|
||||||
|
Account Information
|
||||||
|
<ul class="list-disc mx-6 space-y-2">
|
||||||
|
<li>
|
||||||
|
User Accounts: retained for the duration of your account relationship plus up to 24 months
|
||||||
|
after account closure to handle any post-termination issues or resolve disputes.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
Customer Support Data
|
||||||
|
<ul class="list-disc mx-6 space-y-2">
|
||||||
|
<li>
|
||||||
|
Support tickets and correspondence: up to 24 months from the date of ticket closure to resolve
|
||||||
|
follow-up inquiries, track service quality, and defend against potential legal claims.
|
||||||
|
</li>
|
||||||
|
<li>Chat transcripts: up to 24 months for quality assurance and staff training purposes.</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
Usage Data
|
||||||
|
<ul class="list-disc mx-6 space-y-2">
|
||||||
|
<li>
|
||||||
|
Website analytics data (cookies, IP addresses, device identifiers): up to 24 months from the
|
||||||
|
date of collection, which allows us to analyze trends while respecting privacy principles.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
Server logs (IP addresses, access times): up to 24 months for security monitoring and
|
||||||
|
troubleshooting purposes.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<p>
|
||||||
|
Usage Data is retained in accordance with the retention periods described above, and may be retained
|
||||||
|
longer only where necessary for security, fraud prevention, or legal compliance.
|
||||||
|
</p>
|
||||||
|
<p>We may retain Personal Data beyond the periods stated above for different reasons:</p>
|
||||||
|
<ul class="list-disc mx-6 space-y-2">
|
||||||
|
<li>
|
||||||
|
Legal obligation: We are required by law to retain specific data (e.g., financial records for tax
|
||||||
|
authorities).
|
||||||
|
</li>
|
||||||
|
<li>Legal claims: Data is necessary to establish, exercise, or defend legal claims.</li>
|
||||||
|
<li>Your explicit request: You ask Us to retain specific information.</li>
|
||||||
|
<li>Technical limitations: Data exists in backup systems that are scheduled for routine deletion.</li>
|
||||||
|
</ul>
|
||||||
|
<p>You may request information about how long We will retain Your Personal Data by contacting Us.</p>
|
||||||
|
<p>
|
||||||
|
When retention periods expire, We securely delete or anonymize Personal Data according to the
|
||||||
|
following procedures:
|
||||||
|
</p>
|
||||||
|
<ul class="list-disc mx-6 space-y-2">
|
||||||
|
<li>Deletion: Personal Data is removed from Our systems and no longer actively processed.</li>
|
||||||
|
<li>
|
||||||
|
Backup retention: Residual copies may remain in encrypted backups for a limited period consistent
|
||||||
|
with our backup retention schedule and are not restored except where necessary for security,
|
||||||
|
disaster recovery, or legal compliance.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
Anonymization: In some cases, We convert Personal Data into anonymous statistical data that cannot
|
||||||
|
be linked back to You. This anonymized data may be retained indefinitely for research and
|
||||||
|
analytics.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<h3 class="text-xl font-bold">Transfer of Your Personal Data</h3>
|
||||||
|
<p>
|
||||||
|
Your information, including Personal Data, is processed at the Company's operating offices and in
|
||||||
|
any other places where the parties involved in the processing are located. It means that this
|
||||||
|
information may be transferred to — and maintained on — computers located outside of Your state,
|
||||||
|
province, country or other governmental jurisdiction where the data protection laws may differ from
|
||||||
|
those from Your jurisdiction.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Where required by applicable law, We will ensure that international transfers of Your Personal Data
|
||||||
|
are subject to appropriate safeguards and supplementary measures where appropriate. The Company will
|
||||||
|
take all steps reasonably necessary to ensure that Your data is treated securely and in accordance
|
||||||
|
with this Privacy Policy and no transfer of Your Personal Data will take place to an organization or
|
||||||
|
a country unless there are adequate controls in place including the security of Your data and other
|
||||||
|
personal information.
|
||||||
|
</p>
|
||||||
|
<h3 class="text-xl font-bold">Delete Your Personal Data</h3>
|
||||||
|
<p>
|
||||||
|
You have the right to delete or request that We assist in deleting the Personal Data that We have
|
||||||
|
collected about You.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Our Service may give You the ability to delete certain information about You from within the
|
||||||
|
Service.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
You may update, amend, or delete Your information at any time by signing in to Your Account, if you
|
||||||
|
have one, and visiting the account settings section that allows you to manage Your personal
|
||||||
|
information. You may also contact Us to request access to, correct, or delete any Personal Data that
|
||||||
|
You have provided to Us.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Please note, however, that We may need to retain certain information when we have a legal obligation
|
||||||
|
or lawful basis to do so.
|
||||||
|
</p>
|
||||||
|
<h3 class="text-xl font-bold">Disclosure of Your Personal Data</h3>
|
||||||
|
<h4 class="text-lg font-bold">Business Transactions</h4>
|
||||||
|
<p>
|
||||||
|
If the Company is involved in a merger, acquisition or asset sale, Your Personal Data may be
|
||||||
|
transferred. We will provide notice before Your Personal Data is transferred and becomes subject to
|
||||||
|
a different Privacy Policy.
|
||||||
|
</p>
|
||||||
|
<h4 class="text-lg font-bold">Law enforcement</h4>
|
||||||
|
<p>
|
||||||
|
Under certain circumstances, the Company may be required to disclose Your Personal Data if required
|
||||||
|
to do so by law or in response to valid requests by public authorities (e.g. a court or a government
|
||||||
|
agency).
|
||||||
|
</p>
|
||||||
|
<h4 class="text-lg font-bold">Other legal requirements</h4>
|
||||||
|
<p>
|
||||||
|
The Company may disclose Your Personal Data in the good faith belief that such action is necessary
|
||||||
|
to:
|
||||||
|
</p>
|
||||||
|
<ul class="list-disc mx-6 space-y-2">
|
||||||
|
<li>Comply with a legal obligation</li>
|
||||||
|
<li>Protect and defend the rights or property of the Company</li>
|
||||||
|
<li>Prevent or investigate possible wrongdoing in connection with the Service</li>
|
||||||
|
<li>Protect the personal safety of Users of the Service or the public</li>
|
||||||
|
<li>Protect against legal liability</li>
|
||||||
|
</ul>
|
||||||
|
<h3 class="text-xl font-bold">Security of Your Personal Data</h3>
|
||||||
|
<p>
|
||||||
|
The security of Your Personal Data is important to Us, but remember that no method of transmission
|
||||||
|
over the Internet, or method of electronic storage is 100% secure. While We strive to use
|
||||||
|
commercially reasonable means to protect Your Personal Data, We cannot guarantee its absolute
|
||||||
|
security.
|
||||||
|
</p>
|
||||||
|
<h2 class="text-2xl font-bold">Children's Privacy</h2>
|
||||||
|
<p>
|
||||||
|
Our Service does not address anyone under the age of 16. We do not knowingly collect personally
|
||||||
|
identifiable information from anyone under the age of 16. If You are a parent or guardian and You
|
||||||
|
are aware that Your child has provided Us with Personal Data, please contact Us. If We become aware
|
||||||
|
that We have collected Personal Data from anyone under the age of 16 without verification of
|
||||||
|
parental consent, We take steps to remove that information from Our servers.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
If We need to rely on consent as a legal basis for processing Your information and Your country
|
||||||
|
requires consent from a parent, We may require Your parent's consent before We collect and use that
|
||||||
|
information.
|
||||||
|
</p>
|
||||||
|
<h2 class="text-2xl font-bold">Links to Other Websites</h2>
|
||||||
|
<p>
|
||||||
|
Our Service may contain links to other websites that are not operated by Us. If You click on a third
|
||||||
|
party link, You will be directed to that third party's site. We strongly advise You to review the
|
||||||
|
Privacy Policy of every site You visit.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
We have no control over and assume no responsibility for the content, privacy policies or practices
|
||||||
|
of any third party sites or services.
|
||||||
|
</p>
|
||||||
|
<h2 class="text-2xl font-bold">Changes to this Privacy Policy</h2>
|
||||||
|
<p>
|
||||||
|
We may update Our Privacy Policy from time to time. We will notify You of any changes by posting the
|
||||||
|
new Privacy Policy on this page.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
We will let You know via email and/or a prominent notice on Our Service, prior to the change
|
||||||
|
becoming effective and update the "Last updated" date at the top of this Privacy Policy.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
You are advised to review this Privacy Policy periodically for any changes. Changes to this Privacy
|
||||||
|
Policy are effective when they are posted on this page.
|
||||||
|
</p>
|
||||||
|
<h2 class="text-2xl font-bold">Contact Us</h2>
|
||||||
|
<p>If you have any questions about this Privacy Policy, You can contact us:</p>
|
||||||
|
<ul class="list-disc mx-6 space-y-2">
|
||||||
|
<li><span>By email: </span><a href="mailto://support@ductcalc.pro" class="btn btn-link">support@ductcalc.pro</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
<div class="bottom-0 left-0 bg-error">
|
||||||
|
<footer class="footer footer-horizontal footer-center
|
||||||
|
bg-base-300 text-base-content p-4">
|
||||||
|
<aside class="grid-flow-row items-center">
|
||||||
|
<div class="flex mx-auto">
|
||||||
|
<a class="btn btn-ghost" href="mailto:support@ductcalc.pro"> <svg class="h-[1em] opacity-50" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
||||||
|
<g
|
||||||
|
stroke-linejoin="round"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-width="2.5"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
>
|
||||||
|
<rect width="20" height="16" x="2" y="4" rx="2"></rect>
|
||||||
|
<path d="m22 7-8.97 5.7a1.94 1.94 0 0 1-2.06 0L2 7"></path>
|
||||||
|
</g>
|
||||||
|
</svg><span>support@ductcalc.pro</span></a>
|
||||||
|
</div>
|
||||||
|
Openly licensed via CC-BY-NC-SA 4.0<a class="btn btn-ghost mx-auto" href="https://github.com/m-housh/swift-duct-calc/src/branch/main/LICENSE" target="_blank"></a>
|
||||||
|
<p class="">Copyright © 2026 - All rights reserved by Michael Housh</p>
|
||||||
|
</aside>
|
||||||
|
</footer>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -33,7 +33,10 @@
|
|||||||
<main class="flex flex-col min-h-screen min-w-full grow mb-auto">
|
<main class="flex flex-col min-h-screen min-w-full grow mb-auto">
|
||||||
<dialog id="loginForm" class="modal modal-open">
|
<dialog id="loginForm" class="modal modal-open">
|
||||||
<div class="modal-box">
|
<div class="modal-box">
|
||||||
<h1 class="text-2xl font-bold mb-6">Login</h1>
|
<div class="flex justify-between">
|
||||||
|
<h1 class="text-2xl font-bold mb-6">Login</h1>
|
||||||
|
Privacy Policy<a class="btn btn-link" href="/privacy-policy" target="_blank"></a>
|
||||||
|
</div>
|
||||||
<form method="post" class="space-y-4">
|
<form method="post" class="space-y-4">
|
||||||
<div>
|
<div>
|
||||||
<label class="input validator w-full"> <svg class="h-[1em] opacity-50" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
<label class="input validator w-full"> <svg class="h-[1em] opacity-50" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
||||||
|
|||||||
Reference in New Issue
Block a user