/* ============================================================
   ResourceLab brand — bright, rounded, cheerful.
   Chunky offset shadows and thick outlines give a tactile,
   sticker-book feel that suits a primary classroom tool.
   ============================================================ */

:root{
  --cream:#FFF9F0;
  --ink:#2D3561;
  --ink-soft:#6B7299;
  --yellow:#FFC93C;
  --coral:#FF6B6B;
  --mint:#4ECDC4;
  --sky:#45AAF2;
  --grape:#A55EEA;
  /* the yellow darkened until it reads as a border against cream */
  --yellow-deep:#E0B000;
  /* The neutrals. Named because they were being retyped: the hairline
     between sections appeared ten times as a literal, so changing it
     meant a find-and-replace and hoping. */
  --hairline:#EFE8DC;      /* dividers inside a white panel */
  --edge:#D9D3C6;          /* the border of something quiet, like a plain pill */
  --placeholder:#B9BED6;   /* text in an empty field */
  /* the display face, named once instead of retyped in six rules */
  --font-display:Fredoka,Nunito,system-ui,sans-serif;
  --paper:#FDF8EF;         /* the off-white a sheet preview sits on */
  --line:3px solid var(--ink);
  --pop:0 5px 0 var(--ink);
  --pop-lg:0 8px 0 var(--ink);
  --radius:20px;
}

*{box-sizing:border-box}
/* must beat display:flex on .stack, or a hidden form still shows */
[hidden]{display:none !important}
html,body{height:100%}
body{
  margin:0;
  font-family:Nunito,"Trebuchet MS",system-ui,sans-serif;
  font-weight:600;
  color:var(--ink);
  background:var(--cream);
  position:relative;
  overflow-x:hidden;
}
h1,h2,h3,.wm-name{font-family:var(--font-display);font-weight:600}

/* floating background blobs */
.blobs{position:fixed;inset:0;pointer-events:none;z-index:0;overflow:hidden}
.blob{position:absolute;border-radius:50%;opacity:.22;filter:blur(2px)}
.b1{width:340px;height:340px;background:var(--yellow);top:-120px;left:-90px}
.b2{width:260px;height:260px;background:var(--mint);bottom:-90px;right:-60px}
.b3{width:180px;height:180px;background:var(--coral);top:22%;right:8%}
.b4{width:150px;height:150px;background:var(--grape);bottom:18%;left:6%}

/* ------------------------------------------------------------ chrome */
.topbar{
  position:relative;z-index:2;
  display:flex;align-items:center;justify-content:space-between;gap:16px;
  padding:16px 24px;flex-wrap:wrap;
}
.wordmark{display:flex;align-items:center;gap:10px;text-decoration:none;color:inherit}
.wm-text{display:flex;flex-direction:column;line-height:1}
.wm-name{font-size:22px;letter-spacing:.2px}
.wm-name em{font-style:normal;color:var(--coral)}
.wm-tld{font-size:11px;font-weight:700;color:var(--ink-soft);letter-spacing:1.6px;text-transform:uppercase}
.logo-mark{flex:none}

