/* Eduport Help Center -- design system
   Palette and component shapes carried over from bde-webapp so the two internal
   tools look like they come from the same place. ASCII only: deploy.ps1 rejects
   anything above char 127. */

:root{
  --bg:#f4f4fb; --panel:#ffffff; --panel-2:#faf9ff; --line:#e8e7f3; --line2:#f0eff8;
  --ink:#17162b; --ink2:#3d3a5c; --muted:#8683a3;
  --accent:#6d5ef7; --accent2:#a99bfb; --accent-soft:#efecff; --accent-ink:#5a47e0;
  --green:#16a34a; --green-soft:#e9f9ef; --green-ink:#15803d;
  --amber:#f59e0b; --amber-soft:#fef6e7; --amber-ink:#b45309;
  --danger:#e11d48; --danger-soft:#fff1f2;
  --sky:#0ea5e9; --sky-soft:#e8f6fe; --sky-ink:#0369a1;
  --sidebar:#1e1b4b;
  --radius:14px; --radius-sm:10px;
  --shadow:0 1px 2px rgba(23,22,43,.05),0 2px 6px rgba(23,22,43,.06);
  --shadow-md:0 8px 22px rgba(30,27,75,.12);
  --shadow-lg:0 24px 60px rgba(30,27,75,.26);
  --ring:0 0 0 3px var(--accent-soft);
  /* ONE FACE, everywhere. Two families meant a heading and the sentence under
     it disagreed about what the product sounds like, and a number in a table
     looked like it came from a different application. Size and weight carry
     the hierarchy instead -- which is all they were ever needed for. */
  --display:'Inter',-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;

  /* surfaces and tints, named by ROLE rather than by colour, so the dark
     palette below only has to restate the roles */
  --panel-3:#f1f0f8; --line3:#d8dee7;
  --tint:#f6f4ff; --tint2:#efebff;
  --green-soft2:#d7efe3; --green-line:#c7ecd4;
  --danger-soft2:#fbdedc; --danger-line:#f0b4ae; --danger-ink:#a32820;
  --green-ink:#15694a;
  --glow1:#e9e6ff; --glow2:#edeefc;
  --note-soft:#fbfaf0; --note-soft2:#f3efd3; --note-line:#e0d9ae; --note-ink:#7a6c18;
  --amber-line:#f6dfae; --sky-line:#c9e7fa; --sidebar-dim:#a9a4d8;
  --sidebar-ink:#ffffff;
}

/* Dark mode -- a scheme of its own, not the light one with the lights off.
   Near-black reads as "screen off"; this is built on deep indigo, the same
   family the sidebar has always used, so the console looks like the same
   product wearing different clothes. Surfaces climb in violet rather than grey,
   the accent moves up to a brighter violet that can hold its own against a dark
   ground, and the state colours (green, amber, rose, sky) all keep real
   saturation instead of collapsing into mud. */
:root[data-theme="dark"]{
  /* Neutral graphite surfaces with only a trace of cool in them; the violet
     is kept for the accent alone, and toned down, so it marks what matters
     instead of washing over the whole screen. */
  --bg:#121317; --panel:#1a1b20; --panel-2:#202127; --panel-3:#27282f;
  --line:#2d2e36; --line2:#232429; --line3:#3b3c46;
  --ink:#ededf2; --ink2:#c6c7d0; --muted:#8c8d99;

  --accent:#9b90e0; --accent2:#7f76c2; --accent-soft:#282738; --accent-ink:#c2bcef;
  --tint:#1e1f25; --tint2:#25262e;

  --green:#34d399; --green-soft:#0f3a2c; --green-soft2:#155041;
  --green-ink:#5eead4; --green-line:#1c6b52;
  --amber:#fbbf24; --amber-soft:#432f0c; --amber-ink:#fcd34d; --amber-line:#6b4c14;
  --danger:#fb7185; --danger-soft:#4a1730; --danger-soft2:#5e1d3c;
  --danger-ink:#fda4af; --danger-line:#87305a;
  --sky:#38bdf8; --sky-soft:#0d3550; --sky-ink:#7dd3fc; --sky-line:#1b587f;

  --note-soft:#3a2f16; --note-soft2:#4a3c1c; --note-line:#6e5a24; --note-ink:#f0d795;

  --sidebar:#0f1013; --sidebar-dim:#8e8f9c;
  --shadow:0 1px 2px rgba(0,0,0,.5),0 2px 8px rgba(0,0,0,.4);
  --shadow-md:0 10px 26px rgba(0,0,0,.55);
  --shadow-lg:0 26px 64px rgba(0,0,0,.7);
  --ring:0 0 0 3px rgba(155,144,224,.2);

  /* The page wash keeps its colour. A flat dark background is the thing that
     makes a dark theme feel cheap; two coloured pools of light do not. */
  --glow1:#1b1b24; --glow2:#16171d;
}

*{box-sizing:border-box}
body{
  margin:0;font-family:'Inter',-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif;
  background:radial-gradient(1200px 620px at 100% -12%,var(--glow1) 0%,transparent 58%),
             radial-gradient(1000px 520px at -12% -6%,var(--glow2) 0%,transparent 55%),var(--bg);
  color:var(--ink2);font-size:13.5px;line-height:1.45;
  -webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;
}
/* One face. Hierarchy comes from size and weight, which is what they are for --
   a second family only ever made a heading and the sentence under it sound like
   two different products. Figures stay aligned through tabular numerals. */
h1,h2,h3{color:var(--ink);margin:0;font-family:var(--display)}
h2{font-size:19px;font-weight:700;margin:6px 0 14px;letter-spacing:-.02em}
h3{font-size:15px;font-weight:700;margin:0 0 10px;letter-spacing:-.015em}
a{color:inherit}
::selection{background:var(--accent-soft)}
::-webkit-scrollbar{width:10px;height:10px}
::-webkit-scrollbar-thumb{background:var(--line3);border-radius:20px;border:2px solid transparent;background-clip:content-box}
::-webkit-scrollbar-thumb:hover{background:var(--line3);background-clip:content-box}

/* ------------------------------------------------------------------ atoms */

