/* Kryyvo brand theme.
 *
 * Loaded last (app_include_css for the desk, web_include_css for the portal),
 * so equal-specificity rules win without !important.
 *
 * Scope: ACCENTS only — primary buttons, checkboxes, active tabs/filters,
 * focus rings, icons. Deliberately NOT touched:
 *   - greys / --text-color: they carry hierarchy, not brand.
 *   - semantic colours (danger/success/warning): they carry meaning;
 *     recolouring a red to brand blue makes destructive actions look safe.
 *   - `a { color: var(--text-color) }`: frappe styles desk links neutral on
 *     purpose — blue links inside dense list views read as noise.
 */

:root,
[data-theme="light"],
[data-theme="dark"] {
	--kryyvo-blue: #45a6dc;  /* brand accent */
	--kryyvo-gold: #edcb46;
	--ky-blue-400: #4fb0e4;
	--ky-blue-500: #45a6dc;
	--ky-blue-600: #3592c9;  /* solid fills */
	--ky-blue-700: #1d6f9f;  /* hover / pressed */

	/* --primary drives checkboxes, radios, active form tabs, active filter and
	   group-by chips, global-search result links and the calendar
	   now-indicator. Audited: none of its 18 usages are body text. */
	--primary: var(--ky-blue-500);
	--brand-color: var(--ky-blue-500);

	/* .btn.btn-primary { background-color: var(--btn-primary) } */
	--btn-primary: var(--ky-blue-600);

	--focus-default: 0 0 0 3px rgba(69, 166, 220, .18);
	--checkbox-focus-shadow: 0 0 0 3px rgba(69, 166, 220, .18);
}

/* ---------- icons ----------
   Frappe icons are lucide-style outlines coloured via --icon-stroke;
   .es-icon glyphs are solid and take their fill from the same variable. */
.icon,
.es-icon {
	--icon-stroke: var(--kryyvo-blue);
}

/* Keep icons legible wherever they sit on a filled or inverted surface.
   Without this, icons inside primary buttons and selected sidebar rows
   render blue-on-blue and effectively disappear. */
.btn .icon,
.btn .es-icon,
[class*="btn-primary"] .icon,
.selected .icon,
.active .icon,
.indicator-pill .icon,
.sidebar-item-container .selected .icon {
	--icon-stroke: currentColor;
}

/* frappe-ui components (the workspace sidebar) do not use --icon-stroke at
   all — their SVGs inherit `currentColor` from a `text-ink-gray-*` utility
   class, so the variable above never reaches them. Colour the wrapper
   instead. Scoped to the sidebar deliberately: `text-ink-gray-7` is also body
   text elsewhere, so overriding that token directly would tint prose. */
.sidebar-item-icon,
.sidebar-item-icon .icon,
.sidebar-item-icon svg {
	color: var(--kryyvo-blue);
}

/* ---------- primary button ----------
   Light mode ships dark-fill/white-text; dark mode INVERTS to
   light-fill/dark-text via `color: var(--neutral)`. We use one blue fill in
   both themes, so the text colour must be pinned or dark mode renders
   black-on-blue. */
.btn.btn-primary,
[data-theme="dark"] .btn.btn-primary {
	color: #fff;
}
.btn.btn-primary:hover {
	background-color: var(--ky-blue-700);
	color: #fff;
}
.btn.btn-primary:active,
[data-theme="dark"] .btn.btn-primary:active {
	background-color: var(--ky-blue-700) !important;
	color: #fff !important;
}

/* ---------- /desk "Sky" — matches the login page ----------
   Same palette and motion as www/login.html so the app opens on the world the
   user just signed in from.

   `.desktop-wrapper` exists only on /desk, so this cannot leak into list or
   form views. Written as `div.desktop-wrapper` (0,1,1) because desktop.css is
   injected at runtime AFTER this stylesheet and would win at equal specificity.

   Clouds are layered radial-gradients and the arcs are an inline SVG data URI,
   so the whole scene needs no extra DOM and no JavaScript. */
/* The scroll container (.main-section, overflow-y:auto) carries a 90px
   padding-bottom for other pages. A full-height wrapper inside it therefore
   measures 100vh + 90px and produces a scrollbar with nothing to scroll to.
   Drop that padding only on the page that actually holds the desk grid,
   rather than hard-coding 90px into a calc() that would break silently if
   frappe ever changes it.

   !important is required, not lazy: frappe sets this padding INLINE from JS,
   and an inline declaration outranks any stylesheet selector however specific.
   An author !important is the only thing that beats a non-important inline
   style, which is exactly this case. */
.main-section:has(.desktop-wrapper) {
	padding-bottom: 0 !important;
}

