/* ==========================================================================
   LISTING DECK — "Midnight"
   ---------------------------------------------------------------------------
   Dark only. There is no light mode and no theme switch.

   Layout: a horizontal navigation bar across the top, then a canvas that owns
   its heading, its tools row and its own scrolling. The employee deck is a
   three-column board — Shelf / Yours / Held — and a listing physically moves
   between the columns as its state changes. Records and forms open as centred
   modals over the board.

   Colour is rationed. Almost everything is slate. Chroma is spent only on
   state: your own hold burns electric lime, free stock reads cool teal,
   someone else's hold is amber, anything urgent goes coral. If it glows, it
   is alive and it is about to change.
   ========================================================================== */

/* ==========================================================================
   1. Tokens
   ========================================================================== */
:root {
    --void: #07090e;
    --deep: #0c1119;

    --pane: rgba(255, 255, 255, 0.04);
    --pane-2: rgba(255, 255, 255, 0.06);
    --pane-lift: rgba(255, 255, 255, 0.085);
    --pane-sunk: rgba(0, 0, 0, 0.3);
    --edge: rgba(255, 255, 255, 0.09);
    --edge-soft: rgba(255, 255, 255, 0.055);
    --edge-strong: rgba(255, 255, 255, 0.17);
    --lit: rgba(255, 255, 255, 0.07);

    --fg: #e9eef7;
    --fg-2: #97a3b8;
    --fg-3: #5f6b80;

    --signal: #a6ff4d;
    --signal-2: #bcff7a;
    --signal-ink: #0a1400;
    --signal-wash: rgba(166, 255, 77, 0.11);
    --signal-edge: rgba(166, 255, 77, 0.34);
    --signal-glow: rgba(166, 255, 77, 0.42);

    --free: #35ded0;
    --free-wash: rgba(53, 222, 208, 0.11);
    --free-edge: rgba(53, 222, 208, 0.32);

    --busy: #ffb03b;
    --busy-wash: rgba(255, 176, 59, 0.11);
    --busy-edge: rgba(255, 176, 59, 0.32);

    --alert: #ff4d6e;
    --alert-wash: rgba(255, 77, 110, 0.11);
    --alert-edge: rgba(255, 77, 110, 0.34);

    --idle: #69748a;
    --idle-wash: rgba(105, 116, 138, 0.14);
    --idle-edge: rgba(105, 116, 138, 0.3);

    --info: #6aa8ff;
    --info-wash: rgba(106, 168, 255, 0.11);
    --info-edge: rgba(106, 168, 255, 0.32);

    /* Aliases so helpers and inline styles written against older names hold. */
    --stamp: var(--signal);
    --shelf: var(--free);
    --brass: var(--busy);
    --archive: var(--idle);
    --ballpoint: var(--info);
    --ink: var(--fg);
    --ink-2: var(--fg-2);
    --ink-3: var(--fg-3);
    --rule: var(--edge-soft);
    --rule-strong: var(--edge);

    --display: 'Bricolage Grotesque', 'Instrument Sans', system-ui, sans-serif;
    --sans: 'Instrument Sans', system-ui, -apple-system, sans-serif;
    --mono: 'Spline Sans Mono', ui-monospace, 'SF Mono', Consolas, monospace;

    --nav-h: 56px;
    --radius-xs: 5px;
    --radius: 9px;
    --radius-lg: 15px;
    --radius-pill: 999px;

    --row-py: 13px;
    --cell-py: 12px;

    --blur: blur(22px) saturate(150%);
    --cast-1: 0 1px 2px rgba(0, 0, 0, 0.5);
    --cast-2: 0 18px 40px -26px rgba(0, 0, 0, 0.95);
    --cast-3: 0 40px 90px -30px rgba(0, 0, 0, 1), 0 2px 10px rgba(0, 0, 0, 0.6);

    --noise: 0.032;
    --ease: cubic-bezier(0.22, 0.61, 0.36, 1);
}

[data-density='compact'] { --row-py: 8px; --cell-py: 7px; }

/* ==========================================================================
   2. Base
   ========================================================================== */
*, *::before, *::after { box-sizing: border-box; }
html, body { height: 100%; }

body {
    margin: 0;
    font-family: var(--sans);
    font-size: 14px;
    line-height: 1.55;
    letter-spacing: -0.005em;
    color: var(--fg);
    background-color: var(--void);
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    overflow: hidden;
}
body.scrolls { overflow: auto; }

body::before {
    content: '';
    position: fixed;
    inset: 0;
    z-index: -1;
    pointer-events: none;
    background:
        radial-gradient(900px 600px at 8% -6%, rgba(166, 255, 77, 0.07), transparent 62%),
        radial-gradient(1000px 700px at 94% 4%, rgba(53, 222, 208, 0.05), transparent 60%),
        radial-gradient(1200px 900px at 50% 112%, rgba(106, 168, 255, 0.045), transparent 65%);
}

.grain {
    position: fixed;
    inset: 0;
    z-index: 1;
    pointer-events: none;
    opacity: var(--noise);
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23n)'/%3E%3C/svg%3E");
}

h1, h2, h3, h4 { margin: 0; font-weight: 600; }
dl, dd { margin: 0; }
[hidden] { display: none !important; }

a { color: inherit; text-decoration-color: var(--edge-strong); text-underline-offset: 3px; }
a:hover { text-decoration-color: currentColor; }

::selection { background: var(--signal); color: var(--signal-ink); }

::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: var(--edge-strong); border: 3px solid transparent; background-clip: content-box; border-radius: var(--radius-pill); }
::-webkit-scrollbar-thumb:hover { background: var(--fg-3); background-clip: content-box; }

:focus-visible { outline: 2px solid var(--signal); outline-offset: 2px; border-radius: var(--radius-xs); }

.skip-link {
    position: fixed;
    top: 10px; left: 10px;
    z-index: 400;
    padding: 10px 16px;
    background: var(--signal);
    color: var(--signal-ink);
    border-radius: var(--radius);
    font-weight: 600;
    text-decoration: none;
    transform: translateY(-180%);
    transition: transform 0.2s var(--ease);
}
.skip-link:focus { transform: translateY(0); }

.mono { font-family: var(--mono); font-variant-numeric: tabular-nums; letter-spacing: -0.02em; }
.muted { color: var(--fg-3); }

.kicker, .col-head {
    font-size: 10px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.13em;
    color: var(--fg-3);
}
/* A field label names a column, so it is printed exactly as the column is. */
.field-label {
    font-family: var(--mono);
    font-size: 11px;
    font-weight: 400;
    letter-spacing: -0.02em;
    color: var(--fg-3);
}

.visually-hidden {
    position: absolute;
    width: 1px; height: 1px;
    padding: 0; margin: -1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
    border: 0;
}

.glass, .panel, .tile, .dialog, .palette, .topnav, .modal-panel, .lot, .board-col {
    background-image: linear-gradient(180deg, var(--pane-2), var(--pane));
    border: 1px solid var(--edge);
    -webkit-backdrop-filter: var(--blur);
    backdrop-filter: var(--blur);
    box-shadow: inset 0 1px 0 var(--lit), var(--cast-2);
}


/* ==========================================================================
   3. Buttons
   ========================================================================== */
.btn {
    --btn-bg: transparent;
    --btn-fg: var(--fg);
    --btn-edge: var(--edge-strong);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 7px;
    padding: 8px 15px;
    font-family: var(--sans);
    font-size: 13px;
    font-weight: 600;
    line-height: 1.3;
    white-space: nowrap;
    color: var(--btn-fg);
    background: var(--btn-bg);
    border: 1px solid var(--btn-edge);
    border-radius: var(--radius);
    cursor: pointer;
    text-decoration: none;
    transition: background 0.16s var(--ease), border-color 0.16s var(--ease),
                color 0.16s var(--ease), box-shadow 0.22s var(--ease), transform 0.1s var(--ease);
}
.btn:active { transform: translateY(1px); }
.btn[disabled], .btn[aria-disabled='true'] { opacity: 0.4; pointer-events: none; }
.btn svg { flex-shrink: 0; }

.btn-stamp, .btn-ink {
    --btn-bg: var(--signal);
    --btn-fg: var(--signal-ink);
    --btn-edge: transparent;
    box-shadow: 0 0 26px -6px var(--signal-glow), inset 0 1px 0 rgba(255, 255, 255, 0.35);
}
.btn-stamp:hover, .btn-ink:hover {
    --btn-bg: var(--signal-2);
    box-shadow: 0 0 34px -4px var(--signal-glow), inset 0 1px 0 rgba(255, 255, 255, 0.45);
}

.btn-quiet { --btn-bg: var(--pane-2); --btn-edge: var(--edge); }
.btn-quiet:hover { --btn-bg: var(--pane-lift); --btn-edge: var(--edge-strong); }

.btn-ghost { --btn-edge: transparent; --btn-fg: var(--fg-2); }
.btn-ghost:hover { --btn-bg: var(--pane-2); --btn-fg: var(--fg); }

.btn-danger { --btn-fg: var(--alert); --btn-edge: var(--alert-edge); }
.btn-danger:hover { --btn-bg: var(--alert-wash); --btn-edge: var(--alert); }

/* Filled, like the other actions in the top bar, and red because of what it
   does. An outlined button standing beside filled ones reads as disabled. */
.btn-danger-ink {
    --btn-bg: var(--alert);
    --btn-fg: #2b0009;
    --btn-edge: transparent;
    box-shadow: 0 0 26px -6px var(--alert), inset 0 1px 0 rgba(255, 255, 255, 0.3);
}
.btn-danger-ink:hover {
    --btn-bg: #ff6b86;
    box-shadow: 0 0 34px -4px var(--alert), inset 0 1px 0 rgba(255, 255, 255, 0.4);
}

.btn-sm { padding: 5px 10px; font-size: 12px; gap: 5px; border-radius: var(--radius-xs); }
.btn-lg { padding: 13px 24px; font-size: 14px; }
.btn-block { width: 100%; }
.btn-icon { padding: 8px; }
.btn-row { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }

kbd, .kbd {
    font-family: var(--mono);
    font-size: 10.5px;
    line-height: 1;
    padding: 4px 5px;
    min-width: 18px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: var(--fg-3);
    background: var(--pane-sunk);
    border: 1px solid var(--edge-soft);
    border-radius: 5px;
}

/* ==========================================================================
   4. State
   ========================================================================== */
