/* PR-ADMIN-FROM-SCRATCH-1 (2026-05-28) — clean foundation.
 *
 * Replaces the prior 600-line admin-shell.css + 232-line admin-polish.css.
 * Operator: "remove the old UI entirely first and rebuild it."
 *
 * NINE tokens. ONE button system. ONE card primitive. ONE input style.
 * No tints. No hover-tints. No state-secondary-soft. Restraint is the
 * polish.
 *
 * Scoped to body[data-admin-shell="on"] so existing non-admin pages
 * (login, tablets, etc.) are unaffected. Every admin page opts in via
 * the body attribute + including this file.
 */

/* ────────────────────────────────────────────────────────────────
   Tokens — 9 colors, 6 type sizes, 9 spacing values, 4 radii
   ──────────────────────────────────────────────────────────────── */

body[data-admin-shell="on"] {
    /* Color — nine tokens. Values MIRROR the main SPA light theme
       (app.css :root[data-theme="light"]) so the admin console + every
       standalone page that rides these tokens (pricing, standards, …)
       reads as the SAME app, in the SAME light/dark themes. */
    --canvas:   #F3F5F8;      /* page bg      = main --bg   */
    --paper:    #FFFFFF;      /* card bg      = main --pn   */
    --ink:      #1A222E;      /* primary text = main --txt  */
    --muted:    #5A6573;      /* secondary    = main --dim  */
    --faint:    #D9DFE7;      /* borders      = main --bdr  */
    --hairline: #EEF1F5;      /* subtle dividers            */
    --accent:   #2563EB;      /* blueprint blue = main --acc (was cyan #0891b2) */
    --danger:   #D33A4B;      /* = main --no   */
    --warn:     #C77700;      /* = main --warn */


    /* Type scale: 12 / 14 / 16 / 20 / 28 / 40 */
    --t-xs:  12px;
    --t-sm:  14px;
    --t:     16px;
    --t-md:  20px;
    --t-lg:  28px;
    --t-xl:  40px;

    /* Spacing: 4 8 12 16 24 32 48 64 96 */
    --s-1:  4px;
    --s-2:  8px;
    --s-3:  12px;
    --s-4:  16px;
    --s-5:  24px;
    --s-6:  32px;
    --s-7:  48px;
    --s-8:  64px;
    --s-9:  96px;

    /* Radii */
    --r-sm: 6px;
    --r:    8px;
    --r-md: 12px;
    --r-lg: 16px;

    /* One shadow, layered subtle */
    --shadow:
        0 1px 0 rgba(15, 23, 42, 0.04),
        0 1px 3px rgba(15, 23, 42, 0.06);

    background: var(--canvas);
    color: var(--ink);
    font-family: 'Inter', -apple-system, system-ui, sans-serif;
    font-size: var(--t-sm);
    line-height: 1.5;
    margin: 0;
    -webkit-font-smoothing: antialiased;
    text-rendering: optimizeLegibility;
}

/* ────────────────────────────────────────────────────────────────
   PR-ADMIN-R1 (2026-09-24) — the console wears the APP's shell.
   admin-shell.js builds index.html's exact chrome (#app-topbar,
   #app-sidebar + #app-sidebar-backdrop, #app-workspace, #app-bottom-nav,
   #app-statusbar) and injects /tokens.css, /shell.css and /mobile.css
   BEFORE this sheet, so shell.css styles that chrome and this sheet stays
   the last word on page components. The ~540 lines of console-only chrome
   that lived here (a slate top bar and drawer with their own palette, the
   7-tab rail, the hover flyouts, the touch sheet) are gone.
   This block carries only what shell.css does not:
     - the search bar and util buttons (app.css owns them in the SPA; the
       console does not load app.css — 1 MB of page styles)
     - anchor resets for nav slots the SPA renders as <button>
     - the sidebar-footer theme toggle
   ──────────────────────────────────────────────────────────────── */

/* The SPA gets border-box from app.css's global `*{box-sizing:border-box}`;
   the console does not load app.css, and a global reset here would shift
   every page's own layout — so the reset is scoped to the chrome. Without
   it the 56px user pill + its padding overflowed the 56px bar. */
body[data-admin-shell="on"] :is(#app-topbar, #app-sidebar, #app-bottom-nav, #app-statusbar, #app-sidebar-backdrop),
body[data-admin-shell="on"] :is(#app-topbar, #app-sidebar, #app-bottom-nav, #app-statusbar) * {
    box-sizing: border-box;
}
body[data-admin-shell="on"] #app-sidebar ul,
body[data-admin-shell="on"] #app-sidebar li { margin: 0; padding: 0; list-style: none; }

/* Anchors in the SPA's button slots. */
body[data-admin-shell="on"] #app-sidebar a.sidebar-nav-item,
body[data-admin-shell="on"] #app-sidebar a.sidebar-nav-item:hover,
body[data-admin-shell="on"] #app-bottom-nav a.bnav-item,
body[data-admin-shell="on"] #app-topbar a.topbar-home-btn,
body[data-admin-shell="on"] #app-topbar a.util-btn {
    text-decoration: none;
    box-sizing: border-box;
}
body[data-admin-shell="on"] #app-sidebar .sidebar-nav-item .nav-icon svg { width: 20px; height: 20px; }

/* Search bar — app.css's .forge-cmd-bar rules, copied verbatim. */
body[data-admin-shell="on"] .forge-cmd-bar {
    display: flex; align-items: center; gap: 8px;
    height: 34px; max-width: 560px; width: 100%;
    padding: 0 10px; cursor: pointer;
    background: var(--inp);
    border: 1px solid var(--bdr);
    border-radius: 6px;
    color: var(--dim);
    box-sizing: border-box;
}
body[data-admin-shell="on"] .forge-cmd-bar:hover,
body[data-admin-shell="on"] .forge-cmd-bar:focus-visible {
    border-color: var(--acc);
    box-shadow: 0 0 0 2px color-mix(in srgb, var(--acc) 22%, transparent);
    outline: none;
}
body[data-admin-shell="on"] .forge-cmd-bar svg { flex: 0 0 16px; color: var(--dim); }
body[data-admin-shell="on"] .forge-cmd-ph { flex: 1; font: 13px var(--ff-ui); color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
body[data-admin-shell="on"] .forge-kbd {
    font: 11px var(--ff-mono); color: var(--dim);
    background: var(--pn); border: 1px solid var(--bdr); border-radius: 3px;
    padding: 1px 6px; margin-left: auto; flex: 0 0 auto;
}
/* Narrow screens: the bar shrinks instead of spilling its ⌘K hint onto the
   bell, and on a phone it is a 44px search button. */
body[data-admin-shell="on"] .forge-cmd-bar { min-width: 0; overflow: hidden; }
@media (max-width: 767px) {
    body[data-admin-shell="on"] .forge-kbd { display: none; }
}
@media (max-width: 560px) {
    body[data-admin-shell="on"] #app-topbar .topbar-search { flex: 0 0 auto; margin: 0 0 0 auto; }
    body[data-admin-shell="on"] .forge-cmd-bar { width: 44px; height: 44px; padding: 0; justify-content: center; }
    body[data-admin-shell="on"] .forge-cmd-ph { display: none; }
}

/* Util buttons (the settings gear; the bell mounts its own .ascut-bell) —
   app.css's .util-btn rule, copied. */
body[data-admin-shell="on"] #app-topbar .util-btn {
    width: 44px; height: 44px; min-height: 44px;
    display: inline-flex; align-items: center; justify-content: center;
    padding: 0;
    background: var(--inp);
    border: 1px solid var(--bdr);
    border-radius: 8px;
    color: var(--dim);
    cursor: pointer;
    position: relative;
    font-size: 15px;
    transition: color var(--dur-chrome) var(--ease-out),
                border-color var(--dur-chrome) var(--ease-out),
                background var(--dur-chrome) var(--ease-out);
}
body[data-admin-shell="on"] #app-topbar .util-btn:hover { color: var(--acc); border-color: var(--acc); background: var(--bg); }
body[data-admin-shell="on"] #app-topbar .util-btn > svg { width: 22px; height: 22px; flex: 0 0 auto; }
body[data-admin-shell="on"] #app-topbar .topbar-bell-host { display: inline-flex; align-items: center; }