div.desktop-wrapper {
	position: relative;
	min-height: 100vh;
	background-color: #cfe9f7;
	background-image:
		/* arc lines */
		url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1120 760' preserveAspectRatio='none'%3E%3Cpath d='M-40 760 C 160 430, 420 300, 1160 250' fill='none' stroke='rgba(255,255,255,.85)' stroke-width='1.1'/%3E%3Cpath d='M-40 700 C 240 470, 560 340, 1160 400' fill='none' stroke='rgba(255,255,255,.6)' stroke-width='1'/%3E%3Cpath d='M1160 760 C 940 470, 620 330, -40 330' fill='none' stroke='rgba(255,255,255,.5)' stroke-width='1'/%3E%3C/svg%3E"),
		/* small drifting puffs */
		radial-gradient(38% 26% at 14% 22%, rgba(255,255,255,.62), rgba(255,255,255,0) 70%),
		radial-gradient(30% 22% at 86% 30%, rgba(255,255,255,.50), rgba(255,255,255,0) 70%),
		/* cloud bank along the horizon */
		radial-gradient(58% 34% at 6% 100%, rgba(255,255,255,.98), rgba(255,255,255,0) 68%),
		radial-gradient(62% 36% at 95% 102%, rgba(255,255,255,.95), rgba(255,255,255,0) 66%),
		radial-gradient(50% 32% at 52% 108%, rgba(255,255,255,1), rgba(255,255,255,0) 64%),
		/* sky */
		linear-gradient(180deg, #7fc4ea 0%, #a9d9f1 26%, #cfe9f7 52%, #eaf5fb 74%, #f7fbfd 100%);
	background-repeat: no-repeat;
	background-size: 100% 100%;
	background-attachment: fixed;
}

/* Frosted chrome, echoing the login page's logo pill. */
div.desktop-wrapper .desktop-navbar {
	background: rgba(255, 255, 255, .72);
	border-bottom: 1px solid rgba(255, 255, 255, .85);
	box-shadow: 0 10px 24px -20px rgba(13, 53, 80, .6);
	backdrop-filter: blur(10px);
}
div.desktop-wrapper .desktop-navbar-modal-search {
	background: rgba(255, 255, 255, .78);
	border: 1px solid rgba(255, 255, 255, .9);
	box-shadow: 0 6px 16px -12px rgba(13, 53, 80, .5);
}

/* Labels sit on the pale lower band; brand navy keeps them readable. */
div.desktop-wrapper .icon-title {
	color: #10283a;
	text-shadow: 0 1px 0 rgba(255, 255, 255, .55);
}

/* Lift the tiles off the sky slightly, the way the login card floats. */
div.desktop-wrapper a.desktop-icon img.app-icon,
div.desktop-wrapper a.desktop-icon .icon-container {
	border-radius: 16px;
	box-shadow: 0 14px 30px -16px rgba(13, 53, 80, .55), 0 2px 5px rgba(13, 53, 80, .07);
	transition: transform .18s ease, box-shadow .18s ease;
}
div.desktop-wrapper a.desktop-icon:hover img.app-icon,
div.desktop-wrapper a.desktop-icon:hover .icon-container {
	transform: translateY(-3px);
	box-shadow: 0 20px 38px -16px rgba(13, 53, 80, .6), 0 2px 6px rgba(13, 53, 80, .08);
}

@media (prefers-reduced-motion: reduce) {
	div.desktop-wrapper a.desktop-icon:hover img.app-icon,
	div.desktop-wrapper a.desktop-icon:hover .icon-container { transform: none; }
}

/* ---------- desk tile labels ----------
   desktop.css truncates every tile label to a single line
   (.icon-title { white-space: nowrap; text-overflow: ellipsis }) inside a
   fixed 35px caption, so "Kryyvo Platform" renders as "Kryyvo Plat…".
   Both rules need lifting: unwrapping the title alone would still clip
   against the caption's fixed height.

   Scoped under .desktop-icon deliberately — that page's stylesheet is
   injected at runtime, after this file, so a bare .icon-title would lose
   the cascade on equal specificity.

   Measured on the live grid: tiles are 127px with 16px padding each side,
   leaving a 93px content box — but "Subcontracting" needs 105px, so it broke
   mid-word. Widening the caption past its parent is the wrong fix: the tile is
   a column flexbox, an oversized child overflows to one side rather than
   centring, and the label ends up 13px off from its icon.

   Reclaim the padding instead. Tiles sit in a grid with its own 16px gap, so
   the internal padding was not what separated them; dropping it to 6px yields
   a 115px content box that fits the longest label with room to spare, and both
   the icon and the caption stay centred in the same box. */
/* `a.desktop-icon`, not `.desktop-icon`: the tile is an <a>, and adding the
   element type raises specificity to (0,1,1) so this beats desktop.css's own
   (0,1,0) rule, which is injected after this stylesheet. */
a.desktop-icon {
	padding-inline: 6px;
}
.desktop-icon .icon-caption {
	height: auto;
	min-height: 35px;
	text-wrap: wrap;
}
.desktop-icon .icon-title {
	white-space: normal;
	overflow: visible;
	text-overflow: clip;
	/* break-word, not anywhere: only split a word that genuinely cannot fit,
	   so nothing breaks mid-word at the widths above. */
	overflow-wrap: break-word;
}

/* ---------- tier 2: hardcoded leftovers ----------
   These ship as literal hex in the compiled bundle rather than as tokens, so
   a variable override cannot reach them. */
.text-primary {
	color: var(--ky-blue-600) !important;
}

.btn-primary-light {
	background-color: rgba(69, 166, 220, .12);
	border-color: rgba(69, 166, 220, .28);
	color: var(--ky-blue-700);
	box-shadow: none;
}
.btn-primary-light:hover,
.btn-primary-light:active,
.btn-primary-light:focus,
.btn-primary-light.focus {
	background-color: rgba(69, 166, 220, .18);
	border-color: rgba(69, 166, 220, .36);
	color: var(--ky-blue-700);
}
[data-theme="dark"] .btn-primary-light {
	background-color: rgba(69, 166, 220, .16);
	color: var(--ky-blue-400);
}

/* Chips/actions already resolve their base colour through var(--primary);
   only their hover is hardcoded. */
.list-sidebar .sidebar-action:hover,
.filter-area .filter-box .remove-filter:hover,
.group-by-popover .group-by-box .remove-group-by:hover {
	color: var(--ky-blue-700);
}