.badge {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 3px 10px 3px 8px;
    border-radius: var(--radius-pill);
    font-size: 10.5px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    white-space: nowrap;
    color: var(--idle);
    background: var(--idle-wash);
    border: 1px solid var(--idle-edge);
}
.badge::before {
    content: '';
    width: 5px; height: 5px;
    border-radius: 50%;
    background: currentColor;
    box-shadow: 0 0 8px currentColor;
    flex-shrink: 0;
}
.badge-available { color: var(--free); background: var(--free-wash); border-color: var(--free-edge); }
.badge-held { color: var(--busy); background: var(--busy-wash); border-color: var(--busy-edge); }
.badge-mine { color: var(--signal); background: var(--signal-wash); border-color: var(--signal-edge); }
.badge-sold { color: var(--idle); background: var(--idle-wash); border-color: var(--idle-edge); }
.badge-info { color: var(--info); background: var(--info-wash); border-color: var(--info-edge); }
.badge-alert { color: var(--alert); background: var(--alert-wash); border-color: var(--alert-edge); }
.badge-paid { color: var(--info); background: var(--info-wash); border-color: var(--info-edge); }
.badge-live { color: var(--signal); background: var(--signal-wash); border-color: var(--signal-edge); }
.badge-mine::before, .badge-live::before { animation: breathe 2.4s ease-in-out infinite; }
@keyframes breathe { 0%, 100% { opacity: 1; } 50% { opacity: 0.25; } }

/* ==========================================================================
   5. Forms
   ========================================================================== */
.field { display: flex; flex-direction: column; gap: 7px; min-width: 0; }
.field-label { display: block; }
.field-hint { font-size: 11.5px; color: var(--fg-3); line-height: 1.5; }

.input, .textarea, .select {
    width: 100%;
    padding: 10px 12px;
    font-family: var(--sans);
    font-size: 13.5px;
    color: var(--fg);
    background: var(--pane-sunk);
    border: 1px solid var(--edge);
    border-radius: var(--radius);
    transition: border-color 0.16s var(--ease), box-shadow 0.16s var(--ease), background 0.16s var(--ease);
}
.input::placeholder, .textarea::placeholder { color: var(--fg-3); }
.input:focus, .textarea:focus, .select:focus {
    outline: none;
    background: var(--pane-2);
    border-color: var(--signal-edge);
    box-shadow: 0 0 0 3px var(--signal-wash);
}
.textarea { resize: vertical; line-height: 1.6; }
.input-mono { font-family: var(--mono); }
.select {
    appearance: none;
    padding-right: 32px;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' fill='none' stroke='%2397a3b8' stroke-width='1.6'%3E%3Cpath d='m1 1.5 5 5 5-5'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 12px center;
}

.field-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 14px; }
.field-grid .span-2 { grid-column: 1 / -1; }
.form-actions { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; margin-top: 18px; }

.search { position: relative; display: flex; align-items: center; min-width: 0; }
.search svg { position: absolute; left: 12px; color: var(--fg-3); pointer-events: none; }
.search .input { padding-left: 35px; padding-right: 32px; }
.search .kbd { position: absolute; right: 9px; pointer-events: none; transition: opacity 0.15s var(--ease); }
.search .input:focus + .kbd, .search .input:not(:placeholder-shown) + .kbd { opacity: 0; }
.search input[type='search']::-webkit-search-cancel-button { -webkit-appearance: none; }

.pw-field { position: relative; display: flex; }
.pw-field .input { padding-right: 42px; }
.pw-toggle {
    position: absolute;
    right: 5px; top: 50%;
    transform: translateY(-50%);
    background: none; border: none;
    padding: 7px; line-height: 0;
    color: var(--fg-3); cursor: pointer;
    border-radius: var(--radius-xs);
}
.pw-toggle:hover { color: var(--fg); }

/* ==========================================================================
   6. Notices
   ========================================================================== */
.notice {
    display: flex;
    align-items: flex-start;
    gap: 11px;
    padding: 13px 16px;
    margin-bottom: 18px;
    font-size: 13px;
    line-height: 1.55;
    color: var(--fg-2);
    background: var(--pane);
    border: 1px solid var(--edge);
    border-left: 2px solid var(--edge-strong);
    border-radius: var(--radius);
}
.notice strong { color: var(--fg); font-weight: 600; }
.notice svg { flex-shrink: 0; margin-top: 2px; }
.notice-error { border-left-color: var(--alert); background: var(--alert-wash); color: var(--fg); }
.notice-success { border-left-color: var(--signal); background: var(--signal-wash); color: var(--fg); }
.notice-info { border-left-color: var(--info); background: var(--info-wash); color: var(--fg); }



/* ==========================================================================
   7. Overlays
   ========================================================================== */
.overlay {
    position: fixed;
    inset: 0;
    z-index: 280;
    display: flex;
    padding: 20px;
    background: rgba(3, 5, 9, 0.74);
    -webkit-backdrop-filter: blur(6px);
    backdrop-filter: blur(6px);
    animation: fade 0.18s var(--ease) both;
}
.overlay-center { align-items: center; justify-content: center; }
.overlay-top { align-items: flex-start; justify-content: center; padding-top: min(13vh, 116px); }
@keyframes fade { from { opacity: 0; } to { opacity: 1; } }

.dialog {
    width: 100%;
    max-width: 430px;
    border-radius: var(--radius-lg);
    box-shadow: inset 0 1px 0 var(--lit), var(--cast-3);
    padding: 26px;
    animation: rise 0.24s var(--ease) both;
}
@keyframes rise {
    from { opacity: 0; transform: translateY(14px) scale(0.98); filter: blur(8px); }
    to { opacity: 1; transform: none; filter: none; }
}
.dialog h2 { font-family: var(--display); font-size: 22px; font-weight: 700; letter-spacing: -0.025em; margin-bottom: 9px; }
.dialog p { margin: 0; color: var(--fg-2); font-size: 13.5px; line-height: 1.6; }
.dialog .form-actions { justify-content: flex-end; }

.palette {
    width: 100%;
    max-width: 580px;
    border-radius: var(--radius-lg);
    box-shadow: inset 0 1px 0 var(--lit), var(--cast-3);
    overflow: hidden;
    display: flex;
    flex-direction: column;
    max-height: min(470px, 72vh);
    animation: rise 0.24s var(--ease) both;
}
.palette-search { display: flex; align-items: center; gap: 11px; padding: 15px 18px; border-bottom: 1px solid var(--edge-soft); flex-shrink: 0; }
.palette-search svg { color: var(--fg-3); flex-shrink: 0; }
.palette-search input { flex: 1; min-width: 0; border: none; background: none; padding: 0; font-family: var(--sans); font-size: 15px; color: var(--fg); }
.palette-search input:focus { outline: none; }
.palette-search input::placeholder { color: var(--fg-3); }
.palette-list { overflow-y: auto; padding: 7px; flex: 1; }
.palette-group { padding: 11px 11px 5px; font-size: 9.5px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.15em; color: var(--fg-3); }
.palette-item {
    display: flex;
    align-items: center;
    gap: 12px;
    width: 100%;
    padding: 10px 11px;
    border: none;
    background: none;
    border-radius: var(--radius-xs);
    font-family: var(--sans);
    font-size: 13.5px;
    color: var(--fg);
    text-align: left;
    cursor: pointer;
}
.palette-item[aria-selected='true'] { background: var(--signal-wash); box-shadow: inset 2px 0 0 var(--signal); }
.palette-item .pi-icon { color: var(--fg-3); flex-shrink: 0; line-height: 0; }
.palette-item[aria-selected='true'] .pi-icon { color: var(--signal); }
.palette-item .pi-label { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.palette-item .pi-meta { font-family: var(--mono); font-size: 11px; color: var(--fg-3); flex-shrink: 0; }
.palette-empty { padding: 30px 16px; text-align: center; color: var(--fg-3); font-size: 13px; }
.palette-foot { display: flex; gap: 15px; padding: 10px 16px; border-top: 1px solid var(--edge-soft); font-size: 11px; color: var(--fg-3); flex-shrink: 0; flex-wrap: wrap; }
.palette-foot span { display: inline-flex; align-items: center; gap: 5px; }

.shortcut-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 22px 30px; margin-top: 20px; }
.shortcut-grid h3 { font-size: 10px; text-transform: uppercase; letter-spacing: 0.13em; color: var(--fg-3); margin-bottom: 9px; }
.shortcut-row { display: flex; align-items: center; justify-content: space-between; gap: 14px; padding: 6px 0; font-size: 13px; border-bottom: 1px solid var(--edge-soft); }
.shortcut-row:last-child { border-bottom: none; }
.shortcut-row .keys { display: flex; gap: 4px; flex-shrink: 0; }

/* ==========================================================================
   8. Top navigation
   ========================================================================== */
.app { display: flex; flex-direction: column; height: 100vh; overflow: hidden; }

.topnav {
    position: relative;
    z-index: 150;
    height: var(--nav-h);
    flex-shrink: 0;
    display: flex;
    align-items: center;
    gap: 20px;
    padding: 0 18px;
    border-width: 0 0 1px 0;
    border-radius: 0;
}
/* A filament of signal drifting along the bottom edge: the app is connected. */
.topnav::after {
    content: '';
    position: absolute;
    left: 0; right: 0; bottom: -1px;
    height: 1px;
    background: linear-gradient(90deg, transparent, var(--signal), transparent);
    background-size: 38% 100%;
    background-repeat: no-repeat;
    opacity: 0.5;
    animation: wire 9s linear infinite;
}
@keyframes wire { from { background-position: -40% 0; } to { background-position: 140% 0; } }

.topnav-brand { display: flex; align-items: center; gap: 10px; text-decoration: none; flex-shrink: 0; }
.topnav-mark {
    width: 30px; height: 30px;
    display: grid;
    place-items: center;
    border-radius: 10px;
    color: var(--signal-ink);
    background: var(--signal);
    box-shadow: 0 0 22px -6px var(--signal-glow), inset 0 1px 0 rgba(255, 255, 255, 0.4);
    flex-shrink: 0;
}
.topnav-word { font-family: var(--display); font-size: 17px; font-weight: 700; letter-spacing: -0.04em; white-space: nowrap; }
.topnav-word em { font-style: normal; color: var(--signal); }

.topnav-tabs { display: flex; align-items: center; gap: 3px; flex: 0 1 auto; min-width: 0; overflow-x: auto; scrollbar-width: none; }
.topnav-tabs::-webkit-scrollbar { display: none; }
.topnav-fill { flex: 1; min-width: 0; }

/* The bar carries the page's own controls, so the canvas can start at content. */
.topnav-mid { display: flex; align-items: center; gap: 12px; flex: 1; min-width: 0; justify-content: flex-end; }
.topnav-search { flex: 1; max-width: 380px; min-width: 0; }
/* Hidden rather than removed: the tables and the board still bind their
   filtering to this input, so taking it out of the markup would mean unpicking
   that wiring on four pages. Delete this one line to bring it back. */
.topnav-search { display: none; }
.topnav-search .input { padding-top: 7px; padding-bottom: 7px; }
.topnav-actions { display: flex; align-items: center; gap: 8px; }
.topnav-actions .btn { padding: 7px 13px; }

.nav-live {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 5px 12px;
    white-space: nowrap;
    border: 1px solid var(--edge-soft);
    border-radius: var(--radius-pill);
    background: var(--pane-sunk);
}
.nav-live .sync { color: var(--fg-2); }
.nav-live .result-count { color: var(--fg-2); }
.nav-live-sep { color: var(--fg-3); }

