diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..e5fac2c --- /dev/null +++ b/.dockerignore @@ -0,0 +1,7 @@ +.git +.pi +.pi-subagents +node_modules +npm-debug.log* +Dockerfile +README.md diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..658aeeb --- /dev/null +++ b/Dockerfile @@ -0,0 +1,15 @@ +FROM node:22-bookworm-slim + +WORKDIR /app +ENV NODE_ENV=production + +COPY package.json package-lock.json ./ +RUN npm ci --omit=dev + +COPY public ./public +COPY server ./server +COPY shared ./shared + +USER node +EXPOSE 8090 +CMD ["node", "server/index.js"] diff --git a/public/app.css b/public/app.css index c7fcc75..d5df6e6 100644 --- a/public/app.css +++ b/public/app.css @@ -377,6 +377,70 @@ body.show-fids .field[data-fid]::after{ opacity:1; } .sw-ref{ background:var(--ink-3); border-top:1px dashed var(--ink-3); background:none; height:0; border-bottom:1.5px dashed var(--ink-3); } .curve-wrap{ border-radius:var(--radius-md); overflow:hidden; border:1px solid var(--line); } +/* ─── PWA and mobile layout ───────────────────────────────────────────── */ +.connection-status{ + position:sticky; top:var(--header-h); z-index:29; padding:8px 14px; + background:var(--warn-bg); border-bottom:1px solid #E8D49E; color:#705318; + font-size:13px; font-weight:600; text-align:center; +} +.connection-status.hidden{ display:none; } + +@media (max-width:720px){ + :root{ --header-h:auto; } + body{ font-size:16px; padding-bottom:env(safe-area-inset-bottom); } + .app-header{ + position:sticky; padding:10px 12px; gap:10px; + padding-top:max(10px, env(safe-area-inset-top)); + } + .brand{ width:100%; justify-content:space-between; } + .brand-mark{ font-size:24px; } + .brand-text h1{ font-size:16px; } + .brand-sub{ font-size:12px; } + .section-nav{ width:100%; order:2; margin:0 -2px; } + .section-nav a{ min-height:40px; display:inline-flex; align-items:center; padding:7px 12px; } + .header-actions{ + order:3; width:100%; display:grid; grid-template-columns:repeat(3, minmax(0, 1fr)); gap:7px; + } + .header-divider{ display:none; } + .ghost-btn, .primary-btn, label.filebtn{ + min-height:44px; padding:8px 6px; font-size:12px; text-align:center; + } + .autosave-chip{ grid-column:1 / -1; justify-content:center; min-height:32px; margin:0; } + .workspace-grid{ padding:14px 10px 48px; gap:14px; } + .panel-card{ margin-bottom:14px; border-radius:12px; } + .panel-head{ padding:14px; align-items:flex-start; } + .panel-head h2{ font-size:16px; padding-top:4px; } + .panel-body{ padding:14px; } + .field-grid{ grid-template-columns:1fr; gap:12px; } + .field-input, .text-input{ min-height:44px; font-size:16px; } + .field-input.sm{ font-size:16px; } + .segmented{ display:flex; width:100%; } + .seg-opt{ flex:1 1 auto; } + .seg-opt span{ min-height:40px; display:flex; align-items:center; justify-content:center; padding:6px 9px; text-align:center; white-space:normal; } + .chip-group{ gap:7px; } + .chip-opt{ flex:1 1 auto; } + .chip-opt span{ min-height:40px; justify-content:center; width:100%; padding:7px 10px; text-align:center; } + .blend-card{ padding:12px; gap:10px; } + .blend-remove, .actuator-remove, .icon-btn{ min-width:44px; min-height:44px; } + .milestone-row, .milestone-row.log-row{ padding:12px 0; } + .milestone-plan{ min-height:40px; display:flex; align-items:center; justify-content:center; } + .actuator-step{ gap:0; } + .actuator-rail{ display:none; } + .actuator-card{ padding:12px; } + .dock-card{ padding:14px; border-radius:12px; } + .checks-grid{ grid-template-columns:1fr; } + .check-tile{ min-height:76px; } + .curve-wrap{ overflow-x:auto; } + #curve-svg-live{ min-width:520px; } + .drawer{ width:100%; max-width:none; } + .drawer-head{ padding:14px; } + .drawer-body{ padding:14px; } +} + +@media (prefers-reduced-motion:reduce){ + *, *::before, *::after{ animation-duration:.01ms !important; animation-iteration-count:1 !important; scroll-behavior:auto !important; transition-duration:.01ms !important; } +} + /* ─── Print: hide the screen shell, show the paper worksheet ───────────── */ #print-sheet{ display:none; } .pv{ display:none; } diff --git a/public/icon.svg b/public/icon.svg new file mode 100644 index 0000000..6a8986c --- /dev/null +++ b/public/icon.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/public/index.html b/public/index.html index adb2e20..ca9f4a0 100644 --- a/public/index.html +++ b/public/index.html @@ -4,6 +4,12 @@ Roast Planner + + + + + + @@ -41,6 +47,7 @@ +