/* apps/website/html/css/app.css — the haustor shell and its component vocabulary.
   Built on css/system.css, which every haustor page links first. Per §8.6 nothing here
   defines a colour, a typeface or a radius; per §4 a --surface fill means a measured value,
   so only .a-card carries one; per §5 glyphs belong to buttons, so no component draws an icon.

   This file exists so a page conversion is mostly deletion: the shapes below repeat across
   the pages (203 button uses, 60 cards, 52 fields, 48 rows), and leaving them page-local is
   what let the old inline CSS drift to 2,472 lines. */

/* ── Layout ──────────────────────────────────────────────────────────────── */
.main.a-main { margin-left:34px; height:100vh; display:flex; flex-direction:column; min-height:0 }
.a-scroll { flex:1; overflow-y:auto; min-height:0 }

/* ── Rail: a 34px position code. Six marks, always; role filtering hides one in
   place so mark 3 is College for everyone (§5.1). ─────────────────────────── */
.a-rail { position:fixed; top:0; left:0; bottom:0; width:34px; border-right:1px solid var(--line);
  background:var(--bg); display:flex; flex-direction:column; align-items:center;
  padding:15px 0; cursor:pointer; z-index:60 }
.a-rail:focus-visible { outline:2px solid var(--edge); outline-offset:-2px }
.a-mark { width:2px; height:12px; background:var(--edge); margin-bottom:8px; flex:0 0 auto }
.a-mark.active { height:16px; background:var(--ink-2) }
.a-mark.attention { background:var(--warn) }
.a-mark.hidden { visibility:hidden }
.a-rail-wm { margin-top:auto; writing-mode:vertical-rl; font-size:9px; letter-spacing:.2em;
  text-transform:uppercase; color:var(--ink-5) }

/* ── Drawer ──────────────────────────────────────────────────────────────── */
.a-scrim { position:fixed; inset:0; background:rgba(0,0,0,.45); z-index:20000 }
.a-drawer { position:fixed; top:0; left:0; bottom:0; width:240px; background:var(--bg);
  border-right:1px solid var(--edge); z-index:20001; padding:18px 0; display:flex;
  overflow-y:auto; overflow-x:hidden;
  flex-direction:column }
.a-drawer-wm { font-size:15px; font-weight:700; color:var(--ink); letter-spacing:-.02em;
  padding:0 18px 20px }
.a-drawer a { display:flex; justify-content:space-between; align-items:baseline; gap:10px;
  padding:7px 18px; font-size:14px; color:var(--ink-2); text-decoration:none;
  transition:background 120ms ease }
.a-drawer a:hover { background:var(--surface) }
.a-drawer a.active { color:var(--ink); font-weight:600; background:var(--surface) }
.a-drawer a em { font-style:normal; font-size:11px; color:var(--ink-5) }
.a-drawer-foot { margin-top:auto; padding:14px 18px 0; font-size:11px; color:var(--ink-5) }
.a-drawer-foot button { display:block; font:inherit; font-size:12px; color:var(--ink-4);
  background:none; border:0; padding:5px 0; cursor:pointer; text-align:left }
.a-drawer-foot button:hover { color:var(--ink-2) }

/* ── Header ──────────────────────────────────────────────────────────────────
   Three columns so the search sits centred regardless of what flanks it. 64px
   (was 52) so the field's underline and the header's own rule are ~26px apart
   instead of ~15 — at 15px, two 1px --line rules read as one doubled line and
   neither wins. */
.a-hdr { display:grid; grid-template-columns:1fr auto 1fr; align-items:center; gap:16px;
  padding:0 24px; height:64px; flex:0 0 64px; border-bottom:1px solid var(--line) }
.a-hdr-title { font-size:16px; font-weight:600; color:var(--ink); letter-spacing:-.01em;
  justify-self:start; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap }
.a-hdr-search { justify-self:center; width:min(330px, 100%); min-width:0 }
.a-hdr-search .a-field { text-align:center }
.a-hdr-search .a-field.has-value { text-align:left }
.a-hdr-right { justify-self:end; display:flex; align-items:center; gap:16px; min-width:0 }
.a-hdr-meta { font-size:11px; color:var(--ink-5); font-variant-numeric:tabular-nums; white-space:nowrap }
/* .a-hdr-sp is retired by the grid; kept as a no-op so an un-migrated page doesn't break. */
.a-hdr-sp { display:none }