.nav-tab {
    position: relative;
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 8px 13px;
    border-radius: var(--radius);
    font-size: 13px;
    font-weight: 500;
    color: var(--fg-3);
    text-decoration: none;
    white-space: nowrap;
    transition: color 0.16s var(--ease), background 0.16s var(--ease);
}
.nav-tab:hover { color: var(--fg); background: var(--pane-2); }
.nav-tab.active { color: var(--signal); background: var(--signal-wash); font-weight: 600; }
/* The active tab hangs a lit filament onto the bar's bottom edge. */
.nav-tab.active::after {
    content: '';
    position: absolute;
    left: 12px; right: 12px;
    bottom: -13px;
    height: 2px;
    border-radius: 2px 2px 0 0;
    background: var(--signal);
    box-shadow: 0 0 14px var(--signal-glow);
}
.nav-tab svg { opacity: 0.8; flex-shrink: 0; }
.nav-tab.active svg { opacity: 1; }
.nav-count {
    font-family: var(--mono);
    font-size: 10.5px;
    letter-spacing: -0.03em;
    padding: 1px 7px;
    color: var(--fg-3);
    background: var(--pane-sunk);
    border: 1px solid var(--edge-soft);
    border-radius: var(--radius-pill);
}
.nav-tab.active .nav-count { color: var(--signal); border-color: var(--signal-edge); background: transparent; }

.topnav-side { display: flex; align-items: center; gap: 8px; flex-shrink: 0; }

.topnav-clock {
    font-size: 12.5px;
    color: var(--fg-2);
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 5px 11px;
    border: 1px solid var(--edge-soft);
    border-radius: var(--radius-pill);
    background: var(--pane-sunk);
}
/* The date is context for the time, not a second reading of its own, so it
   sits back a shade and lets the running numerals lead. */
.topnav-date {
    font-size: 12px;
    color: var(--fg-3);
}

/* The city, not the time — small caps so the numerals stay the loud part. */
.topnav-zone {
    font-size: 10.5px;
    font-weight: 500;
    letter-spacing: 0.07em;
    text-transform: uppercase;
    color: var(--fg-3);
}

.topnav-clock::before {
    content: '';
    width: 5px; height: 5px;
    border-radius: 50%;
    background: var(--signal);
    box-shadow: 0 0 9px var(--signal);
    animation: breathe 2.4s ease-in-out infinite;
}

.cmdk {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 6px 8px 6px 11px;
    font-family: var(--sans);
    font-size: 12.5px;
    color: var(--fg-3);
    background: var(--pane-sunk);
    border: 1px solid var(--edge-soft);
    border-radius: var(--radius-pill);
    cursor: pointer;
    transition: color 0.16s var(--ease), border-color 0.16s var(--ease);
}
.cmdk:hover { color: var(--fg); border-color: var(--edge-strong); }
/* Hidden alongside the search field it stands in for on pages that have none.
   The palette still opens with the keyboard; this was only its visible door. */
.cmdk { display: none; }

/* The bell. Its dot carries the count rather than sitting blank, because
   "three things happened" and "something happened" are different news. */
.bell-wrap { position: relative; display: inline-flex; }
.bell { position: relative; }
/* A short swing when something arrives, so the bell reports it even if the
   toast has already gone or the reader looked away. */
.bell.is-ringing svg { animation: ring 0.6s var(--ease); transform-origin: 50% 3px; }
@keyframes ring {
    0%, 100% { transform: rotate(0); }
    12% { transform: rotate(13deg); }
    30% { transform: rotate(-11deg); }
    48% { transform: rotate(7deg); }
    66% { transform: rotate(-4deg); }
    84% { transform: rotate(2deg); }
}
.bell-dot {
    position: absolute;
    top: 1px; right: 1px;
    min-width: 15px;
    height: 15px;
    padding: 0 4px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-family: var(--mono);
    font-size: 9px;
    font-weight: 600;
    line-height: 1;
    color: var(--signal-ink);
    background: var(--signal);
    border-radius: var(--radius-pill);
    box-shadow: 0 0 10px -2px var(--signal-glow);
}

/* The panel hangs off the bell rather than landing in the middle of the
   screen. A notification is a glance, not an errand: it should appear where you
   clicked and leave the page behind it visible and usable. */
.notice-panel {
    position: absolute;
    top: calc(100% + 10px);
    right: 0;
    z-index: 200;
    width: min(400px, calc(100vw - 32px));
    max-height: min(64vh, 520px);
    display: flex;
    flex-direction: column;
    border-radius: var(--radius-lg);
    background: var(--deep);
    background-image: linear-gradient(180deg, var(--pane-2), transparent 120px);
    border: 1px solid var(--edge-strong);
    box-shadow: inset 0 1px 0 var(--lit), var(--cast-3);
    overflow: hidden;
    animation: drop 0.18s var(--ease) both;
}
@keyframes drop {
    from { opacity: 0; transform: translateY(-8px) scale(0.98); }
    to { opacity: 1; transform: none; }
}

.notice-head {
    flex-shrink: 0;
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 14px 16px;
    border-bottom: 1px solid var(--edge-soft);
}
.notice-head h2 {
    flex: 1;
    font-size: 10px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.14em;
    color: var(--fg-3);
}
/* The mute sits with the notifications rather than in a settings screen: the
   moment you want it off is the moment it just went off in your ear. */
.notice-sound {
    padding: 4px;
    line-height: 0;
    color: var(--fg-3);
    background: none;
    border: none;
    border-radius: var(--radius-xs);
    cursor: pointer;
    transition: color 0.14s var(--ease), background 0.14s var(--ease);
}
.notice-sound:hover { color: var(--fg); background: var(--pane-2); }
.notice-sound.is-off { color: var(--fg-3); opacity: 0.55; }

.notice-read-all {
    padding: 4px 9px;
    font-family: var(--sans);
    font-size: 11px;
    font-weight: 500;
    color: var(--fg-3);
    background: none;
    border: 1px solid var(--edge);
    border-radius: var(--radius-xs);
    cursor: pointer;
    white-space: nowrap;
    transition: color 0.14s var(--ease), border-color 0.14s var(--ease);
}
.notice-read-all:hover { color: var(--fg); border-color: var(--edge-strong); }

.notice-count {
    padding: 2px 8px;
    font-size: 10.5px;
    letter-spacing: -0.02em;
    color: var(--signal);
    background: var(--signal-wash);
    border: 1px solid var(--signal-edge);
    border-radius: var(--radius-pill);
}

/* The list fades out at the foot of the panel rather than stopping dead, so a
   half-visible row reads as "there is more" instead of as a cut-off mistake. */
.notice-panel::after {
    content: '';
    position: absolute;
    left: 1px; right: 1px; bottom: 1px;
    height: 34px;
    pointer-events: none;
    border-radius: 0 0 var(--radius-lg) var(--radius-lg);
    background: linear-gradient(180deg, transparent, var(--deep));
}

.notice-list { overflow-y: auto; padding: 4px 4px 14px; scrollbar-width: thin; }

/* A day's worth of news sits under its own heading. Notifications are read by
   "when", so the shape of the list should answer that before anything else. */
.notice-day {
    position: sticky;
    top: 0;
    z-index: 1;
    padding: 10px 12px 7px;
    font-size: 9.5px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.16em;
    color: var(--fg-3);
    background: linear-gradient(180deg, var(--deep) 68%, transparent);
}

/* The run is a timeline: one hairline down the left, each entry a station on
   it. That is what a feed of things-that-happened actually is, and it reads as
   a chronology instead of as a stack of cards. */
.notice-run {
    position: relative;
    margin: 0;
    padding: 0 0 2px;
    list-style: none;
}
.notice-run::before {
    content: '';
    position: absolute;
    left: 27px;
    top: 4px;
    bottom: 10px;
    width: 1px;
    background: var(--edge-soft);
}

.notice-item {
    position: relative;
    display: flex;
    align-items: baseline;
    gap: 12px;
    padding: 9px 12px 9px 0;
    margin-left: 12px;
    border-radius: var(--radius);
}
.notice-item:hover { background: var(--pane-2); }

/* The station itself. It sits on the line, so it needs the panel's own
   background behind it to punch a hole in the hairline. */
.notice-node {
    position: relative;
    flex: 0 0 30px;
    width: 30px;
    height: 30px;
    display: grid;
    place-items: center;
    align-self: flex-start;
    border-radius: 50%;
    color: var(--fg-3);
    background: var(--deep);
    border: 1px solid var(--edge);
}
/* The station carries the consequence. Everything unremarkable stays slate, so
   the coloured ones are the ones worth stopping on. */
.notice-item.is-money { --tone: var(--signal); --tone-edge: var(--signal-edge); --tone-wash: var(--signal-wash); }
.notice-item.is-gain { --tone: var(--free); --tone-edge: var(--free-edge); --tone-wash: var(--free-wash); }
.notice-item.is-loss { --tone: var(--alert); --tone-edge: var(--alert-edge); --tone-wash: var(--alert-wash); }

.notice-item.is-money .notice-node,
.notice-item.is-gain .notice-node,
.notice-item.is-loss .notice-node {
    color: var(--tone);
    border-color: var(--tone-edge);
    background: var(--tone-wash);
}
/* Unread rings the station rather than washing the whole row, so the list keeps
   one flat surface and the eye still finds what is new. */
.notice-item.is-unread .notice-node {
    border-color: var(--signal);
    box-shadow: 0 0 0 3px var(--signal-wash);
}

.notice-text {
    flex: 1;
    min-width: 0;
    padding-top: 5px;
    font-size: 13px;
    line-height: 1.5;
    color: var(--fg-2);
    overflow-wrap: anywhere;
}
/* The bank account is what the sentence is about, so it carries the weight. */
.notice-text strong { color: var(--fg); font-weight: 600; }
.notice-item.is-unread .notice-text { color: var(--fg); }

.notice-when {
    flex: 0 0 auto;
    padding-top: 6px;
    font-size: 10px;
    letter-spacing: -0.02em;
    color: var(--fg-3);
    white-space: nowrap;
}
.notice-item.is-unread .notice-when { color: var(--signal); }

/* Kept out of the way until the row is under the cursor: a column of crosses
   down the panel would read as the point of the list, which it is not. */
.notice-drop {
    flex: 0 0 auto;
    margin-top: 2px;
    padding: 4px;
    line-height: 0;
    color: var(--fg-3);
    background: none;
    border: none;
    border-radius: var(--radius-xs);
    cursor: pointer;
    opacity: 0;
    transition: opacity 0.14s var(--ease), color 0.14s var(--ease), background 0.14s var(--ease);
}
.notice-item:hover .notice-drop, .notice-drop:focus-visible { opacity: 1; }
.notice-drop:hover { color: var(--alert); background: var(--alert-wash); }

/* The page loads itself as you reach for it; the button is only there for
   anyone scrolling with a keyboard. */
.notice-more {
    display: block;
    width: 100%;
    margin-top: 6px;
    padding: 11px;
    font-family: var(--sans);
    font-size: 12px;
    color: var(--fg-3);
    background: none;
    border: none;
    border-top: 1px solid var(--edge-soft);
    cursor: pointer;
}
.notice-more:hover { color: var(--fg); background: var(--pane-2); }

