/* ---------------------------------------------------------------------------
 * Vedaanta design system — hand-written CSS, no build step.
 *
 * These are the SAME tokens as the Node app's packages/ui/src/styles.css, so
 * the two versions are visually identical. They come from the running Vedaanta
 * stylesheet and the logo; nothing here is invented.
 *
 * Written as plain CSS rather than Tailwind on purpose: shared hosting has no
 * Node, so there is no build step available. A compiled utility framework would
 * mean building on a laptop and committing the output, which drifts the moment
 * someone edits a template without rebuilding.
 *
 * Two rules from the design system are load-bearing:
 *   1. Saffron appears ONCE per screen — the single most important action.
 *   2. State is never carried by colour alone. Every semantic colour is paired
 *      with a word, because the front desk reads these under time pressure and
 *      colour-vision deficiency is common in this user population.
 * --------------------------------------------------------------------------- */

:root {
  /* Brand — carried forward from the logo */
  --navy-900: #081a45;
  --navy-800: #0a1f54;
  --navy-700: #0f2c74;
  --navy-500: #1c47a8;
  --navy-300: #5b7fd4;
  --navy-100: #dce6ff;

  --saffron: #fe8028;
  --saffron-700: #c85a10;
  --saffron-100: #fff0e4;

  /* Semantic — state only, never decoration */
  --success: #16a34a;
  --success-soft: #dcfce7;
  --warning: #c2740a;
  --warning-soft: #fdf0d5;
  --danger: #dc3545;
  --danger-soft: #fde3e5;

  /* Short names for the same three, because forty places across twelve views
     were already written as --ok / --warn / --bad and none of them existed. An
     undefined custom property does not fall back to anything: the declaration
     is simply dropped, so every one of those was silently rendering in the
     inherited colour — including a "danger" border that was not red and a seat
     state whose whole job was to look alarming. */
  --ok: var(--success);
  --warn: var(--warning);
  --bad: var(--danger);

  --bg: #f6f8fc;
  --surface: #fff;
  --surface-2: #eef2f9;
  --line: #dfe6f1;
  --line-strong: #c3cfe2;
  --ink: #0d1c3a;
  --ink-2: #4a5b76;
  --ink-3: #7d8ca6;

  /* Overridden per tenant from tenants.primary_color / accent_color, which is
     how white-labelling works without rebuilding anything. */
  --brand: var(--navy-700);
  --brand-ink: #fff;
  --accent: var(--saffron);

  /* Seat states: four states, four treatments, each with a glyph as well */
  --seat-free-bg: #fff;
  --seat-free-line: #8fd0a8;
  --seat-free-ink: #12703a;
  --seat-busy-bg: var(--navy-700);
  --seat-busy-line: var(--navy-700);
  --seat-busy-ink: #fff;
  --seat-hold-bg: var(--warning-soft);
  --seat-hold-line: #e0ad5b;
  --seat-hold-ink: #8a5205;
  --seat-dead-bg: var(--surface-2);
  --seat-dead-line: var(--line-strong);
  --seat-dead-ink: var(--ink-3);

  --radius: 10px;
  --font: 'Poppins', system-ui, -apple-system, 'Segoe UI', sans-serif;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme='light']) {
    --bg: #060c1b;
    --surface: #0d1730;
    --surface-2: #15203f;
    --line: #1f2c4e;
    --line-strong: #2e3f68;
    --ink: #e9eefa;
    --ink-2: #a3b3d0;
    --ink-3: #71829f;
    --brand: var(--navy-300);
    --brand-ink: #06122e;
    --accent: #ff9445;
    --seat-free-bg: #0f1c33;
    --seat-free-line: #2f7a52;
    --seat-free-ink: #5fd493;
    --seat-busy-bg: #2a54ad;
    --seat-busy-line: #2a54ad;
    --seat-hold-bg: #33260c;
    --seat-hold-line: #8a6420;
    --seat-hold-ink: #e3a13a;
    --seat-dead-bg: #101a33;
    --seat-dead-line: #26355a;
  }
}

*, *::before, *::after { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }

body {
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font);
  font-size: 14px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}

a { color: var(--brand); text-decoration: none; }
a:hover { text-decoration: underline; }

