@font-face {
  font-family: "MarkOT";
  src: url("../fonts/MarkOT.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "MarkOT";
  src: url("../fonts/MarkOT-Bold.woff2") format("woff2");
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "MarkOT";
  src: url("../fonts/MarkOT-Italic.woff2") format("woff2");
  font-weight: 400;
  font-style: italic;
  font-display: swap;
}

:root {
  --bs-font-sans-serif: "MarkOT", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  --bs-primary: #169eb0;
  --bs-primary-rgb: 22, 158, 176;
  --bs-success: #169eb0;
  --bs-success-rgb: 22, 158, 176;
  --bs-link-color: #083a59;
  --bs-link-color-rgb: 8, 58, 89;
  --bs-link-hover-color: #169eb0;
  --bs-body-color: #45505d;
  --eodc-focus: #169eb0;
  /*
   * Served straight from the eodc.eu WordPress uploads - the same hero the
   * eodc.eu landing page uses. It is close to square (2554x2560), so `cover`
   * on a wide viewport crops it top and bottom and shows the middle band;
   * that is the pink-to-teal transition, which is the intended framing.
   */
  --eodc-hero: url("https://eodc.eu/wp-content/uploads/2024/12/usgs-hoS3dzgpHzw-unsplash_ty-scaled.jpg");
  --eodc-logo: url("https://eodc.eu/wp-content/uploads/2024/12/eodc_Logo_earth_white_400x400_rgb.png");
  --eodc-cta: #8b6c32;
  /*
   * eodc.eu's CTA hover shifts gold text to white with a light-blue outline.
   * White works on the dark hero but would vanish on the light-mode wash, so
   * light mode shifts to the brand teal instead - same "gold to blue" move,
   * still legible.
   */
  --eodc-cta-hover: #0e7c94;
  --eodc-cta-hover-border: #169eb0;
}

/*
 * Every token this block shares with :root above must be re-declared here.
 * custom.css loads after style.min.css and :root ties [data-bs-theme=dark] on
 * specificity, so :root beats Bootstrap's own dark values on source order -
 * a token omitted here silently keeps its light value in dark mode. That is
 * what made headings ("Server Options") dark-on-dark: --bs-body-color was
 * only set on :root. --bs-heading-color is `inherit` in Bootstrap, so body
 * color covers headings too.
 */
[data-bs-theme="dark"] {
  --bs-primary: #3cbee0;
  --bs-primary-rgb: 60, 190, 224;
  --bs-success: #3cbee0;
  --bs-success-rgb: 60, 190, 224;
  --bs-link-color: #a0d7e7;
  --bs-link-hover-color: #3cbee0;
  --bs-body-color: #f9f9f9;
  --bs-emphasis-color: #ffffff;
  --bs-secondary-color: rgba(249, 249, 249, 0.75);
  --eodc-focus: #3cbee0;
  --eodc-cta: #d9c991;
  --eodc-cta-hover: #ffffff;
  --eodc-cta-hover-border: #40bee0;
}

body {
  font-family: var(--bs-font-sans-serif);
  background: transparent;
}

/*
 * The hero is EODC's own duotone satellite scene, loaded from the eodc.eu
 * WordPress uploads (see --eodc-hero). If eodc.eu is unreachable the image
 * simply does not paint and the gradient below shows on its own.
 *
 * Set on html, not body, and fixed so it paints exactly once relative to the
 * viewport: on body it tiles once body's box is shorter than the scrollable
 * page, which banded the short pages.
 *
 * darkmode.js sets data-bs-theme on documentElement, i.e. <html> itself, so
 * the dark variant has to be html[data-bs-theme="dark"] - a descendant
 * selector such as `[data-bs-theme="dark"] html` can never match the root.
 *
 * Light mode washes the image out to near-white instead of reusing the dark
 * overlay: the default body/control/modal colours are dark-on-light, so a
 * dark hero there leaves stock components (white modals, white inputs)
 * illegible.
 */
html {
  background-image: linear-gradient(180deg, rgba(249, 249, 249, 0.82) 0%, rgba(219, 232, 236, 0.9) 100%),
    var(--eodc-hero);
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
  background-attachment: fixed;
}

/*
 * Deliberately a near-neutral scrim, not the brand blue used before: a blue
 * tint shifts the hero's pink toward purple. Neutral darkening keeps the
 * pink/teal hues true while still holding enough contrast under the off-white
 * body text. Raise the alphas if text over the brighter areas reads weakly.
 */
html[data-bs-theme="dark"] {
  background-image: linear-gradient(180deg, rgba(3, 12, 18, 0.08) 0%, rgba(3, 12, 18, 0.35) 100%),
    var(--eodc-hero);
}

/*
 * With the scrim this light, text over the hero's bright pink and pale teal
 * areas needs its own contrast rather than relying on the backdrop. Applied at
 * body level so it reaches every floating element, then switched off inside
 * components that paint their own solid surface, where it would just blur.
 */
html[data-bs-theme="dark"] body {
  text-shadow: 0 1px 4px rgba(0, 0, 0, 0.8);
}

html[data-bs-theme="dark"] .form-control,
html[data-bs-theme="dark"] .form-select,
html[data-bs-theme="dark"] .select__control,
html[data-bs-theme="dark"] .select__menu,
html[data-bs-theme="dark"] .modal-content,
html[data-bs-theme="dark"] .table,
html[data-bs-theme="dark"] .terminal-container {
  text-shadow: none;
}

/*
 * Fully transparent banner - no fill and no backdrop blur, so the hero runs
 * unbroken behind it. page.html puts Bootstrap's bg-body-tertiary utility
 * directly on the <nav>, and utilities are !important, so overriding it needs
 * !important regardless of source order.
 *
 * Only the brand accents are set here. Bootstrap already derives navbar link,
 * toggler-icon and .btn-outline-contrast colours from the active theme, and
 * those defaults are correct against a transparent bar - the previous explicit
 * white values and the toggler invert() existed only to compensate for the
 * dark fill this rule used to paint, and would now be wrong in light mode.
 */
.navbar {
  background-color: transparent !important;
  --bs-navbar-hover-color: #169eb0;
}

html[data-bs-theme="dark"] .navbar {
  /* Bootstrap's .65 alpha is thin over a vibrant image; lift it for contrast. */
  --bs-navbar-color: rgba(255, 255, 255, 0.9);
  --bs-navbar-hover-color: #bae3fa;
  --bs-navbar-active-color: #ffffff;
  --bs-navbar-brand-color: #ffffff;
  --bs-navbar-brand-hover-color: #bae3fa;
  --bs-navbar-toggler-border-color: rgba(255, 255, 255, 0.3);
}

.navbar .btn-outline-contrast {
  --bs-btn-hover-bg: #169eb0;
  --bs-btn-hover-border-color: #169eb0;
  --bs-btn-hover-color: #ffffff;
}

/*
 * The wordmark is a flat brand-cyan shape on transparency, which is too light
 * to read against the light-mode wash; deepen it there only.
 */
html:not([data-bs-theme="dark"]) .navbar .jpy-logo {
  filter: brightness(0.62) saturate(1.5);
}

/* Core JupyterHub styles these in Jupyter orange, unreachable via --bs-* vars. */
.form-control:focus,
.form-select:focus {
  border-color: var(--eodc-focus);
  outline-color: var(--eodc-focus);
  box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px var(--eodc-focus);
}

#login-main .auth-form-header {
  background: #083a59;
}

