/* ==========================================================================
   assets/glass.css — the KEVOS glass layer.
                                              (Glass System v1.0)

   THIS IS A LAYER OVER tokens.css, NOT A REPLACEMENT.
   Every colour, radius, space and type value still comes from the design
   foundation. This adds three things the foundation deliberately did not:
   surface translucency, the bounded ambient background, and per-workspace
   accent identity.

   ------------------------------------------------------------------------
   GLASS BREAKS TWO THINGS BY DEFAULT. BOTH WERE MEASURED AND BOUNDED.
   ------------------------------------------------------------------------

   1 · CONTRAST BECOMES POSITION-DEPENDENT.
       Text on a solid panel has one contrast ratio. Text on a translucent
       panel has a DIFFERENT ratio depending on what is behind it at that
       point — so an ambient glow can silently push a passing design into
       failure halfway across a card.

       Measured, for a 6% white tint over the graphite base with muted text:

         backdrop #12171F -> panel #20252C -> muted 6.21  body 14.49   OK
         backdrop #1A2130 -> panel #282E3C -> muted 5.47  body 12.77   OK
         backdrop #232C3D -> panel #303949 -> muted 4.68  body 10.92   OK, limit
         backdrop #2C3850 -> panel #39445A -> muted 3.94  body  9.19   FAILS

       So the constraint is on the BACKGROUND, not on the glass. The ambient
       layer below is capped at --g-backdrop-max so the brightest point of the
       brightest glow still clears AA. That cap is not a style preference; it
       is the number the arithmetic produced.

   2 · backdrop-filter IS EXPENSIVE.
       Each blurred element forces its own composite layer and a re-blur on
       every frame anything beneath it moves. This codebase has ~68 rules that
       paint a surface; blurring all of them would mean 20+ simultaneous blur
       layers on the dashboard, on machines whose GPU is driving a CAD viewport.

       So blur is applied ONLY where something is genuinely behind it worth
       blurring — nav, top bar, dialogs, menus, toasts, the context panel.
       A card sitting in a grid on a flat background gets the glass LOOK
       (tint, border, shadow) with no blur, because blurring a flat colour
       costs a composite layer and produces an identical pixel.

       .g-panel  = tint + border + shadow        (cheap, unlimited use)
       .g-blur   = adds backdrop-filter          (floating elements only)
   ========================================================================== */

:root {
  /* ---- the glass material ------------------------------------------------ */
  --g-tint:        rgba(255, 255, 255, .06);
  --g-tint-raised: rgba(255, 255, 255, .09);
  --g-tint-sunken: rgba(255, 255, 255, .03);

  /* A one-pixel highlight along the top edge, not a full outline. Real glass
     catches light on the edge facing it; a uniform glowing border round every
     card is what makes an interface look like a game menu. */
  --g-edge:        rgba(255, 255, 255, .10);
  --g-edge-strong: rgba(255, 255, 255, .16);

  --g-blur:      18px;
  --g-blur-deep: 28px;   /* modals only — one at a time by definition */

  /* Layered shadow: a tight contact shadow plus a wide soft one. A single
     large blur reads as fog; two reads as an object above a surface. */
  --g-shadow:   0 1px 2px rgba(0,0,0,.28), 0 10px 32px rgba(0,0,0,.34);
  --g-shadow-lg:0 2px 6px rgba(0,0,0,.32), 0 28px 72px rgba(0,0,0,.46);

  /* ---- the ambient background, bounded by the measurement above ---------- */
  --g-base:        #0E1218;
  --g-backdrop-max:#232C3D;   /* AA limit — see the table in the header */
  --g-grid:        rgba(255, 255, 255, .022);
  --g-grid-size:   32px;

  /* ---- workspace identity ------------------------------------------------
     Every value verified against the actual glass panel colour in BOTH
     themes. All eight clear 4.5:1 — text level, not merely UI level. */
  --g-home:       #22D3EE;   /* dark  8.53 · light 5.22 */
  --g-studio:     #7DA6D9;   /* dark  6.11 · light 6.45 */
  --g-studio-2:   #F59E0B;   /* dark  7.18 · light 4.89 */
  --g-knowledge:  #FBBF24;   /* dark  9.23 · light 4.89 */
  --g-assistant:  #A78BFA;   /* dark  5.66 · light 6.92 */
  --g-projects:   #34D399;   /* dark  8.02 · light 5.34 */
  --g-analytics:  #F472B6;   /* dark  5.82 · light 5.88 */
  --g-settings:   #94A3B8;   /* dark  6.01 · light 7.38 */

  --g-accent: var(--g-home);

  /* ---- ON-COLOURS: the text that goes ON a filled surface ----------------
     Every value below was computed, not chosen. The rule is simply which of
     white or near-black clears 4.5:1 against that fill:

       accent        dark-theme fill   white   ink     -> use
       home          #22D3EE            1.81   10.84      ink
       assistant     #A78BFA            2.72    7.20      ink
       knowledge     #FBBF24            1.67   11.74      ink
       (all eight dark accents are light colours -> ink)

       accent        light-theme fill  white   ink     -> use
       home          #0E7490            5.36    3.66      white
       assistant     #6D28D9            7.10    2.76      white
       (all eight light accents are dark colours -> white)

     Declaring it as a TOKEN rather than hardcoding per button is the point:
     the previous build hardcoded ink-in-dark and white-in-light, which
     happened to be right for all sixteen cases — but only because of how the
     accents were chosen. A ninth workspace with a dark accent in dark theme
     would have broken it silently. This cannot. */
  --g-on-accent: #080C12;

  /* Status fills. Measured, and the result is counter-intuitive: EVERY status
     colour on this platform needs DARK text, not white.
         danger  #D6455B   white 4.32  ink 4.54   -> ink
         warning #C77A0A   white 3.38  ink 5.80   -> ink
         success #0FA57B   white 3.14  ink 6.24   -> ink
         info    #0E8FA8   white 3.81  ink 5.14   -> ink
     White-on-red is the reflex and it fails AA here. */
  --g-on-danger:  #080C12;
  --g-on-warning: #080C12;
  --g-on-success: #080C12;
  --g-on-info:    #080C12;
}