/* --- type scale, from the design document ------------------------------- */
.page-title      { font-size: 26px; font-weight: 780; letter-spacing: -.02em; line-height: 1.2; margin: 0; }
.section-heading { font-size: 19px; font-weight: 700; line-height: 1.25; margin: 0; }
.column-label    { font-size: 11px; font-weight: 700; letter-spacing: .1em; text-transform: uppercase; color: var(--ink-3); }
.muted           { color: var(--ink-2); }
.small           { font-size: 12.5px; }
.tabular         { font-variant-numeric: tabular-nums; }

/* --- app shell ----------------------------------------------------------- */
.shell { display: grid; grid-template-columns: 248px 1fr; min-height: 100vh; }
@media (max-width: 900px) { .shell { grid-template-columns: 1fr; } }

.nav {
  background: var(--navy-800);
  padding: 14px;
  display: flex;
  flex-direction: column;
  gap: 2px;
  overflow-y: auto;
}
/* --- the brand rail ------------------------------------------------------
   The logo is the tenant's own artwork, so its colours are unknown. Vedaanta's
   sets "LIBRARY" in dark navy, which on a navy rail vanished entirely — half
   the mark was simply not there. Putting it on a light plate makes any logo
   legible without anyone redrawing anything, and gives the rail a head rather
   than starting straight into a list of links. */
.nav__brand {
  display: block;
  padding: 2px 2px 14px;
  text-decoration: none;
  border-bottom: 1px solid rgba(255,255,255,.07);
  margin-bottom: 6px;
}
.nav__brand:hover { text-decoration: none; }

.nav__plate {
  display: grid;
  place-items: center;
  min-height: 68px;
  padding: 10px 14px;
  border-radius: 12px;
  /* Very slightly warm white: a pure #fff plate against navy has a hard edge
     that reads as a missing image. */
  background: linear-gradient(180deg, #fff 0%, #f4f7fd 100%);
  /* The accent hairline ties the plate to the tenant's own colour, so a
     library that brands itself green does not get an orange rail. */
  box-shadow: 0 1px 0 rgba(255,255,255,.5) inset,
              0 0 0 1px rgba(255,255,255,.10),
              0 6px 18px rgba(4, 14, 40, .35);
  transition: transform .15s ease, box-shadow .15s ease;
}
.nav__brand:hover .nav__plate {
  transform: translateY(-1px);
  box-shadow: 0 1px 0 rgba(255,255,255,.6) inset,
              0 0 0 1px var(--accent),
              0 8px 22px rgba(4, 14, 40, .45);
}

/* Nearly twice what it was, and free to use the full width of the rail. */
.nav__plate img {
  max-height: 52px;
  max-width: 100%;
  width: auto;
  object-fit: contain;
  display: block;
}

.nav__wordmark {
  display: flex; align-items: baseline; gap: 1px;
  font-size: 22px; font-weight: 800; letter-spacing: -.02em;
  color: var(--navy-800, #0f2c74);
}

/* Printed whatever the logo does. A logo can be missing, wrong, or unreadable
   at this size; which library you are working in should never be a guess. */
.nav__name {
  display: block;
  margin-top: 10px;
  padding: 0 4px;
  font-size: 13.5px; font-weight: 700; letter-spacing: -.01em;
  color: #fff;
  line-height: 1.25;
}
.nav__where {
  display: block;
  padding: 1px 4px 0;
  font-size: 10.5px; font-weight: 500; letter-spacing: .04em;
  color: #8fa6d8;
}
.nav__group {
  padding: 14px 10px 6px;
  font-size: 9.5px;
  font-weight: 700;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: #6f86b8;
}
.nav__item {
  display: flex; align-items: center; gap: 10px;
  padding: 8px 10px; border-radius: 6px;
  font-size: 13.5px; font-weight: 500; color: #c2d0ec; text-decoration: none;
}
.nav__item:hover { background: rgba(255,255,255,.05); text-decoration: none; }
.nav__item--on { background: rgba(255,255,255,.1); color: #fff; }
.nav__item svg { width: 18px; height: 18px; flex: none; opacity: .9; }
.nav__foot { margin-top: auto; padding-top: 16px; }

.main { min-width: 0; background: var(--surface); }
.main__inner { max-width: 1180px; margin: 0 auto; padding: 24px; }

/* --- cards, tiles, tables ------------------------------------------------ */
.card { background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius); padding: 20px; }

.tiles { display: grid; gap: 16px; grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); }
.tile { background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius); padding: 14px 16px; }
.tile__label { font-size: 11px; font-weight: 700; letter-spacing: .09em; text-transform: uppercase; color: var(--ink-3); }
.tile__value { font-size: 26px; font-weight: 800; letter-spacing: -.02em; margin-top: 6px; font-variant-numeric: tabular-nums; }
.tile__sub   { font-size: 12px; color: var(--ink-2); margin-top: 4px; }

