/* Generated by branding/build-space-css.js — edit that file, not this one. */

/* ================================ Shared ================================ */

@font-face {
  font-family: 'Montserrat';
  font-style: normal;
  font-weight: 300 700;
  font-display: swap;
  src: url('fonts/montserrat.woff2?v=1') format('woff2');
  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;
}

/* Every element on the login page, including form controls, which don't inherit fonts. */
div:has(> main):is(:has(form[aria-label="Login form"]), :has(a[href*="/oauth/"]):not(:has(form))),
div:has(> main):is(:has(form[aria-label="Login form"]), :has(a[href*="/oauth/"]):not(:has(form))) * {
  font-family: 'Montserrat', sans-serif;
}

/* Layout: the logo and tagline sit at the top and the card sits in the exact centre of the
   screen, as long as everything fits. The page is a flex column of
   [logo + tagline, grows][error][card][theme toggles, grows]: the two growing blocks start
   from zero and share the spare height equally, which centres the card. Neither can shrink
   below its own content, so on a short screen or with a taller card (SSO buttons) the logo
   block keeps its height and pushes the card down just enough instead of overlapping it,
   and the toggles in the bottom corner can never sit on top of the card. When everything is
   taller than the screen, the page scrolls. */
div:has(> main):is(:has(form[aria-label="Login form"]), :has(a[href*="/oauth/"]):not(:has(form))) {
  --logo-h: clamp(72px, 12vh, 132px);
  --stack-gap: clamp(20px, 4.5vh, 48px);
  --page-pad-y: clamp(20px, 4vh, 48px);
  isolation: isolate;
  overflow-x: clip;
  padding: var(--page-pad-y) 16px;
  /* LibreChat sizes this page with min-h-screen (100vh). On iPhone, 100vh is the height with
     Safari's toolbar hidden, so with the toolbar showing the page ends up taller than the
     screen and can be dragged up and down. 100svh is the visible height with the toolbar
     showing: the page fits exactly and only scrolls when the content truly needs it. */
  min-height: 100vh;
  min-height: 100svh;
  /* Backdrop width: the full screen width, but never so wide that the skyline (the lower
     46% of the image) climbs past about half the screen height on a short or ultrawide
     screen, and at least 900px so a phone shows the hall and clock tower at a readable size
     rather than a thin strip. Where it is narrower than the screen, the sky colour and
     ground line carry on to the edges. */
  --backdrop-w: max(900px, min(100%, 192vh));
}

div:has(> main):is(:has(form[aria-label="Login form"]), :has(a[href*="/oauth/"]):not(:has(form))) > div:has(img[src="assets/logo.svg"]) {
  order: 1;
  flex: 1 1 0;
  justify-content: flex-start;
}

div:has(> main):is(:has(form[aria-label="Login form"]), :has(a[href*="/oauth/"]):not(:has(form))) > div.mx-auto {
  order: 2;
  flex: 0 0 auto;
  margin-bottom: 12px;
}

div:has(> main):is(:has(form[aria-label="Login form"]), :has(a[href*="/oauth/"]):not(:has(form))) > main {
  order: 3;
  flex: 0 0 auto;
}

/* The theme / contrast toggles become the growing bottom block, pinned to its bottom-left.
   In LibreChat's markup they come before the card, so 'order' moves them to the end. */
div:has(> main):is(:has(form[aria-label="Login form"]), :has(a[href*="/oauth/"]):not(:has(form))) > div.absolute.bottom-0 {
  order: 4;
  position: static;
  flex: 1 1 0;
  display: flex;
  align-items: flex-end;
  margin: 0 0 calc(16px - var(--page-pad-y));
  /* Mirrors the logo block's gap below it (the toggles sit 16px from the bottom edge rather
     than inside the page padding), so the two grow blocks match and the card centres. */
  padding-top: calc(var(--stack-gap) + var(--page-pad-y) - 16px);
}

@media (max-height: 760px) {
  div:has(> main):is(:has(form[aria-label="Login form"]), :has(a[href*="/oauth/"]):not(:has(form))) {
    --logo-h: clamp(56px, 10vh, 84px);
    --stack-gap: clamp(16px, 3vh, 28px);
    --page-pad-y: clamp(16px, 3vh, 28px);
  }
}

@media (max-height: 620px) {
  div:has(> main):is(:has(form[aria-label="Login form"]), :has(a[href*="/oauth/"]):not(:has(form))) {
    --logo-h: 52px;
    --stack-gap: 12px;
  }
}

/* LibreChat serves assets/logo.svg with a two-day browser cache, so a browser that saw the
   old logo keeps it. Swapping the image through a versioned URL here takes effect on the
   next page load everywhere the logo appears. Bump LOGO_VERSION after changing the logo. */
img[src="assets/logo.svg"] {
  content: url('icons/logo-light.png?v=3');
}

html.dark img[src="assets/logo.svg"] {
  content: url('icons/logo-dark.png?v=3');
}

/* Logo with a soft halo, then the tagline, stacked above the card. */
div:has(> main):is(:has(form[aria-label="Login form"]), :has(a[href*="/oauth/"]):not(:has(form))) div:has(> img[src="assets/logo.svg"]) {
  display: flex;
  flex-direction: column;
  align-items: center;
  height: auto;
  margin: 0 0 var(--stack-gap);
}

div:has(> main):is(:has(form[aria-label="Login form"]), :has(a[href*="/oauth/"]):not(:has(form))) div:has(> img[src="assets/logo.svg"]) img {
  height: var(--logo-h);
  width: auto;
  max-width: 88vw;
  object-fit: contain;
}

div:has(> main):is(:has(form[aria-label="Login form"]), :has(a[href*="/oauth/"]):not(:has(form))) div:has(> img[src="assets/logo.svg"])::after {
  content: 'The nationally leading business school committed to incubating innovative entrepreneurship, and social responsibility for sustainable development';
  display: block;
  width: min(620px, 100%);
  margin-top: clamp(6px, 1.2vh, 14px);
  font-size: clamp(0.72rem, 1.05vw, 0.875rem);
  line-height: 1.5;
  letter-spacing: 0.01em;
  text-align: center;
  text-wrap: balance;
}

html:lang(th) div:has(> main):is(:has(form[aria-label="Login form"]), :has(a[href*="/oauth/"]):not(:has(form))) div:has(> img[src="assets/logo.svg"])::after {
  content: 'สถาบันการศึกษาด้านบริหารธุรกิจชั้นนำของประเทศ ที่มุ่งบ่มเพาะความเป็นผู้ประกอบการเชิงนวัตกรรมและจิตสำนึกต่อสังคม เพื่อการพัฒนาที่ยั่งยืน';
}

@media (max-height: 620px) {
  div:has(> main):is(:has(form[aria-label="Login form"]), :has(a[href*="/oauth/"]):not(:has(form))) div:has(> img[src="assets/logo.svg"])::after {
    font-size: 0.7rem;
    line-height: 1.4;
  }
}

/* The footer (privacy / terms links) floats at the bottom rather than joining the stack. */
div:has(> main):is(:has(form[aria-label="Login form"]), :has(a[href*="/oauth/"]):not(:has(form))) > [role='contentinfo'] {
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
}

/* Card proportions. LibreChat's card is a fixed 370px with uneven spacing (16px top and
   bottom padding, a 40px gap under the title, 48px of stacked margins under "OR"). One
   rhythm here, tightened further on short screens so the card with SSO buttons still
   fits without scrolling down to 560px of height. */
div:has(> main):is(:has(form[aria-label="Login form"]), :has(a[href*="/oauth/"]):not(:has(form))) > main > div {
  --card-pad-y: clamp(20px, 3vh, 28px);
  --card-pad-x: clamp(18px, 5vw, 28px);
  --card-gap: clamp(14px, 2vh, 20px);
  --field-gap: 14px;
  --button-h: 42px;
  width: min(370px, 100%);
  padding: var(--card-pad-y) var(--card-pad-x);
}

div:has(> main):is(:has(form[aria-label="Login form"]), :has(a[href*="/oauth/"]):not(:has(form))) > main > div > h1 {
  margin-bottom: 0;
}

div:has(> main):is(:has(form[aria-label="Login form"]), :has(a[href*="/oauth/"]):not(:has(form))) > main > div > form {
  margin-top: var(--card-gap);
}

div:has(> main):is(:has(form[aria-label="Login form"]), :has(a[href*="/oauth/"]):not(:has(form))) > main > div > form > div:first-child {
  margin-bottom: var(--field-gap);
}

div:has(> main):is(:has(form[aria-label="Login form"]), :has(a[href*="/oauth/"]):not(:has(form))) > main > div > form > div:has(> [data-testid='login-button']) {
  margin-top: var(--card-gap);
}

div:has(> main):is(:has(form[aria-label="Login form"]), :has(a[href*="/oauth/"]):not(:has(form))) [data-testid="login-button"] {
  height: var(--button-h);
}

div:has(> main):is(:has(form[aria-label="Login form"]), :has(a[href*="/oauth/"]):not(:has(form))) > main > div .border-t:has(> .absolute) {
  margin-top: var(--card-gap);
}

div:has(> main):is(:has(form[aria-label="Login form"]), :has(a[href*="/oauth/"]):not(:has(form))) > main > div .border-t:has(> .absolute) + div {
  margin-top: var(--card-gap);
}

div:has(> main):is(:has(form[aria-label="Login form"]), :has(a[href*="/oauth/"]):not(:has(form))) > main > div .border-t:has(> .absolute) + div + div,
div:has(> main):is(:has(form[aria-label="Login form"]), :has(a[href*="/oauth/"]):not(:has(form))) > main > div .border-t:has(> .absolute) + div + div > div:first-child {
  margin-top: 0;
}

/* SSO-only login (ALLOW_EMAIL_LOGIN=false): the buttons follow the title directly. */
div:has(> main):is(:has(form[aria-label="Login form"]), :has(a[href*="/oauth/"]):not(:has(form))) > main > div:not(:has(.border-t > .absolute)) > h1 ~ div.mt-2:has(a[href*='/oauth/']) {
  margin-top: var(--card-gap);
}

div:has(> main):is(:has(form[aria-label="Login form"]), :has(a[href*="/oauth/"]):not(:has(form))) > main > div:not(:has(.border-t > .absolute)) > h1 ~ div.mt-2:has(a[href*='/oauth/']) > div:first-child {
  margin-top: 0;
}

/* With no email form, the SSO button is the only way in, so it takes the primary look. */
div:has(> main):is(:has(form[aria-label="Login form"]), :has(a[href*="/oauth/"]):not(:has(form))) > main > div:not(:has(form)) a[href*='/oauth/'] {
  justify-content: center;
  min-height: var(--button-h);
  border: 1px solid var(--button-border);
  color: var(--button-fg);
  font-weight: 500;
  background: var(--button-bg);
  box-shadow: var(--button-shadow);
  transition: transform 0.2s ease, background-color 0.2s ease, box-shadow 0.2s ease;
}

div:has(> main):is(:has(form[aria-label="Login form"]), :has(a[href*="/oauth/"]):not(:has(form))) > main > div:not(:has(form)) a[href*='/oauth/']:hover {
  background: var(--button-bg-hover);
  border-color: var(--button-border-hover);
  box-shadow: var(--button-shadow-hover);
}

@media (prefers-reduced-motion: reduce) {
  div:has(> main):is(:has(form[aria-label="Login form"]), :has(a[href*="/oauth/"]):not(:has(form))) > main > div:not(:has(form)) a[href*='/oauth/'],
  div:has(> main):is(:has(form[aria-label="Login form"]), :has(a[href*="/oauth/"]):not(:has(form))) > main > div:not(:has(form)) a[href*='/oauth/']:hover {
    transition: none;
    transform: none;
  }
}


/* Phones (portrait): a narrower, lighter card with room around it, so the logo, tagline
   and card read as three calm blocks rather than one crowded column. */
@media (max-width: 480px) {
  div:has(> main):is(:has(form[aria-label="Login form"]), :has(a[href*="/oauth/"]):not(:has(form))) {
    --logo-h: clamp(60px, 9vh, 88px);
    --stack-gap: clamp(22px, 4.5vh, 40px);
    padding-left: 24px;
    padding-right: 24px;
  }

  div:has(> main):is(:has(form[aria-label="Login form"]), :has(a[href*="/oauth/"]):not(:has(form))) div:has(> img[src="assets/logo.svg"])::after {
    width: min(320px, 100%);
    font-size: 0.75rem;
  }

  div:has(> main):is(:has(form[aria-label="Login form"]), :has(a[href*="/oauth/"]):not(:has(form))) > main > div {
    --card-pad-y: 20px;
    --card-pad-x: 20px;
    --card-gap: 14px;
    --field-gap: 12px;
    --button-h: 42px;
    width: min(340px, 100%);
    border-radius: 18px;
  }

  div:has(> main):is(:has(form[aria-label="Login form"]), :has(a[href*="/oauth/"]):not(:has(form))) > main > div > h1::after {
    line-height: 1.9rem;
  }

  div:has(> main):is(:has(form[aria-label="Login form"]), :has(a[href*="/oauth/"]):not(:has(form))) form .webkit-dark-styles,
  div:has(> main):is(:has(form[aria-label="Login form"]), :has(a[href*="/oauth/"]):not(:has(form))) form .webkit-dark-styles:focus {
    padding-top: 1.3rem;
    padding-bottom: 0.3rem;
  }
}

/* Short screens (including short phones): tighter card spacing. */
@media (max-height: 700px) {
  div:has(> main):is(:has(form[aria-label="Login form"]), :has(a[href*="/oauth/"]):not(:has(form))) > main > div {
    --card-pad-y: 16px;
    --card-pad-x: 22px;
    --card-gap: 12px;
    --field-gap: 10px;
    --button-h: 40px;
  }

  div:has(> main):is(:has(form[aria-label="Login form"]), :has(a[href*="/oauth/"]):not(:has(form))) form .webkit-dark-styles,
  div:has(> main):is(:has(form[aria-label="Login form"]), :has(a[href*="/oauth/"]):not(:has(form))) form .webkit-dark-styles:focus {
    padding-top: 1.3rem;
    padding-bottom: 0.3rem;
  }
}

/* Landscape phones and very short windows: drop the tagline, keep the logo small. */
@media (max-height: 520px) {
  div:has(> main):is(:has(form[aria-label="Login form"]), :has(a[href*="/oauth/"]):not(:has(form))) {
    --logo-h: 40px;
    --stack-gap: 16px;
  }

  div:has(> main):is(:has(form[aria-label="Login form"]), :has(a[href*="/oauth/"]):not(:has(form))) div:has(> img[src="assets/logo.svg"])::after {
    display: none;
  }
}

/* Custom heading. LibreChat has no setting for the login title, so the original text is
   collapsed and replaced visually (screen readers still announce the original). */
div:has(> main):is(:has(form[aria-label="Login form"]), :has(a[href*="/oauth/"]):not(:has(form))) > main > div > h1 {
  font-size: 0;
  line-height: 0;
}

/* The heading sizes to the card: both titles set about 13.9 times their font size wide in
   Montserrat, so 7% of the card's inner width keeps them on one line at any card width. */
div:has(> main):is(:has(form[aria-label="Login form"]), :has(a[href*="/oauth/"]):not(:has(form))) > main > div {
  container-type: inline-size;
}

div:has(> main):is(:has(form[aria-label="Login form"]), :has(a[href*="/oauth/"]):not(:has(form))) > main > div > h1::after {
  content: 'Welcome to CMUBS AI Hub';
  display: block;
  font-size: min(1.5rem, 7cqi);
  line-height: 2.25rem;
  letter-spacing: -0.01em;
  white-space: nowrap;
}

html:lang(th) div:has(> main):is(:has(form[aria-label="Login form"]), :has(a[href*="/oauth/"]):not(:has(form))) > main > div > h1::after {
  content: 'ยินดีต้อนรับสู่ CMUBS AI Hub';
}

html:lang(en) div:has(> main):is(:has(form[aria-label="Login form"]), :has(a[href*="/oauth/"]):not(:has(form))) label[for='email'] {
  font-size: 0;
}

html:lang(en) div:has(> main):is(:has(form[aria-label="Login form"]), :has(a[href*="/oauth/"]):not(:has(form))) label[for='email']::after {
  content: 'Email';
  font-size: 0.875rem;
  line-height: 1.25rem;
}

html:lang(th) div:has(> main):is(:has(form[aria-label="Login form"]), :has(a[href*="/oauth/"]):not(:has(form))) label[for='email'] {
  font-size: 0;
}

html:lang(th) div:has(> main):is(:has(form[aria-label="Login form"]), :has(a[href*="/oauth/"]):not(:has(form))) label[for='email']::after {
  content: 'อีเมล';
  font-size: 0.875rem;
  line-height: 1.25rem;
}

/* Glass fields. LibreChat paints them with a hard-coded inset colour (.webkit-dark-styles
   in client/src/style.css) and gives the floating label a solid background, both of which
   read as opaque boxes on the glass card. Here the fill is translucent and the floated
   label rests inside the field's top edge rather than on its border, so it needs no
   background. Autofill keeps an opaque tint because Chrome paints its own over it. */
div:has(> main):is(:has(form[aria-label="Login form"]), :has(a[href*="/oauth/"]):not(:has(form))) form .webkit-dark-styles,
div:has(> main):is(:has(form[aria-label="Login form"]), :has(a[href*="/oauth/"]):not(:has(form))) form .webkit-dark-styles:focus {
  background: var(--field-bg);
  background-clip: padding-box;
  -webkit-box-shadow: none;
  box-shadow: none;
  -webkit-text-fill-color: var(--field-text);
  padding-top: 1.45rem;
  padding-bottom: 0.4rem;
}

/* iOS Safari zooms the page in when a field under 16px gets focus, and leaves it zoomed.
   16px on touch devices stops that without disabling pinch-zoom for people who need it. */
@media (hover: none) and (pointer: coarse) {
  div:has(> main):is(:has(form[aria-label="Login form"]), :has(a[href*="/oauth/"]):not(:has(form))) form .webkit-dark-styles,
  div:has(> main):is(:has(form[aria-label="Login form"]), :has(a[href*="/oauth/"]):not(:has(form))) form .webkit-dark-styles:focus {
    font-size: 16px;
  }
}

div:has(> main):is(:has(form[aria-label="Login form"]), :has(a[href*="/oauth/"]):not(:has(form))) form .webkit-dark-styles:-webkit-autofill,
div:has(> main):is(:has(form[aria-label="Login form"]), :has(a[href*="/oauth/"]):not(:has(form))) form .webkit-dark-styles:-webkit-autofill:hover,
div:has(> main):is(:has(form[aria-label="Login form"]), :has(a[href*="/oauth/"]):not(:has(form))) form .webkit-dark-styles:-webkit-autofill:focus {
  -webkit-box-shadow: 0 0 0 50vh var(--field-autofill) inset;
  -webkit-text-fill-color: var(--field-text);
}

div:has(> main):is(:has(form[aria-label="Login form"]), :has(a[href*="/oauth/"]):not(:has(form))) form label {
  background: transparent;
}

