/* Kozak on a phone -- the ADMIN area: /login, /password, /admin/users,
   /admin/runs and /jira. Owner: admin area.
   Spec: docs/superpowers/specs/2026-10-01-kozak-phone-layout-design.md

   Linked with media="(pointer: coarse) and (max-width: 960px)" (D1/D2) from
   base.html, AFTER its head block, and from login.html, which does not extend
   base.html and links shell.css + this file itself. So: no @media wrapper is
   needed for the phone query, a desktop browser never applies a byte of this
   file, and it loads after app.css, shell.css and jira.html's inline <style>.

   Every rule is scoped to a class that only these templates render (.loginpage,
   .pwbox, .admpage, .jw), so nothing here can reach another area's page.
   shell.css already forces every field to 16px and sizes .ghost/.primary to
   44px; this file builds on that. Never overflow-x:hidden/clip (D8). */

/* ---- /login (ADM-6) ------------------------------------------------------ */

/* TOP-aligned, not centred: centred, Sign in sat at y 537-579 of 844, under the
   on-screen keyboard. svh, not vh, so iOS's URL bar does not add a scroll. */
.loginpage{min-height:100svh;place-items:start center;
  padding:max(6vh, env(safe-area-inset-top)) 16px 24px}
/* shell.css gives every <main> a 12px padding; this <main> is the sign-in box. */
.loginpage .loginbox{width:100%;max-width:22rem;padding:0}
.loginpage .loginbox label{font-size:14px;gap:6px}
.loginpage .loginbox input{min-height:44px;padding:10px 12px}
.loginpage .loginbox button{min-height:44px;font-size:16px}

/* ---- /password (ADM-2) --------------------------------------------------- */

/* The forced first-login screen. 90vw ignored everything beside it; fill the
   column instead, capped so landscape gets a form, not an 820px strip. */
.shell-main .pwbox{width:auto;max-width:26rem;padding:16px 12px}
.shell-main .pwbox label{font-size:14px;gap:6px}
.shell-main .pwbox .pwnote{font-size:14px}
.shell-main .pwbox input{min-height:44px;padding:10px 12px}
.shell-main .pwbox button{min-height:44px;font-size:16px}

/* ---- /admin/users + /admin/runs (ADM-1 / ADM-4 / ADM-5 / ADM-7) ---------- */

/* .admpage is a plain wrapper div in both templates (no desktop CSS): the
   gutter the bare banners/intro/table never had, flush at x=0 before. */
.admpage{padding:12px}
.admpage > :first-child{margin-top:0}
.admpage .muted{font-size:13px}

/* Owner decision 2-Oct, "there should be no side to side scroll on the phone":
   both admin tables are LISTS, so every row is a stacked CARD -- label: value
   lines, actions at the foot -- and .admscroll (a plain div, unstyled on the
   desktop too) no longer scrolls. CSS ONLY: the templates are untouched, so
   the desktop cannot move, and the phone confirm() scripts read the same DOM
   (tr.cells[1] is still the Email cell -- CSS display does not change what
   .cells returns). Labels and the Admin yes/no are generated content, which
   never enters textContent, so they cannot leak into a confirm() message. */
.admpage{--admlw:92px}
.admpage .kv.align,.admpage .kv.align tbody{display:block;width:auto}
.admpage .kv.align thead{display:none}
.admpage .kv.align tr{display:flex;flex-wrap:wrap;align-items:baseline;gap:6px 8px;margin:0 0 12px;
  padding:12px;border:1px solid var(--line);border-radius:12px;background:var(--panel);font-size:15px;line-height:1.4}
/* opacity:1 -- app.css dims a deactivated row's cells to .55; on a card that
   is unreadable muted-on-muted. The dashed card + Status line carry it now. */
.admpage .kv.align td{display:block;min-width:0;padding:0;border:0;opacity:1;white-space:normal;overflow-wrap:anywhere}
/* The label of a label: value line (a td's ::before), styled like the
   desktop's column head. --admlw + the 8px gap = where every value starts. */
.admusers .kv.align td:is(:nth-child(4),:nth-child(5),:nth-child(6))::before,
.admruns .kv.align td:not(:last-child)::before{flex:0 0 var(--admlw);color:var(--muted);font-size:11px;
  font-weight:600;letter-spacing:.03em;text-transform:uppercase}
/* Landscape / tablet: cards two-up instead of 800px-wide strips. start, not
   stretch, so an open Reset... grows only its own card. */
@media (min-width:600px){
  .admpage .kv.align tbody{display:grid;grid-template-columns:repeat(auto-fill,minmax(300px,1fr));
    gap:12px;align-items:start}
  .admpage .kv.align tr{margin:0}
}

/* Users. Header line: Email (+ "(you)") and the #id; the Name under it. The
   Email's basis leaves room for the #id and NOTHING else: with flex-basis 0, an
   empty Name (collapsed) let the ADMIN label pack up beside the email. */
