/* Street Poker marketing studio.

   GEOMETRY AND ENRICHMENT BOTH COME FROM HUD/landing.html. The website cuts the
   top-left and bottom-right corner off every card, button and badge and rounds
   nothing. That notch, flat near-black fills and JetBrains Mono numerals are
   what make a surface read as Street Poker instead of a generic dark dashboard.

   ⛔ A previous pass here deleted the page's background gradients on the
   grounds that "the real page is a flat #06060b" -- that was read off
   HUD/main.css (the APP) and this surface takes its language from the SITE,
   which is not flat at all. Measured from landing.html: body is pure #000, the
   section behind the cards carries
       radial-gradient(ellipse 100% 60% at 50% 0%, #060d1f, #02050d 50%, #000)
   plus two soft blue atmosphere circles and a 2px scanline at 1.5% blue.
   Card-on-page contrast is only 1.061:1 on the real site too, so the
   separation was never coming from the fill -- it comes from the page having
   tone under the card, from a 44px measure of air inside it, and from the
   hairline. Take the notch and you have to take these as well, or the surface
   reads as dead. That is what "too dull" was.

   SCALE. Nothing here is a fixed pixel size that a monitor can outgrow. The
   three faults this replaces, all measured at 2560x1400:
     - a stat tile rendered 563x107 with a 30px numeral in the corner: ~520px
       of empty box per tile, because the grid stretched instead of capping;
     - the whole Overview ended at y=434 of 1400 -- 69% void;
     - every font-size fixed, so a 22px page title on a 2560 display.
   Fixed by --shell-max (the site caps its own rows at 1200px), clamp() on
   every size that should answer to the viewport, and vh-aware card minimums. */
@import url('https://fonts.googleapis.com/css2?family=Outfit:wght@300;400;500;600;700;800&family=JetBrains+Mono:wght@400;500;600;700;800&display=swap');

*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

/* The UA stylesheet gives [hidden] `display: none`, and ANY author rule that
   sets display beats it -- origin loses to origin before specificity is even
   consulted. So `.palette-row { display: flex }` quietly made el.hidden = true
   a no-op, and the command palette listed every page no matter what you typed.
   Every filter in app.js sets .hidden, so this one line is load-bearing. */
[hidden] { display: none !important; }

:root {
  --bg-base: #000;
  --bg-border: rgba(255,255,255,0.06);
  --bg-border-solid: #1b2740;
  --bg-hover: rgba(255,255,255,0.04);
  --text-primary: #e2e8f0;
  --text-bright: #f1f5f9;
  --text-body: #cbd5e1;
  --text-muted: #94a3b8;
  --text-dim: #64748b;      /* was #475569 -- 2.9:1, under AA even for dim labels */
  --accent-blue: #3b82f6;
  --accent-green: #22c55e;
  --accent-red: #ef4444;
  --accent-yellow: #eab308;
  --accent-purple: #a855f7;
  --accent-orange: #f97316;
  --font: 'JetBrains Mono', ui-monospace, monospace;
  --font-ui: 'Outfit', system-ui, -apple-system, 'Segoe UI', sans-serif;

  /* The website's surfaces: flat near-black, blue hairlines, no gloss. */
  --sp-ink: #060a14;        /* .card       */
  --sp-inset: #030710;      /* .term       */
  --sp-sink: #030508;       /* .stat-cell -- darker than the card, on purpose */
  --sp-line: rgba(59,130,246,0.08);
  --sp-line-lit: rgba(59,130,246,0.22);
  --sp-wash: linear-gradient(180deg, rgba(59,130,246,0.03) 0%, transparent 40%);

  /* --sp-blue FILLS, --accent-blue is for TEXT ONLY. White on #3b82f6 is
     3.68:1 and fails AA; on #2563eb it is 5.17:1. Do not swap them. */
  --sp-blue: #2563eb;

  /* The notch. Four sizes, matching the site: cards 8, buttons 8, small
     buttons and chrome 6, tags/badges/insets 4. Below ~4px on a wide element
     it stops reading as a cut and looks like a rendering artifact. */
  --cut: polygon(0 8px, 8px 0, 100% 0, 100% calc(100% - 8px), calc(100% - 8px) 100%, 0 100%);
  --cut-6: polygon(0 6px, 6px 0, 100% 0, 100% calc(100% - 6px), calc(100% - 6px) 100%, 0 100%);
  --cut-4: polygon(0 4px, 4px 0, 100% 0, 100% calc(100% - 4px), calc(100% - 4px) 100%, 0 100%);
  --cut-3: polygon(0 3px, 3px 0, 100% 0, 100% calc(100% - 3px), calc(100% - 3px) 100%, 0 100%);

  /* ── The scale, in one place ──────────────────────────
     Every one of these answers to the viewport. The caps are what stop a wide
     monitor from turning a four-item row into four 563px boxes: past
     --shell-max the extra width becomes margin, which is what the site does
     (.feat__inner, .altrow and .gallery-strip all stop at 1200px). */
  --shell-max: 1560px;
  --sidebar-w: clamp(196px, 14.5vw, 244px);
  --gut: clamp(16px, 2.4vw, 44px);        /* page gutter   */
  --pad: clamp(15px, 1.35vw, 26px);       /* card padding  */
  --gap: clamp(12px, 1.05vw, 20px);       /* grid gap      */
  --fig: clamp(28px, 2.55vw, 42px);       /* hero numeral  */
  --fig-sm: clamp(21px, 1.7vw, 28px);
  --h1: clamp(21px, 1.9vw, 30px);
  /* Panels that would otherwise leave the lower half of a tall monitor empty.
     vh, so a 27" screen gets taller cards rather than the same cards and more
     void underneath them. */
  --panel-min: clamp(216px, 26vh, 380px);
}

/* ── The page ──────────────────────────────────────────── */
/* Three layers, all lifted from the site: the section radial, the two
   atmosphere circles, and the scanline. Fixed so they do not slide away on
   scroll -- this is the room the cards sit in, not part of the document. */
