/* Vendored from poma-portal portal/css/poma-tokens.css.
 *
 * This app used to <link> this stylesheet straight off poma.life, which meant
 * its entire appearance depended on another product staying up and unchanged.
 * It is a copy now so this app can be served from any origin. Re-sync by hand
 * if the platform tokens move; nothing does it automatically.
 */
/* ═══════════════════════════════════════════════════════════════════
   poma.life — Shared Design Tokens
   Served from https://poma.life/css/poma-tokens.css and linked by every
   app (portal, projects, model, hub). Cache-Control is no-cache, so edits
   here reach all four apps on the next portal deploy.

   TWO SYSTEMS LIVE IN THIS FILE:

   1. LEGACY `--poma-*` (bottom of file) — HSL channel triplets consumed as
      `hsl(var(--poma-bg))`. Used only by the portal's vanilla CSS/JS. Frozen:
      do not change these values, they are load-bearing for the current
      portal look. They retire when the portal static pass lands.

   2. CURRENT `--p-*` + shadcn channels (below) — the Blue Slate / Warm Slate
      system ported from Opum. OPT-IN: everything is scoped under
      `:root[data-poma-tokens]`, so an app sees none of it until its
      index.html declares `<html data-poma-tokens>`. That gate is what lets
      this ship ahead of the per-app migrations without moving a single
      pixel in an app that hasn't adopted yet.

   WHY TWO TOKEN SHAPES. The `--p-*` tokens are raw hex, for hand-written CSS
   and bespoke chrome. The unprefixed names (`--background`, `--card`,
   `--primary`…) are HSL *channels* for the shadcn/Tailwind layer that
   projects/model/portal-SPA are built on — setting those is what re-skins
   ~900-1100 existing utility classes per app for free.

   The `--p-` prefix is deliberate and is the one place this diverges from
   Opum's naming. Opum calls the raw tokens `--accent`/`--border`/`--success`
   and had to rename its shadcn channels to `--accent-ui`/`--border-ui`/
   `--success-ui` to stop the two colliding — a collision that fails silently
   (a hex where a channel triplet is expected yields no border, or
   currentColor). Prefixing the raw side instead keeps every poma app's
   existing Tailwind config untouched and makes the collision impossible.
   Colours are identical to Opum's; only the variable names differ.
   ═══════════════════════════════════════════════════════════════════ */


/* ═══════════════════════════════════════════════════════════════════
   1. LIGHT — "Warm Slate"
   The daylight counterpart to Blue Slate: same ~215 hue family, inverted.
   The page is a tinted grey and CARDS are the white, rather than
   white-on-white with the card border doing all the work.

   Elevation can't work in light the way it does in dark — panel is already
   pure white, so there is nowhere brighter to go. Floating surfaces (elev2)
   instead sit a touch OFF-white, which keeps the white fields inside a
   modal readable as fields. Borders and a restrained shadow carry the rest.

   The text ramp has four steps because the apps use four, and it is darker
   than a typical grey scale: on a tinted (not white) background the usual
   #6B7280/#9CA3AF pairing measures 4.43 and 2.33, both below AA.
   ═══════════════════════════════════════════════════════════════════ */