.table-wrap { overflow-x: auto; border: 1px solid var(--line); border-radius: var(--radius); }
table.data { width: 100%; min-width: 620px; border-collapse: collapse; font-size: 14px; }
table.data thead tr { background: var(--surface-2); }
table.data th {
  text-align: left; padding: 10px 14px;
  font-size: 11px; font-weight: 700; letter-spacing: .1em; text-transform: uppercase; color: var(--ink-2);
}
table.data td { padding: 10px 14px; border-top: 1px solid var(--line); }
table.data tbody tr:hover { background: var(--surface-2); }

/* --- pills: always a word, never colour alone ---------------------------- */
.pill {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 2px 10px; border-radius: 999px;
  font-size: 11.5px; font-weight: 700; white-space: nowrap;
}
.pill--ok    { background: var(--success-soft); color: var(--success); }
.pill--warn  { background: var(--warning-soft); color: var(--warning); }
.pill--bad   { background: var(--danger-soft);  color: var(--danger); }
.pill--info  { background: var(--surface-2);    color: var(--ink-2); }
.pill--brand { background: var(--brand);        color: var(--brand-ink); }

/* --- buttons: three variants, and the restraint is the decision ---------- */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  padding: 8px 16px; border-radius: 7px; border: 1px solid var(--line-strong);
  background: var(--surface); color: var(--ink);
  font-family: inherit; font-size: 14px; font-weight: 600; cursor: pointer;
  text-decoration: none;
}
.btn:hover { background: var(--surface-2); text-decoration: none; }
.btn--primary { background: var(--brand); color: var(--brand-ink); border-color: var(--brand); }
.btn--accent  { background: var(--accent); color: #3a1c04; border-color: var(--accent); }
.btn--primary:hover, .btn--accent:hover { opacity: .9; }
.btn--sm { padding: 5px 12px; font-size: 12.5px; }
.btn:disabled { opacity: .5; cursor: not-allowed; }
.btn:focus-visible, .field input:focus-visible, .field select:focus-visible {
  outline: 2px solid var(--accent); outline-offset: 2px;
}

/* --- forms ---------------------------------------------------------------- */
.field { display: grid; gap: 6px; }
.field > span { font-size: 11px; font-weight: 700; letter-spacing: .1em; text-transform: uppercase; color: var(--ink-3); }
.field input, .field select, .field textarea {
  width: 100%; padding: 9px 12px;
  border: 1px solid var(--line-strong); border-radius: 7px;
  background: var(--surface); color: var(--ink);
  font-family: inherit; font-size: 14px;
}
.field input:focus { border-color: var(--brand); outline: none; }
.grid-2 { display: grid; gap: 16px; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); }

.alert { padding: 10px 14px; border-radius: 7px; font-size: 13px; font-weight: 600; }
.alert--bad  { background: var(--danger-soft);  color: var(--danger); }
.alert--ok   { background: var(--success-soft); color: var(--success); }
.alert--warn { background: var(--warning-soft); color: var(--warning); }

/* --- seat map: the most-used component in the product -------------------- */
.seat-block {
  border: 1px dashed var(--line-strong); border-radius: var(--radius); padding: 14px;
}
.seat-grid { display: grid; grid-template-columns: repeat(5, 1fr); gap: 8px; }
.seat {
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px;
  aspect-ratio: 1 / .86; border-radius: 8px; border: 2px solid;
  font-size: 15px; font-weight: 800; font-variant-numeric: tabular-nums; line-height: 1;
  background: none; font-family: inherit; cursor: default;
}
/* A word under every seat: colour is never the only signal. */
.seat small { font-size: 9.5px; font-weight: 600; opacity: .9; }
.seat--free { border-color: var(--seat-free-line); background: var(--seat-free-bg); color: var(--seat-free-ink); cursor: pointer; }
/* Hover is a lift, NOT the accent colour. Accent on hover looked identical to
   the "chair used by another shift" state, so pointing at a free seat made it
   appear unavailable. Accent now means one thing only: you picked this. */
.seat--free:hover { border-color: var(--brand); box-shadow: 0 2px 8px rgba(15,44,116,.16); }
.seat--sold { border-color: var(--seat-busy-line); background: var(--seat-busy-bg); color: var(--seat-busy-ink); }
.seat--held { border-color: var(--seat-hold-line); background: var(--seat-hold-bg); color: var(--seat-hold-ink); }
.seat--dead { border-style: dashed; border-color: var(--seat-dead-line); background: var(--seat-dead-bg); color: var(--seat-dead-ink); }