.notice-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 12px;
    padding: 46px 20px;
    text-align: center;
    font-size: 13px;
    color: var(--fg-3);
}
.notice-empty svg { opacity: 0.35; }

/* ---------------------------------------------------------------- toasts */

/* Only notifications raise one. Your own actions are confirmed by the row
   changing under you; this is for things done elsewhere, by somebody else. */
.toast-stack {
    position: fixed;
    right: 20px;
    bottom: 20px;
    z-index: 320;
    display: flex;
    flex-direction: column-reverse;
    gap: 10px;
    width: min(350px, calc(100vw - 40px));
    pointer-events: none;
}
.toast {
    position: relative;
    display: flex;
    align-items: flex-start;
    gap: 12px;
    padding: 13px 15px 15px;
    font-size: 13px;
    line-height: 1.45;
    color: var(--fg-2);
    border-radius: var(--radius);
    background: var(--deep);
    background-image: linear-gradient(180deg, var(--pane-2), transparent);
    border: 1px solid var(--edge-strong);
    box-shadow: inset 0 1px 0 var(--lit), var(--cast-3);
    cursor: pointer;
    pointer-events: auto;
    overflow: hidden;
    animation: toast-in 0.3s var(--ease) both;
}
.toast:hover { border-color: var(--edge-strong); }
.toast.is-leaving { animation: toast-out 0.2s var(--ease) both; }
.toast-text { min-width: 0; padding-top: 6px; overflow-wrap: anywhere; }
.toast-text strong { color: var(--fg); font-weight: 600; }

.toast-node {
    flex: 0 0 30px;
    width: 30px;
    height: 30px;
    display: grid;
    place-items: center;
    border-radius: 50%;
    color: var(--fg-3);
    background: var(--pane-sunk);
    border: 1px solid var(--edge);
}
.toast.is-money { --tone: var(--signal); --tone-edge: var(--signal-edge); --tone-wash: var(--signal-wash); }
.toast.is-gain { --tone: var(--free); --tone-edge: var(--free-edge); --tone-wash: var(--free-wash); }
.toast.is-loss { --tone: var(--alert); --tone-edge: var(--alert-edge); --tone-wash: var(--alert-wash); }

.toast.is-money, .toast.is-gain, .toast.is-loss { border-color: var(--tone-edge); }
.toast.is-money .toast-node,
.toast.is-gain .toast-node,
.toast.is-loss .toast-node {
    color: var(--tone);
    border-color: var(--tone-edge);
    background: var(--tone-wash);
}

/* The toast shows its own lifetime running out, so nobody feels they have to
   dismiss it before it takes something away from them. */
.toast-drain {
    position: absolute;
    left: 0; right: 0; bottom: 0;
    height: 2px;
    background: var(--edge-soft);
}
.toast-drain i {
    display: block;
    height: 100%;
    width: 100%;
    background: var(--fg-3);
    transform-origin: left center;
    animation: drain 7s linear forwards;
}
.toast.is-money .toast-drain i,
.toast.is-gain .toast-drain i,
.toast.is-loss .toast-drain i { background: var(--tone); box-shadow: 0 0 10px -2px var(--tone); }
@keyframes drain { to { transform: scaleX(0); } }

@keyframes toast-in {
    from { opacity: 0; transform: translateX(24px) scale(0.96); }
    to { opacity: 1; transform: none; }
}
@keyframes toast-out { to { opacity: 0; transform: translateX(24px); } }

.topnav-me { display: flex; align-items: center; gap: 9px; padding-left: 6px; }
.topnav-me-text { display: flex; flex-direction: column; line-height: 1.2; min-width: 0; }
.topnav-me-name { font-size: 12.5px; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 130px; }
.topnav-me-role { font-size: 9px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.14em; color: var(--fg-3); }

.nav-toggle { display: none; }

.avatar {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 28px; height: 28px;
    border-radius: 9px;
    background: color-mix(in srgb, var(--avatar-color, var(--fg-3)) 18%, transparent);
    border: 1px solid color-mix(in srgb, var(--avatar-color, var(--fg-3)) 45%, transparent);
    color: var(--avatar-color, var(--fg-3));
    font-family: var(--sans);
    font-size: 10px;
    font-weight: 700;
    flex-shrink: 0;
}
.avatar-sm { width: 22px; height: 22px; font-size: 8.5px; border-radius: 7px; }
td .avatar-sm { margin-right: 8px; vertical-align: middle; }

/* ==========================================================================
   9. Canvas
   ========================================================================== */
.canvas { flex: 1; min-height: 0; display: flex; flex-direction: column; }

.canvas-head {
    flex-shrink: 0;
    display: flex;
    align-items: flex-end;
    justify-content: space-between;
    gap: 20px;
    flex-wrap: wrap;
    padding: 24px 30px 0;
}
.canvas-titles { min-width: 0; }
.canvas-kicker {
    display: block;
    margin-bottom: 7px;
    font-size: 10px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.18em;
    color: var(--fg-3);
}
.canvas-kicker em { font-style: normal; color: var(--signal); }
/* A wide gap between the largest and smallest type is what gives the screens
   their pace — the heading is meant to be conspicuously bigger than anything
   around it. */
.canvas-title { font-family: var(--display); font-size: clamp(34px, 4vw, 46px); font-weight: 800; letter-spacing: -0.052em; line-height: 0.98; }
.canvas-sub { color: var(--fg-2); font-size: 13.5px; margin: 12px 0 0; max-width: 70ch; line-height: 1.6; }
.canvas-actions { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }

.canvas-tools {
    flex-shrink: 0;
    display: flex;
    align-items: center;
    gap: 12px;
    flex-wrap: wrap;
    padding: 18px 30px 0;
}
.canvas-tools .search { flex: 1; max-width: 380px; min-width: 200px; }

.canvas-body { flex: 1; min-height: 0; overflow-y: auto; padding: 22px 30px 56px; }
/* The board owns its own scrolling: the columns scroll, the page does not. */
.canvas-board .canvas-body { overflow: hidden; padding: 18px 22px 22px; }

/* ==========================================================================
   10. Panels & tiles
   ========================================================================== */
.panel { border-radius: var(--radius-lg); margin-bottom: 20px; overflow: hidden; }
.panel-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 14px;
    flex-wrap: wrap;
    padding: 15px 20px;
    border-bottom: 1px solid var(--edge-soft);
}
.panel-head h2 { font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.13em; color: var(--fg-3); display: flex; align-items: center; gap: 10px; }
.panel-head-actions { display: flex; align-items: center; gap: 9px; flex-wrap: wrap; }
.panel-body { padding: 20px; }
.panel-body-flush { padding: 0; }

.tiles { display: grid; grid-template-columns: repeat(auto-fit, minmax(172px, 1fr)); gap: 14px; margin-bottom: 22px; }
.tile { position: relative; padding: 18px 20px; border-radius: var(--radius-lg); overflow: hidden; }
.tile::before {
    content: '';
    position: absolute;
    inset: -40% 40% 40% -40%;
    background: radial-gradient(circle, var(--tile-accent, transparent), transparent 68%);
    opacity: 0.16;
    pointer-events: none;
}
.tile-available { --tile-accent: var(--free); }
.tile-held { --tile-accent: var(--busy); }
.tile-mine { --tile-accent: var(--signal); }
.tile-sold { --tile-accent: var(--idle); }
.tile-info { --tile-accent: var(--info); }
.tile-alert { --tile-accent: var(--alert); }
.tile-value {
    position: relative;
    display: block;
    font-family: var(--mono);
    font-size: 33px;
    font-weight: 500;
    line-height: 1.02;
    font-variant-numeric: tabular-nums;
    letter-spacing: -0.05em;
    color: var(--tile-accent, var(--fg));
}
.tile-label { position: relative; display: block; margin-top: 7px; }
.tile-foot { position: relative; display: block; margin-top: 8px; font-size: 11.5px; color: var(--fg-3); }
.tile-delta { font-family: var(--mono); font-size: 11.5px; letter-spacing: -0.02em; }
.tile-delta.up { color: var(--signal); }
.tile-delta.down { color: var(--alert); }

/* ==========================================================================
   11. Dashboard: state columns, then a 12-track grid
   ========================================================================== */
.state-row { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 14px; margin-bottom: 20px; }

.state-card {
    position: relative;
    padding: 20px 22px;
    border-radius: var(--radius-lg);
    border: 1px solid var(--state-edge, var(--edge));
    background:
        radial-gradient(110% 180% at 0% 0%, var(--state-wash, transparent), transparent 58%),
        linear-gradient(180deg, var(--pane-2), var(--pane));
    -webkit-backdrop-filter: var(--blur);
    backdrop-filter: var(--blur);
    box-shadow: inset 0 1px 0 var(--lit), var(--cast-2);
    overflow: hidden;
}
.state-card::before {
    content: '';
    position: absolute;
    inset: 0 0 auto 0;
    height: 1px;
    background: linear-gradient(90deg, var(--state-color, var(--edge)), transparent 70%);
}
/* From an administrator's chair every hold belongs to somebody else, so held
   reads amber here — lime stays reserved for "yours" and for primary actions. */
.state-free { --state-color: var(--free); --state-wash: var(--free-wash); --state-edge: var(--free-edge); }
.state-busy { --state-color: var(--busy); --state-wash: var(--busy-wash); --state-edge: var(--busy-edge); }
.state-closed { --state-color: var(--idle); --state-wash: var(--idle-wash); --state-edge: var(--idle-edge); }

.state-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.state-name { font-size: 10.5px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.14em; color: var(--fg-3); }
.state-value {
    display: block;
    margin-top: 8px;
    font-family: var(--mono);
    font-size: 46px;
    font-weight: 500;
    line-height: 1;
    letter-spacing: -0.06em;
    font-variant-numeric: tabular-nums;
    color: var(--state-color, var(--fg));
    text-shadow: 0 0 44px var(--state-wash);
}
.state-share { height: 5px; margin-top: 14px; border-radius: var(--radius-pill); background: var(--pane-sunk); overflow: hidden; }
.state-share i { display: block; height: 100%; background: var(--state-color); box-shadow: 0 0 12px -1px var(--state-color); border-radius: var(--radius-pill); transition: width 0.5s var(--ease); }
.state-foot { display: block; margin-top: 10px; font-size: 11.5px; color: var(--fg-3); }

/* A 12-track grid so panels can take deliberately unequal widths. */
.grid12 { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); gap: 16px; align-items: start; }
.grid12 > .panel { margin-bottom: 0; }
.col-8 { grid-column: span 8; }
.col-6 { grid-column: span 6; }
.col-4 { grid-column: span 4; }
.col-12 { grid-column: span 12; }

/* ==========================================================================
   12. Tables
   ========================================================================== */
.table-wrap { overflow-x: auto; }
/* One column per database field means a wider natural table; the wrapper
   scrolls rather than letting the columns crush. */
