/* Uspark 2026 page-system pass.
 * One shared layer keeps every route in the same visual world while preserving
 * the existing templates, HTMX behavior, and semantic design tokens. */

html { background: var(--paper); }

body {
  min-width: 20rem;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-ui);
  font-size: var(--type-body);
  line-height: var(--leading-body);
}

::selection { background: var(--spark); color: var(--logo-ink); }

:where(h1, h2, h3) {
  color: var(--ink);
  text-wrap: balance;
}

:where(p, li) { text-wrap: pretty; }

/* Labels above headings were doing the heading's job on nearly every family. */
:where(.parent-eyebrow, .eyebrow, .growth-kicker, .workbench-kicker, .class-kicker) {
  display: none !important;
}

/* Shared chrome */
.site-header {
  min-height: 4.5rem;
  padding-inline: var(--content-gutter);
  border-bottom-color: color-mix(in oklch, var(--line) 78%, transparent) !important;
  background: var(--surface) !important;
}

.site-header .logo-mark { min-width: 7rem; }

.site-header__nav a,
.nav-login,
.mb-dashboard,
.nav-signout {
  font-weight: 650;
}

.site-header__nav a[aria-current="page"] {
  color: var(--action);
}

.icon-button,
.u-avatar-nav,
.nav-notify {
  min-width: var(--control-h);
  min-height: var(--control-h);
  border-radius: var(--radius-control) !important;
}

.icon-button > svg {
  width: 1.25rem;
  height: 1.25rem;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.8;
  stroke-linecap: round;
}

.site-search,
.parent-search__row {
  border-radius: var(--radius-control) !important;
  box-shadow: none !important;
}

.site-search:focus-within,
.parent-search__row:focus-within {
  outline: 3px solid var(--focus-outer);
  outline-offset: 2px;
}

:where(button, .nav-signup, .hbtn-primary, .hbtn-secondary, .hbtn-indigo,
  .auth-btn, .u-cta, .class-button, .dbcont-btn, .learner-focus-action) {
  border-radius: var(--radius-control) !important;
  font-weight: 700 !important;
}

:where(input:not([type="checkbox"]):not([type="radio"]), textarea, select) {
  min-height: var(--control-h);
  border-radius: var(--radius-control) !important;
  background: var(--surface) !important;
  color: var(--ink) !important;
}

:where(input, textarea, select)::placeholder { color: var(--muted); opacity: 1; }

:where(button, input, textarea, select):disabled {
  cursor: not-allowed;
  opacity: .55;
}

/* Public, persuasive pages */
.parent-hero {
  min-height: calc(100svh - 4.5rem);
  padding-block: clamp(3rem, 8vw, 7rem) !important;
}

.parent-hero__copy { align-self: center; }

.parent-hero h1 {
  margin-top: 0 !important;
  letter-spacing: -.04em !important;
}

.parent-hero__lead { max-width: 38rem; }

.parent-hero__art img,
.parent-tutor-card__photo,
.teach-page :where(img, video) {
  border-radius: var(--radius-card) !important;
}

.parent-subject-list a {
  min-height: 3.75rem;
  align-items: center;
}

.parent-steps li > span {
  border-radius: var(--radius-node) !important;
}

.parent-tutor-card__body { padding-top: .875rem; }

.parent-story-grid blockquote {
  border: 0;
  border-radius: 0;
}

:where(.teach-page, .pg:has(.ab-hero)) h1 {
  max-width: 13ch;
  font-size: clamp(2.75rem, 7vw, 6rem) !important;
  line-height: .98 !important;
  letter-spacing: -.04em !important;
}

/* Discovery: filters stay compact on phones and results appear in the first fold. */
.search-filter-disclosure { min-width: 0; }

.search-filter-disclosure > summary {
  display: none;
  list-style: none;
}

.search-filter-disclosure > summary::-webkit-details-marker { display: none; }

.search-page .search-intro {
  padding-block: clamp(2rem, 6vw, 4.5rem) !important;
}

.search-page .search-intro h1 {
  margin-top: 0 !important;
  letter-spacing: -.04em !important;
}

.search-filterbar {
  border-radius: var(--radius-card) !important;
  box-shadow: none !important;
}

.search-page .sptcard {
  overflow: hidden;
  border-radius: var(--radius-card) !important;
}

.search-page .sptcard:hover {
  transform: translateY(-2px);
}

.search-page .sptavatar { border-radius: calc(var(--radius-card) - 2px) !important; }

.search-page .spresults-head { min-height: 3.25rem; }

/* Guided entry. The split-screen needs a full-bleed wrap: ::before paints the
   left half of the *viewport*, and the card is placed in the right half by the
   wrap's own padding-left. ui.css caps :where(.auth-wrap, …) at 34rem for the
   older single-column layout, so undo that here or the 50% resolves against
   34rem and the card collapses into a ~190px column against the midline. */
