/* ===========================================================================
   Tootor UI — the look.

   WHY THIS IS A STYLESHEET AND NOT A REWRITE
   The panels are ~800KB of markup already written in Tailwind utilities. This
   layer restyles what is there by matching the patterns that markup already
   uses (a white card with a ring and a big radius, a nav item, a primary
   button) rather than touching a single tag. That means the redesign cannot
   break a screen it has never seen, and any screen added later inherits it.

   Everything is scoped under html[data-ui="v2"], so the old flat look is one
   attribute away if something here turns out to be wrong on a screen I could
   not check.

   THE IDEA
   English Studio's panel was flat white cards on flat grey — a clean 2020
   admin. This is the opposite bet: a living, school-coloured background with
   translucent surfaces floating over it. Depth comes from blur and layered,
   hue-tinted shadow instead of from 1px borders, so two schools with different
   brand colours end up with panels that feel genuinely different rather than
   the same panel with a different button.
   =========================================================================== */

html[data-ui="v2"] {
  /* Radii. Bigger than the old 12px throughout — the single change that most
     separates "web admin" from "app". radius_scale still drives --radius. */
  --r-xs: 10px;
  --r-sm: 14px;
  --r-md: calc(var(--radius, 12px) + 6px);
  --r-lg: calc(var(--radius, 12px) + 12px);
  --r-pill: 999px;

  /* Glass. Opacity stays high enough that body text keeps its contrast — a
     card you cannot read is not a design, and 0.72 is about the floor. */
  --glass-bg: color-mix(in srgb, var(--surface-card, #fff) 78%, transparent);
  --glass-bg-solid: color-mix(in srgb, var(--surface-card, #fff) 92%, transparent);
  --glass-stroke: color-mix(in srgb, var(--surface-border, #e2e8f0) 60%, transparent);
  --glass-blur: 18px;

  /* Shadows tinted with the brand hue rather than pure black. Grey shadow on a
     coloured ground reads as dirt; a tinted one reads as depth. */
  --sh-1: 0 1px 2px color-mix(in srgb, var(--brand-900, #0b2d5e) 8%, transparent);
  --sh-2: 0 4px 16px -4px color-mix(in srgb, var(--brand-900, #0b2d5e) 14%, transparent),
          0 1px 3px color-mix(in srgb, var(--brand-900, #0b2d5e) 7%, transparent);
  --sh-3: 0 18px 40px -12px color-mix(in srgb, var(--brand-900, #0b2d5e) 22%, transparent),
          0 4px 12px -4px color-mix(in srgb, var(--brand-900, #0b2d5e) 10%, transparent);

  --ease: cubic-bezier(.22, 1, .36, 1);      /* a settle, not a bounce */
  --dur: .28s;
}

/* ---------------------------------------------------------------------------
   1. THE BACKGROUND

   Painted on two fixed layers behind everything: a flat ground, and above it
   the school's own colour as slow-moving light. Fixed rather than attached to
   the page so it never scrolls with content or repaints on every frame of a
   scroll.
   --------------------------------------------------------------------------- */
html[data-ui="v2"] body { background: transparent; position: relative; }

html[data-ui="v2"] body::before {
  content: '';
  position: fixed; inset: 0; z-index: -2;
  background: var(--surface, #f6f8fc);
}

/* The light. Three soft pools of brand colour; `filter: blur()` on a low-detail
   layer is cheap, and only transform is animated so it stays on the compositor. */
html[data-ui="v2"] body::after {
  content: '';
  position: fixed; inset: -30%; z-index: -1;
  pointer-events: none;
  opacity: var(--bg-strength, 1);
  /* Five overlapping pools rather than three, each fading out over a longer
     distance. Three tight ones left a visible seam across the middle of the
     page where the top pair ran out and the bottom one had not begun. */
  background-image:
    radial-gradient(60% 55% at 12% 12%, var(--brand-300, #8db9ff) 0%, transparent 70%),
    radial-gradient(55% 50% at 88% 8%,  var(--brand-400, #5a98e8) 0%, transparent 72%),
    radial-gradient(70% 60% at 75% 55%, var(--brand-200, #bcd7ff) 0%, transparent 75%),
    radial-gradient(65% 60% at 20% 78%, var(--brand-300, #8db9ff) 0%, transparent 72%),
    radial-gradient(80% 70% at 50% 100%, var(--brand-100, #d9eaff) 0%, transparent 70%);
  filter: blur(80px) saturate(125%);
  will-change: transform;
  animation: tootor-drift 34s var(--ease) infinite alternate;
}

@keyframes tootor-drift {
  0%   { transform: translate3d(0, 0, 0)        scale(1);    }
  50%  { transform: translate3d(2%, -1.5%, 0)   scale(1.06); }
  100% { transform: translate3d(-1.5%, 2%, 0)   scale(1.02); }
}

/* --- the choices a school can make ------------------------------------- */

/* Plain: the old flat ground, for a school that wants nothing behind its work. */
html[data-ui="v2"][data-bg="plain"] body::after { display: none; }

/* Aurora is the default above. Mesh is the same idea held still, for anyone
   who finds movement distracting — and it is also what everyone gets under
   prefers-reduced-motion. */
html[data-ui="v2"][data-bg="mesh"] body::after { animation: none; }

/* Vivid: the same light, turned up. */
html[data-ui="v2"][data-bg="vivid"] body::after { opacity: 1; filter: blur(55px) saturate(150%); }

/* Soft: barely there — a tint rather than a picture. */
html[data-ui="v2"][data-bg="soft"] body::after { opacity: .45; filter: blur(90px) saturate(105%); }

/* A photograph the school uploaded, dimmed enough to stay a background. */
html[data-ui="v2"][data-bg="image"] body::after {
  background-image: var(--bg-image, none);
  background-size: cover; background-position: center;
  filter: none; opacity: 1; inset: 0;
  animation: none;
}
html[data-ui="v2"][data-bg="image"] body::before {
  background: var(--surface, #f6f8fc);
}
/* A scrim over the photo, or nothing on it would be readable. */
html[data-ui="v2"][data-bg="image"] body {
  --glass-bg: color-mix(in srgb, var(--surface-card, #fff) 88%, transparent);
}

/* A bar above a `min-h-screen` shell makes the page exactly that bar taller
   than the window, so every screen gained a pointless 43px of scroll. The bar
   publishes its own height and the shell subtracts it. */
html[data-ui="v2"] .min-h-screen {
  min-height: calc(100vh - var(--tootor-bar-h, 0px));
}
/* The sidebar is `h-screen` — a fixed height, not a minimum — so capping only
   the shell left it stretching the flex row back to a full viewport. Both have
   to know about the bar. */
html[data-ui="v2"] .h-screen,
html[data-ui="v2"] .lg\:h-screen {
  height: calc(100vh - var(--tootor-bar-h, 0px));
}

/* ---------------------------------------------------------------------------
   2. GLASS SURFACES

   Matched against the shapes the existing markup already makes: a light card
   with a hairline ring and a large radius. Written as attribute selectors so
   no HTML had to change.
   --------------------------------------------------------------------------- */
html[data-ui="v2"] [class*="bg-white"][class*="rounded-2xl"],
html[data-ui="v2"] [class*="bg-white"][class*="rounded-xl"],
html[data-ui="v2"] .card,
html[data-ui="v2"] .modal-card {
  background: var(--glass-bg) !important;
  -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(160%);
  backdrop-filter: blur(var(--glass-blur)) saturate(160%);
  border-radius: var(--r-lg);
  box-shadow: var(--sh-2);
  border: 1px solid var(--glass-stroke);
  /* The utility ring these cards carry would double the border. */
  --tw-ring-shadow: 0 0 #0000;
  transition: box-shadow var(--dur) var(--ease), transform var(--dur) var(--ease);
}

/* Cards that are also links or rows lift slightly under the cursor. Only where
   the markup says it is interactive — a lift on a static panel is a lie. */
html[data-ui="v2"] a[class*="bg-white"][class*="rounded-2xl"]:hover,
html[data-ui="v2"] [class*="bg-white"][class*="rounded-2xl"][class*="cursor-pointer"]:hover {
  transform: translateY(-2px);
  box-shadow: var(--sh-3);
}

/* The rails. More opaque than a card: they sit against the page edge where the
   background is strongest, and text on them has to stay crisp. */
html[data-ui="v2"] #sidebar,
html[data-ui="v2"] #side-nav {
  background: var(--glass-bg-solid) !important;
  -webkit-backdrop-filter: blur(22px) saturate(160%);
  backdrop-filter: blur(22px) saturate(160%);
  border-right: 1px solid var(--glass-stroke) !important;
}

html[data-ui="v2"] header,
html[data-ui="v2"] #tabbar,
html[data-ui="v2"] #a-tabbar {
  background: var(--glass-bg-solid) !important;
  -webkit-backdrop-filter: blur(22px) saturate(160%);
  backdrop-filter: blur(22px) saturate(160%);
}

/* A branded sidebar keeps its colour; glass over a solid brand fill would just
   make the brand colour muddy. */
html[data-ui="v2"][data-sidebar="brand"] #sidebar,
html[data-ui="v2"][data-sidebar="brand"] #side-nav {
  background: linear-gradient(170deg,
              var(--brand-700, #114794), var(--brand-900, #0b2d5e)) !important;
  backdrop-filter: none; -webkit-backdrop-filter: none;
  border-right-color: color-mix(in srgb, var(--brand-900,#0b2d5e) 60%, transparent) !important;
}

/* Everything sitting ON a coloured or dark rail takes its colour FROM the rail.
   The markup was written for a white sidebar, so every label in it is a dark
   slate — which on the brand gradient above is dark-on-dark and effectively
   invisible. This is deliberately a broad sweep rather than a list of ids:
   the rail is a known, self-contained region, and any label added to it later
   should inherit legibility rather than have to ask for it. */
html[data-ui="v2"][data-sidebar="brand"] #sidebar,
html[data-ui="v2"][data-sidebar="brand"] #side-nav,
html[data-ui="v2"][data-sidebar="dark"]  #sidebar,
html[data-ui="v2"][data-sidebar="dark"]  #side-nav { color: #fff; }

html[data-ui="v2"][data-sidebar="brand"] #sidebar *:not(svg):not(path),
html[data-ui="v2"][data-sidebar="brand"] #side-nav *:not(svg):not(path),
html[data-ui="v2"][data-sidebar="dark"]  #sidebar *:not(svg):not(path),
html[data-ui="v2"][data-sidebar="dark"]  #side-nav *:not(svg):not(path) {
  color: inherit;
}

/* Secondary lines stay secondary — legible, but still clearly a caption. */
html[data-ui="v2"][data-sidebar="brand"] #sidebar .text-xs,
html[data-ui="v2"][data-sidebar="brand"] #side-nav .text-xs,
html[data-ui="v2"][data-sidebar="brand"] #side-whoami,
html[data-ui="v2"][data-sidebar="dark"]  #sidebar .text-xs,
html[data-ui="v2"][data-sidebar="dark"]  #side-nav .text-xs,
html[data-ui="v2"][data-sidebar="dark"]  #side-whoami { color: rgba(255,255,255,.62); }

/* Idle nav items are quieter than the active one, as they were on white. */
html[data-ui="v2"][data-sidebar="brand"] .nav-item:not(.active),
html[data-ui="v2"][data-sidebar="brand"] .nav-link:not(.bg-brand-50),
html[data-ui="v2"][data-sidebar="dark"]  .nav-item:not(.active),
html[data-ui="v2"][data-sidebar="dark"]  .nav-link:not(.bg-brand-50) {
  color: rgba(255,255,255,.72) !important;
}
html[data-ui="v2"][data-sidebar="brand"] .nav-item:not(.active):hover,
html[data-ui="v2"][data-sidebar="brand"] .nav-link:not(.bg-brand-50):hover,
html[data-ui="v2"][data-sidebar="dark"]  .nav-item:not(.active):hover,
html[data-ui="v2"][data-sidebar="dark"]  .nav-link:not(.bg-brand-50):hover {
  background: rgba(255,255,255,.12) !important;
  color: #fff !important;
}

/* The selected one is a bright pill, so which screen you are on is readable
   from the far side of a desk. */
html[data-ui="v2"][data-sidebar="brand"] .nav-item.active,
html[data-ui="v2"][data-sidebar="brand"] .nav-link.bg-brand-50,
html[data-ui="v2"][data-sidebar="dark"]  .nav-item.active,
html[data-ui="v2"][data-sidebar="dark"]  .nav-link.bg-brand-50 {
  background: rgba(255,255,255,.18) !important;
  color: #fff !important;
  box-shadow: inset 0 0 0 1px rgba(255,255,255,.22);
}
html[data-ui="v2"][data-sidebar="brand"] .nav-item.active svg,
html[data-ui="v2"][data-sidebar="brand"] .nav-link.bg-brand-50 svg,
html[data-ui="v2"][data-sidebar="dark"]  .nav-item.active svg,
html[data-ui="v2"][data-sidebar="dark"]  .nav-link.bg-brand-50 svg { color: #fff; }

/* Rules and separators inside a coloured rail. */
html[data-ui="v2"][data-sidebar="brand"] #sidebar [class*="border-slate"],
html[data-ui="v2"][data-sidebar="brand"] #side-nav [class*="border-slate"],
html[data-ui="v2"][data-sidebar="dark"]  #sidebar [class*="border-slate"],
html[data-ui="v2"][data-sidebar="dark"]  #side-nav [class*="border-slate"] {
  border-color: rgba(255,255,255,.16) !important;
}

/* ---------------------------------------------------------------------------
   3. NAVIGATION
   --------------------------------------------------------------------------- */
html[data-ui="v2"] .nav-item,
html[data-ui="v2"] .nav-link {
  border-radius: var(--r-sm);
  transition: background var(--dur) var(--ease),
              color var(--dur) var(--ease),
              transform .18s var(--ease);
}
html[data-ui="v2"] .nav-item:hover,
html[data-ui="v2"] .nav-link:hover { transform: translateX(2px); }

html[data-ui="v2"] .nav-item.active,
html[data-ui="v2"] .nav-link.bg-brand-50 {
  background: linear-gradient(100deg,
              color-mix(in srgb, var(--brand-500, #1e6fd9) 18%, transparent),
              color-mix(in srgb, var(--brand-500, #1e6fd9) 7%, transparent)) !important;
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--brand-500, #1e6fd9) 22%, transparent);
}

/* ---------------------------------------------------------------------------
   4. CONTROLS
   --------------------------------------------------------------------------- */
html[data-ui="v2"] button,
html[data-ui="v2"] .btn,
html[data-ui="v2"] input,
html[data-ui="v2"] select,
html[data-ui="v2"] textarea {
  border-radius: var(--r-xs);
  transition: background var(--dur) var(--ease), border-color var(--dur) var(--ease),
              box-shadow var(--dur) var(--ease), transform .14s var(--ease),
              filter var(--dur) var(--ease);
}
html[data-ui="v2"] button:active { transform: scale(.97); }

/* Primary buttons get a gradient and a coloured glow, which is most of what
   makes a button read as "the thing to press" without an outline. */
html[data-ui="v2"] [class*="bg-brand-500"],
html[data-ui="v2"] [class*="bg-brand-600"] {
  background-image: linear-gradient(140deg,
                    var(--brand-500, #1e6fd9), var(--brand-700, #114794)) !important;
  box-shadow: 0 6px 18px -6px color-mix(in srgb, var(--brand-500, #1e6fd9) 65%, transparent);
  border: 0;
}
html[data-ui="v2"] [class*="bg-brand-500"]:hover,
html[data-ui="v2"] [class*="bg-brand-600"]:hover {
  filter: brightness(1.07);
  box-shadow: 0 10px 26px -8px color-mix(in srgb, var(--brand-500, #1e6fd9) 75%, transparent);
}

html[data-ui="v2"] input:focus,
html[data-ui="v2"] select:focus,
html[data-ui="v2"] textarea:focus {
  outline: none;
  border-color: var(--brand-500, #1e6fd9);
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--brand-500, #1e6fd9) 16%, transparent);
}

/* ---------------------------------------------------------------------------
   5. MOTION

   One entrance, used everywhere, so screens feel like they belong to the same
   application. Deliberately short: this is a tool people use all day, and an
   animation you notice twice is an animation you resent by the fiftieth time.
   --------------------------------------------------------------------------- */
@keyframes tootor-rise {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: none; }
}
html[data-ui="v2"] #view-root > * { animation: tootor-rise .34s var(--ease) both; }

/* Rows and cards arrive just behind the container, which reads as one movement
   rather than a list flickering into place. Capped at eight: past that the last
   item waits long enough to feel broken. */
html[data-ui="v2"] #view-root > * > *:nth-child(1) { animation-delay: .02s }
html[data-ui="v2"] #view-root > * > *:nth-child(2) { animation-delay: .04s }
html[data-ui="v2"] #view-root > * > *:nth-child(3) { animation-delay: .06s }
html[data-ui="v2"] #view-root > * > *:nth-child(4) { animation-delay: .08s }

html[data-ui="v2"] .modal-backdrop,
html[data-ui="v2"] .veil { animation: tootor-fade .2s var(--ease) both; }
@keyframes tootor-fade { from { opacity: 0 } to { opacity: 1 } }

/* ---------------------------------------------------------------------------
   6. TYPOGRAPHY
   --------------------------------------------------------------------------- */
html[data-ui="v2"] h1,
html[data-ui="v2"] h2 { letter-spacing: -.022em; }
html[data-ui="v2"] h1 { text-wrap: balance; }

/* ---------------------------------------------------------------------------
   7. WHEN NOT TO DO ANY OF THIS
   --------------------------------------------------------------------------- */

/* Somebody who has asked their system for less movement gets a still page.
   The background stays — it is the design, not an effect — it simply stops
   moving. */
@media (prefers-reduced-motion: reduce) {
  html[data-ui="v2"] body::after,
  html[data-ui="v2"] #view-root > *,
  html[data-ui="v2"] .modal-backdrop,
  html[data-ui="v2"] .veil { animation: none !important; }
  html[data-ui="v2"] * { transition-duration: .01ms !important; }
}

/* backdrop-filter is the one thing here without a graceful failure: without it
   a translucent card is just a washed-out card with the background showing
   through the text. Where it is unsupported, surfaces go solid. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  html[data-ui="v2"] [class*="bg-white"][class*="rounded-2xl"],
  html[data-ui="v2"] [class*="bg-white"][class*="rounded-xl"],
  html[data-ui="v2"] #sidebar,
  html[data-ui="v2"] #side-nav,
  html[data-ui="v2"] header,
  html[data-ui="v2"] #tabbar,
  html[data-ui="v2"] #a-tabbar { background: var(--surface-card, #fff) !important; }
}

/* Printing a contract should produce a document, not a screenshot of one. */
@media print {
  html[data-ui="v2"] body::before,
  html[data-ui="v2"] body::after { display: none !important; }
  html[data-ui="v2"] * { backdrop-filter: none !important; box-shadow: none !important; }
}