/* Narrow desktop: keep the search centred while giving the title and Alerts equal room.
   The clock is the least important header datum once these three items compete for width. */
@media (min-width: 621px) and (max-width: 780px) {
  .a-hdr { grid-template-columns:minmax(0,1fr) minmax(180px,330px) minmax(0,1fr) }
  .a-hdr-meta { display:none }
  .a-hdr-search { width:100% }
}

/* ── Notifications ─────────────────────────────────────────────────────────
   The shell creates this shared component dynamically. Unread is a measured state,
   so it alone receives a surface fill and a warning spine. */
.notif-wrap { position:relative; flex:0 0 auto }
.notif-badge { position:absolute; top:-7px; right:-8px; min-width:16px; height:16px; padding:0 4px;
  background:var(--err); color:var(--bg); font-size:10px; line-height:16px; text-align:center }
.notif-panel { position:absolute; top:calc(100% + 10px); right:0; width:320px; max-height:420px;
  overflow-y:auto; background:var(--bg); border:1px solid var(--edge); z-index:1000 }
.notif-head { display:flex; justify-content:space-between; align-items:center; padding:11px 13px;
  border-bottom:1px solid var(--line); font-size:13px; font-weight:600; color:var(--ink) }
.notif-readall { font:inherit; background:none; border:0; color:var(--ink-4); font-size:12px; cursor:pointer }
.notif-readall:hover { color:var(--ink) }
.notif-list { display:block }
.notif-empty { padding:24px; text-align:center; color:var(--ink-4); font-size:13px }
.notif-item { display:block; padding:11px 13px; border-bottom:1px solid var(--line-2);
  border-left:2px solid transparent; text-decoration:none; color:inherit }
.notif-item:last-child { border-bottom:0 }
.notif-item:hover { background:var(--surface) }
.notif-item.unread { background:var(--surface); border-left-color:var(--warn) }
.notif-item.unread:hover { border-left-color:var(--ink-2) }
.notif-title { font-size:13px; color:var(--ink); font-weight:500 }
.notif-body { font-size:12px; color:var(--ink-2); margin-top:2px }
.notif-time { font-size:11px; color:var(--ink-4); margin-top:4px }

/* ── Components ──────────────────────────────────────────────────────────── */
.a-row { display:flex; align-items:center; gap:12px; height:30px; padding:0 10px;
  text-decoration:none; color:var(--ink-2); transition:background 120ms ease }
.a-row + .a-row { border-top:1px solid var(--line-2) }
.a-row:hover { background:var(--surface) }
.a-row .n { flex:1; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
  font-size:13px; color:var(--ink) }
.a-row .m { font-size:11px; color:var(--ink-5) }

.a-table { width:100%; border-collapse:collapse; font-size:13px }
.a-table th { text-align:left; font-size:11px; letter-spacing:.13em; text-transform:uppercase;
  font-weight:500; color:var(--ink-5); padding:0 10px 8px; border-bottom:1px solid var(--line) }
.a-table td { padding:0 10px; height:30px; border-bottom:1px solid var(--line-2); color:var(--ink-2) }
.a-table td.n, .a-table th.n { text-align:right; font-variant-numeric:tabular-nums }
.a-table tbody tr:hover td { background:var(--surface) }

/* §4: a fill means a measured value. Not a generic container. */
.a-card { background:var(--surface); border-left:2px solid var(--edge); padding:10px 12px }
.a-card .k { display:block; font-size:12px; color:var(--ink-4); margin-bottom:3px }
.a-card .v { display:block; font-size:22px; font-weight:600; color:var(--ink); letter-spacing:-.015em }
.a-card.warn { border-left-color:var(--warn) } .a-card.err { border-left-color:var(--err) }

.a-tabs { display:flex; border-bottom:1px solid var(--line); padding:0 24px; flex:0 0 38px;
  align-items:center }
.a-tabs a, .a-tabs button { font:inherit; font-size:12px; color:var(--ink-4); background:none;
  border:0; border-bottom:2px solid transparent; padding:0 13px 10px; margin-top:10px;
  cursor:pointer; text-decoration:none; transition:color 120ms ease }