/* Free, but somebody is still sitting in it who has not paid.
   It IS sellable, so it stays light like a free seat rather than solid like a
   taken one — but the red edge and the diagonal hatch stop it reading as an
   empty chair, which is how it used to get handed to somebody else while the
   student was still coming in and still meaning to pay.
   Hatched as well as coloured: the state must survive being colour-blind or
   printed in black and white. */
.seat--owed {
  cursor: pointer;
  border-color: var(--bad);
  border-style: dashed;
  color: var(--bad);
  background:
    repeating-linear-gradient(-45deg,
      transparent 0 6px,
      color-mix(in srgb, var(--bad) 10%, transparent) 6px 12px),
    var(--seat-free-bg);
}
.seat--owed:hover { box-shadow: 0 2px 8px color-mix(in srgb, var(--bad) 28%, transparent); }

/* The same treatment at legend size. */
.legend i.seat-key--owed {
  border-color: var(--bad);
  border-style: dashed;
  background:
    repeating-linear-gradient(-45deg,
      transparent 0 3px,
      color-mix(in srgb, var(--bad) 22%, transparent) 3px 6px),
    var(--seat-free-bg);
}

/* The selected seat.
   Two selectors for the same thing: :has() covers current browsers with no
   scripting, and .seat--picked is set by a few lines of JS for older ones.
   Whichever fires first, the desk gets the same answer -- and the desk has to
   be certain which chair it just sold. */
.seat--free:has(input:checked),
.seat--picked {
  border-color: var(--accent);
  background: var(--accent);
  color: #3a1c04;
  box-shadow: 0 0 0 3px rgba(254,128,40,.28);
  transform: translateY(-1px);
}
/* A tick as well as the colour, because colour is never the only signal --
   the same rule the word under every seat already follows. */
.seat--free:has(input:checked)::after,
.seat--picked::after {
  content: '✓';
  position: absolute; top: 3px; right: 5px;
  font-size: 11px; font-weight: 800; line-height: 1;
}
.seat { position: relative; }
/* The hidden radio still has to be reachable by keyboard. */
.seat:focus-within { outline: 2px solid var(--brand); outline-offset: 2px; }
/* Expiring within 7 days is an annotation on an occupied seat, not a 5th state */
.seat--expiring { box-shadow: 0 0 0 2px var(--warning); }

.legend { display: flex; flex-wrap: wrap; gap: 8px 20px; font-size: 12px; color: var(--ink-2); }
.legend i { display: inline-block; width: 14px; height: 14px; border-radius: 4px; border: 2px solid; vertical-align: -2px; margin-right: 6px; }

/* --- occupancy meter: amber above 90% ------------------------------------ */
.meter { height: 7px; border-radius: 999px; background: var(--surface-2); overflow: hidden; }
.meter__fill { height: 100%; border-radius: 999px; background: var(--brand); }
.meter__fill--warn { background: var(--warning); }

/* --- shift selector ------------------------------------------------------- */
.tabs { display: flex; flex-wrap: wrap; gap: 6px; }
.tab {
  padding: 6px 14px; border-radius: 7px; border: 1px solid var(--line-strong);
  background: var(--surface); color: var(--ink-2);
  font-size: 12.5px; font-weight: 600; text-decoration: none;
}
.tab--on { background: var(--brand); border-color: var(--brand); color: var(--brand-ink); }
.tab:hover { text-decoration: none; }

/* --- the "i" mark --------------------------------------------------------
 *
 * Next to a button whose name is not the whole story. "Renew" is the example
 * that forced it: the word is clear enough, but WHEN to press it rather than
 * "Change seat or shift" is not, and the answer was previously a paragraph
 * that had to sit on the page whether or not anybody needed it.
 *
 * Built on <details>, so it needs no JavaScript and is keyboard-operable for
 * free. It stays open until the mark is pressed again, on purpose: the panel
 * is something to read while looking at the form, not a tooltip that vanishes
 * the moment the pointer moves.
 * ------------------------------------------------------------------------- */