.table { width: 100%; min-width: 940px; border-collapse: collapse; }
.table th, .table td { text-align: left; padding: var(--cell-py) 16px; border-bottom: 1px solid var(--edge-soft); vertical-align: middle; }
/* Headings are the literal database column names, so they are set as
   identifiers: mono, lower case, no letterspaced small-caps treatment. */
.table th {
    font-family: var(--mono);
    font-size: 11px;
    font-weight: 400;
    letter-spacing: -0.02em;
    color: var(--fg-3);
    border-bottom: 1px solid var(--edge);
    white-space: nowrap;
}
.table td { font-size: 13.5px; }
.table tbody tr:last-child td { border-bottom: none; }
.table tbody tr { transition: background 0.12s var(--ease); }
.table tbody tr:hover { background: var(--pane-2); }

/* A status edge on the leading side, so a table scans the same way the board
   does — colour first, label second. */
.table tbody tr[data-sort-status], .table tbody tr[data-sort-outcome], #reservations-body tr {
    box-shadow: inset 2px 0 0 var(--row-edge, transparent);
}
.table tbody tr[data-sort-status='available'] { --row-edge: color-mix(in srgb, var(--free) 60%, transparent); }
.table tbody tr[data-sort-status='reserved'] { --row-edge: color-mix(in srgb, var(--busy) 60%, transparent); }
.table tbody tr[data-sort-status='sold'] { --row-edge: color-mix(in srgb, var(--idle) 60%, transparent); }
.table tbody tr[data-sort-outcome='active'] { --row-edge: color-mix(in srgb, var(--busy) 60%, transparent); }
.table tbody tr[data-sort-outcome='expired'] { --row-edge: color-mix(in srgb, var(--alert) 60%, transparent); }
.table tbody tr[data-sort-outcome='cancelled'] { --row-edge: color-mix(in srgb, var(--idle) 55%, transparent); }
.table tbody tr[data-sort-outcome='completed'] { --row-edge: color-mix(in srgb, var(--free) 60%, transparent); }
#reservations-body tr { --row-edge: color-mix(in srgb, var(--busy) 60%, transparent); }

.table tbody tr.is-editing { background: var(--signal-wash); box-shadow: inset 2px 0 0 var(--signal); }
.table td.num, .table th.num { text-align: right; font-family: var(--mono); font-variant-numeric: tabular-nums; }
.table .cell-strong { font-weight: 600; }
.table .cell-quiet { color: var(--fg-3); }
.table td.mono, .table .countdown { white-space: nowrap; }
.table .cell-title .cell-strong { overflow-wrap: anywhere; }
.table-actions { display: flex; gap: 4px; justify-content: flex-end; }

/* An action reduced to its icon. Square, so a row of them reads as a set of
   equal choices rather than a ragged line of words, and generous enough to hit
   without aiming. The label lives in aria-label and title, never nowhere. */
.btn-glyph {
    width: 38px;
    height: 38px;
    padding: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
}
.btn-glyph svg { display: block; }

/* The key under a table. Quiet by design: it is there for the first read and
   then wants to be ignored, so it sits at the foot in small type. */
.legend {
    display: flex;
    flex-wrap: wrap;
    gap: 6px 20px;
    margin: 0;
    padding: 14px 16px 2px;
    list-style: none;
    border-top: 1px solid var(--edge-soft);
}
.legend li {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    font-size: 11.5px;
    color: var(--fg-3);
}
.legend-mark {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 24px;
    height: 24px;
    border: 1px solid var(--edge-soft);
    border-radius: var(--radius-sm);
    background: var(--pane-sunk);
    color: var(--fg-2);
}
.table-actions form { display: contents; }

th[data-sort] { cursor: pointer; user-select: none; }
th[data-sort]:hover { color: var(--fg); }
th[data-sort] .sort-arrow { opacity: 0.25; margin-left: 5px; font-size: 8px; }
th[data-sort].sorted-asc, th[data-sort].sorted-desc { color: var(--signal); }
th[data-sort].sorted-asc .sort-arrow, th[data-sort].sorted-desc .sort-arrow { opacity: 1; }

.table-toolbar { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; padding: 13px 20px; border-bottom: 1px solid var(--edge-soft); }
.result-count { font-family: var(--mono); font-size: 11.5px; letter-spacing: -0.02em; color: var(--fg-3); white-space: nowrap; }

.col-check { width: 38px; padding-right: 0 !important; }
.table input[type='checkbox'] { width: 15px; height: 15px; accent-color: var(--signal); cursor: pointer; vertical-align: middle; }

.bulk-bar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 14px;
    flex-wrap: wrap;
    padding: 11px 20px;
    background: var(--signal-wash);
    border-bottom: 1px solid var(--signal-edge);
}
.bulk-count { font-family: var(--mono); font-size: 12px; color: var(--signal); letter-spacing: -0.02em; }

.copyable {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    background: none;
    border: none;
    padding: 2px 6px;
    margin: -2px -6px;
    border-radius: var(--radius-xs);
    font: inherit;
    color: inherit;
    cursor: pointer;
    max-width: 100%;
    text-align: left;
}
.copyable:hover { background: var(--pane-lift); }
.copyable > span { overflow-wrap: anywhere; }
/* A value is the record itself, so it is shown whole: table cells and the
   record modal let it wrap rather than trailing off into an ellipsis. */
.table .copyable > span { overflow: visible; text-overflow: clip; }
.table td:not(.mono) .copyable > span { white-space: normal; overflow-wrap: anywhere; }
.modal-field .copyable, .modal-field .copyable > span { max-width: 100%; white-space: normal; overflow: visible; text-overflow: clip; overflow-wrap: anywhere; }
.copyable .copy-icon { opacity: 0; color: var(--fg-3); flex-shrink: 0; line-height: 0; transition: opacity 0.14s var(--ease); }
.copyable:hover .copy-icon, .copyable:focus-visible .copy-icon { opacity: 1; }
.copyable.copied { color: var(--signal); }
.copyable.copied .copy-icon { opacity: 1; color: var(--signal); }

/* ==========================================================================
   13. Empty & loading
   ========================================================================== */
.empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 13px;
    padding: 52px 26px;
    text-align: center;
    color: var(--fg-2);
}
.empty-mark { color: var(--fg-3); line-height: 0; opacity: 0.5; }
.empty h3 { font-family: var(--display); font-size: 19px; font-weight: 700; letter-spacing: -0.03em; color: var(--fg); }
.empty p { margin: 0; font-size: 13px; line-height: 1.6; max-width: 40ch; }
.empty-sm { padding: 30px 18px; }

.sk {
    height: 10px;
    border-radius: 4px;
    background: linear-gradient(100deg, var(--pane-sunk) 38%, var(--pane-lift) 50%, var(--pane-sunk) 62%);
    background-size: 220% 100%;
    animation: sweep 1.5s ease-in-out infinite;
}
.sk-60 { width: 60%; }
.sk-40 { width: 40%; }
.sk-85 { width: 85%; }
@keyframes sweep { from { background-position: 130% 0; } to { background-position: -30% 0; } }
.lot.is-skeleton { pointer-events: none; display: flex; flex-direction: column; gap: 11px; }

/* ==========================================================================
   14. The board
   ========================================================================== */
.board { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 16px; height: 100%; min-height: 0; }

.board-col {
    display: flex;
    flex-direction: column;
    min-height: 0;
    border-radius: var(--radius-lg);
    border-top: 2px solid var(--col-color, var(--edge));
    overflow: hidden;
}
.board-shelf { --col-color: var(--free); }
.board-mine { --col-color: var(--signal); }
.board-paid { --col-color: var(--info); }

.board-col-head {
    flex-shrink: 0;
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 8px 12px;
    padding: 14px 16px;
    border-bottom: 1px solid var(--edge-soft);
    background: linear-gradient(180deg, var(--col-wash, transparent), transparent);
}
.board-shelf .board-col-head { --col-wash: var(--free-wash); }
.board-mine .board-col-head { --col-wash: var(--signal-wash); }
.board-paid .board-col-head { --col-wash: var(--info-wash); }

.board-col-name {
    display: flex;
    align-items: center;
    gap: 9px;
    font-size: 11px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.13em;
    color: var(--col-color);
}
.board-col-name::before {
    content: '';
    width: 6px; height: 6px;
    border-radius: 50%;
    background: currentColor;
    box-shadow: 0 0 10px currentColor;
}
/* Six choices in a column header, so they are pared to the numbers alone and
   sized to sit between the column's name and its count without crowding
   either. The header wraps rather than squeezing them when space runs out. */
.band-filter { display: flex; align-items: center; gap: 4px; flex-wrap: wrap; min-width: 0; }
.band-chip {
    padding: 5px 11px;
    font-family: var(--mono);
    font-size: 12px;
    font-weight: 500;
    letter-spacing: -0.03em;
    line-height: 1.4;
    color: var(--fg-2);
    background: var(--pane-sunk);
    border: 1px solid var(--edge);
    border-radius: var(--radius-pill);
    cursor: pointer;
    white-space: nowrap;
    transition: color 0.14s var(--ease), background 0.14s var(--ease),
                border-color 0.14s var(--ease), box-shadow 0.18s var(--ease);
}
.band-chip:hover { color: var(--fg); background: var(--pane-lift); border-color: var(--edge-strong); }
/* The chosen slice reads as loudly as the column it is filtering, or you lose
   track of why the shelf looks half empty. */
.band-chip.is-on {
    color: var(--free);
    background: var(--free-wash);
    border-color: var(--free);
    box-shadow: 0 0 16px -4px var(--free);
}

