/* ===================================================================
   VOOHY APP DESIGN SYSTEM  (logged-in surfaces)

   One file, one source of truth for the look of everything behind the
   login. Deliberately mirrors views/component_landing_head.php so the
   marketing site and the product read as the same piece of software:
   same paper-and-ink palette, same two signal colours taken from the
   Voohy mark, same type pairing.

   Loaded as a real stylesheet from <head> (see views/header_head.php),
   not injected into <body>, so it does not depend on PHP include order
   and the browser can cache it.

   Every rule is either a vx- prefixed class or scoped to the app shell
   via body.vx-app / body:has(.vx-app-shell), so linking this file on a
   public page changes nothing there. vx- also keeps it clear of
   DaisyUI 2.x, which these pages still load.
   =================================================================== */

/* ---------- TOKENS ---------------------------------------------- */
:root {
	--paper:      #faf9f7;   /* app background                        */
	--paper-2:    #f1eee9;   /* sidebar panel, table headers, wells   */
	--card:       #ffffff;
	--ink:        #18181b;   /* primary text, primary buttons         */
	--ink-2:      #52525b;   /* secondary text                        */
	--ink-3:      #8b8b93;   /* metadata, placeholders                */
	--rule:       rgba(24,24,27,0.14);
	--rule-2:     rgba(24,24,27,0.07);
	--accent:     #c0432b;   /* coral, from the stem of the mark      */
	--accent-bg:  rgba(192,67,43,0.07);
	--on-accent:  #ffffff;
	--grass:      #14755b;   /* teal-green, from the leaves           */
	--grass-bg:   rgba(20,117,91,0.08);
	--amber:      #92610d;
	--amber-bg:   rgba(146,97,13,0.09);

	--rail:       268px;     /* sidebar width at lg and up            */
	--radius:     10px;
}

/* ---------- BASE ------------------------------------------------- */
/* Scoped two ways on purpose: :has() keys off the shell markup with no
   script and no flash, and the .vx-app class is set by a one-line
   inline script for anything that predates :has(). Either alone is
   enough; together they cover every browser we see. */
body.vx-app,
body:has(.vx-app-shell) {
	background: var(--paper);
	color: var(--ink);
	font-family: 'Instrument Sans', system-ui, -apple-system, sans-serif;
	font-optical-sizing: auto;
	-webkit-font-smoothing: antialiased;
}
body.vx-app ::selection,
body:has(.vx-app-shell) ::selection { background: var(--accent); color: #fff; }

/* The sidebar is position:fixed, so it is out of flow. Rather than
   touch the twelve-column grid that 85 page templates hard-code, we
   simply inset the whole document. Only pages that actually render a
   rail get the inset. */
@media (min-width: 1024px) {
	body.vx-has-rail,
	body:has(.vx-rail) { padding-left: var(--rail); }

	/* The old rail occupied grid column one, so those templates set
	   `lg:col-span-11` (a few `lg:col-span-10 xl:col-span-11`) on
	   <main>. With the rail out of the grid that strands a column, so
	   reclaim the row. Matching on col-span-11 is what keeps catalog
	   and insights out of it — they carry a secondary sidebar in the
	   grid and span 9/10, so they are left exactly as they were. */
	body:has(.vx-rail) main.lg\:col-span-11,
	body:has(.vx-rail) main.xl\:col-span-11,
	body.vx-has-rail main.lg\:col-span-11,
	body.vx-has-rail main.xl\:col-span-11 { grid-column: span 12 / span 12; }
}

/* ---------- TYPE ------------------------------------------------- */
.vx-display {
	font-family: 'Fraunces', Georgia, serif;
	font-optical-sizing: auto;
	letter-spacing: -0.021em;
	font-weight: 400;
	color: var(--ink);
}
.vx-h1 { font-size: clamp(2rem, 1.4rem + 1.9vw, 2.75rem); line-height: 1.08; }
.vx-h2 { font-size: 1.375rem; line-height: 1.2; }
.vx-h3 { font-size: 1.0625rem; line-height: 1.3; font-weight: 500; }

/* Small-caps machine label. Same device as the marketing site, used
   here for section headers, table columns and metadata. */
.vx-label {
	font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
	font-size: 11px;
	letter-spacing: 0.14em;
	text-transform: uppercase;
	color: var(--ink-3);
}
.vx-meta { font-size: 0.8125rem; color: var(--ink-3); }
.vx-sub  { font-size: 0.875rem;  color: var(--ink-2); line-height: 1.55; }
.vx-tnum { font-variant-numeric: tabular-nums; }

/* ---------- PAGE SCAFFOLD ---------------------------------------- */
.vx-page   { padding: 2.25rem 0 4rem; }
.vx-page-head { margin-bottom: 2rem; }
.vx-page-head .vx-sub { margin-top: 0.5rem; max-width: 60ch; }

/* Hairline that separates stacked sections without adding a box */
.vx-rule { border: 0; border-top: 1px solid var(--rule-2); margin: 2rem 0; }

/* ---------- CARD -------------------------------------------------- */
.vx-card {
	background: var(--card);
	border: 1px solid var(--rule-2);
	border-radius: var(--radius);
	padding: 1.25rem 1.375rem;
}
.vx-card-lg { padding: 1.75rem; }
.vx-card-head {
	display: flex; align-items: baseline; justify-content: space-between;
	gap: 1rem; margin-bottom: 1rem;
}
/* Interactive card. Lifts on the accent rather than on a drop shadow. */
a.vx-card, .vx-card-link {
	display: block; text-decoration: none;
	transition: border-color .18s ease, transform .18s ease;
}
a.vx-card:hover, .vx-card-link:hover {
	border-color: var(--rule);
	transform: translateY(-1px);
}

/* Card that needs to be picked out of a grid — an unfinished
   benchmark, a required next step. Coral edge, no fill, so it reads
   as "this one" without shouting. */
.vx-card-flagged { border-color: var(--accent); }
.vx-card-flagged:hover { border-color: var(--accent); }

/* A quiet well for secondary content inside a card */
.vx-well {
	background: var(--paper-2);
	border-radius: 8px;
	padding: 0.875rem 1rem;
}

/* ---------- BUTTONS ----------------------------------------------- */
.vx-btn {
	display: inline-flex; align-items: center; justify-content: center;
	gap: 0.5rem;
	font-family: 'Instrument Sans', system-ui, sans-serif;
	font-size: 0.875rem; font-weight: 500; line-height: 1;
	padding: 0.625rem 1rem;
	border-radius: 8px;
	border: 1px solid transparent;
	cursor: pointer;
	text-decoration: none;
	transition: background-color .16s ease, border-color .16s ease, opacity .16s ease;
	white-space: nowrap;
}
.vx-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.vx-btn-primary   { background: var(--ink);    color: var(--paper); }
.vx-btn-primary:hover   { background: #2c2c31; color: var(--paper); }

.vx-btn-accent    { background: var(--accent); color: var(--on-accent); }
.vx-btn-accent:hover    { opacity: .88; color: var(--on-accent); }

.vx-btn-ghost     { background: var(--card);   color: var(--ink); border-color: var(--rule); }
.vx-btn-ghost:hover     { background: var(--paper-2); color: var(--ink); }

.vx-btn-quiet     { background: transparent;   color: var(--ink-2); }
.vx-btn-quiet:hover     { background: var(--paper-2); color: var(--ink); }

.vx-btn-sm  { padding: 0.4375rem 0.75rem; font-size: 0.8125rem; }
.vx-btn-lg  { padding: 0.8125rem 1.375rem; font-size: 0.9375rem; }
.vx-btn-block { width: 100%; }
.vx-btn[disabled], .vx-btn.is-disabled { opacity: .45; pointer-events: none; }

/* ---------- BADGES ------------------------------------------------ */
.vx-badge {
	display: inline-flex; align-items: center; gap: 0.3125rem;
	font-size: 0.75rem; font-weight: 500; line-height: 1;
	padding: 0.3125rem 0.5625rem;
	border-radius: 999px;
	background: var(--paper-2); color: var(--ink-2);
	white-space: nowrap;
}
.vx-badge-grass  { background: var(--grass-bg);  color: var(--grass); }
.vx-badge-accent { background: var(--accent-bg); color: var(--accent); }
.vx-badge-amber  { background: var(--amber-bg);  color: var(--amber); }
.vx-badge-ink    { background: var(--ink);       color: var(--paper); }

/* ---------- TABLE -------------------------------------------------- */
.vx-table { width: 100%; border-collapse: collapse; font-size: 0.875rem; }
.vx-table thead th {
	font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
	font-size: 11px; letter-spacing: 0.12em; text-transform: uppercase;
	color: var(--ink-3); font-weight: 400; text-align: left;
	padding: 0.75rem 1rem;
	background: var(--paper-2);
	border-bottom: 1px solid var(--rule-2);
	white-space: nowrap;
}
.vx-table thead th:first-child { border-top-left-radius: 8px; }
.vx-table thead th:last-child  { border-top-right-radius: 8px; }
.vx-table tbody td {
	padding: 0.9375rem 1rem;
	border-bottom: 1px solid var(--rule-2);
	color: var(--ink-2);
	vertical-align: middle;
}
.vx-table tbody tr:last-child td { border-bottom: 0; }
.vx-table tbody tr:hover td { background: rgba(24,24,27,0.015); }
.vx-table td .vx-strong, .vx-strong { color: var(--ink); font-weight: 500; }
/* Row that needs to be picked out — an in-progress session ahead of
   completed ones. Same device as .vx-card-flagged: a wash, not a
   shout. */
.vx-row-flagged td { background: var(--amber-bg); }

/* ---------- FORM --------------------------------------------------- */
.vx-input, .vx-select, .vx-textarea {
	width: 100%;
	font-family: 'Instrument Sans', system-ui, sans-serif;
	font-size: 0.875rem;
	color: var(--ink);
	background: var(--card);
	border: 1px solid var(--rule);
	border-radius: 8px;
	padding: 0.625rem 0.75rem;
	transition: border-color .16s ease, box-shadow .16s ease;
}
.vx-input::placeholder, .vx-textarea::placeholder { color: var(--ink-3); }
.vx-input:focus, .vx-select:focus, .vx-textarea:focus {
	outline: none;
	border-color: var(--ink);
	box-shadow: 0 0 0 3px rgba(24,24,27,0.06);
}
.vx-field-label {
	display: block; font-size: 0.8125rem; font-weight: 500;
	color: var(--ink); margin-bottom: 0.375rem;
}

/* Selectable option card — the pattern used for difficulty pickers,
   plan pickers and any other "choose one of these" moment. */
.vx-option {
	display: block; width: 100%; text-align: left;
	background: var(--card);
	border: 1px solid var(--rule-2);
	border-radius: var(--radius);
	padding: 1rem 1.125rem;
	cursor: pointer;
	transition: border-color .16s ease, background-color .16s ease;
}
.vx-option:hover { border-color: var(--rule); }
.vx-option.is-selected,
.vx-option:has(input:checked) {
	background: var(--grass-bg);
	border-color: var(--grass);
}

/* ---------- PROGRESS ----------------------------------------------- */
.vx-progress {
	height: 6px; border-radius: 999px;
	background: var(--rule-2); overflow: hidden;
}
.vx-progress > span {
	display: block; height: 100%; border-radius: 999px;
	background: var(--grass);
	transition: width .5s cubic-bezier(.2,.7,.3,1);
}

/* ---------- EMPTY STATE --------------------------------------------- */
.vx-empty {
	text-align: center;
	padding: 3rem 1.5rem;
	border: 1px dashed var(--rule);
	border-radius: var(--radius);
	background: var(--card);
}

/* ---------- SIDEBAR ------------------------------------------------- */
/* No `display` here on purpose. The element carries Tailwind's
   `hidden lg:flex`, and this sheet is linked after the Play CDN has
   injected its own — declaring display:flex at equal specificity would
   win on source order and leak the rail onto mobile, where the top
   bar's slide-down menu is the navigation. Same reason .vx-only-mobile
   exists at the foot of this file. */
.vx-rail {
	position: fixed; inset: 0 auto 0 0;
	width: var(--rail);
	flex-direction: column;
	padding: 0.75rem;
	background: var(--paper);
	z-index: 40;
}
.vx-rail-inner {
	display: flex; flex-direction: column; flex: 1 1 auto; min-height: 0;
	background: var(--paper-2);
	border: 1px solid var(--rule-2);
	border-radius: 14px;
	overflow: hidden;
}
/* Workspace identity block at the top of the rail */
.vx-rail-id {
	display: flex; align-items: center; gap: 0.625rem;
	padding: 0.875rem 0.9375rem;
	border-bottom: 1px solid var(--rule-2);
}
/* These are spans, so they need display:block or the name and the
   sub-line run together on one line. */
.vx-rail-id-text { display: block; min-width: 0; line-height: 1.25; }
.vx-rail-id-name {
	display: block;
	font-size: 0.875rem; font-weight: 600; color: var(--ink);
	white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.vx-rail-id-sub {
	display: block;
	font-size: 0.75rem; color: var(--ink-3);
	white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.vx-rail-nav { flex: 1 1 auto; overflow-y: auto; padding: 0.75rem 0.625rem; }

/* Section view: replaces the global nav entirely on /catalog and
   /insights — see the branch in views/sidebar.php and
   views/component_rail_sections.php. Back link first, then the
   section title in the same label device used everywhere else. */
.vx-nav-back { color: var(--ink-2); margin-bottom: 0.25rem; }
.vx-rail-group-label {
	padding: 0.5rem 0.625rem 0.375rem;
	font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
	font-size: 10px; letter-spacing: 0.14em; text-transform: uppercase;
	color: var(--ink-3);
}
.vx-rail-group-label-sub { padding-top: 0.75rem; opacity: .8; }
/* Filters sit a step quieter than destinations: no icon, so the text
   lines up with the labels above it rather than with their glyphs. */
.vx-nav-sub {
	padding-left: 1.9375rem;
	font-weight: 400;
	font-size: 0.8125rem;
}
.vx-rail-foot { padding: 0.625rem; border-top: 1px solid var(--rule-2); }
.vx-nav-item {
	position: relative;
	display: flex; align-items: center; gap: 0.6875rem;
	padding: 0.5625rem 0.625rem;
	margin-bottom: 2px;
	border-radius: 8px;
	font-size: 0.875rem; font-weight: 500;
	color: var(--ink-2);
	text-decoration: none;
	transition: background-color .16s ease, color .16s ease;
}
.vx-nav-item:hover { background: rgba(24,24,27,0.045); color: var(--ink); }
.vx-nav-item svg { width: 18px; height: 18px; flex: 0 0 18px; opacity: .72; }
.vx-nav-item.is-active {
	background: var(--card);
	color: var(--ink);
	box-shadow: 0 1px 2px rgba(24,24,27,0.05);
}
.vx-nav-item.is-active svg { opacity: 1; }
/* Coral marker so the active row carries the brand accent */
.vx-nav-item.is-active::before {
	content: ""; position: absolute; left: -0.625rem; top: 50%;
	width: 3px; height: 18px; margin-top: -9px;
	border-radius: 0 3px 3px 0;
	background: var(--accent);
}

/* ---------- TOP BAR -------------------------------------------------- */
.vx-topbar {
	display: flex; align-items: center; justify-content: flex-end;
	gap: 0.5rem;
	padding: 0.75rem 1.5rem;
	background: transparent;
}
.vx-topbar-item {
	display: inline-flex; align-items: center; gap: 0.5rem;
	padding: 0.4375rem 0.625rem;
	border-radius: 8px;
	font-size: 0.875rem; font-weight: 500; color: var(--ink-2);
	text-decoration: none;
	transition: background-color .16s ease, color .16s ease;
}
.vx-topbar-item:hover { background: var(--paper-2); color: var(--ink); }
.vx-avatar {
	width: 30px; height: 30px; border-radius: 999px;
	object-fit: cover; background: var(--paper-2);
}
.vx-menu {
	position: absolute; right: 0; top: calc(100% + 6px);
	min-width: 208px;
	background: var(--card);
	border: 1px solid var(--rule-2);
	border-radius: var(--radius);
	box-shadow: 0 8px 28px rgba(24,24,27,0.10);
	padding: 0.375rem;
	z-index: 60;
}
.vx-menu a, .vx-menu button {
	display: flex; align-items: center; gap: 0.5rem; width: 100%;
	padding: 0.5rem 0.625rem;
	border-radius: 6px;
	font-size: 0.875rem; color: var(--ink-2);
	text-decoration: none; text-align: left; background: none; border: 0;
	cursor: pointer;
}
.vx-menu a:hover, .vx-menu button:hover { background: var(--paper-2); color: var(--ink); }
.vx-menu-sep { height: 1px; background: var(--rule-2); margin: 0.375rem 0; }

/* ---------- DRAWER ---------------------------------------------------- */
.vx-drawer {
	position: fixed; inset: 0 0 0 auto;
	width: min(430px, 100vw);
	background: var(--card);
	border-left: 1px solid var(--rule-2);
	box-shadow: -12px 0 40px rgba(24,24,27,0.08);
	display: flex; flex-direction: column;
	z-index: 70;
}
.vx-drawer-head { padding: 1.25rem 1.375rem; border-bottom: 1px solid var(--rule-2); }
.vx-drawer-body { flex: 1 1 auto; overflow-y: auto; padding: 1.25rem 1.375rem; }
.vx-drawer-foot { padding: 1rem 1.375rem; border-top: 1px solid var(--rule-2); }

/* ---------- TABS ------------------------------------------------------- */
.vx-tabs { display: flex; gap: 1.5rem; border-bottom: 1px solid var(--rule-2); }
.vx-tab {
	position: relative;
	padding: 0.75rem 0.125rem;
	font-size: 0.875rem; font-weight: 500;
	color: var(--ink-3); text-decoration: none;
	transition: color .16s ease;
}
.vx-tab:hover { color: var(--ink-2); }
.vx-tab.is-active { color: var(--ink); }
.vx-tab.is-active::after {
	content: ""; position: absolute; left: 0; right: 0; bottom: -1px;
	height: 2px; background: var(--ink);
}

/* ---------- MOTION ------------------------------------------------------ */
@media (prefers-reduced-motion: reduce) {
	body.vx-app *, body.vx-app *::before, body.vx-app *::after {
		transition-duration: 0.01ms !important;
		animation-duration: 0.01ms !important;
	}
}

/* ---------- RESPONSIVE UTILITIES ----------------------------------------
   Tailwind's `lg:hidden` cannot be relied on for an element that also
   carries a vx- class setting `display`: the Play CDN injects its sheet
   while the <head> is still parsing, so this file is linked after it and
   wins on source order at equal specificity. That is exactly how the
   hamburger stayed visible on desktop.

   So hiding at desktop is owned here. It only sets `display: none` and
   never sets a display below lg, which leaves whatever the element
   already uses (Tailwind's `flex`, or .vx-topbar-item's inline-flex)
   intact. It must stay the last rule in the file so it beats those.
   ------------------------------------------------------------------------ */
@media (min-width: 1024px) {
	.vx-only-mobile { display: none; }
}