body {
  background: var(--bg-base);
  color: var(--text-body);
  font-family: var(--font-ui);
  font-size: clamp(13.5px, 0.92vw, 15px);
  min-height: 100vh;
  -webkit-font-smoothing: antialiased;
}
body::before {
  content: ''; position: fixed; inset: 0; z-index: 0; pointer-events: none;
  background:
    radial-gradient(circle at 22% 24%, rgba(59,130,246,0.07), transparent 42%),
    radial-gradient(circle at 80% 76%, rgba(37,99,235,0.05), transparent 44%),
    radial-gradient(ellipse 100% 60% at 50% 0%, #060d1f 0%, #02050d 50%, #000 100%);
}
/* .sec::before on the site: a 2px scanline at 1.5% blue. It is the difference
   between "black" and "a surface". */
body::after {
  content: ''; position: fixed; inset: 0; z-index: 0; pointer-events: none;
  background: repeating-linear-gradient(0deg,
    transparent, transparent 1px, rgba(59,130,246,0.015) 1px, rgba(59,130,246,0.015) 2px);
}
.shell, .login-body { position: relative; z-index: 1; }

a { color: inherit; text-decoration: none; }
::selection { background: rgba(59,130,246,0.3); }

/* ── Shell ─────────────────────────────────────────────── */
.shell { display: flex; min-height: 100vh; }

.sidebar {
  width: var(--sidebar-w);
  flex: 0 0 var(--sidebar-w);
  border-right: 1px solid var(--sp-line);
  background: rgba(6,10,20,0.72);
  backdrop-filter: blur(6px);
  padding: 20px 12px 24px;
  position: sticky;
  top: 0;
  height: 100vh;
  overflow-y: auto;
  display: flex; flex-direction: column;
}

/* The mark is HUD/sp-logo-clean.png, the de-glowed copy built for dark
   surfaces. Never redraw it: both .svg variants in the repo are bad traces and
   have been rejected on sight, and a hand-built "SP" in a rounded box (which is
   what this was) is the same mistake with fewer steps. */
.brand { display: flex; align-items: center; gap: 9px; padding: 2px 8px 18px; }
.brand-mark { height: clamp(20px, 1.5vw, 26px); width: auto; flex: none; display: block; }
.brand-name { font-size: clamp(12px, 0.85vw, 14px); font-weight: 700; letter-spacing: 0.14em; text-transform: uppercase; color: var(--text-bright); }
.brand-name em { font-style: normal; color: var(--accent-blue); }

.nav-group { margin-bottom: 16px; padding-top: 14px; border-top: 1px solid rgba(59,130,246,0.07); }
.nav-group:first-of-type { border-top: none; padding-top: 0; }
.nav-label {
  font-size: 9px; letter-spacing: 0.18em; text-transform: uppercase;
  color: var(--text-dim); padding: 0 10px 8px; font-weight: 700;
}
/* The active row carries a 2px blue bar on its leading edge -- the trainer's
   own .nav-item language, and the one piece of chrome that survives being
   glanced at. clip-path would eat a left border, so it is a ::before. */
.nav-item {
  position: relative;
  display: flex; align-items: center; gap: 10px;
  padding: 8px 10px; clip-path: var(--cut-6);
  font-size: clamp(12.5px, 0.88vw, 13.5px); color: var(--text-muted);
  transition: background 0.12s ease, color 0.12s ease;
}
.nav-item::before {
  content: ''; position: absolute; left: 0; top: 4px; bottom: 4px; width: 2px;
  background: var(--accent-blue); opacity: 0; transition: opacity 0.12s ease;
}
.nav-item:hover { background: var(--bg-hover); color: var(--text-primary); }
.nav-item.active {
  background: rgba(59,130,246,0.10);
  color: var(--text-bright);
  font-weight: 500;
}
.nav-item.active::before { opacity: 1; }
.nav-item.active .nav-ico { color: var(--accent-blue); }
.nav-ico { width: 16px; text-align: center; font-size: 13px; color: var(--text-dim); }
.nav-count {
  margin-left: auto; font-family: var(--font); font-size: 10px; font-weight: 600;
  color: var(--text-muted); background: rgba(59,130,246,0.12);
  padding: 1px 6px; clip-path: var(--cut-3);
}

/* Past --shell-max the surplus becomes gutter instead of stretching a four-item
   row into four 563px boxes.
   The cap is a PADDING on the track, not a max-width on each child: a child
   with its own smaller max-width (the 640px pipeline form, the 420px shot-list
   tile) would then centre itself in the page and read as a floating dialog
   rather than as the next thing in the column. This way the column is centred
   and everything inside it stays left-aligned to it.
   vw rather than %, because percentage padding on a flex item resolves against
   .shell -- which is the whole viewport, sidebar included -- and would
   overshoot by exactly the rail's width. */
.main {
  flex: 1; min-width: 0;
  padding: clamp(18px, 1.8vw, 30px)
           max(var(--gut), (100vw - var(--sidebar-w) - var(--shell-max)) / 2)
           72px;
}

/* The site's eyebrow: dot, 32px rule, letter-spaced uppercase label. */
.topbar {
  display: flex; align-items: flex-end; justify-content: space-between;
  gap: 20px; margin-bottom: clamp(18px, 1.7vw, 28px); flex-wrap: wrap;
  padding-bottom: clamp(14px, 1.3vw, 22px);
  border-bottom: 1px solid rgba(59,130,246,0.07);
}
.page-title {
  font-size: var(--h1); font-weight: 700; letter-spacing: -0.02em;
  color: var(--text-bright); text-transform: uppercase; line-height: 1.1;
}
.page-sub { font-size: clamp(12px, 0.85vw, 13.5px); color: var(--text-muted); margin-top: 5px; max-width: 62ch; }
.topbar-actions { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }

/* ── Buttons ───────────────────────────────────────────── */
/* The site's button: uppercase Outfit, 700, .05em, notched, flat fill, no
   border on the filled variant and no outer glow. */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  height: clamp(30px, 2.3vw, 36px); padding: 0 clamp(13px, 1.1vw, 20px);
  font-family: var(--font-ui); font-size: clamp(10.5px, 0.78vw, 12px); font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.05em; white-space: nowrap;
  color: var(--accent-blue);
  border: 1px solid rgba(59,130,246,0.2); clip-path: var(--cut);
  background: rgba(59,130,246,0.08);
  cursor: pointer; transition: filter 0.12s ease, background 0.12s ease, color 0.12s ease;
}
.btn:hover { filter: brightness(1.25); color: #93c5fd; }
.btn:active { transform: translateY(1px); }
/* Filled with --sp-blue, not --accent-blue: white on #3b82f6 measures 3.68:1
   and fails AA. #2563eb is 5.17:1 and looks the same at this size. */
.btn-primary { background: var(--sp-blue); border-color: transparent; color: #fff; }
.btn-primary:hover { filter: brightness(1.15); color: #fff; }
.btn-sm { height: 26px; padding: 0 11px; font-size: 10.5px; clip-path: var(--cut-6); }
.btn-danger { border-color: rgba(239,68,68,0.3); color: var(--accent-red); background: rgba(239,68,68,0.07); }
.btn-danger:hover { background: rgba(239,68,68,0.14); color: #fca5a5; }

/* ── Cards ─────────────────────────────────────────────── */
/* #060a14 on a blue hairline with a top-edge wash and a border that lights on
   hover. The site gives this 44px of padding; a dashboard cannot, but 16px was
   the other failure -- --pad runs 15 to 26 so the measure opens up with the
   monitor instead of staying cramped on a 27". */
.card {
  position: relative;
  background: var(--sp-ink);
  border: 1px solid var(--sp-line);
  clip-path: var(--cut);
  padding: var(--pad);
  transition: border-color 0.2s ease;
}
.card::before {
  content: ''; position: absolute; inset: 0;
  background: var(--sp-wash);
  pointer-events: none;
}
.card:hover { border-color: var(--sp-line-lit); }
.card > * { position: relative; }

.card-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; margin-bottom: calc(var(--pad) * 0.72);
}
/* Dot + rule + label, the site's eyebrow. One line of CSS per part, and it is
   the strongest cheap signal that a panel belongs to this product. */
.card-title {
  display: flex; align-items: center; gap: 8px;
  font-size: clamp(9.5px, 0.7vw, 11px); letter-spacing: 0.15em;
  text-transform: uppercase; color: var(--text-muted); font-weight: 700;
}
.card-title::before {
  content: ''; flex: none; width: 5px; height: 5px;
  background: var(--accent-blue); clip-path: polygon(50% 0, 100% 50%, 50% 100%, 0 50%);
}

.grid { display: grid; gap: var(--gap); }
/* minmax(0, 1fr) rather than a bare 1fr: a bare 1fr has min-width:auto, so one
   long unbroken string (a URL in a table cell) pushes the whole column wider
   than the grid and the row overflows. */
.grid-4 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 208px), 1fr)); }
.grid-accts { grid-template-columns: repeat(auto-fit, minmax(min(100%, 178px), 1fr)); }
.grid-3 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 272px), 1fr)); }
.grid-2 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 352px), 1fr)); }
.mb { margin-bottom: var(--gap); }

/* The two-up row at the foot of a page was the worst of the void: two
   short cards and 900px of nothing under them. They get a vh-aware floor, so
   the taller the monitor the taller they are. */