/*
 * Centred logo above the sign-in button, as on the eodc.eu landing page.
 * Added as a pseudo-element on .service-login (the OAuth login variant, which
 * exists only on the login page) so it needs no custom login.html and so no
 * new volume mount. Decorative, so having no alt text is correct.
 */
.service-login::before {
  content: "";
  display: block;
  /* 304px is the rendered size on the eodc.eu landing page at full screen. */
  width: min(304px, 60vw);
  aspect-ratio: 1;
  margin: 0 auto 2rem;
  background: var(--eodc-logo) center / contain no-repeat;
}

/*
 * eodc.eu publishes only the white-on-transparent logo, so light mode darkens
 * it rather than pointing at a dark variant that does not exist - white on the
 * light wash would be invisible. :not([data-bs-theme="dark"]) rather than
 * ="light" so it also covers the moment before darkmode.js sets the attribute.
 */
html:not([data-bs-theme="dark"]) .service-login::before {
  filter: brightness(0.18);
}

/*
 * Profile cards sit directly on the hero image: no fill, border or shadow.
 * Text colour comes from the body token above rather than being hardcoded
 * here, so it follows the theme instead of assuming a dark background.
 */
#form fieldset {
  display: flex;
  flex-direction: column;
  gap: 1rem;
}

.profile-select {
  background: transparent !important;
  border: none !important;
  box-shadow: none;
}

