diff --git a/scripts/setup-dev.sh b/scripts/setup-dev.sh index 2ba18aaf..87857799 100755 --- a/scripts/setup-dev.sh +++ b/scripts/setup-dev.sh @@ -7,8 +7,8 @@ set -euo pipefail REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)" PYTHON="${PYTHON:-python3}" -# Fail fast if Python is too old (Django 5 requires 3.10+) -"${PYTHON}" -c 'import sys; v=sys.version_info; (v.major==3 and v.minor>=10) or (print(f"Error: Python 3.10+ required for Django 5. Found {v.major}.{v.minor}", file=sys.stderr), sys.exit(1))' || exit 1 +# Fail fast if Python is too old (Django 6 requires 3.10+) +"${PYTHON}" -c 'import sys; v=sys.version_info; (v.major==3 and v.minor>=10) or (print(f"Error: Python 3.10+ required for Django 6. Found {v.major}.{v.minor}", file=sys.stderr), sys.exit(1))' || exit 1 echo "==> Setting up TubeSync dev environment" echo " Python: $($PYTHON --version)" diff --git a/tubesync/common/static/styles/output.css b/tubesync/common/static/styles/output.css new file mode 100644 index 00000000..fad9b193 --- /dev/null +++ b/tubesync/common/static/styles/output.css @@ -0,0 +1,1313 @@ +/*! tailwindcss v4.2.1 | MIT License | https://tailwindcss.com */ +@layer properties; +@layer theme, base, components, utilities; +@layer theme { + :root, :host { + --font-sans: 'Roboto', Arial, Helvetica, sans-serif; + --font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', + monospace; + --color-green-600: oklch(62.7% 0.194 149.214); + --color-black: #000; + --color-white: #fff; + --spacing: 0.25rem; + --container-2xl: 42rem; + --container-7xl: 80rem; + --text-xs: 0.75rem; + --text-xs--line-height: calc(1 / 0.75); + --text-sm: 0.875rem; + --text-sm--line-height: calc(1.25 / 0.875); + --text-lg: 1.125rem; + --text-lg--line-height: calc(1.75 / 1.125); + --text-xl: 1.25rem; + --text-xl--line-height: calc(1.75 / 1.25); + --text-2xl: 1.5rem; + --text-2xl--line-height: calc(2 / 1.5); + --text-3xl: 1.875rem; + --text-3xl--line-height: calc(2.25 / 1.875); + --font-weight-medium: 500; + --font-weight-semibold: 600; + --font-weight-bold: 700; + --tracking-tight: -0.025em; + --tracking-wider: 0.05em; + --leading-relaxed: 1.625; + --radius-md: 0.375rem; + --radius-lg: 0.5rem; + --aspect-video: 16 / 9; + --default-transition-duration: 150ms; + --default-transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + --default-font-family: var(--font-sans); + --default-mono-font-family: var(--font-mono); + --color-background: #ffffff; + --color-foreground: #0f172a; + --color-card: #ffffff; + --color-border: #e2e8f0; + --color-input: #e2e8f0; + --color-ring: #e71d36; + --color-primary: #e71d36; + --color-primary-foreground: #fdfffc; + --color-accent: #f97316; + --color-accent-foreground: #fdfffc; + --color-destructive: #b91c1c; + --color-destructive-foreground: #fdfffc; + --color-muted: #f1f5f9; + --color-muted-foreground: #64748b; + --color-nav: #011627; + --color-nav-foreground: #fdfffc; + --color-header: #e71d36; + --color-header-foreground: #fdfffc; + --color-footer: #0f172a; + --color-footer-foreground: #94a3b8; + } +} +@layer base { + *, ::after, ::before, ::backdrop, ::file-selector-button { + box-sizing: border-box; + margin: 0; + padding: 0; + border: 0 solid; + } + html, :host { + line-height: 1.5; + -webkit-text-size-adjust: 100%; + tab-size: 4; + font-family: var(--default-font-family, ui-sans-serif, system-ui, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji'); + font-feature-settings: var(--default-font-feature-settings, normal); + font-variation-settings: var(--default-font-variation-settings, normal); + -webkit-tap-highlight-color: transparent; + } + hr { + height: 0; + color: inherit; + border-top-width: 1px; + } + abbr:where([title]) { + -webkit-text-decoration: underline dotted; + text-decoration: underline dotted; + } + h1, h2, h3, h4, h5, h6 { + font-size: inherit; + font-weight: inherit; + } + a { + color: inherit; + -webkit-text-decoration: inherit; + text-decoration: inherit; + } + b, strong { + font-weight: bolder; + } + code, kbd, samp, pre { + font-family: var(--default-mono-font-family, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace); + font-feature-settings: var(--default-mono-font-feature-settings, normal); + font-variation-settings: var(--default-mono-font-variation-settings, normal); + font-size: 1em; + } + small { + font-size: 80%; + } + sub, sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; + } + sub { + bottom: -0.25em; + } + sup { + top: -0.5em; + } + table { + text-indent: 0; + border-color: inherit; + border-collapse: collapse; + } + :-moz-focusring { + outline: auto; + } + progress { + vertical-align: baseline; + } + summary { + display: list-item; + } + ol, ul, menu { + list-style: none; + } + img, svg, video, canvas, audio, iframe, embed, object { + display: block; + vertical-align: middle; + } + img, video { + max-width: 100%; + height: auto; + } + button, input, select, optgroup, textarea, ::file-selector-button { + font: inherit; + font-feature-settings: inherit; + font-variation-settings: inherit; + letter-spacing: inherit; + color: inherit; + border-radius: 0; + background-color: transparent; + opacity: 1; + } + :where(select:is([multiple], [size])) optgroup { + font-weight: bolder; + } + :where(select:is([multiple], [size])) optgroup option { + padding-inline-start: 20px; + } + ::file-selector-button { + margin-inline-end: 4px; + } + ::placeholder { + opacity: 1; + } + @supports (not (-webkit-appearance: -apple-pay-button)) or (contain-intrinsic-size: 1px) { + ::placeholder { + color: currentcolor; + @supports (color: color-mix(in lab, red, red)) { + color: color-mix(in oklab, currentcolor 50%, transparent); + } + } + } + textarea { + resize: vertical; + } + ::-webkit-search-decoration { + -webkit-appearance: none; + } + ::-webkit-date-and-time-value { + min-height: 1lh; + text-align: inherit; + } + ::-webkit-datetime-edit { + display: inline-flex; + } + ::-webkit-datetime-edit-fields-wrapper { + padding: 0; + } + ::-webkit-datetime-edit, ::-webkit-datetime-edit-year-field, ::-webkit-datetime-edit-month-field, ::-webkit-datetime-edit-day-field, ::-webkit-datetime-edit-hour-field, ::-webkit-datetime-edit-minute-field, ::-webkit-datetime-edit-second-field, ::-webkit-datetime-edit-millisecond-field, ::-webkit-datetime-edit-meridiem-field { + padding-block: 0; + } + ::-webkit-calendar-picker-indicator { + line-height: 1; + } + :-moz-ui-invalid { + box-shadow: none; + } + button, input:where([type='button'], [type='reset'], [type='submit']), ::file-selector-button { + appearance: button; + } + ::-webkit-inner-spin-button, ::-webkit-outer-spin-button { + height: auto; + } + [hidden]:where(:not([hidden='until-found'])) { + display: none !important; + } +} +@layer utilities { + .visible { + visibility: visible; + } + .absolute { + position: absolute; + } + .fixed { + position: fixed; + } + .relative { + position: relative; + } + .static { + position: static; + } + .start { + inset-inline-start: var(--spacing); + } + .end { + inset-inline-end: var(--spacing); + } + .right-0 { + right: calc(var(--spacing) * 0); + } + .bottom-0 { + bottom: calc(var(--spacing) * 0); + } + .col-span-full { + grid-column: 1 / -1; + } + .container { + width: 100%; + @media (width >= 40rem) { + max-width: 40rem; + } + @media (width >= 48rem) { + max-width: 48rem; + } + @media (width >= 64rem) { + max-width: 64rem; + } + @media (width >= 80rem) { + max-width: 80rem; + } + @media (width >= 96rem) { + max-width: 96rem; + } + } + .m-1\.5 { + margin: calc(var(--spacing) * 1.5); + } + .-mx-2 { + margin-inline: calc(var(--spacing) * -2); + } + .mx-auto { + margin-inline: auto; + } + .mt-1 { + margin-top: calc(var(--spacing) * 1); + } + .mt-1\.5 { + margin-top: calc(var(--spacing) * 1.5); + } + .mt-2 { + margin-top: calc(var(--spacing) * 2); + } + .mt-8 { + margin-top: calc(var(--spacing) * 8); + } + .mb-1 { + margin-bottom: calc(var(--spacing) * 1); + } + .mb-1\.5 { + margin-bottom: calc(var(--spacing) * 1.5); + } + .mb-2 { + margin-bottom: calc(var(--spacing) * 2); + } + .mb-3 { + margin-bottom: calc(var(--spacing) * 3); + } + .mb-4 { + margin-bottom: calc(var(--spacing) * 4); + } + .mb-6 { + margin-bottom: calc(var(--spacing) * 6); + } + .ml-2 { + margin-left: calc(var(--spacing) * 2); + } + .block { + display: block; + } + .contents { + display: contents; + } + .flex { + display: flex; + } + .grid { + display: grid; + } + .hidden { + display: none; + } + .inline-flex { + display: inline-flex; + } + .table { + display: table; + } + .aspect-video { + aspect-ratio: var(--aspect-video); + } + .h-10 { + height: calc(var(--spacing) * 10); + } + .h-12 { + height: calc(var(--spacing) * 12); + } + .h-full { + height: 100%; + } + .w-1\/3 { + width: calc(1 / 3 * 100%); + } + .w-full { + width: 100%; + } + .max-w-2xl { + max-width: var(--container-2xl); + } + .max-w-7xl { + max-width: var(--container-7xl); + } + .max-w-\[80\%\] { + max-width: 80%; + } + .min-w-0 { + min-width: calc(var(--spacing) * 0); + } + .min-w-\[2\.5rem\] { + min-width: 2.5rem; + } + .flex-1 { + flex: 1; + } + .transform { + transform: var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,); + } + .cursor-pointer { + cursor: pointer; + } + .resize { + resize: both; + } + .list-inside { + list-style-position: inside; + } + .list-disc { + list-style-type: disc; + } + .grid-cols-1 { + grid-template-columns: repeat(1, minmax(0, 1fr)); + } + .flex-col { + flex-direction: column; + } + .flex-wrap { + flex-wrap: wrap; + } + .items-center { + align-items: center; + } + .items-end { + align-items: flex-end; + } + .justify-center { + justify-content: center; + } + .gap-1 { + gap: calc(var(--spacing) * 1); + } + .gap-1\.5 { + gap: calc(var(--spacing) * 1.5); + } + .gap-2 { + gap: calc(var(--spacing) * 2); + } + .gap-3 { + gap: calc(var(--spacing) * 3); + } + .gap-4 { + gap: calc(var(--spacing) * 4); + } + .gap-6 { + gap: calc(var(--spacing) * 6); + } + .space-y-1 { + :where(& > :not(:last-child)) { + --tw-space-y-reverse: 0; + margin-block-start: calc(calc(var(--spacing) * 1) * var(--tw-space-y-reverse)); + margin-block-end: calc(calc(var(--spacing) * 1) * calc(1 - var(--tw-space-y-reverse))); + } + } + .divide-y { + :where(& > :not(:last-child)) { + --tw-divide-y-reverse: 0; + border-bottom-style: var(--tw-border-style); + border-top-style: var(--tw-border-style); + border-top-width: calc(1px * var(--tw-divide-y-reverse)); + border-bottom-width: calc(1px * calc(1 - var(--tw-divide-y-reverse))); + } + } + .divide-border { + :where(& > :not(:last-child)) { + border-color: var(--color-border); + } + } + .truncate { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + .overflow-hidden { + overflow: hidden; + } + .overflow-x-auto { + overflow-x: auto; + } + .rounded { + border-radius: 0.25rem; + } + .rounded-lg { + border-radius: var(--radius-lg); + } + .rounded-md { + border-radius: var(--radius-md); + } + .border { + border-style: var(--tw-border-style); + border-width: 1px; + } + .border-t { + border-top-style: var(--tw-border-style); + border-top-width: 1px; + } + .border-b { + border-bottom-style: var(--tw-border-style); + border-bottom-width: 1px; + } + .border-accent { + border-color: var(--color-accent); + } + .border-border { + border-color: var(--color-border); + } + .border-destructive\/20 { + border-color: color-mix(in srgb, #b91c1c 20%, transparent); + @supports (color: color-mix(in lab, red, red)) { + border-color: color-mix(in oklab, var(--color-destructive) 20%, transparent); + } + } + .border-input { + border-color: var(--color-input); + } + .border-primary\/20 { + border-color: color-mix(in srgb, #e71d36 20%, transparent); + @supports (color: color-mix(in lab, red, red)) { + border-color: color-mix(in oklab, var(--color-primary) 20%, transparent); + } + } + .border-white\/5 { + border-color: color-mix(in srgb, #fff 5%, transparent); + @supports (color: color-mix(in lab, red, red)) { + border-color: color-mix(in oklab, var(--color-white) 5%, transparent); + } + } + .border-white\/10 { + border-color: color-mix(in srgb, #fff 10%, transparent); + @supports (color: color-mix(in lab, red, red)) { + border-color: color-mix(in oklab, var(--color-white) 10%, transparent); + } + } + .bg-accent { + background-color: var(--color-accent); + } + .bg-background { + background-color: var(--color-background); + } + .bg-black { + background-color: var(--color-black); + } + .bg-card { + background-color: var(--color-card); + } + .bg-destructive { + background-color: var(--color-destructive); + } + .bg-footer { + background-color: var(--color-footer); + } + .bg-header { + background-color: var(--color-header); + } + .bg-muted { + background-color: var(--color-muted); + } + .bg-muted\/30 { + background-color: color-mix(in srgb, #f1f5f9 30%, transparent); + @supports (color: color-mix(in lab, red, red)) { + background-color: color-mix(in oklab, var(--color-muted) 30%, transparent); + } + } + .bg-muted\/50 { + background-color: color-mix(in srgb, #f1f5f9 50%, transparent); + @supports (color: color-mix(in lab, red, red)) { + background-color: color-mix(in oklab, var(--color-muted) 50%, transparent); + } + } + .bg-nav { + background-color: var(--color-nav); + } + .bg-nav\/90 { + background-color: color-mix(in srgb, #011627 90%, transparent); + @supports (color: color-mix(in lab, red, red)) { + background-color: color-mix(in oklab, var(--color-nav) 90%, transparent); + } + } + .bg-primary { + background-color: var(--color-primary); + } + .object-cover { + object-fit: cover; + } + .p-3 { + padding: calc(var(--spacing) * 3); + } + .p-4 { + padding: calc(var(--spacing) * 4); + } + .p-5 { + padding: calc(var(--spacing) * 5); + } + .px-1\.5 { + padding-inline: calc(var(--spacing) * 1.5); + } + .px-2 { + padding-inline: calc(var(--spacing) * 2); + } + .px-3 { + padding-inline: calc(var(--spacing) * 3); + } + .px-4 { + padding-inline: calc(var(--spacing) * 4); + } + .py-0\.5 { + padding-block: calc(var(--spacing) * 0.5); + } + .py-1 { + padding-block: calc(var(--spacing) * 1); + } + .py-2 { + padding-block: calc(var(--spacing) * 2); + } + .py-2\.5 { + padding-block: calc(var(--spacing) * 2.5); + } + .py-3 { + padding-block: calc(var(--spacing) * 3); + } + .py-5 { + padding-block: calc(var(--spacing) * 5); + } + .py-6 { + padding-block: calc(var(--spacing) * 6); + } + .py-8 { + padding-block: calc(var(--spacing) * 8); + } + .\!pt-0 { + padding-top: calc(var(--spacing) * 0) !important; + } + .pt-4 { + padding-top: calc(var(--spacing) * 4); + } + .pt-6 { + padding-top: calc(var(--spacing) * 6); + } + .\!pb-0 { + padding-bottom: calc(var(--spacing) * 0) !important; + } + .pb-2 { + padding-bottom: calc(var(--spacing) * 2); + } + .text-center { + text-align: center; + } + .text-left { + text-align: left; + } + .text-right { + text-align: right; + } + .align-top { + vertical-align: top; + } + .text-3xl { + font-size: var(--text-3xl); + line-height: var(--tw-leading, var(--text-3xl--line-height)); + } + .text-sm { + font-size: var(--text-sm); + line-height: var(--tw-leading, var(--text-sm--line-height)); + } + .text-xs { + font-size: var(--text-xs); + line-height: var(--tw-leading, var(--text-xs--line-height)); + } + .leading-relaxed { + --tw-leading: var(--leading-relaxed); + line-height: var(--leading-relaxed); + } + .font-bold { + --tw-font-weight: var(--font-weight-bold); + font-weight: var(--font-weight-bold); + } + .font-medium { + --tw-font-weight: var(--font-weight-medium); + font-weight: var(--font-weight-medium); + } + .font-semibold { + --tw-font-weight: var(--font-weight-semibold); + font-weight: var(--font-weight-semibold); + } + .tracking-tight { + --tw-tracking: var(--tracking-tight); + letter-spacing: var(--tracking-tight); + } + .tracking-wider { + --tw-tracking: var(--tracking-wider); + letter-spacing: var(--tracking-wider); + } + .whitespace-nowrap { + white-space: nowrap; + } + .text-accent { + color: var(--color-accent); + } + .text-accent-foreground { + color: var(--color-accent-foreground); + } + .text-destructive { + color: var(--color-destructive); + } + .text-destructive-foreground { + color: var(--color-destructive-foreground); + } + .text-footer-foreground { + color: var(--color-footer-foreground); + } + .text-foreground { + color: var(--color-foreground); + } + .text-green-600 { + color: var(--color-green-600); + } + .text-header-foreground { + color: var(--color-header-foreground); + } + .text-muted-foreground { + color: var(--color-muted-foreground); + } + .text-nav-foreground { + color: var(--color-nav-foreground); + } + .text-nav-foreground\/80 { + color: color-mix(in srgb, #fdfffc 80%, transparent); + @supports (color: color-mix(in lab, red, red)) { + color: color-mix(in oklab, var(--color-nav-foreground) 80%, transparent); + } + } + .text-primary { + color: var(--color-primary); + } + .text-primary-foreground { + color: var(--color-primary-foreground); + } + .text-white { + color: var(--color-white); + } + .lowercase { + text-transform: lowercase; + } + .uppercase { + text-transform: uppercase; + } + .underline { + text-decoration-line: underline; + } + .invert { + --tw-invert: invert(100%); + filter: var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,); + } + .filter { + filter: var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,); + } + .transition-colors { + transition-property: color, background-color, border-color, outline-color, text-decoration-color, fill, stroke, --tw-gradient-from, --tw-gradient-via, --tw-gradient-to; + transition-timing-function: var(--tw-ease, var(--default-transition-timing-function)); + transition-duration: var(--tw-duration, var(--default-transition-duration)); + } + .hover\:border-accent { + &:hover { + @media (hover: hover) { + border-color: var(--color-accent); + } + } + } + .hover\:border-primary { + &:hover { + @media (hover: hover) { + border-color: var(--color-primary); + } + } + } + .hover\:bg-accent { + &:hover { + @media (hover: hover) { + background-color: var(--color-accent); + } + } + } + .hover\:bg-destructive\/80 { + &:hover { + @media (hover: hover) { + background-color: color-mix(in srgb, #b91c1c 80%, transparent); + @supports (color: color-mix(in lab, red, red)) { + background-color: color-mix(in oklab, var(--color-destructive) 80%, transparent); + } + } + } + } + .hover\:bg-muted { + &:hover { + @media (hover: hover) { + background-color: var(--color-muted); + } + } + } + .hover\:bg-muted\/50 { + &:hover { + @media (hover: hover) { + background-color: color-mix(in srgb, #f1f5f9 50%, transparent); + @supports (color: color-mix(in lab, red, red)) { + background-color: color-mix(in oklab, var(--color-muted) 50%, transparent); + } + } + } + } + .hover\:bg-primary { + &:hover { + @media (hover: hover) { + background-color: var(--color-primary); + } + } + } + .hover\:bg-white\/10 { + &:hover { + @media (hover: hover) { + background-color: color-mix(in srgb, #fff 10%, transparent); + @supports (color: color-mix(in lab, red, red)) { + background-color: color-mix(in oklab, var(--color-white) 10%, transparent); + } + } + } + } + .hover\:text-accent { + &:hover { + @media (hover: hover) { + color: var(--color-accent); + } + } + } + .hover\:text-accent-foreground { + &:hover { + @media (hover: hover) { + color: var(--color-accent-foreground); + } + } + } + .hover\:text-destructive\/80 { + &:hover { + @media (hover: hover) { + color: color-mix(in srgb, #b91c1c 80%, transparent); + @supports (color: color-mix(in lab, red, red)) { + color: color-mix(in oklab, var(--color-destructive) 80%, transparent); + } + } + } + } + .hover\:text-header-foreground { + &:hover { + @media (hover: hover) { + color: var(--color-header-foreground); + } + } + } + .hover\:text-nav-foreground { + &:hover { + @media (hover: hover) { + color: var(--color-nav-foreground); + } + } + } + .hover\:text-primary { + &:hover { + @media (hover: hover) { + color: var(--color-primary); + } + } + } + .hover\:text-primary-foreground { + &:hover { + @media (hover: hover) { + color: var(--color-primary-foreground); + } + } + } + .hover\:text-white { + &:hover { + @media (hover: hover) { + color: var(--color-white); + } + } + } + .sm\:hidden { + @media (width >= 40rem) { + display: none; + } + } + .sm\:inline { + @media (width >= 40rem) { + display: inline; + } + } + .sm\:table-cell { + @media (width >= 40rem) { + display: table-cell; + } + } + .sm\:grid-cols-2 { + @media (width >= 40rem) { + grid-template-columns: repeat(2, minmax(0, 1fr)); + } + } + .sm\:flex-row { + @media (width >= 40rem) { + flex-direction: row; + } + } + .sm\:items-center { + @media (width >= 40rem) { + align-items: center; + } + } + .sm\:px-6 { + @media (width >= 40rem) { + padding-inline: calc(var(--spacing) * 6); + } + } + .md\:col-span-5 { + @media (width >= 48rem) { + grid-column: span 5 / span 5; + } + } + .md\:col-span-7 { + @media (width >= 48rem) { + grid-column: span 7 / span 7; + } + } + .md\:grid-cols-12 { + @media (width >= 48rem) { + grid-template-columns: repeat(12, minmax(0, 1fr)); + } + } + .lg\:grid-cols-2 { + @media (width >= 64rem) { + grid-template-columns: repeat(2, minmax(0, 1fr)); + } + } + .lg\:grid-cols-3 { + @media (width >= 64rem) { + grid-template-columns: repeat(3, minmax(0, 1fr)); + } + } + .xl\:grid-cols-4 { + @media (width >= 80rem) { + grid-template-columns: repeat(4, minmax(0, 1fr)); + } + } +} +@font-face { + font-family: 'Roboto'; + src: url('../fonts/roboto/roboto-light.woff') format('woff'); + font-weight: 300; + font-style: normal; + font-display: swap; +} +@font-face { + font-family: 'Roboto'; + src: url('../fonts/roboto/roboto-regular.woff') format('woff'); + font-weight: 400; + font-style: normal; + font-display: swap; +} +@font-face { + font-family: 'Roboto'; + src: url('../fonts/roboto/roboto-bold.woff') format('woff'); + font-weight: 700; + font-style: normal; + font-display: swap; +} +@layer base { + html { + font-size: 1.05rem; + } + body { + background-color: var(--color-background); + font-family: var(--font-sans); + color: var(--color-foreground); + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + display: flex; + min-height: 100vh; + flex-direction: column; + } + a { + color: var(--color-primary); + transition-property: color, background-color, border-color, outline-color, text-decoration-color, fill, stroke, --tw-gradient-from, --tw-gradient-via, --tw-gradient-to; + transition-timing-function: var(--tw-ease, var(--default-transition-timing-function)); + transition-duration: var(--tw-duration, var(--default-transition-duration)); + &:hover { + @media (hover: hover) { + color: var(--color-accent); + } + } + text-decoration: none; + } + h1 { + font-size: var(--text-2xl); + line-height: var(--tw-leading, var(--text-2xl--line-height)); + --tw-font-weight: var(--font-weight-bold); + font-weight: var(--font-weight-bold); + --tw-tracking: var(--tracking-tight); + letter-spacing: var(--tracking-tight); + color: var(--color-foreground); + margin: 0; + padding: 0 0 0.5rem 0; + } + h2 { + font-size: var(--text-xl); + line-height: var(--tw-leading, var(--text-xl--line-height)); + --tw-font-weight: var(--font-weight-semibold); + font-weight: var(--font-weight-semibold); + --tw-tracking: var(--tracking-tight); + letter-spacing: var(--tracking-tight); + color: var(--color-foreground); + margin: 0; + padding: 1.5rem 0 1rem 0; + } + h3 { + font-size: var(--text-lg); + line-height: var(--tw-leading, var(--text-lg--line-height)); + --tw-font-weight: var(--font-weight-semibold); + font-weight: var(--font-weight-semibold); + color: var(--color-foreground); + } + strong { + font-weight: 700; + } + svg.tubesync-logo .logo-icon, svg.tubesync-logo .logo-left-arrow, svg.tubesync-logo .logo-right-arrow { + fill: currentColor !important; + } + code { + border-radius: 0.25rem; + background-color: var(--color-muted); + padding-inline: calc(var(--spacing) * 1.5); + padding-block: calc(var(--spacing) * 0.5); + font-family: var(--font-mono); + font-size: var(--text-xs); + line-height: var(--tw-leading, var(--text-xs--line-height)); + } + input[type="text"], input[type="url"], input[type="email"], input[type="password"], input[type="number"], input[type="search"], textarea { + width: 100%; + border-radius: var(--radius-md); + border-style: var(--tw-border-style); + border-width: 1px; + border-color: var(--color-input); + background-color: var(--color-background); + padding-inline: calc(var(--spacing) * 3); + padding-block: calc(var(--spacing) * 2); + font-size: var(--text-sm); + line-height: var(--tw-leading, var(--text-sm--line-height)); + color: var(--color-foreground); + --tw-outline-style: none; + outline-style: none; + &:focus { + border-color: var(--color-ring); + } + &:focus { + --tw-ring-shadow: var(--tw-ring-inset,) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color, currentcolor); + box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow); + } + &:focus { + --tw-ring-color: var(--color-ring); + } + transition-property: color, background-color, border-color, outline-color, text-decoration-color, fill, stroke, --tw-gradient-from, --tw-gradient-via, --tw-gradient-to; + transition-timing-function: var(--tw-ease, var(--default-transition-timing-function)); + transition-duration: var(--tw-duration, var(--default-transition-duration)); + } + textarea { + min-height: 120px; + } + select { + width: 100%; + border-radius: var(--radius-md); + border-style: var(--tw-border-style); + border-width: 1px; + border-color: var(--color-input); + background-color: var(--color-background); + padding-inline: calc(var(--spacing) * 3); + padding-block: calc(var(--spacing) * 2); + font-size: var(--text-sm); + line-height: var(--tw-leading, var(--text-sm--line-height)); + color: var(--color-foreground); + --tw-outline-style: none; + outline-style: none; + &:focus { + border-color: var(--color-ring); + } + &:focus { + --tw-ring-shadow: var(--tw-ring-inset,) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color, currentcolor); + box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow); + } + &:focus { + --tw-ring-color: var(--color-ring); + } + appearance: auto; + } + input[type="checkbox"] { + border-radius: 0.25rem; + border-color: var(--color-border); + color: var(--color-primary); + width: 1rem; + height: 1rem; + } + .errors { + margin-bottom: calc(var(--spacing) * 4); + border-radius: var(--radius-lg); + border-style: var(--tw-border-style); + border-width: 1px; + border-color: color-mix(in srgb, #b91c1c 20%, transparent); + @supports (color: color-mix(in lab, red, red)) { + border-color: color-mix(in oklab, var(--color-destructive) 20%, transparent); + } + background-color: color-mix(in srgb, #b91c1c 5%, transparent); + @supports (color: color-mix(in lab, red, red)) { + background-color: color-mix(in oklab, var(--color-destructive) 5%, transparent); + } + padding: calc(var(--spacing) * 4); + } + .errors li, .errorlist li { + padding-inline: calc(var(--spacing) * 2); + padding-block: calc(var(--spacing) * 1); + font-size: var(--text-sm); + line-height: var(--tw-leading, var(--text-sm--line-height)); + color: var(--color-destructive); + } + .error-text { + color: var(--color-destructive); + } +} +.truncate { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} +.nowrap { + white-space: nowrap; +} +.no-text-transform { + text-transform: none; +} +@property --tw-rotate-x { + syntax: "*"; + inherits: false; +} +@property --tw-rotate-y { + syntax: "*"; + inherits: false; +} +@property --tw-rotate-z { + syntax: "*"; + inherits: false; +} +@property --tw-skew-x { + syntax: "*"; + inherits: false; +} +@property --tw-skew-y { + syntax: "*"; + inherits: false; +} +@property --tw-space-y-reverse { + syntax: "*"; + inherits: false; + initial-value: 0; +} +@property --tw-divide-y-reverse { + syntax: "*"; + inherits: false; + initial-value: 0; +} +@property --tw-border-style { + syntax: "*"; + inherits: false; + initial-value: solid; +} +@property --tw-leading { + syntax: "*"; + inherits: false; +} +@property --tw-font-weight { + syntax: "*"; + inherits: false; +} +@property --tw-tracking { + syntax: "*"; + inherits: false; +} +@property --tw-blur { + syntax: "*"; + inherits: false; +} +@property --tw-brightness { + syntax: "*"; + inherits: false; +} +@property --tw-contrast { + syntax: "*"; + inherits: false; +} +@property --tw-grayscale { + syntax: "*"; + inherits: false; +} +@property --tw-hue-rotate { + syntax: "*"; + inherits: false; +} +@property --tw-invert { + syntax: "*"; + inherits: false; +} +@property --tw-opacity { + syntax: "*"; + inherits: false; +} +@property --tw-saturate { + syntax: "*"; + inherits: false; +} +@property --tw-sepia { + syntax: "*"; + inherits: false; +} +@property --tw-drop-shadow { + syntax: "*"; + inherits: false; +} +@property --tw-drop-shadow-color { + syntax: "*"; + inherits: false; +} +@property --tw-drop-shadow-alpha { + syntax: ""; + inherits: false; + initial-value: 100%; +} +@property --tw-drop-shadow-size { + syntax: "*"; + inherits: false; +} +@property --tw-shadow { + syntax: "*"; + inherits: false; + initial-value: 0 0 #0000; +} +@property --tw-shadow-color { + syntax: "*"; + inherits: false; +} +@property --tw-shadow-alpha { + syntax: ""; + inherits: false; + initial-value: 100%; +} +@property --tw-inset-shadow { + syntax: "*"; + inherits: false; + initial-value: 0 0 #0000; +} +@property --tw-inset-shadow-color { + syntax: "*"; + inherits: false; +} +@property --tw-inset-shadow-alpha { + syntax: ""; + inherits: false; + initial-value: 100%; +} +@property --tw-ring-color { + syntax: "*"; + inherits: false; +} +@property --tw-ring-shadow { + syntax: "*"; + inherits: false; + initial-value: 0 0 #0000; +} +@property --tw-inset-ring-color { + syntax: "*"; + inherits: false; +} +@property --tw-inset-ring-shadow { + syntax: "*"; + inherits: false; + initial-value: 0 0 #0000; +} +@property --tw-ring-inset { + syntax: "*"; + inherits: false; +} +@property --tw-ring-offset-width { + syntax: ""; + inherits: false; + initial-value: 0px; +} +@property --tw-ring-offset-color { + syntax: "*"; + inherits: false; + initial-value: #fff; +} +@property --tw-ring-offset-shadow { + syntax: "*"; + inherits: false; + initial-value: 0 0 #0000; +} +@layer properties { + @supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))) { + *, ::before, ::after, ::backdrop { + --tw-rotate-x: initial; + --tw-rotate-y: initial; + --tw-rotate-z: initial; + --tw-skew-x: initial; + --tw-skew-y: initial; + --tw-space-y-reverse: 0; + --tw-divide-y-reverse: 0; + --tw-border-style: solid; + --tw-leading: initial; + --tw-font-weight: initial; + --tw-tracking: initial; + --tw-blur: initial; + --tw-brightness: initial; + --tw-contrast: initial; + --tw-grayscale: initial; + --tw-hue-rotate: initial; + --tw-invert: initial; + --tw-opacity: initial; + --tw-saturate: initial; + --tw-sepia: initial; + --tw-drop-shadow: initial; + --tw-drop-shadow-color: initial; + --tw-drop-shadow-alpha: 100%; + --tw-drop-shadow-size: initial; + --tw-shadow: 0 0 #0000; + --tw-shadow-color: initial; + --tw-shadow-alpha: 100%; + --tw-inset-shadow: 0 0 #0000; + --tw-inset-shadow-color: initial; + --tw-inset-shadow-alpha: 100%; + --tw-ring-color: initial; + --tw-ring-shadow: 0 0 #0000; + --tw-inset-ring-color: initial; + --tw-inset-ring-shadow: 0 0 #0000; + --tw-ring-inset: initial; + --tw-ring-offset-width: 0px; + --tw-ring-offset-color: #fff; + --tw-ring-offset-shadow: 0 0 #0000; + } + } +} diff --git a/tubesync/common/templates/base.html b/tubesync/common/templates/base.html index b1556f96..4f39e004 100644 --- a/tubesync/common/templates/base.html +++ b/tubesync/common/templates/base.html @@ -3,10 +3,8 @@ - - - - + + TubeSync - {% block headtitle %}Synchronize YouTube to your local media server{% endblock %} diff --git a/tubesync/tubesync/settings.py b/tubesync/tubesync/settings.py index ac74234f..9ea74d3b 100644 --- a/tubesync/tubesync/settings.py +++ b/tubesync/tubesync/settings.py @@ -229,19 +229,22 @@ except ImportError as e: sys.exit(1) -DJANGO_HUEY = { - 'default': TaskQueue.LIMIT.value, - 'queues': dict(), - 'verbose': None if DEBUG else False, -} -for queue_name in TaskQueue.values: - queues = DJANGO_HUEY['queues'] - if TaskQueue.LIMIT.value == queue_name: - queues[queue_name] = sqlite_tasks(queue_name, prefix='net', tasks_dir=HUEY_TASKS_DIR) - elif TaskQueue.NET.value == queue_name: - queues[queue_name] = sqlite_tasks(queue_name, thread=True, workers=0, tasks_dir=HUEY_TASKS_DIR) - else: - queues[queue_name] = sqlite_tasks(queue_name, thread=True, tasks_dir=HUEY_TASKS_DIR) +# Allow local_settings.py to fully override DJANGO_HUEY (e.g. to use Redis instead of SQLite). +# If not overridden, fall back to the default sqlite_tasks-based configuration. +if not globals().get('DJANGO_HUEY'): + DJANGO_HUEY = { + 'default': TaskQueue.LIMIT.value, + 'queues': dict(), + 'verbose': None if DEBUG else False, + } + for queue_name in TaskQueue.values: + queues = DJANGO_HUEY['queues'] + if TaskQueue.LIMIT.value == queue_name: + queues[queue_name] = sqlite_tasks(queue_name, prefix='net', tasks_dir=HUEY_TASKS_DIR) + elif TaskQueue.NET.value == queue_name: + queues[queue_name] = sqlite_tasks(queue_name, thread=True, workers=0, tasks_dir=HUEY_TASKS_DIR) + else: + queues[queue_name] = sqlite_tasks(queue_name, thread=True, tasks_dir=HUEY_TASKS_DIR) for django_huey_queue in DJANGO_HUEY['queues'].values(): connection = django_huey_queue.get('connection') if connection: