/* OmniConflux console design system: the omniconflux.com tokens as plain CSS (gateway/public is served as static
   files, so there is no build step). Colors, the Geist faces, motion and the picker come from the website
   (omniconflux-web origin/main: app/globals.css, app/theme-picker.css, app/showcase.css, app/motion.css,
   components/blend/MiniMark.tsx); Daylight, the fixed type scale and the state roles come from
   docs/app/design-system.md (sections 1.2, 1.3 and 1.8). Every page links this one file: the console, the sign-in
   page, the landing page and the offline page. Pages read the semantic names below and never name a hex value. */

/* Geist and Geist Mono (Vercel, SIL OFL 1.1; license in fonts/Geist-OFL.txt). Latin subsets, weights 400 to 700.
   The console is an app opened again and again, so the faces swap in (the metric-matched fallbacks keep it still). */
@font-face {
  font-family: "Geist";
  src: url("fonts/Geist-Latin.woff2") format("woff2");
  font-weight: 400 700;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Geist Mono";
  src: url("fonts/GeistMono-Latin.woff2") format("woff2");
  font-weight: 400 700;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2190-21FF, U+2212, U+2215, U+2500-257F, U+25A0-25FF, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Geist Fallback";
  src: local("Arial"), local("ArialMT"), local("Liberation Sans"), local("Helvetica");
  size-adjust: 104.76%;
  ascent-override: 95.94%;
  descent-override: 28.16%;
  line-gap-override: 0%;
}
@font-face {
  font-family: "Geist Mono Fallback";
  src: local("Courier New"), local("CourierNewPSMT"), local("Liberation Mono");
  size-adjust: 99.98%;
  ascent-override: 100.52%;
  descent-override: 29.5%;
  line-gap-override: 0%;
}

/* Confluence, the default: royal purple and black, flat. Surfaces and hairlines are the ground with only its
   lightness raised. --accent marks focus, selection, links and live marks; --accent-fill carries filled buttons under
   --accent-ink. The work states keep their meaning in every theme: cyan running, the text colour verified, rose sent
   back, gold under test, hollow idle, Solar red blocked. --strand-1 to 7 colour the mark's seven strands. */
:root,
html[data-theme="confluence"] {
  color-scheme: dark;
  --bg: #07051A;
  --surface-1: #0D0C22;
  --surface-2: #14122A;
  --hairline: #24233C;
  --hairline-strong: #656683;
  --text: #F4F1FF;
  --text-2: #A39CC4;
  --text-3: #8780A7;
  --accent: #A855F7;
  --accent-fill: #7C3AED;
  --accent-deep: #4B0082;
  --accent-ink: var(--text);
  --state-running: #22D3EE;
  --state-verified: var(--text);
  --state-returned: #FB7185;
  --state-testing: #FBBF24;
  --state-idle: var(--hairline-strong);
  --state-blocked: #F1453F;
  --state-ink: var(--bg);
  --role-solar: #F1453F;
  --role-aurora: #2DD4BF;
  --role-platinum: #E2E8F0;
  --term-blue: #60A5FA;
  --term-blue-bright: #93C5FD;
  --term-magenta: #E879F9;
  --term-magenta-bright: #F0ABFC;
  --strand-1: #4B0082; --strand-2: #5B21B6; --strand-3: #7C3AED; --strand-4: #A855F7; --strand-5: #6366F1; --strand-6: #0EA5E9; --strand-7: #22D3EE;
  --mark-hi: #FFFFFF;
}
html[data-theme="aurora"] {
  --bg: #03100F;
  --surface-1: #081816;
  --surface-2: #0E201E;
  --hairline: #1D3331;
  --hairline-strong: #557572;
  --text: #EEFBF9;
  --text-2: #94BDB8;
  --text-3: #7AA29D;
  --accent: #2DD4BF;
  --accent-fill: #0F766E;
  --accent-deep: #134E4A;
  --strand-1: #0F766E; --strand-2: #14B8A6; --strand-3: #2DD4BF; --strand-4: #22D3EE; --strand-5: #6366F1; --strand-6: #8B5CF6; --strand-7: #34D399;
}
html[data-theme="solar"] {
  --bg: #150505;
  --surface-1: #1D0A09;
  --surface-2: #27100F;
  --hairline: #3E2220;
  --hairline-strong: #80625D;
  --text: #F9F3F0;
  --text-2: #CBBAB2;
  --text-3: #A9958E;
  --accent: #F1453F;
  --accent-fill: #D42323;
  --accent-deep: #5C1715;
  --strand-1: #5C0B0B; --strand-2: #7F1D1D; --strand-3: #B91C1C; --strand-4: #F1453F; --strand-5: #DC2626; --strand-6: #991B1B; --strand-7: #FF4D4D;
}
html[data-theme="platinum"] {
  --bg: #08090D;
  --surface-1: #0F1116;
  --surface-2: #161920;
  --hairline: #262A33;
  --hairline-strong: #636B7A;
  --text: #F5F7FA;
  --text-2: #A8B0BF;
  --text-3: #8C94A3;
  --accent: #C7D2FE;
  --accent-fill: #E2E8F0;
  --accent-deep: #1E293B;
  --accent-ink: var(--bg);
  --strand-1: #64748B; --strand-2: #94A3B8; --strand-3: #CBD5E1; --strand-4: #E2E8F0; --strand-5: #A5B4FC; --strand-6: #C7D2FE; --strand-7: #F8FAFC;
}
/* Daylight, the light theme for bright rooms: the same roles on paper. Each state hue keeps its meaning at a lower
   lightness so its word passes 4.5:1; the mark keeps the Confluence strands. */