.board-col-meta { display: flex; align-items: center; gap: 9px; min-width: 0; }
.board-col-note {
    font-size: 11px;
    letter-spacing: -0.02em;
    color: var(--fg-3);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.board-col-note.is-low { color: var(--alert); }
.board-col-count {
    font-family: var(--mono);
    font-size: 12px;
    letter-spacing: -0.03em;
    color: var(--fg-3);
    padding: 2px 9px;
    background: var(--pane-sunk);
    border: 1px solid var(--edge-soft);
    border-radius: var(--radius-pill);
    flex-shrink: 0;
}

.board-col-body {
    flex: 1;
    min-height: 0;
    overflow-y: auto;
    overscroll-behavior: contain;
    padding: 12px;
    display: flex;
    flex-direction: column;
    gap: 10px;
    scrollbar-width: thin;
}
.board-col-body::-webkit-scrollbar { width: 8px; }
.board-col-body::-webkit-scrollbar-thumb { border-width: 2px; }
/* Anything short of a full column should not stretch its last card. */
.board-col-body > * { flex-shrink: 0; }

/* -- A card on the board -------------------------------------------------- */
.lot {
    position: relative;
    display: flex;
    flex-direction: column;
    padding: 14px 15px 12px;
    border-radius: var(--radius);
    text-align: left;
    cursor: pointer;
    overflow: hidden;
    flex-shrink: 0;
    transition: border-color 0.16s var(--ease), transform 0.16s var(--ease), box-shadow 0.16s var(--ease);
    animation: lot-in 0.3s var(--ease) both;
}
.lot:hover { border-color: var(--edge-strong); transform: translateY(-2px); box-shadow: inset 0 1px 0 var(--lit), var(--cast-3); }
.lot:focus-visible { outline: none; border-color: var(--signal); box-shadow: 0 0 0 3px var(--signal-wash), inset 0 1px 0 var(--lit); }
.lot.is-mine { border-color: var(--signal-edge); }
.lot.is-paid { border-color: var(--info-edge); }
/* Closed by you, but an administrator has since put it back into circulation:
   it stays on your record and shows on the shelf at the same time. */
.lot.is-paid.is-reopened { border-style: dashed; opacity: 0.85; }
.lot.is-sold { opacity: 0.55; }
.lot.is-active { border-color: var(--signal-edge); box-shadow: inset 0 1px 0 var(--lit), 0 0 0 1px var(--signal-edge); }
@keyframes lot-in { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }

/* A card that just changed column announces itself where it landed: the whole
   board is built on that movement, so the arrival has to be legible. */
.lot.did-move {
    animation: lot-land 0.8s var(--ease) both;
    z-index: 2;
}
.board-shelf .lot.did-move { --land: var(--free); --land-glow: rgba(53, 222, 208, 0.4); }
.board-mine .lot.did-move { --land: var(--signal); --land-glow: var(--signal-glow); }
.board-paid .lot.did-move { --land: var(--info); --land-glow: rgba(106, 168, 255, 0.4); }
@keyframes lot-land {
    0% { opacity: 0; transform: translateY(-10px) scale(0.96); border-color: var(--land); box-shadow: 0 0 0 4px var(--land-glow); }
    35% { opacity: 1; transform: none; border-color: var(--land); box-shadow: 0 0 0 3px var(--land-glow); }
    100% { transform: none; box-shadow: inset 0 1px 0 var(--lit), var(--cast-2); }
}

.lot-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 9px; margin-bottom: 11px; }
.lot-name { font-size: 16px; font-weight: 600; line-height: 1.25; letter-spacing: -0.025em; }
.lot-ref { font-family: var(--mono); font-size: 10.5px; letter-spacing: -0.02em; color: var(--fg-3); }

/* A timed card leads with the clock, not the name: on this board the question
   is always "how long have I got", and the name is how you confirm which one. */
