/* Field Ledger — a visit record book for staff working on a phone, outdoors.
   Ruled rows over cards; one loud thing (the running visit) over many accents. */

:root{
  --paper:#EFF1EC; --surface:#FBFCFA; --sunk:#E6E9E2;
  --ink:#10322B; --ink-2:#33544B; --ink-3:#6B857C;
  --rule:#D2D9CF; --rule-strong:#B9C3B5;
  --marigold:#E39A0C; --marigold-deep:#9A6606; --marigold-wash:#FCF0D6;
  --moss:#3F7350; --moss-wash:#E2EDE4;
  --clay:#A8402C; --clay-wash:#F7E4DF;
  --focus:#0B6BCB;
  --r:4px; --r-lg:8px;
  --tap:48px;
  --shell:1120px;
  --bar-h:64px;
}
@media (prefers-color-scheme:dark){
  :root{
    --paper:#0D1A17; --surface:#14251F; --sunk:#0A1411;
    --ink:#E8EFE9; --ink-2:#B4C6BD; --ink-3:#87A096;
    --rule:#26403A; --rule-strong:#38574E;
    --marigold:#F0AC2A; --marigold-deep:#F0AC2A; --marigold-wash:#33260B;
    --moss:#7FB98D; --moss-wash:#152A1C;
    --clay:#E0836D; --clay-wash:#2E1712;
    --focus:#6BA8F5;
  }
}

*,*::before,*::after{box-sizing:border-box}
html{-webkit-text-size-adjust:100%}
body{
  margin:0; background:var(--paper); color:var(--ink);
  font-family:Archivo,"Helvetica Neue",Arial,sans-serif;
  font-size:16px; line-height:1.5;
  font-variant-numeric:tabular-nums;
  -webkit-font-smoothing:antialiased;
}
h1,h2,h3,h4{margin:0; font-weight:700; line-height:1.15; letter-spacing:-.015em}
h1{font-size:1.5rem} h2{font-size:1.25rem} h3{font-size:1.0625rem} h4{font-size:.9375rem}
p{margin:0 0 .75rem} p:last-child{margin-bottom:0}
a{color:inherit}
img{max-width:100%}

:focus-visible{outline:3px solid var(--focus); outline-offset:2px; border-radius:2px}
@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{animation-duration:.001ms!important;animation-iteration-count:1!important;transition-duration:.001ms!important}
}

/* ---------- shell ---------- */
.shell{max-width:var(--shell); margin:0 auto; padding:0 16px}
.page{padding-block:20px 24px}
/* room for the fixed bottom tab bar + any sticky action bar */
body.has-tabbar main{padding-bottom:calc(var(--bar-h) + env(safe-area-inset-bottom) + 16px)}