html[data-theme="daylight"] {
  color-scheme: light;
  --bg: #FBFAFF;
  --surface-1: #F3F1FA;
  --surface-2: #EAE7F4;
  --hairline: #D6D2E4;
  --hairline-strong: #6E6A8B;
  --text: #14122A;
  --text-2: #4A4668;
  --text-3: #5F5B7E;
  --accent: #6D28D9;
  --accent-fill: #5B21B6;
  --accent-deep: #EDE9FE;
  --accent-ink: #FFFFFF;
  --state-running: #0F6B80;
  --state-returned: #BE123C;
  --state-testing: #8A5700;
  --state-blocked: #B91C1C;
  --role-solar: #B91C1C;
  --role-aurora: #0F6E67;
  --role-platinum: #475569;
  --term-blue: #1D4ED8;
  --term-blue-bright: #2563EB;
  --term-magenta: #A21CAF;
  --term-magenta-bright: #A21CAF;
  --mark-hi: #FFFFFF;
}

/* Everything that does not change with the theme. Type steps are the app's fixed pixel scale (Operate surfaces want a
   steady size at a known DPI): size, leading and tracking travel together, nothing is under 12 px and nothing is
   tracked tighter than -0.03em. Headings are 560, mono labels 500. */
:root {
  --font-sans: "Geist", "Geist Fallback", ui-sans-serif, system-ui, sans-serif;
  --font-mono: "Geist Mono", "Geist Mono Fallback", ui-monospace, monospace;
  --weight-heading: 560;

  --text-display: 48px; --leading-display: 52px; --tracking-display: -0.03em;
  --text-h1: 34px; --leading-h1: 40px; --tracking-h1: -0.025em;
  --text-h2: 24px; --leading-h2: 30px; --tracking-h2: -0.02em;
  --text-h3: 18px; --leading-h3: 24px; --tracking-h3: -0.015em;
  --text-lead: 16px; --leading-lead: 24px; --tracking-lead: -0.01em;
  --text-body: 14px; --leading-body: 20px;
  --text-small: 13px; --leading-small: 18px;
  --text-label: 12px; --leading-label: 16px; --tracking-label: 0.01em;
  --text-mono-code: 13px; --leading-mono-code: 20px;
  --text-mono-label: 12px; --leading-mono-label: 16px; --tracking-mono-label: 0.02em;

  /* Spacing on the 4 px base; allowed steps only. */
  --space-1: 4px; --space-2: 8px; --space-3: 12px; --space-4: 16px; --space-6: 24px; --space-8: 32px; --space-12: 48px; --space-18: 72px;

  /* Radius by role. A full pill is only for the live status dot. */
  --radius-media: 0;
  --radius-chip: 2px;
  --radius-control: 6px;
  --radius-cell: 10px;
  --radius-window: 16px;

  /* Depth is a hairline, never a shadow (the one floating layer, a dialog over the page, carries a real offset). */
  --line: 1px solid var(--hairline);
  --line-strong: 1px solid var(--hairline-strong);
  --shadow-float: 0 12px 32px rgba(0, 0, 0, 0.55);

  --ease-enter: cubic-bezier(0.16, 1, 0.3, 1);
  --ease-exit: cubic-bezier(0.7, 0, 0.84, 0);
  --ease-dismiss: cubic-bezier(0.23, 1, 0.32, 1);
  --ease-state: cubic-bezier(0.65, 0, 0.35, 1);
  --ease-burst: cubic-bezier(0.2, 0.9, 0.1, 1);
  --dur-feedback: 120ms;
  --dur-state: 200ms;
  --dur-panel: 420ms;

  /* The console's modules were written against older names; these aliases give each one its role in the system
     so a module never names a colour of its own. Live, alive and streaming are the running state; warnings are the
     gold under-test state; failures and danger are the blocked red; the old cyan highlight is the accent. */
  --void: var(--bg);
  --ink: var(--text);
  --ink-dim: var(--text-2);
  --ink-mute: var(--text-3);
  --surface: var(--surface-1);
  --glass: var(--surface-1);
  --glass-2: var(--surface-2);
  --glass-hi: transparent;
  --glass-line: var(--hairline);
  --glass-line-soft: var(--hairline);
  --blur: none;
  --shadow: none;
  --r: var(--radius-cell);
  --holo: var(--accent);
  --cyan: var(--state-running);
  --green: var(--state-running);
  --bio-green: var(--state-running);
  --green-dk: var(--hairline-strong);
  --bio-green-dk: var(--hairline-strong);
  --amber: var(--state-testing);
  --warn-amber: var(--state-testing);
  --red: var(--state-blocked);
  --red-dk: var(--hairline-strong);
  --omniconflux-red: var(--accent);
  --omniconflux-red-dk: var(--accent);
  --disp: var(--font-sans);
  --body: var(--font-sans);
  --mono: var(--font-mono);
}

