/* Design system base (GTM-331): page background, type defaults, focus, motion preferences.
   Scoped under html.ps-v2 (portal-nav.js sets it on every page before the first paint). */

/* hidden means hidden: no stylesheet rule (page, feature file or component) and no inline display can show an element that
   carries the hidden attribute. Code toggles el.hidden (GTM-337 removed the last inline style.display reveals, so the old
   exception for them is gone). */
html.ps-v2 [hidden] { display: none !important; }

html.ps-v2 body {
  background: var(--ps-page);
  color: var(--ps-fg);
  font-family: var(--ps-font-ui);
  font-size: var(--ps-type-body);
  font-weight: var(--ps-weight-regular);
  line-height: 1.5;
  letter-spacing: 0;   /* the website's brand.css tracks body text at .05em; the portal doesn't */
  -webkit-font-smoothing: antialiased;
}

/* The card edge stays a hairline: its lime end read as a yellow haze over a calm page. (GTM-333's photo backgrounds,
   removed Oct 12, 2026, brought back the full edge.) */
html.ps-v2 { --ps-edge: linear-gradient(135deg, rgba(255,255,255,.95), rgba(227,208,252,.5) 50%, rgba(255,255,255,.55)); }
/* Night Wash (GTM-332, Oct 13): dark glass is clear (white at 4.5%), so a gradient painted under the whole card would show
   through it. The rim moves into --ps-glass-shadow (a 1px inner line plus a top highlight) and the edge layer is empty. */
html.ps-v2[data-theme="dark"] { --ps-edge: linear-gradient(transparent, transparent); }

/* Focus ring (GTM-337): --ps-focus is ink in light and sprout in dark (a theme token, so it swaps inside .ps-dark and
   .ps-invert on its own). The always-dark chrome (rail, phone bars, accent cards, toasts, tooltips, the footer) is dark in
   both themes, so the ring there is always sprout. Every component's ring reads --ps-focus; never a fixed color. */
