discstation 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,328 @@
1
+ :root {
2
+ --paper: #f0ede4;
3
+ --paper-deep: #e3dfd4;
4
+ --ink: #1a1a1a;
5
+ --muted: #6f6a60;
6
+ --line: #b9b4a9;
7
+ --soft-line: rgba(26, 26, 26, 0.15);
8
+ --grid-line: rgba(26, 26, 26, 0.075);
9
+ --surface: rgba(250, 248, 240, 0.7);
10
+ --accent: #bc7355;
11
+ --accent-text: #1a1a1a;
12
+ --mono: "JetBrains Mono", "IBM Plex Mono", "SFMono-Regular", Consolas, monospace;
13
+ --display: Impact, Haettenschweiler, "Arial Narrow Bold", sans-serif;
14
+ }
15
+
16
+ :root[data-theme="dark"] {
17
+ --paper: #11213a;
18
+ --paper-deep: #1a3150;
19
+ --ink: #f0ede4;
20
+ --muted: #b8c2cf;
21
+ --line: #8fa0b8;
22
+ --soft-line: rgba(240, 237, 228, 0.2);
23
+ --grid-line: rgba(240, 237, 228, 0.12);
24
+ --surface: rgba(24, 45, 73, 0.82);
25
+ }
26
+
27
+ * { box-sizing: border-box; }
28
+
29
+ html { background: var(--paper); overflow-x: hidden; }
30
+
31
+ body {
32
+ position: relative;
33
+ margin: 0;
34
+ min-width: 320px;
35
+ color: var(--ink);
36
+ background-color: var(--paper);
37
+ background-image:
38
+ linear-gradient(to right, var(--grid-line) 1px, transparent 1px),
39
+ linear-gradient(to bottom, var(--grid-line) 1px, transparent 1px);
40
+ background-size: 56px 56px;
41
+ background-attachment: fixed;
42
+ font-family: var(--mono);
43
+ overflow-x: hidden;
44
+ }
45
+
46
+ body::before,
47
+ body::after {
48
+ content: "";
49
+ position: fixed;
50
+ inset: 0;
51
+ pointer-events: none;
52
+ z-index: 0;
53
+ }
54
+
55
+ body::before {
56
+ background-image:
57
+ linear-gradient(12deg, transparent 49.75%, var(--grid-line) 49.95%, transparent 50.15%),
58
+ linear-gradient(-9deg, transparent 49.8%, var(--grid-line) 50%, transparent 50.2%);
59
+ background-position: 0 18px, 0 144px;
60
+ background-size: 100% 280px, 100% 360px;
61
+ opacity: 0.65;
62
+ }
63
+
64
+ body::after {
65
+ background: var(--line);
66
+ opacity: 0.55;
67
+ -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='56' height='56' viewBox='0 0 56 56'%3E%3Cg fill='none' stroke='white' stroke-width='1.25'%3E%3Cpath d='M0 0h8M0 0v8M56 0h-8M56 0v8M0 56h8M0 56v-8M56 56h-8M56 56v-8'/%3E%3C/g%3E%3C/svg%3E");
68
+ mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='56' height='56' viewBox='0 0 56 56'%3E%3Cg fill='none' stroke='white' stroke-width='1.25'%3E%3Cpath d='M0 0h8M0 0v8M56 0h-8M56 0v8M0 56h8M0 56v-8M56 56h-8M56 56v-8'/%3E%3C/g%3E%3C/svg%3E");
69
+ -webkit-mask-repeat: repeat;
70
+ mask-repeat: repeat;
71
+ -webkit-mask-size: 56px 56px;
72
+ mask-size: 56px 56px;
73
+ }
74
+
75
+ button, input { font: inherit; }
76
+ button { color: inherit; }
77
+
78
+ .page-shell {
79
+ position: relative;
80
+ z-index: 1;
81
+ width: min(100% - 32px, 1080px);
82
+ margin: 0 auto;
83
+ }
84
+
85
+ .topbar {
86
+ min-height: 64px;
87
+ display: flex;
88
+ align-items: center;
89
+ justify-content: space-between;
90
+ border-bottom: 1px solid var(--ink);
91
+ font-size: 11px;
92
+ letter-spacing: 0.11em;
93
+ }
94
+
95
+ .brand {
96
+ display: inline-flex;
97
+ align-items: center;
98
+ gap: 10px;
99
+ color: var(--ink);
100
+ text-decoration: none;
101
+ font-weight: 700;
102
+ }
103
+
104
+ .brand-mark {
105
+ display: grid;
106
+ width: 25px;
107
+ height: 25px;
108
+ place-items: center;
109
+ border: 1px solid var(--ink);
110
+ font-size: 9px;
111
+ letter-spacing: 0;
112
+ }
113
+
114
+ .topbar-actions { display: inline-flex; align-items: center; gap: 12px; }
115
+ .theme-toggle {
116
+ width: 27px;
117
+ height: 27px;
118
+ padding: 0;
119
+ border: 1px solid var(--ink);
120
+ background: transparent;
121
+ cursor: pointer;
122
+ font-size: 15px;
123
+ line-height: 1;
124
+ }
125
+ .theme-toggle:hover { background: var(--ink); color: var(--paper); }
126
+
127
+ .connection { display: inline-flex; align-items: center; gap: 8px; }
128
+ .connection-dot {
129
+ width: 8px;
130
+ height: 8px;
131
+ display: inline-block;
132
+ border: 1px solid var(--ink);
133
+ border-radius: 50%;
134
+ background: var(--muted);
135
+ }
136
+ .connection-dot.online { background: #287346; border-color: #287346; }
137
+ .connection-dot.offline { background: #9d4035; border-color: #9d4035; }
138
+
139
+ .section-rule { border-bottom: 1px solid var(--ink); }
140
+
141
+ .hero { padding: 58px 0 38px; }
142
+ .eyebrow, .section-kicker, .stamp-label {
143
+ font-size: 10px;
144
+ font-weight: 700;
145
+ letter-spacing: 0.14em;
146
+ }
147
+ .eyebrow { margin-bottom: 18px; }
148
+
149
+ h1, h2 { margin: 0; }
150
+ h1 {
151
+ max-width: 760px;
152
+ font-family: var(--display);
153
+ font-size: clamp(48px, 11vw, 118px);
154
+ line-height: 0.87;
155
+ letter-spacing: -0.035em;
156
+ font-weight: 900;
157
+ }
158
+ h1 em { font-style: normal; -webkit-text-stroke: 1px var(--ink); color: transparent; }
159
+ .lede {
160
+ max-width: 560px;
161
+ margin: 28px 0 26px;
162
+ color: var(--muted);
163
+ font-size: 12px;
164
+ line-height: 1.8;
165
+ }
166
+ .hero-specs {
167
+ display: flex;
168
+ flex-wrap: wrap;
169
+ gap: 8px 22px;
170
+ font-size: 10px;
171
+ letter-spacing: 0.08em;
172
+ }
173
+
174
+ .capability-strip {
175
+ display: grid;
176
+ grid-template-columns: repeat(2, 1fr);
177
+ gap: 0;
178
+ }
179
+ .capability-strip div {
180
+ display: flex;
181
+ gap: 10px;
182
+ padding: 15px 0;
183
+ border-right: 1px solid var(--soft-line);
184
+ font-size: 10px;
185
+ letter-spacing: 0.08em;
186
+ }
187
+ .capability-strip div:nth-child(2n) { border-right: 0; padding-left: 15px; }
188
+ .capability-strip strong { font-size: 10px; }
189
+
190
+ .burn-panel { padding: 30px 0 34px; }
191
+ .panel-heading { display: flex; justify-content: space-between; gap: 16px; align-items: end; }
192
+ h2 { margin-top: 8px; font-family: var(--display); font-size: clamp(30px, 7vw, 64px); line-height: 0.9; letter-spacing: -0.02em; }
193
+ .panel-index { color: var(--muted); font-size: 10px; white-space: nowrap; }
194
+ .tabs { display: flex; margin-top: 28px; border-bottom: 1px solid var(--ink); }
195
+ .tab {
196
+ border: 0;
197
+ border-top: 1px solid transparent;
198
+ padding: 12px 15px;
199
+ background: transparent;
200
+ cursor: pointer;
201
+ font-size: 10px;
202
+ letter-spacing: 0.1em;
203
+ }
204
+ .tab.active { border: 1px solid var(--ink); border-bottom: 1px solid var(--paper); margin-bottom: -1px; font-weight: 700; }
205
+ .tab.active { border-bottom: 2px solid var(--accent); }
206
+ .tab-panel { padding-top: 21px; }
207
+ .tab-panel[hidden] { display: none; }
208
+ .global-progress { margin-top: 18px; font-size: 10px; letter-spacing: 0.08em; }
209
+ .global-progress > div:first-child { display: flex; justify-content: space-between; margin-bottom: 7px; }
210
+ .progress-track { height: 8px; border: 1px solid var(--ink); }
211
+ .progress-track span { display: block; width: 0; height: 100%; background: var(--accent); transition: width 0.2s; }
212
+ .progress-track span.indeterminate { animation: progress-pulse 1.2s ease-in-out infinite alternate; }
213
+ @keyframes progress-pulse { from { opacity: 0.35; } to { opacity: 1; } }
214
+ .field-note { margin: 0 0 15px; color: var(--muted); font-size: 11px; line-height: 1.65; }
215
+ .field-label { display: block; margin: 20px 0 7px; font-size: 10px; font-weight: 700; letter-spacing: 0.1em; }
216
+ .text-input, .url-input {
217
+ width: 100%;
218
+ border: 1px solid var(--ink);
219
+ border-radius: 0;
220
+ min-height: 52px;
221
+ padding: 15px;
222
+ color: var(--ink);
223
+ background: var(--surface);
224
+ outline: none;
225
+ font-size: 12px;
226
+ }
227
+ .text-input:focus, .url-input:focus { border-color: var(--accent); box-shadow: 4px 4px 0 var(--accent); }
228
+ .black-button {
229
+ width: 100%;
230
+ margin-top: 14px;
231
+ border: 1px solid var(--ink);
232
+ border-radius: 0;
233
+ padding: 16px;
234
+ background: var(--accent);
235
+ color: var(--accent-text);
236
+ cursor: pointer;
237
+ font-weight: 700;
238
+ letter-spacing: 0.1em;
239
+ text-align: left;
240
+ }
241
+ .black-button span { float: right; }
242
+ .black-button:hover { background: var(--accent); filter: brightness(0.92); }
243
+ .black-button:disabled { cursor: not-allowed; opacity: 0.45; }
244
+ .outline-button {
245
+ flex: 1;
246
+ border: 1px solid var(--ink);
247
+ border-radius: 0;
248
+ padding: 12px 8px;
249
+ background: transparent;
250
+ cursor: pointer;
251
+ font-size: 10px;
252
+ font-weight: 700;
253
+ letter-spacing: 0.08em;
254
+ }
255
+ .outline-button:hover { background: var(--ink); color: var(--paper); }
256
+ .picker-row { display: flex; gap: 8px; margin-bottom: 15px; }
257
+ .dropzone {
258
+ margin: 0 0 15px;
259
+ border: 1px dashed var(--ink);
260
+ padding: 18px 12px;
261
+ color: var(--muted);
262
+ text-align: center;
263
+ font-size: 10px;
264
+ letter-spacing: 0.08em;
265
+ }
266
+ .dropzone.drag { background: var(--paper-deep); color: var(--ink); }
267
+ .disc-meter { margin-bottom: 18px; font-size: 10px; letter-spacing: 0.05em; }
268
+ .disc-meter > div:first-child { display: flex; justify-content: space-between; gap: 12px; margin-bottom: 7px; }
269
+ .meter-track { height: 8px; border: 1px solid var(--ink); }
270
+ .meter-track span { display: block; height: 100%; width: 0; background: var(--accent); transition: width 0.2s; }
271
+ .selection-list { max-height: 260px; overflow: auto; border-top: 1px solid var(--soft-line); }
272
+ .selection-row { display: flex; align-items: center; gap: 10px; padding: 10px 0; border-bottom: 1px solid var(--soft-line); font-size: 10px; }
273
+ .selection-name { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
274
+ .selection-meta { color: var(--muted); white-space: nowrap; }
275
+ .remove-selection { border: 0; padding: 0 4px; background: transparent; cursor: pointer; font-weight: 700; }
276
+ .empty-selection { padding: 16px 0; color: var(--muted); font-size: 10px; letter-spacing: 0.08em; }
277
+ .selection-summary, .form-message { margin-top: 10px; color: var(--muted); font-size: 10px; line-height: 1.6; }
278
+ .form-message.error { color: #9d4035; }
279
+ .form-message.ok { color: #287346; }
280
+
281
+ .footer-stamp {
282
+ display: flex;
283
+ justify-content: space-between;
284
+ gap: 16px;
285
+ padding: 18px 0 24px;
286
+ font-size: 10px;
287
+ letter-spacing: 0.08em;
288
+ }
289
+
290
+ .footer-note {
291
+ padding: 26px 0 22px;
292
+ color: var(--muted);
293
+ font-size: 10px;
294
+ line-height: 1.7;
295
+ }
296
+ .footer-note .eyebrow { margin-bottom: 7px; color: var(--ink); }
297
+ .footer-note-title {
298
+ color: var(--ink);
299
+ font-family: var(--display);
300
+ font-size: clamp(1.45rem, 5vw, 2.8rem);
301
+ line-height: 0.9;
302
+ letter-spacing: -0.02em;
303
+ }
304
+ .footer-note-title em { font-style: normal; -webkit-text-stroke: 1px var(--ink); color: transparent; }
305
+ .footer-note p { max-width: 520px; margin: 12px 0 10px; }
306
+ .footer-note .hero-specs { font-size: 9px; gap: 5px 16px; }
307
+
308
+ .sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0; }
309
+
310
+ @media (min-width: 720px) {
311
+ .page-shell { width: min(100% - 72px, 1080px); }
312
+ .hero { padding-top: 92px; }
313
+ .capability-strip { grid-template-columns: repeat(4, 1fr); }
314
+ .capability-strip div:nth-child(2n) { padding-left: 0; }
315
+ .capability-strip div:not(:last-child) { border-right: 1px solid var(--soft-line); }
316
+ .capability-strip div + div { padding-left: 18px; }
317
+ .burn-panel { width: min(100%, 720px); margin-left: auto; margin-right: auto; }
318
+ }
319
+
320
+ @media (max-width: 600px) {
321
+ .topbar { gap: 12px; }
322
+ .topbar-actions { gap: 8px; }
323
+ .connection { font-size: 9px; }
324
+ h1 { font-size: clamp(2.35rem, 12vw, 4rem); }
325
+ .hero { padding-top: 48px; }
326
+ .hero-specs { line-height: 1.7; }
327
+ .footer-stamp { flex-wrap: wrap; line-height: 1.7; }
328
+ }
@@ -0,0 +1,13 @@
1
+ [Unit]
2
+ Description=DiscStation physical media appliance
3
+ After=network.target
4
+
5
+ [Service]
6
+ EnvironmentFile=-%h/.local/share/discstation/discstation.env
7
+ ExecStart=%h/.local/share/discstation/venv/bin/python %h/.local/share/discstation/app/discstation.py
8
+ Restart=on-failure
9
+ RestartSec=3
10
+ KillSignal=SIGKILL
11
+
12
+ [Install]
13
+ WantedBy=default.target