/* The root keeps the browser's 16 px so rem steps mean what they mean on the website; the body sets the UI size. */
html {
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-sans);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
}
body { background: var(--bg); color: var(--text); font-family: var(--font-sans); font-size: var(--text-body); line-height: var(--leading-body); }
:where(b, strong) { font-weight: 560; }
:where(code, kbd, samp, pre) { font-family: var(--font-mono); }
:where(a) { color: var(--accent); text-underline-offset: 3px; }
:where(button:not(:disabled), summary, select) { cursor: pointer; }

:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
/* A text field wears the same ring hugging its own edge. */
:where(input:not([type="checkbox"]):not([type="radio"]), textarea, select):focus-visible { outline-offset: -1px; }
::selection { background: var(--accent-fill); color: var(--accent-ink); }
::placeholder { color: var(--text-3); opacity: 1; }

* { scrollbar-width: thin; scrollbar-color: var(--hairline-strong) transparent; }
::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: var(--hairline); border: 2px solid transparent; border-radius: var(--radius-control); background-clip: padding-box; }
::-webkit-scrollbar-thumb:hover { background-color: var(--hairline-strong); }

/* The work-state mark: a 6 px square in the state colour, always beside its word. */
.state-mark { display: inline-block; flex: none; width: 6px; height: 6px; border-radius: var(--radius-chip); background: currentColor; vertical-align: middle; }
.state-mark.is-idle { background: none; box-shadow: inset 0 0 0 1px currentColor; }

/* The mark: the website's header mark, converged and still (the <symbol id="oc-mark"> each page carries). */
.oc-mark { display: block; flex: none; width: 32px; height: 32px; overflow: visible; }

/* Theme picker (theme-picker.js), the website's colorway picker for the console's six themes. The trigger is a 44 px
   tool wearing the current theme's chip; its palette hangs from it, right edges aligned, one column of chips under
   the trigger's chip. Opening unfolds that column from the chip and the words follow; closing is a quieter fade; a
   keyboard open shows at once. A pick crossfades the page and hands its chip back to the trigger. */