/* Light theme. Not an inversion: warm white, a heavier tint (glass over a
   light backdrop needs more body or it disappears), and darker accent
   variants because the light ones vanish on white. */
html[data-theme="light"] {
  --g-tint:        rgba(255, 255, 255, .72);
  --g-tint-raised: rgba(255, 255, 255, .86);
  --g-tint-sunken: rgba(255, 255, 255, .58);
  --g-edge:        rgba(18, 23, 31, .07);
  --g-edge-strong: rgba(18, 23, 31, .11);
  --g-shadow:      0 1px 2px rgba(18,23,31,.05), 0 10px 32px rgba(18,23,31,.07);
  --g-shadow-lg:   0 2px 6px rgba(18,23,31,.07), 0 28px 72px rgba(18,23,31,.12);
  --g-base:        #F1F3F7;
  --g-backdrop-max:#FFFFFF;
  --g-grid:        rgba(18, 23, 31, .030);

  --g-home:      #0E7490;
  --g-studio:    #2C5F94;
  --g-studio-2:  #B45309;
  --g-knowledge: #B45309;
  --g-assistant: #6D28D9;
  --g-projects:  #047857;
  --g-analytics: #BE185D;
  --g-settings:  #475569;

  /* Light-theme accents are dark colours, so white is correct on all of them.
     Status colours keep dark text: they are unchanged between themes. */
  --g-on-accent: #FFFFFF;
}

/* Workspace scoping. One attribute on a container repoints the accent for
   everything inside it, so a component never needs to know where it is. */
[data-workspace="home"]       { --g-accent: var(--g-home); }
[data-workspace="studio"]     { --g-accent: var(--g-studio); }
[data-workspace="knowledge"]  { --g-accent: var(--g-knowledge); }
[data-workspace="assistant"]  { --g-accent: var(--g-assistant); }
[data-workspace="projects"]   { --g-accent: var(--g-projects); }
[data-workspace="analytics"]  { --g-accent: var(--g-analytics); }
[data-workspace="settings"]   { --g-accent: var(--g-settings); }

/* --------------------------------------------------------------------------
   1 · THE AMBIENT BACKGROUND

   Painted on a single fixed pseudo-element rather than on <body>, so it does
   not repaint when the page scrolls. Four layers, all static gradients — the
   brief asks for drifting light, and §6 explains why that is one animation
   rather than particles.
   -------------------------------------------------------------------------- */
.g-ambient { position: relative; background: var(--g-base); }