:root[data-poma-tokens] {
  /* ── Raw surfaces ──────────────────────────────────────────────── */
  --p-bg:       #F4F5F7;   /* app background (tinted, not white) */
  --p-canvas:   #ECEFF3;   /* app frame — top bars, side rails */
  --p-panel:    #FFFFFF;   /* cards, panels, inputs, tables */
  --p-elev:     #F7F8FA;   /* subtle raised fill — chips, rows */
  --p-elev2:    #FAFBFC;   /* modals, popovers, dropdowns, tooltips */
  --p-hover:    #EEF1F5;
  --p-border:   #D6DCE5;
  --p-borderS:  #C2CAD6;   /* stronger border — inputs, dividers under load */

  /* ── Raw text ramp ────────────────────────────────────────────── */
  --p-text:     #111827;   /* never pure black */
  --p-text2:    #4B5563;
  --p-text3:    #5B6472;
  --p-text4:    #7B8593;

  /* ── Raw status ───────────────────────────────────────────────── */
  --p-success:  #15803D;
  --p-warn:     #946200;
  --p-danger:   #DC2626;
  --p-info:     #1D4ED8;

  /* ── Status chips ─────────────────────────────────────────────── */
  /* A status needs two presentations, because one value cannot do both jobs.
     The tokens above are the colour as TEXT on a page surface, and on white
     that forces them dark — which is why a "Pending" chip built from
     --p-warn came out brown rather than yellow.
     A chip is a fill, an ink and an edge instead. The fill and edge carry the
     hue (so warn reads unmistakably YELLOW), and the ink is dark enough to
     stay legible on it. Every ink clears 4.5 against its own fill. */
  --p-success-fill: #ECFDF3; --p-success-ink: #14532D; --p-success-edge: #34C36B;
  --p-warn-fill:    #FEF6D9; --p-warn-ink:    #6B4A00; --p-warn-edge:    #E0AE1A;
  --p-danger-fill:  #FEF0F0; --p-danger-ink:  #991B1B; --p-danger-edge:  #EF7676;
  --p-info-fill:    #EFF4FF; --p-info-ink:    #1E40AF; --p-info-edge:    #7EA6F8;

  /* ── shadcn/Tailwind channels ─────────────────────────────────── */
  --background:           220 16% 96%;   /* --p-bg */
  --foreground:           221 39% 11%;   /* --p-text */
  --card:                 0 0% 100%;     /* --p-panel */
  --card-foreground:      221 39% 11%;
  --card-border:          216 22% 87%;   /* --p-border */
  --popover:              210 25% 98%;   /* --p-elev2 */
  --popover-foreground:   221 39% 11%;
  --popover-border:       216 20% 80%;   /* --p-borderS */
  --secondary:            220 23% 97%;   /* --p-elev */
  --secondary-foreground: 221 39% 11%;
  --muted:                220 23% 97%;   /* --p-elev */
  --muted-foreground:     215 14% 34%;   /* --p-text2 */
  /* NB: shadcn's `--accent` is the hover/selection SURFACE, not the brand
     accent. The brand accent is --p-accent / --primary, set per accent below. */
  --accent:               214 26% 95%;   /* --p-hover */
  --accent-foreground:    221 39% 11%;
  /* 45%, not 51%. --destructive is a FILL token — light carries white text on
     it — but 89 places across the app also read it as a TEXT colour, and at
     51% that measured 4.36:1 on --background, just under the 4.5 AA asks. It
     was the only surface that failed; dark is a light red on a dark page and
     clears easily.
  
     Darkening helps BOTH jobs at once: as text it goes 4.36 -> 5.30, and white
     on it as a button goes 4.80 -> 5.83. Six points of lightness, and the only
     cost is a slightly deeper red. */
  --destructive:          0 72% 45%;     /* --p-danger */
  --destructive-foreground: 0 0% 100%;
  --border:               216 22% 87%;   /* --p-border */
  --input:                216 22% 87%;

  /* ── Elevation & outline helpers (consumed by the projects app) ── */
  --button-outline: rgba(0,0,0, .10);
  --badge-outline:  rgba(0,0,0, .05);
  --opaque-button-border-intensity: -8;  /* percentage */
  --elevate-1: rgba(0,0,0, .03);
  --elevate-2: rgba(0,0,0, .08);

  /* ── Shadows ──────────────────────────────────────────────────── */
  /* Restrained by design. Separation is carried by the borders above — a
     dense UI with a shadow under every card turns to soup. */
  --shadow-2xs: 0px 1px 2px 0px hsl(221 39% 11% / 0.05);
  --shadow-xs:  0px 1px 2px 0px hsl(221 39% 11% / 0.08);
  --shadow-sm:  0px 1px 3px 0px hsl(221 39% 11% / 0.10), 0px 1px 2px -1px hsl(221 39% 11% / 0.10);
  --shadow:     0px 2px 4px -1px hsl(221 39% 11% / 0.08), 0px 4px 6px -1px hsl(221 39% 11% / 0.10);
  --shadow-md:  0px 4px 6px -1px hsl(221 39% 11% / 0.10), 0px 2px 4px -2px hsl(221 39% 11% / 0.06);
  --shadow-lg:  0px 10px 15px -3px hsl(221 39% 11% / 0.10), 0px 4px 6px -4px hsl(221 39% 11% / 0.06);
  --shadow-xl:  0px 20px 25px -5px hsl(221 39% 11% / 0.10), 0px 8px 10px -6px hsl(221 39% 11% / 0.06);
  --shadow-2xl: 0px 25px 50px -12px hsl(221 39% 11% / 0.25);

  /* ── Categorical chart ramp ───────────────────────────────────── */
  /* Deliberately NOT derived from the accent: these encode unrelated series,
     so they must stay distinguishable from each other and stable when the
     user changes accent. Carried forward from the existing apps, which
     already tuned them per mode. */
  --chart-1: 239 84% 57%;
  --chart-2: 142 76% 28%;
  --chart-3: 24 85% 32%;
  --chart-4: 262 83% 35%;
  --chart-5: 173 58% 30%;

  /* ── Sidebar (shadcn convention) ──────────────────────────────── */
  /* A sidebar is the design's `canvas` surface — the app frame rather than a
     card — so it sits one step off the page rather than matching it. The
     primary/ring entries are references, not values, so a sidebar follows the
     user's accent choice without needing its own per-accent rules. */
  --sidebar-background: 214 23% 94%;   /* --p-canvas */
  --sidebar-foreground: 215 14% 34%;   /* --p-text2 */
  --sidebar-primary: var(--primary);
  --sidebar-primary-foreground: var(--primary-foreground);
  --sidebar-accent: 214 26% 95%;       /* --p-hover */
  --sidebar-accent-foreground: 221 39% 11%;
  --sidebar-border: 216 22% 87%;       /* --p-border */
  --sidebar-ring: var(--ring);

  /* ── App-specific extras ──────────────────────────────────────── */
  /* Dependency arrows on the projects Gantt. A dedicated token rather than a
     borrowed chart colour: --primary already means "now" and selection,
     green reads as done and red as danger, so links get a hue that means
     nothing else. Defined here so the app can delete its local copy. */
  --gantt-link: 195 85% 38%;
}