.auth-wrap {
  position: relative;
  width: 100% !important;
  max-width: none !important;
  margin-inline: 0 !important;
  min-height: 100svh;
  overflow: hidden;
  padding: clamp(1rem, 4vw, 3rem) !important;
  padding-left: calc(50% + clamp(1rem, 4vw, 3rem)) !important;
  background: var(--paper) !important;
}

.auth-wrap::before {
  position: fixed;
  inset: 0 50% 0 0;
  background: var(--welcome);
  content: "";
}

.auth-wrap::after {
  position: fixed;
  top: 50%;
  left: 25%;
  width: min(18vw, 14rem);
  aspect-ratio: 1;
  background: url("/icons/logo.svg") center / contain no-repeat;
  content: "";
  transform: translate(-50%, -50%);
}

.auth-wrap--story::after { display: none; }

.auth-story {
  position: fixed;
  z-index: 1;
  inset: 0 50% 0 0;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  justify-content: center;
  padding: clamp(2.5rem, 5vw, 5rem);
  color: var(--welcome-ink);
}

.auth-story__logo {
  position: absolute;
  top: clamp(2rem, 4vw, 3.5rem);
  left: clamp(2.5rem, 5vw, 5rem);
}

.auth-story__logo .logo-mark { color: var(--welcome-ink); }
.auth-story__logo .signal-mark { width: 2.5rem; height: 2.5rem; }
.auth-story__logo .wordmark,
.auth-story__logo .wordmark-u { color: var(--welcome-ink) !important; }

.auth-story__copy { max-width: 35rem; }

.auth-story__title {
  max-width: 15ch;
  margin: 0;
  font-family: var(--font-editorial);
  font-size: clamp(2.25rem, 3.7vw, 4rem);
  font-weight: 520;
  line-height: 1.02;
  letter-spacing: -.035em;
  text-wrap: balance;
}

.auth-story__body {
  max-width: 31rem;
  margin: 1.5rem 0 0;
  font-size: clamp(1rem, 1.2vw, 1.125rem);
  line-height: 1.7;
}

.auth-story__scope {
  max-width: 31rem;
  margin: 2rem 0 0;
  padding-top: 1rem;
  border-top: 1px solid color-mix(in oklch, var(--welcome-ink) 24%, transparent);
  font-size: var(--text-sm);
  font-weight: 650;
  line-height: 1.5;
}

/* Centred inside the right half by the wrap's justify-content, not shoved
   against the midline by a percentage margin. max-width overrides the 28rem
   in ui.css so the card can actually reach the 30rem it asks for. */
.auth-card {
  position: relative;
  width: min(100%, 30rem) !important;
  max-width: 30rem !important;
  margin-left: 0 !important;
  padding: clamp(2rem, 5vw, 4rem) !important;
  border: 0 !important;
  background: transparent !important;
  box-shadow: none !important;
}

.auth-title {
  font-family: var(--font-editorial);
  font-size: clamp(2.5rem, 5vw, 4.5rem) !important;
  font-weight: 520 !important;
  line-height: .98;
  letter-spacing: -.035em;
}

.auth-logo { margin-bottom: clamp(2rem, 6vw, 4rem) !important; }

.auth-field input { padding-inline: 1rem !important; }

.auth-btn { min-height: 3rem !important; }

/* Workbenches and forms */
.desktop-app-frame {
  width: min(100%, var(--content-wide));
  margin-inline: auto;
}

.desktop-sidebar {
  background: var(--surface-2) !important;
}

.desk-nav-item {
  min-height: var(--control-h) !important;
  border-radius: var(--radius-control);
}

.desk-nav-item.active {
  background: var(--surface) !important;
  color: var(--action) !important;
  box-shadow: inset 0 0 0 1px var(--line);
}

:where(.learner-workbench, .tutor-workbench) .dbgreet {
  padding-top: clamp(2rem, 5vw, 4rem) !important;
}

:where(.learner-workbench, .tutor-workbench) .dbgreet h1 {
  margin-top: 0 !important;
  font-size: clamp(2.25rem, 5vw, 4.25rem) !important;
  letter-spacing: -.04em !important;
}

:where(.dbcard, .ep-card, .class-panel, .request-card, .lesson-card, .stat-card) {
  border-radius: var(--radius-card) !important;
  box-shadow: none !important;
}

.dbcard-head :is(h2, h3),
.ep-card > h2 {
  font-size: 1rem !important;
  font-weight: 720 !important;
}

.dbstats { gap: .75rem !important; }

.dbstat {
  border-radius: var(--radius-card) !important;
  background: var(--surface) !important;
}

.ep-workbench-content,
.learner-focus-page {
  padding-block: clamp(2rem, 5vw, 4rem);
}

.ep-workbench-content > :first-child { margin-top: 0 !important; }

.class-title { margin-top: 0 !important; letter-spacing: -.04em !important; }