/* [for][class] lifts specificity above Tailwind's peer-focus:top-1.5 / -translate-y-4. */
div:has(> main):is(:has(form[aria-label="Login form"]), :has(a[href*="/oauth/"]):not(:has(form))) form input:is(:focus, :not(:placeholder-shown)) ~ label[for][class] {
  top: 0.3rem;
  --tw-translate-y: 0px;
}

div:has(> main):is(:has(form[aria-label="Login form"]), :has(a[href*="/oauth/"]):not(:has(form))) form input:is(:focus, :not(:placeholder-shown)) ~ label[for][class],
div:has(> main):is(:has(form[aria-label="Login form"]), :has(a[href*="/oauth/"]):not(:has(form))) form input:is(:focus, :not(:placeholder-shown)) ~ label[for][class]::after {
  line-height: 1rem;
}

/* "OR" divider above the SSO buttons: LibreChat draws a full border and masks it with a
   solid label background, which shows as a dark chip on the glass. Instead the line fades
   in from the edges and leaves a gap for the label. */
div:has(> main):is(:has(form[aria-label="Login form"]), :has(a[href*="/oauth/"]):not(:has(form))) > main > div .border-t:has(> .absolute) {
  border: 0;
  height: 1px;
  background: linear-gradient(90deg, transparent 0%, rgb(var(--border-medium)) 22%, rgb(var(--border-medium)) 40%, transparent 40%, transparent 60%, rgb(var(--border-medium)) 60%, rgb(var(--border-medium)) 78%, transparent 100%);
}

div:has(> main):is(:has(form[aria-label="Login form"]), :has(a[href*="/oauth/"]):not(:has(form))) > main > div .border-t:has(> .absolute) > .absolute {
  background: transparent;
  color: rgb(var(--text-secondary));
  letter-spacing: 0.08em;
}

/* SSO buttons (Continue with OpenID, etc.) match the glass fields, at the same slim height
   as the Continue button: min-height sets it and the label centres vertically. */
div:has(> main):is(:has(form[aria-label="Login form"]), :has(a[href*="/oauth/"]):not(:has(form))) > main > div a[href*='/oauth/'] {
  min-height: var(--button-h);
  padding-top: 0;
  padding-bottom: 0;
  background: var(--field-bg);
  border-color: rgb(var(--border-light));
  transition: background-color 0.2s ease, border-color 0.2s ease;
}

div:has(> main):is(:has(form[aria-label="Login form"]), :has(a[href*="/oauth/"]):not(:has(form))) > main > div a[href*='/oauth/']:hover {
  background: var(--field-bg-hover);
  border-color: rgb(var(--border-medium));
}

/* The CMU wordmark in place of LibreChat's default OpenID glyph on the SSO button (the
   sign-in is a CMU IT account): white letters on the dark theme's navy button, deep teal on
   the light theme's white one. The glyph's path is hidden and the wordmark is painted as the
   icon's background, sized to its 242:72 proportions, so the button's layout is untouched.
   An OPENID_IMAGE_URL set in .env renders an <img> instead and is left as it is. */
div:has(> main):is(:has(form[aria-label="Login form"]), :has(a[href*="/oauth/"]):not(:has(form))) svg#openid {
  --sso-icon-h: 0.875rem;
  flex: none;
  width: calc(var(--sso-icon-h) * 242 / 72);
  height: var(--sso-icon-h);
  background: url('icons/sso-light.png?v=3') center / contain no-repeat;
}

html.dark div:has(> main):is(:has(form[aria-label="Login form"]), :has(a[href*="/oauth/"]):not(:has(form))) svg#openid {
  background-image: url('icons/sso-dark.png?v=3');
}

div:has(> main):is(:has(form[aria-label="Login form"]), :has(a[href*="/oauth/"]):not(:has(form))) svg#openid > path {
  display: none;
}

/* The wordmark is wider than the glyph it replaces, so the button trims its side padding and
   icon gap, and the label sits a size down with slightly tighter tracking, to keep "Continue
   with CMU IT Account" on one line down to 360px screens; below that it wraps rather than
   overflowing. */
div:has(> main):is(:has(form[aria-label="Login form"]), :has(a[href*="/oauth/"]):not(:has(form))) > main > div a[href*='/oauth/']:has(> svg#openid) {
  padding-left: 1rem;
  padding-right: 1rem;
}

div:has(> main):is(:has(form[aria-label="Login form"]), :has(a[href*="/oauth/"]):not(:has(form))) > main > div a[href*='/oauth/']:has(> svg#openid) > svg#openid + * {
  margin-left: 0.625rem;
  font-size: 0.84375rem;
  font-weight: 600;
  letter-spacing: -0.01em;
  white-space: nowrap;
}

/* Keyboard focus: a ring set 2px off the button, in the theme's text colour (deep teal on
   light, white on dark) rather than the browser's default black. */