.admusers .kv.align td:nth-child(2){order:1;flex:1 1 calc(100% - 64px);font-size:16px;font-weight:600;line-height:1.35}
.admusers .kv.align td:nth-child(2) .muted{font-size:13px;font-weight:400}
.admusers .kv.align td:nth-child(1){order:2;flex:none;color:var(--muted);font-size:13px}
.admusers .kv.align td:nth-child(1)::before{content:"#"}
.admusers .kv.align td:nth-child(3){order:3;flex:0 0 100%}
.admusers .kv.align td:nth-child(3):empty{display:none}
/* Admin, Status and Password cells dissolve (.inline-form already is
   display:contents in app.css), so their BUTTONS become items of the card and
   can be ordered to its foot, while the cell's ::before/::after stay up in
   the label: value lines. */
.admusers .kv.align td:is(:nth-child(4),:nth-child(5),:nth-child(7)){display:contents}
.admusers .kv.align td:nth-child(4)::before{content:"Admin";order:4}
.admusers .kv.align td:nth-child(5)::before{content:"Status";order:5}
.admusers .kv.align td:nth-child(6)::before{content:"Last login"}
/* Values. Admin has no text on the desktop -- the button's polarity IS the
   state (on=0 posts "revoke", so the account is an admin today). BOTH values
   come from :has(), so a browser without it shows no value, never a wrong one. */
.admusers .kv.align td:nth-child(4)::after{order:4}
.admusers .kv.align td:nth-child(4):has(input[name=on][value="1"])::after{content:"no"}
.admusers .kv.align td:nth-child(4):has(input[name=on][value="0"])::after{content:"yes \2014  may fire PROD"}
.admusers .kv.align tr:not(.rowoff)>td:nth-child(5)::after{content:"active";order:5}
/* A deactivated row already says so in a span -- that real text is the value. */
.admusers .kv.align .rowoff>td:nth-child(5)>span:first-of-type{order:5;color:var(--ink);font-size:inherit}
.admusers .kv.align td:nth-child(4)::after,.admusers .kv.align tr:not(.rowoff)>td:nth-child(5)::after,
.admusers .kv.align .rowoff>td:nth-child(5)>span:first-of-type{flex:1 1 calc(100% - var(--admlw) - 8px)}
/* "must change password": a note under the Status value. */
.admusers .kv.align tr:not(.rowoff)>td:nth-child(5)>span,
.admusers .kv.align .rowoff>td:nth-child(5)>span~span{order:6;flex:0 0 calc(100% - var(--admlw) - 8px);
  margin-left:calc(var(--admlw) + 8px);font-size:13px}
.admusers .kv.align td:nth-child(6){order:7;flex:0 0 100%;display:flex;align-items:baseline;gap:8px;
  color:var(--ink);font-size:inherit}
/* Foot: a rule, then the three actions (44px .ghost from shell.css) sharing
   the width, in the desktop's left-to-right order; an open Reset...'s form
   takes the line below them (see the @supports block). */
.admusers .kv.align td:nth-child(7)::before{content:"";order:19;flex:0 0 100%;margin-top:4px;
  border-top:1px solid var(--line)}
.admusers .kv.align td:nth-child(4) button{order:20}
.admusers .kv.align td:nth-child(5) button{order:21}
.admusers .kv.align td:nth-child(7) .pwmini{order:22}
.admusers .kv.align td button.ghost,.admusers .kv.align .pwmini{flex:1 1 auto}
.admusers .kv.align .pwmini>summary{display:block;text-align:center}
.admusers .kv.align .pwmini[open]{flex-basis:100%}
/* Owner rule 2-Oct, "ensure that this kind of things match": on the desktop an
   open Reset... stays where it was (top of the Password cell, its form under
   it). Here the whole <details> dropped to a line of its own, so the button
   just tapped jumped under Grant/Deactivate. Where the browser exposes the
   open content box (::details-content), the details dissolves instead: the
   summary keeps its slot beside Deactivate and only the form takes the next
   line. Without that support the rule above still applies (form usable). */
@supports selector(::details-content){
  .admusers .kv.align .pwmini[open]{display:contents}
  .admusers .kv.align .pwmini[open]>summary{order:22;flex:1 1 auto;margin-bottom:0}
  .admusers .kv.align .pwmini[open]::details-content{order:23;flex:0 0 100%;min-width:0}
}
/* Deactivated: a dashed, unfilled card and muted name lines -- opaque text,
   not a see-through card. */
.admusers .kv.align tr.rowoff{border-style:dashed;background:none}
.admusers .kv.align .rowoff>td:is(:nth-child(2),:nth-child(3)){color:var(--muted)}

/* Runs: User first, then Product..Submitted as label: value lines, and Stop
   -- the kill switch for a runaway PROD run -- full width at the foot. */