[data-theme-picker] { width: 44px; height: 44px; }
.theme-control { position: relative; flex: none; }
.theme-trigger {
  display: flex; align-items: center; justify-content: center; width: 44px; height: 44px; padding: 0;
  border: var(--line-strong); border-radius: var(--radius-control); background: var(--bg); color: var(--text);
}
.theme-trigger[aria-expanded="true"] { background: var(--surface-2); }
@media (hover: hover) { .theme-trigger:hover { background: var(--surface-2); } }
.theme-dropdown {
  position: absolute; top: calc(100% + 8px); right: 0; z-index: 80; width: min(272px, calc(100vw - 24px)); padding: 6px;
  border: var(--line-strong); border-radius: var(--radius-cell); background: var(--surface-1); color: var(--text);
  transform-origin: calc(100% - 22px) -8px; opacity: 0; pointer-events: none; visibility: hidden;
}
.theme-dropdown[data-open] { opacity: 1; pointer-events: auto; visibility: visible; }
.theme-option {
  position: relative; display: flex; align-items: center; gap: 12px; width: 100%; min-height: 48px; margin: 0;
  padding: 6px 7px 6px 12px; border: 0; border-radius: var(--radius-control); background: none; color: var(--text);
  font: inherit; text-align: left;
}
.theme-option:focus-visible { outline-offset: -2px; }
.theme-option[data-theme="auto"] { margin-bottom: 9px; }
.theme-option[data-theme="auto"]::before { content: ""; position: absolute; inset-inline: 12px 7px; bottom: -5px; height: 1px; background: var(--hairline); }
.theme-option-copy { display: grid; flex: 1; min-width: 0; }
.theme-option-name { font-size: var(--text-small); line-height: var(--leading-small); font-weight: 560; }
.theme-option-role { font-size: var(--text-label); line-height: var(--leading-label); letter-spacing: var(--tracking-label); color: var(--text-2); }
@media (hover: hover) { .theme-option:hover { background: var(--surface-2); } }

/* Chips: one flat square per theme, in one order everywhere. Auto is the same chip split on the diagonal, half filled
   with the theme it resolves to. The selected chip wears an ink ring. A swatch shows its own theme's accent by
   definition, the one place a value is named per theme. */