div:has(> main):is(:has(form[aria-label="Login form"]), :has(a[href*="/oauth/"]):not(:has(form))) > main > div a[href*='/oauth/']:focus-visible,
div:has(> main):is(:has(form[aria-label="Login form"]), :has(a[href*="/oauth/"]):not(:has(form))) [data-testid="login-button"]:focus-visible {
  outline: 2px solid var(--focus-ring);
  outline-offset: 2px;
}

@media (max-width: 379px) {
  div:has(> main):is(:has(form[aria-label="Login form"]), :has(a[href*="/oauth/"]):not(:has(form))) {
    padding-left: 16px;
    padding-right: 16px;
  }

  div:has(> main):is(:has(form[aria-label="Login form"]), :has(a[href*="/oauth/"]):not(:has(form))) svg#openid {
    --sso-icon-h: 0.75rem;
  }

  div:has(> main):is(:has(form[aria-label="Login form"]), :has(a[href*="/oauth/"]):not(:has(form))) > main > div a[href*='/oauth/']:has(> svg#openid) {
    padding-left: 0.75rem;
    padding-right: 0.75rem;
  }

  div:has(> main):is(:has(form[aria-label="Login form"]), :has(a[href*="/oauth/"]):not(:has(form))) > main > div a[href*='/oauth/']:has(> svg#openid) > svg#openid + * {
    margin-left: 0.5rem;
    font-size: 0.8125rem;
  }
}

@media (max-width: 359px) {
  div:has(> main):is(:has(form[aria-label="Login form"]), :has(a[href*="/oauth/"]):not(:has(form))) > main > div a[href*='/oauth/']:has(> svg#openid) > svg#openid + * {
    white-space: normal;
    text-align: left;
  }
}

/* Surfaces step up in lightness, page -> card -> buttons and fields, so each layer reads
   at a glance in either theme; the card is a flat panel with a hairline edge, blurred just
   enough to quiet the line art behind it. */
div:has(> main):is(:has(form[aria-label="Login form"]), :has(a[href*="/oauth/"]):not(:has(form))) > main > div {
  border: 1px solid var(--card-border);
  border-radius: 24px;
  background: var(--card-bg);
  box-shadow: var(--card-shadow);
  -webkit-backdrop-filter: blur(18px) saturate(140%);
  backdrop-filter: blur(18px) saturate(140%);
}

div:has(> main):is(:has(form[aria-label="Login form"]), :has(a[href*="/oauth/"]):not(:has(form))) [data-testid="login-button"] {
  border: 1px solid var(--button-border);
  color: var(--button-fg);
  background: var(--button-bg);
  box-shadow: var(--button-shadow);
  transition: transform 0.2s ease, background-color 0.2s ease, box-shadow 0.2s ease;
}

div:has(> main):is(:has(form[aria-label="Login form"]), :has(a[href*="/oauth/"]):not(:has(form))) [data-testid="login-button"]:hover {
  background: var(--button-bg-hover);
  border-color: var(--button-border-hover);
  box-shadow: var(--button-shadow-hover);
}

/* ============================ Dark: navy skyline ============================ */

html.dark div:has(> main):is(:has(form[aria-label="Login form"]), :has(a[href*="/oauth/"]):not(:has(form))) {
  /* Dark theme tokens (client/src/style.css .dark) keep the form legible on navy. */
  --text-primary: var(--gray-100);
  --text-secondary: var(--gray-300);
  --text-secondary-alt: var(--gray-400);
  --text-tertiary: var(--gray-400);
  --surface-primary: var(--gray-900);
  --border-light: 52 72 102;
  --border-medium: 80 104 138;
  --accent-primary: 94 196 216;
  --accent-primary-hover: 140 216 230;
  color-scheme: dark;
  background: linear-gradient(rgba(218, 227, 244, 0.9), rgba(218, 227, 244, 0.9)) center bottom / 100% 1px no-repeat,
    url('backdrops/dark.jpg?v=1') center bottom / var(--backdrop-w) auto no-repeat,
    #1a3b5e;
}

html.dark div:has(> main):is(:has(form[aria-label="Login form"]), :has(a[href*="/oauth/"]):not(:has(form))) div:has(> img[src="assets/logo.svg"])::after {
  /* Same colour as the "Chiang Mai University Business School" line in logo-dark.png. */
  color: #e4e2ec;
  text-shadow: 0 1px 12px rgba(6, 18, 34, 0.8);
}

html.dark div:has(> main):is(:has(form[aria-label="Login form"]), :has(a[href*="/oauth/"]):not(:has(form))) div:has(> img[src="assets/logo.svg"]) img {
  filter: drop-shadow(0 0 24px rgba(255, 255, 255, 0.12)) drop-shadow(0 10px 24px rgba(6, 18, 34, 0.6));
}

/* Dark: page #1a3b5e (the backdrop's sky) -> card one step lighter -> buttons and fields
   another step lighter, with white text. */