.admruns .kv.align td:not(:last-child){flex:0 0 100%;display:flex;align-items:baseline;gap:8px}
.admruns .kv.align td:first-child{font-size:16px;font-weight:600}
.admruns .kv.align td:nth-child(1)::before{content:"User"}
.admruns .kv.align td:nth-child(2)::before{content:"Product"}
.admruns .kv.align td:nth-child(3)::before{content:"Buyside"}
.admruns .kv.align td:nth-child(4)::before{content:"Env"}
.admruns .kv.align td:nth-child(5)::before{content:"Status"}
.admruns .kv.align td:nth-child(6)::before{content:"Submitted"}
.admruns .kv.align td:last-child{flex:0 0 100%;margin-top:4px;padding-top:10px;border-top:1px solid var(--line)}
.admruns .kv.align td:last-child button{width:100%}

/* Controls: .ghost (Grant/Revoke, Deactivate/Reactivate, Stop, Reset...,
   Add a user) is already 44px from shell.css. The small forms take one line
   per control, in the desktop's order -- except the password + Repeat pair,
   which sits side by side as on the desktop (Reset...: New password | Repeat,
   then Set password; Add a user: Password | Repeat). */
.admpage .pwmini>summary{font-size:14px}
.admpage .pwmini form{flex-flow:row wrap;align-items:stretch;gap:8px}
.admpage .pwmini form>*{flex:0 0 100%;min-width:0}
.admpage .pwmini input[type=email],.admpage .pwmini input[type=text],
.admpage .pwmini input[type=password]{min-height:44px;min-width:0;width:100%;padding:10px 12px}
.admpage .pwmini form>input[type=password]{flex:1 1 calc(50% - 4px);width:auto}
.admpage .pwmini button[type=submit]{min-height:44px;font-size:16px;padding:10px 14px}
.admpage .pwmini p.muted{white-space:normal}
/* The whole "Admin (may fire PROD)" row is the tap target, not a 13px box. */
.admpage .pwmini .adminbox{min-height:44px;gap:10px;font-size:15px;white-space:normal}
.admpage .pwmini .adminbox input{width:22px;height:22px;margin:0;flex:none}
.admpage .adduser[open]{max-width:30rem}

/* ---- /jira (JIRA-1 / JIRA-2) --------------------------------------------- */

/* The .jw prefix keeps every rule on this page only. This file loads after
   jira.html's inline <style>, so equal specificity would already win. */
.shell-main .jw{padding:12px 12px 40px}
/* shell.css pads every .toolbar for the harness; this page's toolbars are
   button rows inside the content, not page bars. */
.shell-main .jw .toolbar{padding:0}
.shell-main .jw button{min-height:44px;font-size:15px}
.shell-main .jw details.new>summary{padding:12px 0}
.shell-main .jw .key{padding:7px 12px}

/* Fields: 16px comes from shell.css; here, 44px tall and no 150-260px floors
   (they pushed a created row's summary ~30px out of its card at 360). */
.shell-main .jw .defs label{flex:1 1 200px;min-width:0}
.shell-main .jw .defs select,.shell-main .jw .defs input,
.shell-main .jw .ctx .f input,.shell-main .jw .ctx .f select{min-height:44px;min-width:0;width:100%}
.shell-main .jw .wide{min-width:0}
.shell-main .jw .ctx .f{flex:1 1 140px;min-width:0;font-size:11px}
.shell-main .jw .ctx .art,.shell-main .jw .ctx .why{flex:2 1 220px}
.shell-main .jw .row .top{min-height:44px}
.shell-main .jw .row .sum{min-width:0;min-height:44px}

/* The per-row tick is the ONLY selection for "Create N selected" (live
   tickets) and Merge. 16px was too small to hit; this is a 40x40 hit area
   (the transparent border counts for hit-testing) around a 24px visible box.
   input.pick, its name/value and the change events are untouched, so the JS
   count and the Create confirm() work exactly as before. */
.shell-main .jw .row .top input[type=checkbox]{-webkit-appearance:none;appearance:none;flex:none;
  width:40px;height:40px;margin:-8px;border:8px solid transparent;border-radius:12px;
  background-clip:padding-box;background-color:var(--bg);box-shadow:inset 0 0 0 1.5px var(--muted)}
.shell-main .jw .row .top input[type=checkbox]:checked{background-color:var(--accent);box-shadow:none;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M3 8.5l3 3 7-7' fill='none' stroke='white' stroke-width='2.2'/%3E%3C/svg%3E");
  background-size:16px;background-repeat:no-repeat;background-position:center}
.shell-main .jw .row .top input[type=checkbox]:focus-visible{outline:2px solid var(--accent);outline-offset:-6px}

@media (max-width:600px){
  .shell-main .jw .defs label{flex-basis:100%}
  .shell-main .jw .ctx .f{flex-basis:calc(50% - 6px)}
  .shell-main .jw .ctx .art,.shell-main .jw .ctx .why{flex-basis:100%}
  /* Portrait: Create goes on its OWN full-width line, away from Clear, Merge
     and Add row -- a live, irreversible action must not share a row of
     look-alike buttons on glass. */
  .shell-main .jw .toolbar .grow{flex:1 1 100%;height:0}
  .shell-main .jw .toolbar button.primary{flex:1 1 100%}
}