.topbar-right{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.whoami{
  font-size:13px;color:var(--ink-soft);max-width:230px;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}

/* =============================================================
   BUTTONS — one system for the whole site.
   Nothing styles a bare <button>: opt in with .btn plus a size
   and a colour, so a new button can never inherit a surprise.

     size   .btn-big  .btn-sm  .btn-tiny  .btn-icon  .btn-block
     colour .btn-mint .btn-coral .btn-ghost .btn-danger
   ============================================================= */
.btn{
  display:inline-flex;align-items:center;justify-content:center;gap:8px;
  font:inherit;font-weight:800;font-size:15px;color:var(--ink);text-decoration:none;
  background:#fff;border:var(--line);border-radius:999px;
  padding:10px 20px;cursor:pointer;box-shadow:var(--pop);
  transition:transform .08s ease, box-shadow .08s ease;
}
.btn:hover{transform:translateY(-2px);box-shadow:0 7px 0 var(--ink)}
.btn:active{transform:translateY(4px);box-shadow:0 1px 0 var(--ink)}
.btn:disabled{opacity:.45;cursor:default;transform:none;box-shadow:var(--pop)}
.btn:disabled:hover{transform:none;box-shadow:var(--pop)}

/* sizes */
.btn-big{width:100%;padding:15px 22px;font-size:17px;border-radius:16px}
.btn-ghost{background:#fff;box-shadow:0 3px 0 var(--ink);padding:8px 14px;font-size:14px}
.btn-sm{
  padding:6px 13px;font-size:13px;border:2px solid var(--ink);
  box-shadow:0 3px 0 var(--ink);
}
.btn-sm:hover{transform:translateY(-1px);box-shadow:0 4px 0 var(--ink)}
.btn-sm:active{transform:translateY(3px);box-shadow:0 0 0 var(--ink)}
.btn-sm:disabled,.btn-sm:disabled:hover{transform:none;box-shadow:0 3px 0 var(--ink)}
.btn-tiny{padding:5px 12px;font-size:13px;box-shadow:0 3px 0 var(--ink)}
.btn-block{width:100%}

/* square icon button — no text padding, so the glyph sits dead centre */
.btn-icon{
  width:30px;height:30px;padding:0;flex:none;
  display:grid;place-items:center;
  border:2px solid var(--ink);box-shadow:0 2px 0 var(--ink);
}
.btn-icon:hover{transform:translateY(-1px);box-shadow:0 3px 0 var(--ink)}
.btn-icon:active{transform:translateY(2px);box-shadow:0 0 0 var(--ink)}
.btn-icon svg{display:block}

/* colours */
.btn-mint{background:var(--mint)}
.btn-coral{background:var(--coral);color:#fff}
.btn-yellow{background:var(--yellow)}
.btn-danger{background:#ffe1e1}

.linky{
  background:none;border:0;color:var(--ink-soft);font:inherit;font-weight:700;
  text-decoration:underline;cursor:pointer;padding:6px;font-size:14px;
  user-select:none;   /* it is a control: a tap should press it, not select it */
}

/* rows of buttons that share the width evenly */
.btnrow{display:flex;gap:6px;margin:10px 0}
.btnrow > .btn{flex:1}

/* ------------------------------------------------------------- login */
/* For a teacher who is not on the list yet, this is the only way in, so
   it gets a proper thumb-sized target rather than a thin underline. */
.page-login .footnote .linky{padding:10px 6px;color:var(--ink);font-weight:800}
.page-login .centre{
  position:relative;z-index:2;
  min-height:calc(100% - 80px);
  display:flex;flex-direction:column;align-items:center;justify-content:center;
  padding:8px 20px 48px;
}
.card{
  width:100%;max-width:440px;background:#fff;
  border:var(--line);border-radius:var(--radius);box-shadow:var(--pop-lg);
  overflow:hidden;
}
.card-cap{height:14px;background:linear-gradient(90deg,
  var(--coral) 0 20%, var(--yellow) 20% 40%, var(--mint) 40% 60%,
  var(--sky) 60% 80%, var(--grape) 80% 100%);
  border-bottom:var(--line)}
.card-body{padding:30px 28px 26px}
.hi{margin:0 0 6px;font-size:28px}
.sub{margin:0 0 22px;color:var(--ink-soft);font-size:15px;line-height:1.5}

.stack{display:flex;flex-direction:column;gap:14px}

/* =============================================================
   FORM CONTROLS — again, opt in.
   Styling bare input/select globally meant every dense panel had
   to fight it back with overrides; .input / .select / .textarea
   (plus the -sm variants) keep that explicit.
   ============================================================= */
.field{display:flex;flex-direction:column;gap:6px}
.field > span{font-size:13px;font-weight:800;color:var(--ink-soft);letter-spacing:.4px}
.field-sm{display:block;margin-bottom:9px;color:var(--ink-soft);font-size:11.5px;font-weight:800}

.input,.select,.textarea{
  font:inherit;font-weight:700;color:var(--ink);width:100%;
  background:var(--cream);border:var(--line);border-radius:14px;
  padding:13px 16px;
}
.textarea{resize:vertical;min-height:56px;font-weight:600}
.input:focus,.select:focus,.textarea:focus{
  outline:none;border-color:var(--sky);box-shadow:0 0 0 4px rgba(69,170,242,.25);
}
.input::placeholder,.textarea::placeholder{color:var(--placeholder);font-weight:600}

/* dense variants for tool panels */
.input-sm,.select-sm{
  font:inherit;font-weight:700;font-size:13px;color:var(--ink);width:100%;
  background:var(--cream);border:2px solid var(--ink);border-radius:9px;
  padding:6px 9px;margin-top:3px;
}
.input-sm:focus,.select-sm:focus{
  outline:none;border-color:var(--sky);box-shadow:0 0 0 3px rgba(69,170,242,.28);
}
.input-sm::placeholder{color:var(--placeholder);font-weight:600}
.input-color{
  width:100%;height:30px;padding:2px;margin-top:3px;cursor:pointer;
  background:var(--cream);border:2px solid var(--ink);border-radius:9px;
}
/* checkbox rows */
.chk{display:flex;align-items:center;gap:7px;color:var(--ink);font-size:12.5px;font-weight:700}
.chk input{width:auto;margin:0}

.code-input{
  text-align:center;font-size:30px;letter-spacing:12px;font-weight:800;
  padding:14px 10px;font-family:var(--font-display);
}
.sent-to{margin:0;font-size:14px;color:var(--ink-soft)}
.sent-to strong{color:var(--ink)}

.note{margin:16px 0 0;font-size:14px;line-height:1.5;min-height:1.2em}
.note.good{color:#1f8a7a}
.note.bad{color:#d64545}
.footnote{position:relative;z-index:2;margin:20px 0 0;font-size:13px;color:var(--ink-soft)}

/* ------------------------------------------------------------- app */
.wrap{position:relative;z-index:2;max-width:1080px;margin:0 auto;padding:10px 24px 60px}
.hero{margin:14px 0 30px}
.hero h1{margin:0 0 6px;font-size:36px}
.hero p{margin:0;color:var(--ink-soft);font-size:16px}
/* no text-transform: people's chosen names should render exactly as typed */
.hero strong{color:var(--ink)}

.tool-grid{display:grid;gap:22px;grid-template-columns:repeat(auto-fill,minmax(280px,1fr))}
.tool{
  display:flex;flex-direction:column;text-decoration:none;color:inherit;
  background:#fff;border:var(--line);border-radius:var(--radius);
  box-shadow:var(--pop-lg);overflow:hidden;
  transition:transform .1s ease, box-shadow .1s ease;
}
a.tool:hover{transform:translateY(-4px);box-shadow:0 12px 0 var(--ink)}
a.tool:active{transform:translateY(3px);box-shadow:0 3px 0 var(--ink)}
.tool.is-soon{opacity:.62;box-shadow:var(--pop)}
.tool-top{
  display:flex;align-items:center;justify-content:center;
  padding:26px;border-bottom:var(--line);
}
.tool-icon{width:60px;height:60px}
.tool-coral .tool-top{background:var(--coral)}
.tool-mint  .tool-top{background:var(--mint)}
.tool-sky   .tool-top{background:var(--sky)}
.tool-grape .tool-top{background:var(--grape)}
.tool-yellow .tool-top{background:var(--yellow)}
.tool-top .tool-icon{color:#fff}
.tool-yellow .tool-top .tool-icon{color:var(--ink)}

.tool-body{padding:20px 22px 22px;display:flex;flex-direction:column;gap:6px;flex:1}
.tool-body h2{margin:0;font-size:21px}
.tool-tag{margin:0;font-size:13px;font-weight:800;color:var(--ink-soft);letter-spacing:.2px}
.tool-desc{margin:6px 0 14px;font-size:14px;line-height:1.5;color:var(--ink-soft);flex:1}
.tool-go{font-weight:800;color:var(--ink)}
.tool-soon{font-weight:800;color:var(--ink-soft)}

/* ------------------------------------------------------------ admin */
.panel{
  background:#fff;border:var(--line);border-radius:var(--radius);
  box-shadow:var(--pop);padding:22px;margin-bottom:22px;
}
.add-row{display:flex;gap:12px;flex-wrap:wrap}
.add-row .input{flex:1;min-width:200px}
.add-row .btn{white-space:nowrap}

.people{width:100%;border-collapse:collapse;font-size:14px}
.people th{
  text-align:left;font-size:12px;letter-spacing:.6px;text-transform:uppercase;
  color:var(--ink-soft);padding:0 12px 10px;
}
.people td{padding:12px;border-top:2px solid #eee9df;vertical-align:middle}
.people tr.is-admin td{background:#fffaf0}
.people .muted{color:var(--ink-soft);text-align:center;padding:22px}
.pill{
  display:inline-block;background:var(--yellow);border:2px solid var(--ink);
  border-radius:999px;padding:2px 10px;font-size:12px;font-weight:800;
  white-space:nowrap;
}
.pill-plain{background:#fff;color:var(--ink-soft);border-color:var(--edge)}
.row-actions{display:flex;gap:6px;flex-wrap:wrap;justify-content:flex-end}

/* header icon links — label collapses on phones so the row never wraps */
.icon-link{position:relative;gap:6px}
.badge{
  min-width:19px;height:19px;padding:0 5px;border-radius:999px;
  background:var(--coral);color:#fff;border:2px solid var(--ink);
  font-size:11px;font-weight:800;line-height:15px;text-align:center;
}
.badge.is-zero{display:none}

/* inbox folder tabs */
.tabs{display:flex;gap:8px;flex-wrap:wrap;margin:0 0 16px}
.tab{
  font:inherit;font-weight:800;font-size:14px;color:var(--ink-soft);
  background:#fff;border:2px solid var(--edge);border-radius:999px;
  padding:8px 16px;cursor:pointer;display:inline-flex;align-items:center;gap:7px;
}
.tab:hover{border-color:var(--ink);color:var(--ink)}
.tab.is-on{
  background:var(--yellow);color:var(--ink);
  border-color:var(--ink);box-shadow:0 3px 0 var(--ink);
}
.tab-n{
  background:rgba(45,53,97,.12);border-radius:999px;
  padding:1px 8px;font-size:12px;
}
.tab.is-on .tab-n{background:rgba(45,53,97,.18)}
.req-by{margin:8px 0 0;font-size:12px;color:var(--ink-soft)}

/* admin inbox */
.req{
  border:2px solid var(--hairline);border-radius:14px;
  padding:14px 16px;margin-bottom:12px;background:#fff;
}
.req.is-done{opacity:.55;background:var(--cream)}
.req-head{display:flex;flex-wrap:wrap;align-items:center;gap:10px;margin-bottom:6px}
.req-kind{font-weight:800;font-size:13.5px}
.req-from{font-size:13px;color:var(--ink-soft)}
.req-when{font-size:12px;color:var(--ink-soft);margin-left:auto}
.req-sub{font-weight:800;font-size:14px;margin-bottom:4px}
.req-body{font-size:14px;line-height:1.55;white-space:pre-wrap;overflow-wrap:anywhere}

/* ============================================================
   Layout helpers.

   These exist so no page has to reach for a style attribute. An inline
   style cannot be themed, cannot be overridden by a later rule, does not
   show up when you search the stylesheet for who sets a colour, and
   quietly drifts out of step with everything around it. The rule for this
   codebase: geometry a script has to COMPUTE (an element's millimetre
   position, the page zoom) belongs inline because it is data; anything
   that is a decision about how the site looks belongs here.

   The exception is src/email.js, which must use literal hex and inline
   styles, because mail clients support neither custom properties nor
   stylesheets worth relying on.
   ============================================================ */
.row{display:flex;gap:10px;flex-wrap:wrap;align-items:center}
.row-lead{margin-right:auto}          /* the label that pushes the rest right */
.row-end{margin-left:auto;display:flex;gap:6px}
.stack-top{margin-top:20px}
.stack-top-lg{margin-top:26px}
.wrap-narrow{max-width:820px}
.num-sm{width:80px}                   /* a number input holding one or two digits */
.tiny{font-size:12px}

/* a panel that wants attention without alarming anybody */
.panel.is-caution{border-color:var(--yellow-deep)}

/* ------------------------------------------------ the lab assistant */
.chat-log{
  min-height:200px;display:grid;gap:10px;align-content:start;
}
.chat-form{display:flex;gap:8px;margin-top:10px}
.chat-in{flex:1}
.chat-bubble{
  padding:10px 14px;border:2px solid var(--ink);border-radius:14px;
  white-space:pre-wrap;max-width:92%;
  background:#fff;justify-self:start;
}
.chat-bubble.is-mine{background:var(--mint);justify-self:end}
/* the quiet line saying which tools the assistant reached for */
.chat-used{font-size:12px;justify-self:start;color:var(--ink-soft)}

/* ---------------------------------------------------- site templates */
.tpl-card{display:block;margin-bottom:14px}
.tpl-row{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin-top:10px}

/* said when a search found nothing by name and widened its net */
.pal-widened{
  grid-column:1/-1;margin:0 0 2px;font-size:12px;line-height:1.45;
  color:var(--ink-soft);font-weight:700;
}

/* line-up controls: six equal icon buttons in one row */
.align-row{display:grid;grid-template-columns:repeat(6,1fr);gap:4px;margin:2px 0 6px}
.align-btn{padding:7px 0;min-width:0;display:flex;align-items:center;justify-content:center}
.align-btn svg{display:block}
.align-note{margin:0 0 9px !important}
/* spreading only ever offers two, so they sit at the left rather than
   stretching across six columns' worth of width */
.spread-row{grid-template-columns:repeat(6,1fr);margin-top:-2px}
.spread-row .align-btn:nth-child(n+3){display:none}

/* turn controls in the element inspector */
.rot-row{display:flex;align-items:flex-end;gap:8px;flex-wrap:wrap;margin-bottom:9px}
.rot-row .field-sm{margin-bottom:0;flex:0 0 88px}
.rot-btns{margin:0;flex:1 1 auto;gap:4px}
.rot-btns .btn{flex:1;padding-left:6px;padding-right:6px;white-space:nowrap}

/* what we already know about whoever sent an access request */
.req-signals{display:flex;flex-wrap:wrap;gap:6px;margin-top:10px}
.req-signals:empty{margin-top:0}
.sig{
  font-size:12px;font-weight:700;line-height:1.35;
  padding:4px 10px;border-radius:999px;
  background:#f2eee6;color:var(--ink-soft);
  border:2px solid transparent;
}
.sig-good{background:#e4f7f2;color:#1f8a7a;border-color:#b7e6dc}
.sig-warn{background:#fff3d6;color:#8a6300;border-color:#ffdf9e}
.sig-bad{background:#ffe6e6;color:#c23b3b;border-color:#ffc2c2}

/* the three outcomes sit above the ordinary filing buttons */
.req-decide{margin-bottom:0}
.req-decide + .btnrow{margin-top:6px}

/* the exact email, shown before anything is sent */
.mail-preview{
  margin:0;padding:12px 14px;max-height:34vh;overflow:auto;
  background:var(--cream);border:2px solid var(--hairline);border-radius:12px;
  font:12.5px/1.55 Consolas,"SFMono-Regular",Menlo,monospace;
  white-space:pre-wrap;overflow-wrap:anywhere;color:var(--ink);
}
.check{display:flex;align-items:center;gap:8px;font-size:13.5px;font-weight:700}
.check input{width:18px;height:18px}
.req .btnrow{margin:12px 0 0;justify-content:flex-start}
.req .btnrow .btn{flex:0 0 auto}

.foot{
  position:relative;z-index:2;text-align:center;padding:0 20px 30px;
  color:var(--ink-soft);font-size:13px;
}

/* ──────────────────── settings cog + dialog ──────────────────── */
.cog-btn{padding:8px 11px;line-height:0}
.cog-btn svg{display:block}

.sheet{
  width:min(94vw, 460px);
  max-height:min(86dvh, 780px);
  padding:26px 24px 22px;
  border:var(--line);border-radius:var(--radius);
  background:#fff;color:var(--ink);
  box-shadow:var(--pop-lg);
  overflow:auto;
  position:relative;
}
.sheet::backdrop{background:rgba(45,53,97,.45)}
.sheet-close-form{position:absolute;top:14px;right:14px;margin:0}
.sheet-close{width:32px;height:32px}   /* the rest comes from .btn.btn-icon */
.sheet-title{margin:0 0 2px;font-size:23px}
.sheet-sub{margin:0 0 18px;color:var(--ink-soft);font-size:13px}

.sheet-sect{border-top:2px solid var(--hairline)}
.sheet-sect:last-of-type{border-bottom:2px solid var(--hairline)}
.sheet-sect > summary{
  list-style:none;cursor:pointer;user-select:none;
  display:flex;align-items:center;justify-content:space-between;gap:8px;
  padding:14px 2px;font-weight:800;font-size:14.5px;
}
.sheet-sect > summary::-webkit-details-marker{display:none}
.sheet-sect > summary::marker{content:""}
.sheet-sect > summary::after{
  content:"";flex:none;width:7px;height:7px;margin-right:4px;
  border-right:2.5px solid currentColor;border-bottom:2.5px solid currentColor;
  transform:translateY(-2px) rotate(45deg);transition:transform .16s ease;
}
.sheet-sect[open] > summary::after{transform:translateY(1px) rotate(-135deg)}
.sheet-body{padding:2px 2px 18px;display:flex;flex-direction:column;gap:12px}
.sheet-hint{margin:0;font-size:13px;line-height:1.5;color:var(--ink-soft)}
.sheet .btn-block{margin-top:2px}

/* request access, on the sign-in page */
.ask-sheet .sheet-body{padding-bottom:2px}
.ask-sheet .note{margin-top:4px;min-height:0}
.ask-tick{margin:0 0 6px;font-size:40px;line-height:1;text-align:center}
#askThanks{text-align:center}
#askThanks .sheet-hint{max-width:34ch;margin:0 auto}
/* The honeypot has to be reachable enough that a form-filling bot takes
   the bait, so it is moved off-screen rather than display:none — which
   most of them know to skip. Nobody with eyes or a screen reader meets it. */
.hp{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}

/* ─────────────────── dialogs & toasts (ui.js) ─────────────────── */
.ui-modal{
  width:min(92vw, 400px);
  padding:26px 24px 20px;
  text-align:left;
}
.ui-title{margin:0 0 10px;font-size:21px}
.ui-msg{margin:0;font-size:15px;line-height:1.55;color:var(--ink)}
.ui-field{margin-top:16px}
.ui-actions{
  display:flex;gap:10px;justify-content:flex-end;flex-wrap:wrap;
  margin-top:22px;
}
.ui-actions .btn{flex:1 1 auto;min-width:110px;justify-content:center}
.ui-danger .ui-title{color:#c23b3b}

.toast-host{
  position:fixed;left:50%;bottom:max(18px, env(safe-area-inset-bottom));
  transform:translateX(-50%);
  z-index:9999;display:flex;flex-direction:column;gap:8px;align-items:center;
  width:min(92vw, 460px);pointer-events:none;
}
.toast{
  pointer-events:auto;cursor:pointer;
  background:#fff;color:var(--ink);
  border:var(--line);border-radius:14px;box-shadow:var(--pop);
  padding:12px 18px;font-weight:700;font-size:14px;line-height:1.45;
  text-align:center;width:100%;
  opacity:0;transform:translateY(14px);
  transition:opacity .22s ease, transform .22s ease;
}
.toast.is-in{opacity:1;transform:translateY(0)}
.toast-good{background:#e7f8f4}
.toast-bad{background:#ffe9e9}
.toast-info{background:#fff}

@media (prefers-reduced-motion:reduce){
  .toast{transition:none;opacity:1;transform:none}
}

/* ───────────────────────── responsive ───────────────────────── */
@media (max-width:760px){
  .topbar{padding:12px 16px;gap:10px}
  .whoami{display:none}                 /* the email is the first thing to go */
  .wrap{padding:6px 16px 48px}
  .hero{margin:8px 0 22px}
  .hero h1{font-size:30px}
  .tool-grid{gap:16px;grid-template-columns:repeat(auto-fill,minmax(240px,1fr))}
  .panel{padding:16px;border-radius:16px}
}

/* The header must stay on ONE row beside the wordmark, so the admin
   links collapse to their icons rather than wrapping onto a second line. */
@media (max-width:700px){
  .topbar{flex-wrap:nowrap;gap:8px}
  .topbar-right{flex-wrap:nowrap;gap:6px}
  .icon-link .lbl{display:none}
  .icon-link{padding:8px 10px}
  .badge{
    position:absolute;top:-6px;right:-6px;
    min-width:18px;height:18px;line-height:14px;padding:0 4px;
  }
  .topbar-right .btn{white-space:nowrap}
}

@media (max-width:560px){
  .hero h1{font-size:26px}
  .hero p{font-size:15px}
  .card-body{padding:24px 20px}
  .hi{font-size:24px}
  .card-cap{height:11px}
  .wm-name{font-size:19px}
  .wm-tld{font-size:10px}
  .logo-mark{width:34px;height:34px}
  .btn-ghost{padding:8px 12px;font-size:13px}
  .code-input{font-size:26px;letter-spacing:9px}
  .add-row{gap:8px}
  .add-row .input,.add-row .btn{width:100%;flex:none}
  .tool-top{padding:20px}
  .tool-icon{width:48px;height:48px}
  .tabs{gap:6px}
  .tab{padding:7px 12px;font-size:13px}
}

/* A 6-column table cannot fit a phone, so each row becomes a little card
   and every cell is labelled from its data-label. */
@media (max-width:620px){
  .people,.people tbody,.people tr,.people td{display:block;width:100%}
  .people thead{display:none}
  .people tr{
    border:2px solid var(--hairline);border-radius:14px;
    padding:12px 14px;margin-bottom:10px;
  }
  .people tr.is-admin{background:#fffaf0}
  .people tr.is-admin td{background:none}
  .people td{
    border:0;padding:4px 0;
    display:flex;gap:10px;align-items:center;justify-content:space-between;
    overflow-wrap:anywhere;
  }
  .people td::before{
    content:attr(data-label);
    font-size:11px;letter-spacing:.6px;text-transform:uppercase;
    color:var(--ink-soft);font-weight:800;flex:none;
  }
  .people td[data-label=""]{padding-top:10px}
  .people td[data-label=""]::before{display:none}
  .row-actions{width:100%;justify-content:stretch}
  .row-actions .btn{flex:1}
  .people .muted{display:block;text-align:center}
}

/* fingers need a bigger target than a mouse pointer does */
@media (hover:none){
  .btn{min-height:44px}
  .btn-tiny{min-height:36px}
  .btn-sm{min-height:38px}
  .btn-icon{min-height:0}
  .btn:hover{transform:none;box-shadow:var(--pop)}
  .btn-sm:hover{transform:none;box-shadow:0 3px 0 var(--ink)}
  .btn-icon:hover{transform:none;box-shadow:0 2px 0 var(--ink)}
  a.tool:hover{transform:none;box-shadow:var(--pop-lg)}
  /* 16px stops iOS zooming the whole page when a field takes focus */
  .input,.select,.textarea,.input-sm,.select-sm{font-size:16px}
  .input-color{height:34px}
}

/* installed as an app: no browser chrome, so respect the notch */
@media (display-mode:standalone){
  .topbar{
    padding-top:max(16px, env(safe-area-inset-top));
    padding-left:max(24px, env(safe-area-inset-left));
    padding-right:max(24px, env(safe-area-inset-right));
  }
  .foot{padding-bottom:max(30px, env(safe-area-inset-bottom))}
}

/* ───────── chooser group headings ───────── */
.tool-group{
  font-family:var(--font-display);font-size:clamp(19px,2.4vw,25px);
  color:var(--ink);margin:34px 0 14px;letter-spacing:-.01em;
  display:flex;align-items:center;gap:12px;
}
.tool-group::after{
  content:"";flex:1;height:3px;border-radius:2px;
  background:var(--ink);opacity:.12;
}
.tool-grid + .tool-group{margin-top:40px}

/* Sign out keeps its word on tablets, but on a phone it collapses to the
   icon like the admin links beside it. Without this an admin's header
   (wordmark + Manage access + Inbox + settings + Sign out) runs past the
   right edge and Sign out becomes unreachable. */
@media (max-width:560px){
  .signout-link .lbl{display:none}
  .signout-link{padding:8px 10px}
}

/* Narrowest phones: claw back the last few pixels so the whole header
   row fits inside the viewport rather than being clipped. */
@media (max-width:430px){
  .topbar{padding-left:12px;padding-right:12px;gap:6px}
  .topbar-right{gap:4px}
  .icon-link{padding:8px 9px}
}

/* Very small phones (320px and similar): the wordmark text gives way and
   the flask alone carries the link home. Losing the word is better than
   losing Sign out off the edge of the screen. */
@media (max-width:365px){
  .wm-text{display:none}
  .topbar{gap:4px}
}


/* ───────────── chooser: pick up where you left off ───────────── */
.recent-files{display:grid;grid-template-columns:repeat(auto-fill,minmax(210px,1fr));gap:10px}
.recent-file{display:flex;flex-direction:column;gap:3px;text-decoration:none;color:var(--ink);
  background:#fff;border:2px solid var(--ink);border-radius:12px;padding:11px 14px;
  box-shadow:0 3px 0 var(--ink);transition:transform .07s ease}
.recent-file:hover{transform:translateY(-2px)}
.rf-name{font-weight:800;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.rf-meta{font-size:12px;color:var(--ink-soft);font-weight:700}
.rf-all{background:var(--yellow)}

/* ───────────── /files rows ───────────── */
.files-bar{display:flex;gap:10px;flex-wrap:wrap;margin-bottom:12px}
.files-bar .input{flex:1;min-width:200px}
.file-list{display:flex;flex-direction:column;gap:8px}
.file-row{display:flex;align-items:center;justify-content:space-between;gap:10px;
  border:2px solid var(--ink);border-radius:12px;padding:8px 12px;background:#fff}
.file-open{display:flex;flex-direction:column;gap:2px;text-decoration:none;color:var(--ink);
  min-width:0;flex:1}
.file-name{font-weight:800;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.file-meta{font-size:12px;color:var(--ink-soft);font-weight:700}
.panel-title{margin:0 0 10px;font-size:18px}

/* ───────────── owner console ───────────── */
.grant-bar{display:flex;gap:8px;flex-wrap:wrap;margin:10px 0}
.grant-bar .input{width:130px}
/* an email address needs more room than a number of weeks does */
.grant-bar .input[type=email]{width:240px}
.mod-matrix{display:flex;flex-direction:column;gap:6px;margin-top:10px}
.mod-row{display:flex;align-items:center;gap:10px;border-bottom:2px solid var(--hairline);padding:6px 0}
.mod-name{flex:1;font-weight:700}
.pill-trial{background:var(--yellow);color:var(--ink)}
.ledger-row{display:flex;gap:10px;align-items:baseline;border-bottom:2px solid var(--hairline);
  padding:7px 0;font-size:14px;flex-wrap:wrap}
.ledger-when{flex:none;font-size:12px;color:var(--ink-soft);font-weight:800;min-width:88px}
@media (max-width:560px){
  .file-row{flex-wrap:wrap}
  .grant-bar .input{width:100%}
}

/* ------------------------------------------- module manager cards */
/* The chooser cards, made editable. They are divs, not links, so the
   lift-on-hover of a real tool card would be a lie. */
.mod-card{cursor:default}
.mod-card .tool-top{position:relative}
.mod-card .eye{
  position:absolute;top:10px;right:10px;
  width:38px;height:38px;border-radius:50%;
  display:flex;align-items:center;justify-content:center;
  background:#fff;color:var(--ink);border:var(--line);
  box-shadow:0 3px 0 var(--ink);cursor:pointer;padding:0;
}
.mod-card .eye:hover{transform:translateY(-1px);box-shadow:0 4px 0 var(--ink)}
.mod-card .eye:active{transform:translateY(3px);box-shadow:0 0 0 var(--ink)}
.mod-card .eye .eye-off{display:none}
.mod-card.is-hidden .eye .eye-on{display:none}
.mod-card.is-hidden .eye .eye-off{display:block}

/* a hidden module still has to be readable — dim the artwork, not the words */
.mod-card.is-hidden .tool-top{filter:grayscale(1);opacity:.55}
.mod-card.is-hidden .mod-view h2{text-decoration:line-through}
.mod-flag{
  display:none;align-self:flex-start;margin-bottom:6px;
  background:var(--ink);color:#fff;border-radius:999px;
  padding:3px 11px;font-size:11px;font-weight:800;letter-spacing:.4px;
}
.mod-card.is-hidden .mod-flag{display:inline-block}

.mod-edit{display:grid;gap:10px}
.mod-edit .input{width:100%}
.mod-edit textarea.input{resize:vertical;line-height:1.45}
.mod-actions{display:flex;gap:8px;flex-wrap:wrap;justify-content:flex-end}
.mod-note:empty{display:none}
.mod-note{margin:10px 0 0}

/* ----------------------------------------------------------- pricing */
.price-grid{display:grid;gap:20px;grid-template-columns:repeat(auto-fit,minmax(250px,1fr))}
.price-card{
  position:relative;display:flex;flex-direction:column;gap:8px;
  background:#fff;border:var(--line);border-radius:var(--radius);
  box-shadow:var(--pop);padding:22px;
}
.price-card.is-star{box-shadow:var(--pop-lg);border-color:var(--coral)}
.price-card.is-owned{opacity:.72}
.price-card h2{margin:0;font-size:20px}
.price-flag{
  position:absolute;top:-12px;right:16px;background:var(--coral);color:#fff;
  border:var(--line);border-radius:999px;padding:3px 12px;
  font-size:11px;font-weight:800;letter-spacing:.4px;
}
.price-amount{margin:0;font-family:var(--font-display);font-size:34px;font-weight:700;line-height:1}
.price-blurb{margin:0;font-size:14px;color:var(--ink-soft)}
.price-points{margin:6px 0 0;padding-left:18px;font-size:13.5px;line-height:1.6;color:var(--ink-soft)}
.price-points li{margin-bottom:2px}
.price-foot{margin-top:auto;padding-top:14px;display:grid;gap:8px}
.price-foot .select,.price-foot .btn{width:100%}
.price-note{margin:0;font-size:12.5px;font-weight:700;color:var(--ink-soft)}
.price-have{margin-top:auto;padding-top:14px;font-weight:800;color:var(--ink)}
.price-offer{background:var(--yellow);font-size:15px}
.price-thanks{background:var(--mint)}
@media (max-width:520px){ .price-amount{font-size:30px} }

/* ----------------------------------------------------------- landing */
.page-landing .wrap{max-width:960px}
.lp-hero{text-align:center;padding:34px 0 10px}
.lp-hero h1{font-size:clamp(28px,5.2vw,46px);line-height:1.14;margin:0 0 16px}
/* the two-line break is a nicety on a wide screen and a ragged mess on a phone */
@media (max-width:640px){ .lp-wide-br{display:none} }
.lp-lede{font-size:clamp(15px,2.2vw,18px);line-height:1.6;color:var(--ink-soft);
  max-width:60ch;margin:0 auto}
.lp-cta{margin:26px 0 8px}
/* .btn-big is a form button and stretches to its panel; in the hero it
   wants to be a pill you press, not a bar across the page. */
.lp-cta .btn{width:auto;border-radius:999px;padding:15px 32px}
.lp-note{font-size:13px;color:var(--ink-soft);margin:0}

.lp-stats{
  display:grid;gap:14px;grid-template-columns:repeat(auto-fit,minmax(140px,1fr));
  margin:30px 0 6px;
}
.lp-stat{
  background:#fff;border:var(--line);border-radius:var(--radius);
  box-shadow:var(--pop);padding:16px;text-align:center;
}
.lp-stat strong{
  display:block;font-family:var(--font-display);
  font-size:30px;font-weight:700;line-height:1;
}
.lp-stat span{display:block;margin-top:5px;font-size:12.5px;color:var(--ink-soft)}

.lp-sect{margin:44px 0}
.lp-sect > h2{font-size:clamp(21px,3.2vw,28px);margin:0 0 14px}
/* the hero centres its lede; a lede under a left-aligned heading must not */
.lp-sect > .lp-lede{margin:0}
.lp-group{
  font-size:11px;letter-spacing:1px;text-transform:uppercase;
  color:var(--ink-soft);font-weight:800;margin:22px 0 8px;
}
.lp-tools{list-style:none;margin:0;padding:0;display:grid;gap:10px;
  grid-template-columns:repeat(auto-fill,minmax(240px,1fr))}
.lp-tool{
  background:#fff;border:var(--line);border-radius:14px;
  box-shadow:var(--pop);padding:12px 14px;border-left-width:7px;
}
.lp-tool strong{display:block;font-size:15px}
.lp-tool span{display:block;margin-top:2px;font-size:12.5px;color:var(--ink-soft)}
.lp-coral{border-left-color:var(--coral)}
.lp-mint{border-left-color:var(--mint)}
.lp-sky{border-left-color:var(--sky)}
.lp-grape{border-left-color:var(--grape)}
.lp-yellow{border-left-color:var(--yellow)}

/* four points, so two columns rather than three-and-a-widow */
.lp-why{display:grid;gap:18px 34px;grid-template-columns:1fr}
@media (min-width:620px){ .lp-why{grid-template-columns:1fr 1fr} }
.lp-why h3{font-size:16px;margin:0 0 5px}
.lp-why p{margin:0;font-size:14px;line-height:1.55;color:var(--ink-soft)}

.lp-prices{list-style:none;margin:16px 0 10px;padding:0;display:grid;gap:10px}
.lp-prices li{
  display:flex;align-items:baseline;gap:14px;flex-wrap:wrap;
  background:#fff;border:var(--line);border-radius:14px;
  box-shadow:var(--pop);padding:13px 16px;
}
.lp-prices strong{font-family:var(--font-display);font-size:24px;font-weight:700;min-width:3.4em}
.lp-prices span{font-size:14px;color:var(--ink-soft)}
.lp-prices .is-star{border-color:var(--coral);box-shadow:var(--pop-lg)}

.lp-end{text-align:center}
.lp-end p{max-width:58ch;margin:0 auto 10px;font-size:15px;line-height:1.6;color:var(--ink-soft)}
@media (max-width:560px){ .lp-hero{padding:22px 0 6px} .lp-sect{margin:34px 0} }