.grid-2 > .card, .grid-2 > div > .card:only-child { min-height: var(--panel-min); }
.grid-2 > .card { display: flex; flex-direction: column; }
.grid-2 > .card > .empty { flex: 1; }

/* ── Stat tiles ────────────────────────────────────────── */
/* .stat-cell on the site sinks BELOW the card it sits in (#030508 on #060a14).
   Doing the same here is what stops four metrics reading as four empty boxes:
   the figure sits in a well, not on a slab. */
.stat { position: relative; overflow: hidden; background: var(--sp-sink); }
/* The site's .stat-cell lights a 2px rule along its bottom edge on hover. Kept
   because flat fills carry their depth in treatments like this one, not in
   gloss -- take the geometry from the site and you have to take its
   enrichments too, or the surface just reads as dead. */
.stat::after {
  content: ''; position: absolute; bottom: 0; left: 18%; right: 18%; height: 2px;
  background: linear-gradient(90deg, transparent, var(--accent-blue), transparent);
  opacity: 0; transition: opacity 0.3s ease;
}
.stat:hover::after { opacity: 1; }
.stat-label { font-size: clamp(9px, 0.66vw, 10.5px); letter-spacing: 0.16em; text-transform: uppercase; color: var(--text-muted); font-weight: 700; }
/* The site's hero figure: JetBrains Mono 800 at -.04em, white. This is the only
   large type in the product -- headings stay at --h1 and under. */
.stat-value {
  font-family: var(--font); font-size: var(--fig); font-weight: 800; color: #fff;
  line-height: 1; margin-top: clamp(8px, 0.8vw, 14px); letter-spacing: -0.04em;
  font-variant-numeric: tabular-nums;
}
.stat-value.sm { font-size: var(--fig-sm); }
/* A metric with no source behind it. Dim, so it reads as absent rather
   than as a real measurement that happens to be zero. */
.stat-value.none { color: var(--text-dim); font-weight: 700; }
.stat-foot { display: flex; align-items: center; gap: 8px; margin-top: 10px; flex-wrap: wrap; }
.delta { font-family: var(--font); font-size: 11px; font-weight: 700; padding: 1px 6px; clip-path: var(--cut-3); }
.delta.up { color: var(--accent-green); background: rgba(34,197,94,0.12); }
.delta.down { color: var(--accent-red); background: rgba(239,68,68,0.12); }
.delta.flat { color: var(--text-dim); background: rgba(255,255,255,0.04); }
.stat-note { font-size: clamp(10.5px, 0.75vw, 12px); color: var(--text-dim); }

/* ── Badges / pills ────────────────────────────────────── */
.badge {
  display: inline-flex; align-items: center; gap: 5px;
  font-size: 9.5px; font-weight: 700; letter-spacing: 0.1em; text-transform: uppercase;
  padding: 2px 7px; clip-path: var(--cut-4); border: 1px solid transparent;
}
.badge-demo { color: var(--accent-yellow); background: rgba(234,179,8,0.10); border-color: rgba(234,179,8,0.3); }
.badge-live { color: var(--accent-green); background: rgba(34,197,94,0.10); border-color: rgba(34,197,94,0.3); }
.badge-off { color: var(--text-dim); background: rgba(255,255,255,0.03); border-color: var(--bg-border); }

/* Was a 20px rounded pill -- the site has no pill shapes at all. */
.pill { display: inline-flex; align-items: center; gap: 5px; font-size: 10px; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase; font-family: var(--font); padding: 3px 8px; clip-path: var(--cut-4); border: 1px solid var(--bg-border); color: var(--text-muted); }
.pill.idea { color: var(--text-muted); }
.pill.scripted { color: var(--accent-purple); background: rgba(168,85,247,0.10); border-color: rgba(168,85,247,0.25); }
.pill.produced { color: var(--accent-orange); background: rgba(249,115,22,0.10); border-color: rgba(249,115,22,0.25); }
.pill.scheduled { color: var(--accent-blue); background: rgba(59,130,246,0.10); border-color: rgba(59,130,246,0.25); }
.pill.posted { color: var(--accent-green); background: rgba(34,197,94,0.10); border-color: rgba(34,197,94,0.25); }

