  /* IBM Plex (OFL, static/fonts/OFL.txt) — IBM's official Latin-1 split
     woff2s, which keep the `zero` feature the slashed-zero tables use. */
  @font-face { font-family: "IBM Plex Sans"; font-weight: 400; font-display: swap;
               src: url(/static/fonts/plex-sans-400.woff2) format("woff2"); }
  @font-face { font-family: "IBM Plex Sans"; font-weight: 400; font-style: italic;
               font-display: swap;
               src: url(/static/fonts/plex-sans-400-italic.woff2) format("woff2"); }
  @font-face { font-family: "IBM Plex Sans"; font-weight: 500; font-display: swap;
               src: url(/static/fonts/plex-sans-500.woff2) format("woff2"); }
  @font-face { font-family: "IBM Plex Sans"; font-weight: 600; font-display: swap;
               src: url(/static/fonts/plex-sans-600.woff2) format("woff2"); }
  @font-face { font-family: "IBM Plex Mono"; font-weight: 400; font-display: swap;
               src: url(/static/fonts/plex-mono-400.woff2) format("woff2"); }
  @font-face { font-family: "IBM Plex Mono"; font-weight: 500; font-display: swap;
               src: url(/static/fonts/plex-mono-500.woff2) format("woff2"); }
  :root {
    /* "Ledger" (key: graphite) — a ledger of quantities over time. Cool
       paper canvas, off-white sheets, near-black ink; the one chromatic
       chrome colour is ledger blue, spent on "now" (the current-month rule),
       the active tab and focus. R/A/G + tags stay the data language. */
    --font: "IBM Plex Sans", -apple-system, BlinkMacSystemFont, "Segoe UI",
            Roboto, sans-serif;
    --font-mono: "IBM Plex Mono", ui-monospace, "SF Mono", Menlo, monospace;
    --ink: #14171c; --muted: #5b6169; --line: #d9dce0; --bg: #eef0f2;
    --surface: #fbfbfa;       /* cards, tables, popovers, inputs */
    --accent: #2a57c9; --accent-deep: #1f44a3;
    --focus: var(--accent);
    --accent-wash: #e6edfb;   /* row hover — visible against the stripe */
    --accent-tint: #d3def7;   /* .saving cells — blue, never the dirty amber */
    --th-bg: #e4e7eb;         /* table headers, month separators */
    --header-ink: #1b1f26;    /* header top tier */
    --stripe: #f4f5f6;        /* zebra rows */
    --red: #b91c1c; --red-deep: #991b1b; --red-bg: #fee2e2;
    --amber: #92400e; --amber-bg: #fef3c7;
    --green: #166534; --green-bg: #dcfce7;
    /* Tag palette (vocab.PALETTE keys) — data language like R/A/G, so it
       lives here in :root and never in a theme override block. */
    --tag-slate: #334155; --tag-slate-bg: #e2e8f0;
    --tag-amber: #92400e; --tag-amber-bg: #fef3c7;
    --tag-green: #166534; --tag-green-bg: #dcfce7;
    --tag-sky: #075985; --tag-sky-bg: #e0f2fe;
    --tag-violet: #5b21b6; --tag-violet-bg: #ede9fe;
    --tag-rose: #9f1239; --tag-rose-bg: #ffe4e6;
    --tag-teal: #0f766e; --tag-teal-bg: #ccfbf1;
    --tag-orange: #9a3412; --tag-orange-bg: #ffedd5;
    --header-fg: #d5d9df;        /* h-top text */
    --header-dim: #a4abb5;       /* userbar */
    --header-link: #c9ced6;
    --header-underline: #7d9be6; /* active userbar link — accent lifted for the dark bar */
    --net: #e9ecef;              /* td.net */
    --zero-ink: #5c6167;         /* td.zero — dimmed, >=4.5:1 on every row fill incl. red/amber warn rows (tests/test_theme.py) */
    --icon-box: #8b95a3;         /* app-icon crates */
    --input-border: #80868f;     /* form fields — 3:1 on surface, stripe, bg */
    --dirty: var(--amber-bg);    /* typed-but-unsaved cell (bulk editors) */
    --shadow-1: 0 1px 2px rgba(15,23,42,.05);     /* resting card/table */
    --shadow-2: 0 3px 10px rgba(15,23,42,.1);     /* lifted card (hover) */
    --shadow-pop: 0 6px 18px rgba(15,23,42,.15);  /* popovers, dialogs */
    --shadow-pin: 8px 0 12px -8px rgba(15,23,42,.3); /* pinned-column edge */
    --fs-xs: 12px; --fs-sm: 12px; --fs-md: 13px; --fs-base: 14px;
    --fs-lg: 16px; --fs-xl: 20px;
    /* Sticky geometry: *-min = no-JS fallback widths of frozen columns (table-enhance.js
     measures real ones into --col1-w/--col2-w/--col3-w); others = pinned chrome heights. */
  --col1-min: 110px; --col2-min: 220px; --col3-min: 90px;
  --editbar-h: 56px; --thead-h: 64px; --tfoot-h: 40px;
  --hit-min: 24px;   /* WCAG 2.2 target size; 44px on coarse pointers (below) */
  --s1: 4px; --s2: 8px; --s3: 12px; --s4: 16px; --s5: 24px;  /* spacing scale */
  --r-sm: 4px; --r-md: 6px; --r-lg: 10px; --r-pill: 999px;
  }
  /* Theme overrides recolor chrome ONLY — R/A/G badges and the dev
     banner are data language and never change. */
  [data-theme="evergreen"] {
    --ink: #1a211e; --muted: #626966; --line: #dfe2e0; --bg: #fbfdfc; --surface: #fff;
    --accent: #0f5f63; --accent-deep: #0b4a4d; --focus: var(--accent);
    --accent-wash: #e0f8f3; --accent-tint: #ccf3ea;
    --th-bg: #eef1f0; --header-ink: #0d3d38; --stripe: #f7f9f8;
    --header-fg: #e7f0ea; --header-dim: #b9cec5; --header-link: #dbe8e1;
    --header-underline: #7fb3a5;
    --net: #e7edeb; --zero-ink: #5f6a65; --icon-box: #b08968;
    --input-border: #858f8a;
  }
  [data-theme="kraft"] {
    --ink: #1c1917; --muted: #6d6661; --line: #e7e5e4; --bg: #fafaf9; --surface: #fff;
    --accent: #9a3412; --accent-deep: #7c2d12; --focus: var(--accent);
    --accent-wash: #fff7ed; --accent-tint: #ffedd5;
    --th-bg: #f5f5f4; --header-ink: #1c1917; --stripe: #fafaf9;
    --header-fg: #e7e5e4; --header-dim: #a8a29e; --header-link: #d6d3d1;
    --header-underline: #b45309;
    --net: #f0efed; --zero-ink: #6c6661; --icon-box: #b45309;
    --input-border: #948b85;
  }
  [data-theme="lavender"] {
    --ink: #211f26; --muted: #65636d; --line: #e3dfe6; --bg: #fdfcfd; --surface: #fff;
    --accent: #6550b9; --accent-deep: #2f265f; --focus: var(--accent);
    --accent-wash: #f4f0fe; --accent-tint: #ebe4ff;
    --th-bg: #f2eff3; --header-ink: #2f265f; --stripe: #faf9fb;
    --header-fg: #e6e1f5; --header-dim: #b3abd1; --header-link: #d9d2ee;
    --header-underline: #9b8ce0;
    --net: #eeeaf2; --zero-ink: #6a6477; --icon-box: #9a86d9;
    --input-border: #8f8a9a;
  }
  * { box-sizing: border-box; }
  button { font-family: inherit; }   /* UA buttons ignore the body font */
  body { margin: 0; font: var(--fs-base)/1.45 var(--font); color: var(--ink); background: var(--bg); }
  .skip { position: absolute; left: -9999px; top: 0; z-index: 30; background: var(--surface);
          color: var(--accent); padding: 8px 14px; border-radius: 0 0 var(--r-md) 0;
          font-weight: 600; }
  .skip:focus { left: 0; }
  header { background: var(--surface); border-bottom: 1px solid var(--line);
           position: sticky; top: 0; z-index: 10; }
  .h-top { display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
           padding: 7px 20px; background: var(--header-ink); color: var(--header-fg); }
  .h-top .brand { font-weight: 700; color: #fff; letter-spacing: -0.01em; }
  .h-top .brand { display: flex; align-items: center; gap: 8px; }
  .h-top .userbar { margin-left: auto; display: flex; align-items: center;
                    gap: 14px; font-size: var(--fs-md); color: var(--header-dim); }
  .h-top .userbar a, .h-top .userbar .linkbtn { color: var(--header-link); text-decoration: none;
                      border-bottom: 2px solid transparent; }
  .h-top .userbar .linkbtn { background: none; border-width: 0 0 2px; padding: 0;
                             font: inherit; cursor: pointer; white-space: nowrap; }
  .h-top .userbar a:hover, .h-top .userbar .linkbtn:hover { color: #fff; }
  .h-top .userbar a.active { color: #fff; border-bottom-color: var(--header-underline); }
  /* Admin links fold into one <details> menu. */
  .adminmenu { position: relative; }
  .adminmenu summary { cursor: pointer; color: var(--header-link);
                       border-bottom: 2px solid transparent; }
  .adminmenu summary:hover { color: #fff; }
  .adminmenu summary.active { color: #fff; border-bottom-color: var(--header-underline); }
  .adminmenu .menu { position: absolute; right: 0; top: calc(100% + 6px); z-index: 20;
                     display: flex; flex-direction: column; min-width: 150px;
                     padding: 4px 0; background: var(--surface);
                     border: 1px solid var(--line); border-radius: var(--r-md);
                     box-shadow: var(--shadow-pop); }
  .h-top .adminmenu .menu a { color: var(--ink); padding: 6px 14px;
                              border-bottom: 0; }
  .h-top .adminmenu .menu a:hover, .h-top .adminmenu .menu a.active {
    color: var(--ink); background: var(--accent-wash); }
  .h-top .adminmenu .menu :focus-visible { outline-color: var(--focus);
                                           outline-offset: -2px; }
  .adminmenu .ver { color: var(--muted); font-size: var(--fs-xs);
                    padding: 6px 14px 2px; border-top: 1px solid var(--line);
                    margin-top: 4px; }
  /* Always-on edge fade hints that the tab strip scrolls when narrow. */
  nav.tabs { display: flex; align-items: center; overflow-x: auto;
             scrollbar-width: none; padding: 0 12px; scroll-padding-inline: 24px;
             mask-image: linear-gradient(to right, transparent, #000 12px,
                                         #000 calc(100% - 24px), transparent); }
  nav.tabs::-webkit-scrollbar { display: none; }
  nav.tabs a { flex: none; }
  .navgrp { display: flex; flex: none; align-items: center; }
  .navgrp + .navgrp, a.nav + .navgrp { border-left: 1px solid var(--line);
                                       margin-left: 6px; padding-left: 6px; }
  .navlabel { color: var(--muted); font-size: var(--fs-xs); padding: 0 4px; }
  header a.nav { color: var(--muted); text-decoration: none; padding: 12px 10px;
                 border-bottom: 2px solid transparent;
                 transition: color .15s ease, border-bottom-color .15s ease; }
  header a.nav:hover { color: var(--ink); }
  header a.nav.active { color: var(--accent); border-bottom-color: var(--accent); }
  @media (max-width: 700px) {
    header { position: static; }   /* give small screens their viewport back */
  }
  main { padding: 20px; max-width: 100%; }
  h1 { font-size: var(--fs-xl); margin: 0 0 4px; }
  h2 { font-size: var(--fs-base); font-weight: 600; margin: var(--s5) 0 var(--s2); }
  h1, h2 { text-wrap: balance; }
  .pagehead { display: flex; justify-content: space-between;
              align-items: center; gap: 12px; flex-wrap: wrap; }
  .sechead { display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap; }
  .sechead h2 { margin-right: auto; }
  .sub { color: var(--muted); margin: 0 0 16px; }
  .sub, .note { max-width: 76ch; }
  div.sub { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
  .cards { display: flex; gap: 12px; flex-wrap: wrap; margin: 16px 0; }
  .card { background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-lg);
          padding: 12px 16px; min-width: 150px;
          box-shadow: var(--shadow-1); }
  .card .k { color: var(--muted); font-size: var(--fs-sm); text-transform: uppercase;
             letter-spacing: .04em; }
  .card .v { font-size: var(--fs-xl); font-weight: 600; margin-top: 2px;
             font-variant-numeric: tabular-nums; }  /* KPIs live-update without reflow */
  .cardactions { margin-top: var(--s2); display: flex; gap: var(--s2); flex-wrap: wrap; }
  a.card { display: block; color: inherit; text-decoration: none;
           transition: border-color .15s ease, box-shadow .15s ease,
                       transform .15s ease; }
  a.card:hover { border-color: var(--accent); transform: translateY(-1px);
                 box-shadow: var(--shadow-2); }
  .tablewrap { overflow-x: auto; background: var(--surface); border: 1px solid var(--line);
               border-radius: var(--r-lg); box-shadow: var(--shadow-1);
               scrollbar-gutter: stable;  /* no column squeeze when the
                                             vertical scrollbar appears */
               scrollbar-width: thin; scrollbar-color: var(--input-border) transparent; }
  .tablewrap::-webkit-scrollbar { width: 8px; height: 8px; }
  .tablewrap::-webkit-scrollbar-thumb { background: var(--input-border);
                                        border-radius: var(--r-pill); }
  .tablewrap::-webkit-scrollbar-track { background: transparent; }
  table { border-collapse: collapse; width: 100%;
          font-variant-numeric: tabular-nums slashed-zero; }
  th, td { padding: 6px 8px; border-bottom: 1px solid var(--line);
           white-space: nowrap; text-align: left; }
  th { position: sticky; top: 0; background: var(--th-bg); font-size: var(--fs-sm); z-index: 2; }
  thead tr:first-child th { top: 0; height: 32px; }
  thead tr:nth-child(2) th { top: 32px; }
  th.group { text-align: center; }
  th.wrap { white-space: normal; max-width: 90px; }
  td.num, th.num { text-align: right; font-variant-numeric: tabular-nums slashed-zero; }
  /* "of" keeps stripes alternating over the *visible* rows when filtered. */
  /* :where() keeps the "of" clause at zero specificity so tr:hover (below,
     equal specificity, later in source) can still repaint striped rows. */
  tbody tr:nth-child(even of :where(:not([hidden], .off))) td { background: var(--stripe); }
  tbody tr td.net { background: var(--net); }
  /* Sits between .net and :hover on purpose — same specificity as both, so
     a negative net cell still reads red, and hover still repaints it. */
  tbody tr td.neg { color: var(--red); font-weight: 600;
                    background: var(--red-bg); }
  /* Coverage-backfill progress bar (Sales History + Financials refunds). */
  .backfill { display: flex; align-items: center; gap: 10px; margin: -8px 0 14px;
              max-width: 480px; }
  .backfill .track { flex: 1; height: 6px; border-radius: var(--r-pill);
                     background: var(--th-bg); overflow: hidden; }
  .backfill .fill { height: 100%; border-radius: var(--r-pill); background: var(--accent);
                    transform-origin: left; transition: transform .6s ease; }
  .backfill .pct { font-size: var(--fs-sm); color: var(--muted);
                   font-variant-numeric: tabular-nums; white-space: nowrap; }
  /* Stock Cover row tints — after the stripe rule (same specificity, later
     wins) and before :hover so hover still repaints. */
  tbody tr.warn-red td { background: var(--red-bg); }
  tbody tr.warn-yellow td { background: var(--amber-bg); }
  tbody tr:hover td { background: var(--accent-wash); }
  .mstart { border-left: 1px solid var(--line); }
  td.zero { color: var(--zero-ink); }
  .fc { font-style: italic; }   /* forecast figures beside actuals */
  td.sku { font-family: var(--font-mono);
           font-size: var(--fs-sm); }
  td.notes { white-space: normal; max-width: 320px; overflow-wrap: anywhere; }
  td.wrapcol { white-space: normal; max-width: 32ch; overflow-wrap: anywhere; }  /* name / rule columns */
  td.rowtotal { font-weight: 600; }
  tbody tr.grandtotal td { font-weight: 600; border-top: 1px solid var(--line); }
  .badge { display: inline-block; border-radius: var(--r-pill); padding: 1px 9px;
           font-size: var(--fs-sm); font-weight: 600; }
  .badge.CRITICAL { color: var(--red); background: var(--red-bg); }
  .badge.WATCH { color: var(--amber); background: var(--amber-bg); }
  .badge.ONTRACK { color: var(--green); background: var(--green-bg); }
  .badge.plain { color: var(--muted); background: var(--bg);
                 border: 1px solid var(--line); }
  .badge.tag-slate { color: var(--tag-slate); background: var(--tag-slate-bg); }
  .badge.tag-amber { color: var(--tag-amber); background: var(--tag-amber-bg); }
  .badge.tag-green { color: var(--tag-green); background: var(--tag-green-bg); }
  .badge.tag-sky { color: var(--tag-sky); background: var(--tag-sky-bg); }
  .badge.tag-violet { color: var(--tag-violet); background: var(--tag-violet-bg); }
  .badge.tag-rose { color: var(--tag-rose); background: var(--tag-rose-bg); }
  .badge.tag-teal { color: var(--tag-teal); background: var(--tag-teal-bg); }
  .badge.tag-orange { color: var(--tag-orange); background: var(--tag-orange-bg); }
  /* Swatch radios (Lists panel tag colors): the input is visually hidden,
     the badge chip IS the control — reuses the palette classes, so the
     checked ring tracks the swatch via currentColor. */
  .swatches { display: inline-flex; gap: 4px; align-items: center;
              vertical-align: middle; }
  .swatches label { cursor: pointer; }
  .swatches input { position: absolute; opacity: 0; }
  .swatches .badge { width: 20px; height: 20px; padding: 0;
                     box-sizing: border-box; border: 2px solid currentColor;
                     border-radius: var(--r-md); opacity: .55; }
  .swatches label:hover .badge { opacity: .85; }
  .swatches input:checked + .badge { opacity: 1;
                                     outline: 2px solid currentColor;
                                     outline-offset: 1px; }
  .swatches input:focus-visible + .badge { outline: 2px solid var(--focus);
                                           outline-offset: 1px; }
  td.tagcell .badge { margin-right: 3px; }
  button.tagpick { border: 1px solid var(--line); background: var(--surface);
                   color: var(--muted); border-radius: var(--r-pill); font-size: var(--fs-xs);
                   padding: 0 7px; cursor: pointer; }
  button.tagpick:hover { color: var(--accent); border-color: var(--accent); }
  /* Tag picker popover: ships inside the cell (checked = saved state) and
     is re-parented to <body> on open; form="skuform" keeps it submitting. */
  .tagpop { position: fixed; z-index: 25; background: var(--surface);
            border: 1px solid var(--line); border-radius: var(--r-lg);
            box-shadow: var(--shadow-pop); padding: 8px 10px;
            display: flex; flex-direction: column; gap: 6px;
            max-height: 320px; overflow-y: auto; overscroll-behavior: contain; }
  .tagpop[hidden] { display: none; }
  .tagpop label { display: flex; align-items: center; gap: 6px;
                  font-size: var(--fs-md); cursor: pointer; }
  .ok { color: var(--muted); font-size: var(--fs-sm); }
  /* Pinned cells need an opaque fill, but at :where() (zero) specificity
     so th, stripe, hover and every cell state (.dirty/.neg/.now/…) still
     paint over it — position/z-index/shadow keep full specificity. */
  :where(.sticky-col td:first-child,
         .sticky-col2 tr:not(.totals) td:nth-child(2),
         .sticky-col3 tr:not(.totals) td:nth-child(3)) { background: var(--surface); }
  .sticky-col th:first-child, .sticky-col td:first-child {
    position: sticky; left: 0; z-index: 1; box-shadow: var(--shadow-pin); }
  .sticky-col th:first-child { z-index: 3; }
  /* Second header row's first th is a data header (US / On Hand / SS %),
     not the row-spanned SKU column — don't pin it to the left edge. */
  .sticky-col thead tr:nth-child(2) th:first-child { left: auto; z-index: 2; }
  .sticky-col2 thead tr:first-child th:first-child,
  .sticky-col2 tr:not(.totals) td:first-child { width: var(--col1-min); min-width: var(--col1-min); }
  .sticky-col2 tr:not(.totals) td:nth-child(2),
  .sticky-col2 thead tr:first-child th:nth-child(2) {
    position: sticky; left: var(--col1-w, var(--col1-min)); z-index: 1;
    box-shadow: 2px 0 0 var(--line), var(--shadow-pin);
    max-width: var(--col2-min); overflow: hidden; text-overflow: ellipsis; }
  .sticky-col2 thead tr:first-child th:nth-child(2) { z-index: 3; }
  /* Third frozen column (the forecast grid's horizon total). Needs col 2 at a
     fixed width so col 3 can pin at col1 + col2. --col1-w/--col2-w are
     measured and set by table-enhance.js (col 1 is content-sized — long SKU
     codes stretch it past any declared width); the fallbacks keep no-JS. */
  .sticky-col3 thead tr:first-child th:nth-child(2),
  .sticky-col3 tr:not(.totals) td:nth-child(2) {
    width: var(--col2-min); min-width: var(--col2-min); }
  .sticky-col3 thead tr:first-child th:nth-child(3),
  .sticky-col3 tr:not(.totals) td:nth-child(3) {
    position: sticky; left: calc(var(--col1-w, var(--col1-min)) + var(--col2-w, var(--col2-min)));
    z-index: 1; box-shadow: 2px 0 0 var(--line), var(--shadow-pin); }
  .sticky-col3 thead tr:first-child th:nth-child(3) { z-index: 3; }
  /* Sortable headers + per-column filter popover (see _table_enhance.html). */
  /* Machine-written column/section marker: a quiet uppercase pill. */
  .pulled { display: inline-block; margin-left: 5px; padding: 0 5px;
    font-size: var(--fs-xs); font-weight: 600; letter-spacing: .05em;
    text-transform: uppercase; color: var(--muted); background: var(--surface);
    border: 1px solid var(--line); border-radius: var(--r-pill);
    vertical-align: 1px; cursor: help; }
  /* Sync-in-flight feedback: .busy on the clicked button spins a ring;
     body.syncing sweeps an indeterminate bar across the top edge. */
  .btn.busy::before { content: ""; display: inline-block; width: 11px;
    height: 11px; border: 2px solid rgba(255,255,255,.35);
    border-top-color: #fff; border-radius: 50%; margin-right: 7px;
    vertical-align: -2px; animation: spin .7s linear infinite; }
  @keyframes spin { to { transform: rotate(360deg); } }
  body.syncing::after { content: ""; position: fixed; top: 0; left: 0;
    width: 40vw; height: 3px; z-index: 40; pointer-events: none;
    background: linear-gradient(90deg, transparent, #fff, transparent);
    filter: drop-shadow(0 1px 1px rgba(0,0,0,.45));
    animation: sweep 1.2s linear infinite; }
  @keyframes sweep { from { transform: translateX(-40vw); }
                     to { transform: translateX(100vw); } }
  /* Channel/country marks in table headers — brand constants. */
  svg.ci { vertical-align: -3.5px; }
  svg.fl { vertical-align: -2px; }
  th.group svg.ci { vertical-align: -3px; }
  th.sortth { cursor: pointer; transition: box-shadow .15s ease; }
  /* Inset shadow tints without replacing the sticky header's background. */
  th.sortth:hover { box-shadow: inset 0 0 0 100px rgba(0,0,0,.05); }
  /* Unsorted arrow appears only on hover/focus; the sorted one stays. */
  .sortind { opacity: 0; font-size: var(--fs-xs); margin-left: 3px; }
  th.sortth:hover .sortind, .sortbtn:focus-visible .sortind { opacity: .55; }
  /* Sort control is a real <button> inside the th — reset to look like text. */
  .sortbtn { border: 0; background: none; padding: 0; font: inherit; color: inherit;
             text-align: inherit; cursor: pointer; }
  th[aria-sort] .sortind { opacity: 1; color: var(--accent); }
  button.cf { border: 0; background: none; font: inherit; font-size: var(--fs-xs);
              color: var(--muted); cursor: pointer; padding: 0 2px; }
  button.cf:hover, button.cf:focus-visible, button.cf.on { color: var(--accent); }
  button.cf.on::after { content: "●"; font-size: 8px; /* glyph, not text */ vertical-align: super; }
  .cfpop[hidden] { display: none; }
  button.cf svg { vertical-align: -1px; }
  .cfpop { position: fixed; z-index: 25; background: var(--surface); font-size: var(--fs-md);
           color: var(--muted); border: 1px solid var(--line); border-radius: var(--r-lg);
           box-shadow: var(--shadow-pop); padding: 8px 10px;
           display: flex; gap: 8px; align-items: center; }
  .cfpop input { width: 88px; padding: 4px 6px; font-size: var(--fs-md); }
  /* Header "manage this vocabulary" buttons (SKU editor, edit mode) — same
     size/affordance language as button.cf above, own icon (a list, not a
     funnel) since it opens a CRUD popover, not a column filter. */
  button.lists { border: 0; background: none; font: inherit; font-size: var(--fs-xs);
                color: var(--muted); cursor: pointer; padding: 0 2px; }
  button.lists:hover, button.lists:focus-visible { color: var(--accent); }
  button.lists svg { vertical-align: -1px; }
  .listpop[hidden] { display: none; }
  .listpop { position: fixed; z-index: 25; background: var(--surface); font-size: var(--fs-md);
             color: var(--muted); border: 1px solid var(--line); border-radius: var(--r-lg);
             box-shadow: var(--shadow-pop); padding: 10px 12px;
             max-width: 380px; overscroll-behavior: contain; }
  .listpop table { font-size: var(--fs-md); }
  .listpop td { padding: 3px 4px; }
  .listmsg { color: var(--red); font-size: var(--fs-sm); margin: 0 0 6px; }
  .listmsg[hidden] { display: none; }
  dialog { border: 1px solid var(--line); border-radius: var(--r-lg);
           box-shadow: var(--shadow-pop); padding: 18px 20px; }
  dialog::backdrop { background: rgba(0,0,0,.35); }   /* neutral, every theme */
  dialog h2 { margin: 0 0 12px; font-size: var(--fs-lg); }
  .note { color: var(--muted); font-size: var(--fs-md); margin: 10px 0; }
  .filterbar { display: flex; align-items: center; gap: var(--s2); flex-wrap: wrap;
  margin: 0 0 var(--s2); }
  .filterbar select { padding: 5px 7px; font-size: var(--fs-md); }
  .filterbar label { color: var(--muted); font-size: var(--fs-md); white-space: nowrap; }
  #rowfilter { width: 260px; }
  /* One-line table toolbar: filter grows left, import/export sit right. */
  .toolbar { display: flex; align-items: center; gap: var(--s2); flex-wrap: wrap;
  margin: 0 0 var(--s2); }
  .toolbar .filterbar { margin: 0; flex: 1 1 340px; }
  .toolgap { flex: 1; }
  .toolbar details.importbox { margin: 0; }
  .toolbar .note { margin: 0; }
  details.importbox { margin: 0 0 12px; }
  details.importbox summary { cursor: pointer; color: var(--accent);
                              font-size: var(--fs-md); font-weight: 600; }
  details.importbox form { display: flex; gap: 10px; align-items: center;
                           flex-wrap: wrap; margin: 8px 0 0; }
  .addrow { display: flex; gap: 10px; align-items: center; margin: 8px 0 0; }
  /* Totals stay pinned to the bottom edge of scrolling tables; consecutive
     totals rows (financials subtotals + grand total) stack in order. */
  tr.totals td { font-weight: 700; border-top: 2px solid var(--ink);
                 background: var(--stripe);
                 position: sticky; bottom: 0; z-index: 2; }
  .flash { background: var(--green-bg); color: var(--green); border-radius: var(--r-md);
           padding: 8px 12px; margin-bottom: 14px; max-width: 720px; }
  .flash.error { background: var(--red-bg); color: var(--red); }
  .flash:has(> .x) { position: relative; padding-right: 30px; }
  .devbanner { background: var(--amber-bg); color: var(--amber); font-size: var(--fs-sm);
               padding: 3px 20px; }
  .btn { display: inline-block; background: var(--accent); color: #fff;
         border: none; border-radius: var(--r-md); padding: 6px 12px; font-size: var(--fs-md);
         font-weight: 600; cursor: pointer; text-decoration: none;
         transition: background-color .15s ease, border-color .15s ease,
                     color .15s ease; }
  /* Compact variant for toolbars and in-table actions — used across the
     templates (btn small) since the first grid pages. */
  .btn.small { padding: 3px 9px; font-size: var(--fs-sm); border-radius: var(--r-sm); }
  .btn:hover { background: var(--accent-deep); }
  .btn:active { transform: translateY(1px); }
  .btn.secondary { background: var(--surface); color: var(--accent);
                   border: 1px solid var(--accent); }
  .btn.secondary:hover { background: var(--th-bg); }
  /* Hierarchy: filled = Add/Save, .secondary outline = Pull/Import, .quiet text = History/Export. */
.btn.quiet { background: none; color: var(--accent); border: 1px solid transparent; }
.btn.quiet:hover { background: var(--th-bg); }
.btn.danger { background: var(--red); }
  .btn.danger:hover { background: var(--red-deep); }
  form.inline { display: inline; }
  /* .btn sets display:inline-block, which silently defeats the hidden
     attribute (Clear filters showed even with no filters active). */
  .btn[hidden] { display: none; }
  input[type=text], input[type=number], input[type=date], input[type=month],
  input[type=email], input[type=search], input[type=file],
  select, textarea { padding: 7px 9px; border: 1px solid var(--input-border);
                     border-radius: var(--r-md); font-size: var(--fs-base); font-family: inherit;
                     transition: border-color .15s ease; }
  select { background-color: var(--surface); color: var(--ink); }
  input:focus, select:focus, textarea:focus { border-color: var(--focus); }
  .formgrid { display: grid; grid-template-columns: minmax(0, 180px) minmax(0, 1fr); gap: 10px 14px;
              align-items: start; background: var(--surface); border: 1px solid var(--line);
              border-radius: var(--r-lg); padding: 20px; width: 100%; max-width: 560px; }
  .formgrid > * { min-width: 0; max-width: 100%; }
  .formgrid select { min-width: 0; }
  .formgrid label { font-size: var(--fs-md); color: var(--muted); }
  /* Column-1 labels align to the FIRST line of their control, not the middle
     of a tall one — 7px matches the inputs' own top padding. Centering drags
     a multi-row control's label down until it reads as labelling the row
     below it. Bare checkboxes get the matching nudge. */
  .formgrid > label { padding-top: 7px; }
  /* Field-level errors / notes sit under the control; full width when stacked. */
  .formgrid > .fielderr, .formgrid > .col2 { grid-column: 2; margin: 0; }
  .formgrid > .fielderr { color: var(--red); }
  /* Grouped controls (channels, targets): full-width fieldset, visible legend. */
  .formgrid > fieldset { grid-column: 1 / -1; margin: 0; min-width: 0;
    border: 1px solid var(--line); border-radius: var(--r-md); padding: var(--s2) var(--s3) var(--s3); }
  .formgrid > fieldset > legend { padding: 0 var(--s1); font-size: var(--fs-md); color: var(--muted); }
  .formgrid > input[type="checkbox"] { margin-top: 9px; }
  /* Bulk editors: typed-but-unsaved = amber + left bar (non-colour cue);
     .saving stays pale accent so the two never look alike. */
  tbody tr td.dirty { background: var(--dirty);
                      box-shadow: inset 3px 0 0 var(--amber); }
  
  tbody tr td.saving { background: var(--accent-tint); }
  tbody tr td.saved { background: var(--green-bg); }
  tbody tr td.error { background: var(--red-bg); }
  input.invalid, select.invalid {
    border-color: var(--red); background: var(--red-bg); }
  tbody tr td.invalid { background: var(--red-bg); }
  td.invalid input { border-color: var(--red); }
  td input.cell { width: 64px; padding: 2px 4px; font-size: var(--fs-md);
                  text-align: right; }
  /* Native spinner buttons eat a third of a 64px grid cell. */
  td input.cell::-webkit-outer-spin-button,
  td input.cell::-webkit-inner-spin-button { -webkit-appearance: none;
                                             margin: 0; }
  td input.cell { -moz-appearance: textfield; appearance: textfield; }
  ::selection { background: var(--accent-tint); }
  :focus-visible { outline: 2px solid var(--focus); outline-offset: 1px; }
  /* Inside scroll containers an outside ring gets clipped — draw it in. */
  nav.tabs a:focus-visible, th :focus-visible, td :focus-visible {
    outline-offset: -2px; }
  .h-top :focus-visible { outline-color: var(--header-fg); }
  .visually-hidden { position: absolute; width: 1px; height: 1px;
    overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
  /* Admin-only sticky sync-failure cards. */
  .syncalerts { position: fixed; bottom: 16px; right: 16px; z-index: 20;
                display: flex; flex-direction: column; gap: 8px; }
  .syncalerts .alert { position: relative; background: var(--red-bg);
                       color: var(--red); border: 1px solid var(--red);
                       border-radius: var(--r-md); padding: 8px 28px 8px 12px;
                       max-width: 360px; font-size: var(--fs-md); }
  .syncalerts .msg { overflow-wrap: anywhere; max-height: 8em; overflow-y: auto; }
  .syncalerts .x, .flash .x { position: absolute; top: 3px; right: 5px; border: 0;
                   background: none; color: inherit; font-size: var(--fs-lg);
                   line-height: 1; padding: 2px; cursor: pointer; }
  /* Sign-in page (app/auth.py _LOGIN_PAGE). */
  body.login { min-height: 100vh; display: flex; flex-direction: column; }
  .loginwrap { flex: 1; display: grid; place-items: center; }
  .loginbox { background: var(--surface); border: 1px solid var(--line);
              border-top: 3px solid var(--header-ink); border-radius: var(--r-lg);
              box-shadow: var(--shadow-1); padding: 32px; width: min(340px, 100%); }
  .loginbox .logo { text-align: center; margin-bottom: 14px; }
  .loginbox h1 { font-size: var(--fs-lg); color: var(--header-ink); }
  .loginbox p { color: var(--muted); font-size: var(--fs-md); }
  .loginbox .flash { margin: 10px 0 0; }
  .loginbox input[type=email], .loginbox .btn { width: 100%; margin-top: 8px; }
  .loginbox .btn { padding: 9px; font-size: var(--fs-base); }
  @media (max-width: 600px) {
    .formgrid { grid-template-columns: 1fr; }
    .formgrid > .fielderr, .formgrid > .col2 { grid-column: 1; }
  }
  @media (prefers-reduced-motion: reduce) {
    .btn.busy::before, body.syncing::after { animation: none; }
    .backfill .fill { transition: none !important; }  /* page <style> wins
                                                         otherwise */
    a.card, .btn, header a.nav, th.sortth, input, select, textarea {
      transition: none; }
  }
  @media print {
    header, .btn, form, #rowfilter, .devbanner, .syncalerts,
    button.cf, .cfpop, .tagpop, .sortind, .pulled, button.lists, .listpop {
      display: none !important; }
    .tablewrap { max-height: none !important; overflow: visible; }
  }

/* The "now line": the current (in-progress) month column opens with a 2px
   ledger-blue rule — the one place chrome spends its accent on data. Each
   rule that also paints an inset shadow on these cells (row-hover
   hairlines, sortable-header hover tint) re-lists the rule so neither is
   lost; the selectors out-specify the originals. */
thead th.now, tbody tr td.now { box-shadow: inset 2px 0 0 var(--accent); }

th.sortth.now:hover { box-shadow: inset 2px 0 0 var(--accent),
                                  inset 0 0 0 100px rgba(0,0,0,.05); }

/* ── Small screens ─────────────────────────────────────────────────────
   Read-mostly phone/tablet support. Everything is screen-scoped so the
   print block above always wins; desktop pixels are untouched. Tiers:
   ≤700px (density + slimmed name column + forecast's 3rd frozen column
   unpinned) · ≤480px phones (only the SKU column stays pinned) ·
   ≤500px-high landscape phones. Sticky offsets themselves are measured
   by table-enhance.js (--col1-w/--col2-w), so these tiers only restyle.
   Mobile is read-mostly: filters/sorting/scroll get the ergonomics;
   editors just keep working (16px inputs kill iOS focus-zoom). */
html { -webkit-text-size-adjust: 100%; }   /* no iOS landscape inflation */
@media screen and (max-width: 700px) {
  main { padding: 12px; }
  table { font-size: var(--fs-md); }
  th, td { padding: 4px 7px; }
  th { font-size: var(--fs-xs); }
  td.notes { max-width: 220px; }
  /* Search gets its own row; facet selects/flags wrap underneath. */
  .toolbar .filterbar { flex: 1 1 100%; }
  #rowfilter { width: 100%; }
  /* Overlays never exceed the viewport. */
  dialog { max-width: calc(100vw - 24px); padding: 14px 16px; }
  .syncalerts .alert { max-width: calc(100vw - 24px); }
  .syncalerts { right: 12px; }
  .cards { display: grid;
           grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); }
  /* iOS Safari zooms the page on focus of any input under 16px. The
     classed rules below redeclare it — they out-specificity the plain
     element selectors in .filterbar/.cfpop/td above. */
  input, select, textarea,
  .filterbar select, .cfpop input, td input.cell { font-size: var(--fs-lg); }
  /* Inline max-height:75/78vh styles predate dvh; override like print
     does. dvh tracks the mobile browser's collapsing chrome. */
  .tablewrap { max-height: 82vh !important; max-height: 82dvh !important; }
  /* A long email is one unbreakable word — ellipsize it (and only it);
     links stay on one line, the version badge keeps its width. */
  .h-top .userbar { min-width: 0; }
  .h-top .userbar a { white-space: nowrap; }
  .h-top .userbar .uemail { min-width: 0; overflow: hidden;
                            text-overflow: ellipsis; white-space: nowrap; }
  /* Name column: 220 → 150px (ellipsis already in place). */
  .sticky-col2 tr:not(.totals) td:nth-child(2),
  .sticky-col2 thead tr:first-child th:nth-child(2) { max-width: 150px; }
  .sticky-col3 thead tr:first-child th:nth-child(2),
  .sticky-col3 tr:not(.totals) td:nth-child(2) { width: 150px;
                                                 min-width: 150px; }
}
@media screen and (max-width: 1024px), screen and (pointer: coarse) {
  /* Mobile + tablet (narrow viewport OR touch-primary — an iPad landscape
     is 1024+): frozen columns eat half the screen, so every column rejoins
     the horizontal scroll. Body cells go static; header cells stay
     position:sticky and only drop their left pin — static would also kill
     the top:0 they inherit from the base th rule and the header row's
     first cell would scroll away with the page. */
  .sticky-col td:first-child,
  .sticky-col2 tr:not(.totals) td:nth-child(2),
  .sticky-col3 tr:not(.totals) td:nth-child(3) {
    position: static; box-shadow: none; }
  .sticky-col th:first-child,
  .sticky-col2 thead tr:first-child th:nth-child(2),
  .sticky-col3 thead tr:first-child th:nth-child(3) {
    left: auto; box-shadow: none; }
}
@media screen and (max-height: 500px) {
  /* Landscape phones: a sticky header would eat a quarter of the height. */
  header { position: static; }
  .tablewrap { max-height: 88vh !important; max-height: 88dvh !important; }
}
/* Small icon/pill buttons: >= 24x24 on desktop (WCAG 2.2 AA), 44x44 on touch. */
button.cf, button.lists, button.tagpick, .syncalerts .x, .flash .x {
  min-width: var(--hit-min); min-height: var(--hit-min);
  display: inline-flex; align-items: center; justify-content: center; }

@media (pointer: coarse) {
  /* (.mx lives in sales_history.html's page style and grows there.) */
  :root { --hit-min: 44px; }
  button.cf, button.lists { padding: 4px 6px; }
  .btn.small { min-height: var(--hit-min); }
  .switch { min-height: var(--hit-min); }
}

/* Promo calendar (task 8): month/year views, bar geometry is server-
   computed (app/main.py) and expressed with plain CSS grid column spans —
   no charting library. Colour-by-type reuses the existing --tag-* tokens
   from :root above (never new tokens): .cal-bar.tag-* is a solid chip using
   the same hue as .badge.tag-*'s text colour, since a bar is a thin strip
   rather than a pill. */
.cal-toolbar { display: flex; align-items: center; gap: var(--s2); margin: var(--s2) 0 var(--s4);
              flex-wrap: wrap; }
.cal-toolbar .spacer { flex: 1 1 auto; }
.cal-anchor { font-weight: 600; min-width: 90px; text-align: center; }
.cal-month { border: 1px solid var(--line); border-radius: var(--r-lg); overflow: hidden;
             background: var(--surface); }
.cal-head { display: grid; grid-template-columns: repeat(7, 1fr);
            background: var(--th-bg); border-bottom: 1px solid var(--line); }
.cal-head div { padding: 5px 8px; font-size: var(--fs-xs); font-weight: 600;
                letter-spacing: .06em; text-transform: uppercase;
                color: var(--muted); text-align: right; }
.cal-week { position: relative; min-height: 86px;
            border-bottom: 1px solid var(--line); padding-bottom: 4px; }
.cal-week:last-child { border-bottom: none; }
.cal-week-label { display: none; }
/* The background layer owns the calendar geometry: hairline column
   separators plus the out-of-month / today washes, full row height. */
.cal-grid { position: absolute; inset: 0; display: grid;
            grid-template-columns: repeat(7, 1fr); pointer-events: none; }
.cal-grid div { border-left: 1px solid var(--line); }
.cal-grid div:first-child { border-left: none; }
.cal-grid .out { background: var(--bg); }   /* canvas color: recedes vs the
                                               card-white in-month cells */
.cal-grid .today { background: var(--accent-wash); }
.cal-daysrow, .cal-barsrow { position: relative; }  /* above .cal-grid */
.cal-daysrow { display: grid; grid-template-columns: repeat(7, 1fr); }
.cal-day { padding: 4px 6px 2px; font-size: var(--fs-sm); color: var(--ink);
           text-align: right; }
.cal-day.out { color: var(--zero-ink); }
.cal-today { display: inline-flex; align-items: center; justify-content: center;
             min-width: 19px; height: 19px; padding: 0 3px; border-radius: var(--r-pill);
             background: var(--accent); color: #fff; font-weight: 600; }
.cal-barsrow { display: grid; grid-template-columns: repeat(7, 1fr); gap: 2px;
              padding: 0 4px 4px; }
.cal-bar { display: block; padding: 2px 7px; margin-top: 2px; border-radius: var(--r-sm);
          font-size: var(--fs-sm); font-weight: 600; line-height: 1.5;
          overflow: hidden; text-overflow: ellipsis;
          white-space: nowrap; text-decoration: none; color: #fff; }
a.cal-bar:hover { filter: brightness(1.12); }
.cal-bar.archived { opacity: 0.55; cursor: default; pointer-events: none; }
.cal-bar.tag-slate { background: var(--tag-slate); }
.cal-bar.tag-amber { background: var(--tag-amber); }
.cal-bar.tag-green { background: var(--tag-green); }
.cal-bar.tag-sky { background: var(--tag-sky); }
.cal-bar.tag-violet { background: var(--tag-violet); }
.cal-bar.tag-rose { background: var(--tag-rose); }
.cal-bar.tag-teal { background: var(--tag-teal); }
.cal-bar.tag-orange { background: var(--tag-orange); }
/* Year view: same card as the month grid, one row per month — the label
   rail speaks the weekday-header language, a thin accent line marks today
   in the current month's track. */
.cal-year { border: 1px solid var(--line); border-radius: var(--r-lg); overflow: hidden;
            background: var(--surface); }
.cal-yrow { display: flex; align-items: stretch;
            border-bottom: 1px solid var(--line); }
.cal-yrow:last-child { border-bottom: none; }
.cal-yrow-label { flex: 0 0 46px; display: flex; align-items: center;
                  padding: 4px 9px; font-size: var(--fs-xs); font-weight: 600;
                  letter-spacing: .06em; text-transform: uppercase;
                  color: var(--muted); background: var(--th-bg);
                  border-right: 1px solid var(--line); }
.cal-yrow.now .cal-yrow-label { color: var(--accent); }
.cal-yrow-track { position: relative; flex: 1 1 auto; display: grid;
                  gap: 1px; min-height: 28px; padding: 3px 4px; }
.cal-nowline { position: absolute; top: 0; bottom: 0; width: 2px;
               background: var(--accent); opacity: .45; }
.cal-yrow-track .cal-bar { margin: 1px 0 0; border-radius: var(--r-sm); }
@media screen and (max-width: 600px) {
  .cal-head, .cal-grid, .cal-daysrow, .cal-nowline { display: none; }
  .cal-week { min-height: 0; padding: 10px 12px; }
  .cal-week-label { display: block; font-weight: 600; margin-bottom: 4px; }
  .cal-barsrow, .cal-yrow-track { display: flex; flex-direction: column; padding: 0; }
  .cal-bar, .cal-yrow-track .cal-bar { margin: 4px 0 0; padding: 6px 9px;
                                     white-space: normal; overflow-wrap: anywhere; font-size: var(--fs-md); }
  .cal-yrow { display: block; }
  .cal-yrow-label { border-right: 0; border-bottom: 1px solid var(--line); }
  .cal-yrow-track { padding: 6px 12px 10px; min-height: 0; }
}

/* Matched-SKU list in the promo form: a plain two-column reference table
   inside its <details>, not part of the sortable data-table system. */
table.matched { border-collapse: collapse; margin-top: 4px; }
table.matched td { padding: 1px 12px 1px 0; font-size: var(--fs-sm);
                   color: var(--muted); }
table.matched td:first-child { font-family: var(--font-mono); }

/* Frozen-SKU list in the archive table: the cell inherits the table's
   white-space:nowrap, so the list needs its own bounded, wrapping panel —
   the row grows in place, same as the Edit form's <details>. */
td details.skulist summary { cursor: pointer; color: var(--accent);
                             font-weight: 600; }
td details.skulist ul { list-style: none; margin: 6px 0 2px; padding: 0;
                        max-width: 340px; max-height: 220px; overflow-y: auto;
                        white-space: normal; }
td details.skulist li { font-size: var(--fs-sm); color: var(--muted);
                        padding: 1px 0; }
td details.skulist code { font-family: var(--font-mono);
                          font-size: var(--fs-sm); color: var(--ink); }

/* grid editors */
/* Bulk-edit tables (forecast, SKUs): sticky action bar, tall scroll box,
   live totals footer, keyboard-nav scroll padding. */
.tablewrap.tall { max-height: 75vh; overflow-y: auto; }
.editbar { position: sticky; top: var(--header-h, 46px); z-index: 5;
           display: flex; flex-wrap: wrap; align-items: center; gap: 8px;
           background: var(--bg); padding: 8px 0; margin: 0 0 8px; }
.editbar input[type=text] { flex: 0 1 260px; min-width: 0; }
.dirtynote { color: var(--amber); font-size: var(--fs-md); font-weight: 600;
             font-variant-numeric: tabular-nums; }
.dirtynote:empty { display: none; }
/* Footer totals keep the frozen columns frozen (the shared sticky-col rules
   skip tr.totals so financials' colspan labels aren't pinned). */
.sticky-col tfoot tr.totals td:first-child { z-index: 3; }
.sticky-col3 tfoot tr.totals td:nth-child(2) {
  position: sticky; left: var(--col1-w, var(--col1-min)); z-index: 3; }
.sticky-col3 tfoot tr.totals td:nth-child(3) {
  position: sticky; left: calc(var(--col1-w, var(--col1-min)) + var(--col2-w, var(--col2-min)));
  z-index: 3; box-shadow: 2px 0 0 var(--line); }
/* Focus (Tab or arrow keys) scrolls the target clear of sticky header/footer/columns. */
html { scroll-padding-top: calc(var(--header-h, 46px) + var(--editbar-h)); }   /* header + .editbar */
.tablewrap:has(> table[data-gridnav]), .tablewrap.sticky-col { scroll-padding-block: var(--thead-h) var(--tfoot-h); }
.tablewrap.sticky-col { scroll-padding-left: var(--col1-w, var(--col1-min)); }
.tablewrap.sticky-col2 {
  scroll-padding-left: calc(var(--col1-w, var(--col1-min)) + var(--col2-w, var(--col2-min))); }
.tablewrap.sticky-col3 {
  scroll-padding-left: calc(var(--col1-w, var(--col1-min)) + var(--col2-w, var(--col2-min)) + var(--col3-w, var(--col3-min))); }
@media screen and (max-width: 1024px), screen and (pointer: coarse) {
  .tablewrap.sticky-col, .tablewrap.sticky-col2, .tablewrap.sticky-col3 {
    scroll-padding-left: 0; } /* columns unpinned there */
}

/* cover bars */
.cover-legend { display: flex; gap: 16px; flex-wrap: wrap; align-items: center; }
td.cover { white-space: nowrap; }
.cover-n { display: inline-block; min-width: 2.2em; text-align: right; }
.cover-bar { display: inline-block; position: relative; vertical-align: middle;
  width: 72px; height: 6px; margin-left: 8px; border-radius: 3px;
  background: var(--line); }
.cover-bar i { position: absolute; left: 0; top: 0; bottom: 0; border-radius: 3px;
  background: var(--muted); }
.cover-bar.c-red i { background: var(--red); }
.cover-bar.c-amber i { background: var(--amber); }
.cover-bar.c-ok i { background: var(--muted); opacity: .6; }
.cover-bar::before, .cover-bar::after { content: ""; position: absolute; top: -1px;
  bottom: -1px; width: 1px; background: var(--surface); z-index: 1; }
.cover-bar::before { left: 33.33%; } .cover-bar::after { left: 66.66%; }
/* net position shading */
tbody tr td.neg.neg1 { background: color-mix(in srgb, var(--red) 12%, var(--surface)); }
tbody tr td.neg.neg2 { background: color-mix(in srgb, var(--red) 24%, var(--surface));
  color: var(--red-deep); }   /* --red is 4.1:1 here */
tbody tr td.neg.neg3 { background: color-mix(in srgb, var(--red) 38%, var(--surface));
  color: var(--ink); }        /* --red is 3.2:1 here; ink is 8:1+ */
tbody tr td.low { background: var(--amber-bg); }
tbody tr td.zero:empty, .sw.np-out {
  background-image: repeating-linear-gradient(45deg, var(--line) 0 1px, transparent 1px 6px); }
.sw { display: inline-block; width: 14px; height: 14px; border-radius: 3px;
  vertical-align: -2px; border: 1px solid var(--line); }
.sw.np-low { background: var(--amber-bg); }
.sw.np-neg1 { background: color-mix(in srgb, var(--red) 12%, var(--surface)); }
.sw.np-neg2 { background: color-mix(in srgb, var(--red) 24%, var(--surface)); }
.sw.np-neg3 { background: color-mix(in srgb, var(--red) 38%, var(--surface)); }

/* charts */
.sub.wide { max-width: none; }
.tablewrap.flush, .note.flush { margin: 0 0 4px; }
.tablewrap.flush { margin-bottom: 4px; }
.kpis { margin: 0 0 12px; }
.kpis .card .d { display: block; font-size: var(--fs-sm); color: var(--muted);
                 font-variant-numeric: tabular-nums; margin-top: 2px; }
.chartfig { margin: 0 0 14px; background: var(--surface); border: 1px solid var(--line);
            border-radius: var(--r-lg); padding: 10px 12px 6px; min-width: 0; }
/* Cards: one size everywhere — 1 column, 2×2 from 900px, one row of 4
   from 1760px (each card ≥ ~420px, enough for the waterfall labels).
   Equal rows + flex column keep every card the same height; the plot
   heights are fixed in fin-charts.js (CARD_H). */
.chartgrid { display: grid; grid-template-columns: 1fr; grid-auto-rows: 1fr; gap: 14px;
             margin: 0 0 14px; }
@media (min-width: 900px) { .chartgrid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1760px) { .chartgrid { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  /* no-COGS viewers get two cards: keep them a half row each */
  .chartgrid:has(> :nth-child(2):last-child) { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.chartgrid > .chartfig { margin: 0; display: flex; flex-direction: column; }
.chartgrid .charthead { min-height: 2.2em; }
.chartgrid .charthead h2 { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.legend .lgm { color: var(--muted); }
.legend .pc { font-variant-numeric: tabular-nums; }
.charthead { display: flex; align-items: baseline; gap: 4px 12px; flex-wrap: wrap; }
.charthead h2 { font-size: var(--fs-base); margin: 0 0 4px; }
.fc-plot { min-height: 40px; }
.fchart { display: block; max-width: 100%; }
.fchart { user-select: none; -webkit-user-select: none; } /* Shift-click ranges must not select text */
.fc-tip { position: fixed; z-index: 30; max-width: 280px; pointer-events: none;
          background: var(--surface); color: var(--ink); border: 1px solid var(--line);
          border-radius: var(--r-md); box-shadow: var(--shadow-pop); padding: 6px 9px;
          font-size: var(--fs-sm); line-height: 1.35; overflow-wrap: anywhere; }
.fc-tip[hidden] { display: none; }
.fchart .mo { cursor: pointer; outline: none; }
.fchart .mo .band { fill: transparent; }
.fchart .mo:hover .band { fill: var(--line); opacity: .35; }
.fchart .mo.on .band { fill: var(--accent-wash, var(--line)); opacity: .9; }
.fchart .mo:focus-visible .band { stroke: var(--focus, var(--accent)); stroke-width: 2; }
.fchart .mtd .seg { fill-opacity: .45; stroke-dasharray: 3 2; stroke: var(--ink); stroke-width: 1; }
.fchart .mtdlabel, .fchart .dagger { font-weight: 700; fill: var(--ink); }
.fchart .gap { font-style: italic; }
.fchart .netdot.open { fill: var(--surface); stroke: var(--ink); }
.fchart .val { fill: var(--ink); font-weight: 600; }
.fchart .sub { font-size: 11px; }
.fchart .code { fill: var(--ink); }
.fchart .lossval { fill: var(--red); }
.fchart .inlab { fill: #fff; font-size: 10px; font-weight: 600; pointer-events: none; }
.fchart .wf-total { fill: var(--tag-slate); }
.fchart .wf-net { fill: var(--green); }
.fchart .wf-loss, .fchart .wf-down { fill: var(--red); }
.fchart .wf-other { fill: var(--muted); fill-opacity: .55; }
.fchart .wf-link { stroke: var(--muted); stroke-dasharray: 2 2; }
.fchart .quad { stroke: var(--line); stroke-dasharray: 4 3; }
.fchart .quadlab { font-size: 11px; paint-order: stroke; stroke: var(--surface); stroke-width: 4px;
                   stroke-linejoin: round; pointer-events: none; }
.fchart.hovering { cursor: pointer; }
.fchart.hovering .dot { opacity: .25; }
.fchart .hot { fill: var(--accent); stroke: var(--ink); stroke-width: 2; pointer-events: none; }
.fchart .hot.loss { fill: var(--red); }
.fchart .skurow { cursor: pointer; outline: none; }
.fchart .skurow .band { fill: transparent; }
.fchart .skurow:hover .band { fill: var(--line); opacity: .6; }
.fchart .skurow:focus-visible .band { fill: var(--line); stroke: var(--focus, var(--accent)); stroke-width: 2; }
tbody tr.flash td { animation: rowflash 2.5s ease-out; }
@keyframes rowflash { 0%, 50% { background: var(--amber-bg); } }
@media (prefers-reduced-motion: reduce) { tbody tr.flash td { animation: none; background: var(--amber-bg); } }
.fchart .dot { fill: var(--accent); fill-opacity: .7; stroke: var(--surface); stroke-width: 1; }
.fchart .dot.loss { fill: var(--red); }
.fchart .dot.open { fill: var(--surface); stroke: var(--accent); stroke-width: 1.5; }
.fc-readout { min-height: 1.45em; margin: 2px 0 0; }
.legend .lg { display: inline-flex; align-items: center; border: 0; background: none; padding: 2px 4px;
              font: inherit; color: var(--ink); cursor: pointer; border-radius: var(--r-sm);
              min-height: var(--hit-min); }
.legend .lg[aria-pressed="false"] { color: var(--muted); text-decoration: line-through; }
.legend .lg[aria-pressed="false"] .sw { opacity: .25; }
.legend .lg:disabled { cursor: default; }
.legend .sw.mtd { border: 1px dashed var(--ink); background: transparent; }
.fchart .grid { stroke: var(--line); stroke-width: 1; }
.fchart .zero { stroke: var(--muted); stroke-width: 1; }
.fchart .ax { fill: var(--muted); font-size: var(--fs-xs); }
.fchart .seg { stroke: var(--surface); stroke-width: 1.5; }
.fchart .netline { fill: none; stroke: var(--ink); stroke-width: 2; }
.fchart .netdot { fill: var(--ink); stroke: var(--surface); stroke-width: 2; }
.fchart .seg.tag-slate, .legend .sw.tag-slate { fill: var(--tag-slate); background: var(--tag-slate); }
.fchart .seg.tag-amber, .legend .sw.tag-amber { fill: var(--tag-amber); background: var(--tag-amber); }
.fchart .seg.tag-green, .legend .sw.tag-green { fill: var(--tag-green); background: var(--tag-green); }
.fchart .seg.tag-sky, .legend .sw.tag-sky { fill: var(--tag-sky); background: var(--tag-sky); }
.fchart .seg.tag-violet, .legend .sw.tag-violet { fill: var(--tag-violet); background: var(--tag-violet); }
.fchart .seg.tag-rose, .legend .sw.tag-rose { fill: var(--tag-rose); background: var(--tag-rose); }
.fchart .seg.tag-teal, .legend .sw.tag-teal { fill: var(--tag-teal); background: var(--tag-teal); }
.fchart .seg.tag-orange, .legend .sw.tag-orange { fill: var(--tag-orange); background: var(--tag-orange); }
.legend { display: flex; flex-wrap: wrap; gap: 4px 14px; font-size: var(--fs-sm);
          color: var(--ink); padding: 4px 0; }
.legend .sw { display: inline-block; width: 10px; height: 10px; border-radius: 2px;
              margin-right: 5px; vertical-align: baseline; }
.legend .sw.line { height: 2px; background: var(--ink); vertical-align: middle; }
.backfill .spin { display: inline-block; }
.backfill .running .spin { animation: bf-spin 1.2s linear infinite; }
@keyframes bf-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .backfill .running .spin { animation: none; } }
.financials-summary td.subcol.metric { font-size: var(--fs-md); font-weight: 600; }

/* switches */
tbody tr.off { display: none; }
.switches { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; }
.switchsep { width: 1px; align-self: stretch; background: var(--line); }
.switch { display: inline-flex; align-items: center; gap: 8px; border: 0; padding: 2px 0;
          background: none; font: inherit; font-size: var(--fs-sm); color: var(--ink); cursor: pointer; }
.switch::after { content: ""; width: 28px; height: 16px; border-radius: var(--r-pill);
                 background: var(--input-border); box-shadow: inset 0 0 0 2px var(--input-border);
                 transition: background .15s, box-shadow .15s; }
.switch::after { background-image: radial-gradient(circle at 8px 50%, var(--surface) 5px, transparent 5.5px); }
.switch[aria-checked="true"]::after { background-color: var(--accent); box-shadow: inset 0 0 0 2px var(--accent);
  background-image: radial-gradient(circle at 20px 50%, var(--surface) 5px, transparent 5.5px); }
.switch:disabled { cursor: not-allowed; opacity: .55; }
@media (prefers-reduced-motion: reduce) { .switch::after { transition: none; } }
/* diffusers overview */
.card.warn { border-color: var(--amber); background: var(--amber-bg); }
.t-red { color: var(--red-deep); }
.t-amber { color: var(--amber); }
td .skuname { display: inline-block; vertical-align: bottom; max-width: 22ch; margin-left: 8px;
  overflow: hidden; text-overflow: ellipsis; font: var(--fs-xs) var(--font); color: var(--muted); }
td.trend { padding-top: 2px; padding-bottom: 2px; }
.spark { display: block; overflow: visible; }
.spark .act { fill: none; stroke: var(--ink); stroke-width: 1.5; }
.spark .fc { fill: none; stroke: var(--accent); stroke-width: 1.5; stroke-dasharray: 3 2; }
.spark .split { stroke: var(--line); stroke-width: 1; }
.basis-tag { display: inline-block; padding: 0 5px; border: 1px dashed var(--amber);
  border-radius: var(--r-pill); color: var(--amber); background: var(--amber-bg);
  font-size: var(--fs-xs); font-weight: 600; letter-spacing: .03em; }
.cover-bar.wide { width: 120px; }
/* Estimated cover (from sales, not forecast): hatched, never solid. */
.cover-bar.est i { background: repeating-linear-gradient(-45deg, var(--amber) 0 3px, transparent 3px 6px);
  outline: 1px dashed var(--amber); }
.cover-bar.wide::before { left: 25%; } .cover-bar.wide::after { left: 50%; }
.cv-tick { position: absolute; top: -3px; bottom: -3px; width: 2px; z-index: 2;
  background: var(--ink); border-radius: 1px; }
.cover-legend i.cv-tick { position: relative; display: inline-block; height: 12px;
  vertical-align: middle; top: 0; }
details.section > summary { cursor: pointer; list-style-position: outside; margin-left: 1em; }
details.section > summary h2 { display: inline; }

/* Secondary sub-columns (Inventory Amazon pipeline, Forecast vs Actual, Financials
   money cells): half-weight beside their main column. */
th.subcol, td.subcol { font-size: var(--fs-xs); padding-left: 6px; padding-right: 6px; }
th.subcol { color: var(--muted); font-weight: 500; }
/* Version-history pages (SKU Master, Promo, Forecast). */
details.version { margin: var(--s3) 0; }
details.version summary { cursor: pointer; }
details.version ul { margin: 6px 0 6px var(--s1); }
.diff-old { color: var(--red); }
.diff-new { color: var(--green); }

/* Second-store hatch over the channel hue (chart segments + legend swatches). */
.hatch { background-image: repeating-linear-gradient(45deg, rgba(255,255,255,.55) 0 2px, transparent 2px 5px); }
.backfill.waiting .pct#bf_run { font-style: italic; }

/* SKU Master bulk items: Fetch list over the table's right edge; ▸ PO history toggle. */
.bulkwrap { width: fit-content; max-width: 100%; }
.bulkwrap > form { display: flex; justify-content: flex-end; margin-bottom: 8px; }
.pobtn { background: none; border: 0; padding: 0 4px; cursor: pointer; color: var(--muted); font: inherit; }
.pobtn:hover { color: var(--ink); }
tr.pohist > td { background: var(--bg); padding: 8px 16px 12px 32px; }