[data-chip="confluence"], html[data-theme="confluence"] .theme-trigger { --chip: #A855F7; }
[data-chip="aurora"], html[data-theme="aurora"] .theme-trigger { --chip: #2DD4BF; }
[data-chip="solar"], html[data-theme="solar"] .theme-trigger { --chip: #F1453F; }
[data-chip="platinum"], html[data-theme="platinum"] .theme-trigger { --chip: #E2E8F0; }
[data-chip="daylight"], html[data-theme="daylight"] .theme-trigger { --chip: #6D28D9; }
.cw-dot {
  position: relative; flex: none; width: 16px; height: 16px; border-radius: var(--radius-chip); background: var(--chip);
  box-shadow: inset 0 0 0 1px color-mix(in oklab, var(--text) 16%, transparent);
  outline: 1.5px solid transparent; outline-offset: 3px;
}
.theme-option[data-theme="auto"] .cw-dot, html[data-theme-choice="auto"] .theme-trigger .cw-dot { border: 1.5px solid var(--chip); background: none; box-shadow: none; }
.theme-option[data-theme="auto"] .cw-dot::after, html[data-theme-choice="auto"] .theme-trigger .cw-dot::after {
  content: ""; position: absolute; inset: -1.5px; border-radius: inherit; background: var(--chip); clip-path: polygon(100% 0, 100% 100%, 0 100%);
}
.theme-option[aria-selected="true"] .cw-dot { outline-color: var(--text); }

@media (prefers-reduced-motion: no-preference) {
  .theme-trigger { transition: scale var(--dur-feedback) var(--ease-burst), background-color var(--dur-state) var(--ease-state); }
  .theme-trigger:active { scale: 0.97; }
  /* Closed: no transition on transform, so the close is a fade with a 1 percent settle while the open's longer travel
     is restored only once the palette is invisible. */
  .theme-dropdown {
    transform: translateY(-6px) scale(0.95); scale: 0.99;
    transition: opacity 150ms var(--ease-dismiss), scale 150ms var(--ease-dismiss), transform 0s linear 150ms, visibility 0s linear 150ms;
  }
  .theme-dropdown[data-open] {
    transform: none; scale: 1;
    transition: opacity 180ms var(--ease-enter), scale 280ms var(--ease-enter), transform 280ms var(--ease-enter), visibility 0s;
  }
  /* Each chip drops out of the trigger's chip into its row, 28 ms after the one above; its words slide out of the
     column after it. Closing leaves them in place until the palette has faded. */
  .theme-option .cw-dot, .theme-option-copy { opacity: 0; transition: opacity 0s linear 150ms, transform 0s linear 150ms; }
  .theme-option .cw-dot { transform: translateY(-14px) scale(0.4); }
  .theme-option-copy { transform: translateX(8px); }
  .theme-dropdown[data-open] .theme-option .cw-dot {
    opacity: 1; transform: none;
    transition: opacity 120ms var(--ease-enter) calc(30ms + var(--i) * 28ms), transform 320ms var(--ease-enter) calc(30ms + var(--i) * 28ms);
  }
  .theme-dropdown[data-open] .theme-option-copy {
    opacity: 1; transform: none;
    transition: opacity 200ms var(--ease-enter) calc(80ms + var(--i) * 28ms), transform 280ms var(--ease-enter) calc(80ms + var(--i) * 28ms);
  }
  /* Opened from the keyboard: the palette is there on the same frame. */
  .theme-control[data-kbd] .theme-dropdown[data-open], .theme-control[data-kbd] .theme-dropdown[data-open] :is(.cw-dot, .theme-option-copy) { transition: none; }
}

/* The pick (theme-picker.js). In the old snapshot the palette and the picked chip carry their own names, so the page's
   crossfade cannot paint over the palette: it leaves first, above the page. In the new snapshot the trigger's chip
   takes the picked chip's name, so the chip flies from its row into the trigger while the page crossfades (420 ms).
   Colours change; layout never does. */
@keyframes oc-fade-out { to { opacity: 0; } }
@keyframes oc-fade-in { from { opacity: 0; } }
@keyframes theme-palette-out { to { opacity: 0; transform: scale(0.99); } }
html[data-retint="pick"] .theme-dropdown { view-transition-name: theme-palette; }
html[data-retint="pick"] .theme-trigger .cw-dot { visibility: hidden; }
html[data-retint="pick"] .theme-option[aria-selected="true"] .cw-dot,
html[data-retint="landed"] .theme-trigger .cw-dot { view-transition-name: theme-chip; }
html[data-retint]::view-transition-group(*) { animation-duration: var(--dur-panel); }
html[data-retint]::view-transition-old(root) { animation: oc-fade-out var(--dur-panel) var(--ease-state) both; mix-blend-mode: plus-lighter; }
html[data-retint]::view-transition-new(root) { animation: oc-fade-in var(--dur-panel) var(--ease-state) both; mix-blend-mode: plus-lighter; }
html[data-retint]::view-transition-old(theme-palette) { animation: theme-palette-out 150ms var(--ease-dismiss) both; transform-origin: calc(100% - 22px) 0; }
html[data-retint]::view-transition-group(theme-chip) { animation-duration: var(--dur-panel); animation-timing-function: var(--ease-enter); }
html[data-retint]::view-transition-old(theme-chip) { animation: none; opacity: 0; }
html[data-retint]::view-transition-new(theme-chip) { animation: none; }

/* Reduced motion: every element shows its finished state; the palette keeps a short crossfade and nothing moves. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: 0.01ms !important; animation-iteration-count: 1 !important; transition-duration: 0.01ms !important; scroll-behavior: auto !important; }
  .theme-dropdown { transition: opacity 120ms var(--ease-dismiss), visibility 0s linear 120ms !important; }
  .theme-dropdown[data-open] { transition: opacity 120ms var(--ease-dismiss), visibility 0s !important; }
}