:is(#sidebar, .ps-tabbar, #notif-bell-btn, #tt-btn, .ps-card--accent, .ps-w--accent, .ps-toast, #toast, .ps-tip, #footer) { --ps-focus: var(--ps-color-sprout-strong); }
html.ps-v2 :focus-visible { outline: 2px solid var(--ps-focus); outline-offset: 2px; }
/* inside a scroller or a sticky table header the ring sits inside the control, so nothing clips it */
html.ps-v2 :is(.ps-table, .ps-twrap, .ps-tcard, .ps-trunc, .ps-gantt, .ps-seg, .ps-tabs) :is(a, button, [tabindex], input, select):focus-visible,
html.ps-v2 :is(.ps-trunc, .ps-kebab, .kebab-btn):focus-visible { outline-offset: -2px; }
/* a link with no class of its own: muted like .ps-link, never the browser's blue and purple; underlined so it never
   relies on color alone. Zero specificity, so every component's own link style wins. */
:where(html.ps-v2) :where(a:not([class])) { color: var(--ps-fg-2); text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: .22em;
  text-decoration-color: color-mix(in srgb, currentColor 40%, transparent); }
:where(html.ps-v2) :where(a:not([class])):is(:hover, :focus-visible) { color: var(--ps-fg); text-decoration-color: currentColor; }
html.ps-v2 ::selection { background: rgba(212, 245, 138, .6); color: var(--ps-color-ink); }

/* Monospace: ids, codes, JSON, hex values (--ps-font-mono at --ps-type-mono, which reads the same size as 13 Poppins) */
html.ps-v2 :is(.ps-mono, code, kbd, samp, pre) { font-family: var(--ps-font-mono); font-size: var(--ps-type-mono); letter-spacing: 0; font-variant-ligatures: none; }
html.ps-v2 :is(code, kbd) { padding: 1px 5px; border-radius: 6px; background: var(--ps-chip); color: var(--ps-fg); }
html.ps-v2 pre { margin: 0; padding: 12px 14px; overflow: auto; border-radius: var(--ps-radius-control); background: var(--ps-chip); color: var(--ps-fg); line-height: 1.55; white-space: pre-wrap; word-break: break-word; }
html.ps-v2 pre code { padding: 0; background: none; }

@media (max-width: 768px) {
  html.ps-v2 .ps-display { font-size: var(--ps-type-display-phone); }
}
/* Reduced motion (GTM-337 P3): nothing moves, scrolls smoothly or loops. Animations and transitions finish at once
   (their end events still fire). The layers that appear and disappear (menus, pop-ups, toasts, drawers, the phone menu,
   modals, tooltips) keep a short opacity fade only, because an instant cut there loses where things came from. */
@media (prefers-reduced-motion: reduce) {
  html, html.ps-v2 { scroll-behavior: auto !important; }
  html.ps-v2 *, html.ps-v2 *::before, html.ps-v2 *::after {
    animation-duration: .01ms !important; animation-iteration-count: 1 !important; animation-delay: 0s !important;
    transition-duration: .01ms !important; transition-delay: 0s !important; scroll-behavior: auto !important;
  }
  html.ps-v2 :is(.ps-pop, .ps-toast, .ps-drawer, .ps-scrim, .ps-modal, .ps-tip, .ps-w__tools, #sidebar, .modal-overlay, #toast) {
    transition-property: opacity, visibility !important; transition-duration: var(--ps-dur-pop) !important; transition-timing-function: ease !important;
  }
  /* the header and "+" panels open with a fade animation (portal.css swaps their keyframes to ps-item-fade) */
  html.ps-v2 :is(#notif-dropdown, #tt-dropdown, #new-item-menu, .kebab-menu).open { animation-duration: var(--ps-dur-pop) !important; }
}

/* Page transitions (GTM-332): moving between portal pages, the frame stays put (the rail, the corner buttons) while
   the page itself fades out up a little and the next one rises in. Cross-document View
   Transitions: same-origin navigations only; browsers without them just load the page. Reduced motion: a crossfade. */
@view-transition { navigation: auto; }
html.ps-v2 #sidebar { view-transition-name: ps-rail; }
html.ps-v2 #notif-bell-widget { view-transition-name: ps-bell; }
html.ps-v2 #tt-widget { view-transition-name: ps-timer; }
html.ps-v2 #new-item-widget { view-transition-name: ps-new; }
html.ps-v2 #portal-body { view-transition-name: ps-page; }
::view-transition-old(root), ::view-transition-new(root) { animation: none; }
::view-transition-old(ps-page) { animation: ps-vt-out 160ms var(--ps-ease-out) both; }
::view-transition-new(ps-page) { animation: ps-vt-in 280ms var(--ps-ease-out) both; }
@keyframes ps-vt-out { to { opacity: 0; transform: translateY(-6px); } }
@keyframes ps-vt-in { from { opacity: 0; transform: translateY(10px); } }
@keyframes ps-vt-fade-out { to { opacity: 0; } }
@keyframes ps-vt-fade-in { from { opacity: 0; } }
@media (prefers-reduced-motion: reduce) {
  ::view-transition-old(ps-page) { animation-name: ps-vt-fade-out; }
  ::view-transition-new(ps-page) { animation-name: ps-vt-fade-in; }
}

/* ---------- Touch (GTM-337 H1, E2): on a coarse pointer every control is at least 44px and glass blurs less ----------
   The control sizes are tokens, so every button family (.ps-btn and its sizes, the modal and form buttons, FullCalendar's)
   grows with them; ps-ui.css sizes the rest (fields, chips, kebabs, tabs, search) in its own touch block. */
@media (pointer: coarse) {
  :root { --ps-size-control: var(--ps-size-touch); --ps-size-control-sm: var(--ps-size-touch); --ps-glass-blur: var(--ps-glass-blur-touch); }
}

/* ---------- Less transparency, more contrast (GTM-337 P1): every material turns solid, nothing blurs ----------
   One block for all of them: the glass tokens point at the solid ones (cards, tables, fields, the legacy card list),
   graphite turns opaque (the rail, the phone bars and menu button, the header buttons, toasts, media tags), and no
   element keeps a backdrop blur, whatever its own rule says. The custom properties are !important so they also win
   inside .ps-dark, .ps-invert and the sign-in scene and card, which set their own theme values. */
@media (prefers-reduced-transparency: reduce), (prefers-contrast: more) {
  :root, .ps-dark, .ps-invert, .login-scene, .login-card {
    --ps-glass: var(--ps-glass-solid) !important; --ps-glass-strong: var(--ps-glass-solid) !important;
    --ps-color-graphite: var(--ps-color-graphite-solid) !important; --ps-qa-card: var(--ps-color-graphite-solid) !important;
    --ps-glass-blur: none !important; --ps-pop-blur: none !important;
  }
  html.ps-v2 *, html.ps-v2 *::before, html.ps-v2 *::after { -webkit-backdrop-filter: none !important; backdrop-filter: none !important; }
  html.ps-v2 .ps-wizard__bar { background: var(--ps-page); }
  html.ps-v2[data-theme="dark"] #sidebar { background: var(--ps-nav); }   /* the rail (portal.css), already solid */
}
/* More contrast (P2): secondary and faint text read as full text; hairlines and card edges turn solid */
@media (prefers-contrast: more) {
  :root, .ps-dark, .ps-invert, .login-scene, .login-card, .ps-card--accent {
    --ps-fg-2: var(--ps-fg) !important; --ps-fg-3: var(--ps-fg) !important;
    --ps-line: color-mix(in srgb, var(--ps-fg) 45%, transparent) !important;
    --ps-edge: linear-gradient(var(--ps-fg), var(--ps-fg)) !important;
  }
  :root { --nav-text-dim: var(--ps-color-on-dark) !important; --nav-text-ghost: var(--ps-color-sprout) !important; }
}
/* Forced colors (P4): controls and the chrome keep a visible boundary when the system strips backgrounds and shadows */
@media (forced-colors: active) {
  html.ps-v2 :is(button, [role="button"], [role="tab"], .ps-btn, .ps-chip, .ps-select-trigger, .login-field, .ps-input, .ps-search,
    input:not([type="checkbox"]):not([type="radio"]):not([type="range"]):not([type="hidden"]), select, textarea):not(.ps-bare, .ps-link) {
    border: 1px solid ButtonText !important;
  }
  html.ps-v2 :is(#sidebar, .ps-menu, .ps-modal__dialog, .ps-drawer, .ps-toast, .ps-tip, .kebab-menu, #new-item-menu, #notif-dropdown,
    #tt-dropdown, .ps-select-panel) {
    border: 1px solid CanvasText !important;
  }
  html.ps-v2 :focus-visible { outline-color: Highlight !important; }
}