.selected-profile {
  background-color: transparent !important;
  border: none !important;
  box-shadow: none !important;
}

/*
 * fancy-profiles draws a divider above the permalink row. !important because
 * its stylesheet is injected at runtime (style-loader) and so lands after
 * this file, winning any equal-specificity contest - and because its dark
 * variant sets border-top-color at higher specificity.
 * Padding is kept: it is the row's spacing, not part of the divider.
 */
.permalink-container {
  border-top: none !important;
}

/*
 * Matches eodc.eu's own CTA buttons (e.g. "Our mission"): transparent fill,
 * thin border, arrow prefix, hover fading only text/border colour with no
 * background fill.
 *
 * #start is the Home page's "Start My Server" (btn btn-lg btn-primary) -
 * a different element from fancy-profiles' .btn-jupyter on the spawn page,
 * styled together here so both CTAs match.
 *
 * The permalink controls ship as `btn btn-link p-0`, i.e. underlined text
 * links with padding stripped by a utility class. The two-class selector
 * outranks both `.btn-link`'s underline and `.p-0`'s !important padding.
 */
.btn-jupyter,
#start,
.permalink-actions .btn-link {
  text-decoration: none;
  --bs-btn-color: var(--eodc-cta) !important;
  --bs-btn-bg: transparent !important;
  --bs-btn-border-color: var(--eodc-cta) !important;
  --bs-btn-hover-color: var(--eodc-cta-hover) !important;
  --bs-btn-hover-bg: transparent !important;
  --bs-btn-hover-border-color: var(--eodc-cta-hover-border) !important;
  --bs-btn-active-color: var(--eodc-cta-hover) !important;
  --bs-btn-active-bg: transparent !important;
  --bs-btn-active-border-color: var(--eodc-cta-hover-border) !important;
  --bs-btn-disabled-color: var(--eodc-cta) !important;
  --bs-btn-disabled-bg: transparent !important;
  --bs-btn-disabled-border-color: var(--eodc-cta) !important;
  width: auto !important;
  align-self: center;
  display: inline-flex !important;
  align-items: center;
  gap: 0.5rem;
  border-width: 1px !important;
  border-radius: 6px !important;
  padding: 0.6rem 1.25rem !important;
  font-size: 1rem !important;
  font-weight: 400 !important;
  letter-spacing: 0.02em;
  box-shadow: none !important;
  transition: border-color 0.2s ease, color 0.2s ease;
}

.btn-jupyter::before,
#start::before,
.permalink-actions .btn-link::before {
  content: "\2192";
  /*
   * The rotation works because the buttons are inline-flex: the pseudo-element
   * becomes a flex item and is therefore blockified. Transforms have no effect
   * on non-replaced inline boxes, which is what ::before would otherwise be.
   */
  transition: transform 0.2s ease;
}

/*
 * fancy-profiles already sets aria-expanded on the disclosure button, so the
 * open state is styleable with no JS and no rebuild of the extension. Only
 * that button carries the attribute, so Copy Permalink's arrow stays put.
 */
.permalink-actions .btn-link[aria-expanded="true"]::before {
  transform: rotate(90deg);
}

@media (prefers-reduced-motion: reduce) {
  .btn-jupyter::before,
  #start::before,
  .permalink-actions .btn-link::before {
    transition: none;
  }
}

/* Buttons inherit the dark-mode text-shadow from body; no separate rule needed. */