/* Sidebar-footer theme toggle rides the nav-item look. */
body[data-admin-shell="on"] #app-sidebar .sidebar-theme-toggle .nav-icon { font-size: 15px; line-height: 1; }

/* Printing (QR plates, station codes, labels, lists): shell.css makes
   #app-workspace a FIXED scroll box, which would print one clipped sheet.
   On paper the chrome goes and the page flows like a document again. */
@media print {
    body[data-admin-shell="on"] :is(#app-topbar, #app-sidebar, #app-sidebar-backdrop, #app-statusbar, #app-bottom-nav) { display: none !important; }
    body[data-admin-shell="on"] #app-workspace { position: static !important; overflow: visible !important; inset: auto !important; }
}

/* ────────────────────────────────────────────────────────────────
   The band — the studios' header (bench-studio.css .studio-band,
   PR-STUDIO-IDENTITY 2026-09-05), same classes and measurements, so a
   console hub page opens the way Cabinet Studio and Door Studio do: the
   shop's name, the page's name, today's date, and the numbers that matter.
   Blueprint blue by default (Cabinet Studio's colour); Door Studio keeps
   teal. Since PR-FLOW-1 (2026-09-24) every console page opens under a band:
   admin-shell.js turns a sub-page's flat .page-head into one (.page-band).
   ──────────────────────────────────────────────────────────────── */
body[data-admin-shell="on"] .studio-band {
    --studio: var(--acc, #2563EB);
    position: relative; overflow: hidden;
    display: flex; align-items: flex-end; justify-content: space-between; gap: 24px; flex-wrap: wrap;
    padding: 22px 26px 20px; margin: 0 0 18px; border-radius: 14px;
    color: var(--studio-ink, #fff);
    background: linear-gradient(140deg, color-mix(in srgb, var(--studio) 88%, #fff) 0%, var(--studio) 46%, color-mix(in srgb, var(--studio) 72%, #000) 100%);
    box-shadow: var(--shadow-4, 0 10px 30px rgba(37, 99, 235, 0.22));
}
body[data-admin-shell="on"] .studio-band::after { content: ""; position: absolute; inset: 0; pointer-events: none; background: radial-gradient(120% 90% at 100% 0%, rgba(255,255,255,.16), transparent 60%); }
body[data-admin-shell="on"] .studio-band > * { position: relative; z-index: 1; }
body[data-admin-shell="on"] .studio-band .sb-shop { font: 600 11.5px var(--ff-ui); letter-spacing: .12em; text-transform: uppercase; opacity: .78; margin-bottom: 4px; }
body[data-admin-shell="on"] .studio-band .sb-title { font: 800 30px/1.02 var(--ff-ui); letter-spacing: -0.025em; margin: 0; color: inherit; }
body[data-admin-shell="on"] .studio-band .sb-date { font: 500 13px var(--ff-ui); opacity: .85; margin-top: 8px; }
body[data-admin-shell="on"] .studio-band .sb-r { display: flex; gap: 26px; align-items: flex-end; flex-wrap: wrap; }
body[data-admin-shell="on"] .studio-band .sb-stat { display: flex; flex-direction: column; align-items: flex-start; gap: 2px; min-width: 96px; }
body[data-admin-shell="on"] .studio-band .sb-stat b { font: 600 26px/1 var(--ff-mono); font-variant-numeric: tabular-nums; letter-spacing: -0.01em; }
body[data-admin-shell="on"] .studio-band .sb-stat b small { font: 600 13px var(--ff-ui); opacity: .8; margin-left: 3px; letter-spacing: 0; }
body[data-admin-shell="on"] .studio-band .sb-stat span { font: 500 12px var(--ff-ui); opacity: .82; white-space: nowrap; }
body[data-admin-shell="on"] .studio-band .sb-stat.sb-late b { color: #FFB4A6; }
/* The band's one action — the hub tiles' "+ New" pill (bench.css .bench-studio-new). */
body[data-admin-shell="on"] .studio-band .sb-cta {
    display: inline-flex; align-items: center; gap: 8px; align-self: center;
    height: 42px; padding: 0 16px; border-radius: 10px;
    background: rgba(255,255,255,.2); border: 1px solid rgba(255,255,255,.34);
    color: inherit; font: 700 14px var(--ff-ui); text-decoration: none; white-space: nowrap;
    transition: background .12s ease, transform .12s ease;
}
body[data-admin-shell="on"] .studio-band .sb-cta:hover { background: rgba(255,255,255,.32); text-decoration: none; }
body[data-admin-shell="on"] .studio-band .sb-cta:active { transform: translateY(1px); }
body[data-admin-shell="on"] .studio-band .sb-cta:focus-visible { outline: none; box-shadow: 0 0 0 3px rgba(255,255,255,.55); }
@media (max-width: 720px) {
    body[data-admin-shell="on"] .studio-band { padding: 18px 18px 16px; }
    body[data-admin-shell="on"] .studio-band .sb-title { font-size: 24px; }
    body[data-admin-shell="on"] .studio-band .sb-r { gap: 18px; }
}
@media (prefers-reduced-motion: no-preference) {
    @keyframes cw-band-in { from { opacity: 0; transform: translateY(5px); } to { opacity: 1; transform: none; } }
    body[data-admin-shell="on"] .studio-band { animation: cw-band-in .4s cubic-bezier(.22,1,.36,1) both; }
}

/* ────────────────────────────────────────────────────────────────
   Main column — full width, like every SPA page
   ──────────────────────────────────────────────────────────────── */

body[data-admin-shell="on"] .admin-main {
    /* PR-ADMIN-R1: the 1200px "article" cap and its data-admin-wide opt-out
       are gone — on a 2560px screen the cap left the console in the middle
       46% of the window, the loudest "different app" tell after the rail.
       A page that is genuinely prose (Privacy, Your data) opts into .prose. */
    padding: 20px 24px 40px;
    width: 100%;
    box-sizing: border-box;
}
body[data-admin-shell="on"] .admin-main.prose { max-width: 76ch; }
@media (max-width: 720px) {
    body[data-admin-shell="on"] .admin-main { padding: 14px 16px 32px; }
}
html[data-ui-mode="mobile"] body[data-admin-shell="on"] .admin-main { padding: 14px 16px 32px; }

/* ────────────────────────────────────────────────────────────────
   Page header — title + subtitle, no chrome
   ──────────────────────────────────────────────────────────────── */

/* Per-page back button (injected by admin-shell.js on every sub-page). Sits
   above the page-head so drilling in from Setup/System always has a way back. */
body[data-admin-shell="on"] .admin-back {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    margin: 0 0 var(--s-4);
    padding: 6px 2px;
    font-size: var(--t-sm);
    font-weight: 600;
    color: var(--muted);
    text-decoration: none;
    transition: color 120ms;
}

body[data-admin-shell="on"] .admin-back:hover {
    color: var(--accent);
}

body[data-admin-shell="on"] .page-head {
    margin: 0 0 var(--s-7) 0;
}

body[data-admin-shell="on"] .page-head h1 {
    /* PR-ADMIN-R1: the SPA's studio header (.shdr h1 — 24px / 600), not the
       28px / 700 article title the console used to open with. */
    font-size: 24px;
    font-weight: 600;
    color: var(--ink);
    letter-spacing: -0.02em;
    line-height: 1.15;
    margin: 0;
}

body[data-admin-shell="on"] .page-head .sub {
    color: var(--muted);
    font-size: var(--t);
    margin: var(--s-2) 0 0 0;
    max-width: 60ch;
    line-height: 1.55;
}

/* ────────────────────────────────────────────────────────────────
   Cards — single primitive
   ──────────────────────────────────────────────────────────────── */

body[data-admin-shell="on"] .card {
    background: var(--paper);
    border: 1px solid var(--hairline);
    border-radius: var(--r-md);
    padding: var(--s-6);
    box-shadow: var(--shadow);
    margin-bottom: var(--s-5);
}

body[data-admin-shell="on"] .card.warn   { border-left: 3px solid var(--warn); }
body[data-admin-shell="on"] .card.danger { border-left: 3px solid var(--danger); }
body[data-admin-shell="on"] .card.ok     { border-left: 3px solid var(--accent); }

body[data-admin-shell="on"] .card-head {
    color: var(--muted);
    font-size: var(--t-xs);
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    margin: 0 0 var(--s-4) 0;
}

body[data-admin-shell="on"] .card .lead {
    font-size: var(--t-md);
    font-weight: 600;
    color: var(--ink);
    letter-spacing: -0.01em;
    line-height: 1.3;
    margin: 0 0 var(--s-2) 0;
}

body[data-admin-shell="on"] .card p {
    color: var(--muted);
    font-size: var(--t-sm);
    line-height: 1.6;
    margin: 0;
}

body[data-admin-shell="on"] .card p + p {
    margin-top: var(--s-3);
}

/* ────────────────────────────────────────────────────────────────
   Big number — used inside cards for hero metrics
   ──────────────────────────────────────────────────────────────── */

body[data-admin-shell="on"] .number {
    font-size: var(--t-xl);
    font-weight: 700;
    color: var(--ink);
    line-height: 1;
    letter-spacing: -0.025em;
    font-variant-numeric: tabular-nums;
}

body[data-admin-shell="on"] .number-label {
    color: var(--muted);
    font-size: var(--t-xs);
    margin-top: var(--s-2);
    letter-spacing: 0.04em;
}

/* ────────────────────────────────────────────────────────────────
   Settings-list — Apple Settings style rows
   ──────────────────────────────────────────────────────────────── */

body[data-admin-shell="on"] .settings-list {
    background: var(--paper);
    border: 1px solid var(--hairline);
    border-radius: var(--r-md);
    box-shadow: var(--shadow);
    overflow: hidden;
    margin-bottom: var(--s-5);
}

body[data-admin-shell="on"] .settings-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--s-5);
    padding: var(--s-5) var(--s-6);
    border-bottom: 1px solid var(--hairline);
    text-decoration: none;
    color: var(--ink);
    transition: background 120ms;
}

body[data-admin-shell="on"] .settings-row:last-child {
    border-bottom: none;
}

body[data-admin-shell="on"] .settings-row:hover {
    background: var(--canvas);
}

body[data-admin-shell="on"] .settings-row .label {
    flex: 1;
}

body[data-admin-shell="on"] .settings-row .label-title {
    font-size: var(--t);
    font-weight: 600;
    color: var(--ink);
    letter-spacing: -0.005em;
    line-height: 1.3;
}

body[data-admin-shell="on"] .settings-row .label-sub {
    color: var(--muted);
    font-size: var(--t-sm);
    margin-top: 2px;
    line-height: 1.5;
}

body[data-admin-shell="on"] .settings-row .chev {
    color: var(--muted);
    font-size: var(--t);
    flex-shrink: 0;
}

body[data-admin-shell="on"] .settings-row:hover .chev {
    color: var(--accent);
}

/* ────────────────────────────────────────────────────────────────
   Grouped settings — section header above each .settings-list card
   (iOS inset-grouped pattern). Breaks a long flat list into scannable
   labeled chunks. Tokens only — adapts to light/dark automatically.
   ──────────────────────────────────────────────────────────────── */

body[data-admin-shell="on"] .settings-section-label {
    font-size: var(--t-xs);
    font-weight: 600;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--muted);
    margin: var(--s-6) 0 var(--s-2);
    padding: 0 var(--s-2);
}

body[data-admin-shell="on"] .settings-section-label:first-of-type {
    margin-top: var(--s-2);
}

body[data-admin-shell="on"] .settings-section-label .section-desc {
    display: block;
    margin-top: 3px;
    font-size: var(--t-xs);
    font-weight: 400;
    letter-spacing: 0;
    text-transform: none;
    color: var(--muted);
}

/* The setup wizard is an ACTION, not a setting — its own card at the top,
   marked with an accent rail + accent title so it reads as "start here"
   without a loud tint (admin shell ethos: restraint, tokens only). */
body[data-admin-shell="on"] .settings-row.is-wizard {
    box-shadow: inset 3px 0 0 var(--accent);
}

body[data-admin-shell="on"] .settings-row.is-wizard .label-title {
    color: var(--accent);
}

/* ────────────────────────────────────────────────────────────────
   Person/Worker row — used on People page
   ──────────────────────────────────────────────────────────────── */

body[data-admin-shell="on"] .person-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--s-5);
    padding: var(--s-4) 0;
    border-bottom: 1px solid var(--hairline);
}

body[data-admin-shell="on"] .person-row:last-child {
    border-bottom: none;
}

body[data-admin-shell="on"] .person-row .who {
    flex: 1;
}

body[data-admin-shell="on"] .person-row .who .name {
    font-size: var(--t-sm);
    font-weight: 600;
    color: var(--ink);
}

body[data-admin-shell="on"] .person-row .who .meta {
    color: var(--muted);
    font-size: var(--t-xs);
    margin-top: 2px;
}

body[data-admin-shell="on"] .person-row .pill {
    flex-shrink: 0;
}

/* ────────────────────────────────────────────────────────────────
   Queue bar — used on Floor page
   ──────────────────────────────────────────────────────────────── */

body[data-admin-shell="on"] .queue-row {
    display: grid;
    grid-template-columns: 140px 1fr 100px;
    align-items: center;
    gap: var(--s-4);
    padding: var(--s-3) 0;
}

body[data-admin-shell="on"] .queue-row .station {
    font-size: var(--t-sm);
    font-weight: 500;
    color: var(--ink);
}

body[data-admin-shell="on"] .queue-row .bar {
    height: 8px;
    background: var(--hairline);
    border-radius: 4px;
    overflow: hidden;
    position: relative;
}

body[data-admin-shell="on"] .queue-row .bar-fill {
    height: 100%;
    background: var(--ink);
    border-radius: 4px;
    transition: width 240ms ease-out;
}

body[data-admin-shell="on"] .queue-row .remain {
    font-size: var(--t-xs);
    color: var(--muted);
    text-align: right;
    font-variant-numeric: tabular-nums;
}

/* ────────────────────────────────────────────────────────────────
   Buttons — one system. Primary (filled accent) / default (ghost) / danger
   ──────────────────────────────────────────────────────────────── */

/* ────────────────────────────────────────────────────────────────
   Buttons — one system
   PR-ADMIN-R1 (2026-09-24): the app chrome (topbar-*, sidebar-*, bnav-*,
   util-*, and the bell's ascut-*) is EXCLUDED, so shell.css styles the
   top bar, sidebar and bottom nav exactly as in the app — the sign-out
   Confirm/Cancel pills are class-only rules and lost to this before.
   ⚠ Still OPEN (DIGEST.md "Generic-button specificity"): the chain is
   (0,10,2) and beats any page's own class-only button styles. Lowering it
   (e.g. :where()) is the real fix, but this sheet is shared by
   cabinet-shop-pricing.html, cabinet-shop-standards.html and
   setup-defaults.html, whose buttons have always rendered under it —
   lowering it restyles those pages, so it is its own change, proved
   page by page. Page components scope under an id meanwhile.
   ──────────────────────────────────────────────────────────────── */

body[data-admin-shell="on"] button:not([class*="admin-"]):not([class*="cmdk-"]):not([class*="sf-"]):not([class*="nav-"]):not([class*="topbar-"]):not([class*="sidebar-"]):not([class*="bnav-"]):not([class*="util-"]):not([class*="ascut-"]):not([data-own-buttons] *),
body[data-admin-shell="on"] .btn {
    display: inline-flex;
    align-items: center;
    gap: var(--s-2);
    padding: 8px var(--s-4);
    font-family: inherit;
    font-size: var(--t-sm);
    font-weight: 500;
    line-height: 1.4;
    border: 1px solid var(--faint);
    background: var(--paper);
    color: var(--ink);
    border-radius: var(--r);
    cursor: pointer;
    text-decoration: none;
    transition: background 120ms, border-color 120ms, transform 80ms;
    min-height: 36px;
}

body[data-admin-shell="on"] button:not([class*="admin-"]):not([class*="cmdk-"]):not([class*="sf-"]):not([class*="nav-"]):not([class*="topbar-"]):not([class*="sidebar-"]):not([class*="bnav-"]):not([class*="util-"]):not([class*="ascut-"]):not([data-own-buttons] *):hover,
body[data-admin-shell="on"] .btn:hover {
    border-color: var(--muted);
    background: var(--canvas);
}

body[data-admin-shell="on"] button:not([class*="admin-"]):not([class*="cmdk-"]):not([class*="sf-"]):not([class*="nav-"]):not([class*="topbar-"]):not([class*="sidebar-"]):not([class*="bnav-"]):not([class*="util-"]):not([class*="ascut-"]):not([data-own-buttons] *):active,
body[data-admin-shell="on"] .btn:active {
    transform: translateY(0.5px);
}

/* PR-ADMIN-R1 (2026-09-24): a primary / danger <button> used to LOSE to the
   generic rule above — (0,2,2) against its guard chain — so it painted
   paper-on-paper. Measured on the Pricing page: "Save pricing"
   (class="primary") computed rgb(255,255,255) with dark text, though both
   Pricing's own CSS and this sheet say primary = accent; every
   <button class="btn primary"> in the console was plain too (a primary <a>
   was fine: only the .btn half of the list matched it). The variants now
   carry the same guard chain plus their class, one step stronger. */
body[data-admin-shell="on"] button.primary:not([class*="admin-"]):not([class*="cmdk-"]):not([class*="sf-"]):not([class*="nav-"]):not([class*="topbar-"]):not([class*="sidebar-"]):not([class*="bnav-"]):not([class*="util-"]):not([class*="ascut-"]):not([data-own-buttons] *),
body[data-admin-shell="on"] .btn.primary {
    background: var(--accent);
    color: #ffffff;
    border-color: var(--accent);
}

body[data-admin-shell="on"] button.primary:not([class*="admin-"]):not([class*="cmdk-"]):not([class*="sf-"]):not([class*="nav-"]):not([class*="topbar-"]):not([class*="sidebar-"]):not([class*="bnav-"]):not([class*="util-"]):not([class*="ascut-"]):not([data-own-buttons] *):hover,
body[data-admin-shell="on"] .btn.primary:hover {
    background: var(--acc2, #1D4ED8);
    border-color: var(--acc2, #1D4ED8);
}

body[data-admin-shell="on"] button.danger:not([class*="admin-"]):not([class*="cmdk-"]):not([class*="sf-"]):not([class*="nav-"]):not([class*="topbar-"]):not([class*="sidebar-"]):not([class*="bnav-"]):not([class*="util-"]):not([class*="ascut-"]):not([data-own-buttons] *),
body[data-admin-shell="on"] .btn.danger {
    color: var(--danger);
}

body[data-admin-shell="on"] button.danger:not([class*="admin-"]):not([class*="cmdk-"]):not([class*="sf-"]):not([class*="nav-"]):not([class*="topbar-"]):not([class*="sidebar-"]):not([class*="bnav-"]):not([class*="util-"]):not([class*="ascut-"]):not([data-own-buttons] *):hover,
body[data-admin-shell="on"] .btn.danger:hover {
    background: rgba(220, 38, 38, 0.06);
    border-color: var(--danger);
}

body[data-admin-shell="on"] button:not([class*="admin-"]):not([class*="cmdk-"]):not([class*="sf-"]):not([class*="nav-"]):not([class*="topbar-"]):not([class*="sidebar-"]):not([class*="bnav-"]):not([class*="util-"]):not([class*="ascut-"]):not([data-own-buttons] *):disabled,
body[data-admin-shell="on"] .btn:disabled {
    opacity: 0.4;
    cursor: not-allowed;
}

/* ────────────────────────────────────────────────────────────────
   Form inputs — one system
   ──────────────────────────────────────────────────────────────── */

body[data-admin-shell="on"] input[type="text"],
body[data-admin-shell="on"] input[type="email"],
body[data-admin-shell="on"] input[type="number"],
body[data-admin-shell="on"] input[type="date"],
body[data-admin-shell="on"] input[type="search"],
body[data-admin-shell="on"] input[type="password"],
body[data-admin-shell="on"] input:not([type]),
body[data-admin-shell="on"] textarea,
body[data-admin-shell="on"] select {
    width: 100%;
    box-sizing: border-box;
    padding: 8px var(--s-3);
    font-family: inherit;
    font-size: var(--t-sm);
    line-height: 1.4;
    color: var(--ink);
    background: var(--paper);
    border: 1px solid var(--faint);
    border-radius: var(--r);
    min-height: 36px;
    transition: border-color 120ms, box-shadow 120ms;
}

body[data-admin-shell="on"] input:focus,
body[data-admin-shell="on"] textarea:focus,
body[data-admin-shell="on"] select:focus {
    outline: none;
    border-color: var(--accent);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 12%, transparent);
}

body[data-admin-shell="on"] input::placeholder {
    color: var(--muted);
    opacity: 0.7;
}

/* :where() (2026-09-24): at (0,1,2) this rule beat every page's own label
   rule. What we build asks `.field-row label { text-transform: none }` for
   its checkbox rows and got "DOORS", "DRAWER BOXES" and an uppercase
   description. Pages that set nothing still get this look. */
:where(body[data-admin-shell="on"]) label {
    display: block;
    font-size: var(--t-xs);
    font-weight: 600;
    color: var(--muted);
    letter-spacing: 0.04em;
    text-transform: uppercase;
    margin-bottom: var(--s-2);
}

body[data-admin-shell="on"] input[type="checkbox"] {
    width: 16px;
    height: 16px;
    accent-color: var(--accent);
    min-height: 0;
    box-shadow: none;
    margin: 0;
}

/* ────────────────────────────────────────────────────────────────
   Status pill — used sparingly for "PIN set" / "needs setup" etc.
   ──────────────────────────────────────────────────────────────── */

body[data-admin-shell="on"] .pill {
    display: inline-flex;
    align-items: center;
    padding: 2px 8px;
    border-radius: 999px;
    font-size: var(--t-xs);
    font-weight: 500;
    background: var(--hairline);
    color: var(--muted);
}

body[data-admin-shell="on"] .pill.ok {
    background: color-mix(in srgb, var(--accent) 8%, transparent);
    color: var(--accent);
}

body[data-admin-shell="on"] .pill.warn {
    background: rgba(234, 88, 12, 0.08);
    color: var(--warn);
}

body[data-admin-shell="on"] .pill.danger {
    background: rgba(220, 38, 38, 0.08);
    color: var(--danger);
}

/* ────────────────────────────────────────────────────────────────
   Hairline divider
   ──────────────────────────────────────────────────────────────── */

body[data-admin-shell="on"] .rule {
    border: 0;
    border-top: 1px solid var(--hairline);
    margin: var(--s-5) 0;
}

/* ────────────────────────────────────────────────────────────────
   Footer link (e.g. "View suggestions →")
   ──────────────────────────────────────────────────────────────── */

body[data-admin-shell="on"] .card-link {
    display: inline-block;
    margin-top: var(--s-4);
    color: var(--accent);
    text-decoration: none;
    font-size: var(--t-sm);
    font-weight: 500;
}

body[data-admin-shell="on"] .card-link:hover {
    color: #0e7490;
}

/* ────────────────────────────────────────────────────────────────
   Toast (replaces inline flash() patterns on existing pages)
   ──────────────────────────────────────────────────────────────── */

body[data-admin-shell="on"] .toast {
    position: fixed;
    bottom: var(--s-5);
    left: 50%;
    transform: translateX(-50%);
    background: var(--ink);
    color: var(--paper);
    padding: var(--s-3) var(--s-5);
    border-radius: var(--r);
    font-size: var(--t-sm);
    box-shadow: var(--shadow);
    z-index: 100;
}

/* ────────────────────────────────────────────────────────────────
   Legacy compat — old pages still depend on these class names
   ──────────────────────────────────────────────────────────────── */

body[data-admin-shell="on"] .paper,
body[data-admin-shell="on"] .panel,
body[data-admin-shell="on"] .group-card,
body[data-admin-shell="on"] .paper-card {
    background: var(--paper);
    border: 1px solid var(--hairline);
    border-radius: var(--r-md);
    padding: var(--s-6);
    box-shadow: var(--shadow);
    margin-bottom: var(--s-5);
}

body[data-admin-shell="on"] h1 {
    font-size: var(--t-lg);
    font-weight: 700;
    color: var(--ink);
    letter-spacing: -0.02em;
    line-height: 1.15;
    margin: 0 0 var(--s-4) 0;
}

body[data-admin-shell="on"] h2 {
    font-size: var(--t);
    font-weight: 600;
    color: var(--ink);
    letter-spacing: -0.005em;
    margin: 0 0 var(--s-3) 0;
}

body[data-admin-shell="on"] h3 {
    font-size: var(--t-sm);
    font-weight: 600;
    color: var(--ink);
    margin: var(--s-4) 0 var(--s-2) 0;
}

body[data-admin-shell="on"] p.subtitle,
body[data-admin-shell="on"] .subtitle,
body[data-admin-shell="on"] .note {
    color: var(--muted);
    font-size: var(--t-sm);
    line-height: 1.55;
    margin: 0 0 var(--s-3) 0;
}

body[data-admin-shell="on"] table {
    width: 100%;
    border-collapse: collapse;
    font-size: var(--t-sm);
}

body[data-admin-shell="on"] table th,
body[data-admin-shell="on"] table td {
    text-align: left;
    padding: var(--s-3) var(--s-2);
    border-bottom: 1px solid var(--hairline);
}

body[data-admin-shell="on"] table th {
    color: var(--muted);
    font-size: var(--t-xs);
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
}

body[data-admin-shell="on"] code {
    font-family: 'JetBrains Mono', ui-monospace, monospace;
    font-size: 12px;
    background: var(--hairline);
    padding: 1px 5px;
    border-radius: 3px;
    color: var(--ink);
}

body[data-admin-shell="on"] a {
    color: var(--accent);
    text-decoration: none;
}

body[data-admin-shell="on"] a:hover {
    text-decoration: underline;
}

body[data-admin-shell="on"] hr {
    border: 0;
    border-top: 1px solid var(--hairline);
    margin: var(--s-6) 0;
}

/* ================================================================
   DARK THEME (2026-07-18) — admin pages + every standalone page on
   these tokens adopt the main SPA dark palette so the whole product
   reads as ONE app. The token names stay; only their values flip
   under html[data-theme="dark"]. Values MIRROR app.css
   :root[data-theme="dark"] exactly.
   ================================================================ */
html[data-theme="dark"] body[data-admin-shell="on"] {
    --canvas:   #000000;      /* = main --bg  */
    --paper:    #16181C;      /* = main --pn  */
    --ink:      #E7E9EA;      /* = main --txt */
    --muted:    #9AA3B0;      /* = main --dim */
    --faint:    #2F3336;      /* = main --bdr */
    --hairline: #202327;      /* subtle dividers on black */
    --accent:   #4C8DFF;      /* = main --acc */
    --danger:   #F2566B;      /* = main --no  */
    --warn:     #F0B429;      /* = main --warn */
}

/* ======================================================================
   PR-UI-MODE (2026-07-30) — admin data tables in MOBILE mode
   ======================================================================
   Gated on html[data-ui-mode="mobile"] (set by ui-mode.js) so desktop is
   untouched. Safety net: any admin table becomes horizontally SCROLLABLE
   instead of forcing the page wider. Opt-in: add class="responsive-table"
   (with td[data-label="Col"]) to get the stacked-card layout. */
html[data-ui-mode="mobile"] body[data-admin-shell="on"] table:not(.responsive-table) {
    display: block;
    max-width: 100%;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
}
html[data-ui-mode="mobile"] table.responsive-table thead {
    position: absolute; width: 1px; height: 1px;
    overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap;
}
html[data-ui-mode="mobile"] table.responsive-table,
html[data-ui-mode="mobile"] table.responsive-table tbody,
html[data-ui-mode="mobile"] table.responsive-table tr,
html[data-ui-mode="mobile"] table.responsive-table td { display: block; width: 100%; }
html[data-ui-mode="mobile"] table.responsive-table tr {
    border: 1px solid var(--bdr, #d9dfe7);
    border-radius: 8px; margin-bottom: 10px; padding: 6px 10px;
}
html[data-ui-mode="mobile"] table.responsive-table td {
    border: none; padding: 4px 0;
    display: flex; justify-content: space-between; gap: 12px;
    text-align: right;
}
html[data-ui-mode="mobile"] table.responsive-table td::before {
    content: attr(data-label);
    font-weight: 600; color: var(--dim, #64748b); text-align: left;
}
html[data-ui-mode="mobile"] table.responsive-table td:not([data-label])::before { content: ""; }

/* ═══════════════════════════════════════════════════════════════════
   PR-ADMIN-P1 (2026-08-27) — the console joins the app.
   Appended as a cascade-final layer on purpose: overrides win without
   touching the 1,293 lines above.

   ALIASES → TOKENS. admin-shell.js injects /tokens.css; every admin
   alias points at the app token so ONE palette edit reaches both
   surfaces. Dark flips automatically via tokens.css — the old dark
   alias literals above in this file are overridden here too.
   (PR-ADMIN-R1, 2026-09-24: the topbar and rail restyles that followed
   this block are gone — the chrome is the SPA's own now, see the top of
   this file. Only the aliases and the ⌘K palette remain below.)
   ═══════════════════════════════════════════════════════════════════ */

body[data-admin-shell="on"],
html[data-theme="dark"] body[data-admin-shell="on"] {
    --canvas:   var(--bg, #F3F5F8);
    --paper:    var(--pn, #FFFFFF);
    --ink:      var(--txt, #1A222E);
    --muted:    var(--dim, #5A6573);
    --faint:    var(--bdr, #D9DFE7);
    --hairline: var(--bdr, #D9DFE7);
    --accent:   var(--acc, #2563EB);
    --danger:   var(--no, #D33A4B);
    /* PR-ADMIN-WARN-TOKEN (2026-09-05): `--warn` is NOT aliased, on purpose.
       Every other line here renames an app token onto its admin alias
       (--acc→--accent, --no→--danger). The app's amber is ALSO called
       `--warn`, so the alias read `--warn: var(--warn, #C77700)` — a custom
       property referencing itself. CSS calls that a cycle and makes the
       property invalid at computed-value time, so `var(--warn)` resolved to
       NOTHING everywhere in the console, and every rule using it fell back to
       transparent. Found by measuring: an amber status rail computed
       `background: rgba(0,0,0,0)` while the identical rule using --accent
       painted fine.
       Deleting the alias is the fix, not repairing it: tokens.css is injected
       by admin-shell.js and declares `--warn` on :root, so the value simply
       inherits — which is what the alias was trying to arrange — and it now
       flips for dark mode with the rest of the palette, which the literal
       fallback never did. */
}


/* ── ⌘K palette ── */
body[data-admin-shell="on"] .cmdk-overlay {
    position: fixed; inset: 0; z-index: 200;
    background: rgba(10, 14, 20, 0.45);
    display: flex; align-items: flex-start; justify-content: center;
    padding-top: 12vh;
}
body[data-admin-shell="on"] .cmdk-box {
    width: min(620px, 92vw);
    background: var(--pn, #FFFFFF);
    border: 1px solid var(--bdr, #D9DFE7);
    border-radius: var(--radius-lg, 16px);
    box-shadow: var(--shadow-4, 0 18px 50px rgba(0,0,0,.25));
    overflow: hidden;
}
body[data-admin-shell="on"] .cmdk-input {
    width: 100%; box-sizing: border-box;
    padding: 15px 18px;
    border: none; outline: none;
    background: transparent;
    color: var(--txt, #1A222E);
    font: 500 16px var(--ff-ui, Inter, sans-serif);
    border-bottom: 1px solid var(--bdr, #D9DFE7);
}
body[data-admin-shell="on"] .cmdk-list { max-height: 52vh; overflow-y: auto; padding: 6px; }
body[data-admin-shell="on"] .cmdk-row {
    display: grid;
    grid-template-columns: auto 1fr;
    column-gap: 12px;
    align-items: baseline;
    padding: 9px 12px;
    border-radius: var(--radius-sm, 6px);
    text-decoration: none;
    cursor: pointer;
}
body[data-admin-shell="on"] .cmdk-row.sel { background: var(--pn-h, #F0F3F7); }
body[data-admin-shell="on"] .cmdk-lbl { color: var(--txt, #1A222E); font: 600 14px var(--ff-ui, Inter, sans-serif); }
body[data-admin-shell="on"] .cmdk-grp { color: var(--dim, #5A6573); font: 500 11.5px var(--ff-mono, monospace); text-align: right; }
body[data-admin-shell="on"] .cmdk-desc { grid-column: 1 / -1; color: var(--dim, #5A6573); font-size: 12.5px; margin-top: 1px; }

/* ────────────────────────────────────────────────────────────────
   PR-SETUP-INLINE (2026-09-24): a console page inside the Setup hub's
   in-place panel (admin-shell.js sets html[data-embed]). No chrome; the
   panel's header carries the title and description, so the page's own
   h1 + .sub hide (an h1 carrying a live status pill stays). Transparent,
   so the panel's surface shows through; height is the content's, which
   the hub measures to size the frame.
   ──────────────────────────────────────────────────────────────── */
html[data-embed="1"], html[data-embed="1"] body { height: auto !important; min-height: 0 !important; }
/* overflow on <html> only: on <body> it makes body a scroll box, and a page's
   sticky save bar then sticks to nothing. */
html[data-embed="1"] { overflow-x: hidden; }
html[data-embed="1"] body[data-admin-shell="on"] { background: transparent; padding: 0; margin: 0; }
html[data-embed="1"] body[data-admin-shell="on"] .admin-main { padding: 18px 22px 22px; max-width: none; }
html[data-embed="1"] .page-head > .sub,
html[data-embed="1"] .page-head > h1:not(:has(*)) { display: none; }
html[data-embed="1"] .page-head { margin: 0; padding: 0; border: 0; min-height: 0; }
@media (max-width: 767px) {
    html[data-embed="1"] body[data-admin-shell="on"] .admin-main { padding: 14px 14px 18px; }
}

/* ────────────────────────────────────────────────────────────────
   PR-SETUP-PAGES (2026-09-24): two opt-in primitives for console pages.
   Chips: <select data-chips> (admin-shell.js draws them; the select hides).
   The .admin-chip class carries the "admin-" prefix the generic button rule
   skips, so these rules are the chips' whole look.
   Switch: <input type="checkbox" class="switch"> — an on/off switch that is
   still a checkbox to the page's code.
   ──────────────────────────────────────────────────────────────── */
body[data-admin-shell="on"] select.admin-chips-src { display: none !important; }
body[data-admin-shell="on"] .admin-chips { display: flex; flex-wrap: wrap; gap: 6px; }
body[data-admin-shell="on"] .admin-chip {
    display: inline-flex; align-items: center; min-height: 40px; padding: 0 14px;
    border: 1px solid var(--faint); border-radius: 999px; background: var(--paper); color: var(--ink);
    font: 500 13.5px var(--ff-ui, inherit); cursor: pointer; white-space: nowrap;
    transition: background 120ms ease, border-color 120ms ease, color 120ms ease;
}
body[data-admin-shell="on"] .admin-chip:hover { border-color: color-mix(in srgb, var(--accent) 45%, var(--faint)); }
body[data-admin-shell="on"] .admin-chip.on { background: color-mix(in srgb, var(--accent) 12%, var(--paper)); border-color: var(--accent); color: var(--accent); font-weight: 600; }
body[data-admin-shell="on"] .admin-chip:focus-visible { outline: 2px solid color-mix(in srgb, var(--accent) 70%, transparent); outline-offset: 2px; }
body[data-admin-shell="on"] .admin-chip:disabled { opacity: .5; cursor: not-allowed; }
body[data-admin-shell="on"] input[type="checkbox"].switch {
    -webkit-appearance: none; appearance: none; position: relative; flex: 0 0 auto;
    width: 44px; height: 26px; margin: 0; border-radius: 999px; cursor: pointer;
    background: color-mix(in srgb, var(--muted) 35%, var(--faint)); border: 0;
    transition: background 150ms ease;
}
body[data-admin-shell="on"] input[type="checkbox"].switch::before {
    content: ""; position: absolute; top: 3px; left: 3px; width: 20px; height: 20px; border-radius: 50%;
    background: var(--paper); box-shadow: 0 1px 3px color-mix(in srgb, var(--ink) 30%, transparent);
    transition: transform 150ms ease;
}
body[data-admin-shell="on"] input[type="checkbox"].switch:checked { background: var(--accent); }
body[data-admin-shell="on"] input[type="checkbox"].switch:checked::before { transform: translateX(18px); }
body[data-admin-shell="on"] input[type="checkbox"].switch:focus-visible { outline: 2px solid color-mix(in srgb, var(--accent) 70%, transparent); outline-offset: 2px; }
body[data-admin-shell="on"] input[type="checkbox"].switch:disabled { opacity: .5; cursor: not-allowed; }
@media (prefers-reduced-motion: reduce) {
    body[data-admin-shell="on"] input[type="checkbox"].switch, body[data-admin-shell="on"] input[type="checkbox"].switch::before, body[data-admin-shell="on"] .admin-chip { transition: none; }
}

/* ────────────────────────────────────────────────────────────────
   PR-SETUP-INLINE (2026-09-24): the in-place panel (/admin/inline-panel.js),
   used by the Setup and Inventory hubs. It grows open under a card's row
   (grid-template-rows 0fr -> 1fr). The close button carries "admin-" so the
   generic button rule leaves it alone.
   ──────────────────────────────────────────────────────────────── */
body[data-admin-shell="on"] .inline-panel { grid-column: 1 / -1; display: grid; grid-template-rows: 0fr; opacity: 0; transition: grid-template-rows .36s cubic-bezier(.22, 1, .36, 1), opacity .22s ease; scroll-margin-top: 84px; }
body[data-admin-shell="on"] .inline-panel.is-open { grid-template-rows: 1fr; opacity: 1; }
body[data-admin-shell="on"] .inline-panel > .ip-inner { min-height: 0; overflow: hidden; border: 1px solid color-mix(in srgb, var(--accent) 40%, var(--faint)); border-radius: 14px; background: var(--canvas); box-shadow: var(--shadow-3, 0 6px 18px rgba(0,0,0,.08)); }
body[data-admin-shell="on"] .ip-head { display: flex; align-items: center; gap: 12px; padding: 12px 14px 12px 20px; background: var(--paper); border-bottom: 1px solid var(--faint); }
body[data-admin-shell="on"] .ip-titles { flex: 1 1 auto; min-width: 0; }
body[data-admin-shell="on"] .ip-titles h3 { margin: 0; font: 700 17px/1.25 var(--ff-ui, inherit); color: var(--ink); letter-spacing: -.01em; }
body[data-admin-shell="on"] .ip-titles p { margin: 2px 0 0; font-size: 12.5px; line-height: 1.45; color: var(--muted); }
body[data-admin-shell="on"] .ip-full { flex: 0 0 auto; display: inline-flex; align-items: center; gap: 6px; min-height: 40px; padding: 0 12px; border-radius: 9px; font: 600 13px var(--ff-ui, inherit); color: var(--accent); text-decoration: none; white-space: nowrap; }
body[data-admin-shell="on"] .ip-full:hover { background: color-mix(in srgb, var(--accent) 10%, transparent); text-decoration: none; }
body[data-admin-shell="on"] .ip-full svg { width: 15px; height: 15px; }
body[data-admin-shell="on"] .admin-ip-close { flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center; width: 44px; height: 44px; min-height: 44px; padding: 0; border: 1px solid var(--faint); border-radius: 10px; background: var(--canvas); color: var(--muted); cursor: pointer; }
body[data-admin-shell="on"] .admin-ip-close:hover { color: var(--ink); border-color: var(--muted); background: var(--paper); }
body[data-admin-shell="on"] .admin-ip-close svg { width: 18px; height: 18px; }
body[data-admin-shell="on"] .ip-body { position: relative; }
body[data-admin-shell="on"] .ip-body iframe { display: block; width: 100%; height: 320px; border: 0; background: transparent; transition: height .24s cubic-bezier(.22, 1, .36, 1); }
body[data-admin-shell="on"] .ip-loading { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; gap: 10px; color: var(--muted); font-size: 13px; pointer-events: none; }
body[data-admin-shell="on"] .ip-loading[hidden] { display: none; }
body[data-admin-shell="on"] .ip-loading::before { content: ""; width: 16px; height: 16px; border-radius: 50%; border: 2px solid color-mix(in srgb, var(--accent) 25%, transparent); border-top-color: var(--accent); animation: ip-spin .8s linear infinite; }
@keyframes ip-spin { to { transform: rotate(360deg); } }
@media (max-width: 640px) { body[data-admin-shell="on"] .ip-head { flex-wrap: wrap; padding: 10px 10px 10px 14px; } body[data-admin-shell="on"] .ip-titles { flex-basis: calc(100% - 60px); } body[data-admin-shell="on"] .ip-full { order: 3; } }
@media (prefers-reduced-motion: reduce) { body[data-admin-shell="on"] .inline-panel, body[data-admin-shell="on"] .ip-body iframe { transition: none; } body[data-admin-shell="on"] .ip-loading::before { animation: none; } }

/* data-own-buttons (2026-09-24): the generic button rule skips every button
   inside an element carrying this attribute (its eight selector chains end in
   :not([data-own-buttons] *)). For a page whose buttons are fully styled by the
   page itself (the setup wizard's rail, picks, chips, scope pills): at (0,10,2)
   the generic rule turned its dotted step rail into clipped boxes and laid each
   pick's title beside its description. Buttons with .btn keep the shared look
   (the .btn half of the rule still matches them). */

/* ────────────────────────────────────────────────────────────────
   PR-FLOW-1 (2026-09-24, owner: "go though every page and make it all flow
   together so no page looks out of place or has a jaring jumpp"). Measured
   on all 57 pages first: a console page painted its content at the top of a
   bare window before its chrome existed (admin-shell.js, then admin-nav.js,
   arrive after the HTML), then the bar and workspace arrived and pushed it
   56 px down (Pricing's layout shift scored 0.98); the title sat in six
   places at five sizes; a page without a scrollbar was 15 px wider than one
   with; single text boxes ran 1,377 px wide.
   ──────────────────────────────────────────────────────────────── */
/* 1. Nothing paints before its chrome. The page lays out hidden until
   admin-shell.js mounts (it adds .admin-body) and then arrives inside the bar
   and the workspace. Should the script never run, it shows after 2.5 s. */
body[data-admin-shell="on"]:not(.admin-body) > * { visibility: hidden; animation: ascut-reveal 0s linear 2.5s forwards; }
@keyframes ascut-reveal { to { visibility: visible; } }
@media (prefers-reduced-motion: no-preference) {
    body[data-admin-shell="on"].admin-body:not(.embed-body) .admin-main { animation: ascut-page-in .18s ease-out both; }
    @keyframes ascut-page-in { from { opacity: 0; } to { opacity: 1; } }
}
/* 2. One content width on every page: the workspace always keeps the
   scrollbar's lane, so a short page is not 15 px wider than a long one. */
body[data-admin-shell="on"] #app-workspace { scrollbar-gutter: stable; }
/* 3. The band on every page (admin-shell.js bandify): the hub band's own
   measurements, so the title sits where Setup's and Inventory's sit. */
body[data-admin-shell="on"] .studio-band[data-area="inventory"] { --studio: var(--acc-inventory); }
body[data-admin-shell="on"] .studio-band[data-area="floor"] { --studio: var(--acc-hardware); }
body[data-admin-shell="on"] .page-head.page-band { margin: 0 0 18px; }
body[data-admin-shell="on"] .page-band > .sb-l { flex: 1 1 440px; min-width: 0; }
body[data-admin-shell="on"] .page-band > .sb-r:empty { display: none; }
body[data-admin-shell="on"] .page-head.page-band h1.sb-title { display: flex; align-items: center; flex-wrap: wrap; gap: 6px 12px; font: 800 30px/1.06 var(--ff-ui); letter-spacing: -0.025em; color: inherit; margin: 0; }
body[data-admin-shell="on"] .page-head.page-band .sub { color: inherit; opacity: .88; font: 500 13.5px/1.5 var(--ff-ui); margin: 8px 0 0; max-width: 80ch; }
body[data-admin-shell="on"] .page-band a { color: inherit; text-decoration: underline; text-underline-offset: 2px; }
body[data-admin-shell="on"] .page-band h1 .pill { font-size: 11px; font-weight: 700; letter-spacing: .04em; color: inherit; background: color-mix(in srgb, currentColor 20%, transparent); border: 1px solid color-mix(in srgb, currentColor 42%, transparent); }
@media (max-width: 720px) {
    body[data-admin-shell="on"] .page-head.page-band h1.sb-title { font-size: 24px; }
}
/* 4. A text box or a picker is about a sentence wide: a single field ran the
   whole page (Email settings, Trusted HTTPS, QuickBooks, Areas). Fields in
   tables, grids and toolbars were already sized by their cells. */
body[data-admin-shell="on"] .card :is(input:is([type="text"], [type="email"], [type="url"], [type="password"], [type="tel"], [type="search"], :not([type])), select, textarea):not(table *) { max-width: 640px; }

/* ═══════════════════════════════════════════════════════════════════
   PR-ADMIN-LOOK (2026-10-01) — console cards read like the app's.
   Measured on Station lists before this block:
     - shell.css `.card` (the SPA's clickable tile) is a flex COLUMN with
       cursor:pointer, a hover tint and overflow:hidden. Every console card
       inherited all four: a lone button stretched the whole card and read
       as a text box ("Open the cutlist designer"), form cards lit up and
       showed a hand cursor, and popovers inside a card were clipped.
     - `.card-head` was 12px grey capitals: the card's name was the
       quietest thing on it. Home and the Setup hub name a card in white
       sentence case.
     - `--surface` was never defined, so every `var(--surface, #fff)` was
       white in the dark theme (the preview frame, template tiles, chips).
     - checkbox and radio labels inherited the field-label capitals
       ("MAKE SEVERAL AT ONCE", "MATERIAL").
   The band stays: it is the console's own mark.
   ═══════════════════════════════════════════════════════════════════ */
body[data-admin-shell="on"] {
    --surface:   var(--pn);
    --surface-2: color-mix(in srgb, var(--txt) 6%, transparent);
}
body[data-admin-shell="on"] .card {
    padding: var(--s-5);
    margin-bottom: 18px;
    cursor: auto;
    overflow: visible;
}
/* A button that is a card's direct child keeps its own width. */
body[data-admin-shell="on"] .card > :is(.btn, button, a.btn) { align-self: flex-start; }
body[data-admin-shell="on"] .card-head {
    color: var(--ink);
    font-size: var(--fs-lg, 17px);
    font-weight: 600;
    letter-spacing: -0.005em;
    line-height: 1.35;
    text-transform: none;
    margin: 0 0 var(--s-3) 0;
}
/* A card whose head sits over a big .lead sentence ("Server" over
   "Running.") keeps the head as a small label above it. */
body[data-admin-shell="on"] .card-head:has(+ .lead) {
    color: var(--muted);
    font-size: var(--t-xs);
    letter-spacing: 0.08em;
    text-transform: uppercase;
    margin-bottom: var(--s-2);
}
body[data-admin-shell="on"] .card-head + p,
body[data-admin-shell="on"] .card-head + .muted-note { margin-top: calc(-1 * var(--s-1)); }
/* (0,0,1) like the label rule above and later, so it wins over that; a
   page's own label rule (a class or more) still wins over this. */
:where(body[data-admin-shell="on"]) label:where(:has(> input:is([type="checkbox"], [type="radio"]))) {
    display: flex;
    align-items: center;
    gap: var(--s-2);
    font-size: var(--t-sm);
    font-weight: 500;
    letter-spacing: 0;
    text-transform: none;
    color: var(--ink);
}