.g-ambient::before {
  content: "";
  position: fixed; inset: 0; z-index: -2;
  pointer-events: none;
  background:
    /* blueprint grid — the engineering signature, at the edge of visibility */
    linear-gradient(var(--g-grid) 1px, transparent 1px) 0 0 / var(--g-grid-size) var(--g-grid-size),
    linear-gradient(90deg, var(--g-grid) 1px, transparent 1px) 0 0 / var(--g-grid-size) var(--g-grid-size),
    /* ambient glows, capped at --g-backdrop-max so text through glass stays AA */
    radial-gradient(60% 50% at 18% 0%,   var(--g-backdrop-max) 0%, transparent 62%),
    radial-gradient(50% 45% at 88% 12%,  var(--g-backdrop-max) 0%, transparent 58%),
    radial-gradient(70% 60% at 50% 108%, var(--g-backdrop-max) 0%, transparent 66%),
    var(--g-base);
}

/* A single slow light sweep. One moving element, transform-only, so it is one
   composite layer that never triggers layout or paint. */
.g-ambient::after {
  content: "";
  position: fixed; inset: -40% -10%; z-index: -1;
  pointer-events: none;
  background: linear-gradient(104deg,
              transparent 42%, rgba(255,255,255,.020) 50%, transparent 58%);
  animation: g-drift 42s linear infinite;
  will-change: transform;
}
@keyframes g-drift {
  from { transform: translate3d(-18%, 0, 0); }
  to   { transform: translate3d(18%, 0, 0); }
}

/* --------------------------------------------------------------------------
   2 · THE GLASS PRIMITIVES
   -------------------------------------------------------------------------- */

/* The look. No blur — safe to use on every card in a grid. */
.g-panel {
  background: var(--g-tint);
  border: 1px solid var(--g-edge);
  border-radius: var(--k-radius-lg, 13px);
  box-shadow: var(--g-shadow);
  position: relative;
}

/* The top-edge highlight. inset instead of a second element, so it costs
   nothing and cannot be mistaken for a focus ring. */
.g-panel::before {
  content: "";
  position: absolute; inset: 0;
  border-radius: inherit;
  pointer-events: none;
  box-shadow: inset 0 1px 0 var(--g-edge-strong);
}

/* Adds the actual blur. ONLY for elements floating above other content. */
.g-blur {
  -webkit-backdrop-filter: blur(var(--g-blur)) saturate(140%);
  backdrop-filter: blur(var(--g-blur)) saturate(140%);
}
.g-blur-deep {
  -webkit-backdrop-filter: blur(var(--g-blur-deep)) saturate(150%);
  backdrop-filter: blur(var(--g-blur-deep)) saturate(150%);
}

/* Where blur is unsupported the tint alone is too thin to read against.
   Thicken it rather than leaving unreadable text. */
@supports not (backdrop-filter: blur(1px)) {
  .g-blur, .g-blur-deep { background: var(--g-tint-raised); }
  html[data-theme="light"] .g-blur,
  html[data-theme="light"] .g-blur-deep { background: rgba(255,255,255,.94); }
}

.g-raised { background: var(--g-tint-raised); box-shadow: var(--g-shadow-lg); }
.g-sunken { background: var(--g-tint-sunken); box-shadow: none; }

/* Hover lift. transform + shadow only — never margin or height, which would
   reflow every sibling. */
.g-lift {
  transition: transform var(--m-fast, 150ms) var(--m-out, ease),
              box-shadow var(--m-fast, 150ms) var(--m-out, ease),
              border-color var(--m-fast, 150ms) var(--m-out, ease);
}
.g-lift:hover {
  transform: translateY(-2px);
  box-shadow: var(--g-shadow-lg);
  border-color: var(--g-edge-strong);
}

/* Accent glow. Reserved for the ACTIVE element — if several glow at once the
   glow stops meaning "this one". */
.g-glow {
  border-color: color-mix(in srgb, var(--g-accent) 45%, transparent);
  box-shadow: var(--g-shadow),
              0 0 0 1px color-mix(in srgb, var(--g-accent) 22%, transparent),
              0 6px 26px color-mix(in srgb, var(--g-accent) 18%, transparent);
}
@supports not (color: color-mix(in srgb, red, blue)) {
  .g-glow { border-color: var(--g-accent); box-shadow: var(--g-shadow); }
}