html.dark div:has(> main):is(:has(form[aria-label="Login form"]), :has(a[href*="/oauth/"]):not(:has(form))) {
  --card-bg: rgba(34, 71, 109, 0.9);
  --card-border: rgba(255, 255, 255, 0.12);
  --card-shadow: 0 24px 60px -28px rgba(6, 18, 34, 0.6);
  --field-bg: rgba(255, 255, 255, 0.08);
  --field-bg-hover: rgba(255, 255, 255, 0.12);
  --field-autofill: #2c5279;
  --field-text: #ffffff;
  --button-bg: #2f5781;
  --button-bg-hover: #3a6390;
  --button-fg: #ffffff;
  --button-border: rgba(255, 255, 255, 0.08);
  --button-border-hover: rgba(255, 255, 255, 0.16);
  --button-shadow: none;
  --button-shadow-hover: none;
  --focus-ring: #ffffff;
}

/* ========================== Light: teal skyline ========================== */

html:not(.dark) div:has(> main):is(:has(form[aria-label="Login form"]), :has(a[href*="/oauth/"]):not(:has(form))) {
  /* Light: page #e8e8e8 (the backdrop's sky) -> card a step lighter -> buttons and fields
     white. Text, hairlines and shadows take a deep teal drawn from the backdrop's line art
     (#34899d), so the card reads as part of the same drawing. */
  --text-primary: 20 60 70;
  --card-bg: rgba(247, 247, 247, 0.92);
  --card-border: rgba(20, 94, 110, 0.14);
  --card-shadow: 0 24px 60px -30px rgba(20, 94, 110, 0.28);
  --field-bg: #ffffff;
  --field-bg-hover: #ffffff;
  --field-autofill: #ffffff;
  --field-text: rgb(var(--text-primary));
  --button-bg: #ffffff;
  --button-bg-hover: #f5f9fa;
  --button-fg: #145e6e;
  --button-border: rgba(20, 94, 110, 0.22);
  --button-border-hover: rgba(20, 94, 110, 0.4);
  --button-shadow: 0 1px 2px rgba(20, 94, 110, 0.08);
  --button-shadow-hover: 0 2px 6px rgba(20, 94, 110, 0.14);
  --focus-ring: #145e6e;
  --accent-primary: 20 94 110;
  --accent-primary-hover: 14 72 85;
  color-scheme: light;
  background: linear-gradient(#34899d, #34899d) center bottom / 100% 1px no-repeat,
    url('backdrops/light.jpg?v=1') center bottom / var(--backdrop-w) auto no-repeat,
    #e8e8e8;
}

html:not(.dark) div:has(> main):is(:has(form[aria-label="Login form"]), :has(a[href*="/oauth/"]):not(:has(form))) div:has(> img[src="assets/logo.svg"])::after {
  /* Same colour as the "Chiang Mai University Business School" line in the logo. */
  color: #404042;
  text-shadow: 0 1px 10px rgba(255, 255, 255, 0.7);
}

html:not(.dark) div:has(> main):is(:has(form[aria-label="Login form"]), :has(a[href*="/oauth/"]):not(:has(form))) div:has(> img[src="assets/logo.svg"]) img {
  filter: drop-shadow(0 10px 22px rgba(20, 94, 110, 0.14));
}

@media (prefers-reduced-motion: reduce) {
  div:has(> main):is(:has(form[aria-label="Login form"]), :has(a[href*="/oauth/"]):not(:has(form))) [data-testid="login-button"],
  div:has(> main):is(:has(form[aria-label="Login form"]), :has(a[href*="/oauth/"]):not(:has(form))) [data-testid="login-button"]:hover {
    transition: none;
    transform: none;
  }
}

div:has(> div.size-10):not(:has(.lucide-hat-glasses)) > p.split-parent::before,
div:has(> div.size-10):not(:has(.lucide-hat-glasses)) > p.split-parent::after {
  animation: greeting-in 0.6s ease-out both;
}

html div:has(> div.size-10):not(:has(.lucide-hat-glasses)) > p.split-parent::before {
  content: "How can I help you today, ";
}

html div:has(> div.size-10):not(:has(.lucide-hat-glasses)) > p.split-parent::after {
  content: "?";
}

html:lang(th) div:has(> div.size-10):not(:has(.lucide-hat-glasses)) > p.split-parent::before {
  content: "วันนี้ให้ช่วยอะไรดี ";
}

html:lang(th) div:has(> div.size-10):not(:has(.lucide-hat-glasses)) > p.split-parent::after {
  content: "";
}

html[data-greeting='1'] div:has(> div.size-10):not(:has(.lucide-hat-glasses)) > p.split-parent::before {
  content: "Good to see you, ";
}

html[data-greeting='1'] div:has(> div.size-10):not(:has(.lucide-hat-glasses)) > p.split-parent::after {
  content: "";
}

html[data-greeting='1']:lang(th) div:has(> div.size-10):not(:has(.lucide-hat-glasses)) > p.split-parent::before {
  content: "ยินดีที่ได้พบคุณ ";
}

html[data-greeting='1']:lang(th) div:has(> div.size-10):not(:has(.lucide-hat-glasses)) > p.split-parent::after {
  content: "";
}

html[data-greeting='2'] div:has(> div.size-10):not(:has(.lucide-hat-glasses)) > p.split-parent::before {
  content: "What shall we work on, ";
}

html[data-greeting='2'] div:has(> div.size-10):not(:has(.lucide-hat-glasses)) > p.split-parent::after {
  content: "?";
}

html[data-greeting='2']:lang(th) div:has(> div.size-10):not(:has(.lucide-hat-glasses)) > p.split-parent::before {
  content: "วันนี้จะทำอะไรกันดี ";
}

html[data-greeting='2']:lang(th) div:has(> div.size-10):not(:has(.lucide-hat-glasses)) > p.split-parent::after {
  content: "";
}

html[data-greeting='3'] div:has(> div.size-10):not(:has(.lucide-hat-glasses)) > p.split-parent::before {
  content: "Ready to learn something new, ";
}

html[data-greeting='3'] div:has(> div.size-10):not(:has(.lucide-hat-glasses)) > p.split-parent::after {
  content: "?";
}

html[data-greeting='3']:lang(th) div:has(> div.size-10):not(:has(.lucide-hat-glasses)) > p.split-parent::before {
  content: "พร้อมเรียนรู้สิ่งใหม่หรือยัง ";
}

html[data-greeting='3']:lang(th) div:has(> div.size-10):not(:has(.lucide-hat-glasses)) > p.split-parent::after {
  content: "";
}

html[data-greeting='4'] div:has(> div.size-10):not(:has(.lucide-hat-glasses)) > p.split-parent::before {
  content: "What’s on your mind, ";
}

html[data-greeting='4'] div:has(> div.size-10):not(:has(.lucide-hat-glasses)) > p.split-parent::after {
  content: "?";
}

html[data-greeting='4']:lang(th) div:has(> div.size-10):not(:has(.lucide-hat-glasses)) > p.split-parent::before {
  content: "มีอะไรอยากให้ช่วยไหม ";
}

html[data-greeting='4']:lang(th) div:has(> div.size-10):not(:has(.lucide-hat-glasses)) > p.split-parent::after {
  content: "";
}

html[data-greeting='5'] div:has(> div.size-10):not(:has(.lucide-hat-glasses)) > p.split-parent::before {
  content: "Let’s turn ideas into impact, ";
}

html[data-greeting='5'] div:has(> div.size-10):not(:has(.lucide-hat-glasses)) > p.split-parent::after {
  content: "";
}

html[data-greeting='5']:lang(th) div:has(> div.size-10):not(:has(.lucide-hat-glasses)) > p.split-parent::before {
  content: "มาเปลี่ยนไอเดียให้เป็นผลลัพธ์กัน ";
}

html[data-greeting='5']:lang(th) div:has(> div.size-10):not(:has(.lucide-hat-glasses)) > p.split-parent::after {
  content: "";
}

html[data-greeting='6'] div:has(> div.size-10):not(:has(.lucide-hat-glasses)) > p.split-parent::before {
  content: "Where shall we start today, ";
}

html[data-greeting='6'] div:has(> div.size-10):not(:has(.lucide-hat-glasses)) > p.split-parent::after {
  content: "?";
}

html[data-greeting='6']:lang(th) div:has(> div.size-10):not(:has(.lucide-hat-glasses)) > p.split-parent::before {
  content: "วันนี้เริ่มจากตรงไหนดี ";
}

html[data-greeting='6']:lang(th) div:has(> div.size-10):not(:has(.lucide-hat-glasses)) > p.split-parent::after {
  content: "";
}

html[data-greeting='7'] div:has(> div.size-10):not(:has(.lucide-hat-glasses)) > p.split-parent::before {
  content: "Let’s build something great, ";
}

html[data-greeting='7'] div:has(> div.size-10):not(:has(.lucide-hat-glasses)) > p.split-parent::after {
  content: "";
}

html[data-greeting='7']:lang(th) div:has(> div.size-10):not(:has(.lucide-hat-glasses)) > p.split-parent::before {
  content: "มาสร้างสิ่งดีๆ ด้วยกัน ";
}

html[data-greeting='7']:lang(th) div:has(> div.size-10):not(:has(.lucide-hat-glasses)) > p.split-parent::after {
  content: "";
}

@keyframes greeting-in {
  from { opacity: 0; }
  to { opacity: 1; }
}

@media (prefers-reduced-motion: reduce) {
  div:has(> div.size-10):not(:has(.lucide-hat-glasses)) > p.split-parent::before,
  div:has(> div.size-10):not(:has(.lucide-hat-glasses)) > p.split-parent::after {
    animation: none;
  }
}
