Files
PacketStation/frontend/src/theme/theme.css
T

761 lines
57 KiB
CSS
Raw Normal View History

/*
PESCO dark theme. Ported from the old build's src/app.src.html (PacketStation repo).
Values are copied as they were so trained users see the same look.
Each block notes the old selectors it came from.
Fonts: the old page loaded Barlow Condensed, IBM Plex Sans and IBM Plex Mono from Google Fonts.
Here the same families are self-hosted from the @fontsource npm packages (see src/theme/fonts.ts).
The fallback stacks are the old ones, so the page still reads right if a font file fails.
*/
/* From :root. */
:root {
--bg: #0d161b;
--panel: #1a252b;
--panel2: #162931;
--line: #26363e;
--line2: #33474f;
--cyan: #49c0de;
--pink: #e5589f;
--amber: #e7b33c;
--green: #5fc98a;
--red: #ef6b6b;
--white: #ffffff;
--near: #eff5f8;
--body: #a9bac3;
--muted: #77878f;
--warnbg: #221b28;
/* Shades the old page wrote inline. Named here so components never hard-code them. */
--on-cyan: #06222b;
--on-pink: #2a0717;
--on-green: #06210f;
--field: #0f1b20;
--col: #111d23;
--sel: #123643;
--sheet: #13222a;
--top-from: #0f2129;
--scrim: rgba(3, 8, 10, 0.66);
--f-disp: "Barlow Condensed", "Arial Narrow", Arial, sans-serif;
--f-body: "IBM Plex Sans", Helvetica, Arial, sans-serif;
--f-mono: "IBM Plex Mono", ui-monospace, Consolas, monospace;
--toph: 64px;
color-scheme: dark;
}
/* From *, [hidden], html, body, form controls, :focus-visible, reduced motion, .wrap. */
*, *::before, *::after { box-sizing: border-box; }
[hidden] { display: none !important; }
html, body { background: var(--bg); }
body { color: var(--body); font-family: var(--f-body); font-size: 15px; line-height: 1.45; margin: 0; }
button, input, select, textarea { font: inherit; color: inherit; }
:focus-visible { outline: 2px solid var(--cyan); outline-offset: 2px; }
@media (prefers-reduced-motion: reduce) { * { transition: none !important; animation: none !important; } }
.wrap { padding-inline: 16px; padding-block: 14px 48px; max-width: 1500px; margin: 0 auto; }
/* Top bar. From .top, .top-in, .brand, .brand img, .brand .nm, .roles, .top .sp, .who, .proto. */
.top { position: sticky; top: env(safe-area-inset-top, 0px); z-index: 30; background: linear-gradient(180deg, var(--top-from), var(--bg)); border-bottom: 1px solid var(--line); padding-inline: 16px; padding-block: 10px; }
.top-in { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; max-width: 1500px; margin: 0 auto; }
.brand { display: flex; align-items: center; gap: 12px; min-width: 0; color: inherit; text-decoration: none; }
.brand img { height: 34px; width: auto; }
.brand .nm { font-family: var(--f-disp); font-weight: 600; font-size: 22px; letter-spacing: .06em; color: var(--near); text-transform: uppercase; white-space: nowrap; }
.brand .nm span { color: var(--cyan); }
.roles { display: flex; gap: 4px; background: var(--panel); border: 1px solid var(--line); border-radius: 10px; padding: 4px; flex-wrap: wrap; }
.roles button { border: 0; background: transparent; padding: 8px 14px; border-radius: 7px; font-weight: 600; font-size: 14px; color: var(--body); cursor: pointer; min-height: 40px; }
.roles button[aria-pressed="true"] { background: var(--cyan); color: var(--on-cyan); }
.top .sp { flex: 1; }
.who { font-size: 13px; color: var(--muted); display: flex; align-items: center; gap: 8px; }
.who select { background: var(--panel); border: 1px solid var(--line2); border-radius: 8px; padding: 8px 10px; color: var(--near); font-weight: 600; min-height: 40px; }
.proto { font-family: var(--f-mono); font-size: 11px; letter-spacing: .08em; color: var(--amber); border: 1px solid #5a4720; border-radius: 6px; padding: 3px 7px; text-transform: uppercase; }
/* Type. From .eyebrow, h1, h2, h3, .mono, .muted, .small, .sr, .lnk. */
.eyebrow { font-family: var(--f-mono); font-size: 11.5px; font-weight: 600; letter-spacing: .14em; text-transform: uppercase; color: var(--cyan); }
h1, h2, h3 { color: var(--near); margin: 0; text-wrap: balance; }
h1 { font-family: var(--f-disp); font-weight: 700; font-size: 34px; letter-spacing: .02em; line-height: 1.05; }
h2 { font-family: var(--f-disp); font-weight: 600; font-size: 22px; letter-spacing: .04em; text-transform: uppercase; }
h3 { font-size: 15px; font-weight: 600; }
.mono { font-family: var(--f-mono); font-variant-numeric: tabular-nums; }
.muted { color: var(--muted); }
.small { font-size: 13px; }
.sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
.lnk { all: unset; cursor: pointer; color: var(--cyan); text-decoration: underline; text-underline-offset: 3px; font-weight: 600; }
.lnk:focus-visible { outline: 2px solid var(--cyan); outline-offset: 2px; }
/* KPI tiles. From .kpis, .kpi, button.kpi, .kpi.on, .kpi .n, .kpi .l, .kpi.hot, .kpi.zero, .phead, .pacts. */
.kpis { display: grid; grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); gap: 12px; margin-block: 12px 20px; }
.kpi { background: var(--panel); border: 1px solid var(--line); border-top: 3px solid var(--cyan); border-radius: 10px; padding: 10px 16px 12px; text-align: left; color: inherit; font: inherit; display: block; width: 100%; }
button.kpi { cursor: pointer; position: relative; transition: border-color .15s, background .15s; }
button.kpi:hover { border-color: var(--cyan); border-top-color: var(--cyan); }
button.kpi::after { content: "Tap to show these \2193"; position: absolute; top: 10px; right: 12px; font-size: 11px; color: var(--muted); opacity: 0; transition: opacity .15s; }
button.kpi:hover::after, button.kpi:focus-visible::after { opacity: 1; }
.kpi.on { background: var(--sel); border-color: var(--cyan); }
.kpi.on::after { content: "Showing only these, tap to clear"; opacity: 1; color: var(--cyan); }
.kpi .n { font-family: var(--f-disp); font-weight: 700; font-size: 44px; line-height: 1; color: var(--white); font-variant-numeric: tabular-nums; }
.kpi .n small { font-size: 20px; color: var(--muted); font-weight: 600; }
.kpi .l { font-size: 12.5px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--cyan); margin-top: 6px; }
.kpi.hot { border-top-color: var(--pink); }
.kpi.hot .l { color: var(--pink); }
.kpi.zero { border-top-color: var(--line2); }
.kpi.zero .n, .kpi.zero .l { color: var(--muted); }
.phead { display: flex; align-items: flex-end; justify-content: space-between; gap: 12px 20px; flex-wrap: wrap; margin-top: 4px; }
.pacts { display: flex; gap: 8px; flex-wrap: wrap; }
/* Sections, boards, cards, bars. From .sec, .sec-h, .board, .col, .col-h, .empty, .card, .bar, .panel. */
.sec { margin-block: 8px 26px; }
.sec-h { display: flex; align-items: baseline; gap: 12px; margin-bottom: 10px; flex-wrap: wrap; }
.sec-h .ct { font-family: var(--f-mono); font-size: 13px; color: var(--muted); }
.board { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 14px; }
.col { background: var(--col); border: 1px solid var(--line); border-radius: 12px; padding: 12px; min-width: 0; display: flex; flex-direction: column; gap: 10px; }
/* New: each column is a frame about three cards tall (--col-max) that scrolls on its own, so a long column never pushes the next one out of view. The heading stays put inside the frame. Narrow screens keep the plain flow (one column per row). */
.col { max-height: min(var(--col-max, 700px), calc(100vh - var(--toph, 64px) - 40px)); overflow-y: auto; overscroll-behavior: contain; scrollbar-width: thin; }
.col-h { display: flex; justify-content: space-between; align-items: center; font-family: var(--f-disp); font-size: 17px; font-weight: 600; letter-spacing: .06em; text-transform: uppercase; color: var(--near); }
.col > .col-h { position: sticky; top: -12px; z-index: 1; background: var(--col); margin: -12px -12px 0; padding: 12px 12px 6px; border-bottom: 1px solid var(--line); }
.col-h .c { font-family: var(--f-mono); font-size: 13px; color: var(--muted); }
.empty { border: 1px dashed var(--line2); border-radius: 10px; padding: 16px; color: var(--muted); font-size: 13.5px; text-align: center; }
.empty.slim { padding: 12px 14px; }
.card { background: var(--panel); border: 1px solid var(--line); border-radius: 10px; padding: 12px 14px; display: flex; flex-direction: column; gap: 6px; text-align: left; width: 100%; color: inherit; font: inherit; transition: border-color .15s; }
button.card, a.card { cursor: pointer; text-decoration: none; }
button.card:hover, a.card:hover { border-color: var(--cyan); }
.card .r1 { display: flex; justify-content: space-between; gap: 6px 8px; align-items: center; flex-wrap: wrap; }
.card .r1 .pill { margin-left: auto; max-width: 100%; overflow: hidden; text-overflow: ellipsis; }
.card .job { font-family: var(--f-disp); font-weight: 700; font-size: 20px; color: var(--white); letter-spacing: .03em; }
.card .tt { color: var(--near); font-weight: 500; }
.card .meta { display: flex; gap: 6px 14px; flex-wrap: wrap; font-size: 12.5px; color: var(--muted); }
.card .meta b { color: var(--body); font-weight: 600; }
.bar { height: 6px; border-radius: 3px; background: var(--bg); overflow: hidden; }
.bar i { display: block; height: 100%; background: var(--cyan); }
.bar i.over { background: var(--pink); }
.panel { background: var(--panel); border: 1px solid var(--line); border-radius: 10px; padding: 12px 14px; }
.panel h3 { margin-bottom: 8px; }
/* Pills and status colours. From .pill, .pill::before, .st-*. */
.pill { display: inline-flex; align-items: center; gap: 6px; font-size: 11.5px; font-weight: 700; letter-spacing: .07em; text-transform: uppercase; border-radius: 999px; padding: 3px 10px; white-space: nowrap; border: 1px solid currentColor; }
.pill::before { content: ""; width: 7px; height: 7px; border-radius: 50%; background: currentColor; }
.st-draft { color: #9fb1ba; }
.st-warehouse { color: var(--amber); }
.st-ready { color: var(--cyan); }
.st-assigned { color: #8fa6ff; }
.st-in_progress { color: var(--green); }
.st-review { color: var(--pink); }
.st-qc { color: #b99cff; }
.st-complete { color: #c6d4da; }
.st-filed { color: var(--muted); }
/* New in the rebuild. Health and error states for the shell. */
.st-ok { color: var(--green); }
.st-bad { color: var(--red); }
.st-wait { color: var(--muted); }
/* Buttons and fields. From .btn and its variants, label.f, input.in, select.in, textarea.in, .in.big, .frow, .ckl. */
.btn { display: inline-flex; align-items: center; justify-content: center; gap: 8px; border-radius: 9px; padding: 10px 18px; font-weight: 700; font-size: 15px; border: 1px solid var(--line2); background: var(--panel); color: var(--near); cursor: pointer; min-height: 46px; letter-spacing: .02em; text-decoration: none; }
.btn:hover { border-color: var(--cyan); }
.btn.pri { background: var(--cyan); border-color: var(--cyan); color: var(--on-cyan); }
.btn.pink { background: var(--pink); border-color: var(--pink); color: var(--on-pink); }
.btn.ghost { background: transparent; }
.btn.sm { min-height: 36px; padding: 6px 12px; font-size: 13.5px; }
.btn.dim { opacity: .6; }
.btn.rejb { border-color: var(--red); color: var(--red); background: transparent; }
.btn.voidbtn { border-color: var(--pink); color: var(--pink); }
.btn:disabled { opacity: .45; cursor: not-allowed; }
.btn svg { vertical-align: -4px; }
label.f { display: flex; flex-direction: column; gap: 4px; font-size: 12px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); min-width: 0; }
input.in, select.in, textarea.in { background: var(--field); border: 1px solid var(--line2); border-radius: 8px; padding: 10px 12px; color: var(--near); font-size: 15px; min-height: 44px; width: 100%; text-transform: none; letter-spacing: 0; font-weight: 500; }
input.in:focus, select.in:focus, textarea.in:focus { border-color: var(--cyan); outline: none; }
input.in:disabled, select.in:disabled, textarea.in:disabled { opacity: .55; cursor: not-allowed; }
textarea.in { min-height: 80px; resize: vertical; }
.in.big { font-size: 22px; min-height: 56px; font-family: var(--f-mono); letter-spacing: .08em; }
.frow { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 12px; }
.ckl { display: flex; gap: 10px; align-items: center; font-weight: 600; color: var(--near); min-height: 46px; cursor: pointer; }
.ckl input { width: 24px; height: 24px; accent-color: var(--green); }
/* Chips and segmented control. From .chips, .chip, .seg, .uchip, .rchip. */
.chips { display: flex; gap: 8px; flex-wrap: wrap; }
.chip { display: inline-flex; gap: 8px; align-items: center; border: 1px solid var(--line2); border-radius: 999px; padding: 8px 14px; cursor: pointer; color: var(--near); background: var(--panel); font-size: 14px; min-height: 42px; }
.chip[aria-pressed="true"] { border-color: var(--cyan); background: var(--sel); }
.seg { display: inline-flex; border: 1px solid var(--line2); border-radius: 10px; overflow: hidden; }
.seg button { background: var(--panel); color: var(--near); border: 0; padding: 8px 14px; min-height: 44px; cursor: pointer; font-size: 13.5px; }
.seg button + button { border-left: 1px solid var(--line2); }
.seg button[aria-pressed="true"], .seg button[aria-selected="true"] { background: var(--sel); color: var(--cyan); font-weight: 700; }
.uchip { display: inline-flex; gap: 8px; align-items: center; background: var(--panel); border: 1px solid var(--line); border-radius: 999px; padding: 6px 12px; color: var(--near); font-size: 13px; }
.uchip .mono { color: var(--muted); }
.rchip { display: inline-block; line-height: 1.5; font-size: 11.5px; font-weight: 700; letter-spacing: .04em; border-radius: 6px; padding: 2px 8px; background: #14262e; color: var(--cyan); border: 1px solid #23414c; }
.rchip.supervisor { color: var(--pink); border-color: #5a2a44; background: #22131b; }
.rchip.lead { color: var(--green); border-color: #24503a; background: #10221a; }
.rchip.admin { color: var(--amber); border-color: #5a4720; background: #211c10; }
/* Callouts and notices. From .callout, .callout.warn, .callout b, .viewonly, .back. */
.callout { border-left: 3px solid var(--cyan); background: var(--panel); border-radius: 0 10px 10px 0; padding: 10px 14px; font-size: 14px; margin-block: 10px; }
.callout.warn { border-left-color: var(--pink); background: var(--warnbg); }
.callout b { color: var(--white); }
.viewonly { display: flex; gap: 10px; align-items: flex-start; border: 1px dashed var(--line2); border-radius: 10px; padding: 10px 14px; margin: 8px 0; font-size: 14px; color: var(--body); background: rgba(255, 255, 255, .02); }
.viewonly b { color: var(--near); }
.back { all: unset; cursor: pointer; color: var(--cyan); font-weight: 600; font-size: 14px; display: inline-flex; gap: 6px; align-items: center; padding-block: 6px; }
/* Tabs. From .tabs, .tabs button, .tabs .cnt, .pmtabs (static variant). */
.tabs { display: flex; gap: 2px; border-bottom: 1px solid var(--line); overflow-x: auto; margin-bottom: 14px; position: sticky; top: var(--toph); z-index: 15; background: var(--bg); }
.tabs button { border: 0; background: transparent; color: var(--muted); font-weight: 600; font-size: 15px; padding: 12px 16px; border-bottom: 3px solid transparent; cursor: pointer; white-space: nowrap; min-height: 48px; }
.tabs button[aria-selected="true"] { color: var(--near); border-bottom-color: var(--cyan); }
.tabs .cnt { font-family: var(--f-mono); font-size: 12px; color: var(--cyan); margin-left: 6px; }
.tabs.static { position: static; }
/* Tables. From .tw, table, th, td, td.num, td .sub. Wrap a table in .tw for sideways scroll. */
.tw { overflow-x: auto; border: 1px solid var(--line); border-radius: 10px; }
table { border-collapse: collapse; width: 100%; font-size: 14px; }
th { background: var(--panel2); text-align: left; font-size: 11.5px; letter-spacing: .08em; text-transform: uppercase; color: var(--muted); font-weight: 700; padding: 9px 10px; white-space: nowrap; }
td { border-top: 1px solid var(--line); padding: 9px 10px; vertical-align: middle; color: var(--near); }
td.num, th.num { text-align: right; font-family: var(--f-mono); font-variant-numeric: tabular-nums; }
td .sub { color: var(--muted); font-size: 12.5px; }
/* Sheet, modal and toast. From .scrim, .sheet, .toast. */
.scrim { position: fixed; inset: 0; background: var(--scrim); z-index: 50; display: flex; align-items: center; justify-content: center; padding: 16px; overscroll-behavior: contain; }
.sheet { background: var(--sheet); border: 1px solid var(--line2); border-radius: 16px; width: min(760px, 100%); max-height: calc(100vh - 32px); max-height: calc(100dvh - 32px); overflow: auto; padding: 18px; display: flex; flex-direction: column; gap: 14px; box-shadow: 0 18px 60px rgba(0, 0, 0, .55); margin: auto; }
.sheet-acts { display: flex; gap: 10px; justify-content: flex-end; flex-wrap: wrap; }
.toast { position: fixed; left: 50%; bottom: calc(20px + env(safe-area-inset-bottom, 0px)); transform: translateX(-50%); background: var(--near); color: var(--bg); font-weight: 600; padding: 10px 18px; border-radius: 10px; z-index: 60; box-shadow: 0 6px 20px rgba(0, 0, 0, .4); max-width: calc(100% - 32px); }
/* Sign-in card and PIN keypad. From .auth, .auth-card, .auth-form, .keypad. */
.auth { display: grid; place-items: center; padding-block: 5vh 40px; }
.auth-card { width: min(440px, 100%); background: var(--panel); border: 1px solid var(--line); border-top: 3px solid var(--cyan); border-radius: 14px; padding: 24px; display: flex; flex-direction: column; gap: 14px; }
.auth-form { display: flex; flex-direction: column; gap: 12px; }
.keypad { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; }
.keypad button { min-height: 60px; border-radius: 10px; border: 1px solid var(--line2); background: var(--field); color: var(--near); font-family: var(--f-mono); font-size: 22px; font-weight: 600; cursor: pointer; }
.keypad button:active { background: var(--sel); }
.keypad button:disabled { opacity: .45; cursor: not-allowed; }
/* Lock screen placeholder. From body.blur-hidden #main and #guard .scrim. The guard sits above every sheet. */
.blur-hidden .wrap { filter: blur(18px); }
.scrim.lock { z-index: 90; }
.lock .auth-card { border-top-color: var(--amber); }
/* Motion, opt-in through a .motion class on body. From .motion .scrim, .motion .sheet, .motion .toast and their keyframes. */
@keyframes mfade { from { opacity: 0; } to { opacity: 1; } }
@keyframes msheet { from { opacity: 0; transform: translateY(18px) scale(.985); } to { opacity: 1; transform: none; } }
@keyframes mtoast { from { opacity: 0; transform: translate(-50%, 14px); } to { opacity: 1; transform: translate(-50%, 0); } }
.motion .scrim { animation: mfade .16s ease-out; }
.motion .sheet { animation: msheet .24s cubic-bezier(.2, .7, .2, 1); }
.motion .toast { animation: mtoast .22s cubic-bezier(.2, .7, .2, 1); }
/* Narrow screens. From the old @media (max-width:700px) and (max-width:640px) blocks. */
@media (max-width: 700px) {
.col { max-height: none; overflow-y: visible; }
.col > .col-h { position: static; margin: 0; padding: 0; border-bottom: 0; }
.tw table { min-width: 620px; }
.tabs { top: 0; position: static; }
}
@media (max-width: 640px) {
h1 { font-size: 28px; }
.kpi .n { font-size: 38px; }
.brand .nm { font-size: 18px; }
.phead h1 { font-size: 26px; }
}
/* ===== New in the rebuild (phase 1) ===== */
/* Sign-in, lock screen, Account and Admin. Built only from the tokens above. */
.callout.flush { margin: 0; }
.btn.wide { width: 100%; min-height: 56px; font-size: 17px; }
.center { align-self: center; text-align: center; }
.grow { flex: 1; }
.end { display: flex; align-items: flex-end; }
.nowrap { white-space: nowrap; }
.stack { display: flex; flex-direction: column; gap: 12px; }
.uname { color: var(--near); font-weight: 600; font-size: 14px; }
.chips.plain { list-style: none; margin: 0; padding: 0; }
.chips.tight { gap: 4px; }
.chip.static { cursor: default; min-height: 0; padding: 4px 10px; font-size: 12.5px; }
.kv { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 10px 20px; margin: 0 0 10px; }
.kv dt { font-size: 11.5px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); }
.kv dd { margin: 2px 0 0; color: var(--near); overflow-wrap: anywhere; }
td.clip { max-width: 280px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
tr.rowlink { cursor: pointer; }
tr.rowlink:hover td { background: var(--panel); }
tr.rowlink.on td { background: var(--sel); }
tr.rowlink:focus-visible { outline: 2px solid var(--cyan); outline-offset: -2px; }
td .pill + .pill { margin-left: 4px; }
.lock .auth-card { max-height: calc(100dvh - 32px); overflow: auto; }
/* ===== New in the rebuild (phase 2) ===== */
/* Clerical home, projects and units, the packet page. Ported from the old .dhead, .facts, .projgrid, .pcard,
.stg, .pbar, .unitbar, .projhits, .crumbs, .due, .fltbar, .qrs, .balloon blocks, plus a few new helpers. */
.sheet.narrow { width: min(560px, 100%); }
.sec-h.flush { margin: 0; }
.chip.sm { min-height: 34px; padding: 4px 12px; font-size: 13.5px; }
.grow0 { min-width: 0; flex: 1 1 420px; }
.pre { white-space: pre-wrap; margin-top: 6px; }
.dhead { display: flex; gap: 18px; align-items: flex-end; justify-content: space-between; flex-wrap: wrap; padding-block: 6px 14px; border-bottom: 1px solid var(--line); margin-bottom: 12px; }
.dhead .facts { display: flex; gap: 6px 22px; flex-wrap: wrap; margin-top: 8px; font-size: 13.5px; }
.dhead .facts span { color: var(--muted); }
.dhead .facts b { color: var(--near); font-weight: 600; font-family: var(--f-mono); font-size: 13px; }
.dhead .pacts { align-items: center; }
.dtitle { color: var(--near); font-weight: 500; font-size: 17px; margin-top: 2px; }
.crumbs2 { margin: 4px 0 6px; }
.crumbs2 b { color: var(--near); }
.crumbs { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-bottom: 6px; font-size: 14px; }
.crumbs span { color: var(--muted); }
.crumbs b { color: var(--near); }
.due { font-weight: 600; }
.due.over { color: var(--pink); font-weight: 700; }
.due.soon { color: var(--amber); font-weight: 700; }
.due.muted { opacity: .7; }
.flagline { margin: 4px 0 8px; }
.card .dept { color: var(--cyan); font-weight: 600; }
.attn { display: flex; flex-direction: column; gap: 8px; margin-bottom: 12px; }
.fltbar { background: var(--panel); border: 1px solid var(--line); border-radius: 14px; padding: 12px 14px; margin: 8px 0 16px; display: flex; flex-direction: column; gap: 10px; }
.fltrow { display: flex; gap: 8px 12px; flex-wrap: wrap; align-items: flex-end; }
.fltrow .f { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.fltrow .f > span { font-size: 11.5px; font-weight: 700; letter-spacing: .07em; text-transform: uppercase; color: var(--muted); }
.fltrow .fltq { flex: 3 1 320px; }
.fltrow .fltp { flex: 1.4 1 260px; }
.fltbtns { display: flex; gap: 8px; align-items: flex-end; flex: none; }
.fltrow2 { display: flex; gap: 10px; flex-wrap: wrap; align-items: center; }
.pick { display: flex; flex-direction: column; gap: 6px; }
.pickp { display: flex; gap: 8px; align-items: baseline; flex-wrap: wrap; color: var(--near); }
.pickp .small { font-weight: 700; letter-spacing: .06em; text-transform: uppercase; font-size: 11.5px; }
.projhits { display: flex; flex-direction: column; gap: 6px; max-height: 280px; overflow: auto; }
.projhit { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; text-align: left; background: var(--panel); border: 1px solid var(--line); border-radius: 10px; padding: 10px 14px; color: var(--near); cursor: pointer; font: inherit; }
.projhit:hover, .projhit:focus-visible { border-color: var(--cyan); }
.projhit .pill { margin-left: auto; }
.projgrid { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 12px; }
.pcard .job { font-size: 20px; }
.stg { display: flex; flex-wrap: wrap; gap: 4px 10px; font-size: 12px; margin-top: 6px; }
.stg span { color: var(--near); }
.stg span.z { color: var(--muted); opacity: .6; }
.pbar { height: 8px; border-radius: 5px; background: var(--line2); overflow: hidden; display: flex; margin: 6px 0 2px; }
.pbar i { display: block; height: 100%; }
.pbar i.f { background: var(--cyan); }
.pbar i.c { background: var(--green); }
.unitbar { display: flex; gap: 10px 14px; align-items: center; flex-wrap: wrap; margin-bottom: 10px; }
.unitlist .pbar { margin: 0; }
th.wide { min-width: 160px; }
table.edit td { padding: 6px; }
input.in.sm { min-height: 36px; padding: 6px 8px; font-size: 14px; }
input.in.num { text-align: right; font-family: var(--f-mono); }
.sheet-acts.start { justify-content: flex-start; align-items: center; }
.sigmean { border-left: 3px solid var(--amber); background: var(--panel); border-radius: 0 10px 10px 0; padding: 8px 12px; }
.sigmean .tt { color: var(--near); font-weight: 600; font-size: 16px; margin-top: 2px; }
.actbox { display: flex; flex-direction: column; gap: 10px; margin-bottom: 14px; }
.hmq { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.hmq b { color: var(--near); }
.acts { display: flex; gap: 10px; flex-wrap: wrap; align-items: flex-start; }
.act { display: flex; flex-direction: column; gap: 4px; max-width: 280px; }
.act .why { color: var(--amber); }
label.btn input.sr { pointer-events: none; }
.balloon { display: inline-grid; place-items: center; width: 26px; height: 26px; border-radius: 50%; border: 1.5px solid var(--cyan); color: var(--cyan); font-family: var(--f-mono); font-size: 12.5px; font-weight: 600; }
.qrs { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 340px), 1fr)); gap: 18px; }
.qr { background: var(--panel); border: 1px solid var(--line); border-radius: 12px; padding: 16px; display: flex; gap: 16px; align-items: center; }
.qr .code { background: var(--white); padding: 10px; border-radius: 8px; flex: none; width: 148px; height: 148px; display: grid; place-items: center; color: var(--bg); }
.qr .code canvas { width: 128px !important; height: 128px !important; }
.qr .txt { min-width: 0; flex: 1; overflow-wrap: anywhere; }
.qr .wo { font-family: var(--f-disp); font-weight: 700; font-size: 22px; color: var(--white); letter-spacing: .03em; line-height: 1.15; }
.pdfv { display: flex; flex-direction: column; gap: 10px; }
.pdfv-bar { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }
.pdfv-bar .seg button { min-width: 44px; font-weight: 700; }
.pdfv-body { display: grid; grid-template-columns: 150px 1fr; gap: 12px; align-items: start; }
.pdfv-pages { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }
.pdfv-pages button { width: 100%; text-align: left; background: var(--panel); border: 1px solid var(--line); border-radius: 8px; padding: 8px 10px; color: var(--near); cursor: pointer; font: inherit; display: flex; flex-wrap: wrap; gap: 4px; align-items: center; }
.pdfv-pages button[aria-current="page"] { border-color: var(--cyan); background: var(--sel); }
.pdfv-frame { overflow: auto; background: var(--col); border: 1px solid var(--line); border-radius: 10px; padding: 1px; min-height: 240px; max-height: calc(100dvh - 160px); }
.pdfv-canvas { display: block; background: var(--white); }
@media (max-width: 700px) {
.pdfv-body { grid-template-columns: 1fr; }
.pdfv-pages { flex-direction: row; flex-wrap: wrap; }
.pdfv-pages button { width: auto; }
}
/* ===== New in the rebuild (phase 4) ===== */
/* The warehouse board, the stage pill and line, the pull table. From the old .wh-*, .whline, .whacts, .whcard,
.whboard, .whcol, .whover, .whsrc, .whghost, .whstep, .whgrp, .whdates, .visbadge, .heat and the pullTable rows. */
.col-h h3 { font: inherit; letter-spacing: inherit; text-transform: inherit; color: inherit; }
.wh-in { color: #d9b25e; border-style: dashed; }
.wh-pull { color: var(--amber); }
.wh-hold { color: var(--pink); }
.wh-done { color: var(--green); }
.whline { font-size: 12.5px; font-weight: 600; padding: 4px 8px; border-radius: 6px; background: rgba(255, 255, 255, .04); border-left: 3px solid currentColor; }
.whline.wh-in { border-left-style: dashed; }
.whacts { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 2px; }
.whcard { cursor: pointer; }
.whcard:hover, .whcard:focus-visible { border-color: var(--cyan); }
.whcard.whdrag { touch-action: pan-y; user-select: none; }
.whboard { grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); }
.whcol { transition: border-color .12s, background .12s; }
.whcol.whover { border-color: var(--cyan); background: #12303a; }
.whsrc { opacity: .35; }
.whghost { position: fixed; z-index: 80; pointer-events: none; transform: translate(-50%, -30%) rotate(1.5deg); box-shadow: 0 10px 30px rgba(0, 0, 0, .5); opacity: .95; }
.whstep { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; margin-bottom: 6px; }
.whgrpbox { display: flex; flex-direction: column; gap: 10px; }
.whgrp { display: flex; justify-content: space-between; align-items: center; margin: 10px 2px 0; font-size: 12px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: var(--cyan); }
.whgrpbox:first-of-type .whgrp { margin-top: 2px; }
.whgrp b { color: var(--muted); }
.whdates { display: flex; gap: 10px; flex-wrap: wrap; color: var(--muted); }
.whdates b { color: var(--body); }
.visbadge { display: inline-block; font-size: 10.5px; font-weight: 700; letter-spacing: .08em; padding: 2px 7px; border-radius: 5px; border: 1px solid var(--cyan); color: var(--cyan); margin-right: 6px; }
.heat { font-family: var(--f-mono); font-weight: 600; color: var(--amber); }
.heat.none { color: var(--muted); font-weight: 400; }
input.in.heatIn { font-family: var(--f-mono); min-width: 170px; }
input.in.heatIn.need { border-color: var(--amber); box-shadow: 0 0 0 1px var(--amber) inset; }
input.in.w80 { width: 80px; }
input.in.w110 { width: 110px; }
table.pull td.need { font-size: 18px; font-weight: 600; }
tr.pullrow.pulled td { background: #13261d; }
tr.pullrow.short td { background: #2a1a24; }
tr.pullerr td { border-top: 0; padding-top: 0; }
.pullck { display: flex; gap: 8px; align-items: center; }
.pullck input { width: 26px; height: 26px; accent-color: var(--green); }
.nack { display: inline-flex; gap: 6px; align-items: center; white-space: nowrap; }
.nack input { width: 20px; height: 20px; }
td.heatcell { min-width: 190px; }
td.shortcell { min-width: 150px; }
.stack.tight { gap: 4px; align-items: flex-start; }
.shortchip { display: inline-flex; flex-wrap: wrap; gap: 4px; align-items: center; }
td.shortqty { font-size: 18px; font-weight: 700; color: var(--pink); }
td.late { color: var(--red); }
.btn.dim { opacity: .55; pointer-events: none; }
.btn.pinktxt { color: var(--pink); }
.mtrframe { width: 100%; height: min(75vh, 900px); border: 1px solid var(--line); border-radius: 10px; background: var(--white); }
.mtrimg { max-width: 100%; height: auto; border-radius: 10px; background: var(--white); align-self: center; }
.bar.usage { position: relative; height: 12px; border-radius: 6px; }
.bar.usage .mark { position: absolute; top: 0; bottom: 0; width: 2px; background: var(--amber); }
/* Phase 5: shop screens. From .stalls, .stall, .sn, .cotag, .cohot, .stallhero, .cobanner, .cob-h, .cob-t, .cob-row, .cosec. */
.stalls { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 10px; align-items: start; }
.stall { background: var(--panel2); border: 1px solid var(--line); border-radius: 10px; padding: 10px 12px; display: flex; flex-direction: column; gap: 5px; min-height: 112px; }
.stall .sn { font-family: var(--f-disp); font-weight: 700; font-size: 18px; letter-spacing: .08em; color: var(--near); display: flex; justify-content: space-between; gap: 8px; }
.stall.idle { opacity: .55; min-height: 0; padding-block: 8px; }
.stall.idle .sn { font-size: 15px; }
.stall .stjob { display: flex; flex-direction: column; gap: 4px; }
.stall .stjob + .stjob { border-top: 1px solid var(--line); padding-top: 6px; }
.stall button.stopen { all: unset; cursor: pointer; color: var(--cyan); font-weight: 600; font-size: 14px; }
.stall button.stopen:focus-visible, .cotag:focus-visible { outline: 2px solid var(--cyan); outline-offset: 2px; }
.stall.cohot { border: 2px solid var(--pink); box-shadow: 0 0 0 3px rgba(229, 88, 159, .18); }
.cotag, .stall button.cotag { all: unset; cursor: pointer; display: block; margin: 6px 0; background: var(--pink); color: var(--white); font-weight: 700; font-size: 11.5px; letter-spacing: .04em; padding: 5px 8px; border-radius: 6px; line-height: 1.25; text-transform: uppercase; }
.stempty { margin-bottom: 22px; }
.stclock { display: flex; align-items: center; flex-wrap: wrap; gap: 0 4px; }
.sdot { display: inline-block; width: 10px; height: 10px; border-radius: 50%; background: var(--muted); margin-right: 6px; }
.sdot.run { background: var(--green); animation: sdotpulse 1.6s infinite; }
@keyframes sdotpulse { 0% { box-shadow: 0 0 0 0 rgba(95, 201, 138, .55); } 70% { box-shadow: 0 0 0 8px rgba(95, 201, 138, 0); } 100% { box-shadow: 0 0 0 0 rgba(95, 201, 138, 0); } }
.stallhero { display: flex; align-items: center; gap: 16px; flex-wrap: wrap; margin-block: 6px 18px; }
.stallhero .big { font-family: var(--f-disp); font-weight: 700; font-size: 64px; line-height: .9; color: var(--white); letter-spacing: .04em; }
.stallhero .stpick { min-width: 220px; }
.stnone { margin-top: 30px; }
.cobanner { border: 3px solid var(--pink); background: linear-gradient(180deg, rgba(229, 88, 159, .22), rgba(229, 88, 159, .08)); border-radius: 14px; padding: 14px 16px; margin: 4px 0 18px; display: flex; flex-direction: column; gap: 10px; box-shadow: 0 0 0 4px rgba(229, 88, 159, .12); animation: copulse 2.2s ease-in-out infinite; }
@keyframes copulse { 0%, 100% { box-shadow: 0 0 0 4px rgba(229, 88, 159, .12), 0 0 0 0 rgba(229, 88, 159, 0); border-color: var(--pink); } 50% { box-shadow: 0 0 0 6px rgba(229, 88, 159, .30), 0 0 34px 6px rgba(229, 88, 159, .38); border-color: #ff8cc4; } }
.cob-h { display: flex; gap: 12px; align-items: center; color: var(--near); }
.cob-h svg { color: var(--pink); flex: none; animation: cobpulse 1.6s ease-in-out infinite; }
@keyframes cobpulse { 50% { opacity: .35; } }
.cob-t { font-family: var(--f-disp); font-size: 26px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase; color: var(--white); line-height: 1.1; }
.cob-row { display: flex; gap: 12px; align-items: center; justify-content: space-between; flex-wrap: wrap; background: rgba(13, 22, 27, .7); border-radius: 10px; padding: 10px 12px; }
.cob-txt { min-width: 0; }
.cosec { border-left: 4px solid var(--pink); padding-left: 12px; }
.supchips { justify-content: flex-end; }
@media (max-width: 640px) {
.stalls { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.stall.busy { grid-column: 1 / -1; }
.cob-t { font-size: 20px; }
.stallhero .big { font-size: 48px; }
}
/* Phase 5: packet page. From .dv, .viewer, .stage, .mk, .ld, .arw, .ht, .htbl, .htprev, .vtools, .fsbar, body.fs-view,
.pagesel, .side, .hlist, .ichip, .ck, .ck-item, .cklay, .clock, .cdot. The drawing stays on white.
Appended after the shop screens block because that block was written first; no selector overlaps it. */
.dv { display: grid; grid-template-columns: minmax(0, 1fr) 320px; gap: 14px; align-items: start; }
.dv.solo { grid-template-columns: minmax(0, 1fr); }
@media (max-width: 980px) { .dv { grid-template-columns: minmax(0, 1fr); } }
.viewer { position: relative; background: var(--white); border-radius: 10px; overflow: hidden; height: min(68vh, 720px); touch-action: none; border: 1px solid var(--line2); cursor: grab; user-select: none; -webkit-user-select: none; -webkit-touch-callout: none; }
.viewer.panning { cursor: grabbing; }
.viewer.marking { cursor: crosshair; outline: 3px solid var(--pink); outline-offset: -3px; }
.viewer.placing { cursor: crosshair; outline: 3px solid var(--amber); outline-offset: -3px; }
.stage { position: absolute; left: 0; top: 0; transform-origin: 0 0; }
.stage-canvas { display: block; max-width: none; pointer-events: none; }
.vload { position: absolute; inset: 0; display: grid; place-items: center; color: #44535a; padding: 16px; pointer-events: none; }
.vload .callout { pointer-events: auto; }
.lead { position: absolute; left: 0; top: 0; width: 100%; height: 100%; overflow: visible; pointer-events: none; }
.ld { stroke-width: 2.5; vector-effect: non-scaling-stroke; fill: none; }
.ld.h { stroke: #b07800; }
.ld.w { stroke: #c2185b; }
.ld.carried { stroke-dasharray: 6 4; }
.mk { position: absolute; z-index: 2; transform: translate(-50%, -50%) scale(var(--inv, 1)); transform-origin: center; width: 44px; height: 44px; border-radius: 50%; background: #fff; color: #c2185b; border: 3px solid #c2185b; font-family: var(--f-mono); font-size: 13px; font-weight: 700; display: grid; place-items: center; box-shadow: 0 2px 6px rgba(0, 0, 0, .45); cursor: pointer; padding: 0; }
.mk.drag { cursor: move; touch-action: none; }
.mk.carried { border-style: dashed; opacity: .85; }
.arw { position: absolute; z-index: 1; width: 20px; height: 14px; transform: translate(-100%, -50%) rotate(var(--rot, 0deg)) scale(var(--inv, 1)); transform-origin: 100% 50%; pointer-events: none; }
.arw::before { content: ""; position: absolute; inset: 0; clip-path: polygon(0 0, 100% 50%, 0 100%); }
.arw.h::before { background: #b07800; }
.arw.w::before { background: #c2185b; }
.arw.drag { pointer-events: auto; cursor: move; touch-action: none; width: 30px; height: 22px; }
.ht { position: absolute; z-index: 2; transform: translate(-50%, -50%) scale(var(--inv, 1)); display: inline-flex; align-items: center; gap: 7px; background: #fff8e6; border: 2px solid #b07800; color: #3d2a00; border-radius: 999px; padding: 3px 12px 3px 3px; font-family: var(--f-mono); font-weight: 700; font-size: 13px; white-space: nowrap; box-shadow: 0 2px 6px rgba(0, 0, 0, .35); cursor: pointer; line-height: 1.2; min-height: 34px; }
.ht .hn { display: grid; place-items: center; width: 26px; height: 26px; border-radius: 50%; background: #b07800; color: #fff; font-size: 12px; flex: none; }
.ht.none { border-style: dashed; color: #7a5a20; }
.ht.drag { cursor: move; touch-action: none; }
.ht.carried { opacity: .85; }
.htbl { position: absolute; z-index: 3; font-size: calc(var(--sw, 3000px) * 0.0075 * var(--hs, 1)); background: #fff; border: .16em solid #b07800; color: #2b1d00; font-family: Arial, Helvetica, sans-serif; line-height: 1.15; box-shadow: 0 .1em .4em rgba(0, 0, 0, .35); user-select: none; -webkit-user-select: none; }
.htbl.drag { cursor: move; touch-action: none; }
.htbl.drag:hover, .htbl.moving { outline: .12em dashed var(--cyan); outline-offset: .25em; }
.htbl .htcap { background: #b07800; color: #fff; font-weight: 700; font-size: .85em; text-align: center; padding: .2em .5em; letter-spacing: .04em; }
.htbl .htcols { display: flex; align-items: flex-start; }
.htbl table { border-collapse: collapse; margin: 0; width: auto; font-size: inherit; }
.htbl th, .htbl td { border: .08em solid #b07800; padding: .2em .5em; white-space: nowrap; background: #fff; color: #2b1d00; font-size: 1em; }
.htbl th { background: #f3e2b8; color: #3d2a00; font-size: .8em; font-weight: 700; text-align: center; letter-spacing: .03em; text-transform: none; }
.htbl td.i { text-align: center; font-weight: 700; }
.htbl td.h { font-family: "Courier New", monospace; font-weight: 700; }
.htbl td.h.none { color: #b00020; }
.htbl td.h.na { color: #6b5a3a; }
.htbl.static { position: static; font-size: 13px; box-shadow: none; display: inline-block; max-width: 100%; overflow: auto; }
.htbl.htghost { position: fixed; z-index: 70; pointer-events: none; font-size: 13px; opacity: .92; transform: translate(-10px, -10px); }
.htprev { border: 1px dashed var(--line2); border-radius: 10px; padding: 10px; }
.htprev.htgrab { cursor: grab; touch-action: none; user-select: none; -webkit-user-select: none; }
.htprev.htgrab:hover { border-color: var(--cyan); }
.vtools { position: absolute; right: 10px; top: 10px; display: flex; flex-direction: column; gap: 6px; z-index: 4; }
.vtools button { width: 44px; height: 44px; border-radius: 9px; border: 1px solid #c9d3d8; background: rgba(255, 255, 255, .94); color: #1a252b; font-size: 20px; font-weight: 700; cursor: pointer; display: grid; place-items: center; padding: 0; }
.vtools button.fit { font-size: 13px; }
.vtools button svg { display: block; margin: auto; }
.fsbar { display: none; }
body.fs-view { overflow: hidden; }
body.fs-view .viewer { position: fixed; inset: 0; width: 100vw; height: 100vh; height: 100dvh; z-index: 80; border-radius: 0; border: 0; }
body.fs-view .fsbar { display: flex; position: absolute; left: 10px; top: 10px; max-width: calc(100% - 80px); z-index: 4; gap: 6px; flex-wrap: wrap; align-items: center; background: rgba(13, 22, 27, .9); padding: 6px 8px; border-radius: 10px; color: var(--near); cursor: default; }
.fsbar .fst { font-size: 13px; margin-right: 6px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 40vw; }
body.fs-view .scrim { z-index: 95; }
body.fs-view .toast { z-index: 99; }
.pagesel { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }
.side { display: flex; flex-direction: column; gap: 12px; min-width: 0; }
.hlist { display: flex; flex-direction: column; gap: 7px; font-size: 13.5px; }
.hlist .row { display: grid; grid-template-columns: 28px 1fr auto; gap: 8px; align-items: center; }
.hlist .row .d { min-width: 0; color: var(--near); overflow-wrap: anywhere; }
.hlist .rowbtn { all: unset; display: grid; grid-template-columns: 28px 1fr auto; gap: 8px; align-items: center; cursor: pointer; min-height: 44px; border-radius: 8px; padding: 0 4px; }
.hlist .rowbtn:hover { background: var(--panel2); }
.hlist .rowbtn:focus-visible { outline: 2px solid var(--cyan); outline-offset: 2px; }
.balloon.pinkb { border-color: var(--pink); color: var(--pink); }
.balloon.carried { border-style: dashed; }
.flabel { font-size: 12px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); margin-bottom: 6px; }
.ichip { width: 56px; height: 56px; border-radius: 50%; border: 2px solid var(--line2); background: var(--panel); color: var(--near); font-family: var(--f-mono); font-size: 20px; font-weight: 700; cursor: pointer; transition: background .12s, border-color .12s, transform .12s; }
.ichip:hover { border-color: var(--cyan); }
.ichip[aria-pressed="true"] { background: var(--cyan); border-color: var(--cyan); color: var(--on-cyan); box-shadow: 0 0 0 4px rgba(73, 192, 222, .28); transform: scale(1.06); }
.ichip:disabled { cursor: default; }
.ck { display: flex; flex-direction: column; gap: 8px; }
.ck-item { display: flex; gap: 14px; align-items: center; background: var(--panel); border: 1px solid var(--line); border-radius: 10px; padding: 12px 14px; cursor: pointer; min-height: 58px; }
.ck-item input { width: 28px; height: 28px; accent-color: var(--green); flex: none; }
.ck-item .t { color: var(--near); font-weight: 500; flex: 1; min-width: 0; }
.ck-item .by { font-size: 12px; color: var(--muted); text-align: right; }
.ck-item.done { border-color: #2d5a41; }
.ck-item[aria-disabled="true"] { cursor: default; }
.cklay { display: grid; grid-template-columns: minmax(0, 1fr) 360px; grid-template-areas: "main side"; gap: 18px; align-items: start; }
.cklay .ckmain { grid-area: main; min-width: 0; }
.cklay .ckside { grid-area: side; position: sticky; top: calc(var(--toph, 64px) + 64px); }
@media (max-width: 980px) { .cklay { grid-template-columns: minmax(0, 1fr); grid-template-areas: "main" "side"; } .cklay .ckside { position: static; } }
.clockrow { display: flex; gap: 16px; align-items: baseline; flex-wrap: wrap; margin-right: auto; }
.clock { font-family: var(--f-disp); font-weight: 700; font-size: 40px; color: var(--white); line-height: 1; font-variant-numeric: tabular-nums; }
.clock small { font-size: 18px; color: var(--muted); }
.cdot { display: inline-block; width: 12px; height: 12px; border-radius: 50%; background: var(--muted); margin-right: 10px; vertical-align: middle; }
.cdot.run { background: var(--green); animation: cdotpulse 1.6s infinite; }
@keyframes cdotpulse { 0% { box-shadow: 0 0 0 0 rgba(95, 201, 138, .6); } 70% { box-shadow: 0 0 0 10px rgba(95, 201, 138, 0); } 100% { box-shadow: 0 0 0 0 rgba(95, 201, 138, 0); } }
.labor { color: var(--body); }
.labor b { color: var(--amber); font-family: var(--f-mono); }
.acts.center { align-items: center; }
.revrow { display: flex; gap: 10px 16px; flex-wrap: wrap; align-items: flex-end; }
.revrow.sep { border-top: 1px solid var(--line); padding-top: 10px; }
.revrow .f { flex: 0 1 220px; }
.revrow .f.grow2 { flex: 1 1 260px; }
.presence { display: flex; gap: 8px; align-items: center; color: var(--body); margin: 6px 0; }
.pdot { width: 9px; height: 9px; border-radius: 50%; background: var(--cyan); flex: none; }
.verifybox { border-color: var(--pink); }
.pinktxt { color: var(--pink); }
.amber { color: var(--amber); }
.near { color: var(--near); }
.mb6 { margin-bottom: 6px; }
.mb8 { margin-bottom: 8px; }
.mb10 { margin-bottom: 10px; }
.mt8 { margin-top: 8px; }
.mt10 { margin-top: 10px; }
/* Phase 6: packet page. From .vtb, .qcdoc, .qcdocs, .itphold and the qcTab layout of the old build. */
.vtbs { display: flex; gap: 6px; }
.vtb { border: 2px solid var(--line2); background: var(--panel); color: var(--body); border-radius: 8px; padding: 8px 14px; font-weight: 700; cursor: pointer; min-height: 42px; }
.vtb:disabled { opacity: .6; cursor: default; }
.vtb.acc[aria-pressed="true"] { background: var(--green); border-color: var(--green); color: var(--on-green); }
.vtb.rej[aria-pressed="true"] { background: var(--pink); border-color: var(--pink); color: var(--on-pink); }
.qctab .ck-item .t .hint { display: block; margin-top: 2px; font-weight: 400; }
.qcinsp { max-width: 720px; }
.qcnde { max-width: 900px; }
.qcnotes { margin-top: 12px; max-width: 900px; }
.qcroute { flex: 0 1 260px; }
.qcbar .acts { align-items: flex-end; }
.qcrej a.lnk, .itphold a.lnk { font-weight: 600; }
.itphold b { color: var(--amber); }
.qcdocs { display: grid; gap: 8px; }
.qcdoc { display: flex; gap: 12px; align-items: flex-start; flex-wrap: wrap; padding: 12px 14px; border: 1px solid var(--line); border-radius: 10px; background: var(--panel); }
.qcdoc.old { opacity: .7; }
.qcdoc .m { flex: 1 1 240px; min-width: 0; }
.qcdoc .a { display: flex; gap: 8px; flex-wrap: wrap; }
.qchist .pill { margin-right: 4px; }
input.in.w220 { width: 220px; max-width: 100%; }
.mt4 { margin-top: 4px; }
/* Phase 6: Q.C. screens. Ported from the old .qcunits, .qcunit, .qcdocs, .qcdoc, .itpcard, .itphdr, .itppage,
.itpsec, .itprows, .itprow, .itpblock, .sigs, .ini, .rejtag, .custrec blocks, plus a few new helpers. */
.qcfolders { margin-top: 22px; }
.qcunits { display: grid; grid-template-columns: repeat(auto-fill, minmax(190px, 1fr)); gap: 10px; }
.qcunit { gap: 8px; padding: 10px 12px; align-items: stretch; text-align: left; }
.qcunit .job { font-size: 17px; }
.qcunit .qm { display: flex; justify-content: space-between; gap: 8px; font-size: 13px; color: var(--muted); }
.qcunit .qm .ok, .qcdoc .ok { color: var(--green); }
.qcdocs { display: grid; gap: 8px; list-style: none; margin: 0; padding: 0; }
.qcdoc { display: flex; gap: 12px; align-items: flex-start; flex-wrap: wrap; padding: 12px 14px; border: 1px solid var(--line); border-radius: 10px; background: var(--panel); }
.qcdoc.old { opacity: .7; }
.qcdoc .tag { font-size: 12px; font-weight: 700; padding: 3px 8px; border-radius: 6px; background: var(--panel2); border: 1px solid var(--line2); white-space: nowrap; }
.qcdoc .m { flex: 1 1 240px; min-width: 0; }
.qcdoc .a { display: flex; gap: 8px; flex-wrap: wrap; }
.itpcard { display: flex; gap: 14px; align-items: center; flex-wrap: wrap; padding: 14px 16px; border: 1px solid var(--line); border-radius: 10px; background: var(--panel); }
a.itpcard { flex-direction: row; text-align: left; }
.itpcard .grow { flex: 1 1 260px; min-width: 0; }
.itpcard .bar { background: var(--panel2); margin: 8px 0 6px; }
.itphdr { display: grid; grid-template-columns: repeat(auto-fill, minmax(210px, 1fr)); gap: 10px; }
.itppage { margin: 26px 0 4px; font-family: var(--f-disp); font-size: 13px; letter-spacing: .12em; text-transform: uppercase; color: var(--cyan); }
.itppage span { color: var(--muted); margin-right: 6px; }
.itpsec .sec-h h2 { font-size: 17px; }
.itprows { display: grid; gap: 6px; }
.itprow { display: grid; grid-template-columns: 42px minmax(0, 1fr) 44px 210px 130px 44px; gap: 10px; align-items: center; padding: 10px 12px; border: 1px solid var(--line); border-radius: 10px; background: var(--panel); }
.itprow.hold { border-left: 3px solid var(--amber); }
.itprow.rej { border-left: 3px solid var(--red); }
.itprow .rejtag { font-size: 12px; color: var(--red); flex-basis: 100%; }
.itprow .apr { display: flex; gap: 6px; flex-wrap: wrap; }
.itprow.na { opacity: .55; }
.itprow.na .t b { text-decoration: line-through; }
.itprow .cd { display: inline-block; min-width: 34px; text-align: center; font-weight: 700; font-size: 12px; padding: 3px 6px; border-radius: 6px; background: var(--panel2); border: 1px solid var(--line2); }
.itprow .qc, .itprow .cu { display: flex; flex-wrap: wrap; gap: 4px 8px; align-items: center; }
.itprow.hd { background: none; border: 0; padding: 0 12px; font-size: 11px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: var(--muted); }
.itprow .ini { font-family: var(--f-disp); font-weight: 700; font-size: 16px; color: var(--green); }
.itpblock { margin: 8px 0 18px; padding: 12px 14px; border: 1px dashed var(--line2); border-radius: 10px; }
.itpblock .sigs { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 12px; margin-top: 8px; }
.itpblock .custrec { display: flex; gap: 6px; flex-wrap: wrap; align-items: center; }
.itpblock .custrec .in { max-width: 200px; }
@media (max-width: 760px) {
.itprow.hd { display: none; }
.itprow { grid-template-columns: 38px minmax(0, 1fr) 40px; }
.itprow .qc { grid-column: 2; grid-row: 2; }
.itprow .cu { grid-column: 2 / 4; grid-row: 3; }
.itprow .mb { grid-column: 3; grid-row: 2; }
}
/* New: the line sheet's N/A checkbox row, the ITP log list and the write message pinned to the bottom. */
.itpck { display: flex; align-items: center; gap: 10px; font-size: 14px; color: var(--near); }
.itpck input { width: 20px; height: 20px; }
.itplog { list-style: none; margin: 0; padding: 0; display: grid; gap: 4px; color: var(--body); }
.itpmsg { position: fixed; left: 50%; bottom: calc(20px + env(safe-area-inset-bottom, 0px)); transform: translateX(-50%); z-index: 60; max-width: calc(100% - 32px); box-shadow: 0 6px 20px rgba(0, 0, 0, .4); }
2026-10-17 23:49:14 -06:00
/* Phase 7: a print menu row is a whole-width button in the .ck list. */
.ck-item.prow { width: 100%; text-align: left; font: inherit; color: inherit; }
.ck-item.prow .t .small { display: block; margin-top: 2px; font-weight: 400; }
.prints { list-style: none; margin: 0; padding: 0; display: grid; gap: 6px; }
.callout .acts .grow { min-width: 240px; }
/* Phase 8: Project Management. From .pmtabs, .pmscope, .pmk, .pmsum, .pmbars, .pmbar, .slowtag, .pmtable. */
.pmtabs { position: static; margin: 14px 0 10px; }
.pmtabs button { font-size: 15px; }
.pmscope { margin: -6px 0 14px; }
.pmk { grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); }
.pmk .kpi .n { font-size: 38px; }
.pmsum h3 { margin-bottom: 6px; }
.pmsum ul { margin: 0; padding-left: 18px; display: flex; flex-direction: column; gap: 4px; color: var(--near); }
.pmbars { display: flex; flex-direction: column; gap: 6px; }
.pmbar { display: grid; grid-template-columns: minmax(150px, 240px) minmax(0, 1fr) minmax(130px, 200px); gap: 12px; align-items: center; font-size: 13.5px; }
.pmbar .lb { color: var(--body); }
.pmbar .tr { height: 14px; background: var(--line); border-radius: 3px; overflow: hidden; }
.pmbar .tr i { display: block; height: 100%; background: var(--cyan); border-radius: 0 4px 4px 0; min-width: 0; }
.pmbar.hot .tr i { background: var(--pink); }
.pmbar.zero { opacity: .5; }
.pmbar .v { color: var(--near); font-variant-numeric: tabular-nums; }
.slowtag { color: var(--pink); font-weight: 700; font-size: 11px; letter-spacing: .06em; text-transform: uppercase; }
.pmtable td { font-size: 13.5px; }
.pmtable tr.flag td { color: #ffb3d6; }
.pmtable tr.sub td { background: rgba(255, 255, 255, .02); font-size: 13px; }
.pmtable tr.rowlink:hover td { background: rgba(73, 192, 222, .08); }
.motion .m-enter .pmbar .tr i { transform-origin: left center; animation: mgrow .6s .15s cubic-bezier(.2, .7, .2, 1) both; }
/* New: the period select's width, the note under a table heading, sideways scroll for wide report tables. */
.pmper { min-width: 170px; }
.pmnote { margin: -4px 0 8px; }
.pmtable { min-width: 720px; }
@media (max-width: 640px) {
.pmbar { grid-template-columns: 1fr; gap: 4px; }
.pmbar .v { font-size: 12.5px; }
}
/* Phase 8: find bar, motion, layout. From the old .fltbar, .fltrow, .fltadv, .fltbtns, .fltn, .fltrow2 .chip,
.projsum, .joblist rows, .mbtn, .mdot, .m-enter, .m-tab, .m-bump and the motion keyframes. Then the sheet
placement and the iPad and phone widths, which are new in the rebuild. */
.fltrow .f { flex: 1 1 160px; min-width: 130px; }
.fltrow .f select, .fltrow .f input { width: 100%; }
.fltrow .fltq { flex: 3 1 320px; }
.fltrow .fltp { flex: 1.4 1 260px; }
.fltbtns { flex-wrap: wrap; }
.fltbtns .btn { min-height: 44px; }
.fltbtns .btn.on { border-color: var(--cyan); color: var(--cyan); }
.fltn { display: inline-grid; place-items: center; min-width: 20px; height: 20px; border-radius: 10px; background: var(--cyan); color: #06222b; font-size: 12px; padding: 0 5px; }
.fltadv { padding-top: 2px; }
.fltrow2 .chip { min-height: 36px; padding: 5px 12px; font-size: 13px; }
.projsel2 { display: flex; gap: 8px; }
.fltrow .projsel2 select { flex: 1 1 0; min-width: 0; }
.fltbar .projsum { padding: 8px 10px; border-top: 1px solid var(--line); display: flex; flex-direction: column; gap: 4px; }
.joblist-sec .sec-h { flex-wrap: wrap; align-items: flex-end; }
.jlsort { display: flex; flex-direction: column; gap: 4px; min-width: 200px; }
.jlsort > span { font-size: 11.5px; font-weight: 700; letter-spacing: .07em; text-transform: uppercase; color: var(--muted); }
.joblist tr.rowlink:focus td { background: rgba(73, 192, 222, .08); }
.cardw { border-radius: 10px; }
.cardw > .card { height: 100%; }
.presence { flex-wrap: wrap; }
/* The Motion switch in the top bar. */
.mbtn { display: inline-flex; align-items: center; gap: 6px; }
.mbtn .mdot { width: 8px; height: 8px; border-radius: 50%; background: var(--muted); }
/* Motion, only under body.motion. Reduced motion never gets the class, and the rule at the top stops it anyway. */
@keyframes menter { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }
@keyframes mtab { from { opacity: 0; transform: translateY(4px); } to { opacity: 1; transform: none; } }
@keyframes mgrow { from { transform: scaleX(0); } to { transform: scaleX(1); } }
@keyframes mglow { 0% { box-shadow: 0 0 0 0 rgba(73, 192, 222, 0); } 15% { box-shadow: 0 0 0 3px rgba(73, 192, 222, .75), 0 0 22px rgba(73, 192, 222, .45); } 100% { box-shadow: 0 0 0 0 rgba(73, 192, 222, 0); } }
@keyframes mlive { 0%, 100% { opacity: 1; transform: scale(1); } 50% { opacity: .35; transform: scale(.7); } }
@keyframes mbump { 30% { color: var(--cyan); } }
.motion .m-enter > * { animation: menter .32s cubic-bezier(.2, .7, .2, 1) both; }
.motion .m-enter > *:nth-child(2) { animation-delay: .04s; }
.motion .m-enter > *:nth-child(3) { animation-delay: .08s; }
.motion .m-enter > *:nth-child(4) { animation-delay: .12s; }
.motion .m-enter > *:nth-child(5) { animation-delay: .16s; }
.motion .m-enter > *:nth-child(n+6) { animation-delay: .2s; }
.motion .m-enter .bar i, .motion .m-enter .pbar i { transform-origin: left center; animation: mgrow .6s .15s cubic-bezier(.2, .7, .2, 1) both; }
.motion .m-tab { animation: mtab .2s cubic-bezier(.2, .7, .2, 1) both; }
.motion .m-changed { animation: mglow 1.7s ease-out; }
.motion .m-bump .n { animation: mbump .5s ease-out; }
.motion .card, .motion .kpi, .motion .projhit, .motion .chip, .motion .btn { transition: border-color .15s, background-color .15s, transform .15s, box-shadow .15s; }
.motion .card:hover { transform: translateY(-1px); box-shadow: 0 6px 18px rgba(0, 0, 0, .28); }
.motion .tabs button { transition: color .15s, border-color .2s; }
.motion .mbtn .mdot { background: var(--cyan); animation: mlive 2.2s ease-in-out infinite; }
/* Sheets on phones: at least 8 px to every edge, sitting low where the thumb is, scrolling inside when tall.
Above 700 px the sheet stays centred with 16 px to every edge (the .scrim and .sheet rules above). */
@media (max-width: 700px) {
.scrim { align-items: flex-end; padding: 8px 8px max(8px, env(safe-area-inset-bottom, 0px)); }
.sheet { margin: auto 0 0; width: 100%; max-height: calc(100vh - 16px); max-height: calc(100dvh - 16px); padding: 16px; }
.sheet.narrow { width: 100%; }
}
/* iPad landscape and narrow desktop windows. */
@media (max-width: 1024px) {
.board { grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); }
.whboard { grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); }
.kpis { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.tw { overflow-x: auto; -webkit-overflow-scrolling: touch; }
.joblist { min-width: 860px; }
.pmtable { min-width: 720px; }
.fltrow .fltq { flex-basis: 100%; }
}
/* iPad portrait: the board columns stack, each with its own heading and scroll frame. */
@media (max-width: 820px) {
.board, .whboard { grid-template-columns: minmax(0, 1fr); }
.col { max-height: min(var(--col-max, 520px), calc(100vh - var(--toph, 64px) - 40px)); }
}
/* Phones. */
@media (max-width: 700px) {
.kpis { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.col { max-height: none; }
.fltrow .f { flex: 1 1 calc(50% - 8px); min-width: 0; }
.fltrow .fltq, .fltrow .fltp { flex-basis: 100%; }
.fltbtns { flex: 1 1 100%; }
.fltbtns .seg { margin-left: auto; }
.fltrow2 .grow { display: none; }
.jlsort { min-width: 0; flex: 1 1 100%; }
.kpi .n { font-size: 34px; }
button.kpi::after { display: none; }
}