.lot-clockline { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.lot-foot-timed { border-top: 1px solid var(--edge-soft); }

/* The shelf identifies a listing by its brand and its two names, nothing more.
   Everything else unlocks when the listing is claimed. */
.lot-brand { display: flex; align-items: center; gap: 15px; margin: 4px 0 13px; }
/* The mark carries the identity on a card that shows almost nothing else, so
   it is sized to be recognised at a glance rather than to sit politely. */
.lot-logo {
    flex: 0 0 58px;
    width: 58px;
    height: 58px;
    padding: 5px;
    margin-top: 4px;
    border-radius: 15px;
    object-fit: contain;
    background: white;
    border: 1px solid var(--edge-soft);
}
.lot-logo-fallback { display: grid; place-items: center; padding: 0; }
.lot-logo-fallback .avatar { width: 36px; height: 36px; font-size: 13px; border: none; background: transparent; }
.lot-names { min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.lot-name1 { font-size: 15.5px; font-weight: 600; letter-spacing: -0.02em; line-height: 1.25; overflow-wrap: anywhere; }
.lot-name2 { font-size: 13px; color: var(--fg-2); line-height: 1.3; overflow-wrap: anywhere; }
.lot-name2.is-empty { color: var(--fg-3); }
.lot-shelf .lot-head { margin-bottom: 0; }

/* The same figure inside a table cell, where it has to sit level with plain
   text in neighbouring columns rather than float like a badge. */
/* Which kind of table you are looking at — running work or a log — is the
   first decision on the screen, so it reads as a row of choices rather than a
   dropdown you have to open to find out where you are. */
.segmented {
    display: inline-flex;
    padding: 3px;
    gap: 2px;
    border: 1px solid var(--edge-soft);
    border-radius: var(--radius-pill);
    background: var(--pane-sunk);
}
.segment {
    padding: 5px 13px;
    border-radius: var(--radius-pill);
    font-size: 12.5px;
    font-weight: 500;
    color: var(--fg-2);
    text-decoration: none;
    white-space: nowrap;
    transition: color 0.16s var(--ease), background 0.16s var(--ease);
}
.segment:hover { color: var(--fg-1); }
.segment.is-on {
    background: var(--signal-wash);
    border: 1px solid var(--signal-edge);
    padding: 4px 12px;
    color: var(--signal);
}

/* The proof viewer. A picture wants room, so this dialog is wider than the
   ones that only ask a question, and the image is free to scroll inside it
   rather than forcing the page to. */
.dialog-wide { max-width: 720px; }

.proof-view {
    margin-top: 18px;
    max-height: 62vh;
    overflow: auto;
    border: 1px solid var(--edge-soft);
    border-radius: var(--radius-md);
    background: var(--pane-sunk);
    display: flex;
    align-items: center;
    justify-content: center;
}
.proof-view img {
    display: block;
    max-width: 100%;
    height: auto;
}
.proof-view iframe {
    width: 100%;
    height: 62vh;
    border: 0;
    display: block;
}

.pill-band {
    display: inline-block;
    padding: 2px 8px;
    border: 1px solid var(--signal-edge);
    border-radius: 999px;
    background: var(--signal-wash);
    color: var(--signal);
    font-size: 11.5px;
    letter-spacing: -0.02em;
    white-space: nowrap;
}

/* The money bracket sits opposite the status badge: a figure, so it reads in
   the numeral face and holds its own weight without shouting over the name. */
.lot-band {
    flex: 0 0 auto;
    padding: 3px 9px;
    border: 1px solid var(--signal-edge);
    border-radius: 999px;
    background: var(--signal-wash);
    color: var(--signal);
    font-family: var(--mono);
    font-size: 11.5px;
    font-weight: 500;
    letter-spacing: -0.02em;
    white-space: nowrap;
}

.lot-locked {
    display: flex;
    align-items: center;
    gap: 8px;
    margin: 0 0 11px;
    padding: 9px 11px;
    font-size: 12px;
    color: var(--fg-3);
    background: var(--pane-sunk);
    border: 1px dashed var(--edge);
    border-radius: var(--radius);
}
.lot-locked svg { flex-shrink: 0; }
/* Not withheld, just folded away — the card invites the click rather than
   refusing it. */
.lot-open { border-style: solid; border-color: var(--signal-edge); color: var(--signal); background: var(--signal-wash); }
.lot:hover .lot-open { border-color: var(--signal); }

.modal-locked {
    display: flex;
    align-items: flex-start;
    gap: 11px;
    margin-top: 10px;
    padding: 15px 16px;
    background: var(--pane-sunk);
    border: 1px dashed var(--edge);
    border-radius: var(--radius);
}
.modal-locked svg { flex-shrink: 0; margin-top: 2px; color: var(--fg-3); }
.modal-locked b { font-size: 13px; }
.modal-locked p { margin: 3px 0 0; font-size: 12.5px; color: var(--fg-2); line-height: 1.55; }

/* The contact columns, one row each, values never clipped. */
.lot-fields { display: flex; flex-direction: column; gap: 4px; margin: 11px 0; }
.lot-field { display: flex; align-items: baseline; gap: 10px; font-size: 12.5px; }
.lot-field dt {
    flex: 0 0 60px;
    font-size: 10.5px;
    letter-spacing: -0.02em;
    color: var(--fg-3);
}
.lot-field dd {
    flex: 1;
    min-width: 0;
    color: var(--fg);
    overflow-wrap: anywhere;
    line-height: 1.45;
}
.lot-field dd.is-empty { color: var(--fg-3); }

.lot-foot { display: flex; align-items: center; justify-content: space-between; gap: 9px; margin-top: auto; padding-top: 10px; border-top: 1px solid var(--edge-soft); }
.lot-foot .btn { flex-shrink: 0; }
/* The timed columns share one anatomy: clock, progress line, then the record. */
.lot-timed { display: block; }
.lot-timed .lot-foot { border-top: 1px solid var(--edge-soft); }

.lot-clock {
    font-family: var(--mono);
    font-size: 34px;
    font-weight: 500;
    line-height: 1;
    letter-spacing: -0.06em;
    font-variant-numeric: tabular-nums;
    color: var(--busy);
}
.lot-clock.is-mine { color: var(--signal); text-shadow: 0 0 26px var(--signal-glow); }
.lot-clock.is-low { color: var(--alert); text-shadow: 0 0 26px rgba(255, 77, 110, 0.5); animation: breathe 1.8s ease-in-out infinite; }
.lot-bar { display: block; height: 3px; margin: 11px 0 0; border-radius: var(--radius-pill); background: var(--pane-sunk); overflow: hidden; }
.lot-bar i { display: block; height: 100%; background: var(--busy); box-shadow: 0 0 10px -1px var(--busy); border-radius: var(--radius-pill); transition: width 1s linear; }
.lot.is-mine .lot-bar i { background: var(--signal); box-shadow: 0 0 10px -1px var(--signal); }
.lot.is-low .lot-bar i { background: var(--alert); box-shadow: 0 0 10px -1px var(--alert); }
.lot-due { font-size: 11.5px; color: var(--fg-3); }
.lot-due b { font-family: var(--mono); font-weight: 500; color: var(--fg-2); letter-spacing: -0.02em; }
.lot-actions { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 10px; }
.lot-actions .btn { flex: 1; min-width: 72px; }

/* Empty columns get the same weight as a card, so the board keeps its rhythm. */
.col-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 9px;
    padding: 30px 18px;
    text-align: center;
    border: 1px dashed var(--edge);
    border-radius: var(--radius);
    color: var(--fg-3);
}
.col-empty .empty-mark { opacity: 0.4; }
.col-empty h3 { font-family: var(--display); font-size: 15px; font-weight: 700; letter-spacing: -0.025em; color: var(--fg-2); }
.col-empty p { margin: 0; font-size: 12.5px; line-height: 1.55; max-width: 30ch; }

.sync { display: inline-flex; align-items: center; gap: 7px; font-family: var(--mono); font-size: 11px; letter-spacing: -0.02em; color: var(--fg-3); white-space: nowrap; }
.sync::before { content: ''; width: 5px; height: 5px; border-radius: 50%; background: var(--signal); box-shadow: 0 0 9px var(--signal); flex-shrink: 0; }
.sync.is-stale::before { background: var(--busy); box-shadow: 0 0 9px var(--busy); }
.sync.is-offline::before { background: var(--alert); box-shadow: 0 0 9px var(--alert); }

/* ==========================================================================
   15. Modals (records and forms both open here)
   ========================================================================== */
.modal {
    position: fixed;
    inset: 0;
    z-index: 260;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 24px;
}
.modal-scrim {
    position: absolute;
    inset: 0;
    background: rgba(3, 5, 9, 0.74);
    -webkit-backdrop-filter: blur(6px);
    backdrop-filter: blur(6px);
    animation: fade 0.2s var(--ease) both;
    border: none;
    padding: 0;
    cursor: default;
}
.modal-panel {
    position: relative;
    width: 100%;
    max-width: 620px;
    max-height: min(88vh, 860px);
    display: flex;
    flex-direction: column;
    border-radius: var(--radius-lg);
    box-shadow: inset 0 1px 0 var(--lit), var(--cast-3);
    animation: rise 0.24s var(--ease) both;
    overflow: hidden;
}
.modal-wide { max-width: 780px; }

.modal-head {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 14px;
    padding: 20px 24px 16px;
    border-bottom: 1px solid var(--edge-soft);
    flex-shrink: 0;
}
.modal-title { font-family: var(--display); font-size: 24px; font-weight: 700; letter-spacing: -0.04em; line-height: 1.1; }
.modal-sub { margin-top: 8px; display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.modal-sub .mono { font-size: 11.5px; color: var(--fg-3); }
.modal-body { flex: 1; min-height: 0; overflow-y: auto; padding: 22px 24px 26px; }
.modal-foot { flex-shrink: 0; padding: 16px 24px; border-top: 1px solid var(--edge-soft); display: flex; gap: 10px; flex-wrap: wrap; }
.modal-foot .btn { flex: 1; min-width: 130px; }

.modal-fields { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: 10px; }
.modal-field { padding: 13px 15px; background: var(--pane-sunk); border: 1px solid var(--edge-soft); border-radius: var(--radius); }
.modal-field-value { display: block; margin-top: 5px; font-size: 14px; }
.modal-field-value.is-empty { color: var(--fg-3); font-size: 13px; }

/* The hold read-out inside a record modal. */
.hold {
    position: relative;
    display: flex;
    align-items: center;
    gap: 20px;
    flex-wrap: wrap;
    padding: 20px;
    margin-bottom: 20px;
    border: 1px solid var(--busy-edge);
    border-radius: var(--radius-lg);
    background: radial-gradient(120% 160% at 0% 0%, var(--busy-wash), transparent 62%), var(--pane);
    overflow: hidden;
}
.hold::before { content: ''; position: absolute; inset: 0 0 auto 0; height: 1px; background: linear-gradient(90deg, var(--busy), transparent 70%); }
.hold-mine { border-color: var(--signal-edge); background: radial-gradient(120% 160% at 0% 0%, var(--signal-wash), transparent 62%), var(--pane); }
.hold-mine::before { background: linear-gradient(90deg, var(--signal), transparent 70%); }

.ring { position: relative; width: 96px; height: 96px; flex-shrink: 0; }
.ring svg { transform: rotate(-90deg); display: block; width: 100%; height: 100%; overflow: visible; }
.ring-track { stroke: var(--edge); }
.ring-fill { stroke: var(--busy); stroke-linecap: round; filter: drop-shadow(0 0 7px currentColor); transition: stroke-dashoffset 0.9s linear, stroke 0.3s var(--ease); }
.hold-mine .ring-fill { stroke: var(--signal); }
.ring-fill.is-low { stroke: var(--alert); }
.ring-pct { position: absolute; inset: 0; display: grid; place-items: center; font-family: var(--mono); font-size: 12.5px; font-variant-numeric: tabular-nums; letter-spacing: -0.02em; color: var(--fg-3); }

.hold-readout { min-width: 0; flex: 1; }
.hold-clock {
    display: block;
    margin-top: 4px;
    font-family: var(--mono);
    font-size: 38px;
    font-weight: 500;
    line-height: 1;
    letter-spacing: -0.06em;
    font-variant-numeric: tabular-nums;
    color: var(--fg);
}
.hold-mine .hold-clock { color: var(--signal); text-shadow: 0 0 40px var(--signal-glow); }
.hold-clock.is-low { color: var(--alert); text-shadow: 0 0 40px rgba(255, 77, 110, 0.5); }
.hold-note { margin-top: 9px; font-size: 12.5px; color: var(--fg-2); }
.hold-note b { font-family: var(--mono); font-weight: 500; color: var(--fg); letter-spacing: -0.02em; }
.hold-strike { animation: rise 0.34s var(--ease) both; }

/* ==========================================================================
   16. Charts
   ========================================================================== */
/* The dashed rule marks the tallest day, so a bar's height is readable as a
   number instead of just a shape. */
.chart { position: relative; }
.chart::before {
    content: '';
    position: absolute;
    left: 0; right: 0; top: 8px;
    border-top: 1px dashed var(--edge);
    pointer-events: none;
}
.chart-bars { display: flex; align-items: flex-end; gap: 6px; height: 150px; padding-top: 8px; }
.bar-col { flex: 1; display: flex; flex-direction: column; justify-content: flex-end; gap: 3px; min-width: 0; height: 100%; }
.bar-col .bar { background: var(--info); min-height: 2px; border-radius: 3px; animation: grow 0.55s var(--ease) both; transform-origin: bottom; transition: filter 0.16s var(--ease); }
.bar-col .bar-cancelled { background: var(--idle); }
.bar-col:hover .bar { filter: brightness(1.35); }
@keyframes grow { from { transform: scaleY(0); } to { transform: scaleY(1); } }

.chart-axis { display: flex; gap: 6px; margin-top: 9px; }
.chart-axis span { flex: 1; min-width: 0; font-family: var(--mono); font-size: 9px; letter-spacing: -0.02em; color: var(--fg-3); text-align: center; white-space: nowrap; }

.chart-legend { display: flex; gap: 17px; flex-wrap: wrap; margin-top: 15px; font-size: 11.5px; color: var(--fg-2); }
.chart-legend span { display: inline-flex; align-items: center; gap: 7px; }
.chart-legend i { width: 9px; height: 9px; border-radius: 3px; display: inline-block; flex-shrink: 0; }

.rank-list { display: flex; flex-direction: column; }
.rank-row { display: flex; align-items: center; gap: 13px; padding: 12px 0; border-bottom: 1px solid var(--edge-soft); }
.rank-row:last-child { border-bottom: none; }
.rank-body { flex: 1; min-width: 0; }
.rank-name { font-size: 13px; font-weight: 500; display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.rank-name .mono { font-size: 12px; color: var(--fg-3); }
.rank-track { height: 5px; margin-top: 7px; border-radius: var(--radius-pill); background: var(--pane-sunk); overflow: hidden; }
.rank-fill { height: 100%; background: linear-gradient(90deg, var(--signal), var(--free)); border-radius: var(--radius-pill); box-shadow: 0 0 12px -2px var(--signal-glow); transition: width 0.5s var(--ease); }

.feed { display: flex; flex-direction: column; }
.feed-row { display: flex; gap: 13px; padding: 12px 0; border-bottom: 1px solid var(--edge-soft); font-size: 13px; }
.feed-row:last-child { border-bottom: none; }
.feed-dot { width: 7px; height: 7px; border-radius: 50%; margin-top: 6px; flex-shrink: 0; background: var(--fg-3); box-shadow: 0 0 9px currentColor; }
.feed-dot.active { background: var(--signal); }
.feed-dot.cancelled { background: var(--idle); }
.feed-dot.expired { background: var(--busy); }
.feed-dot.completed { background: var(--free); }
.feed-body { flex: 1; min-width: 0; }
.feed-text { color: var(--fg); }
.feed-text b { font-weight: 600; }
.feed-time { font-family: var(--mono); font-size: 11px; letter-spacing: -0.02em; color: var(--fg-3); margin-top: 3px; }

/* ==========================================================================
   17. Quick paste, rules list, countdowns
   ========================================================================== */
.paste-box .textarea {
    font-family: var(--mono);
    font-size: 12.5px;
    line-height: 1.75;
    letter-spacing: -0.02em;
    border-color: var(--signal-edge);
    box-shadow: 0 0 0 3px var(--signal-wash);
}
.divider {
    display: flex;
    align-items: center;
    gap: 13px;
    margin: 24px 0 20px;
    font-size: 9.5px;
    font-weight: 600;
    letter-spacing: 0.15em;
    text-transform: uppercase;
    color: var(--fg-3);
}
.divider::before, .divider::after { content: ''; flex: 1; height: 1px; background: var(--edge-soft); }

#batch-table td { padding: 5px 6px; }
#batch-table th { font-size: 9px; }
.inline-input {
    width: 100%;
    min-width: 78px;
    padding: 7px 9px;
    font-family: var(--sans);
    font-size: 12.5px;
    color: var(--fg);
    background: var(--pane-sunk);
    border: 1px solid var(--edge-soft);
    border-radius: var(--radius-xs);
}
.inline-input:focus { outline: none; border-color: var(--signal-edge); box-shadow: 0 0 0 2px var(--signal-wash); }


.countdown { font-family: var(--mono); font-size: 13.5px; font-variant-numeric: tabular-nums; letter-spacing: -0.02em; }
.countdown.is-low { color: var(--alert); }
.countdown-bar { display: block; height: 3px; width: 100%; max-width: 112px; margin-top: 6px; background: var(--pane-sunk); border-radius: var(--radius-pill); overflow: hidden; }
.countdown-bar i { display: block; height: 100%; width: 100%; background: var(--busy); box-shadow: 0 0 9px -1px var(--busy); border-radius: var(--radius-pill); transition: width 1s linear; }
.countdown-bar i.is-low { background: var(--alert); box-shadow: 0 0 9px -1px var(--alert); }

/* ==========================================================================
   18. Login — a horizontal split: statement above, form below
   ========================================================================== */
/* One thing on the page, in the middle of it. The beam still drifts behind so
   the screen is not a flat rectangle, but nothing competes with the form. */
.auth {
    min-height: 100vh;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 24px;
    position: relative;
    overflow: hidden;
}
.auth::before {
    content: '';
    position: absolute;
    inset: -25% -10%;
    background: linear-gradient(108deg, transparent 42%, var(--signal-wash) 50%, transparent 58%);
    mask-image: radial-gradient(70% 60% at 50% 50%, #000 8%, transparent 74%);
    -webkit-mask-image: radial-gradient(70% 60% at 50% 50%, #000 8%, transparent 74%);
    animation: sweep-beam 15s ease-in-out infinite alternate;
    pointer-events: none;
}
@keyframes sweep-beam { from { transform: translateX(-5%); } to { transform: translateX(5%); } }

.auth-card {
    position: relative;
    width: 100%;
    max-width: 380px;
    padding: 32px;
    border-radius: var(--radius-lg);
    background: var(--deep);
    background-image: linear-gradient(180deg, var(--pane-2), transparent 140px);
    border: 1px solid var(--edge);
    box-shadow: inset 0 1px 0 var(--lit), var(--cast-3);
}
.auth-card .field + .field { margin-top: 14px; }
.auth-card .btn { margin-top: 22px; }

/* ==========================================================================
   19. Responsive
   ========================================================================== */
@media (min-width: 981px) {
    .mobile-only { display: none !important; }
}

@media (max-width: 1280px) {
    .col-8 { grid-column: span 12; }
    .col-6 { grid-column: span 6; }
    .col-4 { grid-column: span 6; }
}

/* With five tabs, a search field and a primary action all in one bar, the tab
   labels are the first thing that can go — the icons and the lit underline
   still say where you are. */
@media (max-width: 1340px) {
    .topnav-tabs .nav-tab-label { display: none; }
    .nav-tab { padding: 8px 10px; }
}

@media (max-width: 1160px) {
    .topnav-clock, .cmdk, .topnav-me-text { display: none; }
}

/* The primary action stays — it is why the page exists. Density and the
   shortcut sheet are power affordances and can go instead. */
@media (max-width: 980px) {
    .topnav-side [data-density-toggle], .topnav-side [data-open-shortcuts] { display: none; }
    .topnav-actions .btn { padding: 7px 11px; font-size: 12px; }
}

@media (max-width: 860px) {
    .nav-live { display: none; }   /* the column headers still carry the counts */
}

@media (max-width: 980px) {
    :root { --nav-h: 54px; }

    /* It is the last element in the markup, because on a wide screen it does
       not exist. Where it does, it belongs beside the brand: that is the corner
       a thumb goes to for a menu, and reading the bar left to right should give
       you "where am I, where can I go" before anything else. */
    .nav-toggle { display: inline-flex; order: -1; }
    .topnav-brand { order: -2; }

    .topnav { gap: 12px; padding: 0 12px; }
    .topnav-tabs {
        position: absolute;
        top: var(--nav-h);
        left: 0; right: 0;
        flex-direction: column;
        align-items: stretch;
        gap: 2px;
        padding: 10px;
        background: var(--deep);
        background-image: linear-gradient(180deg, var(--pane-2), transparent 90px);
        border-bottom: 1px solid var(--edge-strong);
        box-shadow: var(--cast-3);
        display: none;
        max-height: calc(100vh - var(--nav-h));
        overflow-y: auto;
    }
    .topnav-tabs.is-open { display: flex; }
    /* The labels are hidden above so the horizontal strip can fit more tabs.
       Here each tab has a whole line to itself, and a menu of bare icons is a
       riddle. This block sits after that one, so it wins. */
    .topnav-tabs .nav-tab-label { display: inline; }

    .nav-tab { padding: 12px 13px; gap: 11px; }
    .nav-tab.active::after { display: none; }
    .nav-count { margin-left: auto; }

    .canvas-head { padding: 18px 18px 0; }
    .canvas-title { font-size: 25px; }
    .canvas-tools { padding: 14px 18px 0; }
    .canvas-body { padding: 18px 18px 48px; }

    /* The board stacks; each column keeps its own header and grows naturally. */
    .canvas-board .canvas-body { overflow-y: auto; }
    .board { grid-template-columns: minmax(0, 1fr); height: auto; }
    .board-col { max-height: 62vh; }

    .state-row { grid-template-columns: minmax(0, 1fr); }
    .grid12 > * { grid-column: span 12 !important; }

    .modal { padding: 0; align-items: flex-end; }
    .modal-panel { max-width: none; max-height: 92vh; border-radius: var(--radius-lg) var(--radius-lg) 0 0; animation: sheet-up 0.28s var(--ease) both; }

    .table-cards thead { display: none; }
    .table-cards { min-width: 0; }
    .table-cards, .table-cards tbody, .table-cards tr, .table-cards td { display: block; width: 100%; }
    .table-cards .cell-title .cell-strong, .table-cards td.mono { white-space: normal; }
    .table-cards tr { padding: 14px 16px; border-bottom: 1px solid var(--edge); }
    .table-cards tr:hover { background: none; }
    .table-cards td {
        display: flex;
        align-items: baseline;
        justify-content: space-between;
        gap: 16px;
        padding: 4px 0;
        border: none;
        text-align: right;
    }
    .table-cards td::before {
        content: attr(data-label);
        font-family: var(--mono);
        font-size: 11px;
        font-weight: 400;
        letter-spacing: -0.02em;
        color: var(--fg-3);
        text-align: left;
        flex-shrink: 0;
    }
    .table-cards td[data-label='']::before { display: none; }
    .table-cards td.cell-title { font-family: var(--display); font-size: 18px; font-weight: 700; letter-spacing: -0.035em; padding-bottom: 9px; }
    .table-cards .table-actions { justify-content: flex-start; padding-top: 10px; flex-wrap: wrap; }

    .shortcut-grid { grid-template-columns: 1fr; gap: 18px; }
    .palette-foot { display: none; }
}

@media (max-width: 620px) {
    .field-grid { grid-template-columns: 1fr; }
    .tiles { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
    .tile { padding: 14px 15px; }
    .tile-value { font-size: 25px; }
    .modal-fields { grid-template-columns: 1fr; }
    .canvas-title { font-size: 22px; }
}

/* --------------------------------------------------------------- touch --
   Anything that only appears on hover is unreachable on a touch screen: there
   is no hover, so the control simply does not exist. These are shown outright
   where the pointer is coarse. */
@media (hover: none) {
    .notice-drop { opacity: 1; }
    .copyable .copy-icon { opacity: 0.5; }
    .lot:hover { transform: none; }
}

/* ------------------------------------------------------------- the bell --
   Anchoring a 400px panel to a button sitting 40px from the edge of a phone
   puts a third of it off-screen. On narrow screens it stops hanging off the
   bell and becomes a panel of its own, inset from both edges. */
@media (max-width: 620px) {
    .notice-panel {
        position: fixed;
        top: calc(var(--nav-h) + 8px);
        left: 8px;
        right: 8px;
        width: auto;
        max-height: calc(100vh - var(--nav-h) - 20px);
    }
    .notice-item { padding: 11px 10px 11px 0; gap: 10px; }
    .notice-text { font-size: 12.5px; }

    /* Full width, and out of the way of a thumb resting at the bottom edge. */
    .toast-stack { left: 10px; right: 10px; bottom: 10px; width: auto; }
    .toast { padding: 12px 13px 14px; }
}

/* ----------------------------------------------------------- the tables --
   Rows in card mode already stack; these are the parts added since. */
@media (max-width: 980px) {
    /* Five choices do not fit across a phone and read badly stacked, so the
       row scrolls sideways instead of folding. */
    .segmented {
        display: flex;
        max-width: 100%;
        overflow-x: auto;
        scrollbar-width: none;
        -webkit-overflow-scrolling: touch;
    }
    .segmented::-webkit-scrollbar { display: none; }
    .segment { flex: 0 0 auto; }

    .table-toolbar { padding: 11px 14px; gap: 9px; }
    .table-toolbar .select { flex: 1 1 auto; min-width: 0; width: auto; }

    /* The action column is the one part of a card row that must stay easy to
       hit, so the buttons keep their size and take a line of their own. */
    .table-cards .table-actions { gap: 8px; }
    .table-cards .btn-glyph { width: 40px; height: 40px; }

    .legend { padding: 12px 14px 2px; gap: 5px 14px; }
    .legend li { font-size: 11px; }
}

/* -------------------------------------------------------------- the board */
@media (max-width: 620px) {
    .board-col-head { padding: 12px 13px; }
    .board-col-body { padding: 10px; gap: 9px; }

    /* Six brackets across a phone: the row scrolls rather than wrapping into
       three ragged lines above the column it filters. */
    .band-filter {
        flex-wrap: nowrap;
        overflow-x: auto;
        scrollbar-width: none;
        -webkit-overflow-scrolling: touch;
        width: 100%;
        order: 3;
        padding-bottom: 2px;
    }
    .band-filter::-webkit-scrollbar { display: none; }
    .band-chip { flex: 0 0 auto; }

    .lot { padding: 13px 13px 11px; }
    .lot-logo { flex-basis: 46px; width: 46px; height: 46px; border-radius: 12px; }
    .lot-clock { font-size: 29px; }
    .lot-actions .btn { flex: 1 1 auto; min-width: 0; }
}

/* ------------------------------------------------------------- overlays --
   A dialog on a phone is a sheet: it comes up from the bottom edge, where the
   hand already is, and takes the full width. */
@media (max-width: 620px) {
    .overlay { padding: 0; align-items: flex-end; }
    .overlay-top { padding-top: 0; align-items: flex-end; }

    .dialog, .dialog-wide, .palette {
        max-width: none;
        width: 100%;
        border-radius: var(--radius-lg) var(--radius-lg) 0 0;
        animation: sheet-up 0.28s var(--ease) both;
    }
    .dialog { padding: 22px 20px calc(22px + env(safe-area-inset-bottom)); }
    .dialog h2 { font-size: 19px; }
    .dialog .form-actions { flex-direction: column-reverse; align-items: stretch; }
    .dialog .form-actions .btn { width: 100%; }

    .proof-view { max-height: 52vh; }
    .proof-view iframe { height: 52vh; }

    .palette { max-height: 76vh; }
}

/* ---------------------------------------------------------------- forms --
   Anything under 16px makes iOS zoom the page the moment it is focused, and
   the layout never quite comes back. */
@media (max-width: 620px) {
    .input, .textarea, .select { font-size: 16px; }
    .auth-card { padding: 24px 20px; }
    .form-actions { flex-direction: column-reverse; align-items: stretch; }
    .form-actions .btn { width: 100%; }
    .bulk-bar { padding: 11px 14px; }
    .bulk-bar .btn-row { width: 100%; }
    .bulk-bar .btn-row .btn { flex: 1 1 auto; }
}

/* ------------------------------------------------------------- the bar --
   A phone gives the top bar about 360px. The brand, a menu button, the page's
   own actions, the bell, an avatar and a way out do not fit in it, so the parts
   that repeat something already on screen give way first. */
@media (max-width: 720px) {
    .topnav { gap: 8px; padding: 0 10px; }

    /* Nothing left inside it at this width, but it still has to hold the
       middle open or the utilities slide over to the brand. */
    .topnav-mid { flex: 1; min-width: 0; }
    .topnav-side { gap: 6px; min-width: 0; }

    /* Every control in the bar keeps a thumb-sized target. */
    .topnav-side .btn-icon, .nav-toggle, .bell { width: 36px; height: 36px; padding: 0; }
}

/* The avatar says who is signed in; on a narrow bar the page underneath
   already does, and the room is worth more. */
@media (max-width: 460px) {
    .topnav-me { display: none; }
    .topnav-word { font-size: 16px; }
}

/* The actions, once the menu has taken them in. They sit under the
   destinations, divided from them, and each spans the sheet: a full-width row
   is the easiest thing there is to hit. */
.nav-actions-moved {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 8px;
    margin-top: 10px;
    padding-top: 12px;
    border-top: 1px solid var(--edge-soft);
}
.nav-actions-moved .btn { width: 100%; padding: 12px 14px; font-size: 13px; }

@keyframes sheet-up { from { transform: translateY(30px); opacity: 0; } to { transform: none; opacity: 1; } }

@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
    }
}

@media print {
    body { background: #fff; color: #000; overflow: visible; }
    body::before { display: none; }
    .app, .canvas, .canvas-body { display: block; height: auto; overflow: visible; }
    .panel { border: 1px solid #ccc; box-shadow: none; backdrop-filter: none; background: #fff; }
}