/* ═══════════════════════════════════════════════════════════════════
   2. DARK — "Blue Slate"
   Replaces the old near-black ramp (#0f172a…), which swallowed cards and
   controls: at ~1.0-1.1 contrast between layers there was nothing to
   separate a panel from the page except its border — and on projects that
   border was itself 1% off the card, so it was separated by nothing at all.

   The floor is raised to #15181D and every step carries a blue-grey
   undertone (hue ~215), so surfaces read as stacked layers rather than
   holes. panel→border is 1.49, which is what does the separating; shadows
   stay off in dark entirely.
   ═══════════════════════════════════════════════════════════════════ */
:root[data-poma-tokens].dark {
  --p-bg:       #15181D;
  --p-canvas:   #1C2128;
  --p-panel:    #242A33;
  --p-elev:     #2C3440;
  --p-elev2:    #323B49;
  --p-hover:    #2F3844;
  --p-border:   #3B4553;
  --p-borderS:  #4A5566;

  --p-text:     #F4F6F8;   /* never pure white */
  --p-text2:    #B6C0CC;
  --p-text3:    #A2ACBA;
  --p-text4:    #7C8797;

  --p-success:  #4ADE80;
  --p-warn:     #FACC15;
  --p-danger:   #FB8C8C;   /* lighter than the light-mode red — #DC2626 fails
                              AA on every surface in this ramp */
  --p-info:     #72B2FC;

  /* Chips, dark. Same three-part structure; the fills are deep tints of the
     hue rather than pale ones, each held clear of --p-panel so the chip is a
     surface rather than a hole. */
  --p-success-fill: #1B3326; --p-success-ink: #6EE79B; --p-success-edge: #2F6B47;
  --p-warn-fill:    #3A3312; --p-warn-ink:    #FBD24E; --p-warn-edge:    #6E5C18;
  --p-danger-fill:  #43262B; --p-danger-ink:  #FCA5A5; --p-danger-edge:  #6E3B3F;
  --p-info-fill:    #1E2E45; --p-info-ink:    #8FC2FD; --p-info-edge:    #345A85;

  --background:           218 16% 10%;   /* --p-bg */
  --foreground:           210 22% 96%;   /* --p-text */
  --card:                 216 17% 17%;   /* --p-panel */
  --card-foreground:      210 22% 96%;
  --card-border:          215 17% 28%;   /* --p-border */
  /* Popovers/dropdowns/tooltips ride the elevated surface, so they read as
     floating above the card they were opened from rather than merging. */
  --popover:              217 19% 24%;   /* --p-elev2 */
  --popover-foreground:   210 22% 96%;
  --popover-border:       216 16% 35%;   /* --p-borderS */
  --secondary:            216 19% 21%;   /* --p-elev */
  --secondary-foreground: 210 22% 96%;
  --muted:                216 19% 21%;
  --muted-foreground:     213 18% 76%;   /* --p-text2 */
  --accent:               217 19% 24%;   /* --p-elev2 (hover/selection surface) */
  --accent-foreground:    210 22% 96%;
  --destructive:          0 93% 77%;     /* --p-danger */
  --destructive-foreground: 200 30% 6%;  /* near-black — white fails on this red */
  --border:               215 17% 28%;   /* --p-border */
  --input:                215 17% 28%;

  --button-outline: rgba(255,255,255, .10);
  --badge-outline:  rgba(255,255,255, .05);
  --opaque-button-border-intensity: 9;
  --elevate-1: rgba(255,255,255, .04);
  --elevate-2: rgba(255,255,255, .09);

  --shadow-2xs: 0px 1px 2px 0px hsl(0 0% 0% / 0.12);
  --shadow-xs:  0px 1px 2px 0px hsl(0 0% 0% / 0.16);
  --shadow-sm:  0px 1px 3px 0px hsl(0 0% 0% / 0.20), 0px 1px 2px -1px hsl(0 0% 0% / 0.20);
  --shadow:     0px 2px 4px -1px hsl(0 0% 0% / 0.12), 0px 4px 6px -1px hsl(0 0% 0% / 0.20);
  --shadow-md:  0px 4px 6px -1px hsl(0 0% 0% / 0.20), 0px 2px 4px -2px hsl(0 0% 0% / 0.10);
  --shadow-lg:  0px 10px 15px -3px hsl(0 0% 0% / 0.25), 0px 4px 6px -4px hsl(0 0% 0% / 0.15);
  --shadow-xl:  0px 20px 25px -5px hsl(0 0% 0% / 0.30), 0px 8px 10px -6px hsl(0 0% 0% / 0.18);
  --shadow-2xl: 0px 25px 50px -12px hsl(0 0% 0% / 0.45);

  --sidebar-background: 215 18% 13%;   /* --p-canvas */
  --sidebar-foreground: 213 18% 76%;   /* --p-text2 */
  --sidebar-primary: var(--primary);
  --sidebar-primary-foreground: var(--primary-foreground);
  --sidebar-accent: 217 19% 24%;       /* --p-elev2 */
  --sidebar-accent-foreground: 210 22% 96%;
  --sidebar-border: 215 17% 28%;       /* --p-border */
  --sidebar-ring: var(--ring);

  --chart-1: 239 84% 67%;
  --chart-2: 142 76% 55%;
  --chart-3: 24 85% 58%;
  --chart-4: 262 83% 62%;
  --chart-5: 173 58% 52%;

  --gantt-link: 195 85% 62%;
}