.a-tabs a:first-child, .a-tabs button:first-child { padding-left:0 }
.a-tabs .active { color:var(--ink); border-bottom-color:var(--edge) }

.a-field { font:inherit; font-size:14px; color:var(--ink); background:none; width:100%;
  border:0; border-bottom:1px solid var(--line); padding:6px 0; outline:none;
  transition:border-color 120ms ease }
.a-field::placeholder { color:var(--ink-5) }
.a-field:focus { border-bottom-color:var(--edge) }

.a-btn { font:inherit; display:inline-flex; align-items:center; gap:8px; font-size:13px;
  color:var(--ink-2); background:none; border:0; padding:0; cursor:pointer;
  transition:color 120ms ease }
.a-btn:hover { color:var(--ink) }
.a-btn svg { stroke:var(--ink-4); fill:none; stroke-width:1.4; flex-shrink:0 }
.a-btn:hover svg { stroke:var(--ink-2) }
.a-btn[disabled] { color:var(--ink-5); cursor:default }

.a-btn2 { font:inherit; font-size:13px; color:var(--ink-2); background:none; border:0;
  padding:0 11px; cursor:pointer; transition:color 120ms ease }
.a-btn2:first-child { padding-left:0 }
.a-btn2 + .a-btn2 { border-left:1px solid var(--line) }
.a-btn2:hover { color:var(--ink) }
.a-btn2.del:hover { color:var(--err) }

.a-chip { font-size:11px; color:var(--ink-5); border-bottom:1px solid var(--line);
  padding-bottom:2px; margin-right:8px }

.a-modal { position:fixed; inset:0; background:rgba(0,0,0,.55); display:none;
  align-items:center; justify-content:center; z-index:90 }
.a-modal.open { display:flex }
.a-modal-box { background:var(--bg); border:1px solid var(--edge); width:min(560px, calc(100vw - 40px));
  max-height:calc(100vh - 80px); overflow-y:auto; padding:20px 22px }
.a-modal-head { display:flex; justify-content:space-between; align-items:baseline;
  margin-bottom:16px }
.a-modal-head .t { font-size:16px; font-weight:600; color:var(--ink) }

@media (max-width: 620px) {
  .main.a-main > .main-scroll,
  .main.a-main-unwrapped,
  body > .right-sidebar,
  body > #linktree-panel { padding-bottom:calc(34px + env(safe-area-inset-bottom)); }
  .main.a-main { margin-left:0 !important }
  /* College uses document flow instead of .main-scroll on phones. Let the root grow with long
     notes/AI output so the trailing rail clearance follows content, not a fixed viewport box. */
  .main.a-main-unwrapped { height:auto; min-height:100dvh; box-sizing:border-box }
  .a-rail { top:auto; right:0; bottom:0; width:auto; height:calc(34px + env(safe-area-inset-bottom)); flex-direction:row;
    justify-content:center; align-items:center; border-right:0; border-top:1px solid var(--line);
    padding:0 0 env(safe-area-inset-bottom) }
  .a-mark { margin:0 4px; width:12px; height:2px }
  .a-mark.active { width:16px; height:2px }
  .a-rail-wm { display:none }
  /* Phone: one line — name, a de-emphasised search, alerts. The clock goes:
     the time is on the device's own status bar two centimetres above. */
  .a-hdr { grid-template-columns:auto 1fr auto; height:auto; min-height:52px;
    flex:0 0 auto; gap:12px; padding:9px 13px }
  .a-hdr-title { max-width:40vw }
  .a-hdr-search { justify-self:stretch; width:auto; min-width:0 }
  .a-hdr-search .a-field { text-align:left; border-bottom-color:transparent; font-size:16px }
  .a-hdr-search .a-field:focus { border-bottom-color:var(--edge) }
  .a-hdr-meta { display:none }
  .notif-panel { position:fixed; top:52px; right:8px; width:calc(100vw - 16px); max-height:calc(100dvh - 94px) }
  .a-field { font-size:16px }   /* under 16px iOS zooms the page on focus */
}

@media (min-width: 621px) {
  .main.a-main { margin-left:34px !important }
}