.info { position: relative; display: inline-block; vertical-align: middle; }
.info > summary {
  list-style: none; cursor: pointer; user-select: none;
  display: grid; place-items: center; width: 18px; height: 18px;
  border: 1px solid var(--line-strong); border-radius: 50%;
  background: var(--surface); color: var(--ink-2);
  font-size: 11px; font-weight: 800; font-style: italic; line-height: 1;
}
.info > summary::-webkit-details-marker { display: none; }
.info > summary::marker { content: ''; }
.info > summary:hover { border-color: var(--brand); color: var(--brand); }
.info[open] > summary { background: var(--brand); border-color: var(--brand); color: var(--brand-ink); }
.info__panel {
  position: absolute; z-index: 40; top: calc(100% + 8px);
  width: min(340px, calc(100vw - 32px));
  padding: 14px 16px; border: 1px solid var(--line-strong); border-radius: var(--radius);
  background: var(--surface); box-shadow: 0 14px 34px rgba(8, 26, 69, .2);
  font-size: 12.5px; font-weight: 400; line-height: 1.6; color: var(--ink-2);
  text-align: left; white-space: normal; cursor: auto;
}
.info__panel--left  { left: 0; }
.info__panel--right { right: 0; }
.info__head { font-size: 13.5px; font-weight: 700; color: var(--ink); }
.info__sub {
  font-size: 10.5px; font-weight: 700; letter-spacing: .09em; text-transform: uppercase;
  color: var(--ink-3); margin-top: 12px;
}
.info__list { margin: 5px 0 0; padding-left: 17px; }
.info__list li + li { margin-top: 5px; }
.info__text { margin: 6px 0 0; }

/* --- printed documents: receipts, records, statements --------------------
 *
 * Paper, not a screen: fixed white and near-black regardless of the theme,
 * because a dark-mode student record printed as a black rectangle is what
 * happens otherwise.
 * ------------------------------------------------------------------------- */
.doc {
  max-width: 820px; margin: 20px auto; padding: 32px;
  background: #fff; color: #111;
  border: 1px solid var(--line); border-radius: 8px;
}
.doc__bar { max-width: 820px; margin: 0 auto; padding: 20px 24px 0; }
.doc__section {
  font-size: 11.5px; font-weight: 700; letter-spacing: .12em; text-transform: uppercase;
  color: #0f2c74; margin: 26px 0 10px; padding-bottom: 5px; border-bottom: 1px solid #dfe6f1;
}
.doc table { width: 100%; border-collapse: collapse; font-size: 12.5px; }
.doc th, .doc td { border: 1px solid #dfe6f1; padding: 7px 10px; text-align: left; vertical-align: top; }
.doc th { background: #eef2f9; font-size: 10.5px; letter-spacing: .05em; text-transform: uppercase; }
.doc tfoot td { background: #f6f8fc; font-weight: 700; }
.doc__pairs { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 12px 24px; }
.doc__pair { break-inside: avoid; }
.doc__key { font-size: 10px; font-weight: 700; letter-spacing: .1em; text-transform: uppercase; color: #6b7a93; }
.doc__val { font-size: 13px; margin-top: 2px; }
.doc__muted { color: #6b7a93; }
.doc__void { opacity: .62; }

/* --- utilities ------------------------------------------------------------ */
.row { display: flex; flex-wrap: wrap; align-items: center; gap: 12px; }
.row--between { justify-content: space-between; }
.push { margin-left: auto; }
.stack > * + * { margin-top: 16px; }
.mt-4 { margin-top: 16px; } .mt-6 { margin-top: 24px; } .mt-8 { margin-top: 32px; }
.text-right { text-align: right; }
.hidden { display: none; }

/* --- printing: the document, not the application around it --------------- */
@media print {
  body { background: #fff; color: #111; }
  .nav, .no-print, .info { display: none !important; }
  .main__inner { padding: 0; max-width: none; }
  @page { margin: 14mm; }

  /* The page IS the sheet, so the card the document sits in on screen —
     its border, its rounding, its margin — is chrome and has to go. */
  .doc { max-width: none; margin: 0; padding: 0; border: 0; border-radius: 0; }

  /* A statement runs to several pages. Repeat the column headings on each,
     and never split a row across the fold: a payment whose amount landed on
     the next sheet is the one somebody disputes. */
  thead { display: table-header-group; }
  tr, .doc__pair { break-inside: avoid; }
  .doc__section { break-after: avoid; }

  /* Browsers drop background colours when printing unless asked. Without this
     the header band of every table prints as bare text and the columns stop
     reading as a table at all. */
  .doc th, .doc tfoot td { -webkit-print-color-adjust: exact; print-color-adjust: exact; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: .01ms !important; transition-duration: .01ms !important; }
}