/* ═══════════════════════════════════════════════════════════════════
   3. ACCENTS
   Each accent is ONE hue at two brightnesses — a bright tint that survives a
   dark surface, and a deep shade that survives a white one. The hues are held
   within a few degrees across the pair so the two themes read as day and
   night of the same product rather than as two identities.

   The light shades are deep BY NECESSITY, not taste: the accent is used as
   link text on white cards, and every mid-brightness candidate fails AA there
   (teal #14B8A6 measures 2.49, purple #A78BFA 2.18).

   The dark hues are checked as TEXT against --p-elev2 (#323B49, the worst
   case), because the accent is used far more as text — links, active nav,
   stat figures — than as a fill. Anything under 4.5:1 there is rejected.
   This is why dark indigo is #A5B4FC and not the apps' current #6467F2,
   which measures 2.56 on that surface and is failing AA today.

                     as text, dark vs #323B49   light vs #FFFFFF
       indigo                 5.67                   7.14
       teal                   4.54                   5.57
       purple                 4.89                   5.70
       gold                   5.51                   4.58

   THE ACCENT MAY NOT OCCUPY A STATUS HUE. Red means destructive/failed/
   overdue across every app, amber means warning, green means success. An
   accent that reads as a status is worse than one fewer choice, so red,
   amber/mustard and green are all excluded and the set is three.

   This is not a matter of taste — the hue space is genuinely occupied. Both
   mustard and green were carried over from the source system and had to be
   dropped after measurement: on white, mustard resolved to #946200 and green
   to #15803D, which are the EXACT hexes of --p-warn and --p-success. They
   collide because the accent and the status ramp are derived under the same
   constraint (deep enough to clear AA on a white card), and that constraint
   has one answer per hue. Searching for a non-colliding value in the same
   family only makes it worse: staying legible while separating from the
   status colour forces mustard to #5C3600, which is brown rather than
   mustard, and for green on the DARK surface there is no solution at all —
   every green that clears 4.5 against --p-elev2 is indistinguishable from
   --p-success.

   Indigo, teal and purple sit in hues that carry no status meaning, which is
   why they survive.

   GOLD IS THE DELIBERATE EXCEPTION (added 2026-08-24 at Mike's request, with
   the brand gold #DFAE33 supplied). It shares the warn hue family, and the
   reason it works where mustard did not is that warn was restructured at the
   same time: a status is now a chip (fill + ink + edge), so warn presents as
   a PALE YELLOW rather than as the deep amber text colour that mustard
   duplicated exactly. Deep gold accent against pale yellow chip is a 4.23
   (light) / 6.16 (dark) separation. Hue proximity is therefore accepted here
   and enforced as a luminance separation instead — see the accent tests.

   Specificity note: the `.dark[data-accent=…]` rules are (0,4,0) and so beat
   both the plain accent rules (0,3,0) and the dark surface block (0,3,0)
   regardless of source order. Nothing here depends on ordering.
   ═══════════════════════════════════════════════════════════════════ */