/* ---------- top bar ---------- */
.topbar{background:var(--ink); color:#EFF1EC; position:sticky; top:0; z-index:40}
@media (prefers-color-scheme:dark){.topbar{background:var(--sunk); border-bottom:1px solid var(--rule)}}
.topbar .shell{display:flex; align-items:center; gap:16px; min-height:56px}
.brand{display:flex; align-items:center; gap:9px; font-weight:800; letter-spacing:-.02em; text-decoration:none; font-size:1.0625rem; color:inherit}
.brand-mark{width:22px; height:22px; flex:none; color:var(--marigold)}
.topnav{display:none; margin-left:auto; gap:4px}
.topnav a{
  text-decoration:none; padding:8px 12px; border-radius:var(--r); font-size:.9375rem;
  font-weight:600; color:#C3D2CB;
}
.topnav a:hover{color:#fff; background:#ffffff14}
.topnav a[aria-current=page]{color:var(--ink); background:var(--marigold)}
@media (prefers-color-scheme:dark){.topnav a[aria-current=page]{color:#0D1A17}}
.topbar-end{margin-left:auto; display:flex; align-items:center; gap:10px}
.topnav+.topbar-end{margin-left:0}
/* who is signed in matters on a shared phone, so the name shows at every width —
   it truncates rather than pushing the sign-out button off the bar */
.whoami{font-size:.8125rem; color:#A9BDB4; max-width:11ch; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; min-width:0}
.signout{background:none; border:1px solid #ffffff33; color:#DDE7E1; font:inherit; font-size:.8125rem; font-weight:600;
  padding:7px 11px; border-radius:var(--r); cursor:pointer; min-height:36px; flex:none; white-space:nowrap}
.signout:hover{background:#ffffff14}
@media (max-width:479px){
  /* the mark alone carries the brand once space is tight */
  .brand-text{display:none}
  .topbar .shell{gap:10px}
}
@media (min-width:900px){
  .topnav{display:flex}
  .whoami{max-width:18ch}
  .topbar .shell{min-height:60px}
}

/* ---------- bottom tab bar (phone) ---------- */
.tabbar{
  position:fixed; inset:auto 0 0 0; z-index:45; display:flex;
  background:var(--surface); border-top:1px solid var(--rule);
  padding-bottom:env(safe-area-inset-bottom);
}
.tabbar a{
  flex:1; display:flex; flex-direction:column; align-items:center; justify-content:center; gap:3px;
  min-height:var(--bar-h); text-decoration:none; color:var(--ink-3);
  font-size:.6875rem; font-weight:600; font-stretch:92%;
  border-top:2px solid transparent; margin-top:-1px;
}
.tabbar a[aria-current=page]{color:var(--ink); border-top-color:var(--marigold)}
.tabbar svg{width:21px; height:21px}
@media (min-width:900px){ .tabbar{display:none} body.has-tabbar main{padding-bottom:24px} }

/* ---------- page heading ---------- */
.head{display:flex; align-items:flex-start; gap:12px; margin-bottom:18px; flex-wrap:wrap}
/* the title block is the first child, not the h1 itself, so target the child */
.head>:first-child{flex:1 1 auto; min-width:0}
.head h1{min-width:0}
.head-sub{color:var(--ink-3); font-size:.875rem; margin-top:3px}
/* the page's main action sits beside the title, where it is seen first */
.head-action{display:flex; align-items:center; gap:8px; flex:0 0 auto; flex-wrap:wrap}
@media (max-width:559px){
  .head-action{flex-basis:100%}
  .head-action .btn{flex:1 1 auto}
}

/* ---------- panel: the one container ---------- */
.panel{background:var(--surface); border:1px solid var(--rule); border-radius:var(--r-lg); overflow:hidden}
.panel+.panel{margin-top:16px}
.panel-head{display:flex; align-items:center; gap:10px; padding:13px 16px; border-bottom:1px solid var(--rule)}
.panel-head h2,.panel-head h3{font-size:.9375rem; font-weight:700}
.panel-head .count{margin-left:auto; color:var(--ink-3); font-size:.8125rem; font-weight:600}
.panel-body{padding:16px}
.panel-foot{padding:12px 16px; border-top:1px solid var(--rule); background:var(--sunk)}

/* ---------- the running visit: the loudest thing on the page ---------- */
.live{
  display:block; text-decoration:none; color:var(--ink);
  background:var(--marigold-wash); border:1px solid var(--marigold);
  border-left:5px solid var(--marigold);
  border-radius:var(--r-lg); padding:14px 16px; margin-bottom:16px;
}
.live-top{display:flex; align-items:center; gap:8px; font-size:.8125rem; font-weight:700; color:var(--marigold-deep)}
.pulse{width:9px; height:9px; border-radius:50%; background:var(--marigold); flex:none; animation:pulse 2s ease-in-out infinite}
@keyframes pulse{0%,100%{opacity:1;transform:scale(1)}50%{opacity:.35;transform:scale(.8)}}
.live-college{font-size:1.1875rem; font-weight:700; letter-spacing:-.02em; margin:5px 0 2px}
.live-meta{font-size:.875rem; color:var(--ink-2)}
.live-foot{display:flex; align-items:center; gap:12px; margin-top:12px}
.elapsed{font-size:1.375rem; font-weight:700; font-stretch:115%; letter-spacing:.01em; font-variant-numeric:tabular-nums}

/* ---------- figures ---------- */
.figures{display:grid; grid-template-columns:repeat(3,1fr); background:var(--surface); border:1px solid var(--rule); border-radius:var(--r-lg); overflow:hidden}
.figure{padding:14px 12px; border-left:1px solid var(--rule); min-width:0}
.figure:first-child{border-left:0}
.figure b{display:block; font-size:1.875rem; font-weight:700; font-stretch:115%; line-height:1; letter-spacing:-.02em}
.figure span{display:block; margin-top:5px; font-size:.75rem; font-weight:600; font-stretch:90%; color:var(--ink-3)}
@media (min-width:560px){ .figure{padding:18px 16px} .figure b{font-size:2.25rem} .figure span{font-size:.8125rem} }

/* ---------- ledger rows ---------- */
.ledger{display:flex; flex-direction:column}
.row{
  display:block; text-decoration:none; color:inherit; position:relative;
  padding:13px 16px 13px 20px; border-bottom:1px solid var(--rule);
  min-height:var(--tap);
}
.row:last-child{border-bottom:0}
.row:hover{background:var(--sunk)}
.row::before{content:""; position:absolute; left:0; top:0; bottom:0; width:4px; background:var(--rule-strong)}
.row.is-live::before{background:var(--marigold)}
.row.is-done::before{background:var(--moss)}
.row.is-due::before{background:var(--clay)}
.row-title{font-weight:700; letter-spacing:-.01em; display:flex; align-items:baseline; gap:8px}
/* only the name flexes — a trailing chip must keep its own width */
.row-title>span:not(.chip){flex:1; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap}
.row-title>.chip{flex:none}
.row-meta{display:flex; flex-wrap:wrap; align-items:center; gap:8px; margin-top:4px; font-size:.8125rem; color:var(--ink-3)}
.row-meta i{width:1px; height:11px; background:var(--rule-strong); display:inline-block; font-style:normal}
.row-note{margin-top:5px; font-size:.875rem; color:var(--ink-2); display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical; overflow:hidden}

/* ---------- chips ---------- */
.chip{
  display:inline-block; padding:2px 8px; border-radius:20px; font-size:.6875rem; font-weight:700;
  font-stretch:92%; white-space:nowrap; background:var(--sunk); color:var(--ink-2); border:1px solid var(--rule)
}
.chip.live{background:var(--marigold-wash); color:var(--marigold-deep); border-color:var(--marigold)}
.chip.done{background:var(--moss-wash); color:var(--moss); border-color:var(--moss)}
.chip.warn{background:var(--clay-wash); color:var(--clay); border-color:var(--clay)}

/* ---------- buttons ---------- */
.btn{
  display:inline-flex; align-items:center; justify-content:center; gap:8px;
  min-height:var(--tap); padding:0 18px; border-radius:var(--r);
  font:inherit; font-size:1rem; font-weight:700; letter-spacing:-.01em;
  text-decoration:none; cursor:pointer; border:1px solid transparent;
  background:var(--sunk); color:var(--ink); border-color:var(--rule-strong);
}
.btn:hover{border-color:var(--ink-3)}
.btn-primary{background:var(--marigold); color:#25190A; border-color:var(--marigold)}
.btn-primary:hover{background:#CE8B08; border-color:#CE8B08}
.btn-ink{background:var(--ink); color:var(--paper); border-color:var(--ink)}
.btn-ink:hover{background:var(--ink-2); border-color:var(--ink-2)}
.btn-danger{background:transparent; color:var(--clay); border-color:var(--clay)}
.btn-danger:hover{background:var(--clay-wash)}
.btn-block{display:flex; width:100%}
.btn-sm{min-height:38px; padding:0 12px; font-size:.875rem}
.btn-lg{min-height:56px; font-size:1.0625rem}

/* sticky thumb-reach action on phones: the primary action stays under the thumb
   while the form scrolls behind it, with a fade so it never sits on top of text */
.thumb{
  position:sticky; bottom:calc(var(--bar-h) + env(safe-area-inset-bottom));
  z-index:30; margin-top:20px; padding:14px 0 10px;
}
.thumb::before{
  content:""; position:absolute; inset:-20px -16px 0; z-index:-1; pointer-events:none;
  background:linear-gradient(to bottom, transparent, var(--paper) 26px);
}
@media (min-width:900px){
  .thumb{position:static; margin-top:20px; padding:0}
  .thumb::before{display:none}
  .thumb .btn{width:auto; display:inline-flex}
}

/* ---------- forms ---------- */
.form{display:grid; gap:16px}
.fieldset{border:0; padding:0; margin:0; display:grid; gap:16px}
.fieldset>legend{
  padding:0; margin-bottom:2px; font-size:.9375rem; font-weight:700; letter-spacing:-.01em;
  color:var(--ink); width:100%; border-bottom:1px solid var(--rule); padding-bottom:8px;
}
/* align-content:start keeps label/input/help at their natural heights. Without it a
   field sitting beside a taller one (long help text, an error) stretches its input. */
.field{display:grid; gap:6px; min-width:0; align-content:start}
.field>label{font-size:.875rem; font-weight:600; color:var(--ink-2)}
.field .req{color:var(--clay)}
.help{font-size:.8125rem; color:var(--ink-3)}
/* Django ships some help text as a <ul> (the password rules); the browser default
   indent and margins pull it away from the field it belongs to. */
.help ul{margin:2px 0 0; padding-left:18px}
.help li{margin:1px 0}
.err{font-size:.8125rem; font-weight:600; color:var(--clay)}
.field-input{
  width:100%; min-height:var(--tap); padding:11px 13px;
  font:inherit; font-size:16px; /* 16px keeps iOS from zooming the page on focus */
  color:var(--ink); background:var(--surface);
  border:1px solid var(--rule-strong); border-radius:var(--r);
  -webkit-appearance:none; appearance:none;
}
.field-input:focus{border-color:var(--ink-2)}
textarea.field-input{min-height:96px; line-height:1.5; resize:vertical}
.field-select{
  background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%236B857C' stroke-width='2'%3E%3Cpath d='M4 6l4 4 4-4'/%3E%3C/svg%3E");
  background-repeat:no-repeat; background-position:right 12px center; background-size:16px; padding-right:38px;
}
.field.has-error .field-input{border-color:var(--clay); background:var(--clay-wash)}
.field-check{width:22px; height:22px; accent-color:var(--marigold); margin:0; flex:none}
.field.is-check{grid-template-columns:22px 1fr; align-items:center; column-gap:12px; row-gap:4px; min-height:var(--tap)}
.field.is-check>label{font-size:1rem; color:var(--ink)}
/* help and error text run the full width; left in column one they would widen it
   and squeeze the label into a narrow strip */
.field.is-check>.help,.field.is-check>.err{grid-column:1/-1}
.form-error{background:var(--clay-wash); border:1px solid var(--clay); color:var(--clay); border-radius:var(--r); padding:12px 14px; font-size:.875rem; font-weight:600}
.error-jump{margin:6px 0 0; padding-left:18px; display:grid; gap:4px}
.error-jump a{font-weight:700}
/* a jumped-to field should not hide under the sticky top bar */
.field-input{scroll-margin-top:72px}
/* one column on a phone, two once there is room — declared as a grid at both widths
   so stacked fields keep the same gap instead of butting together */
.grid-2{display:grid; gap:16px}
@media (min-width:700px){
  .grid-2{grid-template-columns:1fr 1fr}
  .grid-2>.span{grid-column:1/-1}
}

/* ---------- search / filter ---------- */
.filters{display:flex; flex-direction:column; gap:10px}
.filters .field-input{background:var(--surface)}
.filters>div{min-width:0}
@media (min-width:700px){
  .filters{flex-direction:row; flex-wrap:wrap; align-items:flex-end}
  .filters>div{flex:1 1 180px}
  .filters>.btn{flex:0 0 auto}
}

/* ---------- description list ---------- */
.facts{margin:0; display:grid; gap:0}
.facts>div{display:grid; gap:2px; padding:12px 0; border-bottom:1px solid var(--rule)}
.facts>div:last-child{border-bottom:0}
.facts dt{font-size:.8125rem; font-weight:600; color:var(--ink-3)}
.facts dd{margin:0; font-size:.9375rem}
@media (min-width:700px){
  .facts>div{grid-template-columns:180px 1fr; gap:16px; align-items:baseline}
}

/* ---------- table (desktop reports) ---------- */
.scroll-x{overflow-x:auto; -webkit-overflow-scrolling:touch}
table.data{width:100%; border-collapse:collapse; font-size:.875rem; min-width:640px}
table.data th{
  text-align:left; font-weight:700; font-size:.75rem; font-stretch:90%; color:var(--ink-3);
  padding:10px 14px; border-bottom:1px solid var(--rule-strong); white-space:nowrap; background:var(--sunk)
}
table.data td{padding:11px 14px; border-bottom:1px solid var(--rule); vertical-align:top}
table.data tr:last-child td{border-bottom:0}
table.data a{font-weight:600}

/* ---------- tiles (colleges) ---------- */
.tiles{display:grid; gap:12px}
@media (min-width:620px){.tiles{grid-template-columns:repeat(2,1fr)}}
@media (min-width:940px){.tiles{grid-template-columns:repeat(3,1fr)}}
.tile{
  display:block; text-decoration:none; color:inherit; background:var(--surface);
  border:1px solid var(--rule); border-radius:var(--r-lg); padding:15px 16px;
}
.tile:hover{border-color:var(--ink-3)}
.tile h3{font-size:1rem; margin-bottom:4px}
.tile-meta{font-size:.8125rem; color:var(--ink-3)}
.tile-foot{display:flex; align-items:center; gap:8px; margin-top:11px; padding-top:11px; border-top:1px solid var(--rule); font-size:.75rem; color:var(--ink-3); font-weight:600}

/* ---------- messages ---------- */
.flash{display:grid; gap:8px; margin-bottom:16px}
.flash p{
  margin:0; padding:12px 14px; border-radius:var(--r); font-size:.9375rem; font-weight:600;
  border:1px solid var(--rule-strong); background:var(--surface)
}
.flash .success{background:var(--moss-wash); border-color:var(--moss); color:var(--moss)}
.flash .error{background:var(--clay-wash); border-color:var(--clay); color:var(--clay)}
.flash .info{background:var(--marigold-wash); border-color:var(--marigold); color:var(--marigold-deep)}

/* ---------- empty state ---------- */
.empty{padding:32px 20px; text-align:center}
.empty h3{margin-bottom:6px}
.empty p{color:var(--ink-3); font-size:.9375rem; max-width:38ch; margin-inline:auto}
.empty .btn{margin-top:16px}

/* ---------- pagination ---------- */
.pager{display:flex; align-items:center; justify-content:space-between; gap:12px}
.pager span{font-size:.8125rem; color:var(--ink-3); font-weight:600}

/* ---------- auth ---------- */
.auth{min-height:100dvh; display:grid; place-items:center; padding:24px 16px; background:var(--ink)}
.auth-box{width:100%; max-width:400px}
.auth-brand{display:flex; align-items:center; gap:10px; color:#EFF1EC; font-weight:800; font-size:1.25rem; letter-spacing:-.02em; margin-bottom:6px}
.auth-brand .brand-mark{width:26px; height:26px; color:var(--marigold)}
.auth-tag{color:#9DB3AA; font-size:.9375rem; margin-bottom:20px}
.auth .panel{border-color:transparent}
.auth-hint{margin-top:14px; font-size:.8125rem; color:#8FA79D; line-height:1.6}
.auth-hint code{color:#C9D8D1; font-size:.8125rem}

/* a form that stacks panels supplies its own gap, so don't add the panel margin too */
.form>.panel+.panel{margin-top:0}

/* a panel carrying something that needs attention */
.panel.accent{border-color:var(--marigold); border-left-width:4px}

/* inline callout: a draft waiting, a batch half keyed in */
.notice{
  display:block; text-decoration:none; color:inherit;
  background:var(--marigold-wash); border:1px solid var(--marigold); border-left-width:4px;
  border-radius:var(--r-lg); padding:13px 16px; margin-bottom:16px;
}
.notice p{font-size:.9375rem; margin-bottom:0}
.notice .btn{margin-top:10px}

/* three-across on wide screens, stacked on a phone */
.grid-3{display:grid; gap:16px}
@media (min-width:700px){ .grid-3{grid-template-columns:1.4fr 1fr 1fr} }

/* one repeatable student batch inside the visit form */
.batch-row{
  border:1px dashed var(--rule-strong); border-radius:var(--r); padding:14px; margin-bottom:12px;
  background:var(--paper); display:grid; gap:14px;
}

.mt{margin-top:16px}
.u-desktop-only{display:none}
@media (min-width:820px){
  .u-mobile-only{display:none}
  .u-desktop-only{display:block}
}
.u-muted{color:var(--ink-3)}
.u-right{margin-left:auto}
.u-wrap{display:flex; flex-wrap:wrap; gap:10px; align-items:center}
.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}

/* ---------- error pages ---------- */
.stop{max-width:34rem; margin:0 auto; padding:48px 0 24px; text-align:center}
.stop-code{
  font-size:3.25rem; font-weight:800; font-stretch:115%; line-height:1;
  color:var(--rule-strong); letter-spacing:-.03em; margin-bottom:10px;
}
.stop h1{font-size:1.5rem; margin-bottom:10px}
.stop p{color:var(--ink-3); font-size:.9375rem; max-width:44ch; margin-inline:auto}
.stop-actions{justify-content:center; margin-top:22px}

/* ---------- long lists scroll inside themselves ---------- */
/* An uncapped list makes the page arbitrarily tall: the pager, the totals and every
   panel below it get pushed out of reach. Cap the list instead and let it scroll in
   place. The cap is whichever is smaller — about 15 rows (20 for the denser tables),
   or a screenful. Going past a screenful would make the "inner" scrollbar meaningless,
   because you would have to scroll the page to see the rest of the box anyway. */
:root{ --list-rows:15; --list-row-h:5rem; --table-rows:20; --table-row-h:2.9rem; --list-max-vh:85vh }

.ledger{
  max-height:min(calc(var(--list-rows) * var(--list-row-h)), var(--list-max-vh));
  overflow-y:auto; overscroll-behavior:contain;
}
/* .ledger is a flex column, and a flex child shrinks by default. Capping the height
   would otherwise squash every row below its natural size and overlap the text. */
.ledger>*{flex:0 0 auto}
.scroll-x{
  max-height:min(calc(var(--table-rows) * var(--table-row-h)), var(--list-max-vh));
  overflow-y:auto; overscroll-behavior:contain;
}
.tiles{
  max-height:min(52rem, var(--list-max-vh)); overflow-y:auto; overscroll-behavior:contain;
  /* the grid's own focus rings would be clipped flush against the edge */
  padding:2px;
}

/* the header has to stay put once the rows scroll under it */
table.data thead th{position:sticky; top:0; z-index:2}

/* a scrollable region needs a visible edge, or it reads as a truncated list */
.ledger, .scroll-x, .tiles{scrollbar-width:thin; scrollbar-color:var(--rule-strong) transparent}
.ledger::-webkit-scrollbar, .scroll-x::-webkit-scrollbar, .tiles::-webkit-scrollbar{width:10px; height:10px}
.ledger::-webkit-scrollbar-thumb, .scroll-x::-webkit-scrollbar-thumb, .tiles::-webkit-scrollbar-thumb{
  background:var(--rule-strong); border-radius:20px; border:3px solid var(--surface);
}
.ledger::-webkit-scrollbar-track, .scroll-x::-webkit-scrollbar-track, .tiles::-webkit-scrollbar-track{background:transparent}

/* only shown on a list that actually overflows — see the script in base.html */
.is-scrollable{border-bottom:1px solid var(--rule)}
.is-scrollable:focus-visible{outline:3px solid var(--focus); outline-offset:-3px}