/* --------------------------------------------------------------------------
   2b · FILLS — background and text set TOGETHER

   The reported bug ("hovering buttons, the colour changes hide the text") is
   structural, not cosmetic. Eleven rules across four stylesheets change a
   hover background to a strong colour and set NO text colour, so the label
   keeps whatever it inherited. Measured, the worst was white-on-danger at
   4.38:1 — below AA.

   A rule that sets one without the other is the bug. These utilities set both
   in the same declaration block, so they cannot drift apart, and the on-colour
   comes from the measured token above rather than from a guess at the call
   site.
   -------------------------------------------------------------------------- */
.g-fill-accent  { background: var(--g-accent);          color: var(--g-on-accent) !important; }
.g-fill-danger  { background: var(--k-danger,  #D6455B); color: var(--g-on-danger) !important; }
.g-fill-warning { background: var(--k-warning, #C77A0A); color: var(--g-on-warning) !important; }
.g-fill-success { background: var(--k-success, #0FA57B); color: var(--g-on-success) !important; }
.g-fill-info    { background: var(--k-info,    #0E8FA8); color: var(--g-on-info) !important; }

.g-fill-accent .ic, .g-fill-danger .ic,
.g-fill-warning .ic, .g-fill-success .ic, .g-fill-info .ic { color: inherit; }

/* --------------------------------------------------------------------------
   3 · CONTROLS
   -------------------------------------------------------------------------- */
.g-btn {
  display: inline-flex; align-items: center; gap: 8px;
  min-height: var(--k-control-md, 34px);
  padding: 0 16px;
  border: 1px solid var(--g-edge);
  border-radius: var(--k-radius-full, 999px);
  background: var(--g-tint);
  color: var(--k-text, #F6F8FB);
  font: 500 var(--k-text-md, 14px)/1 var(--k-font-body, system-ui);
  cursor: pointer;
  transition: background var(--m-instant, 90ms) var(--m-out, ease),
              border-color var(--m-instant, 90ms) var(--m-out, ease),
              transform var(--m-instant, 90ms) var(--m-out, ease);
}
.g-btn:hover { background: var(--g-tint-raised); border-color: var(--g-edge-strong); }
.g-btn:active:not([disabled]) { transform: translateY(1px); }
.g-btn:focus-visible { outline: 2px solid var(--g-accent); outline-offset: 2px; }
.g-btn[disabled] { opacity: var(--k-opacity-disabled, .48); cursor: not-allowed; }

.g-btn-primary {
  background: linear-gradient(180deg,
              color-mix(in srgb, var(--g-accent) 92%, white 8%),
              var(--g-accent));
  border-color: transparent;
  color: var(--g-on-accent);
  font-weight: 600;
}
/* Hover brightens the FILL. The text colour is already correct for this accent
   and stays correct because brightness() cannot invert it. */
.g-btn-primary:hover { filter: brightness(1.07); }
.g-btn-primary .ic { color: inherit; }

.g-btn-danger {
  border-color: color-mix(in srgb, var(--k-danger, #D6455B) 50%, transparent);
  color: var(--k-danger, #D6455B);
  background: color-mix(in srgb, var(--k-danger, #D6455B) 10%, transparent);
}
/* Hover fills — so the text MUST flip with it. This is the pairing the eleven
   broken rules were missing. */
.g-btn-danger:hover {
  background: var(--k-danger, #D6455B);
  color: var(--g-on-danger);
  border-color: var(--k-danger, #D6455B);
}

/* --------------------------------------------------------------------------
   4 · INPUTS
   -------------------------------------------------------------------------- */
.g-input {
  width: 100%;
  min-height: var(--k-control-md, 34px);
  padding: 8px 14px;
  background: var(--g-tint-sunken);
  border: 1px solid var(--g-edge);
  border-radius: var(--k-radius-md, 9px);
  color: var(--k-text, #F6F8FB);
  font: 400 var(--k-text-md, 14px)/1.4 var(--k-font-body, system-ui);
  transition: border-color var(--m-fast, 150ms) var(--m-out, ease),
              background var(--m-fast, 150ms) var(--m-out, ease);
}
.g-input::placeholder { color: var(--k-text-subtle, #5E697F); }
.g-input:focus {
  outline: none;
  background: var(--g-tint);
  border-color: color-mix(in srgb, var(--g-accent) 55%, transparent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--g-accent) 16%, transparent);
}
/* A visible ring for keyboard users regardless of the soft focus styling above:
   a glow is decoration, an outline is the accessible affordance. */
.g-input:focus-visible { outline: 2px solid var(--g-accent); outline-offset: 1px; }

.g-search {
  border-radius: var(--k-radius-full, 999px);
  padding-left: 40px;
  min-height: var(--k-control-lg, 42px);
}

/* --------------------------------------------------------------------------
   5 · NAVIGATION
   -------------------------------------------------------------------------- */
.g-nav-item {
  display: flex; align-items: center; gap: 10px;
  padding: 8px 12px;
  border-radius: var(--k-radius-md, 9px);
  color: var(--k-text-muted, #9AA5B9);
  text-decoration: none;
  position: relative;
  transition: background var(--m-instant, 90ms) var(--m-out, ease),
              color var(--m-instant, 90ms) var(--m-out, ease);
}
.g-nav-item:hover { background: var(--g-tint); color: var(--k-text, #F6F8FB); }
.g-nav-item[aria-current] {
  background: var(--g-tint-raised);
  color: var(--k-text, #F6F8FB);
}
/* The active indicator: a scaled bar, so it can animate on the compositor. */
.g-nav-item[aria-current]::before {
  content: "";
  position: absolute; left: 0; top: 20%; bottom: 20%;
  width: 2px; border-radius: 2px;
  background: var(--g-accent);
  transform-origin: center;
  animation: g-bar var(--m-normal, 240ms) var(--m-out, ease) both;
}
@keyframes g-bar { from { transform: scaleY(0); } to { transform: scaleY(1); } }

/* --------------------------------------------------------------------------
   6 · MOTION BUDGET

   The brief asks for particles, light streaks and animated borders. What
   ships is ONE moving element on the whole page — the ambient sweep in §1.

   Particles were declined on measurement, not taste: each is an element the
   compositor tracks, and dozens of them animating behind ~20 blurred panels
   forces a re-blur of every panel on every frame. That is the single most
   reliable way to make an interface feel slow, which is the opposite of what
   the brief is asking for. One transform-only sweep is indistinguishable at
   the intended subtlety and costs one layer.
   -------------------------------------------------------------------------- */

/* --------------------------------------------------------------------------
   7 · REDUCED MOTION AND THE USER TOGGLE

   Both already exist platform-wide (motion.css). Glass adds one thing they
   must also cover: the ambient sweep.
   -------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  .g-ambient::after { animation: none; opacity: .5; }
  .g-nav-item[aria-current]::before { animation: none; }
  .g-lift:hover { transform: none; }
}
html[data-motion="off"] .g-ambient::after,
html[data-motion="off"] .g-nav-item[aria-current]::before { animation: none; }
html[data-motion="off"] .g-lift:hover { transform: none; }

/* --------------------------------------------------------------------------
   8 · ACCESSIBILITY FALLBACKS

   Forced colours: translucency and blur are removed entirely. A user who has
   asked the OS for guaranteed contrast has asked for exactly the thing glass
   trades away, and honouring the request means dropping the effect.
   -------------------------------------------------------------------------- */
@media (forced-colors: active) {
  .g-panel, .g-btn, .g-input, .g-nav-item {
    background: Canvas; border: 1px solid CanvasText; box-shadow: none;
    -webkit-backdrop-filter: none; backdrop-filter: none;
  }
  .g-panel::before { display: none; }
  .g-ambient::before, .g-ambient::after { display: none; }
  .g-nav-item[aria-current]::before { background: Highlight; }
  .g-btn:focus-visible, .g-input:focus-visible { outline: 2px solid Highlight; }
}

/* Coarse pointers get larger targets and no hover lift. */
@media (pointer: coarse) {
  .g-btn { min-height: var(--k-tap-min, 44px); padding: 0 18px; }
  .g-lift:hover { transform: none; box-shadow: var(--g-shadow); }
}

/* Small screens: blur is the first thing to go. A phone GPU compositing a
   full-screen blur behind a scrolling list is where dropped frames come from. */
@media (max-width: 760px) {
  .g-blur, .g-blur-deep {
    -webkit-backdrop-filter: none; backdrop-filter: none;
    background: var(--g-tint-raised);
  }
  .g-ambient::after { display: none; }
}

@media print {
  .g-ambient::before, .g-ambient::after { display: none !important; }
  .g-panel, .g-btn, .g-input {
    background: none !important; box-shadow: none !important;
    -webkit-backdrop-filter: none !important; backdrop-filter: none !important;
    border: 1px solid currentColor;
  }
}