/* ── Indigo — poma default. Applies when data-accent is absent. ───── */
:root[data-poma-tokens] {
  --p-accent: #3538ED;
  --p-accent-tint:        #3538ED29;  /* ~16% — the wash behind selected nav,
                                         active pills and hover rows */
  --p-accent-tint-strong: #3538ED44;
  --primary:            239 84% 57%;
  --primary-foreground: 0 0% 100%;
  --ring:               239 84% 57%;
}
:root[data-poma-tokens].dark {
  --p-accent: #A5B4FC;
  --p-accent-tint:        #A5B4FC29;
  --p-accent-tint-strong: #A5B4FC44;
  --primary:            230 94% 82%;
  --primary-foreground: 200 30% 6%;   /* near-black — white fails on every
                                         one of the dark accent hues */
  --ring:               230 94% 82%;
}

/* ── Teal (Opum's default, offered here as an alternate) ─────────── */
:root[data-poma-tokens][data-accent="teal"] {
  --p-accent: #107569;
  --p-accent-tint: #10756929; --p-accent-tint-strong: #10756944;
  --primary: 173 76% 26%; --primary-foreground: 0 0% 100%; --ring: 173 76% 26%;
}
:root[data-poma-tokens].dark[data-accent="teal"] {
  --p-accent: #14B8A6;
  --p-accent-tint: #14B8A629; --p-accent-tint-strong: #14B8A644;
  --primary: 173 80% 40%; --primary-foreground: 200 30% 6%; --ring: 173 80% 40%;
}

/* ── Purple ──────────────────────────────────────────────────────── */
:root[data-poma-tokens][data-accent="purple"] {
  --p-accent: #7C3AED;
  --p-accent-tint: #7C3AED29; --p-accent-tint-strong: #7C3AED44;
  --primary: 262 83% 58%; --primary-foreground: 0 0% 100%; --ring: 262 83% 58%;
}
:root[data-poma-tokens].dark[data-accent="purple"] {
  --p-accent: #B49CFB;
  --p-accent-tint: #B49CFB29; --p-accent-tint-strong: #B49CFB44;
  --primary: 255 92% 80%; --primary-foreground: 200 30% 6%; --ring: 255 92% 80%;
}

/* ── Gold ─────────────────────────────────────────────────────────── */
/* The one accent that shares a hue family with a status (warn). It is only
   viable because warn now presents as a CHIP: the accent is a deep gold at
   43°, the warn chip is a pale yellow fill, and they sit 4.23 (light) and
   6.16 (dark) apart in contrast — never mistakable as swatches, even though
   the hue is close. The dark value is the brand gold as supplied; the light
   value is the same hue taken deep enough to clear AA on a white card, which
   the brand gold itself cannot do (it measures 2.05 there). */