/* Platform dots -- status dots are the only round things on the site. */
.pdot { width: 7px; height: 7px; border-radius: 50%; display: inline-block; flex: none; }
.p-instagram { background: #e1306c; } .c-instagram { color: #e1306c; }
.p-facebook  { background: #1877f2; } .c-facebook  { color: #1877f2; }
.p-tiktok    { background: #25f4ee; } .c-tiktok    { color: #25f4ee; }
.p-youtube   { background: #ff0000; } .c-youtube   { color: #ff0000; }
.p-x         { background: #d1d5db; } .c-x         { color: #d1d5db; }
.p-reddit    { background: #ff4500; } .c-reddit    { color: #ff4500; }
.p-discord   { background: #5865f2; } .c-discord   { color: #5865f2; }

/* ── Account cards ─────────────────────────────────────── */
.acct { display: block; transition: border-color 0.14s ease; }
.acct:hover { border-color: var(--sp-line-lit); }
/* The badge used to sit in the same row as the handle and took 64px of a
   143px card, leaving 82px for a 106px name -- "@streetpokerhud" is one token
   with nothing to break on, so it ran under the badge. It belongs next to the
   platform label anyway: it describes where the number came from, not who the
   account is. */
.acct-top { margin-bottom: 12px; }
.acct-top .badge { flex: none; margin-left: auto; }
/* Was nowrap + ellipsis in a 172px column, which cut "Street Poker HUD" down to
   "Street Poker ...". Two lines beats a truncated name, and the height is
   reserved whether or not it needs them so the big numeral sits on the same
   baseline across the whole grid. */
.acct-handle {
  font-size: clamp(12px, 0.85vw, 13.5px); font-weight: 600; color: var(--text-primary);
  line-height: 1.25; min-height: 2.5em;
  display: flex; align-items: baseline; gap: 7px;
  /* Still break rather than clip: a long handle in a narrow card has nowhere
     else to go, and two lines are already reserved for it above. */
  overflow-wrap: anywhere;
}
.acct-handle .pdot { flex: none; align-self: center; }
.acct-plat {
  display: flex; align-items: center; gap: 6px; margin-top: 3px;
  font-size: 9.5px; letter-spacing: 0.12em; text-transform: uppercase;
  color: var(--text-dim); font-weight: 600;
}
.spark { display: block; width: 100%; height: 34px; margin-top: 10px; overflow: visible; }

/* ── Tables ────────────────────────────────────────────── */
/* A wide table (creators has 8 columns) was being clipped by the card's
   clip-path at narrow widths -- the notes column just vanished off the edge.
   Scroll the card that holds a table instead of losing columns. :has scopes it
   to exactly those cards, so nothing else grows a scrollbar. */
.card:has(table) { overflow-x: auto; }
table { width: 100%; border-collapse: collapse; }
th {
  text-align: left; font-size: clamp(9px, 0.66vw, 10.5px); letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--text-muted); font-weight: 700; padding: 0 10px 10px; border-bottom: 1px solid var(--sp-line);
  white-space: nowrap;
}
td { padding: clamp(10px, 0.9vw, 14px) 10px; border-bottom: 1px solid rgba(255,255,255,0.035); font-size: clamp(12.5px, 0.88vw, 13.5px); color: var(--text-body); vertical-align: middle; }
tr:last-child td { border-bottom: none; }
tbody tr { transition: background 0.1s ease; }
tbody tr:hover { background: rgba(59,130,246,0.04); }
td.num, th.num { text-align: right; font-family: var(--font); font-variant-numeric: tabular-nums; }
td.num { font-size: clamp(12px, 0.84vw, 13px); }
/* A header row over nothing is a hole, not a table. */
.tr-empty:hover { background: none; }
.tr-empty td {
  padding: clamp(22px, 2.6vw, 38px) 14px; text-align: center; color: var(--text-dim);
  background: var(--sp-sink); line-height: 1.5;
}
.t-strong { color: var(--text-bright); font-weight: 600; }
.t-dim { color: var(--text-dim); font-size: clamp(11px, 0.78vw, 12px); }

/* ── Forms ─────────────────────────────────────────────── */
label.f { display: block; font-size: clamp(9px, 0.66vw, 10.5px); letter-spacing: 0.14em; text-transform: uppercase; color: var(--text-muted); font-weight: 700; margin: clamp(14px, 1.2vw, 20px) 0 7px; }
/* Enumerated rather than bare `input`, so checkboxes keep their native look.
   password/email were missing, which left the login field unstyled -- narrow,
   light and un-notched next to the one above it. */
input[type=text], input[type=password], input[type=email], input[type=url],
input[type=number], input[type=datetime-local], input[type=file], textarea, select {
  width: 100%; padding: 10px 12px;
  background: var(--sp-inset); border: 1px solid var(--bg-border-solid); clip-path: var(--cut-4);
  color: var(--text-bright); font-family: var(--font-ui); font-size: clamp(12.5px, 0.88vw, 13.5px);
  transition: border-color 0.12s ease, box-shadow 0.12s ease;
}
/* The ring is INSET: clip-path clips an outer box-shadow along the diagonal,
   so a normal focus ring would be sliced off at both notched corners. */
input:focus, textarea:focus, select:focus { outline: none; border-color: var(--accent-blue); box-shadow: inset 0 0 0 2px rgba(59,130,246,0.35); }
textarea { min-height: clamp(90px, 11vh, 150px); resize: vertical; line-height: 1.5; }
td select, td input { width: auto; min-width: 104px; }
.hint { font-size: clamp(11px, 0.79vw, 12.5px); color: var(--text-dim); margin-top: 8px; line-height: 1.5; }
.hint code, code { font-family: var(--font); font-size: 0.92em; color: var(--text-muted); background: rgba(59,130,246,0.07); padding: 1px 4px; }
.row { display: flex; gap: 12px; flex-wrap: wrap; }
.row > * { flex: 1; min-width: 150px; }
.checks { display: flex; gap: 8px; flex-wrap: wrap; }
.check {
  display: inline-flex; align-items: center; gap: 7px; cursor: pointer;
  padding: 8px 13px; border: 1px solid var(--bg-border-solid); clip-path: var(--cut-4);
  font-size: 12.5px; color: var(--text-muted); transition: all 0.12s ease;
}
.check:hover { border-color: rgba(255,255,255,0.16); color: var(--text-primary); }
.check input { accent-color: var(--accent-blue); }
.check.on { border-color: rgba(59,130,246,0.4); background: rgba(59,130,246,0.08); color: var(--text-bright); }

/* ── Lint findings ─────────────────────────────────────── */
.lint { margin-top: 12px; display: grid; gap: 7px; }
.lint-item { display: flex; gap: 9px; padding: 10px 12px; clip-path: var(--cut-4); font-size: clamp(11.5px, 0.84vw, 13px); line-height: 1.45; border: 1px solid transparent; }
.lint-item.block { background: rgba(239,68,68,0.08); border-color: rgba(239,68,68,0.28); color: #fca5a5; }
.lint-item.warn { background: rgba(234,179,8,0.07); border-color: rgba(234,179,8,0.25); color: #fde047; }
.lint-item.ok { background: rgba(34,197,94,0.07); border-color: rgba(34,197,94,0.25); color: #86efac; }
.lint-ico { font-weight: 700; flex: none; }

/* ── Calendar ──────────────────────────────────────────── */
.cal { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: 7px; }
.cal-h { font-size: clamp(9px, 0.66vw, 10.5px); letter-spacing: 0.14em; text-transform: uppercase; color: var(--text-muted); font-weight: 700; text-align: center; padding-bottom: 8px; }
/* vh, not px: four weeks should fill a tall monitor rather than sit in the top
   third of it. */
.cal-day { min-height: clamp(86px, 13vh, 168px); border: 1px solid var(--sp-line); clip-path: var(--cut-6); padding: 8px; background: var(--sp-inset); }
.cal-day.today { border-color: rgba(59,130,246,0.45); background: rgba(59,130,246,0.06); }
/* Was .cal-day.empty, which collided with the .empty STATE below and gave
   every past day a centred blue "+". A modifier that means "past" should say
   so; a bare state word next to a component class is how that happens. */
.cal-day.is-past { opacity: 0.3; }
.cal-num { font-family: var(--font); font-size: 11px; font-weight: 600; color: var(--text-muted); margin-bottom: 6px; }
.cal-ev { font-size: 10.5px; padding: 4px 5px; clip-path: var(--cut-3); margin-bottom: 3px; background: rgba(59,130,246,0.14); color: #bfdbfe; overflow: hidden; display: flex; align-items: flex-start; gap: 4px; }
.cal-ev .pdot { margin-top: 4px; }
.cal-ev-t {
  overflow: hidden; white-space: normal; line-height: 1.25;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
}
.cal-gap { font-size: 10px; color: var(--accent-yellow); opacity: 0.65; }

/* ── Pipeline board ────────────────────────────────────── */
.board { display: grid; grid-template-columns: repeat(5, minmax(190px, 1fr)); gap: var(--gap); overflow-x: auto; padding-bottom: 8px; }
.col-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 10px; padding: 0 3px 8px; border-bottom: 1px solid var(--sp-line); }
.col-name { font-size: clamp(9px, 0.66vw, 10.5px); letter-spacing: 0.14em; text-transform: uppercase; color: var(--text-muted); font-weight: 700; }
.col-count { font-family: var(--font); font-size: 10px; font-weight: 600; color: var(--text-dim); }
.col-body { display: grid; gap: 8px; align-content: start; min-height: 60px; }
.cardlet {
  background: var(--sp-ink); border: 1px solid var(--sp-line); clip-path: var(--cut-6);
  padding: 11px 12px; font-size: 12.5px; transition: border-color 0.12s ease;
}
.cardlet:hover { border-color: var(--sp-line-lit); }
.cardlet-title { color: var(--text-primary); font-weight: 500; line-height: 1.35; margin-bottom: 8px; }
.cardlet-meta { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.cardlet-thumb { width: 100%; clip-path: var(--cut-4); margin-bottom: 8px; border: 1px solid var(--bg-border); display: block; }
.move { display: flex; gap: 4px; margin-top: 9px; }
.move button { flex: 1; font-size: 10px; height: 22px; padding: 0; }
/* An empty column slot. ⛔ NOT a dashed rounded rectangle -- that is the single
   strongest "template" tell on a dark surface. A sunken well in the card's own
   shape reads as part of the product. */
.cardlet.is-empty {
  background: var(--sp-sink); border-style: solid; border-color: rgba(59,130,246,0.07);
  color: var(--text-dim); text-align: center; font-size: 11px;
  letter-spacing: 0.12em; text-transform: uppercase; padding: 18px 12px;
}

/* ── Empty states ──────────────────────────────────────── */
/* Was grey text floating in a large card, which is what made a half-populated
   page read as broken. Now the site's .term inset: sunken fill, notch, a lit
   blue mark, and it CENTRES in whatever space it is given. */
.empty {
  display: grid; place-content: center; justify-items: center; gap: 10px;
  text-align: center; padding: clamp(24px, 3vw, 44px) 18px;
  color: var(--text-dim); font-size: clamp(12px, 0.85vw, 13.5px); line-height: 1.5;
  background: var(--sp-sink); border: 1px solid rgba(59,130,246,0.07);
  clip-path: var(--cut-4);
}
.empty::before {
  content: '+'; display: grid; place-items: center;
  width: 30px; height: 30px; font-size: 17px; font-weight: 300;
  color: var(--accent-blue); background: rgba(59,130,246,0.10);
  border: 1px solid rgba(59,130,246,0.22); clip-path: var(--cut-4);
}
.empty a { color: var(--accent-blue); font-weight: 600; }
/* Some "empty" states are good news -- an empty queue, no demo rows left. A
   blue + invites you to fix something that is not broken. */
.empty--ok::before { content: '✓'; font-size: 14px; color: var(--accent-green); background: rgba(34,197,94,0.10); border-color: rgba(34,197,94,0.22); }

/* ── Misc ──────────────────────────────────────────────── */
.flash { padding: 12px 15px; clip-path: var(--cut-6); margin-bottom: var(--gap); font-size: 13px; border: 1px solid rgba(34,197,94,0.3); background: rgba(34,197,94,0.08); color: #86efac; }
.live-dot { width: 5px; height: 5px; border-radius: 50%; background: var(--accent-blue); animation: pulse 2s ease-in-out infinite; }
@keyframes pulse { 0%,100% { opacity: 1; } 50% { opacity: 0.35; } }
@media (prefers-reduced-motion: reduce) { .live-dot { animation: none; } }
.meta-line { display: flex; align-items: center; gap: 7px; font-size: clamp(10.5px, 0.75vw, 11.5px); color: var(--text-dim); flex-wrap: wrap; }
/* A 2px rule, not a rounded bar -- the site's meter. */
.bar { height: 2px; background: rgba(255,255,255,0.07); overflow: hidden; }
.bar > i { display: block; height: 100%; background: var(--accent-blue); }
.funnel-step { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: clamp(9px, 0.85vw, 13px) 0; border-bottom: 1px solid rgba(255,255,255,0.045); }
.funnel-step:last-of-type { border-bottom: none; }
.funnel-name { font-size: clamp(12px, 0.85vw, 13.5px); color: var(--text-body); display: flex; align-items: center; gap: 7px; }
.funnel-num { font-family: var(--font); font-size: clamp(14px, 1vw, 17px); font-weight: 700; color: var(--text-bright); font-variant-numeric: tabular-nums; }
.funnel-rate { font-family: var(--font); font-size: clamp(10.5px, 0.76vw, 12px); color: var(--accent-blue); }
.preview-img { width: 100%; max-width: clamp(260px, 26vw, 420px); clip-path: var(--cut); border: 1px solid var(--bg-border); display: block; margin-inline: auto; }

/* ── Ad studio ─────────────────────────────────────────── */
/* The library was a fixed 96px grid, so on a 27" it was a wall of stamps with
   the rest of the card empty. Creatives are 1080x1920 -- give the tile the
   real aspect so a thumbnail looks like the thing it will become. */
.ad-lib { display: grid; grid-template-columns: repeat(auto-fill, minmax(clamp(96px, 8vw, 148px), 1fr)); gap: 10px; align-content: start; }
.ad-lib img {
  width: 100%; aspect-ratio: 9 / 16; object-fit: cover; display: block;
  clip-path: var(--cut-6); border: 1px solid var(--sp-line);
  transition: border-color 0.14s ease, filter 0.14s ease;
}
.ad-lib a:hover img { border-color: var(--sp-line-lit); filter: brightness(1.12); }
/* The studio's two columns are a 900px form and a short thumbnail feed. Left to
   stretch, the library card measured 614x914 holding three 240px tiles -- 640px
   of empty card. align-items:start lets it end where its content does, and
   sticky then keeps it in view while you fill in the long form beside it. */
.grid-studio { align-items: start; }
.grid-studio > .card:last-child { position: sticky; top: clamp(18px, 1.8vw, 30px); }

@media (min-width: 1500px) {
  /* The form has more to say than the feed does: an even split gave the fields
     the same width as a column of thumbnails. */
  .grid-studio { grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr); }
}
@media (max-width: 860px) {
  /* Sticky in a single-column stack pins the library over the form. */
  .grid-studio > .card:last-child { position: static; }
}

@media (max-width: 860px) {
  /* The sidebar used to be display:none here, and it is the only navigation in
     the app -- below 860px there was no way to reach another page at all. It
     becomes a horizontal strip instead. */
  .shell { display: block; }
  .sidebar {
    width: auto; flex: none; height: auto; position: sticky; top: 0; z-index: 10;
    border-right: none; border-bottom: 1px solid var(--sp-line);
    flex-direction: row; align-items: center; gap: 6px;
    overflow-x: auto; overflow-y: hidden; padding: 10px 12px;
  }
  .brand { padding: 0 6px 0 0; flex: none; }
  .brand-name, .nav-label, .nav-count { display: none; }
  .nav-group { margin: 0; padding-top: 0; border-top: none; display: flex; gap: 6px; }
  .nav-item { white-space: nowrap; }
  .main { padding: 18px 16px 50px; }
  .board { grid-template-columns: repeat(5, 78vw); }
  .cal { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .cal-h { display: none; }
  .topbar { align-items: flex-start; flex-direction: column; gap: 12px; }
}

/* ── File input ────────────────────────────────────────── */
/* Styled through the native ::file-selector-button pseudo-element rather than
   the usual hidden-input-plus-label dance: same result, no extra markup and no
   script to keep the filename label in sync. */
input[type=file] { padding: 8px 10px; cursor: pointer; }
input[type=file]::file-selector-button {
  margin-right: 11px; height: 26px; padding: 0 13px;
  font-family: var(--font-ui); font-size: 10.5px; font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.05em;
  color: var(--accent-blue);
  background: rgba(59,130,246,0.08);
  border: 1px solid rgba(59,130,246,0.2);
  clip-path: var(--cut-6);
  cursor: pointer; transition: filter 0.12s ease;
}
input[type=file]::file-selector-button:hover { filter: brightness(1.3); }

/* ── Auth ──────────────────────────────────────────────── */
.signed-in {
  display: flex; align-items: center; gap: 8px;
  padding: 0 8px 16px; margin-top: -6px;
}
.signed-in-who {
  font-family: var(--font); font-size: 10px; letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--text-muted);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.signed-in form { margin-left: auto; }
/* Pushed to the bottom of the rail on desktop, where a sign-out belongs;
   the 860px strip puts it back in flow. */
@media (min-width: 861px) { .signed-in { margin-top: auto; padding-top: 16px; padding-bottom: 0; border-top: 1px solid rgba(59,130,246,0.07); } }

.login-body { display: grid; place-items: center; min-height: 100vh; padding: 24px; }
.login-card { width: 100%; max-width: 360px; padding: clamp(26px, 3vw, 36px); }
.login-mark { height: 26px; width: auto; display: block; margin-bottom: 20px; }
.login-title { font-size: 21px; font-weight: 700; text-transform: uppercase; letter-spacing: -0.02em; color: var(--text-bright); }
.login-sub { font-size: 12.5px; color: var(--text-muted); margin-top: 4px; }
.login-card label.f:first-of-type { margin-top: 22px; }
.login-error { margin-top: 14px; }
.login-go { width: 100%; margin-top: 20px; height: 40px; }

/* ══════════════════════════════════════════════════════════
   DASHBOARD SURFACES

   Everything below answers the same brief as the block at the top of this
   file: the notch, flat near-black fills, JetBrains Mono numerals, and no
   fixed size a monitor can outgrow. Nothing here introduces a new colour --
   platform colours are declared exactly once, as .p-<platform>, and the chart
   reads them back off a probe element rather than keeping a second copy.
   ══════════════════════════════════════════════════════════ */

/* ── Sidebar search trigger ──────────────────────────────── */
.omni {
  display: flex; align-items: center; gap: 8px; width: 100%;
  margin-bottom: 16px; padding: 0 9px; height: 30px;
  background: var(--sp-inset); border: 1px solid var(--sp-line);
  clip-path: var(--cut-6); cursor: pointer;
  color: var(--text-dim); font-family: var(--font-ui);
  font-size: clamp(11px, 0.78vw, 12.5px);
}
.omni:hover { border-color: var(--sp-line-lit); color: var(--text-muted); }
.omni-ico { font-size: 12px; }
.omni-text { flex: 1; text-align: left; overflow: hidden; white-space: nowrap; }
kbd {
  font-family: var(--font); font-size: 9.5px; font-weight: 600;
  padding: 2px 4px; color: var(--text-dim);
  background: rgba(255,255,255,0.05); border: 1px solid var(--bg-border);
  clip-path: var(--cut-3);
}
.nav-count--alert {
  color: var(--accent-yellow); background: rgba(234,179,8,0.14);
  border-color: rgba(234,179,8,0.3);
}

/* ── Segmented control (range / week paging) ─────────────── */
.seg { display: inline-flex; border: 1px solid var(--sp-line); clip-path: var(--cut-6); background: var(--sp-inset); }
.seg-b {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 42px; height: 26px; padding: 0 10px;
  font-family: var(--font); font-size: 10.5px; font-weight: 700;
  letter-spacing: 0.06em; color: var(--text-dim);
  border-right: 1px solid var(--sp-line);
}
.seg-b:last-child { border-right: none; }
.seg-b:hover { color: var(--text-primary); background: var(--bg-hover); }
.seg-b.on { color: #fff; background: var(--sp-blue); }

.filter {
  height: 26px; width: clamp(120px, 14vw, 200px); padding: 0 10px;
  font-size: 11.5px; font-family: var(--font-ui);
  background: var(--sp-inset); border: 1px solid var(--sp-line);
  color: var(--text-body); clip-path: var(--cut-6);
}
.filter::placeholder { color: var(--text-dim); }
.filter:focus { outline: none; border-color: var(--accent-blue); }

.stat-of { color: var(--text-dim); font-size: 0.55em; font-weight: 600; }

/* ── Needs you ───────────────────────────────────────────── */
/* Borrowed from Stripe's "action required" strip: the thing that is wrong
   goes above the numbers, because the numbers only mean something once you
   know whether anything needs doing. */
.attn-row {
  display: flex; align-items: flex-start; gap: 11px;
  padding: clamp(10px, 0.9vw, 14px) 0;
  border-bottom: 1px solid rgba(255,255,255,0.045);
}
.attn-row:last-child { border-bottom: none; }
.attn-row:hover .attn-title { color: var(--text-bright); }
.attn-row:hover .attn-cta { color: #93c5fd; }
.attn-dot { width: 6px; height: 6px; flex: none; margin-top: 6px; clip-path: var(--cut-3); background: var(--text-dim); }
.attn--block .attn-dot { background: var(--accent-red); box-shadow: 0 0 8px rgba(239,68,68,0.6); }
.attn--warn .attn-dot { background: var(--accent-yellow); }
.attn--info .attn-dot { background: var(--accent-blue); }
.attn-body { min-width: 0; flex: 1; }
.attn-title { display: block; color: var(--text-primary); font-weight: 600; font-size: clamp(12.5px, 0.9vw, 14px); }
.attn-detail { display: block; margin-top: 3px; color: var(--text-dim); font-size: clamp(11px, 0.79vw, 12.5px); line-height: 1.5; }
.attn-cta {
  flex: none; align-self: center; font-family: var(--font);
  font-size: clamp(10px, 0.72vw, 11.5px); font-weight: 600; color: var(--accent-blue);
  white-space: nowrap;
}

/* ── The chart ───────────────────────────────────────────── */
/* One dominant time series with a range switch above it, the way Plausible and
   Vercel's analytics do. The legend doubles as the per-channel readout so the
   space under the axis is not wasted on a key nobody needs twice. */
.chart { position: relative; margin-top: 4px; }
.chart-svg { display: block; width: 100%; }
.chart-grid { stroke: rgba(255,255,255,0.05); stroke-width: 1; }
.chart-ytick, .chart-xtick {
  fill: var(--text-dim); font-family: var(--font); font-size: 9.5px;
  font-variant-numeric: tabular-nums;
}
.chart-cross { stroke: rgba(59,130,246,0.45); stroke-width: 1; stroke-dasharray: 3 3; }
.chart-tip {
  position: absolute; top: 6px; pointer-events: none;
  background: rgba(3,7,16,0.96); border: 1px solid var(--sp-line-lit);
  clip-path: var(--cut-4); padding: 9px 11px; min-width: 132px;
  font-size: 11px; z-index: 3;
}
.tip-d { font-family: var(--font); font-size: 9.5px; letter-spacing: 0.1em; text-transform: uppercase; color: var(--text-dim); margin-bottom: 6px; }
.tip-r { display: flex; align-items: center; gap: 6px; color: var(--text-muted); padding: 2px 0; text-transform: capitalize; }
.tip-r b { margin-left: auto; font-family: var(--font); color: var(--text-bright); font-variant-numeric: tabular-nums; }

.chart-legend { display: flex; flex-wrap: wrap; gap: 7px; margin-top: 14px; }
.lg {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 5px 10px; background: var(--sp-inset);
  border: 1px solid var(--sp-line); clip-path: var(--cut-4);
  cursor: pointer; font-family: var(--font-ui); font-size: 11.5px; color: var(--text-muted);
}
.lg:hover { border-color: var(--sp-line-lit); }
.lg.off { opacity: 0.4; }
.lg.off .lg-dot { background: var(--text-dim) !important; }
.lg-dot { width: 7px; height: 7px; border-radius: 50%; flex: none; }
.lg-name { text-transform: capitalize; }
.lg-val { font-family: var(--font); font-weight: 700; color: var(--text-bright); font-variant-numeric: tabular-nums; }
.lg-move { font-family: var(--font); font-size: 10px; font-weight: 600; }
.lg-move.up { color: var(--accent-green); }
.lg-move.down { color: var(--accent-red); }
.lg-move.flat { color: var(--text-dim); }

/* ── Cadence bars ────────────────────────────────────────── */
.bars {
  position: relative; display: grid; grid-auto-flow: column; grid-auto-columns: 1fr;
  gap: clamp(5px, 0.6vw, 10px); align-items: end;
  height: clamp(110px, 15vh, 180px); margin-top: 6px;
  padding-bottom: 18px;
}
/* The floor the marketing plan sets, drawn where it falls. */
.bars::after {
  content: ''; position: absolute; left: 0; right: 0; bottom: calc(18px + var(--floor));
  border-top: 1px dashed rgba(234,179,8,0.45); pointer-events: none;
}
.bar-col { position: relative; height: 100%; display: flex; flex-direction: column; justify-content: flex-end; }
/* The empty track. Without it a zero week renders as nothing, which reads as a
   missing column rather than as "you posted nothing that week" -- and those
   weeks are the entire point of this chart. */
.bar-col::before {
  content: ''; position: absolute; inset: 0;
  background: rgba(255,255,255,0.028);
  clip-path: polygon(0 3px, 3px 0, 100% 0, 100% 100%, 0 100%);
}
.bar-fill {
  position: relative; z-index: 1; min-height: 2px; background: var(--sp-blue);
  clip-path: polygon(0 3px, 3px 0, 100% 0, 100% 100%, 0 100%);
}
.bar-fill.under { background: rgba(234,179,8,0.3); }
.bar-n {
  position: absolute; top: -15px; left: 0; right: 0; text-align: center;
  font-family: var(--font); font-size: 10px; font-weight: 700; color: var(--text-muted);
}
.bar-x {
  position: absolute; bottom: -18px; left: 0; right: 0; text-align: center;
  font-family: var(--font); font-size: 9px; color: var(--text-dim);
}

/* ── Activity feed ───────────────────────────────────────── */
/* minmax(0, 1fr): an auto column grows to the longest nowrap label and pushes
   the page sideways on a phone; this lets the label's ellipsis do its job. */
.feed { display: grid; grid-template-columns: minmax(0, 1fr); }
.feed-row {
  display: flex; align-items: center; gap: 10px;
  padding: clamp(7px, 0.7vw, 11px) 0;
  border-bottom: 1px solid rgba(255,255,255,0.035);
  font-size: clamp(11.5px, 0.84vw, 13px);
}
.feed-row:last-child { border-bottom: none; }
.feed-row:hover .feed-label { color: var(--text-bright); }
.feed-kind {
  flex: none; width: 66px; text-align: center; padding: 2px 0;
  font-family: var(--font); font-size: 9px; font-weight: 700;
  letter-spacing: 0.1em; text-transform: uppercase;
  clip-path: var(--cut-3); color: var(--text-dim);
  background: rgba(255,255,255,0.04); border: 1px solid var(--bg-border);
}
.feed-kind--posted { color: var(--accent-green); background: rgba(34,197,94,0.10); border-color: rgba(34,197,94,0.25); }
.feed-kind--shot { color: var(--accent-purple); background: rgba(168,85,247,0.10); border-color: rgba(168,85,247,0.25); }
.feed-kind--link { color: var(--accent-blue); background: rgba(59,130,246,0.10); border-color: rgba(59,130,246,0.25); }
.feed-kind--creator { color: var(--accent-orange); background: rgba(249,115,22,0.10); border-color: rgba(249,115,22,0.25); }
.feed-label { flex: 1; min-width: 0; color: var(--text-body); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.feed-when { flex: none; font-family: var(--font); font-size: 10.5px; color: var(--text-dim); }

/* ── Toasts ──────────────────────────────────────────────── */
.toasts {
  position: fixed; right: clamp(14px, 2vw, 28px); bottom: clamp(14px, 2vw, 28px);
  z-index: 60; display: grid; gap: 8px; width: min(380px, calc(100vw - 32px));
}
.toast {
  display: flex; align-items: flex-start; gap: 9px;
  padding: 11px 13px; clip-path: var(--cut-6);
  font-size: clamp(11.5px, 0.84vw, 13px); line-height: 1.45;
  background: rgba(3,7,16,0.97); border: 1px solid var(--sp-line-lit);
  color: var(--text-body);
  animation: toast-in 0.18s ease;
}
@keyframes toast-in { from { opacity: 0; transform: translateY(6px); } }
.toast--ok { border-color: rgba(34,197,94,0.32); color: #86efac; }
.toast--warn { border-color: rgba(234,179,8,0.32); color: #fde047; }
.toast--block { border-color: rgba(239,68,68,0.32); color: #fca5a5; }
.toast-ico { font-weight: 700; flex: none; }
.toast-x { margin-left: auto; background: none; border: none; color: inherit; opacity: 0.55; cursor: pointer; font-size: 15px; line-height: 1; }
.toast-x:hover { opacity: 1; }

/* ── Dialogs ─────────────────────────────────────────────── */
dialog { border: none; padding: 0; color: var(--text-body); background: transparent; max-width: none; max-height: none; }
dialog::backdrop { background: rgba(0,0,0,0.74); backdrop-filter: blur(3px); }

.palette {
  width: min(640px, 94vw); margin: 12vh auto auto;
  background: var(--sp-ink); border: 1px solid var(--sp-line-lit); clip-path: var(--cut);
}
.palette-in { display: flex; flex-direction: column; max-height: 66vh; }
.palette-q {
  width: 100%; height: 48px; padding: 0 18px; flex: none;
  background: transparent; border: none; border-bottom: 1px solid var(--sp-line);
  color: var(--text-bright); font-family: var(--font-ui); font-size: 15px;
}
.palette-q:focus { outline: none; box-shadow: none; }
.palette-q::placeholder { color: var(--text-dim); }
.palette-list { overflow-y: auto; padding: 8px; flex: 1; }
.palette-group {
  font-size: 9px; letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--text-dim); font-weight: 700; padding: 10px 10px 6px;
}
.palette-row {
  display: flex; align-items: center; gap: 10px;
  padding: 8px 10px; clip-path: var(--cut-4);
  font-size: 13px; color: var(--text-body); cursor: pointer;
}
.palette-row.is-sel { background: rgba(59,130,246,0.14); color: var(--text-bright); }
.palette-kind {
  flex: none; width: 58px; text-align: center; padding: 2px 0;
  font-family: var(--font); font-size: 8.5px; font-weight: 700;
  letter-spacing: 0.1em; text-transform: uppercase; color: var(--text-dim);
  background: rgba(255,255,255,0.04); border: 1px solid var(--bg-border); clip-path: var(--cut-3);
}
.palette-foot {
  display: flex; gap: 14px; align-items: center; flex: none;
  padding: 9px 14px; border-top: 1px solid var(--sp-line);
  font-size: 10.5px; color: var(--text-dim);
}
.palette-foot-end { margin-left: auto; }

/* A right-hand sheet rather than a centred modal: the board stays visible
   behind it, so moving a card and editing it are the same mental place. */
.sheet {
  margin: 0 0 0 auto; height: 100vh; max-height: 100vh;
  width: min(620px, 96vw);
  background: var(--sp-ink); border-left: 1px solid var(--sp-line-lit);
}
.sheet-in { padding: clamp(20px, 2.2vw, 34px); overflow-y: auto; height: 100vh; }
.sheet-x { position: absolute; top: 12px; right: 14px; z-index: 2; }
.sheet-x button {
  width: 28px; height: 28px; font-size: 16px; line-height: 1; cursor: pointer;
  background: var(--sp-inset); border: 1px solid var(--sp-line);
  color: var(--text-muted); clip-path: var(--cut-4);
}
.sheet-x button:hover { color: var(--text-bright); border-color: var(--sp-line-lit); }
.sheet-head { margin-bottom: 16px; padding-right: 34px; }
.sheet-title { font-size: clamp(16px, 1.3vw, 21px); font-weight: 700; color: var(--text-bright); margin: 8px 0 5px; line-height: 1.25; }
.sheet-move { display: flex; flex-wrap: wrap; gap: 5px; padding: 12px 0; border-block: 1px solid var(--sp-line); }
.sheet-sep { height: 1px; background: var(--sp-line); margin: clamp(20px, 2vw, 30px) 0; }

.steps { margin: 8px 0 14px; padding-left: 20px; color: var(--text-body); font-size: clamp(11.5px, 0.84vw, 13px); line-height: 1.55; }
.steps li { margin: 5px 0; }
.steps a { color: var(--accent-blue); }

/* The post kit tops the sheet: nothing posts by itself, so putting it up by
   hand is the job, and everything it takes sits in one place. */
.kit { padding: 14px; margin-bottom: 16px; background: var(--sp-inset); border: 1px solid var(--sp-line-lit); clip-path: var(--cut-6); }
.kit-grid { display: grid; grid-template-columns: minmax(0, 150px) minmax(0, 1fr); gap: 14px; }
.kit-grid > :only-child { grid-column: 1 / -1; }
.kit-media { display: grid; gap: 8px; align-content: start; }
.kit-media video, .kit-media img { width: 100%; aspect-ratio: 9 / 16; object-fit: contain; background: #000; border: 1px solid var(--bg-border); clip-path: var(--cut-4); display: block; }
.kit-copy { min-width: 0; }
.kit-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-top: 12px; }
.kit-row:first-child { margin-top: 0; }
.kit-label { font-family: var(--font); font-size: 10.5px; letter-spacing: 0.06em; text-transform: uppercase; color: var(--text-muted); }
.kit-count { margin-left: 6px; color: var(--text-dim); }
.kit-over { color: var(--accent-red); font-weight: 700; }
.kit-text {
  margin: 6px 0 0; padding: 9px 11px; max-height: 150px; overflow-y: auto;
  white-space: pre-wrap; overflow-wrap: anywhere;
  font-family: var(--font-ui); font-size: 12.5px; line-height: 1.5; color: var(--text-body);
  background: var(--sp-sink); border: 1px solid var(--sp-line); clip-path: var(--cut-4);
}
.kit-slides { display: flex; flex-wrap: wrap; align-items: center; gap: 5px; }
.kit-slides .btn { min-width: 26px; padding: 0 8px; justify-content: center; }
.kit-poll { display: grid; gap: 5px; margin-top: 6px; }
.kit-opt {
  display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 6px 6px 6px 11px;
  font-size: 12.5px; color: var(--text-body); background: var(--sp-sink); border: 1px solid var(--sp-line); clip-path: var(--cut-4);
}
.kit-pub { margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--sp-line); display: grid; gap: 5px; }
.kit-pub .kit-opt a { color: var(--accent-blue); margin-left: 4px; }
.kit-pub-acts { display: flex; gap: 5px; flex: none; }
.share-url { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-top: 4px; }
.share-url code { flex: 1 1 220px; min-width: 0; overflow-wrap: anywhere; font-size: 13px; padding: 8px 10px;
  border-radius: 8px; background: rgba(59,130,246,0.07); border: 1px solid var(--sp-line); }
.share-new { margin-top: 12px; padding-top: 10px; border-top: 1px solid var(--sp-line); }
.share-new .kit-label { flex-basis: 100%; }
.kit-done { display: flex; align-items: center; flex-wrap: wrap; gap: 10px; margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--sp-line); }
@media (max-width: 520px) {
  .kit-grid { grid-template-columns: minmax(0, 1fr); }
  .kit-media { max-width: 180px; }
}

/* ── Inline record-a-number forms ────────────────────────── */
/* Four of the six platforms have no API. Typing the number in IS the
   integration, so it gets a real affordance rather than a settings page. */
.inline-set { display: flex; gap: 4px; align-items: center; }
.inline-set input { width: 78px; min-width: 0; height: 26px; padding: 0 7px; font-size: 11.5px; }
.inline-set input[type=text] { width: 86px; }
.inline-set select { height: 26px; padding: 0 7px; font-size: 11.5px; min-width: 0; }
.inline-set .btn { flex: none; }

.weekly { display: grid; gap: 8px; }
.weekly-row {
  display: grid; gap: 10px; align-items: center;
  grid-template-columns: minmax(120px, 1.4fr) auto 110px 90px;
  padding: 8px 10px; background: var(--sp-inset);
  border: 1px solid var(--sp-line); clip-path: var(--cut-4);
}
.weekly-who { display: flex; align-items: center; gap: 7px; min-width: 0; margin: 0; cursor: pointer; }
.weekly-was { font-family: var(--font); font-size: 10.5px; color: var(--text-dim); white-space: nowrap; }
.weekly-row input { height: 30px; margin: 0; font-size: 12px; }
@media (max-width: 720px) {
  .weekly-row { grid-template-columns: 1fr 1fr; }
  .weekly-who { grid-column: 1 / -1; }
}

/* ── Board: dragging ─────────────────────────────────────── */
.cardlet[draggable] { cursor: grab; }
.cardlet.dragging { opacity: 0.4; cursor: grabbing; }
.col-body.over { outline: 1px dashed var(--sp-line-lit); outline-offset: 3px; background: rgba(59,130,246,0.04); }
.cardlet-res {
  display: flex; gap: 8px; margin-top: 8px; padding-top: 7px;
  border-top: 1px solid rgba(255,255,255,0.05);
  font-family: var(--font); font-size: 10px; color: var(--text-dim);
}
.cardlet-res-hit { color: var(--accent-blue); font-weight: 700; }

/* ── Calendar extras ─────────────────────────────────────── */
.cal-day { position: relative; }
.cal-mon { color: var(--accent-blue); font-size: 9px; letter-spacing: 0.1em; text-transform: uppercase; }
.cal-add {
  position: absolute; inset: 0; display: grid; place-items: center;
  font-size: 18px; color: var(--text-dim); opacity: 0;
  transition: opacity 0.12s ease;
}
.cal-day:hover .cal-add { opacity: 1; color: var(--accent-blue); background: rgba(59,130,246,0.05); }
a.cal-ev:hover { background: rgba(59,130,246,0.26); }

/* ── Links page ──────────────────────────────────────────── */
.built {
  display: flex; align-items: center; gap: 9px; margin-top: 12px;
  padding: 10px 12px; clip-path: var(--cut-4);
  background: rgba(34,197,94,0.07); border: 1px solid rgba(34,197,94,0.25);
}
.built-ico { color: var(--accent-green); font-weight: 700; flex: none; }
.built-url { flex: 1; min-width: 0; font-family: var(--font); font-size: 11.5px; color: #86efac; word-break: break-all; }
.link-copy {
  margin-top: 3px; padding: 0; background: none; border: none; cursor: pointer;
  font-family: var(--font); font-size: 10px; color: var(--text-dim);
  text-decoration: underline; text-underline-offset: 2px;
}
.link-copy:hover { color: var(--accent-blue); }
.code-hi { font-family: var(--font); font-size: 11.5px; color: var(--accent-blue); }
.code-ok { font-family: var(--font); font-size: 11.5px; color: var(--accent-green); }
.code-off { font-family: var(--font); font-size: 11.5px; color: var(--text-dim); }
.row-done td { opacity: 0.68; }

/* ── Sortable headers ────────────────────────────────────── */
th.sortable { cursor: pointer; user-select: none; }
th.sortable:hover { color: var(--text-primary); }
th.sorted-up::after { content: ' ▲'; font-size: 7px; color: var(--accent-blue); }
th.sorted-down::after { content: ' ▼'; font-size: 7px; color: var(--accent-blue); }

/* Rows in a card that link somewhere. */
a.funnel-step:hover .funnel-name { color: var(--text-bright); }

/* ── Narrow screens ──────────────────────────────────────── */
/* The strip at 860px is already defined above and it is a deliberate design:
   .shell goes to block, the rail becomes a horizontally scrolling row of icons
   with every label hidden. An earlier version of this block re-declared
   .shell/.sidebar as a grid, which put two nav groups in one cell and drew
   "Pipeline" straight through "Attribution". Only add what the strip does not
   already cover. */
@media (max-width: 860px) {
  /* Full-width with a shortcut hint makes no sense in a row of icons, and
     there is no Cmd key on a phone. Keep the affordance, drop the chrome. */
  .omni { width: auto; flex: none; margin-bottom: 0; padding: 0 10px; }
  .omni-text, .omni kbd { display: none; }
  .sheet { width: 100vw; }
  .palette { margin-top: 6vh; }
  .attn-row { flex-wrap: wrap; }
  .attn-cta { margin-left: 17px; }
  .bars { height: 120px; }
}