/* Messages, records, and operations */
:where(.cv-wrap, .msg-layout, .admin-shell, .u-app-canvas) {
  background: var(--paper);
}

.admin-rail { background: var(--surface-2) !important; }

.admin-route-nav a {
  min-height: var(--control-h);
  border-radius: var(--radius-control);
}

.admin-route-nav a.active {
  background: var(--surface) !important;
  box-shadow: inset 0 0 0 1px var(--line);
}

:where(table, .adtable, .class-roster) th {
  color: var(--muted);
  font-size: .72rem;
  letter-spacing: .04em;
  text-transform: uppercase;
}

:where(table, .adtable, .class-roster) td { vertical-align: middle; }

/* Reading pages */
.pg:has(.doc-head) { padding-inline: var(--content-gutter); }

.doc-head h1 {
  margin-top: 0 !important;
  letter-spacing: -.035em !important;
}

.doc-toc a {
  border-radius: var(--radius-control) !important;
  background: transparent !important;
}

.doc-toc a:hover { background: var(--surface-2) !important; }

.doc-plain {
  border: 0 !important;
  border-radius: var(--radius-control) !important;
  background: var(--surface-2) !important;
}

.doc-body { max-width: 68ch; }

/* Mobile shell */
@media (max-width: 59.99rem) {
  .site-header { min-height: 3.75rem; }

  .site-header .logo-mark { min-width: 0; }

  .parent-hero { min-height: auto; padding-block: 3rem 4rem !important; }

  .parent-hero h1 { font-size: clamp(2.75rem, 14vw, 4.25rem) !important; }

  .search-page .search-intro { padding: 1.75rem var(--content-gutter) 1rem !important; }

  .search-page .search-intro h1 { font-size: clamp(2rem, 10vw, 3rem) !important; }

  .search-filter-disclosure {
    margin-bottom: 1.5rem;
    border-block: 1px solid var(--line);
  }

  .search-filter-disclosure > summary {
    display: flex;
    min-height: 3.5rem;
    align-items: center;
    gap: .65rem;
    color: var(--ink);
    font-weight: 720;
    cursor: pointer;
  }

  .search-filter-disclosure > summary > :last-child {
    margin-left: auto;
    transition: transform var(--duration-fast) var(--ease-standard);
  }

  .search-filter-disclosure[open] > summary > :last-child { transform: rotate(180deg); }

  .search-filter-disclosure:not([open]) > .search-filterbar { display: none !important; }

  .search-filter-disclosure[open] > .search-filterbar {
    display: grid !important;
    margin-bottom: 1rem;
  }

  .search-page .spmain { padding-top: 0 !important; }

  /* No split below this breakpoint: drop the half-width padding the desktop
     rule adds, and let the card go full-bleed again. */
  .auth-wrap { align-items: flex-start; padding: 0 !important; }
  .auth-wrap::before,
  .auth-wrap::after { display: none; }
  .auth-story { display: none; }

  /* Edge-to-edge on phones, but still capped and centred on tablets — this
     breakpoint runs all the way to 60rem, where a full-bleed form field would
     be ~845px wide. */
  .auth-card {
    width: 100% !important;
    max-width: 30rem !important;
    margin: 0 auto !important;
    padding: 2rem 1.25rem 3rem !important;
  }

  .auth-logo { justify-content: flex-start !important; margin-bottom: 3rem !important; }
  .auth-title, .auth-sub { text-align: left !important; }

  .desktop-app-content { padding-inline: var(--content-gutter) !important; }

  .dbstats { grid-template-columns: repeat(2, minmax(0, 1fr)) !important; }

  .doc-head { padding-top: 3rem !important; }
}

/* Desktop keeps the disclosure permanently open (see the `open` attribute in
   search.html and the load-time collapse in ux.js) — ui.css's unconditional
   `.search-filterbar { display: grid }` already applies once it's open, so
   nothing needs forcing here. A CSS-only `display` override on a *closed*
   `<details>`'s content would not be enough anyway: Chromium hides that
   content via an internal skip that isn't undone by author `display` rules,
   so the filterbar would stay uninteractable regardless of viewport width. */

@media (max-width: 40rem) {
  .search-page .spresults-head {
    display: grid !important;
    grid-template-columns: 1fr;
  }

  .search-page .spresults-tools {
    width: 100%;
    justify-content: space-between;
  }

  :where(.dbcard, .ep-card, .class-panel) { padding: 1rem !important; }

  .dbstats { gap: .5rem !important; }
}

@media (prefers-reduced-motion: no-preference) {
  .search-page .sptcard {
    transition: transform var(--duration-fast) var(--ease-standard), border-color var(--duration-fast) var(--ease-standard);
  }
}

@media print {
  .search-filter-disclosure > summary { display: none !important; }
  .search-filter-disclosure > .search-filterbar { display: none !important; }
}