:root[data-poma-tokens][data-accent="gold"] {
  --p-accent: #996E00;
  --p-accent-tint: #996E0029; --p-accent-tint-strong: #996E0044;
  --primary: 43 100% 30%; --primary-foreground: 0 0% 100%; --ring: 43 100% 30%;
}
:root[data-poma-tokens].dark[data-accent="gold"] {
  --p-accent: #DFAE33;
  --p-accent-tint: #DFAE3329; --p-accent-tint-strong: #DFAE3344;
  --primary: 43 73% 54%; --primary-foreground: 200 30% 6%; --ring: 43 73% 54%;
}

/* ═══════════════════════════════════════════════════════════════════
   4. DENSITY, TYPE SCALE & GEOMETRY

   Density scales the rhythm tokens by 0.88 / 1.0 / 1.14. It intentionally
   does NOT scale the type ramp: shrinking text is a legibility decision, not
   a density one, and the two get conflated the moment they share a control.

   The type ramp is defined but NOT applied to body here. The apps currently
   run on Tailwind's 14/16px defaults; adopting a 12.5px base is a per-app
   decision that belongs with each app's migration, not with the token drop.
   ═══════════════════════════════════════════════════════════════════ */
:root[data-poma-tokens] {
  /* Rhythm — balanced (default) */
  --p-row-h:  30px;
  --p-gap:    12px;
  --p-gap-lg: 20px;

  /* Type ramp */
  --p-fs-micro: 10.5px;   /* dot labels, table superscripts */
  --p-fs-cap:   11.5px;   /* captions, field labels */
  --p-fs-body:  12.5px;
  --p-fs-sub:   13.5px;
  --p-fs-h3:    17px;
  --p-fs-h2:    22px;
  --p-fs-h1:    28px;

  /* Faces. Geist needs a <link> in the app's index.html; until then this
     degrades to Inter, which every app already loads. Geist Mono is
     load-bearing for the numeric treatment — every figure renders in it, so
     columns of numbers align and digits stop shifting width as they update.
     CJK faces trail the Latin ones: neither Geist nor Inter carries Chinese
     glyphs, so without them a share link opened in Chinese falls back to
     whatever the browser picks, which varies by OS and often mismatches the
     Latin text mid-sentence. */
  /* 'Geist Variable' is the family name Fontsource registers for the
     self-hosted build, which is how the apps ship it (Google Fonts is blocked
     in mainland China and our Shenzhen partners open share links from there).
     Plain 'Geist' follows for any context that does load it from Google. */
  --p-font-sans: 'Geist Variable', 'Geist', 'Inter Variable', Inter, -apple-system,
    BlinkMacSystemFont, 'Segoe UI', Roboto, 'PingFang SC', 'Hiragino Sans GB',
    'Microsoft YaHei', 'Noto Sans SC', sans-serif;
  --p-font-mono: 'Geist Mono Variable', 'Geist Mono', 'JetBrains Mono Variable',
    'JetBrains Mono', ui-monospace, 'Courier New', monospace;

  /* Corners. House radius is 6px; 10px for panels and modals. */
  --p-radius:    6px;
  --p-radius-lg: 10px;
  --radius:      6px;   /* shadcn's knob, kept in step with --p-radius */
}

:root[data-poma-tokens][data-density="compact"] {
  --p-row-h: 26px; --p-gap: 11px; --p-gap-lg: 18px;
}
:root[data-poma-tokens][data-density="roomy"] {
  --p-row-h: 34px; --p-gap: 14px; --p-gap-lg: 23px;
}


/* ═══════════════════════════════════════════════════════════════════
   4b. LEGACY BRIDGE
   Re-points the `--poma-*` tokens at the current palette — but ONLY inside
   the gate.

   The reason this exists: poma-panels.css and poma-messenger.css are shared
   widgets, loaded by projects, model and hub as well as the portal, and they
   style themselves from `--poma-*`. Once an app opts into the token system
   its own chrome is Blue Slate while those widgets would still be painting
   the retired ramp — the same palette, two eras, on one screen.

   Because the bridge is scoped to `[data-poma-tokens]`, the widgets follow
   whichever app they are embedded in: new palette inside a migrated app,
   untouched inside the portal's un-migrated static pages, which still read
   the frozen values in section 6.

   These are channel triplets, so they can reference the shadcn channels
   directly — `hsl(var(--poma-bg))` in the widget CSS resolves through to
   `--background`. The `/ 0.n` entries work for the same reason: the value is
   substituted textually inside the consumer's own hsl().
   ═══════════════════════════════════════════════════════════════════ */