.logo{width:34px;height:34px;border-radius:11px;background:linear-gradient(140deg,#8b7ff9,#6d5ef7);
  color:#fff;display:flex;align-items:center;justify-content:center;font-weight:800;font-size:15px;
  box-shadow:0 4px 14px rgba(109,94,247,.45);letter-spacing:-.02em;flex:none}

.finput{border:1px solid var(--line);border-radius:var(--radius-sm);padding:10px 12px;font-size:13.5px;
  color:var(--ink);background:var(--panel);width:100%;font-family:inherit;
  transition:border-color .15s,box-shadow .15s,background .15s}
.finput::placeholder{color:var(--muted)}
.finput:hover{border-color:var(--line3)}
.finput:focus{outline:none;border-color:var(--accent);box-shadow:var(--ring)}
.finput:disabled{background:var(--panel-3);color:var(--muted);cursor:not-allowed}
select.finput{cursor:pointer;-webkit-appearance:none;appearance:none;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%237a869a' stroke-width='3'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
  background-repeat:no-repeat;background-position:right 11px center;padding-right:30px}
textarea.finput{resize:vertical;line-height:1.5;min-height:80px}
label.fl{display:block;font-size:12px;color:var(--muted);margin:14px 0 6px;font-weight:600}

.btn{background:linear-gradient(180deg,#7b6cf9,#6d5ef7);border:none;color:#fff;border-radius:var(--radius-sm);
  padding:10px 16px;cursor:pointer;font-weight:600;font-size:13px;box-shadow:0 2px 8px rgba(109,94,247,.32);
  text-decoration:none;display:inline-flex;align-items:center;justify-content:center;gap:6px;
  white-space:nowrap;transition:transform .12s,box-shadow .15s,filter .15s;font-family:inherit}
.btn:hover{filter:brightness(1.06);box-shadow:0 6px 16px rgba(109,94,247,.42)}
.btn:active{transform:translateY(1px)}
.btn:disabled{opacity:.55;cursor:not-allowed;box-shadow:none;transform:none;filter:none}
.btn.ghost{background:var(--panel);border:1px solid var(--line);color:var(--ink2);box-shadow:var(--shadow)}
.btn.ghost:hover{background:var(--panel-2);border-color:var(--line3);filter:none}
.btn.green{background:linear-gradient(180deg,#1eae53,#16a34a);box-shadow:0 2px 6px rgba(22,163,74,.28)}
.btn.green:hover{box-shadow:0 5px 14px rgba(22,163,74,.34)}
.btn.danger{background:linear-gradient(180deg,#ef2455,#e11d48);box-shadow:0 2px 6px rgba(225,29,72,.28)}
.btn.sm{padding:7px 12px;font-size:12px;border-radius:9px}

.pill{display:inline-flex;align-items:center;gap:5px;padding:3px 10px;border-radius:20px;
  font-size:11px;font-weight:600;line-height:1.6;white-space:nowrap}
.pill::before{content:"";width:6px;height:6px;border-radius:50%;background:currentColor;flex:none}
/* One colour. Six tinted pills made a page look like a legend for a chart
   nobody was reading -- the words already say which state it is, and the tint
   was decoration competing with the one violet that means "act here". */
.pill.new, .pill.open, .pill.awaiting, .pill.resolved,
.pill.suggestion, .pill.cancelled{
  background:var(--accent-soft);color:var(--accent-ink)}
.pill.closed{background:var(--panel-3);color:var(--muted)}

.prio{display:inline-flex;align-items:center;padding:2px 8px;border-radius:6px;font-size:11px;font-weight:700}
/* Priority keeps a single accent too. Urgent is the one thing worth a second
   colour, because it is the one thing that should interrupt you. */
.prio.low, .prio.medium, .prio.high{background:var(--accent-soft);color:var(--accent-ink)}
.prio.urgent{background:var(--danger-soft);color:var(--danger-ink)}

.tag{display:inline-flex;align-items:center;gap:5px;padding:2px 9px;border-radius:20px;font-size:11px;
  font-weight:600;background:var(--accent-soft);color:var(--accent-ink);white-space:nowrap}
.tag .x{cursor:pointer;opacity:.5;font-weight:800}
.tag .x:hover{opacity:1}

.muted{color:var(--muted)}
.small{font-size:12px}
.right{text-align:right}
.nowrap{white-space:nowrap}
.spacer{flex:1}
.row{display:flex;align-items:center;gap:10px}
.wrap{flex-wrap:wrap}

/* ------------------------------------------------------------------ login */

.authwrap{min-height:100vh;display:flex;align-items:center;justify-content:center;padding:20px}
.authcard{background:var(--panel);border:1px solid var(--line);border-radius:20px;box-shadow:var(--shadow-lg);
  padding:34px;width:min(410px,94vw);animation:pop .3s ease}
.authcard .brand{display:flex;align-items:center;gap:11px;margin-bottom:22px;padding:0}
.authcard h1{font-size:19px;font-weight:750}
.authmsg{font-size:12.5px;margin-top:14px;min-height:16px}
.authmsg.err{color:var(--danger)}
@keyframes pop{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:none}}

/* ----------------------------------------------------------------- layout */

.sidebar{position:fixed;top:0;left:0;bottom:0;width:230px;
  background:linear-gradient(185deg,#242157 0%,#1a1740 100%);
  border-right:1px solid rgba(255,255,255,.06);display:flex;flex-direction:column;z-index:40;
  transition:transform .22s ease}
.sidebar .brand{display:flex;align-items:center;gap:11px;padding:18px 18px 14px;color:#fff}
.sidebar .brand b{font-size:14px;font-weight:700;letter-spacing:-.01em}
.sidebar .brand .sub{font-size:11px;color:var(--sidebar-dim);font-weight:500}
.navsec{padding:12px 12px 2px;font-size:10.5px;text-transform:uppercase;letter-spacing:.08em;
  color:#7f7ab5;font-weight:700}
.navitem{display:flex;align-items:center;gap:9px;padding:9px 14px;margin:1px 8px;border-radius:9px;
  color:#c9c5ec;cursor:pointer;font-size:13px;font-weight:500;transition:background .13s,color .13s}
.navitem:hover{background:rgba(255,255,255,.06);color:#fff}
.navitem.on{background:var(--accent);color:#fff;font-weight:600;box-shadow:0 3px 12px rgba(109,94,247,.4)}
.navitem .ct{margin-left:auto;font-size:11px;font-weight:700;opacity:.8}
.navfoot{margin-top:auto;padding:14px;border-top:1px solid rgba(255,255,255,.07);color:var(--sidebar-dim);font-size:12px}
.navfoot .who{color:#fff;font-weight:600;font-size:12.5px}
.navfoot .role{font-size:11px;color:#8f8ac4;text-transform:capitalize}

main{margin-left:var(--navw,230px);padding:22px 26px 60px;min-height:100vh}
.topbar{display:flex;align-items:center;gap:12px;margin-bottom:18px;flex-wrap:wrap}
.topbar h2{margin:0}

.panel{background:var(--panel);border:1px solid var(--line);border-radius:var(--radius);
  box-shadow:var(--shadow);padding:16px}
.panel + .panel{margin-top:14px}

.grid{display:grid;gap:14px}
.g2{grid-template-columns:repeat(auto-fit,minmax(260px,1fr))}
.g4{grid-template-columns:repeat(auto-fit,minmax(180px,1fr))}

/* A row of white rectangles on a near-white page reads as one flat block --
   the numbers were doing all the work of separating themselves. A light wash
   and an accent rule give each tile an edge, and match the Overview cards so
   the two screens look like the same product. */
.stat{position:relative;overflow:hidden;
  background:linear-gradient(180deg,var(--tint) 0%,var(--panel) 62%);
  border:1px solid var(--line);border-radius:var(--radius);padding:14px 16px;
  box-shadow:var(--shadow)}
.stat::before{content:'';position:absolute;left:0;top:0;bottom:0;width:3px;
  background:var(--accent);opacity:.55}
.stat .k{font-size:12px;color:var(--ink2);font-weight:650}
.stat .v{font-size:30px;font-weight:700;color:var(--ink);margin-top:3px;letter-spacing:-.03em;
  font-family:var(--display);font-variant-numeric:tabular-nums;line-height:1.1}
.stat .sub{font-size:11.5px;color:var(--muted);margin-top:2px}

/* ------------------------------------------------------------------ table */

.tblwrap{overflow-x:auto;border:1px solid var(--line);border-radius:var(--radius);background:var(--panel);
  box-shadow:var(--shadow)}
table.tbl{width:100%;border-collapse:collapse;font-size:13px;min-width:760px}
table.tbl th{text-align:left;padding:11px 12px;background:var(--panel-2);color:var(--ink2);
  font-family:var(--display);font-weight:600;font-size:12px;letter-spacing:-.005em;
  border-bottom:1px solid var(--line);white-space:nowrap;position:sticky;top:0}
table.tbl td{padding:10px 12px;border-bottom:1px solid var(--line2);vertical-align:middle;
  font-variant-numeric:tabular-nums}
table.tbl tr:last-child td{border-bottom:none}
table.tbl tbody tr{cursor:pointer;transition:background .1s}
table.tbl tbody tr:hover{background:var(--panel-2)}
table.tbl.flat tbody tr{cursor:default}
table.tbl.flat tbody tr:hover{background:transparent}
.tno{font-weight:700;color:var(--accent-ink);font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12px}

.tabs{display:flex;gap:4px;background:var(--panel-2);border:1px solid var(--line);padding:4px;
  border-radius:12px;flex-wrap:wrap}
/* The selected tab was a white panel with a tinted word on it -- readable, but
   it needed looking for. An agent glancing at this screen has to know which
   queue they are in without hunting, so the selected one is solid. */
/* ONE TAB STYLE, used by every tab strip in the console.
   A white pill that fills in when selected. It answers the only question a tab
   row is asked -- which one am I on -- and stops six of them competing for the
   same attention. */
.tabs, .rtabs, .ctabs{
  display:flex;gap:8px;flex-wrap:wrap;
  background:transparent;border:0;padding:0;margin-bottom:16px}
.tab, .rtab, .ctab, .bpill{
  padding:8px 17px;border-radius:999px;cursor:pointer;
  /* The display face, as on every heading and every name in the console. The
     body face made a row of tabs read as a sentence rather than as controls. */
  font-family:var(--display);font-size:13px;font-weight:600;
  letter-spacing:-.01em;
  color:var(--ink2);background:var(--panel);
  border:1px solid var(--line);transition:.13s;white-space:nowrap}
.tab:hover, .rtab:hover, .ctab:hover, .bpill:hover{
  border-color:var(--accent);color:var(--ink);background:var(--panel)}
.tab.on, .rtab.on, .ctab.on, .bpill.on{
  background:var(--accent);border-color:var(--accent);color:#fff;
  box-shadow:0 1px 3px rgba(0,0,0,.16)}
.tab.on:hover, .rtab.on:hover, .ctab.on:hover, .bpill.on:hover{
  background:var(--accent);border-color:var(--accent);color:#fff}
.tab:hover{background:var(--panel);color:var(--ink)}
.tab.on{background:var(--accent);color:#fff;
  box-shadow:0 1px 4px rgba(0,0,0,.2)}
.tab.on:hover{background:var(--accent);color:#fff}


/* Departments as chips here too, so the two screens filter the same way. */
.deptchips{margin:0 0 14px}

.filters{display:flex;gap:8px;flex-wrap:wrap;align-items:center;margin:14px 0}
.filters .finput{width:auto;min-width:150px;padding:8px 11px;font-size:12.5px}
.filters select.finput{min-width:130px}

.empty{padding:40px 20px;text-align:center;color:var(--muted);font-size:13px}
.loading{padding:40px 20px;text-align:center;color:var(--muted);font-size:13px}

/* ------------------------------------------------------------ ticket view */

.tkhead{display:flex;gap:14px;align-items:flex-start;flex-wrap:wrap}
.tkhead .ttl{font-size:18px;font-weight:750;color:var(--ink);letter-spacing:-.01em}
.tklayout{display:grid;grid-template-columns:minmax(0,1fr) 300px;gap:14px;align-items:start}
@media(max-width:980px){.tklayout{grid-template-columns:1fr}}

.kv{display:flex;justify-content:space-between;gap:10px;padding:6px 0;border-bottom:1px solid var(--line2);
  font-size:12.5px}
.kv:last-child{border-bottom:none}
.kv .k{color:var(--muted);font-weight:600;flex:none}
.kv .v{color:var(--ink);text-align:right;word-break:break-word}

/* The thread. Three visually distinct entry types, deliberately: a student can
   see replies, nobody outside support sees internal notes, and a mentor note is
   neither. Nobody should have to guess who wrote what or who can read it. */
.entry{border-radius:var(--radius-sm);padding:11px 13px;margin-bottom:9px;border:1px solid var(--line)}
.entry .meta{display:flex;align-items:center;gap:8px;font-size:11.5px;color:var(--muted);
  margin-bottom:5px;font-weight:600;flex-wrap:wrap}
.entry .who{color:var(--ink);font-weight:700}
.entry .body{white-space:pre-wrap;font-size:13px;color:var(--ink2);word-break:break-word}
.entry.agent{background:var(--panel);border-left:3px solid var(--accent)}
.entry.student{background:var(--panel-2);border-left:3px solid var(--line3)}
.entry.question{background:var(--amber-soft);border-left:3px solid var(--amber)}
.entry.internal{background:var(--note-soft);border-left:3px solid var(--note-line);border-style:dashed}
.entry.mentorc{background:var(--sky-soft);border-left:3px solid var(--sky)}
.vis{font-size:10.5px;font-weight:700;padding:1px 7px;border-radius:20px;text-transform:uppercase;
  letter-spacing:.04em}
.vis.pub{background:var(--green-soft);color:var(--green-ink)}
.vis.staff{background:var(--note-soft2);color:var(--note-ink)}
.vis.mentor{background:#dbeefb;color:var(--sky-ink)}

.gate{background:var(--amber-soft);border:1px solid var(--amber-line);border-radius:var(--radius-sm);
  padding:10px 12px;font-size:12.5px;color:var(--amber-ink);margin-bottom:10px}


/* ------------------------------------------------------- modal and toasts */

#overlay{position:fixed;inset:0;background:rgba(23,22,43,.42);z-index:80;display:none;
  align-items:center;justify-content:center;padding:20px;backdrop-filter:blur(2px)}
#overlay.on{display:flex}
#modal{position:relative;background:var(--panel);border-radius:18px;
  box-shadow:var(--shadow-lg);padding:0;
  width:min(560px,96vw);max-height:88vh;overflow:auto;animation:pop .22s ease}
#modal h3{font-size:16px;margin-bottom:14px}
/* A zero-height sticky strip: it takes no room in the layout but pins the
   close button to the top-right of the card, so it is still there after you
   have scrolled to the bottom of a long form. */
.modalhead{position:sticky;top:0;z-index:3;height:0;display:flex;
  justify-content:flex-end;padding:0 10px}
.modalbody{padding:22px}
.modalx{margin-top:10px;width:30px;height:30px;flex:none;
  display:flex;align-items:center;justify-content:center;
  border:1px solid var(--line);border-radius:9px;cursor:pointer;
  background:var(--panel);color:var(--muted);font-size:19px;line-height:1;
  font-weight:600;transition:.14s}
.modalx:hover{color:var(--ink);border-color:var(--line3);background:var(--panel-2)}
.modalx:focus-visible{outline:2px solid var(--accent);outline-offset:2px}

#toasts{position:fixed;bottom:20px;left:50%;transform:translateX(-50%);z-index:90;
  display:flex;flex-direction:column;gap:8px;align-items:center;pointer-events:none}
.toast{background:var(--ink);color:#fff;padding:10px 18px;border-radius:20px;font-size:12.5px;
  font-weight:600;box-shadow:var(--shadow-md);animation:pop .2s ease}
.toast.err{background:var(--danger)}

/* --------------------------------------------------------------- mobile */

/* Three dots rather than the word Menu: it sits above the page title on every
   screen, and says "navigation" without taking a word's worth of room from the
   heading beside it.

   Sticky, because it used to scroll away with the page. On a narrow window the
   sidebar is off-canvas, so this button is the only way back to it -- and it
   was the one control that could not be reached once you had scrolled. */
.navtoggle{position:sticky;top:10px;z-index:30;
  display:flex;flex-direction:column;align-items:center;justify-content:center;gap:4px;
  width:34px;height:34px;padding:0;margin-bottom:12px;
  border:1px solid var(--line);border-radius:9px;background:var(--panel);
  box-shadow:var(--shadow);cursor:pointer;transition:.14s}
.navtoggle:hover{border-color:var(--accent);background:var(--panel-2)}
.navtoggle:focus-visible{outline:none;box-shadow:var(--ring)}
.navtoggle span{display:block;width:16px;height:2px;border-radius:2px;
  background:var(--ink2);transition:.14s}
.navtoggle:hover span{background:var(--accent-ink)}

/* Folded away: the column goes, and the page takes the width back. */
#app{--navw:230px}
#app.navhidden{--navw:0px}
#app.navhidden .sidebar{transform:translateX(-100%)}
main{transition:margin-left .22s ease}
@media(max-width:860px){
  .sidebar{transform:translateX(-100%)}
  .sidebar.on{transform:none;box-shadow:var(--shadow-lg)}
  main{margin-left:0;padding:16px 14px 60px}
  /* On a narrow window the sidebar covers the page rather than sitting beside
     it, so the button that brings it back has to stay on top of it. */
  .navtoggle{top:8px}
}

/* ============================================================== ticket view
   The thread is the screen people live in, so it gets real structure: a
   timeline with avatars and a connector, and a composer that takes one line of
   attention instead of half the page. */

.tkcard{background:var(--panel);border:1px solid var(--line);border-radius:var(--radius);
  box-shadow:var(--shadow);overflow:hidden}
.tkcard .hd{padding:16px 18px;border-bottom:1px solid var(--line);
  background:linear-gradient(180deg,var(--panel-2),var(--panel))}
.tkcard .hd .ttl{font-size:18px;font-weight:750;color:var(--ink);letter-spacing:-.015em;margin:6px 0 4px}
.tkcard .hd .meta{font-size:12px;color:var(--muted);display:flex;gap:7px;flex-wrap:wrap;align-items:center}
.tkcard .bd{padding:16px 18px}

.av{width:30px;height:30px;border-radius:50%;flex:none;display:flex;align-items:center;
  justify-content:center;font-size:11px;font-weight:750;letter-spacing:-.02em;color:#fff;
  background:linear-gradient(140deg,#8b7ff9,#6d5ef7);box-shadow:0 2px 6px rgba(109,94,247,.3)}
.av.stu{background:linear-gradient(140deg,#9aa3b2,#6b7482);box-shadow:0 2px 6px rgba(107,116,130,.28)}
.av.int{background:linear-gradient(140deg,#d4c257,var(--note-line));box-shadow:0 2px 6px rgba(184,169,74,.3)}
.av.men{background:linear-gradient(140deg,#38bdf8,#0ea5e9);box-shadow:0 2px 6px rgba(14,165,233,.3)}

/* timeline */
.tl{position:relative;padding-left:0}
.tl-item{display:flex;gap:11px;position:relative;padding-bottom:16px}
.tl-item:last-child{padding-bottom:0}
.tl-item::before{content:"";position:absolute;left:14px;top:34px;bottom:0;width:2px;background:var(--line)}
.tl-item:last-child::before{display:none}
.tl-body{flex:1;min-width:0}
.tl-head{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-bottom:5px;line-height:1.3}
.tl-head b{font-size:13px;color:var(--ink);font-weight:700}
.tl-head .when{font-size:11.5px;color:var(--muted)}
.tl-text{font-size:13.5px;color:var(--ink2);white-space:pre-wrap;word-break:break-word;
  background:var(--panel-2);border:1px solid var(--line2);border-radius:12px;
  border-top-left-radius:3px;padding:10px 13px;line-height:1.55}
.tl-item.agent .tl-text{background:var(--tint);border-color:#e4dfff}
.tl-item.question .tl-text{background:var(--amber-soft);border-color:#f6e2b8}
.tl-item.internal .tl-text{background:var(--note-soft);border-color:var(--note-line);border-style:dashed}
.tl-item.mentorc .tl-text{background:var(--sky-soft);border-color:var(--sky-line)}
.tl-note{font-size:11.5px;color:var(--muted);margin-top:5px;font-style:italic}

/* composer -- one box, three modes, so it stops dominating the screen */
.composer{border:1px solid var(--line);border-radius:var(--radius);overflow:hidden;
  background:var(--panel);margin-top:6px}
.ctabs{display:flex;gap:2px;padding:6px;background:var(--panel-2);border-bottom:1px solid var(--line);
  flex-wrap:wrap}
/* Which of the two you are writing decides whether a student ever sees it, so
   the tab has to be unmistakable rather than merely correct. Solid when
   selected, and the internal note keeps its own colour -- the one thing worth
   never getting wrong here is sending a note to a student. */
.ctab{padding:7px 15px;border-radius:8px;font-size:12.5px;font-weight:650;
  color:var(--ink2);cursor:pointer;border:0;background:transparent;
  font-family:inherit;transition:.13s}
.ctab:hover{color:var(--ink);background:var(--panel)}
.ctab.on{background:var(--accent);color:#fff;box-shadow:0 1px 4px rgba(0,0,0,.2)}
.ctab.on:hover{background:var(--accent);color:#fff}


/* The outcome sits beside Send, small, because most replies do not change it. */
.outsel{margin-right:8px}
.outsel .sel{padding:7px 30px 7px 12px;font-size:12.5px}
.composer .cbody{padding:12px 13px}
.composer textarea{border:none;width:100%;font-family:inherit;font-size:13.5px;resize:vertical;
  min-height:74px;color:var(--ink);background:transparent;line-height:1.55}
.composer textarea:focus{outline:none}
.composer textarea::placeholder{color:var(--muted)}
.crow{display:flex;align-items:center;gap:10px;flex-wrap:wrap;padding:10px 13px;
  border-top:1px solid var(--line2);background:var(--panel-2)}
.crow .hint{font-size:11.5px;color:var(--muted)}
.qbox{display:flex;align-items:center;gap:7px;cursor:pointer;font-size:12.5px;color:var(--ink2);
  font-weight:600;user-select:none}
.qbox input{width:15px;height:15px;accent-color:var(--accent);cursor:pointer}

/* side panel bits */
.sp{background:var(--panel);border:1px solid var(--line);border-radius:var(--radius);
  box-shadow:var(--shadow);padding:14px 16px;margin-bottom:12px}
.sp h3{font-size:12px;text-transform:uppercase;letter-spacing:.05em;color:var(--muted);
  font-weight:700;margin:0 0 10px}
.spanrow{padding:9px 0;border-bottom:1px solid var(--line2)}
.spanrow:last-child{border-bottom:none}
.spanrow .top{display:flex;align-items:center;gap:8px;margin-bottom:6px}
.spanrow .top b{font-size:12.5px;color:var(--ink)}
.mini{display:flex;justify-content:space-between;font-size:11.5px;padding:2px 0}
.mini .k{color:var(--muted)}
.mini .v{color:var(--ink);font-weight:600}

@media(max-width:1100px){.tklayout{grid-template-columns:1fr}}

/* Roomy list rows, in the shape of the student booking table: an identifier
   column, then a person with an avatar, then the facts. Status is deliberately
   absent -- the tabs above already say which status you are looking at, so a
   column repeating it on every row is noise. */
table.tbl.roomy td{padding:14px 14px}
table.tbl.roomy th{padding:12px 14px}
table.tbl.roomy tbody tr{border-bottom:1px solid var(--line2)}
.who{display:flex;align-items:center;gap:10px}
.who .nm{font-weight:600;color:var(--ink);font-size:13.5px;line-height:1.25}
.who .ph{font-size:11.5px;color:var(--muted);margin-top:2px}
.who .av{width:30px;height:30px;font-size:11px}

/* Sticky action bar. The actions that end a ticket -- resolve, transfer, close
   -- have to be reachable without scrolling past the whole conversation to find
   them, so they ride at the top and stay there. */
.actionbar{position:sticky;top:0;z-index:25;display:flex;align-items:center;gap:9px;
  flex-wrap:wrap;padding:11px 14px;margin:-6px -6px 14px;border-radius:12px;
  background:rgba(250,249,255,.92);backdrop-filter:blur(8px);
  border:1px solid var(--line);box-shadow:var(--shadow)}
.actionbar .finput.sm{width:auto;min-width:112px;padding:7px 26px 7px 10px;font-size:12px;
  border-radius:9px}
@media(max-width:860px){.actionbar{position:static;backdrop-filter:none}}

/* The side panel scrolls with the page but sticks once it reaches the top, so
   the student's details stay in view while reading a long thread. */
@media(min-width:1101px){
  .tklayout > div:last-child{position:sticky;top:66px;max-height:calc(100vh - 80px);
    overflow-y:auto;padding-right:2px}
}

/* ============================================================== ticket page
   Hierarchy is the whole point here. The student's problem is set large and at
   a readable measure; labels and metadata are deliberately much quieter. If
   everything is 13px semibold, nothing is. */

.tk2{display:grid;grid-template-columns:minmax(0,1fr) 310px;gap:22px;align-items:start}
@media(max-width:1080px){.tk2{grid-template-columns:1fr}}

.subjblock{margin-bottom:16px}
.subj{font-size:27px;line-height:1.2;font-weight:700;color:var(--ink);font-family:var(--display);
  letter-spacing:-.03em;margin:0 0 7px;max-width:26ch}
.submeta{font-size:12.5px;color:var(--muted)}

.backarrow{border:1px solid var(--line);background:var(--panel);color:var(--ink2);
  width:32px;height:32px;border-radius:9px;cursor:pointer;font-size:16px;line-height:1;
  display:flex;align-items:center;justify-content:center;flex:none;box-shadow:var(--shadow);
  transition:background .13s,border-color .13s}
.backarrow:hover{background:var(--panel-2);border-color:var(--line3)}

/* the next action, in a sentence */
.banner{font-size:13.5px;line-height:1.5;padding:13px 16px;border-radius:var(--radius-sm);
  margin-bottom:20px;font-weight:500;border:1px solid transparent}
.banner.todo{background:var(--accent-soft);border-color:var(--tint2);color:var(--accent-ink);font-weight:600}
.banner.wait{background:var(--amber-soft);border-color:var(--amber-line);color:var(--amber-ink)}
.banner.ok{background:var(--green-soft);border-color:var(--green-line);color:var(--green-ink)}
.banner.done{background:var(--panel-3);border-color:#dfe3e9;color:var(--muted)}
.banner.neutral{background:var(--panel-2);border-color:var(--line);color:var(--ink2)}

/* entries -- the thing you came to read */
.entries{display:flex;flex-direction:column;gap:14px}
.ent{border:1px solid var(--line);border-radius:var(--radius);padding:16px 18px 17px;
  background:var(--panel);box-shadow:var(--shadow);border-left:3px solid var(--line3)}
.ent.student{background:var(--sky-soft);border-color:var(--sky-line);
  border-left-color:var(--sky)}
.ent.student .say,.ent.student .who{color:var(--ink)}
.ent.agent{border-left-color:var(--accent)}
.ent.question{background:var(--note-soft);border-color:var(--note-line);border-left-color:var(--amber)}
.ent header{display:flex;align-items:center;gap:10px;margin-bottom:11px}
.ent header .av{width:32px;height:32px;font-size:11.5px}
.ent .meta{display:flex;align-items:center;gap:9px;flex-wrap:wrap}
.ent .who{font-size:13px;font-weight:700;color:var(--ink)}
.ent .when{font-size:11.5px;color:var(--muted);font-weight:500}
.badge{font-size:9.5px;font-weight:750;letter-spacing:.06em;text-transform:uppercase;
  padding:2px 8px;border-radius:20px}
.badge.stu{background:var(--panel-3);color:var(--ink2)}
.badge.sup{background:var(--accent-soft);color:var(--accent-ink)}
.ent .say{font-size:15px;line-height:1.68;color:var(--ink);white-space:pre-wrap;
  word-break:break-word;margin:0;max-width:68ch}
.entnote{font-size:11.5px;color:var(--muted);margin-top:11px;padding-top:9px;
  border-top:1px solid var(--line2);font-style:italic}

/* activity, folded away until asked for */
.disclose{margin-top:18px;background:none;border:none;color:var(--accent-ink);cursor:pointer;
  font-size:12.5px;font-weight:650;font-family:inherit;padding:6px 0;display:inline-flex;
  align-items:center;gap:7px}
.disclose:hover{text-decoration:underline}
.disclose .ct{background:var(--accent-soft);border-radius:20px;padding:1px 8px;font-size:11px}
.activity{background:var(--panel);border:1px solid var(--line);border-radius:var(--radius);
  box-shadow:var(--shadow);padding:6px 18px;margin-top:8px}
.actrow{display:flex;gap:11px;padding:11px 0;border-bottom:1px solid var(--line2)}
.actrow:last-child{border-bottom:none}
.actrow .t{font-size:13px;color:var(--ink);font-weight:600}
.actrow .t .when{font-weight:500;color:var(--muted);font-size:11.5px;margin-left:9px}
.actrow .d{font-size:12.5px;color:var(--ink2);margin-top:4px;white-space:pre-wrap;line-height:1.5}
.actrow.internal .d{background:var(--note-soft);border:1px dashed var(--note-line);border-radius:8px;padding:9px 11px}
.actrow.mentorc .d{background:var(--sky-soft);border:1px solid var(--sky-line);border-radius:8px;padding:9px 11px}

/* the rail -- present, and quieter than everything to its left */
.tkrail{display:flex;flex-direction:column;gap:12px}
@media(min-width:1081px){.tkrail{position:sticky;top:64px}}
.card{background:var(--panel);border:1px solid var(--line);border-radius:var(--radius);
  box-shadow:var(--shadow);padding:15px 17px}
.card h3{font-size:12.5px;color:var(--ink2);font-weight:650;margin:0 0 11px;
  font-family:var(--display);letter-spacing:-.01em}
.stuhd{display:flex;align-items:center;gap:11px;padding-bottom:12px;margin-bottom:6px;
  border-bottom:1px solid var(--line2)}
.stuhd .av{width:38px;height:38px;font-size:13px}
.stuhd .nm{font-size:14.5px;font-weight:750;color:var(--ink);letter-spacing:-.01em}
.stuhd .sub{font-size:11.5px;color:var(--muted);margin-top:1px;
  font-family:ui-monospace,SFMono-Regular,Menlo,monospace}
.frow{display:flex;justify-content:space-between;gap:12px;padding:7px 0;font-size:12.5px}
.frow .k{color:var(--muted);flex:none}
.frow .v{color:var(--ink);font-weight:600;text-align:right;word-break:break-word}
.note{font-size:11px;color:var(--muted);line-height:1.5;margin:11px 0 0;
  padding-top:10px;border-top:1px solid var(--line2)}

.hspan{padding:9px 0;border-bottom:1px solid var(--line2)}
.hspan:last-of-type{border-bottom:none}
.hspan .top{display:flex;justify-content:space-between;align-items:baseline;gap:8px;margin-bottom:5px}
.hspan .top b{font-size:12.5px;color:var(--ink)}
.hspan .st{font-size:10.5px;color:var(--muted);text-transform:uppercase;letter-spacing:.04em}
.mini{display:flex;justify-content:space-between;font-size:11.5px;padding:2px 0}
.mini .k{color:var(--muted)}
.mini .v{color:var(--ink);font-weight:600}
.mini.total{margin-top:9px;padding-top:9px;border-top:1px solid var(--line2);font-size:12.5px}

.composer{margin-top:20px}
.acthint{font-size:11.5px;color:var(--muted);margin:10px 0 4px;line-height:1.5}
.stat.go{cursor:pointer;transition:transform .12s,box-shadow .15s,border-color .15s}
.stat.go:hover{transform:translateY(-1px);box-shadow:var(--shadow-md);border-color:var(--accent2)}
.stat.go:active{transform:none}
.totalpill{font-size:12px;color:var(--muted);font-weight:600}
tr.picked td{background:var(--accent-soft)}
tr.picked td:first-child{box-shadow:inset 3px 0 0 var(--accent)}
.linkish{color:var(--accent-ink)}
tr[data-cat] td,tr[data-dept] td{cursor:pointer}
.bignum{font-weight:700;color:var(--ink);font-variant-numeric:tabular-nums}
.bignum.hot{color:var(--danger)}
.totalrow td{background:var(--panel-2);border-top:2px solid var(--line)}

/* Data tables read better with the labels left and the figures right, and with
   a hairline separating the name from its numbers. */
table.tbl.nums td:not(:first-child),table.tbl.nums th:not(:first-child){text-align:right}
table.tbl.nums td:first-child{border-right:1px solid var(--line2)}
table.tbl.nums th:first-child{border-right:1px solid var(--line)}
table.tbl.nums tbody tr:hover td{background:var(--panel-2)}

/* A count is easier to compare against its neighbours with a little length to
   it, so the "needs us" figure carries a bar scaled to the busiest row. */
.needs{display:inline-flex;align-items:center;gap:9px;justify-content:flex-end}
.needs .bar{height:6px;border-radius:20px;background:var(--accent);min-width:4px;opacity:.85}
.needs .bar.hot{background:var(--danger)}
.navsec{font-family:var(--display);letter-spacing:.02em}
.tab{font-family:var(--display);letter-spacing:-.01em}
.sidebar .brand b{font-family:var(--display);font-size:15px;letter-spacing:-.02em}
.authcard h1{font-family:var(--display);letter-spacing:-.02em}

/* Overview table: readable rather than large. Nothing here changes a font size.
   The work is done by grouping, by killing the zeros, and by keeping a row
   narrow enough that its label and its numbers stay in one glance. */
.tblwrap.tight{max-width:880px}
.tblwrap.tight table.tbl{min-width:0}
table.tbl.grouped td:first-child{width:34%}
table.tbl.grouped .gsep{border-left:1px solid var(--line)}
table.tbl.grouped tbody tr:hover td{background:var(--tint)}
.nil{color:#c9ccd4}
.hotnum{color:var(--danger)}
/* the magnitude bar sat on top of its own number; grouping does the job better */
.needs,.needs .bar{display:none}

/* ===================================================== reading a data table
   Comprehension, not decoration. Four changes, each doing a specific job:

   1. Figures in a mono face with tabular digits. Every digit occupies the same
      width, so a column of numbers lines up as a column instead of a ragged
      edge, and 1 / 11 / 111 are instantly comparable. This is the single
      biggest readability win available to a table and costs nothing in size.
   2. The column that matters is tinted. "Needs us" is the number you act on,
      so the eye should land there first without being shouted at.
   3. Headers darker and heavier than the body they label, so the structure of
      the table is legible before any of its contents.
   4. Rows announce that they are clickable -- a left rule and an arrow on
      hover -- rather than leaving you to discover it. */

/* Numbers keep their column alignment through tabular figures rather than
   through a second family. */
:root{ --mono:'Inter',-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif; }

table.tbl.grouped th{color:var(--ink2);font-weight:650;font-size:12px;
  background:var(--panel-2);letter-spacing:0;text-transform:none;padding:12px 14px}

table.tbl.grouped td:not(:first-child),
table.tbl.grouped td:not(:first-child) b,
table.tbl.grouped td:not(:first-child) span{
  font-family:var(--mono);font-variant-numeric:tabular-nums;font-size:13px;
  letter-spacing:-.2px}

/* the number you act on */
table.tbl.grouped th:nth-child(2),
table.tbl.grouped td:nth-child(2){background:var(--tint)}
table.tbl.grouped td:nth-child(2) b{font-weight:700;color:var(--ink)}
table.tbl.grouped tr:hover td:nth-child(2){background:var(--tint2)}

/* the row label anchors the row: solid ink, colour only on hover */
table.tbl.grouped td:first-child b{color:var(--ink);font-weight:650;
  border-bottom:1px solid transparent;transition:.14s}
table.tbl.grouped tbody tr:hover td:first-child b{color:var(--accent-ink);
  border-bottom-color:var(--accent2)}

/* say that a row can be opened */
table.tbl.grouped tbody tr td:first-child{position:relative;padding-left:18px}
table.tbl.grouped tbody tr td:first-child::before{content:"";position:absolute;left:0;top:8px;
  bottom:8px;width:3px;border-radius:0 3px 3px 0;background:transparent;transition:.14s}
table.tbl.grouped tbody tr:hover td:first-child::before{background:var(--accent)}
table.tbl.grouped tbody tr td:last-child{position:relative}
table.tbl.grouped tbody tr td:last-child::after{content:"\2192";position:absolute;right:-2px;
  color:var(--accent);opacity:0;transition:.14s}
table.tbl.grouped tbody tr:hover td:last-child::after{opacity:.55;right:6px}
table.tbl.grouped tbody tr:hover td:last-child{padding-right:26px}

/* durations read as words, so they stay in the UI face and sit quieter */
table.tbl.grouped td.gsep,table.tbl.grouped td.gsep + td{color:var(--ink2)}
.totalrow td{font-weight:700}
.totalrow td:first-child::before{display:none}

/* The department drawer: its tickets, opened in place. Quiet by design -- it
   answers "what are those four things" without becoming a second ticket
   screen, and without taking you off the comparison you were making. */
tr.opened td{background:var(--tint)!important}
tr.opened td:first-child::before{background:var(--accent)!important}
tr.drawer td{padding:0;background:var(--panel-2);border-bottom:1px solid var(--line)}
tr.drawer:hover td{background:var(--panel-2)}
.drawerbox{padding:12px 16px 14px}
.drawerhd{font-size:11px;font-weight:700;letter-spacing:.4px;text-transform:uppercase;
  color:var(--muted);margin-bottom:8px}
.drow{display:flex;align-items:center;gap:12px;padding:9px 10px;border-radius:8px;
  background:var(--panel);border:1px solid var(--line);margin-bottom:6px;cursor:pointer;
  transition:border-color .13s}
.drow:hover{border-color:var(--accent2)}
.drow .dstu{font-weight:600;color:var(--ink);font-size:13px;min-width:170px}
.drow .deps{font-family:var(--mono);font-size:11px;color:var(--muted);margin-left:7px;font-weight:400}
.drow .dcat{font-size:12.5px;color:var(--ink2);flex:1;min-width:120px}
.drow .down{font-size:12px;color:var(--muted);min-width:110px;text-align:right}
.drow .dage{font-family:var(--mono);font-size:11px;color:var(--muted);min-width:74px;text-align:right}
.drawerall{margin-top:4px;background:none;border:none;color:var(--accent-ink);cursor:pointer;
  font-size:12.5px;font-weight:600;font-family:inherit;padding:5px 0}
.drawerall:hover{text-decoration:underline}
@media(max-width:900px){
  .drow{flex-wrap:wrap;gap:7px}
  .drow .down,.drow .dage{text-align:left;min-width:0}
}

/* Fixes to the row affordance: the arrow was sliding in AND changing the cell's
   padding, which reflowed the last column and let the arrow sit on top of the
   value. Space is now reserved whether or not the arrow is showing, so nothing
   moves and nothing overlaps. */
table.tbl.grouped tbody tr td:last-child{padding-right:28px}
table.tbl.grouped tbody tr:hover td:last-child{padding-right:28px}
table.tbl.grouped tbody tr td:last-child::after{right:9px;transition:opacity .14s}
table.tbl.grouped tbody tr:hover td:last-child::after{right:9px;opacity:.5}

/* Seven narrow columns fit inside the capped width, so the table should never
   need its own horizontal scrollbar. */
.tblwrap.tight{overflow-x:visible}
.tblwrap.tight table.tbl.grouped{min-width:0;width:100%;table-layout:fixed}
table.tbl.grouped td:first-child,table.tbl.grouped th:first-child{width:26%}
table.tbl.grouped th:nth-child(n+2){width:11%}
table.tbl.grouped th:nth-child(6),table.tbl.grouped th:nth-child(7){width:15%}
table.tbl.grouped th,table.tbl.grouped td{overflow:hidden;text-overflow:ellipsis}
@media(max-width:820px){
  .tblwrap.tight{overflow-x:auto}
  .tblwrap.tight table.tbl.grouped{min-width:680px;table-layout:auto}
}

/* The department name is not a link. Clicking it opens the row in place, so
   the underline was promising navigation that never happens -- and an
   underlined word inside a table reads as a stray hyperlink. Replaced with a
   disclosure caret that turns a quarter when the row opens: same click, but
   now the row says what it is about to do. */
table.tbl.grouped tbody tr:hover td:first-child b,
table.tbl.grouped tbody tr.opened td:first-child b{border-bottom-color:transparent}
table.tbl.grouped tbody tr.opened td:first-child b{color:var(--accent-ink);font-weight:700}

table.tbl.grouped tbody tr td:first-child{padding-left:26px}
table.tbl.grouped tbody tr td:first-child::before{
  content:"\203A";width:auto;border-radius:0;background:none!important;
  left:9px;top:50%;bottom:auto;transform:translateY(-50%);
  font-size:16px;line-height:1;font-weight:700;color:var(--muted);opacity:.45;
  transition:transform .16s ease,color .16s,opacity .16s}
table.tbl.grouped tbody tr:hover td:first-child::before{color:var(--accent);opacity:1}
table.tbl.grouped tbody tr.opened td:first-child::before{
  color:var(--accent);opacity:1;transform:translateY(-50%) rotate(90deg)}

/* The trailing arrow meant "this takes you elsewhere". Only the Everything row
   still does that, so it is the only row that keeps one. */
table.tbl.grouped tbody tr td:last-child::after{content:none}
table.tbl.grouped tbody tr.totalrow td:last-child::after{content:"\2192";opacity:.45}
table.tbl.grouped tbody tr.totalrow:hover td:last-child::after{opacity:.85}
.totalrow td:first-child{padding-left:26px}

/* --- Overview, made legible ------------------------------------------------
   "Needs us / Waiting / Resolved / Closed / Oldest waiting" asked the reader to
   hold the whole status model in their head, and two of those words meant
   waiting on opposite people. The columns now say whose turn it is, in the
   order a ticket moves through them, and each heading carries its own
   definition so nothing has to be looked up or remembered. */

.legend{font-size:12.5px;color:var(--ink2);background:var(--panel-2);
  border:1px solid var(--line);border-left:3px solid var(--accent2);
  border-radius:0 8px 8px 0;padding:9px 13px;margin-bottom:12px;line-height:1.5}
.legend b{color:var(--accent-ink);font-weight:650}

table.tbl.grouped th{vertical-align:top;padding-top:12px;padding-bottom:10px}
.hdl{display:block;font-weight:650;color:var(--ink2);font-size:12.5px}
.hdn{display:block;margin-top:3px;font-weight:450;font-size:10.5px;
  color:var(--muted);letter-spacing:0;text-transform:none;white-space:normal;
  line-height:1.35}

/* Six columns now, not seven: resolved and closed are both "done" at this
   altitude, and the split is one click away in the drawer. */
table.tbl.grouped td:first-child,table.tbl.grouped th:first-child{width:24%}
table.tbl.grouped th:nth-child(2){width:14%}
table.tbl.grouped th:nth-child(3){width:16%}
table.tbl.grouped th:nth-child(4){width:15%}
table.tbl.grouped th:nth-child(5){width:14%}
table.tbl.grouped th:nth-child(6){width:17%}
table.tbl.grouped th:nth-child(7){width:auto}
table.tbl.grouped th{overflow:visible}

/* --- Ratings, Speed, Routing ----------------------------------------------
   Three tabs that each answer one question about every department, replacing a
   single nine-column table that answered four at once and could not be read. */

/* Rank on the Speed table. A number in front of the name, not a whole column:
   the position IS a property of the row, and giving it its own column would
   have made the table wider to say something the order already says. */
.rank{display:inline-flex;align-items:center;justify-content:center;
  width:20px;height:20px;margin-right:9px;border-radius:6px;
  background:var(--accent);color:#fff;font-family:var(--mono);
  font-size:11px;font-weight:600;vertical-align:1px}
.rank.none{background:var(--line);color:var(--muted)}
table.tbl.grouped tbody tr:hover .rank{background:var(--accent-ink)}
table.tbl.grouped.speed td:first-child,
table.tbl.grouped.speed th:first-child{width:30%}
table.tbl.grouped.speed th:nth-child(n+2){width:17.5%}

/* Routing mode is a phrase, not a figure, so it drops out of the mono face the
   rest of the numeric columns use. */
td.routecell{font-family:inherit!important;font-size:12.5px;color:var(--ink2);
  letter-spacing:0!important}
table.tbl.grouped.routing td:first-child,
table.tbl.grouped.routing th:first-child{width:22%}
table.tbl.grouped.routing th:nth-child(2){width:20%}
table.tbl.grouped.routing th:nth-child(n+3){width:14.5%}

/* The two feedback lists. Alternatives rather than sections, so they are a
   toggle: you are either looking for problems or for good examples. */
.sidetabs{display:flex;gap:6px;margin-bottom:10px}
.sidetab{font-family:inherit;font-size:12.5px;font-weight:600;cursor:pointer;
  padding:6px 12px;border-radius:999px;border:1px solid var(--line);
  background:var(--panel);color:var(--ink2);transition:.13s}
.sidetab:hover{border-color:var(--accent2)}
.sidetab.on{background:var(--accent);border-color:var(--accent);color:#fff}
.sidetab .ct{font-family:var(--mono);font-size:11px;opacity:.75;margin-left:5px}

/* One rating. Read top to bottom: what they asked, what we sent, what they
   thought of it. The student's own words are the last line and the loudest,
   because that is the part that decides whether this needs following up. */
.fbcard{border:1px solid var(--line);border-left:3px solid var(--line);
  border-radius:0 9px 9px 0;background:var(--panel);padding:11px 14px 12px;
  margin-bottom:8px;cursor:pointer;transition:border-color .13s,box-shadow .13s}
.fbcard:hover{border-color:var(--accent2);box-shadow:0 2px 10px rgba(80,60,200,.07)}
.fbcard.bad{border-left-color:var(--danger-line)}
.fbcard.good{border-left-color:var(--green-line)}

.fbhd{display:flex;align-items:baseline;gap:10px;flex-wrap:wrap;margin-bottom:8px}
.fbverdict{font-size:10.5px;font-weight:700;letter-spacing:.5px;text-transform:uppercase;
  padding:2px 7px;border-radius:5px}
.fbcard.bad  .fbverdict{background:var(--danger-soft);color:var(--danger-ink)}
.fbcard.good .fbverdict{background:var(--green-soft);color:var(--green-ink)}
.fbno{font-family:var(--mono);font-size:11px;color:var(--muted);font-weight:500}
.fbstu{font-size:13px;font-weight:650;color:var(--ink)}
.fbcat{font-size:12px;color:var(--ink2)}
.fbwhen{margin-left:auto;font-size:11px;color:var(--muted)}

.fbline{display:flex;gap:10px;margin-top:5px;font-size:12.5px;line-height:1.5}
.fbk{flex:0 0 74px;font-size:10.5px;font-weight:700;letter-spacing:.4px;
  text-transform:uppercase;color:var(--muted);padding-top:2px}
.fbv{flex:1;color:var(--ink2);min-width:0}
.fbby{display:block;margin-top:3px;font-size:11px;color:var(--muted)}

.fbreason{display:flex;gap:10px;margin-top:10px;padding-top:10px;
  border-top:1px dashed var(--line)}
.fbq{flex:1;font-size:13px;line-height:1.55;color:var(--ink);font-style:italic}
.fbnone{font-size:12.5px;color:var(--muted)}

@media(max-width:760px){
  .fbline,.fbreason{flex-direction:column;gap:2px}
  .fbk{flex:none}
}

/* --- Liked and disliked, made impossible to confuse -----------------------
   Two number columns side by side are read wrong at speed: the eye takes in
   the figure and has to go back up to the heading to learn which one it just
   read. The thumb and the colour carry the meaning instead, so the number no
   longer has to be interpreted. The words "thumbs up" and "thumbs down" that
   used to sit under the headings are gone -- the icon already said it. */

.thumb{width:14px;height:14px;fill:currentColor;vertical-align:-2px}
.thumb.down{transform:rotate(180deg) scaleX(-1)}

th.hgood,th.hbad{white-space:nowrap}
th.hgood .thumb,th.hbad .thumb{margin-right:6px}
th.hgood{color:var(--green-ink)!important}
th.hbad{color:var(--danger-ink)!important}

/* The count itself: coloured, so a dislike reads as a dislike before you have
   read the column it is in. */
.cnum{display:inline-block;min-width:26px;padding:2px 8px;border-radius:6px;
  font-family:var(--mono);font-size:13px;font-weight:600;text-align:center}
.cnum.good{background:var(--green-soft);color:var(--green-ink)}
.cnum.bad{background:var(--danger-soft);color:var(--danger-ink)}
/* Two verdicts can share one cell (the mentor's student table), and a like
   pressed against a dislike reads as a single two-digit number. */
.cnum + .cnum{margin-left:6px}
table.tbl.grouped tbody tr:hover .cnum.good{background:var(--green-soft2)}
table.tbl.grouped tbody tr:hover .cnum.bad{background:var(--danger-soft2)}

table.tbl.grouped.ratings td:first-child,
table.tbl.grouped.ratings th:first-child{width:40%}
table.tbl.grouped.ratings th:nth-child(n+2){width:20%}

/* A department nobody has rated has nothing to open, so it does not pretend to
   be openable: no caret, no pointer, no colour shift on hover. */
tr.flat td{cursor:default}
tr.flat td:first-child::before{content:none!important}
table.tbl.grouped tbody tr.flat:hover td:first-child b{color:var(--ink)}
table.tbl.grouped tbody tr.flat:hover td{background:transparent}

/* The toggle is two thumbs and two numbers. Nothing needs writing down. */
.sidetab{display:inline-flex;align-items:center;gap:7px}
.sidetab .thumb{width:15px;height:15px}
.sidetab.bad{color:var(--danger-ink)}
.sidetab.good{color:var(--green-ink)}
.sidetab.bad.on{background:var(--danger-ink);border-color:var(--danger-ink);color:#fff}
.sidetab.good.on{background:var(--green-ink);border-color:var(--green-ink);color:#fff}
.sidetab.empty{opacity:.45}
.sidetab .ct{font-family:var(--mono);font-size:12px;font-weight:600;opacity:1}

/* On a card the thumb is the verdict -- a round badge rather than a word. */
.fbverdict{display:inline-flex;align-items:center;justify-content:center;
  width:24px;height:24px;border-radius:50%;padding:0}
.fbverdict .thumb{width:13px;height:13px;vertical-align:0}
.fbcard.bad  .fbverdict{background:var(--danger-soft);color:var(--danger-ink)}
.fbcard.good .fbverdict{background:var(--green-soft);color:var(--green-ink)}

/* A duration that is still running reads differently from one that finished.
   The "so far" ones are the tickets still costing time right now. */
.drow .dage.live{color:var(--accent-ink);font-weight:600}

/* A live ticket that has been sitting for more than two days. Every ticket has
   to be solved, so the ones being forgotten should be the ones that catch the
   eye first. */
.tbl td.stale{color:var(--danger-ink);font-weight:650}

/* =========================================================================
   THE FRONT DOOR -- four ways into the Help Center
   =========================================================================
   Shown instead of the sign-in card in demo mode. It is the first thing anyone
   reviewing this sees, so it carries the same weight as a screen rather than
   the weight of a debug switch: four cards, each one a job rather than a
   permission level. */

.portalwrap{min-height:100vh;display:flex;align-items:center;justify-content:center;padding:28px 18px}
.pshell{width:min(980px,100%);animation:pop .32s ease}

.phd{display:flex;align-items:center;gap:13px;margin-bottom:24px}
.phd h1{font-size:22px;font-weight:750;letter-spacing:-.02em}
.psub{font-size:13px;color:var(--muted);margin-top:2px}
.demoflag{font-size:10.5px;font-weight:700;letter-spacing:.5px;text-transform:uppercase;
  color:var(--accent-ink);background:var(--accent-soft);border:1px solid var(--tint2);
  padding:5px 11px;border-radius:999px;white-space:nowrap}

.pgrid{display:grid;grid-template-columns:repeat(4,1fr);gap:14px}

.prole{display:flex;flex-direction:column;align-items:flex-start;text-align:left;gap:0;
  font-family:inherit;cursor:pointer;background:var(--panel);border:1px solid var(--line);
  border-radius:18px;padding:20px 18px 16px;box-shadow:var(--shadow);
  transition:transform .14s,box-shadow .18s,border-color .18s}
.prole:hover{transform:translateY(-3px);box-shadow:var(--shadow-md);border-color:var(--accent2)}
.prole:active{transform:none}

/* Each door gets its own colour, held all the way through the product: a
   student screen is blue, an agent screen violet, admin green, mentor amber.
   It is the only wayfinding a four-in-one demo has. */
.prole .pic{width:42px;height:42px;border-radius:13px;display:flex;align-items:center;
  justify-content:center;margin-bottom:14px;flex:none}
.prole .pic svg{width:23px;height:23px;fill:#fff}
.prole.student .pic{background:linear-gradient(140deg,#38a3e8,#0e7fc4);box-shadow:0 5px 15px rgba(14,127,196,.35)}
.prole.agent   .pic{background:linear-gradient(140deg,#8b7ff9,#6d5ef7);box-shadow:0 5px 15px rgba(109,94,247,.38)}
.prole.admin   .pic{background:linear-gradient(140deg,#22b862,#16a34a);box-shadow:0 5px 15px rgba(22,163,74,.32)}
.prole.mentor  .pic{background:linear-gradient(140deg,#f7b33f,#e08c09);box-shadow:0 5px 15px rgba(224,140,9,.32)}

.prole .ptag{font-size:10.5px;font-weight:700;letter-spacing:.5px;text-transform:uppercase;
  color:var(--muted)}
.prole .pname{font-family:var(--display);font-size:16.5px;font-weight:700;color:var(--ink);
  letter-spacing:-.015em;margin-top:3px}
.prole .pblurb{font-size:12.5px;color:var(--ink2);line-height:1.5;margin-top:8px}
.prole .pdoes{display:flex;flex-direction:column;gap:5px;margin-top:14px;padding-top:12px;
  border-top:1px solid var(--line2);width:100%}
.prole .pdo{font-size:11.5px;color:var(--muted);display:flex;align-items:center;gap:7px}
.prole .pdo::before{content:"";width:4px;height:4px;border-radius:50%;background:var(--accent2);flex:none}
.prole.student .pdo::before{background:#7cc2ee}
.prole.admin .pdo::before{background:#7ed1a0}
.prole.mentor .pdo::before{background:#f5cd85}

/* Step two: who. A list rather than more cards -- by this point the choice is
   between people, and a person is a row. */
.ppeople{background:var(--panel);border:1px solid var(--line);border-radius:18px;
  box-shadow:var(--shadow-md);padding:16px}
.pback{font-family:inherit;font-size:12.5px;font-weight:600;color:var(--muted);cursor:pointer;
  background:none;border:none;padding:4px 4px 12px;display:block}
.pback:hover{color:var(--accent-ink)}
.plist{display:grid;grid-template-columns:repeat(2,1fr);gap:9px}

.pperson{display:flex;align-items:center;gap:12px;text-align:left;font-family:inherit;
  cursor:pointer;background:var(--panel);border:1px solid var(--line);border-radius:13px;
  padding:11px 13px;transition:border-color .14s,background .14s,transform .12s}
.pperson:hover{border-color:var(--accent2);background:var(--panel-2);transform:translateX(2px)}
.pface{width:36px;height:36px;border-radius:11px;color:#fff;display:flex;align-items:center;
  justify-content:center;font-weight:700;font-size:12.5px;flex:none;letter-spacing:.02em}
.pinfo{display:flex;flex-direction:column;min-width:0;flex:1}
.pinfo .pn{font-size:13.5px;font-weight:650;color:var(--ink);white-space:nowrap;
  overflow:hidden;text-overflow:ellipsis}
.pinfo .ps{font-size:11px;color:var(--muted);font-family:var(--mono);margin-top:1px}
.pinfo .pnote{font-size:11px;color:var(--muted);margin-top:2px;white-space:nowrap;
  overflow:hidden;text-overflow:ellipsis}
.pcount{display:flex;flex-direction:column;align-items:flex-end;flex:none;line-height:1.15}
.pcount b{font-family:var(--display);font-size:19px;color:var(--accent-ink);
  font-variant-numeric:tabular-nums}
.pcount span{font-size:9.5px;text-transform:uppercase;letter-spacing:.4px;color:var(--muted);
  font-weight:600}
.pcount.zero b{color:#c9cbd8}

.pfoot{font-size:11.5px;color:var(--muted);text-align:center;margin:22px 0 0;line-height:1.6}

/* The way into the demo from the real sign-in screen. */
.demolink{display:block;margin-top:20px;padding:12px 14px;border-radius:var(--radius-sm);
  border:1px dashed #d6d2f2;background:var(--panel-2);text-decoration:none;
  transition:border-color .15s,background .15s}
.demolink:hover{border-color:var(--accent);background:var(--accent-soft)}
.demolink b{display:block;font-size:12.5px;color:var(--accent-ink);font-weight:650}
.demolink span{display:block;font-size:11.5px;color:var(--muted);margin-top:2px;line-height:1.45}

@media(max-width:900px){
  .pgrid{grid-template-columns:repeat(2,1fr)}
  .plist{grid-template-columns:1fr}
}
@media(max-width:560px){
  .pgrid{grid-template-columns:1fr}
  .prole .pdoes{display:none}
}

/* =========================================================================
   THE STUDENT PORTAL
   =========================================================================
   Deliberately unlike the staff console. Wider type, more air, no tables, and
   nothing that needs a glossary. A student is here with a problem, not to
   administer a queue, so every screen has one thing to do on it. */

.stwrap{max-width:760px}

.sthero{margin-bottom:22px}
.sthero h1{font-family:var(--display);font-size:26px;font-weight:750;letter-spacing:-.025em;
  color:var(--ink)}
.sthero p{font-size:14px;color:var(--ink2);line-height:1.6;margin:8px 0 0;max-width:58ch}

.stepline{display:flex;align-items:center;gap:9px;margin-bottom:16px}
.stepdot{width:21px;height:21px;border-radius:50%;display:flex;align-items:center;
  justify-content:center;font-size:11px;font-weight:700;background:#e9eaf2;color:var(--muted);flex:none}
.stepdot.on{background:var(--accent);color:#fff;box-shadow:0 2px 8px rgba(109,94,247,.4)}
.stepdot.done{background:var(--green-soft);color:var(--green-ink)}
.steplbl{font-size:12px;font-weight:600;color:var(--muted)}
.steprule{flex:1;height:1px;background:var(--line);max-width:60px}

/* Categories as cards. A dropdown would collapse the only hard part of raising
   a ticket -- working out which of six things it is -- into a list you cannot
   read without opening it. */
.catgrid{display:grid;grid-template-columns:repeat(3,1fr);gap:11px}
.catcard{display:flex;flex-direction:column;text-align:left;font-family:inherit;cursor:pointer;
  background:var(--panel);border:1px solid var(--line);border-radius:14px;padding:15px 15px 14px;
  box-shadow:var(--shadow);transition:transform .13s,box-shadow .16s,border-color .16s,background .16s}
.catcard:hover{transform:translateY(-2px);box-shadow:var(--shadow-md);border-color:var(--accent2)}
.catcard.on{border-color:var(--accent);background:var(--accent-soft);box-shadow:var(--ring)}
.catcard .cname{font-size:13.5px;font-weight:700;color:var(--ink);line-height:1.35}
.catcard .chint{font-size:11.5px;color:var(--muted);line-height:1.5;margin-top:6px}
.catcard.on .chint{color:var(--accent-ink)}

.stdescribe{margin-top:16px;background:var(--panel);border:1px solid var(--line);
  border-radius:var(--radius);box-shadow:var(--shadow);padding:16px 17px 14px;animation:pop .25s ease}
.sdhd{display:flex;align-items:center;gap:10px;font-family:var(--display);font-size:15px;
  font-weight:700;color:var(--ink);margin-bottom:12px}
.sdcat{font-family:'Inter',sans-serif;font-size:11px;font-weight:600;color:var(--accent-ink);
  background:var(--accent-soft);padding:3px 10px;border-radius:999px}
.sdsub{margin-bottom:10px}
.sdbody{min-height:120px;font-size:14px;line-height:1.6}
.sdrow{display:flex;align-items:center;gap:14px;flex-wrap:wrap;margin-top:12px}
.sdnote{font-size:11.5px;color:var(--muted);line-height:1.5;max-width:44ch}

/* The one line that tells a student whether they have to do anything. */
.stcall{border-radius:var(--radius);padding:14px 16px;margin-bottom:18px;
  font-family:var(--display);font-size:16px;font-weight:700;letter-spacing:-.015em;
  background:linear-gradient(135deg,var(--amber-soft),var(--amber-soft));border:1px solid var(--amber-line);color:var(--amber-ink)}
.stcall span{display:block;font-family:'Inter',sans-serif;font-size:12.5px;font-weight:450;
  color:#9a7328;margin-top:4px;line-height:1.5}
.stcall.calm{background:linear-gradient(135deg,#eefaf2,#e6f7ec);border-color:var(--green-line);color:var(--green-ink)}
.stcall.calm span{color:#4e8a68}

.stcards{display:grid;gap:10px}
.stsec{margin:26px 0 10px;font-size:12px;text-transform:uppercase;letter-spacing:.6px;
  color:var(--muted);font-weight:700}
.stsec span{color:#b9bcca}

.stcard{display:flex;flex-direction:column;text-align:left;font-family:inherit;cursor:pointer;
  background:var(--panel);border:1px solid var(--line);border-left:3px solid var(--line3);
  border-radius:var(--radius);padding:14px 16px;box-shadow:var(--shadow);
  transition:transform .13s,box-shadow .16s,border-color .16s}
.stcard:hover{transform:translateX(3px);box-shadow:var(--shadow-md)}
.stcard.you{border-left-color:var(--amber)}
.stcard.ok{border-left-color:var(--green)}
.stcard.us{border-left-color:var(--accent)}
.stcard.queue{border-left-color:var(--sky)}
.stcard.done{border-left-color:var(--line3);opacity:.82}
.schd{display:flex;align-items:center;gap:9px;flex-wrap:wrap}
.sno{font-family:var(--mono);font-size:11px;color:var(--muted)}
.sage{font-size:11px;color:var(--muted);margin-left:auto}
.ssubj{font-size:15px;font-weight:650;color:var(--ink);margin-top:9px;line-height:1.4}
.sline{font-size:12.5px;color:var(--ink2);margin-top:4px}
.sfoot{font-size:11px;color:var(--muted);margin-top:9px;padding-top:9px;
  border-top:1px solid var(--line2)}

/* Whose turn it is, said as a word. This replaces the internal status pill
   everywhere a student can see it. */
.sstate{display:inline-flex;align-items:center;gap:5px;padding:3px 11px;border-radius:999px;
  font-size:11px;font-weight:700;white-space:nowrap}
.sstate::before{content:"";width:6px;height:6px;border-radius:50%;background:currentColor;flex:none}
.sstate.you{background:var(--amber-soft);color:var(--amber-ink)}
.sstate.ok{background:var(--green-soft);color:var(--green-ink)}
.sstate.us{background:var(--accent-soft);color:var(--accent-ink)}
.sstate.queue{background:var(--sky-soft);color:var(--sky-ink)}
.sstate.done{background:var(--panel-3);color:var(--muted)}

.composer.student{margin-top:18px}
.composer.student .crow .hint{max-width:52ch;line-height:1.5}

.stclose{display:flex;align-items:center;gap:12px;flex-wrap:wrap;margin-top:18px;
  padding-top:16px;border-top:1px solid var(--line2)}
.stclose span{font-size:11.5px;color:var(--muted)}

/* ---------------------------------------------------- giving a rating

   Two verdicts and no stars. A five point scale asks a sixteen-year-old to
   grade a support reply, which nobody does consistently and which produces a
   number that cannot be acted on. "Did this solve it, yes or no" can be, and
   the reason box under a no is where the whole value of the ratings dashboard
   comes from -- so it is given room rather than tucked away. */

.ratebox{margin-top:20px;border-radius:var(--radius);padding:18px 18px 16px;
  background:linear-gradient(150deg,#f7f5ff,#f2f7ff);border:1px solid #ded9f7}
.rbq{font-family:var(--display);font-size:16px;font-weight:700;color:var(--ink);
  letter-spacing:-.015em;margin-bottom:13px}
.rbtns{display:flex;gap:11px;flex-wrap:wrap}
.rbtn{display:flex;align-items:center;gap:9px;font-family:inherit;font-size:13.5px;font-weight:650;
  cursor:pointer;background:var(--panel);border:1.5px solid var(--line);border-radius:13px;
  padding:12px 18px;color:var(--ink2);transition:.15s}
.rbtn .thumb{width:19px;height:19px;flex:none;transition:.15s}
.rbtn.up .thumb{fill:var(--muted)}
.rbtn.down .thumb{fill:var(--muted)}
.rbtn.up:hover,.rbtn.up.on{border-color:var(--green);background:var(--green-soft);color:var(--green-ink)}
.rbtn.up:hover .thumb,.rbtn.up.on .thumb{fill:var(--green)}
.rbtn.down:hover,.rbtn.down.on{border-color:var(--danger);background:var(--danger-soft);color:var(--danger)}
.rbtn.down:hover .thumb,.rbtn.down.on .thumb{fill:var(--danger)}
.rbtn.on{box-shadow:0 3px 12px rgba(23,22,43,.09)}
.rbhint{font-size:11.5px;color:var(--muted);margin-top:12px;line-height:1.5}
.rbwhy{margin-top:14px;animation:pop .22s ease}
.rbwhy textarea{min-height:76px;font-size:13.5px;line-height:1.55;resize:vertical}

.ratedone{display:flex;align-items:flex-start;gap:12px;margin-top:20px;padding:14px 16px;
  border-radius:var(--radius);border:1px solid var(--line)}
.ratedone .thumb{width:20px;height:20px;flex:none;margin-top:2px}
.ratedone.good{background:var(--green-soft);border-color:var(--green-line);color:var(--green-ink)}
.ratedone.good .thumb{fill:var(--green)}
.ratedone.bad{background:var(--danger-soft);border-color:var(--danger-line);color:var(--danger)}
.ratedone.bad .thumb{fill:var(--danger)}
.ratedone b{font-size:13px;font-weight:700}
.rq{font-size:12.5px;line-height:1.55;margin-top:5px;color:var(--ink2);font-style:italic}

@media(max-width:760px){
  .catgrid{grid-template-columns:repeat(2,1fr)}
}
@media(max-width:520px){
  .catgrid{grid-template-columns:1fr}
  .rbtn{flex:1;justify-content:center}
}

/* =========================================================================
   THE MENTOR PORTAL
   =========================================================================
   A mentor reads rather than works, so this is a reporting surface with one
   writing action on it: the comment only staff can see. */

/* Their turn is the mentor's cue -- the student they look after owes support an
   answer, and a word from the mentor is what unsticks it. So it is warm, where
   the admin's equivalent column is deliberately quiet. */
.waitnum{color:var(--amber-ink);font-weight:700}

.mtlist{display:grid;gap:8px}
.mtrow{display:flex;align-items:center;gap:14px;text-align:left;font-family:inherit;cursor:pointer;
  background:var(--panel);border:1px solid var(--line);border-left:3px solid var(--line3);
  border-radius:var(--radius-sm);padding:12px 14px;box-shadow:var(--shadow);
  transition:transform .12s,box-shadow .15s,border-color .15s}
.mtrow:hover{transform:translateX(3px);box-shadow:var(--shadow-md)}
.mtrow.you{border-left-color:var(--amber)}
.mtrow.us{border-left-color:var(--accent)}
.mtrow.queue{border-left-color:var(--sky)}
.mtrow.ok,.mtrow.done{border-left-color:var(--green)}
.mtstate{display:inline-flex;align-items:center;gap:5px;padding:3px 10px;border-radius:999px;
  font-size:10.5px;font-weight:700;white-space:nowrap;flex:none;min-width:104px;
  justify-content:center}
.mtstate::before{content:"";width:5px;height:5px;border-radius:50%;background:currentColor;flex:none}
.mtstate.you{background:var(--amber-soft);color:var(--amber-ink)}
.mtstate.ok,.mtstate.done{background:var(--green-soft);color:var(--green-ink)}
.mtstate.us{background:var(--accent-soft);color:var(--accent-ink)}
.mtstate.queue{background:var(--sky-soft);color:var(--sky-ink)}
.mtmid{display:flex;flex-direction:column;min-width:0;flex:1}
.mtsubj{font-size:13.5px;font-weight:600;color:var(--ink);white-space:nowrap;overflow:hidden;
  text-overflow:ellipsis}
.mtmeta{font-size:11.5px;color:var(--muted);margin-top:2px;white-space:nowrap;overflow:hidden;
  text-overflow:ellipsis}
.mtflags{display:flex;align-items:center;gap:8px;flex:none}
.mtv{display:flex;align-items:center}
.mtv .thumb{width:15px;height:15px}
.mtv.like .thumb{fill:var(--green)}
.mtv.dislike .thumb{fill:var(--danger)}
.mtnote{font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:.4px;
  color:var(--accent-ink);background:var(--accent-soft);padding:3px 8px;border-radius:999px}

.mcbox{margin-top:22px;background:var(--panel);border:1px solid var(--line);
  border-radius:var(--radius);box-shadow:var(--shadow);padding:16px 17px}
.mcbox h3{display:flex;align-items:center;gap:8px}
.mcbox h3 .ct{font-size:11px;font-weight:700;color:var(--accent-ink);background:var(--accent-soft);
  padding:2px 8px;border-radius:999px}
.mchint{font-size:11.5px;color:var(--muted);line-height:1.55;margin:0 0 13px}
.mclist{display:grid;gap:9px;margin-bottom:13px}
.mcitem{display:flex;gap:11px;padding:11px 12px;border-radius:var(--radius-sm);
  background:var(--note-soft);border:1px solid var(--note-line)}
.mcitem p{margin:4px 0 0;font-size:13px;line-height:1.55;color:var(--ink2)}
.mcwho{font-size:12px;font-weight:700;color:var(--amber-ink);display:flex;align-items:center;gap:8px}
.mcwho .when{font-weight:450;color:var(--muted);font-size:11px}
.mcbox textarea{min-height:84px;font-size:13.5px;line-height:1.55;resize:vertical}

/* Pickers -- the alternative to a dropdown when the whole list fits on screen.
   A <select> collapses five readable words into one, and hides the choice with
   consequences (what someone is allowed to do) behind the same click as the
   one without. */
.pickrow{display:flex;flex-wrap:wrap;gap:7px}
.pick{font-family:inherit;font-size:12px;font-weight:600;cursor:pointer;padding:6px 13px;
  border-radius:999px;border:1px solid var(--line);background:var(--panel);color:var(--ink2);
  transition:.13s}
.pick:hover{border-color:var(--accent2);background:var(--panel-2)}
.pick.on{background:var(--accent-soft);border-color:var(--accent);color:var(--accent-ink)}

.pickcards{display:grid;gap:8px}
.pickcard{display:flex;flex-direction:column;text-align:left;font-family:inherit;cursor:pointer;
  padding:11px 13px;border-radius:var(--radius-sm);border:1px solid var(--line);
  background:var(--panel);transition:.13s}
.pickcard:hover{border-color:var(--accent2);background:var(--panel-2)}
.pickcard.on{border-color:var(--accent);background:var(--accent-soft);box-shadow:var(--ring)}
.pickcard .pkn{font-size:13px;font-weight:700;color:var(--ink)}
.pickcard .pkd{font-size:11.5px;color:var(--muted);line-height:1.5;margin-top:3px}
.pickcard.on .pkd{color:var(--accent-ink)}

/* The gate note carries a headline and an explanation; without this they run
   together into one sentence that reads as a typo. */
.gate b{display:block;margin-bottom:3px}
.gate span{display:block;line-height:1.55}

/* A grid item will not shrink below its content unless told to, so the ticket
   rows pushed the page sideways on a phone. */
.mtrow{min-width:0}
@media(max-width:620px){
  /* Two lines instead of one: state and flags on top, what it is about
     underneath, where it gets the full width to be read. */
  .mtrow{flex-wrap:wrap;gap:9px}
  .mtstate{min-width:0}
  .mtflags{order:1;margin-left:auto}
  .mtmid{order:2;flex-basis:100%}
}

/* Two bands on the front door: the accounts that really sign in, and the two
   previews that never will. The distinction is load-bearing -- somebody who
   misses it walks away thinking students need provisioning -- so it is drawn
   with a heading and a solid/dashed edge rather than left to the wording. */
.pband{margin-bottom:22px}
.pbhd{margin-bottom:11px}
.pbhd h2{font-family:var(--display);font-size:12px;font-weight:700;letter-spacing:.7px;
  text-transform:uppercase;color:var(--muted);margin:0}
.pbhd p{font-size:12px;color:var(--muted);line-height:1.55;margin:5px 0 0;max-width:70ch}
.pband .pgrid{grid-template-columns:repeat(2,1fr)}
.prole.real{border-color:#d8d3f5}
.prole:not(.real){border-style:dashed;background:var(--panel-2)}
.prole:not(.real) .ptag{color:var(--muted)}
.prole.real .ptag{color:var(--accent-ink)}

.pprev{font-size:11.5px;color:var(--amber-ink);background:var(--amber-soft);
  border:1px solid var(--amber-line);border-radius:var(--radius-sm);padding:9px 12px;
  margin:0 0 12px;line-height:1.5}

@media(max-width:900px){
  .pband .pgrid{grid-template-columns:repeat(2,1fr)}
}
@media(max-width:560px){
  .pband .pgrid{grid-template-columns:1fr}
}

/* The student's verdict, where the 1-5 stars used to sit in the ticket header. */
.vpill{display:inline-flex;align-items:center;gap:6px;padding:3px 11px;border-radius:999px;
  font-size:11px;font-weight:700;white-space:nowrap}
.vpill .thumb{width:13px;height:13px}
.vpill.good{background:var(--green-soft);color:var(--green-ink)}
.vpill.good .thumb{fill:var(--green)}
.vpill.bad{background:var(--danger-soft);color:var(--danger)}
.vpill.bad .thumb{fill:var(--danger)}

/* A quiet action on a rail card heading -- the tag editor, and anything like it
   later. It sits on the baseline of the h3 rather than below it, so the card
   keeps its height. */
.card h3{display:flex;align-items:center;gap:8px}
.cardbtn{margin-left:auto;font-family:inherit;font-size:11px;font-weight:650;cursor:pointer;
  color:var(--accent-ink);background:var(--accent-soft);border:1px solid transparent;
  border-radius:999px;padding:3px 10px;transition:.13s}
.cardbtn:hover{border-color:var(--accent);background:#e7e3ff}

.taggrp{margin-bottom:14px}
.taggrp:last-child{margin-bottom:0}
.tgname{font-size:10.5px;font-weight:700;letter-spacing:.5px;text-transform:uppercase;
  color:var(--muted);margin-bottom:7px}

/* --- The row is the control ----------------------------------------------
   No button inside the cell. A button in a table asks you to aim at a small
   target inside a large one you were already pointing at -- the row you are
   reading is the row you want, so the whole row is clickable and says so:
   it lifts, its edge lights up, and an arrow appears at the end. */

.dname{font-size:13.5px;font-weight:650;color:var(--ink)}
.dname.quiet{color:var(--muted);font-weight:600}

tr.rowgo{cursor:pointer}
tr.rowgo td{transition:background .12s}
tr.rowgo:hover td{background:var(--tint)}
tr.rowgo:hover .dname{color:var(--accent-ink)}
tr.rowgo:active td{background:var(--tint2)}

/* The arrow lives in the last cell and only appears on the row you are
   pointing at, so five permanent arrows do not sit there adding noise. */
tr.rowgo td:last-child{position:relative;padding-right:26px}
tr.rowgo td:last-child::before{content:"\2192";position:absolute;right:8px;top:50%;
  transform:translateY(-50%) translateX(-3px);color:var(--accent);opacity:0;
  font-size:14px;transition:opacity .13s,transform .13s;pointer-events:none}
tr.rowgo:hover td:last-child::before{opacity:.9;transform:translateY(-50%) translateX(0)}

/* Only Ratings still opens in place, so only Ratings keeps the caret. The
   other three tables are read, not unfolded. */
table.tbl.grouped tbody tr td:first-child::before{content:none}
table.tbl.grouped.ratings tbody tr td:first-child::before{content:"\203A"}
table.tbl.grouped:not(.ratings) tbody tr td:first-child{padding-left:12px}
table.tbl.grouped tbody tr td:last-child::after{content:none}
table.tbl.grouped tbody tr.totalrow td:last-child::after{content:none}

/* The row highlight stays -- it helps the eye hold a line across seven columns
   -- but nothing else pretends the row itself is pressable. */
table.tbl.grouped:not(.ratings) tbody tr:hover td:first-child b{color:var(--ink)}


/* --- The theme switch ------------------------------------------------------
   Two states, remembered. It sits with the account details because that is
   where a preference belongs, not in a settings screen nobody opens. */
.themerow{display:flex;align-items:center;gap:8px;margin-top:10px}
.themebtn{flex:1;display:inline-flex;align-items:center;justify-content:center;gap:7px;
  font-family:inherit;font-size:12px;font-weight:600;cursor:pointer;
  padding:7px 10px;border-radius:9px;border:1px solid rgba(255,255,255,.16);
  background:rgba(255,255,255,.06);color:rgba(255,255,255,.82);transition:.13s}
.themebtn:hover{background:rgba(255,255,255,.13);color:#fff}
.themebtn svg{width:14px;height:14px;fill:currentColor}

/* Inputs and pills carry their own light-mode assumptions in a couple of
   places; these are the only per-theme touch-ups the sweep could not reach. */
:root[data-theme="dark"] .finput::placeholder{color:var(--muted)}
:root[data-theme="dark"] select.finput{
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%238c88ad' stroke-width='3'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E")}
:root[data-theme="dark"] .logo{box-shadow:0 2px 8px rgba(0,0,0,.4)}
:root[data-theme="dark"] .fbcard:hover{box-shadow:0 2px 10px rgba(0,0,0,.4)}

/* --- The history table ----------------------------------------------------
   The whole conversation as columns. A transcript makes you scroll to find out
   how a ticket went; side by side, the same exchange is one horizontal glance.
   Ours and theirs alternate, tinted differently, so which way a message went is
   read before any of it is. */

.viewswitch{display:inline-flex;margin-left:auto;background:var(--panel-3);
  border-radius:9px;padding:3px;gap:2px}
.vsbtn{font-family:inherit;font-size:12px;font-weight:600;cursor:pointer;
  padding:5px 12px;border-radius:7px;border:0;background:transparent;
  color:var(--muted);transition:.13s}
.vsbtn:hover{color:var(--ink2)}
.vsbtn.on{background:var(--panel);color:var(--accent-ink);box-shadow:var(--shadow)}

.histwrap{overflow-x:auto}
table.tbl.hist{width:100%;min-width:1080px;border-collapse:separate;border-spacing:0}
table.tbl.hist th{position:sticky;top:0;z-index:2;
  background:var(--panel-2);color:var(--ink2);font-weight:700;font-size:11px;
  letter-spacing:.5px;text-transform:uppercase;padding:11px 12px;text-align:left;
  border-bottom:1px solid var(--line)}
table.tbl.hist th.us{color:var(--accent-ink)}
table.tbl.hist th.them{color:var(--green-ink)}
table.tbl.hist td{padding:12px;vertical-align:top;border-bottom:1px solid var(--line2);
  font-size:12.5px;line-height:1.5}
table.tbl.hist tbody tr{cursor:pointer;transition:background .12s}
table.tbl.hist tbody tr:hover td{background:var(--tint)}

th.c-tkt,td.c-tkt{width:104px}
th.c-stu,td.c-stu{width:150px}
th.c-said,td.c-said{width:19%}
th.c-verdict,td.c-verdict{width:150px}

.hno{font-family:var(--mono);font-size:11px;font-weight:600;color:var(--muted);margin-bottom:5px}
.hage{font-size:11px;color:var(--muted);margin-top:5px}
.hstu{font-weight:700;color:var(--ink);font-size:13px}
.heps{font-family:var(--mono);font-size:10.5px;color:var(--muted);margin-top:1px}
.hcat{font-size:11.5px;color:var(--ink2);margin-top:5px}
.hdept{font-size:11px;color:var(--muted);margin-top:2px}

/* Four columns of prose need a ceiling, or one long message sets the height of
   the whole row and the table stops being scannable. */
.hsay{display:-webkit-box;-webkit-line-clamp:5;-webkit-box-orient:vertical;
  overflow:hidden;color:var(--ink)}
.hwho{font-size:10.5px;font-weight:650;margin-top:5px;letter-spacing:.2px}
td.c-said.us{background:var(--tint)}
td.c-said.us .hwho{color:var(--accent-ink)}
td.c-said.them .hwho{color:var(--green-ink)}
td.c-said.us.empty,td.c-said.them.empty{opacity:.55}
table.tbl.hist tbody tr:hover td.c-said.us{background:var(--tint2)}

.hv{display:inline-flex;align-items:center;gap:6px;font-size:11.5px;font-weight:700;
  padding:4px 9px;border-radius:7px}
.hv .thumb{width:12px;height:12px}
.hv.good{background:var(--green-soft);color:var(--green-ink)}
.hv.bad{background:var(--danger-soft);color:var(--danger-ink)}
.hv.none{background:var(--panel-3);color:var(--muted);font-weight:600}
.hvq{margin-top:7px;font-size:11.5px;font-style:italic;line-height:1.45;color:var(--ink2);
  display:-webkit-box;-webkit-line-clamp:4;-webkit-box-orient:vertical;overflow:hidden}

@media(max-width:900px){ .viewswitch{margin-left:0} }

/* The EPS id is a second fact, not part of the name. */
.tcstu .deps{margin-left:7px;font-family:var(--mono);font-size:11px;
  font-weight:400;color:var(--muted)}


/* Dark-mode touch-ups the token sweep could not reach: a few components carry
   their own light-mode assumptions in gradients and shadows. */
:root[data-theme="dark"] .logo{
  background:linear-gradient(140deg,#8f85d4,#6f66b8);
  box-shadow:0 2px 8px rgba(0,0,0,.4)}
:root[data-theme="dark"] .sidebar{
  background:linear-gradient(180deg,#15161b 0%,var(--sidebar) 100%)}
:root[data-theme="dark"] ::-webkit-scrollbar-thumb{background:var(--line3);background-clip:content-box}
:root[data-theme="dark"] ::-webkit-scrollbar-thumb:hover{background:var(--accent2);background-clip:content-box}
:root[data-theme="dark"] ::selection{background:rgba(155,144,224,.28)}
:root[data-theme="dark"] .stat{
  background:linear-gradient(180deg,var(--tint) 0%,var(--panel) 62%)}
:root[data-theme="dark"] .depttile{background:var(--panel-2)}
:root[data-theme="dark"] .depttile:hover{background:var(--accent-soft);
  box-shadow:0 2px 8px rgba(0,0,0,.45)}

/* --- Tag priority ----------------------------------------------------------
   Three weights, because a row of identical chips makes the reader weigh them
   all the same, which is the same as weighing none of them. High shouts, low
   recedes, normal sits where tags always sat. */

.tag.hi{background:var(--tagc,var(--accent));color:#fff;font-weight:700;
  box-shadow:0 1px 4px rgba(23,22,43,.18);padding:3px 11px}
.tag.mid{background:var(--accent-soft);color:var(--accent-ink)}
.tag.lo{background:transparent;color:var(--muted);border:1px dashed var(--line3);
  font-weight:500}
:root[data-theme="dark"] .tag.hi{box-shadow:0 1px 6px rgba(0,0,0,.45)}

/* The priority marker doubles as the control: click to cycle. Three states need
   a click, not a dropdown. */
.tprio{font-family:var(--mono);font-size:10px;font-weight:800;line-height:1;
  cursor:pointer;border:0;border-radius:5px;padding:2px 4px;margin-right:1px;
  background:rgba(255,255,255,.22);color:inherit;transition:.12s}
.tag.mid .tprio,.tag.lo .tprio{background:rgba(109,94,247,.14)}
.tprio:hover{background:rgba(255,255,255,.4)}
.tag.mid .tprio:hover,.tag.lo .tprio:hover{background:rgba(109,94,247,.28)}

/* --- Department tables, with some life in them -----------------------------
   Flat white, uniform grey, everything the same weight -- correct and dull.
   The fix is not decoration, it is hierarchy: the number you act on gets size
   and colour, the supporting figures step back, the header carries the accent,
   and the row you are pointing at is marked at its edge. */

.tblwrap.tight{background:var(--panel);border:1px solid var(--line);
  border-radius:var(--radius);box-shadow:var(--shadow);overflow:hidden}
.tblwrap.tight table.tbl.grouped{border-collapse:separate;border-spacing:0}

table.tbl.grouped thead tr{
  background:linear-gradient(180deg,var(--panel-2) 0%,var(--panel) 100%)}
table.tbl.grouped thead th{border-bottom:2px solid var(--accent-soft)}

/* The whole name cell is the target, not just the text inside it. */
table.tbl.grouped tbody td:first-child{padding:6px 8px!important}
.depttile{margin:0}

/* One number per row is the one you act on. It gets weight and colour and
   nothing else. Size is deliberately NOT part of the emphasis: two figures in
   the same row at two sizes stop being comparable at a glance, which is the
   only reason to put them in the same row. Same face, same size, same digit
   width -- bold is enough to say "this one". */
table.tbl.grouped td:nth-child(2) b{font-weight:700;color:var(--accent-ink)}
table.tbl.grouped td:nth-child(2) b.hotnum{color:var(--danger)}
table.tbl.grouped td:not(:first-child):not(:nth-child(2)){color:var(--ink2)}

/* Point at a row and its edge lights up, so the eye can hold a line across six
   columns without a zebra stripe shouting on every other row. */
table.tbl.grouped tbody tr td:first-child{position:relative}
table.tbl.grouped tbody tr td:first-child::after{content:"";position:absolute;
  left:0;top:6px;bottom:6px;width:3px;border-radius:0 3px 3px 0;
  background:transparent;transition:background .13s}
table.tbl.grouped tbody tr:hover td:first-child::after{background:var(--accent)}
table.tbl.grouped tbody tr:hover td{background:var(--tint)}

.totalrow td{background:var(--panel-2)!important;border-top:2px solid var(--line)}
.totalrow td:first-child::after{display:none!important}

/* The stat cards above the tables carry the same idea: the figure is the point. */
.stat .v{font-family:var(--display);letter-spacing:-.02em}
.stat{transition:border-color .13s,box-shadow .13s,transform .13s}
.stat:hover{border-color:var(--accent2);box-shadow:var(--shadow-md);transform:translateY(-1px)}

/* --- Grouped by type of issue ----------------------------------------------
   The tracker this replaces groups by type of issue with a count on each group,
   and that is the right unit: nobody scanning support thinks "ticket 1041",
   they think "how bad is admissions this week". */

.grouphd{display:flex;align-items:center;gap:10px;margin:22px 0 9px}
.grouphd:first-child{margin-top:0}
.gname{font-family:var(--display);font-size:14px;font-weight:700;color:var(--ink);
  background:var(--accent-soft);color:var(--accent-ink);
  padding:4px 12px;border-radius:8px;letter-spacing:-.01em}
.gcount{font-family:var(--mono);font-size:12px;font-weight:700;color:var(--muted)}
.grouphd::after{content:"";flex:1;height:1px;background:var(--line)}

th.c-note,td.c-note{width:150px}
.hnote{font-size:11.5px;line-height:1.45;color:var(--note-ink);
  background:var(--note-soft);border:1px dashed var(--note-line);
  border-radius:7px;padding:7px 9px;margin-bottom:6px}
.hnote:last-child{margin-bottom:0}
.hnhead{display:flex;align-items:baseline;justify-content:space-between;gap:6px;
  padding-bottom:4px;margin-bottom:5px;border-bottom:1px dashed var(--note-line)}
.hnwho{font-size:10.5px;font-weight:800;letter-spacing:.2px}
.hnwhen{font-size:9.5px;opacity:.7;white-space:nowrap}
.hnbody{font-size:11.5px}
.hncount{font-size:9.5px;font-weight:800;letter-spacing:.5px;text-transform:uppercase;
  color:var(--muted);margin-bottom:5px}

.hphone{display:block;font-family:var(--mono);font-size:11px;color:var(--accent-ink);
  margin-top:4px;text-decoration:none;border-bottom:1px solid transparent}
.hphone:hover{border-bottom-color:var(--accent2)}

.hby{margin-top:6px;font-size:10.5px;color:var(--muted);line-height:1.35}

table.tbl.hist{min-width:1240px}
th.c-said,td.c-said{width:16%}

/* --- The rank filter -------------------------------------------------------
   What the student made of the answer, as a filter. Counts on each so the
   shape of the week is visible before anything is clicked. */

.rankbar{display:flex;gap:8px;flex-wrap:wrap;margin-bottom:14px}
.rankbtn{display:inline-flex;align-items:center;gap:7px;font-family:inherit;
  font-size:12.5px;font-weight:650;cursor:pointer;padding:7px 13px;border-radius:999px;
  border:1px solid var(--line);background:var(--panel);color:var(--ink2);transition:.13s}
.rankbtn:hover{border-color:var(--accent2);color:var(--ink)}
.rankbtn .thumb{width:13px;height:13px}
.rankbtn .rn{font-family:var(--mono);font-size:11px;font-weight:700;opacity:.6}
.rankbtn.on{background:var(--accent);border-color:var(--accent);color:#fff}
.rankbtn.on .rn{opacity:.85}
.rankbtn.good.on{background:var(--green-ink);border-color:var(--green-ink);color:var(--panel)}
.rankbtn.bad.on{background:var(--danger-ink);border-color:var(--danger-ink);color:var(--panel)}
.rankbtn.good{color:var(--green-ink)}
.rankbtn.bad{color:var(--danger-ink)}

th.c-reason,td.c-reason{width:22%}
.hreason{font-style:italic;line-height:1.5;color:var(--ink)}

/* Type of issue reads as a label, not prose -- it is the column the old tracker
   is scanned by, so it gets a shape the eye can catch at speed. */
th.c-type,td.c-type{width:132px}
.typechip{display:inline-block;font-size:11.5px;font-weight:650;line-height:1.35;
  padding:4px 9px;border-radius:7px;background:var(--accent-soft);color:var(--accent-ink)}


/* --- The department picker -------------------------------------------------
   At the top with the title, because "show me one team" is the first cut
   anyone makes and it applies to every view on the screen. */
.deptpick{display:inline-flex;align-items:center;gap:10px;
  background:var(--accent-soft);border:1px solid var(--accent2);
  border-radius:12px;padding:6px 10px 6px 14px}
.deptpick .dplab{font-size:10.5px;font-weight:800;letter-spacing:.6px;
  text-transform:uppercase;color:var(--accent-ink)}
.deptpick select.finput{width:auto;min-width:200px;font-size:14px;font-weight:700;
  color:var(--ink);
  /* background-COLOR, not the shorthand: the shorthand resets background-repeat
     and background-position, which tiles the chevron across the whole control. */
  padding:9px 34px 9px 13px;background-color:var(--panel);
  border-color:var(--accent2);border-radius:9px}
.deptpick select.finput:hover{border-color:var(--accent);box-shadow:var(--ring)}
.deptpick select.finput:focus{box-shadow:var(--ring)}
@media(max-width:760px){
  .deptpick{width:100%;margin-top:8px}
  .deptpick select.finput{flex:1}
}


/* The student makes one choice: a department, or a sub-department under one.
   So the department leads and the sub-department qualifies it. A ticket with
   nothing underneath was sent to the department directly -- not a gap. */
.subdept{margin-top:5px;font-size:11px;color:var(--muted);line-height:1.35}

/* --- The two columns that carry the ticket ---------------------------------
   Issue description and Response are on every ticket. The clarifying question
   and the student's reply are on some -- worth reading when they happened, dead
   space when they did not. So the always-there pair gets the width and the
   sometimes-there pair folds away behind one control. */

th.c-said.lead,td.c-said.lead{width:23%}
th.c-said:not(.lead),td.c-said:not(.lead){width:14%}
table.tbl.hist th.lead{font-size:11.5px}

/* The control sits on the column it opens from, the way a spreadsheet collapses
   a group of columns: a small arrow in the header, pointing the way the hidden
   columns will appear. No separate switch to find. */
table.tbl.hist th.c-said.lead{position:relative;padding-right:30px}
.colx{position:absolute;right:6px;top:50%;transform:translateY(-50%);
  width:20px;height:20px;display:inline-flex;align-items:center;justify-content:center;
  font-family:inherit;font-size:15px;font-weight:800;line-height:1;cursor:pointer;
  border:1px solid var(--line3);border-radius:6px;background:var(--panel);
  color:var(--muted);transition:.13s;padding:0}
.colx:hover{border-color:var(--accent);background:var(--accent-soft);color:var(--accent-ink)}
.colx.on{border-color:var(--accent2);background:var(--accent-soft);color:var(--accent-ink)}

/* Mentor, and who finished it. All three are snapshots or facts that get asked
   about separately, so each is a column that can be scanned down rather than a
   caption tucked under something else. */
th.c-mentor,td.c-mentor{width:120px}
th.c-by,td.c-by{width:110px}
th.c-when,td.c-when{width:120px}
.hmentor{font-size:12.5px;font-weight:600;color:var(--ink2)}
.hbatch{font-family:var(--mono);font-size:10.5px;color:var(--muted);margin-top:3px}
.hby2{font-size:12.5px;font-weight:600;color:var(--accent-ink)}
.hwhen{font-size:11.5px;color:var(--ink2);line-height:1.4}
table.tbl.hist{min-width:1560px}

/* Two ways to read the same feedback: which team has a problem, and what
   exactly students said. Tabs rather than one screen trying to be both. */
/* These tabs switch between two whole dashboards, so they have to look like a
   control rather than a caption. The old version left the inactive half in
   --muted on a barely-tinted strip: it read as a disabled label, and people did
   not know a second dashboard was there at all. The selected tab is now solid,
   and the unselected one is dark enough to be read as an offer. */
.rtabs{display:inline-flex;gap:4px;background:var(--panel-3);
  border:1px solid var(--line);border-radius:11px;
  padding:4px;margin-bottom:18px}
.rtab{font-family:var(--display);font-size:13.5px;font-weight:700;cursor:pointer;
  padding:8px 18px;border-radius:8px;border:0;background:transparent;
  color:var(--ink2);letter-spacing:-.01em;transition:.14s}
.rtab:hover{background:var(--panel);color:var(--ink)}
.rtab.on{background:var(--accent);color:#fff;
  box-shadow:0 1px 4px rgba(0,0,0,.22)}
.rtab.on:hover{background:var(--accent);color:#fff}
.rtab:focus-visible{outline:2px solid var(--accent);outline-offset:2px}

/* --- Overview: four tables, one shape --------------------------------------
   Rows down the side, states across the top, totals always last. Once you can
   read one you can read all four, which is the point of not letting each table
   invent its own arrangement. */

.ovhd{display:flex;align-items:baseline;gap:11px;margin:26px 0 10px}
.ovhd:first-of-type{margin-top:4px}
.ovname{font-family:var(--display);font-size:15px;font-weight:700;color:var(--ink);
  letter-spacing:-.01em}
.ovnote{font-size:12px;color:var(--muted)}
.ovhd::after{content:"";flex:1;height:1px;background:var(--line)}

table.tbl.grouped.ov{table-layout:auto}
/* Date wise: department names wrap onto two lines rather than being cut short,
   so "Concern to Ajas Sir" reads as a name and not as "Concern t...". */
table.tbl.grouped.ov.wraph th{white-space:normal;overflow:visible;text-overflow:clip;
  vertical-align:bottom;line-height:1.25;max-width:110px;min-width:70px}
table.tbl.grouped.ov td:first-child,
table.tbl.grouped.ov th:first-child{width:auto;min-width:150px}
table.tbl.grouped.ov th:not(:first-child),
table.tbl.grouped.ov td:not(:first-child){width:auto;text-align:right}
/* Table 1 has one row and it is the answer, so it is allowed to be loud. */
.ovbig{font-family:var(--display);font-size:19px;font-weight:700;color:var(--accent-ink)}
table.tbl.grouped.ov .totalrow .ovbig{color:var(--accent-ink)}

/* --- Overview drill-down ---------------------------------------------------
   Three of the four sheets are the same question at three zoom levels, so the
   table drills rather than the screen changing. The breadcrumb is what stops
   that being disorienting: it says where you are and takes you back. */

.crumb{display:flex;align-items:center;gap:11px;margin:18px 0 4px}
.crumbb{font-family:inherit;font-size:12.5px;font-weight:600;cursor:pointer;
  padding:6px 12px;border-radius:8px;border:1px solid var(--line);
  background:var(--panel);color:var(--ink2);transition:.13s}
.crumbb:hover{border-color:var(--accent2);color:var(--accent-ink)}
.crumbnow{font-family:var(--display);font-size:14px;font-weight:700;color:var(--ink)}

/* A count you can click. It has to read as pressable without turning the grid
   into a wall of buttons, so it is bare until you point at it. */
.cellgo{font-family:var(--mono);font-size:13px;font-weight:600;cursor:pointer;
  border:1px solid transparent;border-radius:6px;padding:2px 9px;
  background:transparent;color:var(--ink2);transition:.12s}
.cellgo:hover{background:var(--accent-soft);border-color:var(--accent2);
  color:var(--accent-ink)}
.cellgo.hot{color:var(--danger);font-weight:700}
.cellgo.hot:hover{background:var(--danger-soft);border-color:var(--danger-line);
  color:var(--danger-ink)}

.topbar .deptpick + .deptpick{margin-left:10px}

/* Liked +1, disliked -1: one number that says which way a department leans,
   which two raw counts do not tell you at a glance. */
.avgv{font-family:var(--mono);font-size:13.5px;font-weight:700;
  padding:3px 10px;border-radius:7px;display:inline-block;min-width:56px;text-align:right}
.avgv.good{background:var(--green-soft);color:var(--green-ink)}
.avgv.bad{background:var(--danger-soft);color:var(--danger-ink)}
.avgv.mid{background:var(--panel-3);color:var(--ink2)}

/* A count that opens its own side of the feedback. */
button.cnum.go{cursor:pointer;border:1px solid transparent;font-family:var(--mono);
  transition:.12s}
button.cnum.go:hover{border-color:currentColor;transform:translateY(-1px)}
button.cnum.go:active{transform:translateY(0)}

/* The Ratings rows carry their own arrow on the tile now, so the leftover
   disclosure caret from the old expand-in-place behaviour has to go -- two
   arrows on one cell reads as a glitch, which it was. */
table.tbl.grouped.ratings tbody tr td:first-child::before{content:none}
table.tbl.grouped.ratings tbody td:first-child{padding:6px 8px}
table.tbl.grouped.ratings .depttile{width:100%;justify-content:space-between}

/* --- Trending --------------------------------------------------------------
   An outage looks like twenty ordinary tickets until you stack them. The count
   leads, the reason it was flagged sits right beside it in words somebody can
   argue with, and the tickets themselves are underneath so the claim can be
   checked in one glance rather than taken on trust. */

.trend{background:var(--panel);border:1px solid var(--line);
  border-left:3px solid var(--amber);border-radius:var(--radius);
  padding:16px 18px 14px;margin-bottom:12px;box-shadow:var(--shadow)}
.trend.loud{border-left-color:var(--danger);box-shadow:var(--shadow-md)}

.trendhd{display:flex;align-items:center;gap:14px;flex-wrap:wrap}
.trendn{font-family:var(--display);font-size:30px;font-weight:700;line-height:1;
  color:var(--amber-ink);min-width:44px;text-align:center}
.trend.loud .trendn{color:var(--danger)}
.trendp{font-family:var(--display);font-size:17px;font-weight:700;color:var(--ink);
  letter-spacing:-.01em}
.trendwhy{font-size:12px;color:var(--muted);margin-top:3px}
.trenddepts{display:flex;gap:7px;flex-wrap:wrap}
.tdept{font-size:11.5px;font-weight:600;color:var(--ink2);background:var(--panel-3);
  border-radius:7px;padding:4px 10px}
.tdept b{color:var(--accent-ink)}

.trendalso{margin-top:11px;font-size:11.5px;color:var(--muted)}
.alsop{display:inline-block;font-family:var(--mono);font-size:11px;
  background:var(--panel-3);border-radius:5px;padding:2px 7px;margin:0 4px 4px 0;
  color:var(--ink2)}

.trendlist{margin-top:12px;padding-top:11px;border-top:1px solid var(--line2)}
.trow{display:flex;align-items:center;gap:11px;padding:7px 9px;border-radius:8px;
  cursor:pointer;font-size:12.5px;transition:background .12s}
.trow:hover{background:var(--tint)}
.trno{font-family:var(--mono);font-size:11px;color:var(--muted);flex:none}
.trstu{font-weight:650;color:var(--ink);flex:none;min-width:130px}
.trtext{flex:1;color:var(--ink2);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.trwhen{font-size:11px;color:var(--muted);flex:none}
.trmore{font-size:11.5px;color:var(--muted);padding:6px 9px}

/* A quiet hour should look deliberately quiet, not like a broken screen. */
.calm{background:var(--green-soft);border:1px solid var(--green-line);
  border-radius:var(--radius);padding:22px 24px}
.calmh{font-family:var(--display);font-size:17px;font-weight:700;color:var(--green-ink)}
.calmb{font-size:13px;color:var(--ink2);margin-top:6px;line-height:1.6;max-width:640px}

@media(max-width:760px){
  .trow{flex-wrap:wrap;gap:6px}
  .trstu,.trtext{min-width:0;white-space:normal}
}

/* A real date range rather than preset buckets: support gets asked about
   specific stretches of time, and a dropdown of fixed periods cannot answer
   those. Opens on the last month, then gets out of the way. */
.deptpick.daterange{gap:8px;flex-wrap:wrap}
.deptpick.daterange input[type=date]{width:auto;min-width:0;font-size:13px;
  font-weight:600;padding:8px 10px;background-color:var(--panel);
  border-color:var(--accent2);border-radius:9px;color:var(--ink);
  font-family:inherit;color-scheme:dark}
:root[data-theme="light"] .deptpick.daterange input[type=date]{color-scheme:light}
.deptpick.daterange .dplab{white-space:nowrap}
.deptpick.daterange .btn{padding:6px 11px}


/* ------------------------------------------------- priority, as a control

   A tag can raise a ticket's priority automatically, and a rule that acts on
   its own needs a visible way to be told it was wrong. So the pill that
   reports the priority is the button that changes it -- there is no second
   control to find, and the thing you want to correct is the thing you click. */
.priobtn{background:none;border:0;padding:0;margin:0;cursor:pointer;
  border-radius:999px;line-height:0;transition:box-shadow .14s,transform .14s}
.priobtn:hover{box-shadow:0 0 0 3px var(--accent-soft);transform:translateY(-1px)}
.priobtn:focus-visible{outline:2px solid var(--accent);outline-offset:2px}

.priopick{display:grid;gap:8px;margin-top:14px}
.ppick{display:flex;align-items:center;gap:12px;width:100%;text-align:left;
  padding:11px 13px;border-radius:10px;cursor:pointer;
  background:var(--panel-2);border:1px solid var(--line);transition:.14s}
.ppick:hover{border-color:var(--accent);background:var(--accent-soft)}
.ppick.on{border-color:var(--accent);box-shadow:inset 3px 0 0 var(--accent)}
.ppwhy{color:var(--muted);font-size:12.5px}

/* A tag that carries priority says so where tags are picked, so nobody is
   surprised by the ticket changing underneath them. */
.pick.hi{border-color:var(--danger)}
.pickbang{display:inline-flex;align-items:center;justify-content:center;
  width:15px;height:15px;margin-right:6px;border-radius:5px;
  background:var(--danger);color:#fff;font-size:10px;font-weight:800}

/* The one answer that is always the same answer, kept out of the agent's
   hands so it cannot come out curt on a bad day. */
.canned{display:flex;align-items:center;gap:10px;flex-wrap:wrap;
  padding:0 14px 10px}
.cannedbtn{padding:5px 11px;border-radius:999px;cursor:pointer;font-size:12px;
  font-weight:600;color:var(--accent-ink);background:var(--accent-soft);
  border:1px solid transparent;transition:.14s}
.cannedbtn:hover{border-color:var(--accent)}


/* =====================================================================
   THE CONTROL BAR

   Two native form controls used to sit loose in the header -- a browser date
   input and a browser select. Both are fine mechanically and wrong here: the
   select hid the department list behind a click, when the list is six items
   long and is itself something people want to read; and two bare date fields
   made every common question ("last week") a typing job.

   So: one recessed bar under the title, holding both controls with their names
   beside them. Presets and exact dates in the same row, because they answer the
   same question at different resolutions and the preset lights up on its own
   when the dates happen to match it. Departments as chips, because a set of
   six mutually exclusive choices is a set of buttons, not a menu.
   ===================================================================== */

.ctrlbar{
  background:var(--panel-2);
  border:1px solid var(--line);
  border-radius:var(--radius);
  padding:4px 16px;
  margin:0 0 20px;
  box-shadow:var(--shadow);
}
.ctrlrow{
  display:flex;align-items:center;gap:14px;flex-wrap:wrap;
  padding:11px 0;
}
.ctrlrow + .ctrlrow{border-top:1px solid var(--line2)}

.ctrlkey{
  font-size:10.5px;font-weight:800;letter-spacing:.7px;text-transform:uppercase;
  color:var(--muted);min-width:78px;
}

/* --- the period, as one list --- */
/* ONE DROPDOWN, everywhere. Same face, same height and same caret as the tab
   pills beside it, and no caption: a control whose current value names its own
   subject does not need "WINDOW" written next to it. */
.selwrap{position:relative;display:inline-flex}
.selwrap::after{
  content:'';position:absolute;right:12px;top:50%;width:7px;height:7px;
  margin-top:-5px;pointer-events:none;
  border-right:2px solid var(--muted);border-bottom:2px solid var(--muted);
  transform:rotate(45deg);
}
.sel{
  appearance:none;-webkit-appearance:none;
  padding:8px 34px 8px 17px;border-radius:999px;cursor:pointer;
  font-family:var(--display);font-size:13px;font-weight:600;
  letter-spacing:-.01em;color:var(--ink2);
  background-color:var(--panel);border:1px solid var(--line);
  transition:.14s;
}
.sel:hover{color:var(--ink)}
.sel:hover{border-color:var(--accent)}
.sel:focus{outline:none;border-color:var(--accent);box-shadow:var(--ring)}

/* --- the exact dates, as one joined field --- */
.dates{
  display:inline-flex;align-items:center;gap:0;
  background:var(--panel);border:1px solid var(--line);
  border-radius:10px;overflow:hidden;transition:.14s;
}
.dates:focus-within{border-color:var(--accent);box-shadow:var(--ring)}
.dinput{
  border:0;background:transparent;color:var(--ink);
  font-family:var(--mono);font-size:12.5px;font-weight:600;
  padding:7px 10px;width:auto;min-width:0;
  font-variant-numeric:tabular-nums;
}
.dinput:focus{outline:none}
.dsep{
  font-size:11px;color:var(--muted);padding:0 2px;
  align-self:center;
}
:root[data-theme="dark"] .dinput{color-scheme:dark}
:root[data-theme="light"] .dinput{color-scheme:light}
.dinput::-webkit-calendar-picker-indicator{
  filter:opacity(.5);cursor:pointer;transition:.14s}
.dinput::-webkit-calendar-picker-indicator:hover{filter:opacity(1)}

.ctrlnote{
  font-size:11.5px;color:var(--muted);font-weight:600;
  padding:4px 9px;border-radius:999px;background:var(--panel);
  border:1px solid var(--line2);white-space:nowrap;
}

/* --- departments, visible without opening anything --- */
.chips{display:flex;align-items:center;gap:6px;flex-wrap:wrap}
.chip{
  padding:6px 13px;border-radius:999px;cursor:pointer;
  font-size:12.5px;font-weight:600;white-space:nowrap;
  color:var(--ink2);background:var(--panel);
  border:1px solid var(--line);transition:.14s;
}
.chip:hover{border-color:var(--accent);color:var(--ink)}
.chip.on{
  background:var(--accent);border-color:var(--accent);color:#fff;
  box-shadow:0 1px 3px rgba(0,0,0,.18);
}

@media (max-width:900px){
  .ctrlkey{min-width:0;width:100%}
  .ctrlrow{gap:10px}
}

/* =====================================================================
   THE TRENDING STRIP

   The only thing on the Overview that does not obey the date range, because a
   spike is happening now and the range is usually a month. It renders only
   when something is actually spiking -- an alert that is always on screen is
   not an alert, it is furniture, and people stop reading furniture.
   ===================================================================== */

.trendstrip{
  display:flex;align-items:center;gap:14px;
  padding:13px 16px;margin:0 0 20px;cursor:pointer;
  border-radius:var(--radius);
  background:linear-gradient(120deg,var(--danger-soft) 0%,var(--panel-2) 70%);
  border:1px solid var(--danger-line);
  box-shadow:var(--shadow);transition:.16s;
}
.trendstrip:hover{border-color:var(--danger);box-shadow:var(--shadow-md)}
.trendstrip:focus-visible{outline:2px solid var(--danger);outline-offset:2px}

.tspulse{flex:none;width:11px;height:11px;position:relative}
.tspulse span{
  position:absolute;inset:0;border-radius:50%;background:var(--danger);
  box-shadow:0 0 0 0 var(--danger);animation:tspulse 2s infinite;
}
@keyframes tspulse{
  0%{box-shadow:0 0 0 0 rgba(225,29,72,.5)}
  70%{box-shadow:0 0 0 9px rgba(225,29,72,0)}
  100%{box-shadow:0 0 0 0 rgba(225,29,72,0)}
}
@media (prefers-reduced-motion:reduce){ .tspulse span{animation:none} }

.tsbody{flex:1;min-width:0}
.tshead{
  font-family:var(--display);font-size:13px;font-weight:700;
  color:var(--danger-ink);letter-spacing:-.01em;
}
.tsrow{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-top:5px}
.tsitem{
  display:inline-flex;align-items:center;gap:7px;
  padding:3px 4px 3px 10px;border-radius:999px;
  background:var(--panel);border:1px solid var(--line);
}
.tsitem b{font-size:12.5px;color:var(--ink);font-weight:650}
.tsn{
  min-width:19px;height:19px;padding:0 5px;border-radius:999px;
  display:inline-flex;align-items:center;justify-content:center;
  background:var(--danger);color:#fff;
  font-family:var(--mono);font-size:11px;font-weight:700;
}
.tsmore{font-size:11.5px;color:var(--muted);font-weight:600}
.tsgo{
  flex:none;font-size:12px;font-weight:700;color:var(--danger-ink);
  white-space:nowrap;
}
@media (max-width:760px){ .tsgo{display:none} }


/* =====================================================================
   ONE COLOUR PER STATE

   Every table, tile and bar on the Overview draws its states from this one
   list. That is what makes the screen readable as a picture: the same green
   always means finished, the same amber always means nobody has picked it up.
   Before this the whole screen was a single shade of violet, so the only way
   to read a table was to read all of it.
   ===================================================================== */

.snew{--st:var(--amber)}
.sopen{--st:var(--accent)}
.swait{--st:var(--sky)}
.sdone{--st:var(--green)}
.scanc{--st:var(--muted)}
.ssugg{--st:var(--note-ink)}

/* --------------------------------------------------------- the total, as tiles

   It used to be a one-row table carrying the same seven columns as the table
   directly beneath it, so the eye read the same thing twice and trusted neither.
   A summary should not be shaped like the detail it summarises. */

.kpis{
  display:grid;gap:10px;margin-bottom:24px;
  grid-template-columns:repeat(auto-fit,minmax(148px,1fr));
}
.kpi{
  position:relative;overflow:hidden;
  padding:14px 15px 13px;border-radius:var(--radius);
  background:var(--panel);border:1px solid var(--line);
  box-shadow:var(--shadow);cursor:pointer;transition:.15s;
}
.kpi::before{
  content:'';position:absolute;left:0;top:0;bottom:0;width:3px;
  background:var(--st,var(--accent));
}
.kpi:hover{transform:translateY(-2px);box-shadow:var(--shadow-md);
  border-color:var(--st,var(--accent))}
.kpi.zero{opacity:.55;box-shadow:none}
.kpi.zero:hover{opacity:1}

.kn{
  font-family:var(--display);font-size:30px;font-weight:700;
  color:var(--ink);line-height:1;letter-spacing:-.03em;
  font-variant-numeric:tabular-nums;
}
.kl{
  margin-top:7px;font-size:12px;font-weight:700;
  color:var(--st,var(--ink2));letter-spacing:-.01em;
}
.kp{margin-top:2px;font-size:11px;color:var(--muted);font-weight:600}

/* The "everything" tile spans two and carries the whole split as one bar. */
.kpi.all{grid-column:span 2;--st:var(--ink2)}
.kpi.all .kn{font-size:38px}
.kpi.all .kl{color:var(--ink2)}
@media (max-width:620px){ .kpi.all{grid-column:span 1} .kpi.all .kn{font-size:30px} }

/* Cells are tinted in their column's colour, at a strength set by how large the
   number is against the biggest in that table -- so the eye finds where the
   work has piled up before reading a single figure. The proportion bar that
   used to sit beside them is gone: two ways of saying the same thing in one
   row was one too many, and the bar was the one you had to learn to read. */

table.tbl.grouped td.h1,
table.tbl.grouped td:nth-child(2).h1{background:color-mix(in srgb,var(--st) 9%,transparent)}
table.tbl.grouped td.h2,
table.tbl.grouped td:nth-child(2).h2{background:color-mix(in srgb,var(--st) 19%,transparent)}
table.tbl.grouped td.h3,
table.tbl.grouped td:nth-child(2).h3{background:color-mix(in srgb,var(--st) 32%,transparent)}
table.tbl.grouped td.h3{font-weight:700;color:var(--ink)}
table.tbl.grouped tbody tr:hover td.h1{background:color-mix(in srgb,var(--st) 15%,transparent)}
table.tbl.grouped tbody tr:hover td.h2{background:color-mix(in srgb,var(--st) 25%,transparent)}
table.tbl.grouped tbody tr:hover td.h3{background:color-mix(in srgb,var(--st) 38%,transparent)}

/* Column headers name their colour, so the tiles and the table read as one
   vocabulary rather than two. */
table.tbl.grouped th .sdot{
  display:inline-block;width:7px;height:7px;border-radius:2px;
  background:var(--st);margin-right:7px;vertical-align:middle}

table.tbl.grouped.ov th:nth-child(2),
table.tbl.grouped.ov td:nth-child(2):not(.h1):not(.h2):not(.h3){background:transparent}
table.tbl.grouped.ov tr:hover td:nth-child(2):not(.h1):not(.h2):not(.h3){background:transparent}
table.tbl.grouped.ov td:nth-child(2) b{color:inherit;font-weight:700}
table.tbl.grouped.ov td:not(:first-child):not(:nth-child(2)){color:inherit}

/* --------------------------------------------------- reply time, per ticket

   Opened from a department on the Time screen. Slowest at the top, because the
   reason to open it is to find what went wrong -- and a table that leads with
   the fastest replies makes you scroll past the good news to reach it. */

table.tbl.grouped.rt td:not(:first-child),
table.tbl.grouped.rt td:not(:first-child) b,
table.tbl.grouped.rt td:not(:first-child) span{
  font-family:var(--mono);font-variant-numeric:tabular-nums;font-size:13px}
table.tbl.grouped.rt td:nth-child(2){font-family:var(--display);font-size:13px}
table.tbl.grouped.rt th:nth-child(2),
table.tbl.grouped.rt td:nth-child(2){background:transparent}
table.tbl.grouped.rt td:nth-child(5){text-align:right}
table.tbl.grouped.rt th:nth-child(5){text-align:right}
table.tbl.grouped.rt td.slow{background:color-mix(in srgb,var(--danger) 12%,transparent)}
table.tbl.grouped.rt td.slow b{color:var(--danger-ink)}
.never{font-family:var(--display)!important;font-size:12px!important;
  color:var(--danger-ink);font-weight:700}
table.tbl.grouped.rt td:last-child{text-align:right}


/* The template is now every dashboard's, so the pieces it needs are no longer
   scoped to the Overview. A tinted cell without a state class simply gets no
   tint -- color-mix on an undefined --st drops the declaration -- which is what
   makes it safe to apply the classes anywhere. */
.sbad{--st:var(--danger)}
table.tbl.grouped th .thsub{display:block;font-weight:500;font-size:10.5px;
  color:var(--muted);margin-top:2px}
/* A tinted cell holding a button (the ageing grid) must not paint over it. */
table.tbl.grouped td.h1 .cellgo,
table.tbl.grouped td.h2 .cellgo,
table.tbl.grouped td.h3 .cellgo{background:transparent;border-color:transparent}


/* ------------------------------------------------------------- settings

   The same block the hiring console uses, so somebody who runs both is not
   learning two layouts. One line of purpose under each name, because "Class
   mapping" tells an admin what the screen is called and not what it decides. */

/* Settings: the sections in their own column beside the app's sidebar, and the settings of the
   open one as rows. The left column is the whole map, so nothing is hidden and there is no need
   for a way back - the menu never went anywhere. */
.setwrap{display:flex;gap:26px;align-items:flex-start;margin-top:14px}
.setnav{flex:none;width:224px;position:sticky;top:8px;align-self:flex-start;
  background:var(--panel);border:1px solid var(--line);border-radius:var(--radius);padding:8px;box-shadow:var(--shadow-md)}
.setnavt{font-size:11px;font-weight:700;letter-spacing:.07em;text-transform:uppercase;color:var(--muted);padding:6px 10px 8px}
.setnavi{display:block;width:100%;text-align:left;padding:9px 11px;border-radius:var(--radius-sm);border:1px solid transparent;
  background:transparent;cursor:pointer;font-size:13.5px;font-weight:600;color:var(--ink2);margin-bottom:1px;
  transition:background .12s ease,color .12s ease}
.setnavi:hover{background:var(--panel-2)}
.setnavi.on{background:var(--accent-soft);color:var(--accent-ink)}
.setpane{flex:1;min-width:0;max-width:720px}
.setpane h3{margin:0 0 2px;font-size:17px;color:var(--ink)}
.setpane .psub{font-size:12.5px;color:var(--muted);margin-bottom:12px}
.setrow{display:flex;align-items:center;gap:16px;padding:13px 10px;border-bottom:1px solid var(--line);
  border-radius:var(--radius-sm);cursor:pointer;transition:background .12s ease}
.setrow:hover{background:var(--panel-2)}
.setrow:last-child{border-bottom:none}
.setrow:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.setrow .rtxt{flex:1;min-width:0}
.setrow .rnm{font-weight:650;color:var(--ink);font-size:14px}
.setrow .rds{font-size:12.5px;color:var(--muted);margin-top:2px;line-height:1.45}
/* It points rather than speaks, and stays grey until you are on the row, so a column of them
   does not read as a column of anything. */
.setrow .rgo{flex:none;color:var(--line3);font-size:19px;line-height:1;transition:color .12s ease}
.setrow:hover .rgo{color:var(--accent)}
@media(max-width:860px){
  .setwrap{flex-direction:column;gap:14px}
  .setnav{width:100%;position:static;display:flex;flex-wrap:wrap;gap:6px}
  .setnavi{width:auto;margin:0;border-color:var(--line);background:var(--panel)}
  .setnavt{display:none}
}
.setgrid{display:grid;grid-template-columns:repeat(auto-fill,minmax(210px,1fr));
  gap:14px;max-width:900px;margin-top:16px}
.setcard{display:flex;flex-direction:column;gap:11px;padding:18px;
  border:1px solid var(--line);border-radius:16px;background:var(--panel);
  cursor:pointer;box-shadow:var(--shadow);
  transition:transform .15s ease,box-shadow .15s ease,border-color .15s ease}
.setcard:hover{transform:translateY(-3px);box-shadow:var(--shadow-md);
  border-color:var(--accent)}
.setcard:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.seticon{width:44px;height:44px;border-radius:13px;background:var(--accent-soft);
  color:var(--accent-ink);display:flex;align-items:center;justify-content:center}
.setname{font-family:var(--display);font-weight:700;color:var(--ink);font-size:14.5px;
  letter-spacing:-.01em}
.setwhy{font-size:12px;color:var(--muted);line-height:1.45;margin-top:-4px}
.setwhy b{color:var(--ink2)}
.setcard.theme .seticon{background:var(--note-soft);color:var(--note-ink)}


/* --------------------------------------------------------------- tags admin

   Grouped by what the priority DOES, because that was the question the screen
   could not answer. The old layout grouped by tag group and hid the priority in
   a "!!" badge -- so the one behaviour on the page was invisible, and there was
   no way at all to set it while creating a tag. */

.tlvl{border:1px solid var(--line);border-radius:var(--radius);background:var(--panel);
  box-shadow:var(--shadow);padding:16px 18px;margin-bottom:14px;
  border-left:3px solid var(--line3)}
.tlvl.p2{border-left-color:var(--danger)}
.tlvl.p1{border-left-color:var(--accent)}
.tlvl.p0{border-left-color:var(--muted)}

.tlvlhd{display:flex;align-items:center;gap:9px}
.tlvlhd .btn.sm{padding:5px 11px;font-size:12px}
.tlvlname{font-family:var(--display);font-size:14.5px;font-weight:700;color:var(--ink);
  letter-spacing:-.01em}
.tlvln{min-width:21px;height:21px;padding:0 6px;border-radius:999px;
  display:inline-flex;align-items:center;justify-content:center;
  background:var(--panel-3);color:var(--ink2);
  font-family:var(--mono);font-size:11.5px;font-weight:700}
.tlvl.p2 .tlvln{background:var(--danger-soft);color:var(--danger-ink)}
.tlvlwhy{font-size:12.5px;color:var(--muted);line-height:1.5;margin:5px 0 12px;max-width:70ch}

.tlist{display:flex;flex-direction:column;gap:2px}
.trow{display:flex;align-items:center;gap:11px;padding:7px 4px;
  border-top:1px solid var(--line2)}
.trow:first-child{border-top:0}
.tgrp{font-size:11.5px;color:var(--muted)}
.tnone{padding:4px}
.btn.tdanger:hover{color:var(--danger);border-color:var(--danger)}
.trow .btn.sm{padding:4px 10px;font-size:11.5px}

.tspask{margin-top:14px;padding:12px 14px;border-radius:11px;
  background:var(--amber-soft);border:1px solid var(--amber-line);
  font-size:13px;color:var(--ink2)}

/* Said where the mistake is, not on the dashboard where its effect shows up. */
.warnline{display:block;margin-top:5px;font-size:11.5px;line-height:1.4;
  color:var(--amber-ink);font-weight:600}
.okline{display:block;margin-top:5px;font-size:11.5px;color:var(--green-ink);font-weight:600}


/* ------------------------------------------- what keeps coming up

   A share bar rather than a second number: the count is the fact, the bar is
   how it compares to the biggest theme without doing the division yourself. */
table.tbl.grouped.recur td{vertical-align:middle}
table.tbl.grouped.recur th:nth-child(2),
table.tbl.grouped.recur td:nth-child(2){background:transparent;width:90px}
table.tbl.grouped.recur td:nth-child(2) b{color:var(--accent-ink);font-weight:700}
.sharebar{display:inline-block;width:110px;height:7px;border-radius:99px;
  background:var(--line2);overflow:hidden;vertical-align:middle;margin-right:9px}
.sharebar i{display:block;height:100%;background:var(--accent);border-radius:99px}
.sharepc{font-family:var(--mono);font-size:12px;color:var(--muted)}
table.tbl.grouped.recur td:first-child b{font-family:var(--display)}


/* ------------------------------------------------- what the form sent

   A flat list of everything that arrived, read as a block. Two of the rows are
   paragraphs rather than values, so they break onto their own line instead of
   being squeezed into a narrow right-hand column and wrapping to six lines. */
.formcard .frow.tall{display:block}
.formcard .frow.tall .k{display:block;margin-bottom:4px}
.formcard .frow.tall .v{display:block;text-align:left;white-space:pre-wrap;
  line-height:1.5;color:var(--ink2)}
.formcard .frow{align-items:flex-start}
.formcard .frow .v{word-break:break-word}

/* A link inside a student's message. Escaped first, linked after -- so the
   colour marks something you can act on, never something they could inject. */
.msglink{color:var(--accent-ink);text-decoration:underline;word-break:break-all}
.msglink:hover{color:var(--accent)}


/* ------------------------------------------------------ attachments

   Shown, not linked. On a technical complaint the screenshot IS the diagnosis,
   and a link makes an agent leave the page to find that out -- which in
   practice means they often do not. Capped in height so a tall screenshot
   cannot push the rest of the rail off the screen. */
.attcard .attshot{display:block;margin-bottom:9px;border-radius:11px;
  overflow:hidden;border:1px solid var(--line);background:var(--panel-2);
  transition:border-color .14s,transform .14s}
.attcard .attshot:hover{border-color:var(--accent);transform:translateY(-1px)}
.attcard .attshot img{display:block;width:100%;max-height:320px;
  object-fit:contain;background:var(--panel-3)}
.attcard .attvid{display:block;width:100%;max-height:320px;margin-bottom:9px;
  border-radius:11px;border:1px solid var(--line);background:#000}
.attcard .attfile{display:block;margin-bottom:7px;padding:9px 12px;
  border-radius:9px;border:1px solid var(--line);background:var(--panel-2);
  color:var(--accent-ink);font-size:12.5px;font-weight:600;
  word-break:break-all;text-decoration:none}
.attcard .attfile:hover{border-color:var(--accent)}


/* --------------------------------------------- several attachments

   Stacked, three screenshots push the student card off the bottom of the rail,
   so the price of a well-documented complaint was losing sight of who sent it.
   Side by side they cost the height of one, and the scroll snap means a swipe
   lands on a picture rather than between two. */
.attcard .attstrip{display:block}
.attcard.multi .attstrip{
  display:flex;gap:9px;overflow-x:auto;scroll-snap-type:x mandatory;
  padding-bottom:6px;margin-bottom:2px;
  -webkit-overflow-scrolling:touch;
}
.attcard.multi .attstrip > *{
  flex:0 0 82%;scroll-snap-align:center;margin-bottom:0}
.attcard.multi .attstrip img{max-height:220px}
.attcard.multi .attstrip .attvid{max-height:220px}
.attcard .attstrip::-webkit-scrollbar{height:6px}
.attcard .attstrip::-webkit-scrollbar-thumb{
  background:var(--line3);border-radius:99px}
.attn{display:inline-flex;align-items:center;justify-content:center;
  min-width:19px;height:19px;padding:0 5px;margin-left:6px;border-radius:99px;
  background:var(--panel-3);color:var(--ink2);
  font-family:var(--mono);font-size:11px;font-weight:700;vertical-align:middle}

/* The trending phrase is a heading you open. */
.trendopen{cursor:pointer;user-select:none}
.trendcar{margin-left:8px;color:var(--muted);font-size:11px}
.trendopen:hover .trendp{color:var(--accent-ink)}

/* Delete is last in the action bar and stays quiet until you point at it.
   It sits beside buttons somebody presses fifty times a day, so it must not
   look like one of them. */
.btn.danger{background:var(--danger);border-color:var(--danger);color:#fff}
.btn.danger:hover:not(:disabled){filter:brightness(1.08)}
.btn.danger:disabled{opacity:.45;cursor:not-allowed}
.delwarn{margin:12px 0 4px;padding:10px 12px;border-radius:10px;
  background:var(--amber-soft);border:1px solid var(--amber-line);
  font-size:12.5px;color:var(--ink2);line-height:1.5}


/* ------------------------------------------------- the mapping overview

   Read as an org chart, not as a settings table: department, what sits under
   it, and which words on the form land there. The only rows that ask anything
   of you are at the top -- everything below is there to be checked, and a
   screen you check should not look like a screen you fill in. */

.mapneed{border:1px solid var(--amber-line);background:var(--amber-soft);
  border-radius:var(--radius);padding:15px 17px;margin-bottom:20px}
.mapneedh{font-family:var(--display);font-size:14px;font-weight:700;
  color:var(--amber-ink)}
.mapneedb{font-size:12.5px;color:var(--ink2);line-height:1.5;margin:5px 0 12px;
  max-width:72ch}
.maprow{display:flex;align-items:center;gap:10px;padding:7px 0;
  border-top:1px solid var(--amber-line)}
.mapsrc{font-weight:650;color:var(--ink);font-size:13px}
.mapn{min-width:20px;height:20px;padding:0 6px;border-radius:99px;
  display:inline-flex;align-items:center;justify-content:center;
  background:var(--panel);color:var(--ink2);
  font-family:var(--mono);font-size:11px;font-weight:700}

.mapdept{border:1px solid var(--line);border-radius:var(--radius);
  background:var(--panel);box-shadow:var(--shadow);margin-bottom:14px;
  overflow:hidden}
.mapdepth{display:flex;align-items:baseline;gap:11px;padding:14px 18px;
  background:var(--panel-2);border-bottom:1px solid var(--line)}
.mapdeptn{font-family:var(--display);font-size:15px;font-weight:700;
  color:var(--ink);letter-spacing:-.01em}
.mapmeta{font-size:12px;color:var(--muted)}

.mapsub{padding:11px 18px;border-top:1px solid var(--line2)}
.mapsub:first-of-type{border-top:0}
.mapsubn{font-size:12.5px;font-weight:700;color:var(--ink2);margin-bottom:7px}
.mapsrcs{display:flex;flex-wrap:wrap;gap:6px}
.mapchip{display:inline-flex;align-items:center;gap:6px;
  padding:4px 5px 4px 11px;border-radius:999px;cursor:pointer;
  background:var(--panel-2);border:1px solid var(--line);
  font-size:12px;font-weight:600;color:var(--ink2);transition:.14s}
.mapchip:hover{border-color:var(--accent);color:var(--ink)}
.mapchipn{min-width:18px;height:18px;padding:0 5px;border-radius:999px;
  display:inline-flex;align-items:center;justify-content:center;
  background:var(--accent-soft);color:var(--accent-ink);
  font-family:var(--mono);font-size:10.5px;font-weight:700}

/* The two states that had no pill of their own. */
.pill.suggestion{background:var(--note-soft);color:var(--note-ink);
  border:1px solid var(--note-line)}
.pill.cancelled{background:var(--panel-3);color:var(--muted);
  border:1px solid var(--line)}
/* Answered through another ticket: out of the queue, but not finished on its own. */
.pill.merged{background:var(--panel-3);color:var(--accent-ink);
  border:1px dashed var(--accent2)}

/* The bucket picker. The name carries the state's colour so the choice looks
   like the thing it will turn the ticket into. */
.stgname{font-family:var(--display);font-size:13.5px;font-weight:700}
.stgname.sopen{color:var(--accent-ink)}
.stgname.sresolved{color:var(--green-ink)}
.stgname.ssuggestion{color:var(--note-ink)}
.stgname.scancelled{color:var(--muted)}
.stmsg{min-height:96px;resize:vertical;margin-top:4px;line-height:1.5}

/* Four names, side by side. */
.stgrow{display:grid;grid-template-columns:repeat(2,1fr);gap:8px;margin:14px 0 0}
.stgpick{padding:13px 14px;border-radius:11px;cursor:pointer;text-align:left;
  background:var(--panel-2);border:1px solid var(--line);transition:.14s}
.stgpick:hover{border-color:var(--accent);background:var(--accent-soft)}
.stgpick.on{border-color:var(--accent);box-shadow:inset 3px 0 0 var(--accent)}

/* Others, as a picker rather than a chip. Shaped like the chips beside it so
   the row still reads as one control. */
.chipsel{display:inline-flex;position:relative}
.chipsel::after{content:'';position:absolute;right:11px;top:50%;width:6px;height:6px;
  margin-top:-4px;pointer-events:none;
  border-right:2px solid var(--muted);border-bottom:2px solid var(--muted);
  transform:rotate(45deg)}
/* A select sizes itself to its WIDEST option, so "Admission and Subscription"
   was making the Others control three times the width of the chips beside it.
   Fixed width, and the open list is as wide as it needs to be regardless. */
.chipdrop{appearance:none;-webkit-appearance:none;
  width:112px;padding:6px 26px 6px 13px;border-radius:999px;cursor:pointer;
  font-size:12.5px;font-weight:600;color:var(--ink2);
  text-overflow:ellipsis;
  background:var(--panel);border:1px solid var(--line);transition:.14s}
.chipdrop:hover{border-color:var(--accent);color:var(--ink)}
.chipsel.on .chipdrop{background:var(--accent);border-color:var(--accent);color:#fff}
.chipsel.on::after{border-color:#fff}


/* ------------------------------------------------- a ticket, over the list

   A page of its own threw the list away and rebuilt it on the way back, and a
   short thread left half a screen of nothing beneath it. Over the top, the
   list is still there, closing costs nothing, and the box is only as tall as
   the ticket needs. */
/* Two columns of very different heights in one scrolling box meant scrolling
   the rail left a screen of nothing where the thread used to be. The box is a
   fixed height now and each column scrolls inside it, so there is no blank
   half and the reply stays reachable however long the rail gets. */
#modal.tkmodal{
  width:min(1180px, 96vw);
  height:min(92vh, 900px);
  padding:0;
  overflow:hidden;
  display:flex;
  flex-direction:column;
  background:var(--bg);
}
#modal.tkmodal .tk2{
  flex:1;min-height:0;
  display:grid;grid-template-columns:minmax(0,1fr) 340px;gap:16px;
  align-items:stretch;
}
#modal.tkmodal .tkmain,
#modal.tkmodal .tkrail{
  min-height:0;overflow-y:auto;overflow-x:hidden;padding-bottom:14px;
}
#modal.tkmodal .tkrail{padding-right:2px}
#modal.tkmodal .actionbar{
  flex:none;margin:0;border-radius:18px 18px 0 0;
  background:var(--panel);border-bottom:1px solid var(--line);
}

/* On a wide screen the rail sits beside the thread as it did on the page; on a
   narrow one it drops underneath rather than squeezing both. */
/* Narrow: one column that scrolls as a whole, since side by side would leave
   neither enough room to be read. */
/* Scrolling stays where the pointer is. With a popup open the page under it is
   pinned, and a column that reaches its end stops there instead of handing the
   rest of the scroll to the list behind -- which is what made the popup feel
   like it was fighting you. */
body:has(#overlay.on), body:has(#overlay2.on){overflow:hidden}
#modal, #modal2,
#modal.tkmodal .tkmain, #modal.tkmodal .tkrail, #modal.tkmodal .tk2{
  overscroll-behavior:contain;
}

@media (max-width: 1000px){
  #modal.tkmodal .tk2{display:block;overflow-y:auto}
  #modal.tkmodal .tkmain, #modal.tkmodal .tkrail{overflow:visible}
  #modal.tkmodal .tkrail{margin-top:16px}
}


/* ------------------------------------------------------------ the list

   One table, in the spacing the thin view had and with the columns the dense
   one had. Long text is clamped to two lines rather than cut to a word count:
   two lines is enough to know whether this is the ticket you are looking for,
   and the ticket itself is one click away. */

table.tbl.list2 td{padding:13px 14px;vertical-align:top}
table.tbl.list2 th{padding:12px 14px}

/* Under the student, in the same grey as the EPS line. It is how you quote
   a ticket, not how you find one, so it does not lead. */
.l2no{font-family:var(--mono);font-size:10.5px;font-weight:500;
  color:var(--muted);margin-top:2px}
.l2age{font-size:11.5px;color:var(--muted);margin-top:3px}
.l2age.stale{color:var(--danger-ink);font-weight:650}

.l2cat{font-size:11.5px;color:var(--ink2);line-height:1.45}
/* Whole days, read as a number rather than a sentence. */
.l2days{font-family:var(--mono);font-size:14px;font-weight:650;color:var(--ink2)}
.l2days.stale{color:var(--danger-ink)}
.l2note{font-size:11px;color:var(--muted);margin-top:3px}

/* Two lines, then an ellipsis. */
.l2text{font-size:11.5px;color:var(--ink);line-height:1.5;
  max-width:340px;
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;
  overflow:hidden}
.l2text.quiet{color:var(--ink2)}
/* The one column anybody reads to decide what to do. Everything else on
   the row went down a step so this could come up one without the table
   growing. */
.l2text.lead{font-size:14px;color:var(--ink);line-height:1.55;
  /* Wraps in full. .l2text is a 2-line -webkit-box clamp, which is why the
     third line was being sliced through the middle. Reply keeps the clamp --
     it is a glance, not the thing you read to decide. */
  display:block;-webkit-line-clamp:none;overflow:visible;
  overflow-wrap:anywhere}

table.tbl.list2 .who .nm{font-size:12.5px}
table.tbl.list2 .who .ph{font-family:var(--mono);font-size:11px;color:var(--muted)}

/* ------------------------------------------------------------ filters

   Shut until wanted. The badge is the only thing worth knowing about a filter
   you are not currently using: whether one is on. */
.filterbar{display:flex;gap:8px;align-items:center;margin:14px 0}
.btn.ghost.sm.on{border-color:var(--accent);color:var(--accent-ink);
  background:var(--accent-soft)}
.fcount{display:inline-flex;align-items:center;justify-content:center;
  min-width:17px;height:17px;padding:0 5px;margin-left:6px;border-radius:99px;
  background:var(--accent);color:#fff;font-size:10.5px;font-weight:700;
  font-family:var(--mono)}

/* The composer's strip sits inside a bordered box, so it keeps a little room
   of its own without reintroducing a second style. */
.ctabs{padding:10px 12px 0;margin-bottom:0}

/* The list's columns, sized by what each holds rather than by whatever the
   longest word in them happened to be. */
table.tbl.list2{table-layout:fixed;min-width:1370px}
/* By class, not by position. Department is only rendered for an admin, and
   nth-child rules silently shifted every column right of it for everybody
   else -- Issue got the width meant for Days. */
table.tbl.list2 .c-who{width:210px}
table.tbl.list2 .c-cat{width:118px}
table.tbl.list2 .c-issue{width:360px}
table.tbl.list2 .c-dept{width:118px}
table.tbl.list2 .c-days{width:62px}
table.tbl.list2 .c-reply{width:230px}
table.tbl.list2 .c-prio{width:92px}
table.tbl.list2 .c-owner{width:110px}
table.tbl.list2 .c-rated{width:62px}
.l2text{max-width:none}

/* The student leads the ticket; the label under them is a label. */
.subj{font-size:22px;letter-spacing:-.02em}
.subwho{font-size:12.5px;color:var(--ink2);margin-top:4px;line-height:1.5}
.submeta{font-size:12px;color:var(--muted);margin-top:3px}


/* --------------------------------------------------- send, and finishing

   Send is the whole action for most replies, so it is one button. The three
   moves that END a ticket live behind the caret: they are worth stopping to
   choose, and putting them in the open made the common case look like a
   decision. */
.sendsplit{position:relative;display:inline-flex}
.sendsplit .btn{border-radius:10px 0 0 10px}
.sendsplit .btn.caret{
  border-radius:0 10px 10px 0;margin-left:1px;padding:0 11px;
  font-size:11px;line-height:1}
.sendsplit .btn.caret:disabled{opacity:.5;cursor:not-allowed}

.sendmenu{position:absolute;right:0;bottom:calc(100% + 7px);z-index:20;
  min-width:230px;padding:5px;border-radius:12px;
  background:var(--panel);border:1px solid var(--line);
  box-shadow:var(--shadow-lg)}
.sendopt{display:block;width:100%;text-align:left;padding:9px 12px;
  border:0;border-radius:8px;background:transparent;cursor:pointer;
  font-family:inherit;font-size:12.5px;font-weight:600;color:var(--ink2)}
.sendopt:hover{background:var(--accent-soft);color:var(--accent-ink)}

/* Transfer sits with Send: the other thing you do when you finish reading a
   ticket. Lighter, because it is the rarer of the two. */
.btn.soft{background:var(--accent-soft);color:var(--accent-ink);
  border:1px solid transparent;margin-right:8px}
.btn.soft:hover{border-color:var(--accent);background:var(--accent-soft)}

/* A card that folds. Shut, it costs one line instead of sixteen -- which is
   what made the rail twice the height of the conversation beside it. */
.cardfold{display:flex;align-items:center;justify-content:space-between;
  width:100%;padding:0;border:0;background:transparent;cursor:pointer;
  font-family:var(--display);font-size:15px;font-weight:700;color:var(--ink);
  letter-spacing:-.01em}
.cardfold:hover{color:var(--accent-ink)}
.foldcar{color:var(--muted);font-size:11px}
.formcard .frow:first-of-type{margin-top:10px}

/* The rail stops stretching to match the thread, so a short conversation does
   not leave a column of nothing beside it. */
.tk2{align-items:start}

/* The second layer is the first one's twin, one step higher. */
#overlay2{position:fixed;inset:0;background:rgba(23,22,43,.42);z-index:95;
  display:none;align-items:center;justify-content:center;padding:20px;
  backdrop-filter:blur(2px)}
#overlay2.on{display:flex}
#modal2{position:relative;background:var(--panel);border-radius:18px;
  box-shadow:var(--shadow-lg);padding:0;width:min(560px,96vw);
  max-height:88vh;overflow:auto;animation:pop .22s ease}
#modal2 h3{font-size:16px;margin-bottom:14px}

/* ---------------------------------------------------------------- composer
   Two tabs and a box to type in. The tabs were sized like page navigation --
   a filled violet slab for a control that only ever picks between two things,
   one of which is the default. Quieter, so the eye goes to the message. */
.composer .ctabs{padding:8px 8px 0;background:transparent;border-bottom:1px solid var(--line)}
.composer .ctab{padding:6px 13px;font-size:12px;border-radius:8px 8px 0 0;
  border:1px solid transparent;border-bottom:none;margin-bottom:-1px}
/* Reply and Remark are not two views of one thing -- one goes to the student
   and one never does. Quiet was the wrong call: the selected tab now carries a
   fill, and Remark carries a different fill, so the two states cannot be
   confused at a glance. */
/* Driven by the composer's own mode rather than by .on. Chasing why .on alone
   would not paint here was not converging, and the mode class is the thing that
   is actually true -- it already colours the body and shows the warning, so the
   tab agreeing with it cannot drift out of step. */
.composer:not(.noting) .ctab[data-c="reply"],
.composer:not(.noting) .ctab[data-c="reply"]:hover{
  background:var(--accent-soft);color:var(--accent-ink);
  border-color:transparent;box-shadow:none}
.composer.noting .ctab[data-c="note"],
.composer.noting .ctab[data-c="note"]:hover{
  background:var(--note-soft2);color:var(--note-ink);
  border-color:transparent;box-shadow:none}
/* and the one that is not selected stays plainly not selected */
.composer.noting .ctab[data-c="reply"],
.composer:not(.noting) .ctab[data-c="note"]{
  background:transparent;color:var(--muted);border-color:transparent;box-shadow:none}

/* And the whole composer changes with it, because by the time you are typing
   you are no longer looking at the tab. */
.composer.noting{background:var(--note-soft);border-color:var(--note-line)}
.composer.noting textarea{background:transparent}
.cwarn{display:none;align-items:center;gap:7px;margin:9px 12px 0;padding:7px 11px;
  border-radius:8px;background:var(--note-soft2);color:var(--note-ink);
  font-size:12px;font-weight:600}
.composer.noting .cwarn{display:flex}
.composer .cbody{padding:8px 14px}
.composer textarea{min-height:104px;border:1px solid var(--line2);
  border-radius:10px;background:var(--panel);padding:11px 12px;
  font-size:13.5px;color:var(--ink);transition:.14s}
.composer textarea:focus{border-color:var(--accent);box-shadow:var(--ring)}
.composer textarea::placeholder{color:var(--muted);font-size:13px}

/* Remarks, in the tab where you would write one. Left-ruled rather than
   bubbled: they are margin notes on the ticket, not messages in the thread. */
.notelist{padding:12px 15px 0;display:flex;flex-direction:column;gap:10px}
.noteitem{border-left:2px solid var(--line3);padding:1px 0 1px 11px}
.notewho{font-size:11px;font-weight:700;color:var(--ink);letter-spacing:.01em}
.notewhen{font-weight:500;color:var(--muted);margin-left:8px;font-family:var(--mono);
  font-size:10.5px}
.notebody{font-size:13px;color:var(--ink-2);line-height:1.55;margin-top:3px;
  white-space:pre-wrap}
.notenone{font-size:12px;color:var(--muted);line-height:1.5}

/* The modal supplies its own padding, so the grid inside it does not need the
   page's. */
#modal.tkmodal .tk2{padding:16px 18px 0}

/* The close, first in the bar. Round, quiet, and the only control of its kind
   on the ticket -- there is no second way out to confuse it with. */
.closex{width:32px;height:32px;flex:none;display:inline-flex;
  align-items:center;justify-content:center;
  border:1px solid var(--line);border-radius:999px;background:var(--panel);
  color:var(--ink2);font-size:19px;line-height:1;cursor:pointer;transition:.14s}
.closex:hover{border-color:var(--accent);color:var(--accent-ink);
  background:var(--panel-2)}
.closex:focus-visible{outline:2px solid var(--accent);outline-offset:2px}

/* A sub-department nothing points at is not an error, but it is not doing
   anything either -- so it is legible and quiet rather than gone. */
tr.mapdim td{opacity:.55}
.mapidle{font-size:11.5px;color:var(--amber-ink);font-weight:600;margin-top:-2px}

/* --------------------------------------------------------- class mapping
   One row per class, so the row has to hold a picker without the picker
   stretching to the full width a .finput normally takes. */
.tbl .tright{text-align:right}
.cmadd{justify-content:flex-end;gap:8px}
.cmadd select.finput{width:auto;min-width:150px;padding:7px 26px 7px 10px;font-size:12.5px}
tr.cmgap td:first-child{box-shadow:inset 2px 0 0 var(--accent)}

/* The default move, said out loud. It is the same thing the Send button does,
   written down so nobody has to guess that the absence of an option is one. */
.sendoptdef{display:block;font-size:11px;color:var(--muted);margin-top:2px;font-weight:400}
.sendopt:hover .sendoptdef{color:inherit;opacity:.75}

/* ----------------------------------------------------------- muted phrases
   A word that means nothing here can be taken out of the count. The control is
   quiet until the card is under the cursor: it is a correction, not an action
   anybody comes to this screen to perform. */
.trmute{width:24px;height:24px;flex:none;border:0;background:none;color:var(--muted);
  font-size:16px;line-height:1;border-radius:7px;cursor:pointer;opacity:0;transition:.12s}
.trend:hover .trmute, .recur tr:hover .trmute, .trmute:focus-visible{opacity:1}
.trmute:hover{background:var(--danger-soft);color:var(--danger-ink)}
.recur .trmute{opacity:0}

.mutedstrip{display:flex;align-items:center;gap:7px;flex-wrap:wrap;margin:10px 0 4px}
.mutedlbl{font-size:11px;font-weight:800;letter-spacing:.07em;text-transform:uppercase;
  color:var(--muted)}
.mutedp{display:inline-flex;align-items:center;gap:3px;background:var(--panel-3);
  color:var(--muted);border-radius:20px;padding:3px 5px 3px 10px;font-size:12px}
.mutedp button{border:0;background:none;color:inherit;cursor:pointer;font-size:13px;
  line-height:1;padding:2px 4px;border-radius:50%}
.mutedp button:hover{background:var(--accent-soft);color:var(--accent-ink)}

/* ----------------------------------------------------------------- my work
   How much I got through, and whether it landed -- side by side, because an
   agent asks both at once and the second used to live on another screen. */
.mywrap{display:grid;grid-template-columns:minmax(0,300px) minmax(0,1fr);gap:14px;
  align-items:stretch;margin-bottom:18px}
@media(max-width:900px){.mywrap{grid-template-columns:minmax(0,1fr)}}
.myhero{background:var(--panel);border:1px solid var(--line);border-radius:var(--radius);
  box-shadow:var(--shadow);padding:16px 18px;display:flex;flex-direction:column;
  justify-content:center}
.myheroh{font-size:10.5px;font-weight:800;letter-spacing:.09em;text-transform:uppercase;
  color:var(--muted);margin-bottom:10px}
.myscore{display:flex;align-items:baseline;gap:8px;flex-wrap:wrap}
.mypct{font-size:34px;font-weight:800;letter-spacing:-.03em;line-height:1;
  color:var(--accent-ink)}
.mypctsub{font-size:12.5px;color:var(--muted)}
.mybar{height:6px;border-radius:4px;background:var(--panel-3);overflow:hidden;margin:12px 0 9px}
.mybar i{display:block;height:100%;border-radius:4px;background:var(--accent)}
.mysplit{display:flex;gap:14px;font-size:12.5px;font-weight:600}
.myup{color:var(--green-ink)}
.mydown{color:var(--muted)}
.myempty{font-size:13px;color:var(--muted);line-height:1.6}
.mynums{display:grid;grid-template-columns:repeat(auto-fit,minmax(140px,1fr));gap:12px}
.sect2{font-size:10.5px;font-weight:800;letter-spacing:.09em;text-transform:uppercase;
  color:var(--muted);margin:0 0 9px}

/* ------------------------------------------------------- channel switch
   Offline is a way of reading every screen, not a screen of its own, so the
   control sits above the view and applies to whatever is under it. */
.chswitch{display:inline-flex;gap:2px;background:var(--panel-3);border-radius:10px;
  padding:3px;margin-bottom:12px}
.chswitch button{border:0;background:none;padding:6px 14px;border-radius:8px;
  cursor:pointer;font-size:12.5px;font-weight:600;color:var(--muted);transition:.14s}
.chswitch button:hover{color:var(--ink)}
.chswitch button.on{background:var(--panel);color:var(--accent-ink);box-shadow:var(--shadow)}
.chswitch button:focus-visible{outline:none;box-shadow:var(--ring)}

/* --------------------------------------------------------------- priority
   Split into levels rather than listed with a dropdown on each row: the
   question here is "which of these are urgent", and a column of identical
   dropdowns does not answer it at a glance. */
.prigrid{display:grid;grid-template-columns:repeat(auto-fit,minmax(230px,1fr));
  gap:12px;margin-top:14px;align-items:start}
.pricol{background:var(--panel);border:1px solid var(--line);border-radius:var(--radius);
  box-shadow:var(--shadow);padding:13px 14px}
.pricol::before{content:"";display:block;height:3px;border-radius:3px;margin:-3px 0 10px}
.pricol.pri-urgent::before{background:var(--danger)}
.pricol.pri-high::before{background:var(--amber)}
.pricol.pri-medium::before{background:var(--accent)}
.pricol.pri-low::before{background:var(--line3)}
.prih{display:flex;align-items:center;gap:8px}
.prin{font-size:13px;font-weight:700}
.prict{font-size:11px;font-weight:700;color:var(--muted);background:var(--panel-3);
  padding:1px 7px;border-radius:20px}
.priwhy{font-size:11.5px;color:var(--muted);line-height:1.5;margin:5px 0 10px}
.prilist{display:flex;flex-direction:column;gap:5px}
.pricat{display:block;width:100%;text-align:left;border:1px solid var(--line);
  background:var(--panel-2);border-radius:9px;padding:7px 10px;cursor:pointer;
  transition:.12s}
.pricat:hover{border-color:var(--accent);background:var(--accent-soft)}
.pcname{display:block;font-size:12.5px;font-weight:600}
.pcdept{display:block;font-size:11px;color:var(--muted);margin-top:1px}
.prinone{font-size:12px;color:var(--muted);padding:4px 2px}

.prisheet{position:fixed;inset:0;z-index:80;background:rgba(30,27,75,.34);
  display:flex;align-items:center;justify-content:center;padding:20px}
.prisheetbox{background:var(--panel);border-radius:var(--radius);box-shadow:var(--shadow-lg);
  padding:18px;width:min(420px,100%);display:flex;flex-direction:column;gap:7px}
.prisheeth{font-size:15px;font-weight:700}
.prisheetwhy{font-size:12px;color:var(--muted);line-height:1.5;margin-bottom:6px}
.prisheetopt{display:flex;align-items:flex-start;gap:10px;text-align:left;
  border:1px solid var(--line);background:none;border-radius:10px;padding:9px 11px;
  cursor:pointer;transition:.12s}
.prisheetopt:hover{border-color:var(--accent);background:var(--accent-soft)}
.prisheetopt.on{border-color:var(--accent);background:var(--accent-soft)}
.prisheetopt b{display:block;font-size:13px}
.prisheetopt small{display:block;font-size:11.5px;color:var(--muted);margin-top:2px}
.pdot{width:9px;height:9px;border-radius:50%;flex:none;margin-top:5px}
.pdot.pri-urgent{background:var(--danger)}
.pdot.pri-high{background:var(--amber)}
.pdot.pri-medium{background:var(--accent)}
.pdot.pri-low{background:var(--line3)}

/* ------------------------------------------------------- the board, dragging
   Cards move between columns the way a Notion board does. Adding sits at the
   bottom of the column it will land in, so the level is chosen by where you
   click rather than in a field afterwards. */
.pricat{user-select:none}
.pricat[draggable="true"]{cursor:grab}
.pricat.dragging{opacity:.45;cursor:grabbing}
.prilist{min-height:44px;border-radius:10px;transition:.12s}
.prilist.over{background:var(--accent-soft);
  box-shadow:inset 0 0 0 2px var(--accent)}
.priadd{width:100%;margin-top:8px;border:1px dashed var(--line3);background:none;
  color:var(--muted);border-radius:9px;padding:7px;font-size:12.5px;font-weight:600;
  cursor:pointer;transition:.12s;font-family:inherit}
.priadd:hover{border-color:var(--accent);color:var(--accent-ink);
  background:var(--accent-soft)}

/* Tags carry their own colour, so the card holds the pill rather than plain
   text. The three levels keep the same edge as the four priority ones. */
.tagboard .pricol.tag-high::before{background:var(--danger)}
.tagboard .pricol.tag-normal::before{background:var(--accent)}
.tagboard .pricol.tag-low::before{background:var(--line3)}
.tagcard{display:flex;align-items:center;gap:8px}
.tagcard .tag{flex:none}
.tagcard .pcdept{margin-top:0;flex:1;min-width:0;overflow:hidden;
  text-overflow:ellipsis;white-space:nowrap}
.tagx{border:0;background:none;color:var(--muted);cursor:pointer;font-size:15px;
  line-height:1;padding:2px 5px;border-radius:6px;opacity:0;transition:.12s;flex:none}
.tagcard:hover .tagx{opacity:1}
.tagx:hover{background:var(--danger-soft);color:var(--danger-ink)}

/* --------------------------------------------------------- status control
   The status shows and sets, the same way priority already does. Marking a
   ticket In progress is the first thing an agent does on opening one, and it
   is how everybody else knows somebody is on it. */
.statusbtn{display:inline-flex;align-items:center;gap:5px;border:1px solid transparent;
  background:none;padding:2px 6px 2px 2px;border-radius:20px;cursor:pointer;
  transition:.12s;font:inherit}
.statusbtn:hover{border-color:var(--line3);background:var(--panel-3)}
.statusbtn:focus-visible{outline:none;box-shadow:var(--ring)}
.statuscar{font-size:9px;color:var(--muted)}

.statusmenu{position:absolute;top:calc(100% - 4px);left:12px;z-index:60;
  background:var(--panel);border:1px solid var(--line);border-radius:12px;
  box-shadow:var(--shadow-md);padding:5px;min-width:230px}
.statusopt{display:block;width:100%;text-align:left;border:0;background:none;
  cursor:pointer;padding:8px 11px;border-radius:8px;font:inherit}
.statusopt b{display:block;font-size:13px;font-weight:600}
.statusopt small{display:block;font-size:11.5px;color:var(--muted);margin-top:1px}
.statusopt:hover{background:var(--accent-soft);color:var(--accent-ink)}
.statusopt:hover small{color:inherit;opacity:.75}
.statusopt.on{background:var(--panel-3)}

/* --------------------------------------------------- the team, per department
   A department with nobody in it takes no tickets, so who is in it sits beside
   the switches that decide how tickets are handed out. */
.teamcell{display:flex;align-items:center;gap:8px}
.teamn{font-size:12px;font-weight:700;background:var(--accent-soft);color:var(--accent-ink);
  padding:1px 8px;border-radius:20px;flex:none}
.teamwho{font-size:12px;color:var(--muted);max-width:190px;overflow:hidden;
  text-overflow:ellipsis;white-space:nowrap}
.teamnone{font-size:12px;color:var(--amber-ink);font-weight:600}
.fixeddept{font-size:14px;font-weight:600;background:var(--accent-soft);
  color:var(--accent-ink);padding:8px 12px;border-radius:var(--radius-sm);
  display:inline-block}

/* ------------------------------------------------------- bucket composer
   One row of pills answering one question: what are you doing with this
   ticket? Picking one reshapes the box below it, so the pills are the only
   control that has to be read before writing. */
.bpills{display:flex;flex-wrap:wrap;gap:8px;padding:12px 14px;
  border-bottom:1px solid var(--line)}

/* Who reads what you are typing. The single most consequential fact about the
   box, so it sits against it rather than in a tooltip. */
.bwho{font-size:11px;font-weight:650;color:var(--muted);letter-spacing:.02em;
  text-transform:uppercase}
.bwho.pub{color:var(--accent)}

/* The Transfer pill is a select, so it needs the caret drawn in and the
   native chrome taken out -- otherwise it reads as a form field beside five
   buttons instead of the sixth choice. */
.bdrop{appearance:none;-webkit-appearance:none;padding-right:30px;
  background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M1 1l4 4 4-4' fill='none' stroke='%236b6880' stroke-width='1.6' stroke-linecap='round'/%3E%3C/svg%3E");
  background-repeat:no-repeat;background-position:right 12px center}
.bdrop.on{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M1 1l4 4 4-4' fill='none' stroke='%23ffffff' stroke-width='1.6' stroke-linecap='round'/%3E%3C/svg%3E");
  /* .bpill.on sets `background:` as a SHORTHAND, which resets background-repeat to its
     initial `repeat` - and it out-specifies .bdrop, where no-repeat is set. The little
     chevron then tiled across the whole pill, which is the zigzag pattern. Repeat and
     position have to be restated here, next to the image they belong to. */
  background-repeat:no-repeat;background-position:right 12px center}

/* ------------------------------------------------------------ tag swatches
   Six, not a colour wheel. A free picker produces twenty tags that are all a
   slightly different blue and tells the reader nothing. */
.swatches{display:flex;gap:9px;flex-wrap:wrap;margin-top:2px}
.swatch{width:30px;height:30px;border-radius:9px;cursor:pointer;
  background:var(--sw);border:2px solid transparent;
  box-shadow:0 0 0 1px var(--line) inset;transition:.13s}
.swatch:hover{transform:translateY(-1px)}
.swatch.on{border-color:var(--ink);box-shadow:0 0 0 2px var(--panel) inset}

/* The tag on the board is a button now, so it has to shed the button chrome
   and keep looking like a tag. */
.tag.tagedit{border:0;font:inherit;cursor:pointer;padding:3px 9px}
.tag.tagedit:hover{filter:brightness(.94)}

/* The Transfer pill is a native <select>, so without this it takes the
   browser's own focus ring -- a blue outline that belongs to no part of this
   design, and the thing that looked like stray blue lines on the control. */
.bpill:focus{outline:none}
.bpill:focus-visible{outline:none;border-color:var(--accent);box-shadow:var(--ring)}
.bdrop:focus{outline:none;box-shadow:none}
.bdrop.on:focus-visible{box-shadow:none}
/* The option list is drawn by the OS. It cannot be styled far, but it can at
   least stop inheriting a blue that nothing else here uses. */
.bdrop option, .sel option{background:var(--panel);color:var(--ink)}

/* Filter sits at the far end of its row. On the left it read as one more tab
   in the row above it, which is why it was easy to miss. */
.filterbar{display:flex;align-items:center;gap:8px}
.filterbar .spacer{flex:1}
/* The search box lives on the bar, not inside the Filter panel. It is given a
   sensible width rather than flex:1 - stretched across the whole row it read as
   a page-wide header field, and the Filter button lost its corner. */
.filterbar .searchbox{width:290px;max-width:46vw;height:34px;padding:7px 12px;
  border-radius:999px;font-size:13px}
.filterbar .searchbox::-webkit-search-cancel-button{cursor:pointer}
@media(max-width:640px){ .filterbar .searchbox{width:100%;max-width:none} }


/* ------------------------------------------------- the admin writes to team
   Admin only, beside the channel switch: both are things done TO the console
   rather than inside one screen of it. */
/* Top right of the whole console, not of the screen you happen to be on --
   a message is not part of Overview or of the ticket list. */
/* Filled, not outlined. A thin violet line on a white circle against a pale
   page was the faintest control on screen -- and it is the one thing that has
   to catch your eye when something arrives. */
.msgbtn{position:fixed;top:16px;right:20px;z-index:70;
  width:42px;height:42px;display:inline-flex;align-items:center;
  justify-content:center;border-radius:999px;cursor:pointer;
  color:#fff;background:var(--accent);border:0;
  box-shadow:0 3px 12px rgba(109,74,255,.42);transition:.14s}
.msgbtn:hover{transform:translateY(-1px);
  box-shadow:0 5px 16px rgba(109,74,255,.52)}
.msgbtn:focus-visible{outline:none;box-shadow:var(--ring)}
.msgico{display:block}

/* The count rides on the icon, because it is the only part worth reading
   without clicking. */
/* display:inline-flex below out-ranks the browser's [hidden]{display:none},
   so the badge sat there reading 0. Nothing to count is nothing to show. */
.msgdot[hidden]{display:none}
/* Inverted, now that the button itself is violet -- a violet badge on a violet
   circle would disappear. */
.msgdot{position:absolute;top:-2px;right:-2px;min-width:19px;height:19px;
  padding:0 5px;border-radius:999px;background:#fff;color:var(--accent-ink);
  font-family:var(--mono);font-size:10.5px;font-weight:800;
  display:inline-flex;align-items:center;justify-content:center;
  border:2px solid var(--accent);box-shadow:0 1px 3px rgba(0,0,0,.18)}

/* An unread message is left-ruled and slightly lifted; a read one is plain. */
.inbox{display:flex;flex-direction:column;gap:10px;max-height:60vh;overflow:auto}
.inmsg{border:1px solid var(--line);border-radius:12px;padding:11px 13px;
  background:var(--panel)}
.inmsg.unread{border-left:3px solid var(--accent);background:var(--accent-soft)}
.inhead{display:flex;justify-content:space-between;gap:10px;align-items:baseline}
.inwho{font-size:12px;font-weight:700;color:var(--ink)}
.inwhen{font-family:var(--mono);font-size:10.5px;color:var(--muted)}
.insubj{font-size:13px;font-weight:650;color:var(--ink);margin-top:4px}
.inbody{font-size:13px;color:var(--ink-2);line-height:1.55;margin-top:3px;
  white-space:pre-wrap}

/* ------------------------------------------------------------------- chat
   A conversation per person, not a mail-merge. The list finds somebody; the
   thread is where you read what was said and where their numbers live. */
.chatwrap{display:flex;flex-direction:column;min-height:420px}
.chathead{display:flex;align-items:center;gap:11px;margin-bottom:12px}
.chathead h3{margin:0}
.chatback{width:30px;height:30px;flex:none;border:1px solid var(--line);
  border-radius:9px;background:var(--panel);color:var(--ink2);cursor:pointer;
  font-size:15px;line-height:1;transition:.14s}
.chatback:hover{border-color:var(--accent);color:var(--accent-ink)}
.chattabs{margin-bottom:12px}

.chatlist{border:1px solid var(--line);border-radius:12px;overflow:auto;
  max-height:340px}
.chatrow{display:flex;align-items:center;gap:11px;width:100%;text-align:left;
  padding:10px 13px;border:0;border-bottom:1px solid var(--line);
  background:transparent;cursor:pointer;font-family:inherit;transition:.12s}
.chatrow:last-child{border-bottom:0}
.chatrow:hover{background:var(--accent-soft)}
.chatav{width:34px;height:34px;flex:none;border-radius:50%;
  display:inline-flex;align-items:center;justify-content:center;
  background:var(--accent);color:#fff;font-size:12px;font-weight:700;
  font-family:var(--display)}
.chatav.big{width:38px;height:38px;font-size:13px}
.chatmid{flex:1;min-width:0}
.chatnm{display:block;font-size:13px;font-weight:650;color:var(--ink)}
.chatsub{display:block;font-size:11.5px;color:var(--muted);margin-top:1px;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.chattime{font-family:var(--mono);font-size:10.5px;color:var(--muted);flex:none}
.chatnone{font-size:12.5px;color:var(--muted);line-height:1.6;padding:16px 13px}
/* A list that is empty and a list that could not be read are different facts, so they
   do not get to look the same. */
.chatnone.bad{color:var(--danger,#b42318);background:rgba(180,35,24,.06);border:1px solid rgba(180,35,24,.18);border-radius:10px;margin:10px 12px;padding:12px 13px}

.chatwho{display:flex;flex-direction:column;min-width:0}
.chatwho b{font-size:14px}
.chatmeta{font-size:11px;color:var(--muted);overflow:hidden;
  text-overflow:ellipsis;white-space:nowrap}

/* The numbers, once you have chosen whose they are. */
.chatstats{display:flex;gap:8px;flex-wrap:wrap;margin-bottom:10px}
.cstat{font-size:11.5px;color:var(--accent-ink);background:var(--accent-soft);
  padding:4px 10px;border-radius:20px}
.cstat b{font-family:var(--mono);font-size:12.5px}
.cstat.zero{color:var(--muted);background:var(--panel-3)}

.chatthread{flex:1;min-height:150px;max-height:300px;overflow:auto;
  padding:12px;border:1px solid var(--line);border-radius:12px;
  background:var(--panel-2);display:flex;flex-direction:column;gap:9px}
.chatthread.tall{max-height:60vh}
.cbub{align-self:flex-end;max-width:82%;background:var(--accent);color:#fff;
  border-radius:14px 14px 4px 14px;padding:9px 12px}
.cbub.them{align-self:flex-start;background:var(--panel);color:var(--ink);
  border:1px solid var(--line);border-radius:14px 14px 14px 4px}
.cbwho{font-size:11px;font-weight:700;opacity:.75;margin-bottom:2px}
.cbbody{font-size:13px;line-height:1.55;white-space:pre-wrap}
.cbmeta{font-size:10px;opacity:.7;margin-top:4px;font-family:var(--mono)}

.chatbox{margin-top:11px}
.chatbox textarea{width:100%;font-family:inherit;font-size:13px;padding:10px 12px;
  border:1px solid var(--line);border-radius:12px;resize:vertical;
  background:var(--panel);color:var(--ink)}
.chatbox textarea:focus{outline:none;border-color:var(--accent);box-shadow:var(--ring)}
.chatsend{display:flex;align-items:center;gap:8px;margin-top:8px}
.chatsend .spacer{flex:1}

/* A message about one ticket says which. The number is the way back to it. */
.cbtk{display:inline-block;font-family:var(--mono);font-size:10.5px;font-weight:700;
  padding:2px 8px;margin-bottom:5px;border-radius:20px;cursor:pointer;
  background:rgba(255,255,255,.24);color:#fff;transition:.12s}
.cbtk:hover{background:rgba(255,255,255,.36)}
.cbub.them .cbtk{background:var(--accent-soft);color:var(--accent-ink)}

/* Who nudged you, and in what capacity. A poke from your team lead and one
   from the Help Center admin are different things to receive. */
.cbrole{display:inline-block;margin-left:7px;padding:1px 7px;border-radius:20px;
  background:var(--accent-soft);color:var(--accent-ink);
  font-family:var(--display);font-size:9.5px;font-weight:700;
  letter-spacing:.04em;text-transform:uppercase;vertical-align:middle}

/* ---------------------------------------------------------- notifications
   The message leads and everything else gets out of its way.

   Two rounds of this were a lavender wall, and the reason was structural
   rather than decorative: every row is unread when you open the panel, so
   tinting the unread ones tinted all of them. And the sender -- the same
   person on every row -- was set first, in bold, three times over, while the
   only part that differed sat underneath it in grey.

   So: white cards, unread marked by one small bar rather than a fill; the
   message at the top in full ink; who and when and which ticket folded into a
   single quiet line beneath. */
.ntcount{font-size:11.5px;font-weight:650;color:var(--muted)}
.ntlist{display:flex;flex-direction:column;gap:8px;overflow:auto;max-height:58vh;
  padding:2px}

.ntrow{display:flex;align-items:flex-start;gap:12px;padding:12px 14px;
  border:1px solid var(--line);border-radius:12px;background:var(--panel);
  transition:.14s}
.ntrow:hover{border-color:var(--line3)}
/* Unread is a bar, not a wash. The kind picks its colour, so what is new and
   what sort of thing it is arrive as one mark. */
.ntrow.unread{box-shadow:inset 3px 0 0 var(--accent)}
.ntrow.asg.unread{box-shadow:inset 3px 0 0 #0f9d8f}
.ntrow.msg.unread{box-shadow:inset 3px 0 0 var(--line3)}

.ntico{width:30px;height:30px;flex:none;border-radius:9px;margin-top:1px;
  display:inline-flex;align-items:center;justify-content:center}
.ntico.msg{background:var(--panel-3);color:var(--muted)}
.ntico.poke{background:var(--accent-soft);color:var(--accent-ink)}
.ntico.asg{background:rgba(15,157,143,.13);color:#0b7a6f}

.ntmid{flex:1;min-width:0;display:flex;flex-direction:column}
/* The part you actually read. */
.ntbody{font-size:13.5px;color:var(--ink);line-height:1.5}
/* Who, when, and which ticket -- one line, one weight, none of it competing. */
.ntmeta{font-size:11px;color:var(--muted);margin-top:4px;line-height:1.4}

.ntacts{display:flex;gap:15px;margin-top:8px}
.ntact{border:0;background:none;padding:0;cursor:pointer;
  font-family:var(--display);font-size:12px;font-weight:650;
  color:var(--accent-ink);transition:.12s}
.ntact:hover{color:var(--accent);text-decoration:underline}

/* Poke was a ghost button in the top bar -- a grey outline against a white
   strip, which is the least readable thing on the ticket. It is an action, so
   it looks like one: filled violet-soft with ink that carries. */
.btn.sm.pokebtn{background:var(--accent-soft);color:var(--accent-ink);
  border:1px solid transparent;font-weight:700}
.btn.sm.pokebtn:hover{background:var(--accent);color:#fff;border-color:var(--accent)}

/* --------------------------------------------------- signature + snippets */
.sniprow{display:flex;align-items:flex-start;gap:12px;padding:10px 0;
  border-bottom:1px solid var(--line)}
.sniprow:last-of-type{border-bottom:0}
.sniptrig{flex:none;font-family:var(--mono);font-size:12px;font-weight:700;
  color:var(--accent-ink);background:var(--accent-soft);
  padding:2px 9px;border-radius:6px}
.snipbody{flex:1;min-width:0;font-size:13px;color:var(--ink-2);line-height:1.5}
.snipro{flex:none;font-size:10.5px;font-weight:700;letter-spacing:.05em;
  text-transform:uppercase;color:var(--muted)}

/* The slash menu, above the cursor the way an editor does it. */
/* Below what you are typing, in the flow, not floating above it.
   Floating, it was positioned over the bucket pills AND clipped in half by
   .composer's overflow:hidden -- so it read as the pills having been replaced
   by half a list. In the flow it covers nothing and cannot be cut off. */
.slashmenu{margin:8px 0 2px;max-height:210px;overflow:auto;padding:4px;
  border-radius:10px;background:var(--panel-2);border:1px solid var(--line)}
.slashopt{display:flex;align-items:baseline;gap:9px;width:100%;text-align:left;
  border:0;background:transparent;border-radius:8px;padding:7px 10px;
  cursor:pointer;font-family:inherit}
.slashopt:hover, .slashopt.on{background:var(--accent-soft)}
.slashopt b{font-family:var(--mono);font-size:12px;color:var(--accent-ink);flex:none}
.slashdef{font-size:9.5px;font-weight:700;letter-spacing:.05em;
  text-transform:uppercase;color:var(--muted);flex:none}
.slashbody{flex:1;min-width:0;font-size:12.5px;color:var(--ink-2);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.composer .cbody{position:relative}

/* ------------------------------------------------------------------ board
   The view this replaces is a Notion board, so the shape is familiar on
   purpose. What changes: the issue is clamped, Done is folded, and a card
   carries the reference and the age it never used to show. */
.viewsw{display:inline-flex;gap:2px;background:var(--panel-3);border-radius:10px;
  padding:3px;margin:14px 0 0}
.vsw{border:0;background:none;padding:6px 15px;border-radius:8px;cursor:pointer;
  font-family:var(--display);font-size:12.5px;font-weight:650;color:var(--muted);
  transition:.14s}
.vsw:hover{color:var(--ink)}
.vsw.on{background:var(--panel);color:var(--accent-ink);box-shadow:var(--shadow)}

.kboard{display:flex;gap:12px;align-items:flex-start;overflow-x:auto;
  padding-bottom:10px}
.kcol{flex:1 1 0;min-width:250px;background:var(--panel-2);border-radius:14px;
  border:1px solid var(--line);padding:10px}
/* Folded, Done stops being a wall of finished work and becomes one line. */
.kcol.shut{flex:0 0 auto;min-width:0}
.kcolh{display:flex;align-items:center;gap:8px;padding:2px 4px 10px}
.kcol.shut .kcolh{padding-bottom:2px;cursor:pointer}
.kdot{width:8px;height:8px;border-radius:50%;flex:none;background:var(--line3)}
.kdot.new{background:var(--amber,#c2670a)}
.kdot.open{background:var(--accent)}
.kdot.awaiting_student{background:#3d6fd6}
.kdot.done{background:#0f9d8f}
.kname{font-family:var(--display);font-size:13px;font-weight:700;color:var(--ink)}
.kct{font-family:var(--mono);font-size:11px;font-weight:700;color:var(--muted);
  background:var(--panel-3);padding:1px 7px;border-radius:20px}
.kfold{margin-left:4px;font-size:10px;color:var(--muted)}

.klist{display:flex;flex-direction:column;gap:8px;min-height:60px;
  border-radius:10px;transition:.12s;max-height:64vh;overflow:auto}
.klist.over{background:var(--accent-soft);box-shadow:inset 0 0 0 2px var(--accent)}
.knone{font-size:12px;color:var(--muted);padding:8px 4px}

.kcard{background:var(--panel);border:1px solid var(--line);border-radius:11px;
  padding:10px 11px;cursor:pointer;user-select:none;transition:.12s}
.kcard:hover{border-color:var(--accent);box-shadow:var(--shadow)}
.kcard.dragging{opacity:.45}
.knm{font-family:var(--display);font-size:13px;font-weight:700;color:var(--ink)}
.kmeta{font-family:var(--mono);font-size:10.5px;color:var(--muted);margin-top:1px}
/* Three lines. Their cards ran the whole complaint, which made four cards
   taller than the screen. */
.kissue{font-size:12.5px;color:var(--ink-2);line-height:1.45;margin-top:7px;
  display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;
  overflow:hidden}
.kfoot{display:flex;align-items:center;gap:7px;margin-top:9px}
.kno{font-family:var(--mono);font-size:10.5px;font-weight:700;color:var(--muted)}
.kdays{margin-left:auto;font-family:var(--mono);font-size:10.5px;color:var(--muted)}

/* Says what the list is, because a row of sentences appearing under the cursor
   is otherwise just a row of sentences. */
.slashhint{font-size:10.5px;color:var(--muted);padding:3px 10px 5px;
  letter-spacing:.02em}

/* The signature, outside the box it wraps. Small and grey on purpose: it is
   the same on every reply, so it is the part you should be able to look past
   while reading the part that changes. */
/* Outside the box, and clearly not part of it: smaller, lighter, and with no
   border of its own. The box has the border now, so the eye lands on the one
   thing that is editable. */
/* Tinted, so it reads as fixed chrome rather than as text somebody forgot to
   delete. It was plain grey on the same white as the box -- indistinguishable
   from a half-written reply, which is why it did not look like anything. */


/* The signature brackets the box, so the three read as one message with a
   hole in the middle -- and the box loses the rounding that would break that. */
.composer .cbody{padding:0 14px}
.composer:has(.sigline) textarea{border-radius:0;border-top:0;border-bottom:0}

/* Readable, not whispered. At 11px pale grey it was the faintest text on the
   screen -- you could not check your own sign-off without leaning in. Same
   size as the reply, one shade lighter, on a tint that says "fixed". */
.sigline{font-size:13.5px;color:var(--ink-2);line-height:1.55;
  white-space:pre-wrap;background:var(--panel-2);padding:11px 16px;
  margin:0 14px}
.sigline.top{border-radius:9px 9px 0 0;margin-top:10px;
  border-bottom:1px solid var(--line)}
.sigline.bot{border-radius:0 0 9px 9px;margin-bottom:10px;
  border-top:1px solid var(--line)}

/* Says what it is, and offers the one thing you would want on seeing it. */
.sigtag{float:right;font-size:9px;font-weight:800;letter-spacing:.07em;
  text-transform:uppercase;color:var(--muted);opacity:.8}
.sigedit{border:0;background:none;padding:0 0 0 7px;cursor:pointer;
  font:inherit;font-size:9px;font-weight:800;letter-spacing:.07em;
  text-transform:uppercase;color:var(--accent-ink)}
.sigedit:hover{text-decoration:underline}

.sigprev{font-family:inherit;font-size:13px;line-height:1.6;color:var(--ink-2);
  white-space:pre-wrap;margin:0;background:var(--panel-2);padding:12px 14px;
  border-radius:10px;border:1px solid var(--line)}

/* How much more common a phrase is than usual -- the number the Recurring
   ranking is actually made of. Shown because otherwise the order looks
   arbitrary whenever a smaller count sits above a larger one. */
.liftup{font-family:var(--mono);font-size:12px;font-weight:700;
  color:var(--accent-ink);background:var(--accent-soft);
  padding:2px 8px;border-radius:6px}

/* Remarks in the rail. Left-ruled rather than bubbled: they are margin notes
   on the ticket, not messages in the thread. */
/* Remarks in the rail. A thread: an initial, who and when on one line, what
   they said in a bubble under it, and a line joining each to the next. */
.rmkct{font-size:10.5px;font-weight:700;color:var(--accent-ink);
  background:var(--accent-soft);padding:1px 7px;border-radius:20px}
.rmklist{display:flex;flex-direction:column}
.rmk{display:flex;gap:10px;position:relative;padding-bottom:14px}
.rmk:last-child{padding-bottom:0}
.rmk:not(:last-child)::before{content:"";position:absolute;left:11px;top:28px;
  bottom:4px;width:2px;border-radius:2px;background:var(--line2)}
.rmkav{width:24px;height:24px;border-radius:50%;flex:none;display:flex;
  align-items:center;justify-content:center;font-size:9.5px;font-weight:800;
  letter-spacing:-.02em;background:var(--accent-soft);color:var(--accent-ink)}
.rmkmain{flex:1;min-width:0}
.rmkhead{display:flex;align-items:center;gap:8px;min-height:24px}
.rmkwho{font-size:12.5px;font-weight:700;color:var(--ink);overflow:hidden;
  text-overflow:ellipsis;white-space:nowrap}
.rmkwhen{margin-left:auto;flex:none;font-size:10.5px;font-weight:500;color:var(--muted)}
.rmkto{display:inline-block;font-size:10.5px;font-weight:700;color:var(--accent-ink);
  background:var(--accent-soft);padding:1px 8px;border-radius:20px;margin:2px 0 1px}
.rmkbody{font-size:13px;color:var(--ink2);line-height:1.5;white-space:pre-wrap;
  word-break:break-word;background:var(--panel-2);border:1px solid var(--line2);
  border-radius:3px 10px 10px 10px;padding:8px 11px;margin-top:4px}
.rmkmore{display:block;width:100%;margin-top:12px;padding:7px;cursor:pointer;
  border:1px dashed var(--line);border-radius:9px;background:none;
  font:inherit;font-size:12px;font-weight:650;color:var(--accent-ink)}
.rmkmore:hover{background:var(--accent-soft);border-color:transparent}

/* The date under a remark's author. */
.rmkdate{font-size:11px;color:var(--muted);margin-top:-3px}

/* Reopened: a finished ticket sent back after its answer. */
.reopill{display:inline-flex;align-items:center;padding:3px 10px;border-radius:20px;
  font-size:11px;font-weight:700;background:var(--accent);color:#fff;white-space:nowrap}
.reochip{display:inline-block;font-size:10px;font-weight:800;letter-spacing:.05em;
  text-transform:uppercase;color:var(--accent-ink);background:var(--accent-soft);
  border:1px solid var(--accent2);padding:1px 7px;border-radius:20px;
  margin:0 6px 3px 0;vertical-align:2px;line-height:1.5}

/* Feedback in the ticket rail, one entry per answer. */
.fbh{padding:9px 0;border-top:1px solid var(--line2)}
.fbhist h3 + .fbh{border-top:0;padding-top:0}
.fbhtop{display:flex;align-items:center;gap:8px}
.fbhround{font-size:12px;font-weight:700;color:var(--ink)}
.fbhwhen{margin-left:auto;font-size:10.5px;color:var(--muted)}
.fbhq{font-size:12.5px;color:var(--ink2);margin-top:5px;line-height:1.45;
  white-space:pre-wrap;word-break:break-word}
.fbhby{font-size:11px;color:var(--muted);margin-top:4px}
.fbh.old{opacity:.72}

/* Past ratings, nested inside the new one -- on the Feedback page and in the
   ticket's rail. */
.fbold{margin-top:9px;display:flex;flex-direction:column;gap:8px;padding:8px 10px;
  background:var(--panel-2);border:1px solid var(--line2);border-radius:9px}
.fboldrow + .fboldrow{border-top:1px solid var(--line2);padding-top:8px}
.fboldn{font-size:10px;font-weight:800;color:var(--muted);text-transform:uppercase;
  letter-spacing:.05em;margin-bottom:4px}
.fboldq{font-size:12px;color:var(--ink2);margin-top:4px;white-space:pre-wrap;word-break:break-word}
.fboldby{font-size:11px;color:var(--muted);margin-top:2px}
.fbhist .fbold .fbhtop .vpill{transform:scale(.92);transform-origin:left center}

/* Similar complaints. One line each; hovering drops the whole complaint open
   beneath it. The drop animates its height with the grid-rows trick, so it
   needs no fixed height. */
.simcard h3.simsub{margin-top:16px}
.sim{padding:9px 0 8px;border-top:1px solid var(--line2);cursor:default}
.simcard h3 + .sim{border-top:0;padding-top:0}
.simtop{display:flex;align-items:center;gap:10px}
.simtext{flex:1;min-width:0;font-size:13px;color:var(--ink);white-space:nowrap;
  overflow:hidden;text-overflow:ellipsis}
.simact{flex:none;border:0;background:none;padding:2px 0;cursor:pointer;font:inherit;
  font-size:11.5px;font-weight:700;color:var(--accent-ink)}
.simact:hover{text-decoration:underline}
.simact.quiet{color:var(--muted)}
/* Days since it arrived, set like the Days column in the list. */
.simdays{font-family:var(--mono);font-size:13px;font-weight:650;color:var(--ink2);margin-top:3px}
.simdays.stale{color:var(--danger-ink)}
.simref{margin-top:6px;font-size:11px;color:var(--muted)}
.simdrop{display:grid;grid-template-rows:0fr;transition:grid-template-rows .18s ease}
.simdrop > div{overflow:hidden;min-height:0}
.sim:hover .simdrop, .sim.open .simdrop{grid-template-rows:1fr}
.simfull{margin-top:7px;font-size:12.5px;line-height:1.5;color:var(--ink2);
  white-space:pre-wrap;word-break:break-word;background:var(--accent-soft);
  border-radius:3px 10px 10px 10px;padding:8px 11px;max-height:260px;overflow:auto}
.banner a.bannerlink{color:var(--accent-ink);font-weight:700;cursor:pointer;
  text-decoration:underline}

/* The student's other tickets, in the same shape as Similar complaints. */
.sim.hist{cursor:pointer}
.histcard .cardfold + .sim{border-top:0;padding-top:2px}
.histmeta{display:flex;align-items:center;gap:8px;font-size:11px;color:var(--muted);
  margin-top:4px}
.histmeta .pill{font-size:10px;padding:2px 8px}

/* Column headings: each opens a menu to sort by it or show only some values. */
table.tbl th.colh{cursor:pointer;user-select:none}
table.tbl th.colh:hover, table.tbl th.colh.on{color:var(--accent-ink)}
th.colh .sarr{margin-left:4px;font-size:12px}
th.colh .colfn{display:inline-flex;align-items:center;justify-content:center;min-width:16px;
  height:16px;padding:0 4px;margin-left:5px;border-radius:8px;background:var(--accent);
  color:#fff;font-size:10px;font-weight:700;vertical-align:1px}
th.colh .colcar{margin-left:5px;font-size:9px;opacity:.4}
th.colh:hover .colcar, th.colh.on .colcar{opacity:1}

.colmenu{position:fixed;z-index:90;min-width:220px;max-width:300px;overflow-y:auto;
  background:var(--panel);border:1px solid var(--line);border-radius:12px;
  box-shadow:0 14px 34px rgba(30,27,75,.18);padding:6px}
.cmh{display:flex;align-items:center;font-size:10px;font-weight:800;letter-spacing:.08em;
  text-transform:uppercase;color:var(--muted);padding:9px 8px 4px}
.cmh:first-child{padding-top:4px}
.cmclear{margin-left:auto;border:0;background:none;cursor:pointer;font:inherit;
  font-size:10px;font-weight:800;letter-spacing:.08em;color:var(--accent-ink)}
.cmopt{display:flex;align-items:center;gap:9px;width:100%;border:0;background:none;
  cursor:pointer;text-align:left;font:inherit;font-size:13px;color:var(--ink);
  padding:7px 8px;border-radius:8px}
.cmopt:hover{background:var(--accent-soft)}
.cmopt.on{color:var(--accent-ink);font-weight:650}
.cmdot{width:9px;height:9px;border-radius:50%;border:1.5px solid var(--muted);flex:none}
.cmopt.on .cmdot{background:var(--accent);border-color:var(--accent)}
.cmbox{width:16px;height:16px;border-radius:5px;border:1.5px solid var(--muted);flex:none;
  display:flex;align-items:center;justify-content:center;font-size:11px;font-weight:800;color:#fff}
.cmopt.on .cmbox{background:var(--accent);border-color:var(--accent)}
.cmlabel{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.cmct{font-size:11px;color:var(--muted);font-variant-numeric:tabular-nums}
.cmnone{font-size:12px;color:var(--muted);padding:6px 8px}

/* Search the values, tick what to show, sort underneath -- the order a
   spreadsheet's filter puts them in. */
.cmsearch{width:100%;box-sizing:border-box;margin-bottom:4px;padding:7px 10px;
  border:1px solid var(--line);border-radius:9px;background:var(--panel-2);
  font:inherit;font-size:12.5px;color:var(--ink)}
.cmsearch:focus{outline:none;border-color:var(--accent);background:var(--panel)}
.cmtools{display:flex;gap:14px;padding:3px 8px 6px}
.cmlink{border:0;background:none;padding:0;cursor:pointer;font:inherit;font-size:11px;
  font-weight:700;color:var(--accent-ink)}
.cmlink:hover{text-decoration:underline}
.cmlist{max-height:230px;overflow-y:auto}
.cmdiv{height:1px;background:var(--line2);margin:6px 4px}

/* The Filter button, and the arrow it points at. */
.fico{vertical-align:-2px}
/* Icon only, so it stays square rather than a button with a gap where a word was. */
.btn.iconbtn{padding:7px 10px;line-height:0}
.btn.iconbtn .fcount{margin-left:5px;line-height:1}
th.colh .colcar.big{font-size:13px;opacity:1;color:var(--accent)}
.colchips{margin-bottom:10px;gap:6px}

/* Ticking tickets in the list to merge them. */
table.tbl th.c-pick, table.tbl td.c-pick{width:34px;padding-left:14px;padding-right:0;cursor:default}
.pickbox{width:16px;height:16px;margin:0;vertical-align:middle;cursor:pointer;
  accent-color:var(--accent)}
table.tbl tr.picked td{background:var(--accent-soft)}
.pickbar{position:fixed;left:50%;bottom:22px;transform:translateX(-50%);z-index:40;
  display:flex;align-items:center;gap:8px;background:var(--panel);
  border:1px solid var(--line);border-radius:14px;
  box-shadow:0 14px 34px rgba(30,27,75,.2);padding:8px 9px 8px 16px}
.pbn{font-size:13px;font-weight:650;color:var(--ink);margin-right:8px;white-space:nowrap}

.mglist{margin-top:14px;display:flex;flex-direction:column;gap:10px;max-height:55vh;overflow-y:auto}
.mggroup{border:1px solid var(--line);border-radius:12px;padding:10px 12px}
.mgwho{font-size:13px;font-weight:700;color:var(--ink);margin-bottom:4px}
.mgwho span{font-weight:500;color:var(--muted);margin-left:8px;font-size:11.5px}
.mgrow{display:flex;align-items:center;gap:10px;padding:6px 4px;border-radius:8px;cursor:pointer}
.mgrow:hover{background:var(--panel-2)}
.mgrow input{margin:0;accent-color:var(--accent);flex:none}
.mgno{font-family:var(--mono);font-size:11.5px;color:var(--muted);flex:none}
.mgtext{flex:1;min-width:0;font-size:13px;color:var(--ink2);white-space:nowrap;
  overflow:hidden;text-overflow:ellipsis}
.mgdays{font-family:var(--mono);font-size:12.5px;font-weight:650;color:var(--ink2);flex:none}
.mgrow:has(input:checked) .mgtext{color:var(--ink);font-weight:600}

/* My signature: one for all, or one per outcome. */
.viewsw.sigmode{margin:0 0 14px}
.chips.sigouts{margin:0 0 14px}

/* Priority: departments with nothing to give a level to yet. */
.pribare{margin:0 0 14px;padding:12px 14px;border:1px dashed var(--accent2);
  border-radius:12px;background:var(--accent-soft)}
.pribareh{font-size:12.5px;font-weight:700;color:var(--accent-ink);margin-bottom:8px}
.pribarewhy{font-weight:500;color:var(--muted);margin-left:6px;font-size:11.5px}
.pribarelist{display:flex;flex-wrap:wrap;gap:8px}
.pribarelist .pricat{width:auto;background:var(--panel)}

/* The signature, taken off this reply. Says so, and offers it back. */
.sigline.off{color:var(--muted);font-size:11.5px;padding:9px 16px}


/* ------------------------------------------------------------- time limits
   A department per row, a priority per column group, and an hour per column.
   The heading is two decks: the priority and its limit on top, the marks that
   limit produces underneath, so a number can be read without knowing anything
   about how the bands were decided. */
.limtbl th,.limtbl td{vertical-align:middle}
.limtbl .c-dept{min-width:170px}
/* Remind sits with the department name, because the name IS the thing being
   reminded about. Pushed right so the column of names stays a column. */
/* Remind is its own last column. It used to sit inside the department cell,
   which needed that cell to be a flex box -- and a heading cell that is a flex
   box stops being a table cell, so its rowspan was dropped and the whole
   second heading row slid one column left. */
.limtbl .c-rem{text-align:right;width:1%;white-space:nowrap;border-left:1px solid var(--line2)}
.limrem{white-space:nowrap}

.limtbl th.limgrp{text-align:center;border-left:1px solid var(--line);
  padding-bottom:6px;white-space:nowrap}
.limtbl th.limgrp .prio{margin-right:6px}
.limgrph{font-size:11px;color:var(--muted);font-weight:600}

.limtbl th.limsub{text-align:center;min-width:78px;padding-top:4px;padding-bottom:8px;
  white-space:nowrap;vertical-align:top}
.limrng{display:block;font-family:var(--mono);font-size:11.5px;font-weight:700;color:var(--ink2)}
.limwhat{display:block;font-size:10.5px;font-weight:500;color:var(--muted);margin-top:2px}
.limtbl th.limsub.over .limrng{color:var(--danger)}

/* The left edge of each group is the only rule in the body, so four groups
   read as four blocks rather than as twelve loose columns. */
.limtbl td.limcell{text-align:center;padding-left:0;padding-right:0}
.limtbl th.limsub.grpstart,
.limtbl td.limcell.grpstart{border-left:1px solid var(--line2)}

.limzero{color:var(--line3);font-family:var(--mono);font-size:13px}

/* A count is a button because the only thing anybody wants from it is the
   tickets behind it. A zero is not: there is nothing to open. */
.limn{font-family:var(--mono);font-size:14px;font-weight:700;cursor:pointer;
  min-width:38px;padding:5px 8px;border-radius:var(--radius-sm);
  border:1px solid transparent;background:transparent;color:var(--ink2);transition:.13s}
.limn:hover{border-color:var(--line3);color:var(--ink)}
.limn.over{color:var(--danger);background:var(--danger-soft)}
.limn.on{border-color:var(--accent);box-shadow:var(--ring)}

.limopen>td{padding:0 !important;background:var(--panel-2)}
.limlist{padding:4px 0 10px}
.limlisth{font-size:11.5px;font-weight:700;letter-spacing:.04em;text-transform:uppercase;
  color:var(--muted);padding:10px 16px 8px}
.limrowi{display:grid;
  grid-template-columns:88px 140px minmax(0,1fr) 130px 110px 150px;
  gap:12px;align-items:center;padding:9px 16px;cursor:pointer;
  border-top:1px solid var(--line2);font-size:12.5px}
.limrowi:hover{background:var(--panel)}
.limno{font-family:var(--mono);font-size:11.5px;color:var(--muted)}
.limwho{font-weight:650;color:var(--ink);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.limsubj{color:var(--ink2);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.limown{color:var(--muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.limspent{font-family:var(--mono);font-size:11.5px;color:var(--muted);text-align:right;
  white-space:nowrap}
.limover{color:var(--danger);font-weight:700}
.limleft{color:var(--green-ink)}

@media (max-width:1100px){
  .limrowi{grid-template-columns:80px minmax(0,1fr) 130px;
    grid-template-areas:'no who spent' 'sub sub sub'}
  .limno{grid-area:no}.limwho{grid-area:who}.limsubj{grid-area:sub}
  .limspent{grid-area:spent}
  .limown,.limst{display:none}
}

/* ---- the setting itself: four numbers, and what each one works out to ---- */
.limset{padding:20px 22px}
.limsetrow{display:grid;grid-template-columns:110px 150px minmax(0,1fr);gap:14px;
  align-items:center;padding:12px 0;border-bottom:1px solid var(--line2)}
.limsetrow:last-of-type{border-bottom:0}
.limsetin input{width:88px;border:1px solid var(--line);border-radius:var(--radius-sm);
  padding:8px 10px;font-size:14px;font-family:var(--mono);color:var(--ink);background:var(--panel)}
.limsetin input:focus{outline:none;border-color:var(--accent);box-shadow:var(--ring)}
.limsetnote{margin-top:16px;padding:12px 14px;background:var(--panel-2);
  border:1px solid var(--line2);border-radius:var(--radius-sm);
  font-size:12.5px;color:var(--muted);line-height:1.5}

/* ---------------------------------------------------- need more data pool
   The phone number is what the intern dials from, so it is the loudest thing
   on the row; the question is what they say once it connects. */
.pooltbl td{vertical-align:top}
.poolwho{font-weight:650;color:var(--ink);cursor:pointer}
.poolwho:hover{color:var(--accent-ink);text-decoration:underline}
.poolphone{font-family:var(--mono);font-size:14px;font-weight:700;color:var(--ink);white-space:nowrap}
.poolq{color:var(--ink2);max-width:360px;white-space:pre-wrap}
.poolask{margin-top:12px;padding:10px 12px;background:var(--panel-2);
  border:1px solid var(--line2);border-radius:var(--radius-sm);white-space:pre-wrap}

/* Stars from the feedback page, beside the Helped / Did not help verdict. */
.vstars{display:inline-block;margin-left:6px;color:#f59e0b;font-size:13px;letter-spacing:1px;
  vertical-align:middle;white-space:nowrap}

/* Dark mode, calmer accent: the buttons, the selected nav item and the round
   badges carry their own bright violet in light mode. On a dark ground that
   glared, so here they use the toned-down accent and drop the coloured glow. */
:root[data-theme="dark"] .btn:not(.ghost):not(.danger){background:linear-gradient(180deg,#8479cc,#7066b8);
  box-shadow:0 1px 3px rgba(0,0,0,.4)}
:root[data-theme="dark"] .btn:not(.ghost):not(.danger):hover{filter:brightness(1.08);box-shadow:0 3px 10px rgba(0,0,0,.45)}
:root[data-theme="dark"] .navitem.on{background:#2c2b3d;color:#ecebf7;
  box-shadow:inset 3px 0 0 var(--accent)}
:root[data-theme="dark"] .stepdot.on{background:#6f66b8;box-shadow:none}
:root[data-theme="dark"] .prole.agent .pic{background:linear-gradient(140deg,#8f85d4,#6f66b8);
  box-shadow:0 3px 10px rgba(0,0,0,.4)}
:root[data-theme="dark"] .tag.mid .tprio,:root[data-theme="dark"] .tag.lo .tprio{background:rgba(155,144,224,.12)}
:root[data-theme="dark"] .tag.mid .tprio:hover,:root[data-theme="dark"] .tag.lo .tprio:hover{background:rgba(155,144,224,.22)}
:root[data-theme="dark"] .av:not(.stu):not(.int):not(.men){background:linear-gradient(140deg,#8f85d4,#6f66b8);box-shadow:none}

/* The Help Center mark: a speech bubble with a question in it, white on the
   violet tile. Sized to the tile, so every .logo gets it. */
.logo .logomark{width:80%;height:80%;display:block}
/* An app-icon tile: near-black glass, a violet light catching two edges,
   silver rings. The same in both themes -- it is a mark, not a surface.
   Placed last so it wins over the older gradient rules. */
.logo,:root[data-theme="dark"] .logo{
  background:linear-gradient(160deg,#26272f,#0e0f13) padding-box,
    linear-gradient(135deg,rgba(169,159,232,.95),rgba(169,159,232,0) 45%,rgba(169,159,232,.7)) border-box;
  border:1.5px solid transparent;border-radius:10px;width:38px;height:38px;
  box-shadow:0 0 14px rgba(169,159,232,.22),inset 0 1px 0 rgba(255,255,255,.07)}
/* Point at the mark and the helper leans in toward the student. */
.logo .lm-helper{transition:transform .35s cubic-bezier(.3,.7,.3,1)}
.logo:hover .lm-helper{transform:translate(-1.1px,-.9px)}
@media (prefers-reduced-motion:reduce){.logo .lm-helper{transition:none}}

/* Dark mode popups: the dialog was the same grey as the page behind it and the
   dimming was too faint, so a popup read as a hazy smear over the ticket. A
   properly dark backdrop, and a dialog a step lighter with a visible edge. */
:root[data-theme="dark"] #overlay,:root[data-theme="dark"] #overlay2{
  background:rgba(4,5,8,.72);backdrop-filter:blur(3px)}
:root[data-theme="dark"] #modal:not(.tkmodal),:root[data-theme="dark"] #modal2{
  background:#24252c;border:1px solid #3b3c46;
  box-shadow:0 24px 70px rgba(0,0,0,.75)}
:root[data-theme="dark"] #modal .modalx,:root[data-theme="dark"] #modal2 .modalx{background:#2c2d35}
/* The little message at the bottom ("Remark added..."). It borrowed the ink
   colour as its background, which in dark mode is near-white -- with white
   text on it. Dark card, light text, green edge for done, red for errors. */
:root[data-theme="dark"] .toast{background:#2a2b33;color:#ededf2;border:1px solid #3f404b;
  box-shadow:0 10px 30px rgba(0,0,0,.6)}
:root[data-theme="dark"] .toast:not(.err){border-left:3px solid var(--green)}
:root[data-theme="dark"] .toast.err{background:#4a1730;color:#ffe4ea;border-color:#87305a}

/* A sub-department name is also the button that moves it elsewhere. */
.subname{background:none;border:0;padding:0;color:var(--ink);font:inherit;cursor:pointer;
  display:inline-flex;align-items:center;gap:6px;text-align:left}
.subname:hover{color:var(--accent)}
.subcar{color:var(--muted);font-size:10px}
.subname:hover .subcar{color:var(--accent)}

/* "Cannot be solved": finished, but nothing was fixed. Its own colour, so it
   is never read as a solved ticket at a glance. */
.sunres{--st:#e0894a}
.pill.unresolvable{background:var(--amber-soft);color:var(--amber-ink);
  border:1px solid var(--amber-line)}
.stgname.sunresolvable{color:var(--amber-ink)}

/* ------------------------------------------------------ multi-select
   Notion's way: a row's box is there only when you point at the row, so the
   list reads clean. Once anything is ticked every box shows, and the bar at
   the bottom says what you can do with them. On a touch screen, where there
   is no pointing, the boxes are always there. */
table.tbl.list2 .c-sel{width:40px;padding-left:12px;padding-right:0;cursor:pointer}
table.tbl.list2 .c-sel input{width:16px;height:16px;margin:2px 0 0;cursor:pointer;
  accent-color:var(--accent);opacity:0;transition:opacity .12s}
table.tbl.list2 tr:hover .c-sel input,
table.tbl.list2.selecting .c-sel input,
table.tbl.list2 .c-sel input:focus-visible,
table.tbl.list2 th.c-sel input{opacity:1}
table.tbl.list2 th.c-sel input{opacity:.55}
table.tbl.list2.selecting th.c-sel input, table.tbl.list2 th.c-sel:hover input{opacity:1}
@media (hover: none){ table.tbl.list2 .c-sel input{opacity:.7} }
table.tbl.list2 tr.picked td{background:var(--accent-soft)}

.bulkbar{position:fixed;left:50%;bottom:22px;transform:translateX(-50%);z-index:60;
  display:flex;align-items:center;gap:6px;flex-wrap:wrap;justify-content:center;
  max-width:calc(100vw - 32px);padding:8px 8px 8px 16px;border-radius:14px;
  background:var(--panel);border:1px solid var(--line);box-shadow:var(--shadow-lg);
  animation:pop .18s ease}
.bulkbar .bbn{font-size:13px;color:var(--ink);margin-right:6px;white-space:nowrap}
.bulkbar .bblink{background:none;border:0;padding:7px 10px;border-radius:9px;cursor:pointer;
  font:600 12.5px Inter,sans-serif;color:var(--accent-ink);white-space:nowrap}
.bulkbar .bblink:hover{background:var(--accent-soft)}
.bulkbar .bbx{background:none;border:0;width:30px;height:30px;border-radius:9px;cursor:pointer;
  font-size:18px;line-height:1;color:var(--muted)}
.bulkbar .bbx:hover{background:var(--panel-2);color:var(--ink)}

.bkchips{display:flex;flex-wrap:wrap;gap:6px;margin:4px 0 14px}
.bkchip{border:1px solid var(--line);background:var(--panel);color:var(--ink2);cursor:pointer;
  padding:7px 12px;border-radius:999px;font:600 12.5px Inter,sans-serif}
.bkchip:hover{border-color:var(--accent2)}
.bkchip.on{background:var(--accent);border-color:var(--accent);color:#fff}

/* The student's mentor, under their name in every list. */
.mnt{font-size:11px;color:var(--muted);margin-top:2px;white-space:nowrap;overflow:hidden;
  text-overflow:ellipsis}
.kcard .mnt{margin-top:1px}

/* Files CRA attaches after a call: small pictures under the remark's words,
   each opening full size. */
.rmkfiles{display:flex;flex-wrap:wrap;gap:6px;margin-top:8px}
.rmkimg{display:block;width:72px;height:72px;border-radius:8px;overflow:hidden;
  border:1px solid var(--line);background:var(--panel-2)}
.rmkimg img{width:100%;height:100%;object-fit:cover;display:block}
.rmkimg:hover{border-color:var(--accent2)}


/* Board columns: three equal columns that share the full width (2026-10-06).
   Fixed 300px left blank space on wide screens; plain stretching made two
   columns wide while Done sat folded. Equal shares, Done open, no gap.
   A folded column still shrinks to its heading. */
.kcol{flex:1 1 0;width:auto;min-width:260px}
.kcol.shut{flex:0 0 auto;width:auto}

/* App form (Settings): the student app's categories, sub-categories and questions. */
.afnode{background:var(--panel);border:1px solid var(--line);border-radius:var(--radius);padding:14px 16px;margin-bottom:12px}
.afnode.sub{background:var(--panel-2);margin:10px 0 0;padding:12px 14px}
.afnode.off{opacity:.62}
.afhead{display:flex;align-items:flex-end;gap:12px;flex-wrap:wrap}
.afhead .aflabel{flex:1 1 220px;min-width:180px;font-weight:600}
.afhead .afroute{flex:0 1 260px;min-width:180px}
.afhead span.afroute{flex:0 1 260px}
.afshow{gap:6px;cursor:pointer;white-space:nowrap}
.afqmove{display:inline-flex;gap:4px}
.afqmove .iconbtn{width:28px;height:28px;padding:0;display:inline-flex;align-items:center;justify-content:center;font-size:13px}
.afqmove .iconbtn:disabled{opacity:.35;cursor:default}
.afwarn{margin-top:8px;font-size:12.5px;color:var(--amber-ink);background:var(--amber-soft);border:1px solid var(--amber-line);border-radius:8px;padding:6px 10px}
.afq{margin-top:12px;display:flex;flex-direction:column;gap:6px;align-items:flex-start}
.afqrow{display:flex;align-items:center;gap:10px;width:100%;padding:6px 8px;border:1px solid var(--line2);border-radius:8px;background:var(--panel)}
.afqrow.off{opacity:.6}
.afqlabel{flex:1;min-width:0}
.afreq{font-size:11px;font-weight:600;color:var(--danger-ink);background:var(--danger-soft);border-radius:6px;padding:1px 6px;margin-left:4px}
.afnone{padding:2px 0}
/* An icon button carried no colour of its own, so a bare <button> fell back to the browser's
   default near-black - invisible on a dark panel, which is how the move arrows became two empty
   squares. */
.iconbtn{color:var(--ink)}
.iconbtn:disabled{color:var(--muted);opacity:.45}
/* What this box is. Said in a word rather than left to the indentation. */
.afkind{display:flex;align-items:center;gap:8px;margin-bottom:10px}
.aftag{font-size:11px;font-weight:700;letter-spacing:.04em;text-transform:uppercase;
  color:var(--accent-ink,var(--ink));background:var(--accent-soft,var(--panel-2));
  border:1px solid var(--line2);border-radius:999px;padding:3px 9px}
.aftag.sub{color:var(--muted);background:transparent}
.afoffpill{font-size:11px;color:var(--muted);border:1px dashed var(--line2);border-radius:999px;padding:3px 9px}
.afkind .afqmove{margin-left:auto}
.afkind .afdel{color:var(--muted)}
/* Each control says what it is, above it. Two boxes side by side with no labels read as the same
   thing written twice. */
.affield{display:flex;flex-direction:column;gap:4px;flex:1 1 220px;min-width:180px}
/* The sizing belongs to the labelled column now. Left on the input and the dropdown it was read
   down the column instead of across the row, so "flex-basis:260px" became 260px of HEIGHT and
   both boxes grew into the empty squares you see when a row stops making sense. */
.affield .aflabel,.affield .afroute{flex:0 0 auto;min-width:0;width:100%}
.aflbl{font-size:11.5px;color:var(--muted)}
.afroutenote{display:flex;align-items:center;font-size:12.5px;color:var(--muted);
  border:1px dashed var(--line2);border-radius:var(--radius-sm,8px);padding:8px 10px;min-height:38px}
.afqhead{font-size:11.5px;color:var(--muted);margin-bottom:2px}
.afsubhead{font-size:11.5px;color:var(--muted);margin-bottom:8px}
.afsubs{margin-top:14px;padding-left:14px;border-left:2px solid var(--line)}
.afsubs > .btn{margin-top:10px}
@media (max-width:640px){.afhead .aflabel,.afhead .afroute{flex:1 1 100%}}

/* FAQs (Settings): the student app's FAQs. */
.fqlist{display:flex;flex-direction:column;gap:8px}
.fqrow{display:flex;align-items:center;gap:12px;background:var(--panel);border:1px solid var(--line);border-radius:var(--radius);padding:10px 14px}
.fqrow.retired{opacity:.6}
.fqmain{flex:1;min-width:0}
.fqq{font-weight:600;color:var(--ink)}
.fqstar{color:var(--amber)}
.fqstatus{font-size:11.5px;font-weight:600;border-radius:999px;padding:2px 9px;white-space:nowrap}
.fqstatus.draft{background:var(--panel-3);color:var(--ink2)}
.fqstatus.published{background:var(--green-soft);color:var(--green-ink)}
.fqstatus.retired{background:var(--panel-3);color:var(--muted)}
.fasum{display:grid;grid-template-columns:repeat(5,minmax(0,1fr));gap:10px}
.fasum>div{background:var(--panel);border:1px solid var(--line);border-radius:var(--radius);padding:10px 14px}
.fasum b{display:block;font-size:20px;color:var(--ink)}
.fasum span{font-size:12px;color:var(--muted)}
.fabar{width:110px;height:6px;border-radius:99px;background:var(--panel-2);overflow:hidden;flex:none}
.fabar>span{display:block;height:100%;background:var(--accent);border-radius:99px}
.fasplit{width:110px;height:6px;border-radius:99px;background:var(--panel-2);overflow:hidden;display:flex;flex:none}
.fasplit .up{background:var(--green)}.fasplit .down{background:var(--danger)}
.fanum{min-width:56px;text-align:right;font-weight:700;color:var(--ink);line-height:1.1}
.fanum small{display:block;font-weight:500;font-size:11px;color:var(--muted)}
.fanum.good,.fagood{color:var(--green-ink)}.fanum.bad,.fanone,.fabad{color:var(--danger)}
.fanone,.fabad,.fagood{font-weight:600}
.falog{gap:14px}.fawhen{font-size:12px;color:var(--muted);white-space:nowrap;min-width:110px}
.fawho{font-size:12px;font-family:ui-monospace,monospace;color:var(--muted);white-space:nowrap}
@media (max-width:760px){.fasum{grid-template-columns:repeat(2,minmax(0,1fr))}.fabar,.fasplit{display:none}
  .falog{flex-wrap:wrap}.falog .fqmain{flex-basis:100%}}
.fqtest{font-size:10.5px;font-weight:700;letter-spacing:.05em;color:var(--amber-ink);background:var(--amber-soft);border:1px solid var(--amber-line);border-radius:6px;padding:1px 6px}
.fqedit{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:18px;align-items:start}
.fqblock{border:1px solid var(--line);border-radius:8px;padding:8px;margin-bottom:8px;background:var(--panel-2)}
.fqpreviewbox{border:1px solid var(--line);border-radius:12px;padding:14px 16px;background:var(--panel);max-height:60vh;overflow:auto}
.fqpq{font-weight:700;font-size:15px;margin-bottom:8px;color:var(--ink)}
.fqpara{margin:0 0 10px;line-height:1.5}
.fqsteps{margin:0 0 10px;padding-left:20px;line-height:1.5}
.fqnote{margin:0 0 10px;padding:10px 12px;border-radius:8px;background:var(--accent-soft);border-left:3px solid var(--accent);color:var(--ink)}
@media (max-width:760px){.fqedit{grid-template-columns:1fr}}
