diff --git a/public/app.css b/public/app.css index 16a52bd..b2265a5 100644 --- a/public/app.css +++ b/public/app.css @@ -1,467 +1,1445 @@ /* Roast Planner — screen UI. worksheet.css is print-only (loaded with media="print"); this file owns the entire on-screen experience and is deliberately independent of the print layout. */ -:root{ - --ink:#1B1614; --ink-2:#5B524B; --ink-3:#8C8179; - --surface:#FBF8F4; --surface-raised:#FFFFFF; --surface-sunken:#F2ECE4; - --line:#E4DCD2; --line-strong:#D3C8BA; - --ember:#A8481A; --ember-soft:#FBEFE6; --ember-strong:#7F350F; - --pass:#2F6F4E; --pass-bg:#E8F3ED; - --warn:#A8741A; --warn-bg:#FBF3E1; - --fail:#B03A22; --fail-bg:#FBEAE5; - --radius-sm:6px; --radius-md:10px; --radius-lg:16px; - --shadow-card:0 1px 2px rgba(27,22,20,.04), 0 8px 24px -12px rgba(27,22,20,.12); - --shadow-pop:0 12px 32px -8px rgba(27,22,20,.28); - --font-ui:-apple-system,BlinkMacSystemFont,"SF Pro Text","Segoe UI",Inter,Helvetica,Arial,sans-serif; - --font-serif:"Iowan Old Style","Palatino Linotype",Palatino,Georgia,"Times New Roman",serif; - --font-mono:"SF Mono",Menlo,Consolas,monospace; - --header-h:60px; +:root { + --ink: #1b1614; + --ink-2: #5b524b; + --ink-3: #8c8179; + --surface: #fbf8f4; + --surface-raised: #ffffff; + --surface-sunken: #f2ece4; + --line: #e4dcd2; + --line-strong: #d3c8ba; + --ember: #a8481a; + --ember-soft: #fbefe6; + --ember-strong: #7f350f; + --pass: #2f6f4e; + --pass-bg: #e8f3ed; + --warn: #a8741a; + --warn-bg: #fbf3e1; + --fail: #b03a22; + --fail-bg: #fbeae5; + --radius-sm: 6px; + --radius-md: 10px; + --radius-lg: 16px; + --shadow-card: + 0 1px 2px rgba(27, 22, 20, 0.04), 0 8px 24px -12px rgba(27, 22, 20, 0.12); + --shadow-pop: 0 12px 32px -8px rgba(27, 22, 20, 0.28); + --font-ui: + -apple-system, BlinkMacSystemFont, "SF Pro Text", "Segoe UI", Inter, + Helvetica, Arial, sans-serif; + --font-serif: + "Iowan Old Style", "Palatino Linotype", Palatino, Georgia, + "Times New Roman", serif; + --font-mono: "SF Mono", Menlo, Consolas, monospace; + --header-h: 60px; } -*{ box-sizing:border-box; } -.hidden{ display:none !important; } -html{ background:var(--surface); } -body{ - margin:0; background:var(--surface); color:var(--ink); - font-family:var(--font-ui); font-size:15px; line-height:1.45; - -webkit-font-smoothing:antialiased; +* { + box-sizing: border-box; +} +.hidden { + display: none !important; +} +html { + background: var(--surface); +} +body { + margin: 0; + background: var(--surface); + color: var(--ink); + font-family: var(--font-ui); + font-size: 15px; + line-height: 1.45; + -webkit-font-smoothing: antialiased; +} +h1, +h2, +h3 { + margin: 0; + font-family: var(--font-ui); +} +output { + font-variant-numeric: tabular-nums; } -h1,h2,h3{ margin:0; font-family:var(--font-ui); } -output{ font-variant-numeric:tabular-nums; } /* ─── Header ──────────────────────────────────────────────────────────── */ -.app-header{ - position:sticky; top:0; z-index:30; height:var(--header-h); - display:flex; align-items:center; gap:24px; - background:var(--surface-raised); border-bottom:1px solid var(--line); - padding:0 20px; +.app-header { + position: sticky; + top: 0; + z-index: 30; + height: var(--header-h); + display: flex; + align-items: center; + gap: 24px; + background: var(--surface-raised); + border-bottom: 1px solid var(--line); + padding: 0 20px; +} +.brand { + display: flex; + align-items: center; + gap: 10px; + flex: 0 0 auto; +} +.brand-mark { + font-size: 22px; + color: var(--ember); + line-height: 1; +} +.brand-text h1 { + font-size: 15px; + font-weight: 700; + letter-spacing: -0.1px; +} +.brand-sub { + margin: 0; + font-size: 11.5px; + color: var(--ink-3); } -.brand{ display:flex; align-items:center; gap:10px; flex:0 0 auto; } -.brand-mark{ font-size:22px; color:var(--ember); line-height:1; } -.brand-text h1{ font-size:15px; font-weight:700; letter-spacing:-.1px; } -.brand-sub{ margin:0; font-size:11.5px; color:var(--ink-3); } -.section-nav{ - display:flex; align-items:center; gap:2px; flex:1 1 auto; overflow-x:auto; - scrollbar-width:none; +.section-nav { + display: flex; + align-items: center; + gap: 2px; + flex: 1 1 auto; + overflow-x: auto; + scrollbar-width: none; } -.section-nav::-webkit-scrollbar{ display:none; } -.section-nav a{ - flex:0 0 auto; padding:6px 12px; border-radius:999px; font-size:12.5px; font-weight:500; - color:var(--ink-2); text-decoration:none; white-space:nowrap; transition:background .15s,color .15s; +.section-nav::-webkit-scrollbar { + display: none; +} +.section-nav a { + flex: 0 0 auto; + padding: 6px 12px; + border-radius: 999px; + font-size: 12.5px; + font-weight: 500; + color: var(--ink-2); + text-decoration: none; + white-space: nowrap; + transition: + background 0.15s, + color 0.15s; +} +.section-nav a:hover { + background: var(--surface-sunken); + color: var(--ink); +} +.section-nav a.active { + background: var(--ember-soft); + color: var(--ember-strong); + font-weight: 600; } -.section-nav a:hover{ background:var(--surface-sunken); color:var(--ink); } -.section-nav a.active{ background:var(--ember-soft); color:var(--ember-strong); font-weight:600; } -.header-actions{ display:flex; align-items:center; gap:8px; flex:0 0 auto; } -.header-divider{ width:1px; height:22px; background:var(--line); margin:0 2px; } - -.ghost-btn, .primary-btn, label.filebtn{ - font-family:var(--font-ui); font-size:12.5px; font-weight:600; cursor:pointer; - border-radius:var(--radius-sm); padding:7px 12px; white-space:nowrap; - border:1px solid transparent; transition:background .15s,border-color .15s,color .15s; +.header-actions { + display: flex; + align-items: center; + gap: 8px; + flex: 0 0 auto; } -.ghost-btn{ background:transparent; color:var(--ink-2); border-color:var(--line); } -.ghost-btn:hover{ background:var(--surface-sunken); color:var(--ink); } -.ghost-btn[aria-pressed="true"]{ background:var(--ember-soft); border-color:var(--ember); color:var(--ember-strong); } -.ghost-btn.small{ font-size:12px; padding:5px 10px; } -.ghost-btn:disabled{ opacity:.45; cursor:default; } -.primary-btn, label.filebtn{ background:var(--ember); color:#fff; border-color:var(--ember); } -.primary-btn:hover, label.filebtn:hover{ background:var(--ember-strong); } -.primary-btn:disabled{ opacity:.5; cursor:default; } -#file-load{ display:none; } -label.filebtn input[type=file]{ display:none; } +.header-divider { + width: 1px; + height: 22px; + background: var(--line); + margin: 0 2px; +} +.account-menu { position: relative; } +.account-menu summary { list-style: none; } +.account-menu summary::-webkit-details-marker { display: none; } +.account-menu-popover { + position: absolute; right: 0; top: calc(100% + 6px); z-index: 35; min-width: 132px; + padding: 6px; border: 1px solid var(--line); border-radius: var(--radius-sm); + background: var(--surface-raised); box-shadow: var(--shadow-pop); +} +.account-menu-popover a, .account-menu-popover button { + display: block; width: 100%; padding: 9px 10px; border: 0; border-radius: var(--radius-sm); + background: transparent; color: var(--ink-2); font: inherit; font-size: 13px; text-align: left; + text-decoration: none; cursor: pointer; +} +.account-menu-popover a:hover, .account-menu-popover button:hover { background: var(--surface-sunken); color: var(--ink); } -.autosave-chip{ - display:flex; align-items:center; gap:6px; font-size:11.5px; color:var(--ink-3); - padding:4px 10px; border-radius:999px; background:var(--surface-sunken); margin-left:2px; +.ghost-btn, +.primary-btn, +label.filebtn { + font-family: var(--font-ui); + font-size: 12.5px; + font-weight: 600; + cursor: pointer; + border-radius: var(--radius-sm); + padding: 7px 12px; + white-space: nowrap; + border: 1px solid transparent; + transition: + background 0.15s, + border-color 0.15s, + color 0.15s; +} +.ghost-btn { + background: transparent; + color: var(--ink-2); + border-color: var(--line); +} +.ghost-btn:hover { + background: var(--surface-sunken); + color: var(--ink); +} +.ghost-btn[aria-pressed="true"] { + background: var(--ember-soft); + border-color: var(--ember); + color: var(--ember-strong); +} +.ghost-btn.small { + font-size: 12px; + padding: 5px 10px; +} +.ghost-btn:disabled { + opacity: 0.45; + cursor: default; +} +.primary-btn, +label.filebtn { + background: var(--ember); + color: #fff; + border-color: var(--ember); +} +.primary-btn:hover, +label.filebtn:hover { + background: var(--ember-strong); +} +.primary-btn:disabled { + opacity: 0.5; + cursor: default; +} +#file-load { + display: none; +} +label.filebtn input[type="file"] { + display: none; +} + +.autosave-chip { + display: flex; + align-items: center; + gap: 6px; + font-size: 11.5px; + color: var(--ink-3); + padding: 4px 10px; + border-radius: 999px; + background: var(--surface-sunken); + margin-left: 2px; +} +.autosave-chip .dot { + width: 6px; + height: 6px; + border-radius: 50%; + background: var(--ink-3); + transition: background 0.2s; +} +.autosave-chip.saving .dot { + background: var(--warn); + animation: pulse 1s ease-in-out infinite; +} +.autosave-chip.saved .dot { + background: var(--pass); +} +@keyframes pulse { + 0%, + 100% { + opacity: 1; + } + 50% { + opacity: 0.35; + } } -.autosave-chip .dot{ width:6px; height:6px; border-radius:50%; background:var(--ink-3); transition:background .2s; } -.autosave-chip.saving .dot{ background:var(--warn); animation:pulse 1s ease-in-out infinite; } -.autosave-chip.saved .dot{ background:var(--pass); } -@keyframes pulse{ 0%,100%{ opacity:1; } 50%{ opacity:.35; } } /* ─── Drawers ─────────────────────────────────────────────────────────── */ -.drawer-overlay{ - position:fixed; inset:0; background:rgba(27,22,20,.32); z-index:40; opacity:1; transition:opacity .18s; +.drawer-overlay { + position: fixed; + inset: 0; + background: rgba(27, 22, 20, 0.32); + z-index: 40; + opacity: 1; + transition: opacity 0.18s; } -.drawer-overlay.hidden{ display:none; } -.drawer{ - position:fixed; top:0; right:0; bottom:0; width:min(420px,92vw); z-index:41; - background:var(--surface-raised); box-shadow:var(--shadow-pop); - display:flex; flex-direction:column; transform:translateX(0); transition:transform .2s; +.drawer-overlay.hidden { + display: none; } -.drawer.hidden{ display:none; } -.drawer-head{ - display:flex; align-items:center; justify-content:space-between; - padding:16px 20px; border-bottom:1px solid var(--line); +.drawer { + position: fixed; + top: 0; + right: 0; + bottom: 0; + width: min(420px, 92vw); + z-index: 41; + background: var(--surface-raised); + box-shadow: var(--shadow-pop); + display: flex; + flex-direction: column; + transform: translateX(0); + transition: transform 0.2s; } -.drawer-head h3{ font-size:14.5px; font-weight:700; } -.icon-btn{ - background:none; border:none; font-size:14px; color:var(--ink-3); cursor:pointer; - width:28px; height:28px; border-radius:var(--radius-sm); +.drawer.hidden { + display: none; } -.icon-btn:hover{ background:var(--surface-sunken); color:var(--ink); } -.drawer-body{ padding:18px 20px; overflow-y:auto; display:flex; flex-direction:column; gap:12px; } -.stack-label{ font-size:12px; font-weight:600; color:var(--ink-2); } -.text-input{ - width:100%; padding:9px 11px; border:1px solid var(--line); border-radius:var(--radius-sm); - font-size:13.5px; font-family:var(--font-ui); background:var(--surface-raised); color:var(--ink); +.drawer-head { + display: flex; + align-items: center; + justify-content: space-between; + padding: 16px 20px; + border-bottom: 1px solid var(--line); +} +.drawer-head h3 { + font-size: 14.5px; + font-weight: 700; +} +.icon-btn { + background: none; + border: none; + font-size: 14px; + color: var(--ink-3); + cursor: pointer; + width: 28px; + height: 28px; + border-radius: var(--radius-sm); +} +.icon-btn:hover { + background: var(--surface-sunken); + color: var(--ink); +} +.drawer-body { + padding: 18px 20px; + overflow-y: auto; + display: flex; + flex-direction: column; + gap: 12px; +} +.stack-label { + font-size: 12px; + font-weight: 600; + color: var(--ink-2); +} +.text-input { + width: 100%; + padding: 9px 11px; + border: 1px solid var(--line); + border-radius: var(--radius-sm); + font-size: 13.5px; + font-family: var(--font-ui); + background: var(--surface-raised); + color: var(--ink); +} +.text-input:focus { + outline: none; + border-color: var(--ember); + box-shadow: 0 0 0 3px var(--ember-soft); +} +.checkbox-row { + display: flex; + align-items: center; + gap: 7px; + font-size: 13px; + color: var(--ink-2); +} +.drawer-actions { + display: flex; + gap: 8px; +} +.drawer-result { + font-size: 12.5px; + color: var(--ink-2); + line-height: 1.55; +} +.drawer-result a { + color: var(--ember); +} +.drawer-result .warnings { + color: var(--warn); + margin: 6px 0 0; + padding-left: 18px; +} +.lib-list { + list-style: none; + margin: 0; + padding: 0; + max-height: 220px; + overflow-y: auto; + border: 1px solid var(--line); + border-radius: var(--radius-sm); +} +.lib-list.hidden { + display: none; +} +.lib-list li { + padding: 8px 10px; + font-size: 12.5px; + border-bottom: 1px solid var(--line); + cursor: pointer; +} +.lib-list li:last-child { + border-bottom: none; +} +.lib-list li:hover { + background: var(--surface-sunken); } -.text-input:focus{ outline:none; border-color:var(--ember); box-shadow:0 0 0 3px var(--ember-soft); } -.checkbox-row{ display:flex; align-items:center; gap:7px; font-size:13px; color:var(--ink-2); } -.drawer-actions{ display:flex; gap:8px; } -.drawer-result{ font-size:12.5px; color:var(--ink-2); line-height:1.55; } -.drawer-result a{ color:var(--ember); } -.drawer-result .warnings{ color:var(--warn); margin:6px 0 0; padding-left:18px; } -.lib-list{ list-style:none; margin:0; padding:0; max-height:220px; overflow-y:auto; border:1px solid var(--line); border-radius:var(--radius-sm); } -.lib-list.hidden{ display:none; } -.lib-list li{ padding:8px 10px; font-size:12.5px; border-bottom:1px solid var(--line); cursor:pointer; } -.lib-list li:last-child{ border-bottom:none; } -.lib-list li:hover{ background:var(--surface-sunken); } /* ─── Workspace layout ────────────────────────────────────────────────── */ -.workspace-grid{ - display:grid; grid-template-columns:1fr 380px; gap:28px; align-items:start; - max-width:1360px; margin:0 auto; padding:28px 24px 80px; +.workspace-grid { + display: grid; + grid-template-columns: 1fr 380px; + gap: 28px; + align-items: start; + max-width: 1360px; + margin: 0 auto; + padding: 28px 24px 80px; } -.form-col{ min-width:0; display:flex; flex-direction:column; } -.dock{ - position:sticky; top:calc(var(--header-h) + 20px); - display:flex; flex-direction:column; gap:18px; - max-height:calc(100vh - var(--header-h) - 40px); overflow-y:auto; - padding-bottom:4px; +.form-col { + min-width: 0; + display: flex; + flex-direction: column; +} +.dock { + position: sticky; + top: calc(var(--header-h) + 20px); + display: flex; + flex-direction: column; + gap: 18px; + max-height: calc(100vh - var(--header-h) - 40px); + overflow-y: auto; + padding-bottom: 4px; } -@media (max-width:1180px){ - .workspace-grid{ grid-template-columns:1fr; } - .dock{ position:static; max-height:none; } +@media (max-width: 1180px) { + .workspace-grid { + grid-template-columns: 1fr; + } + .dock { + position: static; + max-height: none; + } } -@media (max-width:1080px){ - .app-header{ flex-wrap:wrap; height:auto; padding:10px 14px; gap:10px; } - .section-nav{ order:3; flex-basis:100%; } +@media (max-width: 1080px) { + .app-header { + flex-wrap: wrap; + height: auto; + padding: 10px 14px; + gap: 10px; + } + .section-nav { + order: 3; + flex-basis: 100%; + } } -@media (max-width:720px){ - .workspace-grid{ padding:18px 14px 60px; } +@media (max-width: 720px) { + .workspace-grid { + padding: 18px 14px 60px; + } } /* ─── Panel cards (form sections) ────────────────────────────────────── */ -.panel-card{ - background:var(--surface-raised); border:1px solid var(--line); border-radius:var(--radius-lg); - margin-bottom:20px; box-shadow:var(--shadow-card); +.panel-card { + background: var(--surface-raised); + border: 1px solid var(--line); + border-radius: var(--radius-lg); + margin-bottom: 20px; + box-shadow: var(--shadow-card); } -.panel-head{ - display:flex; align-items:center; justify-content:space-between; gap:16px; - padding:16px 22px; border-bottom:1px solid var(--line); +.panel-head { + display: flex; + align-items: center; + justify-content: space-between; + gap: 16px; + padding: 16px 22px; + border-bottom: 1px solid var(--line); } -.panel-head h2{ font-size:16px; font-weight:700; letter-spacing:-.1px; } -.panel-body{ padding:20px 22px 22px; } -.subhead{ - font-size:11px; text-transform:uppercase; letter-spacing:.06em; font-weight:700; - color:var(--ink-3); margin:20px 0 12px; +.panel-head h2 { + font-size: 16px; + font-weight: 700; + letter-spacing: -0.1px; +} +.panel-body { + padding: 20px 22px 22px; +} +.subhead { + font-size: 11px; + text-transform: uppercase; + letter-spacing: 0.06em; + font-weight: 700; + color: var(--ink-3); + margin: 20px 0 12px; +} +.subhead:first-child { + margin-top: 0; } -.subhead:first-child{ margin-top:0; } /* ─── Fields ──────────────────────────────────────────────────────────── */ -.field-grid{ - display:grid; grid-template-columns:repeat(auto-fit,minmax(150px,1fr)); gap:14px 18px; margin-bottom:14px; +.field-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); + gap: 14px 18px; + margin-bottom: 14px; } -.field-grid:last-child{ margin-bottom:0; } -.field{ position:relative; display:flex; flex-direction:column; gap:5px; } -.field.wide{ grid-column:1 / -1; } -.field.accent .field-label{ color:var(--ember-strong); } -.field-label{ - font-size:12px; font-weight:600; color:var(--ink-2); display:flex; align-items:center; gap:4px; +.field-grid:last-child { + margin-bottom: 0; } -.hint{ - font-size:11px; color:var(--ink-3); cursor:help; border-radius:50%; width:14px; height:14px; - display:inline-flex; align-items:center; justify-content:center; +.field { + position: relative; + display: flex; + flex-direction: column; + gap: 5px; } -.field-input{ - width:100%; padding:8px 10px; border:1px solid var(--line); border-radius:var(--radius-sm); - font-family:var(--font-ui); font-size:13.5px; color:var(--ink); background:var(--surface-raised); - transition:border-color .15s, box-shadow .15s; +.field.wide { + grid-column: 1 / -1; +} +.field.accent .field-label { + color: var(--ember-strong); +} +.field-label { + font-size: 12px; + font-weight: 600; + color: var(--ink-2); + display: flex; + align-items: center; + gap: 4px; +} +.hint { + font-size: 11px; + color: var(--ink-3); + cursor: help; + border-radius: 50%; + width: 14px; + height: 14px; + display: inline-flex; + align-items: center; + justify-content: center; +} +.field-input { + width: 100%; + padding: 8px 10px; + border: 1px solid var(--line); + border-radius: var(--radius-sm); + font-family: var(--font-ui); + font-size: 13.5px; + color: var(--ink); + background: var(--surface-raised); + transition: + border-color 0.15s, + box-shadow 0.15s; +} +.field-input.sm { + text-align: center; + font-family: var(--font-mono); + font-size: 13px; +} +.field-input.note { + font-family: var(--font-ui); +} +.field-input:focus { + outline: none; + border-color: var(--ember); + box-shadow: 0 0 0 3px var(--ember-soft); +} +.field-input.prefilled { + background: #fff6de; + border-color: #e4c766; +} +.field-input::placeholder { + color: var(--ink-3); + opacity: 0.7; } -.field-input.sm{ text-align:center; font-family:var(--font-mono); font-size:13px; } -.field-input.note{ font-family:var(--font-ui); } -.field-input:focus{ outline:none; border-color:var(--ember); box-shadow:0 0 0 3px var(--ember-soft); } -.field-input.prefilled{ background:#FFF6DE; border-color:#E4C766; } -.field-input::placeholder{ color:var(--ink-3); opacity:.7; } -.unit-input{ position:relative; } -.unit-input .field-input{ padding-right:32px; } -.unit-input.sm .field-input{ padding-right:26px; } -.unit-input .unit{ - position:absolute; right:10px; top:50%; transform:translateY(-50%); - font-size:11.5px; color:var(--ink-3); pointer-events:none; +.unit-input { + position: relative; +} +.unit-input .field-input { + padding-right: 32px; +} +.unit-input.sm .field-input { + padding-right: 26px; +} +.unit-input .unit { + position: absolute; + right: 10px; + top: 50%; + transform: translateY(-50%); + font-size: 11.5px; + color: var(--ink-3); + pointer-events: none; +} +.unit-input.sm .unit { + right: 7px; + font-size: 10.5px; } -.unit-input.sm .unit{ right:7px; font-size:10.5px; } /* field-id badge — hidden until hover/focus, or pinned via "Field IDs" toggle */ -.field[data-fid]::after{ - content:attr(data-fid); position:absolute; top:-6px; right:0; - font-family:var(--font-mono); font-size:9.5px; font-weight:700; color:var(--ember); - background:var(--ember-soft); padding:1px 5px; border-radius:5px; - opacity:0; transition:opacity .12s; pointer-events:none; +.field[data-fid]::after { + content: attr(data-fid); + position: absolute; + top: -6px; + right: 0; + font-family: var(--font-mono); + font-size: 9.5px; + font-weight: 700; + color: var(--ember); + background: var(--ember-soft); + padding: 1px 5px; + border-radius: 5px; + opacity: 0; + transition: opacity 0.12s; + pointer-events: none; +} +.field[data-fid]:hover::after, +.field[data-fid]:focus-within::after { + opacity: 1; +} +body.show-fids .field[data-fid]::after { + opacity: 1; } -.field[data-fid]:hover::after, .field[data-fid]:focus-within::after{ opacity:1; } -body.show-fids .field[data-fid]::after{ opacity:1; } /* ─── Choice controls (segmented + chips) ───────────────────────────── */ -.segmented{ - display:inline-flex; flex-wrap:wrap; gap:2px; background:var(--surface-sunken); - padding:2px; border-radius:var(--radius-md); +.segmented { + display: inline-flex; + flex-wrap: wrap; + gap: 2px; + background: var(--surface-sunken); + padding: 2px; + border-radius: var(--radius-md); } -.segmented.small{ padding:2px; } -.seg-opt{ position:relative; cursor:pointer; } -.seg-opt input{ position:absolute; opacity:0; width:0; height:0; } -.seg-opt span{ - display:block; padding:6px 12px; border-radius:8px; font-size:12.5px; font-weight:500; - color:var(--ink-2); white-space:nowrap; transition:background .15s,color .15s,box-shadow .15s; +.segmented.small { + padding: 2px; } -.seg-opt input:checked + span{ - background:var(--surface-raised); color:var(--ember-strong); font-weight:700; - box-shadow:0 1px 2px rgba(27,22,20,.12); +.seg-opt { + position: relative; + cursor: pointer; +} +.seg-opt input { + position: absolute; + opacity: 0; + width: 0; + height: 0; +} +.seg-opt span { + display: block; + padding: 6px 12px; + border-radius: 8px; + font-size: 12.5px; + font-weight: 500; + color: var(--ink-2); + white-space: nowrap; + transition: + background 0.15s, + color 0.15s, + box-shadow 0.15s; +} +.seg-opt input:checked + span { + background: var(--surface-raised); + color: var(--ember-strong); + font-weight: 700; + box-shadow: 0 1px 2px rgba(27, 22, 20, 0.12); +} +.seg-opt input:focus-visible + span { + outline: 2px solid var(--ember); + outline-offset: 1px; } -.seg-opt input:focus-visible + span{ outline:2px solid var(--ember); outline-offset:1px; } -.chip-group{ display:flex; flex-wrap:wrap; gap:8px; } -.chip-opt{ cursor:pointer; } -.chip-opt input{ position:absolute; opacity:0; width:0; height:0; } -.chip-opt span{ - display:inline-flex; align-items:center; padding:7px 14px; border-radius:999px; - border:1px solid var(--line); font-size:12.5px; font-weight:500; color:var(--ink-2); - background:var(--surface-raised); transition:all .15s; +.chip-group { + display: flex; + flex-wrap: wrap; + gap: 8px; } -.chip-opt input:checked + span{ - background:var(--ember-soft); border-color:var(--ember); color:var(--ember-strong); font-weight:700; +.chip-opt { + cursor: pointer; +} +.chip-opt input { + position: absolute; + opacity: 0; + width: 0; + height: 0; +} +.chip-opt span { + display: inline-flex; + align-items: center; + padding: 7px 14px; + border-radius: 999px; + border: 1px solid var(--line); + font-size: 12.5px; + font-weight: 500; + color: var(--ink-2); + background: var(--surface-raised); + transition: all 0.15s; +} +.chip-opt input:checked + span { + background: var(--ember-soft); + border-color: var(--ember); + color: var(--ember-strong); + font-weight: 700; +} +.chip-opt input:focus-visible + span { + outline: 2px solid var(--ember); + outline-offset: 1px; } -.chip-opt input:focus-visible + span{ outline:2px solid var(--ember); outline-offset:1px; } /* ─── Blend cards ─────────────────────────────────────────────────────── */ -#blend-body.collapsed .blend-cards, #blend-body.collapsed .blend-total, -#blend-body.collapsed #btn-add-blend, #blend-body.collapsed .subhead, -#blend-body.collapsed .field.wide, #blend-body.collapsed .field-grid{ display:none; } -.blend-cards{ display:flex; flex-direction:column; gap:10px; margin-bottom:12px; } -.blend-card{ - display:grid; grid-template-columns:1.4fr 1fr 1fr .7fr .8fr auto; gap:10px; align-items:end; - background:var(--surface-sunken); border-radius:var(--radius-md); padding:12px; +#blend-body.collapsed .blend-cards, +#blend-body.collapsed .blend-total, +#blend-body.collapsed #btn-add-blend, +#blend-body.collapsed .subhead, +#blend-body.collapsed .field.wide, +#blend-body.collapsed .field-grid { + display: none; } -.blend-card .field-label{ font-size:10.5px; } -.blend-remove{ - background:none; border:1px solid var(--line); color:var(--ink-3); width:30px; height:30px; - border-radius:var(--radius-sm); cursor:pointer; font-size:13px; +.blend-cards { + display: flex; + flex-direction: column; + gap: 10px; + margin-bottom: 12px; +} +.blend-card { + display: grid; + grid-template-columns: 1.4fr 1fr 1fr 0.7fr 0.8fr auto; + gap: 10px; + align-items: end; + background: var(--surface-sunken); + border-radius: var(--radius-md); + padding: 12px; +} +.blend-card .field-label { + font-size: 10.5px; +} +.blend-remove { + background: none; + border: 1px solid var(--line); + color: var(--ink-3); + width: 30px; + height: 30px; + border-radius: var(--radius-sm); + cursor: pointer; + font-size: 13px; +} +.blend-remove:hover { + background: var(--fail-bg); + color: var(--fail); + border-color: var(--fail); +} +.blend-total { + display: flex; + align-items: center; + gap: 10px; + margin-bottom: 14px; +} +.blend-total-bar { + flex: 1 1 auto; + height: 6px; + border-radius: 999px; + background: var(--surface-sunken); + overflow: hidden; +} +.blend-total-fill { + height: 100%; + background: var(--ember); + width: 0%; + transition: + width 0.2s, + background 0.2s; +} +.blend-total-fill.over, +.blend-total-fill.under { + background: var(--fail); +} +.blend-total-label { + font-size: 11.5px; + font-family: var(--font-mono); + color: var(--ink-3); + white-space: nowrap; +} +@media (max-width: 640px) { + .blend-card { + grid-template-columns: 1fr 1fr; + } } -.blend-remove:hover{ background:var(--fail-bg); color:var(--fail); border-color:var(--fail); } -.blend-total{ display:flex; align-items:center; gap:10px; margin-bottom:14px; } -.blend-total-bar{ flex:1 1 auto; height:6px; border-radius:999px; background:var(--surface-sunken); overflow:hidden; } -.blend-total-fill{ height:100%; background:var(--ember); width:0%; transition:width .2s,background .2s; } -.blend-total-fill.over, .blend-total-fill.under{ background:var(--fail); } -.blend-total-label{ font-size:11.5px; font-family:var(--font-mono); color:var(--ink-3); white-space:nowrap; } -@media (max-width:640px){ .blend-card{ grid-template-columns:1fr 1fr; } } /* ─── Milestone lists (temps / roast log) ────────────────────────────── */ -.milestone-list{ display:flex; flex-direction:column; gap:6px; } -.milestone-row{ - display:grid; grid-template-columns:110px 64px 1fr 90px; gap:12px; align-items:center; - padding:8px 4px; border-bottom:1px solid var(--line); +.milestone-list { + display: flex; + flex-direction: column; + gap: 6px; } -.milestone-row:last-child{ border-bottom:none; } -.milestone-row.log-row{ grid-template-columns:110px 64px 72px 64px 1fr; } -.milestone-label{ font-size:13px; font-weight:600; color:var(--ink); } -.milestone-plan{ - font-family:var(--font-mono); font-size:13px; color:var(--ink-2); text-align:center; - background:var(--surface-sunken); border-radius:var(--radius-sm); padding:6px 4px; +.milestone-row { + display: grid; + grid-template-columns: 110px 64px 1fr 90px; + gap: 12px; + align-items: center; + padding: 8px 4px; + border-bottom: 1px solid var(--line); } -.milestone-time{ text-align:center; } -.band-track{ - position:relative; height:6px; border-radius:999px; background:var(--surface-sunken); +.milestone-row:last-child { + border-bottom: none; } -.band-range{ position:absolute; top:0; bottom:0; background:var(--pass-bg); border-radius:999px; } -.band-marker{ - position:absolute; top:50%; width:10px; height:10px; border-radius:50%; - background:var(--ink); border:2px solid var(--surface-raised); box-shadow:0 0 0 1px var(--ink-3); - transform:translate(-50%,-50%); display:none; transition:left .15s; +.milestone-row.log-row { + grid-template-columns: 110px 64px 72px 64px 1fr; } -.band-marker.out-of-band{ background:var(--fail); box-shadow:0 0 0 1px var(--fail); } -@media (max-width:640px){ - .milestone-row, .milestone-row.log-row{ grid-template-columns:1fr; gap:6px; } - .band-track{ order:3; } +.milestone-label { + font-size: 13px; + font-weight: 600; + color: var(--ink); +} +.milestone-plan { + font-family: var(--font-mono); + font-size: 13px; + color: var(--ink-2); + text-align: center; + background: var(--surface-sunken); + border-radius: var(--radius-sm); + padding: 6px 4px; +} +.milestone-time { + text-align: center; +} +.band-track { + position: relative; + height: 6px; + border-radius: 999px; + background: var(--surface-sunken); +} +.band-range { + position: absolute; + top: 0; + bottom: 0; + background: var(--pass-bg); + border-radius: 999px; +} +.band-marker { + position: absolute; + top: 50%; + width: 10px; + height: 10px; + border-radius: 50%; + background: var(--ink); + border: 2px solid var(--surface-raised); + box-shadow: 0 0 0 1px var(--ink-3); + transform: translate(-50%, -50%); + display: none; + transition: left 0.15s; +} +.band-marker.out-of-band { + background: var(--fail); + box-shadow: 0 0 0 1px var(--fail); +} +@media (max-width: 640px) { + .milestone-row, + .milestone-row.log-row { + grid-template-columns: 1fr; + gap: 6px; + } + .band-track { + order: 3; + } } /* ─── Actuator timeline ───────────────────────────────────────────────── */ -.actuator-timeline{ display:flex; flex-direction:column; } -.actuator-step{ display:flex; gap:14px; position:relative; padding-bottom:16px; } -.actuator-step:last-child{ padding-bottom:0; } -.actuator-rail{ display:flex; flex-direction:column; align-items:center; flex:0 0 auto; } -.actuator-dot{ - width:10px; height:10px; border-radius:50%; background:var(--ember); margin-top:10px; flex:0 0 auto; +.actuator-timeline { + display: flex; + flex-direction: column; } -.actuator-line{ width:1px; flex:1 1 auto; background:var(--line); margin-top:4px; } -.actuator-step:last-child .actuator-line{ display:none; } -.actuator-card{ - flex:1 1 auto; background:var(--surface-sunken); border-radius:var(--radius-md); padding:12px 14px; - display:grid; grid-template-columns:70px 1fr 1fr auto; gap:10px; align-items:end; +.actuator-step { + display: flex; + gap: 14px; + position: relative; + padding-bottom: 16px; } -.actuator-card .field-label{ font-size:10.5px; } -.actuator-why{ grid-column:1 / -1; } -.actuator-remove{ - background:none; border:1px solid var(--line); color:var(--ink-3); width:28px; height:28px; - border-radius:var(--radius-sm); cursor:pointer; font-size:12px; align-self:start; +.actuator-step:last-child { + padding-bottom: 0; +} +.actuator-rail { + display: flex; + flex-direction: column; + align-items: center; + flex: 0 0 auto; +} +.actuator-dot { + width: 10px; + height: 10px; + border-radius: 50%; + background: var(--ember); + margin-top: 10px; + flex: 0 0 auto; +} +.actuator-line { + width: 1px; + flex: 1 1 auto; + background: var(--line); + margin-top: 4px; +} +.actuator-step:last-child .actuator-line { + display: none; +} +.actuator-card { + flex: 1 1 auto; + background: var(--surface-sunken); + border-radius: var(--radius-md); + padding: 12px 14px; + display: grid; + grid-template-columns: 70px 1fr 1fr auto; + gap: 10px; + align-items: end; +} +.actuator-card .field-label { + font-size: 10.5px; +} +.actuator-why { + grid-column: 1 / -1; +} +.actuator-remove { + background: none; + border: 1px solid var(--line); + color: var(--ink-3); + width: 28px; + height: 28px; + border-radius: var(--radius-sm); + cursor: pointer; + font-size: 12px; + align-self: start; +} +.actuator-remove:hover { + background: var(--fail-bg); + color: var(--fail); + border-color: var(--fail); +} +@media (max-width: 640px) { + .actuator-card { + grid-template-columns: 1fr 1fr; + } } -.actuator-remove:hover{ background:var(--fail-bg); color:var(--fail); border-color:var(--fail); } -@media (max-width:640px){ .actuator-card{ grid-template-columns:1fr 1fr; } } /* ─── Dock: shared card chrome ───────────────────────────────────────── */ -.dock-card{ - background:var(--surface-raised); border:1px solid var(--line); border-radius:var(--radius-lg); - box-shadow:var(--shadow-card); padding:18px 20px; +.dock-card { + background: var(--surface-raised); + border: 1px solid var(--line); + border-radius: var(--radius-lg); + box-shadow: var(--shadow-card); + padding: 18px 20px; +} +.dock-card-head { + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: 12px; +} +.dock-card-head h2 { + font-size: 13px; + font-weight: 700; + text-transform: uppercase; + letter-spacing: 0.05em; + color: var(--ink-2); } -.dock-card-head{ display:flex; align-items:center; justify-content:space-between; margin-bottom:12px; } -.dock-card-head h2{ font-size:13px; font-weight:700; text-transform:uppercase; letter-spacing:.05em; color:var(--ink-2); } /* ─── Ledger ──────────────────────────────────────────────────────────── */ -.ledger-group{ display:flex; flex-direction:column; } -.ledger-row{ display:flex; align-items:center; gap:8px; padding:6px 0; border-bottom:1px solid var(--line); } -.ledger-row:last-child{ border-bottom:none; } -.l-fid{ font-family:var(--font-mono); font-size:9.5px; color:var(--ink-3); background:var(--surface-sunken); border-radius:4px; padding:1px 4px; flex:0 0 auto; } -.l-label{ font-size:12.5px; color:var(--ink-2); flex:1 1 auto; } -.l-val{ font-family:var(--font-mono); font-size:13px; font-weight:600; color:var(--ink); text-align:right; min-width:52px; } -.ledger-input{ - width:60px; text-align:right; font-family:var(--font-mono); font-size:13px; font-weight:600; - padding:4px 7px; border:1px solid var(--line); border-radius:var(--radius-sm); background:var(--surface-sunken); color:var(--ink); +.ledger-group { + display: flex; + flex-direction: column; } -.ledger-input:focus{ outline:none; border-color:var(--ember); box-shadow:0 0 0 3px var(--ember-soft); background:var(--surface-raised); } -.ledger-total{ - display:flex; align-items:baseline; justify-content:space-between; - margin:10px 0; padding-top:8px; border-top:1.5px solid var(--ink); +.ledger-row { + display: flex; + align-items: center; + gap: 8px; + padding: 6px 0; + border-bottom: 1px solid var(--line); +} +.ledger-row:last-child { + border-bottom: none; +} +.l-fid { + font-family: var(--font-mono); + font-size: 9.5px; + color: var(--ink-3); + background: var(--surface-sunken); + border-radius: 4px; + padding: 1px 4px; + flex: 0 0 auto; +} +.l-label { + font-size: 12.5px; + color: var(--ink-2); + flex: 1 1 auto; +} +.l-val { + font-family: var(--font-mono); + font-size: 13px; + font-weight: 600; + color: var(--ink); + text-align: right; + min-width: 52px; +} +.ledger-input { + width: 60px; + text-align: right; + font-family: var(--font-mono); + font-size: 13px; + font-weight: 600; + padding: 4px 7px; + border: 1px solid var(--line); + border-radius: var(--radius-sm); + background: var(--surface-sunken); + color: var(--ink); +} +.ledger-input:focus { + outline: none; + border-color: var(--ember); + box-shadow: 0 0 0 3px var(--ember-soft); + background: var(--surface-raised); +} +.ledger-total { + display: flex; + align-items: baseline; + justify-content: space-between; + margin: 10px 0; + padding-top: 8px; + border-top: 1.5px solid var(--ink); +} +.ledger-total span { + font-size: 12px; + font-weight: 700; + text-transform: uppercase; + letter-spacing: 0.04em; + color: var(--ink-2); +} +.ledger-total output { + font-family: var(--font-serif); + font-size: 26px; + font-weight: 600; + color: var(--ink); +} +.ledger-total.drop { + border-top: none; + margin-top: 4px; + padding-top: 10px; + background: var(--ember-soft); + border-radius: var(--radius-md); + padding: 12px 14px; + margin-bottom: 0; +} +.ledger-total.drop span { + color: var(--ember-strong); +} +.ledger-total.drop output { + color: var(--ember-strong); + font-size: 30px; } -.ledger-total span{ font-size:12px; font-weight:700; text-transform:uppercase; letter-spacing:.04em; color:var(--ink-2); } -.ledger-total output{ font-family:var(--font-serif); font-size:26px; font-weight:600; color:var(--ink); } -.ledger-total.drop{ border-top:none; margin-top:4px; padding-top:10px; background:var(--ember-soft); border-radius:var(--radius-md); padding:12px 14px; margin-bottom:0; } -.ledger-total.drop span{ color:var(--ember-strong); } -.ledger-total.drop output{ color:var(--ember-strong); font-size:30px; } -.ledger-info{ - display:flex; align-items:center; gap:8px; flex-wrap:wrap; margin:10px 0 16px; - padding:8px 10px; border-left:2px solid var(--line-strong); background:var(--surface-sunken); border-radius:0 var(--radius-sm) var(--radius-sm) 0; +.ledger-info { + display: flex; + align-items: center; + gap: 8px; + flex-wrap: wrap; + margin: 10px 0 16px; + padding: 8px 10px; + border-left: 2px solid var(--line-strong); + background: var(--surface-sunken); + border-radius: 0 var(--radius-sm) var(--radius-sm) 0; +} +.info-pill { + display: flex; + align-items: center; + gap: 5px; + font-size: 11.5px; + color: var(--ink-2); +} +.info-pill span { + color: var(--ink-3); +} +.info-pill output { + font-family: var(--font-mono); + font-weight: 600; +} +.info-note { + font-size: 10px; + color: var(--ink-3); + flex-basis: 100%; } -.info-pill{ display:flex; align-items:center; gap:5px; font-size:11.5px; color:var(--ink-2); } -.info-pill span{ color:var(--ink-3); } -.info-pill output{ font-family:var(--font-mono); font-weight:600; } -.info-note{ font-size:10px; color:var(--ink-3); flex-basis:100%; } /* ─── Sanity checks ───────────────────────────────────────────────────── */ -.checks-grid{ display:grid; grid-template-columns:1fr 1fr; gap:10px; } -.check-tile{ - border:1px solid var(--line); border-radius:var(--radius-md); padding:10px 12px; - display:flex; flex-direction:column; gap:2px; position:relative; +.checks-grid { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 10px; } -.check-name{ font-size:10.5px; color:var(--ink-3); font-weight:600; text-transform:uppercase; letter-spacing:.02em; } -.check-value{ font-family:var(--font-mono); font-size:18px; font-weight:700; color:var(--ink); } -.check-band{ font-size:10.5px; color:var(--ink-3); } -.check-tile::before{ - content:""; position:absolute; top:10px; right:10px; width:8px; height:8px; border-radius:50%; - background:var(--ink-3); +.check-tile { + border: 1px solid var(--line); + border-radius: var(--radius-md); + padding: 10px 12px; + display: flex; + flex-direction: column; + gap: 2px; + position: relative; +} +.check-name { + font-size: 10.5px; + color: var(--ink-3); + font-weight: 600; + text-transform: uppercase; + letter-spacing: 0.02em; +} +.check-value { + font-family: var(--font-mono); + font-size: 18px; + font-weight: 700; + color: var(--ink); +} +.check-band { + font-size: 10.5px; + color: var(--ink-3); +} +.check-tile::before { + content: ""; + position: absolute; + top: 10px; + right: 10px; + width: 8px; + height: 8px; + border-radius: 50%; + background: var(--ink-3); +} +.check-tile.pass::before { + background: var(--pass); +} +.check-tile.fail::before { + background: var(--fail); +} +.check-tile.pass { + border-color: var(--pass-bg); + background: var(--pass-bg); +} +.check-tile.fail { + border-color: var(--fail-bg); + background: var(--fail-bg); +} +.check-tile.pass .check-value { + color: var(--pass); +} +.check-tile.fail .check-value { + color: var(--fail); } -.check-tile.pass::before{ background:var(--pass); } -.check-tile.fail::before{ background:var(--fail); } -.check-tile.pass{ border-color:var(--pass-bg); background:var(--pass-bg); } -.check-tile.fail{ border-color:var(--fail-bg); background:var(--fail-bg); } -.check-tile.pass .check-value{ color:var(--pass); } -.check-tile.fail .check-value{ color:var(--fail); } /* ─── Curve card ──────────────────────────────────────────────────────── */ -.curve-legend{ display:flex; align-items:center; gap:10px; font-size:10.5px; color:var(--ink-3); text-transform:none; letter-spacing:0; font-weight:500; } -.curve-legend .sw{ display:inline-block; width:12px; height:2px; margin-right:3px; vertical-align:middle; } -.sw-plan{ background:var(--ink); } -.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); } +.curve-legend { + display: flex; + align-items: center; + gap: 10px; + font-size: 10.5px; + color: var(--ink-3); + text-transform: none; + letter-spacing: 0; + font-weight: 500; +} +.curve-legend .sw { + display: inline-block; + width: 12px; + height: 2px; + margin-right: 3px; + vertical-align: middle; +} +.sw-plan { + background: var(--ink); +} +.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 { + 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; line-height:1.15; - text-align:center; white-space:normal; - } - .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; } +.connection-status.hidden { + display: none; } -@media (prefers-reduced-motion:reduce){ - *, *::before, *::after{ animation-duration:.01ms !important; animation-iteration-count:1 !important; scroll-behavior:auto !important; transition-duration:.01ms !important; } +@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; + line-height: 1.15; + text-align: center; + white-space: normal; + } + .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: 0.01ms !important; + animation-iteration-count: 1 !important; + scroll-behavior: auto !important; + transition-duration: 0.01ms !important; + } } /* ─── Print: hide the screen shell, show the paper worksheet ───────────── */ -#print-sheet{ display:none; } -.pv{ display:none; } +#print-sheet { + display: none; +} +.pv { + display: none; +} -@media print{ - .app-header, .drawer, .drawer-overlay, .workspace-grid{ display:none !important; } - body{ background:#fff; } - #print-sheet{ display:block; } - .ws-input{ display:none !important; } - .pv{ display:inline-block; min-width:inherit; border-bottom:.9pt solid var(--ink); } - .opt input:checked + span{ border:.9pt solid var(--ink); background:none; color:var(--ink); border-radius:50%; padding:0 1.4mm; } - td.passcell.pass::after, td.passcell.fail::after{ content:none; } - td.passcell.pass::before{ content:"✓ "; } - td.passcell.fail::before{ content:"✗ "; } +@media print { + .app-header, + .drawer, + .drawer-overlay, + .workspace-grid { + display: none !important; + } + body { + background: #fff; + } + #print-sheet { + display: block; + } + .ws-input { + display: none !important; + } + .pv { + display: inline-block; + min-width: inherit; + border-bottom: 0.9pt solid var(--ink); + } + .opt input:checked + span { + border: 0.9pt solid var(--ink); + background: none; + color: var(--ink); + border-radius: 50%; + padding: 0 1.4mm; + } + td.passcell.pass::after, + td.passcell.fail::after { + content: none; + } + td.passcell.pass::before { + content: "✓ "; + } + td.passcell.fail::before { + content: "✗ "; + } } /* ─── Legacy .opt styling reused by the (hidden-on-screen) print worksheet's own radios ── */ -.opt{ display:inline-block; cursor:pointer; margin-right:1.5mm; } -.opt input{ position:absolute; opacity:0; width:0; height:0; } -.opt span{ padding:0 .8mm; border-radius:3mm; } -.opt input:checked + span{ background:#f6efe7; border:.9pt solid #7a3b12; color:#7a3b12; font-weight:700; } -input.f, select.f{ border:none; border-bottom:.9pt solid #1a1512; background:transparent; font:inherit; height:4.2mm; padding:0 .5mm; color:#1a1512; } +.opt { + display: inline-block; + cursor: pointer; + margin-right: 1.5mm; +} +.opt input { + position: absolute; + opacity: 0; + width: 0; + height: 0; +} +.opt span { + padding: 0 0.8mm; + border-radius: 3mm; +} +.opt input:checked + span { + background: #f6efe7; + border: 0.9pt solid #7a3b12; + color: #7a3b12; + font-weight: 700; +} +input.f, +select.f { + border: none; + border-bottom: 0.9pt solid #1a1512; + background: transparent; + font: inherit; + height: 4.2mm; + padding: 0 0.5mm; + color: #1a1512; +} diff --git a/public/index.html b/public/index.html index 34be1c2..0ac9b6c 100644 --- a/public/index.html +++ b/public/index.html @@ -53,10 +53,13 @@ - - +
+ Account +
+ + +
+
(r.ok ? r.json() : null)) .then((body) => { - if (body?.user?.role === "admin") { - const button = document.getElementById("btn-admin"); - button.classList.remove("hidden"); - button.onclick = () => { - location.href = "/admin"; - }; - } + if (body?.user?.role === "admin") + document.getElementById("menu-admin").classList.remove("hidden"); }) .catch(() => {}); initPrefillPanel({