:root[data-poma-tokens] {
  --poma-bg:             var(--background);
  --poma-surface:        var(--card);
  --poma-surface-raised: var(--secondary);
  --poma-text:           var(--foreground);
  --poma-text-muted:     var(--muted-foreground);
  --poma-text-faint:     215 10% 53%;        /* --p-text4 */
  --poma-primary:        var(--primary);
  /* No distinct hover shade: --primary is one value, and a channel triplet
     cannot be color-mix()ed. The widgets that hover carry their own opacity
     shift, so this reads as "no extra tint" rather than as a broken state. */
  --poma-primary-hover:  var(--primary);
  --poma-primary-subtle: var(--primary) / 0.15;
  --poma-success:        142 72% 29%;        /* --p-success */
  --poma-warning:        40 100% 29%;        /* --p-warn */
  --poma-danger:         var(--destructive);
  --poma-border:         var(--border);
  --poma-border-subtle:  var(--border) / 0.4;
  --poma-input-bg:       var(--secondary);
  --poma-input-border:   var(--input);
  --poma-ring:           var(--ring);
  --poma-font-sans:      var(--p-font-sans);
  --poma-font-mono:      var(--p-font-mono);
  --poma-glass-bg:       rgba(255, 255, 255, 0.55);
  --poma-glass-bg-heavy: rgba(255, 255, 255, 0.85);
  --poma-glass-border:   rgba(214, 220, 229, 0.5);   /* --p-border */
}

:root[data-poma-tokens].dark {
  --poma-text-faint:     216 11% 54%;        /* --p-text4, dark */
  --poma-success:        142 69% 58%;        /* --p-success, dark */
  --poma-warning:        48 96% 53%;         /* --p-warn, dark */
  --poma-glass-bg:       rgba(36, 42, 51, 0.55);     /* --p-panel */
  --poma-glass-bg-heavy: rgba(36, 42, 51, 0.85);
  --poma-glass-border:   rgba(59, 69, 83, 0.5);      /* --p-border, dark */
}


/* ═══════════════════════════════════════════════════════════════════
   5. GATED GLOBALS
   Selection and scrollbar chrome, token-aware. Scoped to the gate so an
   un-migrated app keeps the legacy dark-tuned versions at the bottom of
   this file.
   ═══════════════════════════════════════════════════════════════════ */
:root[data-poma-tokens] ::selection {
  background-color: var(--p-accent-tint-strong);
  color: var(--p-text);
}
:root[data-poma-tokens] ::-webkit-scrollbar { width: 8px; height: 8px; }
:root[data-poma-tokens] ::-webkit-scrollbar-track { background: transparent; }
:root[data-poma-tokens] ::-webkit-scrollbar-thumb {
  background: var(--p-borderS);
  border-radius: 4px;
}
:root[data-poma-tokens] ::-webkit-scrollbar-thumb:hover { background: var(--p-text4); }

/* Firefox equivalent — thin, and coloured from the same two tokens. */
:root[data-poma-tokens] { scrollbar-width: thin; scrollbar-color: var(--p-borderS) transparent; }


/* ═══════════════════════════════════════════════════════════════════
   6. LEGACY `--poma-*` — FROZEN
   Values below are unchanged from the pre-Blue-Slate file. The portal's
   vanilla CSS/JS reads them (~30 references) and the glass utilities are
   used by the portal shell. Projects, model and hub link this file but
   reference none of these — for them it is inert.

   Do not add to this block. New work uses the `--p-*` system above.
   ═══════════════════════════════════════════════════════════════════ */
:root {
  /* Backgrounds */
  --poma-bg:              222 47% 11%;     /* #0f172a */
  --poma-surface:         217 33% 17%;     /* #1e293b */
  --poma-surface-raised:  217 33% 20%;     /* #253348 */

  /* Text */
  --poma-text:            214 32% 91%;     /* #e2e8f0 */
  --poma-text-muted:      215 20% 65%;     /* #94a3b8 */
  --poma-text-faint:      217 19% 45%;     /* #5d6b82 */

  /* Brand / Primary (Indigo) */
  --poma-primary:         239 84% 67%;
  --poma-primary-hover:   239 84% 57%;
  --poma-primary-subtle:  239 84% 67% / 0.15;

  /* Status */
  --poma-success:         160 84% 39%;
  --poma-warning:         45 93% 47%;
  --poma-danger:          0 84% 60%;

  /* Borders */
  --poma-border:          217 33% 18%;
  --poma-border-subtle:   217 33% 18% / 0.4;

  /* Input */
  --poma-input-bg:        217 33% 15%;
  --poma-input-border:    217 33% 25%;
  --poma-ring:            239 84% 67%;

  /* Typography */
  --poma-font-sans:       'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  --poma-font-mono:       'JetBrains Mono', 'Fira Code', 'Cascadia Code', monospace;
  --poma-text-xs:         0.6875rem;
  --poma-text-sm:         0.8125rem;
  --poma-text-base:       0.875rem;
  --poma-text-lg:         1.125rem;
  --poma-text-xl:         1.5rem;

  /* Spacing (4px base) */
  --poma-space-1:         0.25rem;
  --poma-space-2:         0.5rem;
  --poma-space-3:         0.75rem;
  --poma-space-4:         1rem;
  --poma-space-5:         1.25rem;
  --poma-space-6:         1.5rem;
  --poma-space-8:         2rem;

  /* Radius */
  --poma-radius-sm:       0.375rem;
  --poma-radius-md:       0.5rem;
  --poma-radius-lg:       0.75rem;
  --poma-radius-xl:       1rem;

  /* Shadows */
  --poma-shadow-sm:       0 1px 2px rgba(0, 0, 0, 0.3);
  --poma-shadow-md:       0 4px 6px rgba(0, 0, 0, 0.3);
  --poma-shadow-lg:       0 10px 25px rgba(0, 0, 0, 0.4);
  --poma-shadow-xl:       0 25px 50px rgba(0, 0, 0, 0.5);

  /* Glass */
  --poma-glass-bg:        rgba(15, 23, 42, 0.5);
  --poma-glass-bg-heavy:  rgba(15, 23, 42, 0.8);
  --poma-glass-border:    rgba(30, 41, 59, 0.4);
  --poma-glass-blur:      30px;
  --poma-glass-blur-sm:   4px;
  --poma-glass-blur-md:   12px;
}

.poma-glass {
  background: var(--poma-glass-bg);
  backdrop-filter: blur(var(--poma-glass-blur));
  -webkit-backdrop-filter: blur(var(--poma-glass-blur));
  border: 1px solid var(--poma-glass-border);
  border-radius: var(--poma-radius-xl);
}

.poma-glass-heavy {
  background: var(--poma-glass-bg-heavy);
  backdrop-filter: blur(var(--poma-glass-blur));
  -webkit-backdrop-filter: blur(var(--poma-glass-blur));
  border: 1px solid var(--poma-glass-border);
  border-radius: var(--poma-radius-xl);
}

/* Legacy selection + scrollbar. `:root:not([data-poma-tokens])` keeps these
   off migrated apps, which get the token-aware versions in section 5. */
:root:not([data-poma-tokens]) ::selection {
  background-color: rgba(99, 102, 241, 0.3);
  color: hsl(var(--poma-text));
}
:root:not([data-poma-tokens]) ::-webkit-scrollbar { width: 6px; height: 6px; }
:root:not([data-poma-tokens]) ::-webkit-scrollbar-track { background: rgba(30, 41, 59, 0.3); }
:root:not([data-poma-tokens]) ::-webkit-scrollbar-thumb { background: rgba(71, 85, 105, 0.5); border-radius: 3px; }
:root:not([data-poma-tokens]) ::-webkit-scrollbar-thumb:hover { background: rgba(71, 85, 105, 0.7); }

/* Legacy light mode — overrides the dark defaults when .dark is absent. */
:root:not(.dark) {
  --poma-bg:             0 0% 97%;
  --poma-surface:        210 17% 95%;
  --poma-surface-raised: 210 17% 92%;
  --poma-text:           222 47% 11%;
  --poma-text-muted:     215 20% 40%;
  --poma-text-faint:     217 19% 58%;
  --poma-glass-bg:       rgba(255, 255, 255, 0.55);
  --poma-glass-bg-heavy: rgba(255, 255, 255, 0.85);
}
