/*
    The workspace shell: the dark rail, the topbar with breadcrumb, Guides and notifications, the
    guides slide-over and the announcement bell. Ported from the workspace design package's shell
    styles with a ws- namespace so nothing here can collide with the main stylesheet, which still
    carries every page's own content styling. Values follow the design frames exactly; anything
    that deviates (the sticky rail, the sign-out control, the collapsed strip's sign-out item)
    exists because the shell must do a job the static frames did not have to do, and each such
    place says so beside the rule.

    Colour and font variables come from the main stylesheet's :root, which this file is always
    loaded after. The few tokens the frames use that the main stylesheet does not define are
    declared here under the same names the frames use.
*/

:root{
  --ws-rail-line:rgba(246,244,239,.12);
  --ws-rail-dim:rgba(246,244,239,.60);
  --ws-line:rgba(20,23,42,.12);
  --ws-line-2:rgba(20,23,42,.07);
  --ws-cloud:#F1F3F7;
  --ws-amber:#9A6B16;
}

/* ---------- shell ---------- */
/* ---------- the operator's side rail ---------- */
/* Every account shares the masthead. Below it, a team's areas fit a single strip and are drawn
   that way; the operator's do not. Two dozen destinations in a horizontally scrolling band means
   most of them are off-screen most of the time, and the reader has to drag to find out what
   exists. A column shows the whole map at once, keeps its grouping legible, and is what the rail
   below is for. It sits under the masthead rather than replacing it, so the brand, the guides and
   the identity stay where they are on every other page.

   Narrow viewports get the strip back: a fixed dark column 240px wide would take most of a phone
   screen, and a short scroll is the lesser cost there. */
.ws-shell.railed .ws-body{display:grid;grid-template-columns:244px minmax(0,1fr);flex:1;min-height:0}
.ws-rail{background:var(--oxford-900);color:var(--ivory);padding:10px 0 18px;display:flex;flex-direction:column;
  border-right:1px solid var(--ws-rail-line);
  /* The masthead is sticky at the top, so the rail pins beneath it and scrolls its own overflow
     rather than running off the foot of a long page. */
  position:sticky;top:var(--ws-mast-h,60px);height:calc(100vh - var(--ws-mast-h,60px));overflow-y:auto}
.ws-rail nav{padding:8px 12px;display:flex;flex-direction:column;gap:2px;flex:1}
.ws-rail .ws-ng{font:500 10px/1 var(--mono);letter-spacing:.2em;color:var(--ws-rail-dim);text-transform:uppercase;
  padding:14px 10px 7px}
.ws-rail nav a{display:flex;align-items:center;gap:11px;padding:8.5px 10px;border-radius:9px;
  font:500 13.5px/1.2 var(--body);color:var(--ws-rail-dim);text-decoration:none}
.ws-rail nav a svg{flex:none;width:17px;height:17px;opacity:.85}
.ws-rail nav a:hover{color:var(--ivory);background:rgba(246,244,239,.05)}
.ws-rail nav a.on{background:rgba(246,244,239,.10);color:var(--ivory);font-weight:600}

.ws-main{background:var(--ivory);min-width:0;display:flex;flex-direction:column}
.ws-topbar{display:flex;align-items:center;gap:14px;padding:16px 30px;border-bottom:1px solid var(--ws-line-2);background:var(--ivory);
  /* Sticky, as the previous topbar was: on a long registrations table the Guides button and the
     bell should not scroll away. */
  position:sticky;top:0;z-index:40}
.ws-topbar .ws-crumb{font:400 12.5px/1.35 var(--body);color:var(--ink-62);display:flex;align-items:center;gap:7px;min-width:0}
.ws-topbar .ws-crumb .cr-sep{color:var(--ink-42)}
.ws-topbar .ws-crumb .cr-team{color:var(--ink-62);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.ws-topbar .ws-crumb a{color:inherit;text-decoration:none}
.ws-topbar .ws-crumb a:hover{color:var(--ink)}
.ws-topbar .sp{flex:1}
.ws-helpbtn{display:inline-flex;align-items:center;gap:8px;height:34px;padding:0 13px;border:1px solid var(--ws-line);
  border-radius:9px;font:600 12.5px/1 var(--body);color:var(--oxford);background:var(--paper);cursor:pointer}
.ws-helpbtn svg{width:14px;height:14px}
.ws-iconbtn{width:34px;height:34px;border:1px solid var(--ws-line);border-radius:9px;display:flex;align-items:center;
  justify-content:center;background:var(--paper);color:var(--ink-62);position:relative;cursor:pointer;padding:0;flex:none}
.ws-iconbtn svg{width:15px;height:15px}
.ws-iconbtn .dot{position:absolute;top:7px;right:7px;width:7px;height:7px;border-radius:50%;background:var(--ws-amber)}

/* The topbar's language switcher keeps its component styling from the main stylesheet; only its
   height is normalised so the row of controls sits on one line. */
.ws-topbar .lang-switch summary{height:34px}

/* ---------- announcement bell popover ---------- */
.ws-bell{position:relative}
.ws-bell-pop{position:absolute;top:calc(100% + 8px);right:0;width:330px;max-width:calc(100vw - 32px);background:var(--paper);
  border:1px solid var(--ws-line-2);border-radius:14px;box-shadow:0 1px 2px rgba(20,23,42,.04),0 18px 44px -18px rgba(20,23,42,.28);
  z-index:60;display:none;text-align:left}
.ws-bell-pop.open{display:block}
.ws-bell-pop .bp-head{padding:12px 16px 9px;font:500 10.5px/1 var(--mono);letter-spacing:.22em;color:var(--ink-62);text-transform:uppercase}
.ws-bell-pop .bp-item{padding:11px 16px;border-top:1px solid var(--ws-line-2)}
.ws-bell-pop .bp-item .bt{font:600 13px/1.35 var(--body);color:var(--ink)}
.ws-bell-pop .bp-item .bb{font:400 12.5px/1.55 var(--body);color:var(--ink-62);margin-top:3px}
.ws-bell-pop .bp-empty{padding:14px 16px;border-top:1px solid var(--ws-line-2);font:400 12.5px/1.55 var(--body);color:var(--ink-62)}
.ws-bell-pop .bp-foot{display:flex;gap:14px;padding:11px 16px;border-top:1px solid var(--ws-line-2)}
.ws-bell-pop .bp-foot a{font:600 12px/1 var(--body);color:var(--oxford);text-decoration:none}
.ws-bell-pop .bp-foot a:hover{text-decoration:underline}


/* ---------- guides slide-over ---------- */
.ws-guides-overlay{position:fixed;inset:0;background:rgba(20,23,42,.34);z-index:70;display:none}
.ws-guides-overlay.open{display:block}
.ws-guides{position:fixed;top:0;right:0;bottom:0;width:400px;max-width:100vw;background:var(--paper);z-index:71;
  box-shadow:-18px 0 44px -22px rgba(20,23,42,.35);transform:translateX(100%);transition:transform .22s ease;
  display:flex;flex-direction:column}
.ws-guides.open{transform:translateX(0)}
.ws-guides .gd-head{display:flex;align-items:center;gap:12px;padding:18px 22px;border-bottom:1px solid var(--ws-line-2)}
.ws-guides .gd-head .gd-eyebrow{font:500 10.5px/1 var(--mono);letter-spacing:.22em;color:var(--ink-62);text-transform:uppercase}
.ws-guides .gd-head .sp{flex:1}
.ws-guides .gd-close{width:30px;height:30px;border:1px solid var(--ws-line);border-radius:8px;background:var(--paper);
  color:var(--ink-62);display:flex;align-items:center;justify-content:center;cursor:pointer;padding:0}
.ws-guides .gd-close svg{width:13px;height:13px}
.ws-guides .gd-body{padding:20px 22px 28px;overflow-y:auto}
.ws-guides .gd-body h3{font:700 16.5px/1.25 var(--display);letter-spacing:-.012em;color:var(--ink);margin:0 0 8px}
.ws-guides .gd-body p{font:400 13px/1.6 var(--body);color:var(--ink-80);margin:0 0 12px}
.ws-guides .gd-body ol{margin:0 0 12px;padding-left:19px}
.ws-guides .gd-body ol li{font:400 13px/1.6 var(--body);color:var(--ink-80);margin-bottom:8px;padding-left:3px}
.ws-guides .gd-body .gd-note{background:var(--ws-cloud);border-radius:12px;padding:12px 15px;font:400 12.5px/1.6 var(--body);color:var(--ink-80)}
.ws-guides [data-guide-section]{display:none}
.ws-guides [data-guide-section].on{display:block}

/* ---------- responsive: the rail becomes a pannable strip ---------- */
/* The rail folds into a strip below this width. It goes earlier than the shell's own breakpoint
   because a column takes 244px away from the page beside it rather than from the space above it,
   and the operator's pages still carry pre-redesign tables that want a wide column. */
@media (max-width:1279px){
  .ws-shell.railed .ws-body{display:flex;flex-direction:column}
  .ws-rail{position:static;height:auto;overflow:visible;border-right:none;padding:0;
    background:var(--oxford);flex-direction:row}
  .ws-rail nav{flex-direction:row;align-items:stretch;gap:16px;padding:0 18px;overflow-x:auto;
    scrollbar-width:none}
  .ws-rail nav::-webkit-scrollbar{display:none}
  .ws-rail .ws-ng{font-size:9.5px;padding:0 9px 0 0;margin-right:3px;align-self:center;flex:none;
    border-right:1px solid rgba(246,244,239,.18)}
  .ws-rail nav a{padding:12px;border-radius:0;border-bottom:2.5px solid transparent;
    font-size:13px;white-space:nowrap;flex:none}
  .ws-rail nav a:hover{background:none}
  .ws-rail nav a.on{background:none;border-bottom-color:var(--brass-bright)}
}

@media (max-width:1023px){
  .ws-cols{grid-template-columns:minmax(0,1fr)}
  .ws-statrow{grid-template-columns:repeat(2,minmax(0,1fr))}
  .ws-grid3{grid-template-columns:repeat(2,minmax(0,1fr))}
}


@media (max-width:719px){
  .ws-topbar{padding:12px 16px}
  .ws-topbar .ws-crumb .cr-tail{display:none}
  .ws-guides{width:100vw}
  /* A page-level control row stacks rather than colliding: the field and the button each take the
     full width instead of fighting over a strip too narrow for either. */
  .ws-pagerow{flex-direction:column;align-items:stretch}
  .ws-pagerow > *{width:100%;min-width:0}
  .ws-pagerow .ws-btn{justify-content:center}
}
/* A field inside a flex row must be allowed to shrink, or its select's intrinsic width pushes it
   over whatever sits beside it. */
.ws-pagerow{display:flex;align-items:center;gap:13px;flex-wrap:wrap}
.ws-pagerow > *{min-width:0}
.ws-pagerow .ws-fld{min-width:0}
.ws-pagerow .ws-fld select{max-width:100%;width:100%}

/* ---------- Records landing ---------- */
.ws-recgrid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:14px;max-width:980px}
.ws-reccard{display:flex;align-items:flex-start;gap:14px;padding:17px 18px;background:var(--paper);
  border:1px solid var(--ws-line-2);border-radius:14px;text-decoration:none;color:var(--ink);
  box-shadow:0 1px 2px rgba(20,23,42,.04),0 10px 26px -18px rgba(20,23,42,.14)}
.ws-reccard:hover{border-color:var(--ws-line)}
.ws-reccard .rc-icon{flex:none;color:var(--oxford);margin-top:2px}
.ws-reccard .rc-icon svg{width:19px;height:19px}
.ws-reccard .rc-title{font:700 15px/1.25 var(--display);letter-spacing:-.01em}
.ws-reccard .rc-sub{font:400 12.5px/1.55 var(--body);color:var(--ink-62);margin-top:4px}
.ws-reccard .rc-chev{flex:none;width:15px;height:15px;color:var(--ink-42);margin-left:auto;align-self:center}
.ws-recnote{margin-top:16px;max-width:980px;background:var(--ws-cloud);border-radius:12px;padding:12px 15px;
  font:400 12.5px/1.6 var(--body);color:var(--ink-80)}
@media (max-width:719px){.ws-recgrid{grid-template-columns:minmax(0,1fr)}}

/* ---------- election workspace: content atoms ----------
   Ported from the design frames with the ws- namespace. These serve the pages rebuilt to the
   workspace design; pages not yet rebuilt keep the main stylesheet's own classes untouched. */
.ws-eyebrow{font:500 10.5px/1 var(--mono);letter-spacing:.22em;color:var(--ink-62);text-transform:uppercase}
.ws-eyebrow.brass{color:var(--brass-600)}
.ws-hxl{font:800 27px/1.12 var(--display);letter-spacing:-.02em;color:var(--ink);margin:0}
.ws-hmd{font:700 16.5px/1.25 var(--display);letter-spacing:-.012em;color:var(--ink);margin:0}
.ws-sub{font:400 13.5px/1.55 var(--body);color:var(--ink-62)}
.ws-small{font:400 12.5px/1.55 var(--body);color:var(--ink-62)}
.ws-card{background:var(--paper);border:1px solid var(--ws-line-2);border-radius:14px;
  box-shadow:0 1px 2px rgba(20,23,42,.04),0 10px 26px -18px rgba(20,23,42,.14)}
/* Cards carry no margin of their own: a page stacks them in a column with a gap, which is one
   rule for the spacing rather than a margin on every card plus a gap around it. A margin here
   added itself to every column that already had a gap and left a stray space under the last card
   on every page. */
.ws-chip{display:inline-flex;align-items:center;gap:5px;height:22px;padding:0 9px;border-radius:6px;
  font:500 10.5px/1 var(--mono);letter-spacing:.14em;white-space:nowrap;text-transform:uppercase}
.ws-chip.active{background:var(--oxford);color:var(--ivory)}
.ws-chip.sched{border:1px solid var(--ws-line);color:var(--ink-62);background:var(--paper)}
.ws-chip.draft{border:1px solid var(--ws-line);color:var(--ink-42);background:var(--paper)}
.ws-chip.sealed{border:1px solid rgba(168,132,60,.45);color:var(--brass-600);background:rgba(168,132,60,.07)}
.ws-chip.ok{border:1px solid rgba(46,107,79,.35);color:var(--verified);background:rgba(46,107,79,.06)}
.ws-chip.warn{border:1px solid rgba(154,107,22,.4);color:var(--ws-amber);background:rgba(154,107,22,.06)}
.ws-chip.bad{border:1px solid rgba(140,47,47,.4);color:var(--oxblood);background:rgba(140,47,47,.06)}
.ws-btn{display:inline-flex;align-items:center;justify-content:center;gap:8px;height:42px;padding:0 18px;border-radius:11px;
  font:600 13.5px/1 var(--body);white-space:nowrap;text-decoration:none;border:0;cursor:pointer}
.ws-btn.primary{background:var(--oxford);color:var(--ivory);box-shadow:0 10px 22px -12px rgba(30,58,95,.55)}
.ws-btn.primary:hover{background:var(--oxford-700)}
.ws-btn.ghost{border:1px solid var(--ws-line);color:var(--oxford);background:var(--paper)}
.ws-btn.lg{height:48px;padding:0 24px;font-size:14.5px;border-radius:12px}
.ws-btn.xs{height:32px;padding:0 12px;font-size:12px;border-radius:8px}
.ws-btn.danger-ghost{border:1px solid rgba(140,47,47,.3);color:var(--oxblood);background:var(--paper)}
.ws-divline{height:1px;background:var(--ws-line-2)}
.ws-note{background:var(--ws-cloud);border-radius:12px;padding:12px 15px;font:400 12.5px/1.6 var(--body);color:var(--ink-80)}
.ws-danger{border:1px solid rgba(140,47,47,.28);border-radius:14px;background:rgba(140,47,47,.03)}

/* the two-column workspace body: content beside the 330px side rail */
.ws-cols{display:grid;grid-template-columns:minmax(0,1fr) 330px;gap:18px;align-items:start}

/* the lifecycle stepper */
.ws-steps{display:flex;align-items:center;gap:0;overflow-x:auto;padding:2px 0}
.ws-steps .st{display:flex;align-items:center;gap:9px;white-space:nowrap}
.ws-steps .st .sc{width:24px;height:24px;border-radius:50%;border:1.5px solid var(--ws-line);display:flex;align-items:center;
  justify-content:center;font:700 11px/1 var(--display);color:var(--ink-42);background:var(--paper);flex:none}
.ws-steps .st .sl{font:500 12px/1 var(--body);color:var(--ink-62)}
.ws-steps .st.done .sc{background:var(--verified);border-color:var(--verified);color:#fff}
.ws-steps .st.now .sc{border-color:var(--oxford);border-width:2px;color:var(--oxford)}
.ws-steps .st.now .sl{color:var(--ink);font-weight:600}
.ws-steps .cn{width:34px;height:1.5px;background:var(--ws-line);margin:0 10px;flex:none}
.ws-steps .cn.done{background:var(--verified)}

/* the workspace tabs */
.ws-wtabs{display:flex;gap:2px;border-bottom:1px solid var(--ws-line-2);overflow-x:auto}
.ws-wtabs a{padding:10px 15px;font:500 13px/1 var(--body);color:var(--ink-62);border-bottom:2px solid transparent;
  white-space:nowrap;text-decoration:none}
.ws-wtabs a:hover{color:var(--ink)}
.ws-wtabs a.on{color:var(--ink);font-weight:600;border-bottom-color:var(--oxford)}

/* readiness rows */
.ws-ready{display:flex;gap:13px;padding:13px 18px;align-items:flex-start}
.ws-ready .ri{flex:none;margin-top:1px}
.ws-ready .ri-dot{flex:none;width:9px;height:9px;border-radius:50%;margin-top:5px}
.ws-ready .ri-dot.amber{background:var(--ws-amber)}
.ws-ready .ri-dot.grey{background:var(--ink-42)}
.ws-ready .ri-dot.oxblood{background:var(--oxblood)}
.ws-ready .rt{font:600 13.5px/1.3 var(--body);color:var(--ink)}
.ws-ready .rd{font:400 12.5px/1.55 var(--body);color:var(--ink-62);margin-top:3px}
.ws-ready .ra{margin-left:auto;flex:none}

/* the workspace header's title row */
.ws-hdrow{display:flex;align-items:center;gap:13px;flex-wrap:wrap}
.ws-hdrow .sp{flex:1}

@media (max-width:1023px){
  .ws-cols{grid-template-columns:minmax(0,1fr)}
}
@media (max-width:719px){
  .ws-hxl{font-size:23px}
}

/* ---------- review and schedule ---------- */
.ws-grid2{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:14px}
@media (max-width:719px){.ws-grid2{grid-template-columns:minmax(0,1fr)}}
/* the confirmation tick: a real checkbox wearing the frame's square */
.ws-check{display:flex;align-items:center;gap:11px;cursor:pointer}
.ws-check input{position:absolute;opacity:0;width:1px;height:1px}
.ws-check .cb{width:19px;height:19px;border-radius:6px;border:1.5px solid var(--ws-line);background:var(--paper);
  display:flex;align-items:center;justify-content:center;flex:none}
.ws-check .cb svg{display:none}
.ws-check input:checked + .cb{background:var(--oxford);border-color:var(--oxford)}
.ws-check input:checked + .cb svg{display:block}
.ws-check input:focus-visible + .cb{outline:2px solid var(--oxford);outline-offset:2px}
/* the what-happens-when timeline rows */
.ws-when{display:flex;gap:12px}
.ws-when .wt{font:500 11px/1.5 var(--mono);letter-spacing:.06em;min-width:120px;color:var(--ink-62);text-transform:uppercase;flex:none}
.ws-when .wd{font:400 12.5px/1.55 var(--body);color:var(--ink-80)}

/* ---------- dashboard and index atoms ---------- */
.ws-statrow{display:grid;grid-template-columns:repeat(5,minmax(0,1fr));gap:12px}
.ws-stat{background:var(--paper);border:1px solid var(--ws-line-2);border-radius:12px;padding:13px 15px;
  display:block;text-decoration:none;color:inherit;transition:border-color .14s ease}
.ws-stat:hover{border-color:var(--ws-line)}
.ws-stat .sn{font:500 24px/1 var(--mono);color:var(--ink)}
.ws-stat .sl{font:500 11.5px/1.35 var(--body);color:var(--ink-62);margin-top:7px}
.ws-stat .sd{width:8px;height:8px;border-radius:50%;background:var(--ws-amber);flex:none}
/* A figure close to a limit it must not pass. The billing page had its own tile for this; the
   state belongs to the atom rather than to one page's copy of it. */
.ws-stat.warn{border-color:rgba(154,107,22,.35);background:rgba(154,107,22,.05)}
@media (max-width:1023px){.ws-statrow{grid-template-columns:repeat(2,minmax(0,1fr))}}
/* the turnout and readiness bar */
.ws-bar{height:6px;border-radius:3px;background:var(--ws-cloud);overflow:hidden}
.ws-bar i{display:block;height:100%;background:var(--oxford);border-radius:3px}
.ws-bar.verified i{background:var(--verified)}
/* the state filter, links rather than tabs so a filter survives a page reload */
.ws-seg{display:inline-flex;background:var(--ws-cloud);border:1px solid var(--ws-line-2);border-radius:10px;padding:3px;gap:3px;flex-wrap:wrap}
.ws-seg a{padding:7px 14px;border-radius:8px;font:600 12px/1 var(--body);color:var(--ink-62);white-space:nowrap;text-decoration:none}
.ws-seg a:hover{color:var(--ink)}
.ws-seg a.on{background:var(--paper);color:var(--ink);box-shadow:0 1px 2px rgba(20,23,42,.06)}
/* the search field */
.ws-search{flex:1;min-width:220px;height:40px;border-radius:11px;background:var(--paper);border:1px solid var(--ws-line);
  display:flex;align-items:center;padding:0 13px;gap:10px}
.ws-search input{flex:1;min-width:0;border:0;outline:0;background:none;font:400 13px/1.4 var(--body);color:var(--ink)}
.ws-search input::placeholder{color:var(--ink-42)}
/* the to-do list table */
.ws-tbl{display:flex;flex-direction:column}
.ws-tbl .tr{display:grid;align-items:center;gap:14px;padding:12px 18px;border-top:1px solid var(--ws-line-2)}
.ws-tbl .tr.hd{border-top:none;padding:10px 18px;font:600 10.5px/1 var(--mono);letter-spacing:.16em;
  color:var(--ink-62);text-transform:uppercase}
.ws-tbl .tr .et{font:600 14px/1.3 var(--body);color:var(--ink);text-decoration:none;display:block}
.ws-tbl .tr .et:hover{color:var(--oxford)}
.ws-tbl .tr > .cell-end{justify-self:end}
/* A row that can be selected keeps its checkbox in a gutter of its own rather than inside the
   first cell, so every cell in the row starts at one left edge instead of the first being pushed
   right by a box the others know nothing about. */
.ws-tbl .tr.has-sel{position:relative;padding-left:44px}
.ws-tbl .tr.has-sel .ws-selbox{position:absolute;left:18px;top:50%;transform:translateY(-50%);margin:0}
.ws-tbl .tr.hd.has-sel .ws-selbox{top:50%}
.ws-empty{padding:34px 18px;text-align:center}
@media (max-width:719px){
  .ws-tbl .tr.hd{display:none}
  .ws-tbl .tr{grid-template-columns:minmax(0,1fr) !important;gap:8px;padding:14px 16px}
  .ws-tbl .tr.has-sel{padding-left:44px}
  /* Stacked, the box sits against the first line rather than the middle of a tall card. */
  .ws-tbl .tr.has-sel .ws-selbox{left:16px;top:17px;transform:none}
  .ws-tbl .tr > .cell-end{justify-self:start}
  .ws-hide-s{display:none !important}
}

/* a guide row is a button, because it opens a panel rather than going anywhere */
.ws-guidelink{width:100%;background:none;border:0;text-align:left;cursor:pointer;font:inherit}
.ws-guidelink:hover .rt{color:var(--oxford)}
.ws-guidelink:focus-visible{outline:2px solid var(--oxford);outline-offset:-2px;border-radius:10px}

/* ---------- the new-election wizard ---------- */
.ws-hlg{font:800 21px/1.15 var(--display);letter-spacing:-.018em;color:var(--ink);margin:0}
/* a field is the frame's box with a real control inside it */
.ws-fld{background:var(--paper);border:1px solid var(--ws-line);border-radius:11px;padding:9px 13px;
  display:block;transition:border-color .14s ease}
.ws-fld:focus-within{border-color:var(--oxford)}
.ws-fld .fl{font:600 10.5px/1 var(--body);color:var(--ink-62);display:block}
.ws-fld input,.ws-fld textarea{width:100%;border:0;outline:0;background:none;padding:0;margin-top:4px;
  font:400 14px/1.35 var(--body);color:var(--ink);display:block}
.ws-fld textarea{resize:vertical;min-height:38px}
.ws-fld input::placeholder,.ws-fld textarea::placeholder{color:var(--ink-42)}
.ws-fld.bad{border-color:var(--oxblood)}
.ws-fld-err{font:400 12px/1.5 var(--body);color:var(--oxblood);margin-top:5px}
/* the wizard's forward steps are stated, not offered, until the draft exists */
.ws-steps .st.ahead .sl{color:var(--ink-42)}
@media (max-width:719px){.ws-btnrow-stack{flex-direction:column;align-items:stretch}}

/* ---------- the ballot builder ---------- */
.ws-grid3{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:14px;align-items:start}
@media (max-width:1023px){.ws-grid3{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media (max-width:719px){.ws-grid3{grid-template-columns:minmax(0,1fr)}}
.ws-office{padding:16px 18px}
.ws-office-grip{flex:none;cursor:grab;line-height:0;padding:2px}
.ws-office-grip:active{cursor:grabbing}
/* a candidate as the ballot shows them: a monogram and a name, nothing else */
.ws-cand{display:flex;align-items:center;gap:10px}
.ws-cand .mono-av{width:26px;height:26px;border-radius:50%;background:var(--ws-cloud);overflow:hidden;flex:none;
  display:flex;align-items:center;justify-content:center;font:700 10px/1 var(--display);color:var(--oxford-700)}
.ws-cand .mono-av img{width:100%;height:100%;object-fit:cover}
.ws-cand .cn{font:500 13px/1.3 var(--body);color:var(--ink);display:block}
.ws-cand .cd{font:400 11.5px/1.4 var(--body);color:var(--ink-62);display:block;margin-top:2px}
.ws-cand-acts{display:none;gap:6px;flex:none;flex-wrap:wrap}
.ws-cand:hover .ws-cand-acts,.ws-cand:focus-within .ws-cand-acts{display:flex}
@media (hover:none){.ws-cand-acts{display:flex}}
/* the dashed slot that adds one */
.ws-addcard{border:1.5px dashed var(--ws-line);border-radius:14px;display:flex;flex-direction:column;
  align-items:center;justify-content:center;gap:10px;color:var(--ink-62);min-height:210px;padding:20px;
  background:none;width:100%;cursor:pointer;font:inherit;text-align:center}
.ws-addcard:hover{border-color:var(--oxford);color:var(--ink)}
.ws-addcard .al{font:600 13.5px/1 var(--body)}

/* ---------- the nominating board ---------- */
.ws-dots{display:inline-flex;gap:5px;align-items:center; margin-left: 20px}
.ws-dots i{width:7px;height:7px;border-radius:50%;background:var(--ws-line);display:block}
.ws-dots i.done{background:var(--verified)}
.ws-dots i.now{background:var(--oxford);box-shadow:0 0 0 3px rgba(30,58,95,.12)}
.ws-threshold{font:500 26px/1 var(--mono);color:var(--ink)}
/* Extra room under a table row. Scoped to the table: the masthead's identity line carries the
   same class name, and unscoped this padded it too and made the masthead 16px taller. */
.ws-tbl .tr{padding-bottom:20px}

/* ---------- the board portal ---------- */
.ws-hashchip{display:inline-flex;align-items:center;gap:7px;background:var(--ws-cloud);border-radius:8px;
  padding:6px 10px;font:500 11.5px/1 var(--mono);letter-spacing:.04em;color:var(--ink-80)}
.ws-quorum{display:flex;gap:5px}
.ws-quorum i{height:6px;border-radius:3px;background:var(--ws-line);flex:1}
.ws-quorum i.done{background:var(--verified)}
/* the ceremony and portal run without the rail: the page is the whole task */
.ws-solo{min-height:100vh;background:var(--ivory);display:flex;flex-direction:column}
.ws-solo-bar{display:flex;align-items:center;gap:12px;padding:14px 22px;border-bottom:1px solid var(--ws-line-2);background:var(--paper)}
/* One column, centred. It was a row, which meant that a page putting two children in here got two
   flex items each asking for the full width, both shrinking to share it, and a layout collapsed to
   half the page. Stacking them instead makes that impossible while leaving a single child, which
   is what every page here has, laid out exactly as before. */
.ws-solo-body{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:flex-start;padding:34px 22px}
.ws-solo-inner{width:100%;max-width:1020px;display:flex;flex-direction:column;gap:16px}

/* The stage an election has arrived at, when that stage is the end of the journey: ticked like
   every finished stage, and still named in full ink so the eye lands on where it got to. */
.ws-steps .st.now-done .sl{color:var(--ink);font-weight:600}

/* ---------- tables on a narrow screen ----------
   A seven-column table cannot be read on a 390-pixel screen, and scrolling one sideways hides the
   column that gives a cell its meaning. Below 720px an opted-in table becomes a stack of cards,
   one per row, each cell carrying its own column heading from data-label. Tables opt in with
   ws-stack so this is a decision made per table rather than imposed on every one. */
@media (max-width:719px){
  .table.ws-stack,
  .table.ws-stack thead,
  .table.ws-stack tbody,
  .table.ws-stack tr,
  .table.ws-stack th,
  .table.ws-stack td{display:block}
  .table.ws-stack thead{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}
  .table.ws-stack tbody tr{border:1px solid var(--ws-line-2);border-radius:12px;background:var(--paper);
    padding:4px 0;margin-bottom:11px}
  .table.ws-stack tbody tr:last-child{margin-bottom:0}
  .table.ws-stack tbody tr:hover{background:var(--paper)}
  .table.ws-stack td{border-bottom:1px solid var(--ws-line-2);padding:9px 15px;
    display:flex;align-items:baseline;justify-content:space-between;gap:14px;text-align:right}
  .table.ws-stack tbody tr td:last-child{border-bottom:none}
  .table.ws-stack td::before{content:attr(data-label);flex:none;text-align:left;
    font:500 10.5px/1.5 var(--mono);letter-spacing:.09em;text-transform:uppercase;color:var(--ink-62)}
  .table.ws-stack td:empty{display:none}
  /* A cell holding controls reads better on its own line, ranged left under its heading. A cell
     under a blank heading is a controls cell by another name, so it is treated the same. */
  .table.ws-stack td[data-stackfull]::before{content:attr(data-label)}
  .table.ws-stack td[data-stackfull]:not([data-label])::before{display:none}
  .table.ws-stack td[data-stackfull],
  .table.ws-stack td:not([data-label]){display:block;text-align:left}
  .table.ws-stack td:not([data-label])::before{display:none}
  .table.ws-stack td .btn,
  .table.ws-stack td form{max-width:100%}
  .table.ws-stack td[data-stackfull]::before{display:block;margin-bottom:7px}
  /* The wrapper's sideways scroll is pointless once the rows have stacked. */
  .table-responsive:has(.table.ws-stack),
  .table-scroll:has(.table.ws-stack){overflow-x:visible;border:none;border-radius:0}
}

/* ---------- the masthead and the navigation band ----------
   The workspace reads top to bottom: a masthead carrying the wordmark, the workspace's own
   controls and whose workspace it is, then a navigation band directly beneath it, then the page.
   The wordmark shares a line with nothing that scrolls, so navigating can never displace it. */
.ws-shell{display:flex;flex-direction:column;min-height:100vh;grid-template-columns:none}
.ws-mast{background:var(--oxford-900);color:var(--ivory);display:flex;align-items:center;gap:16px;
  padding:13px 30px;position:sticky;top:0;z-index:70}
.ws-mast .brand{display:flex;align-items:center;gap:11px;flex:none;color:var(--ivory)}
/* The mark is one silhouette painted in currentColor, so a dark surface has to say so. The base
   stylesheet colours it ink for light pages, and the footer and the operator rail each override
   that for their own dark ground; the workspace masthead never did, so the mark was drawn in ink
   on oxford and was effectively invisible. */
.ws-mast .brand .cv-seal{color:var(--ivory)}
.ws-mast .brand .bt{font:700 16px/1 var(--display);letter-spacing:-.01em;display:block}
.ws-mast .brand .bt b{color:var(--brass-bright)}
.ws-mast .brand .bs{font:500 9.5px/1 var(--mono);letter-spacing:.2em;color:var(--ws-rail-dim);margin-top:5px;display:block}
.ws-mast .sp{flex:1}
.ws-mast .ws-tm{display:flex;align-items:center;gap:10px;flex:none;min-width:0}
.ws-mast .ws-tm .av{width:31px;height:31px;border-radius:50%;background:rgba(246,244,239,.14);display:flex;
  align-items:center;justify-content:center;font:700 11px/1 var(--display);color:var(--ivory);flex:none}
.ws-mast .ws-tm .who{min-width:0}
.ws-mast .ws-tm .tn{font:600 12.5px/1.25 var(--body);color:var(--ivory);display:block;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.ws-mast .ws-tm .tr{font:400 11px/1 var(--body);color:var(--ws-rail-dim);margin-top:3px;display:block}
.ws-mbtn{display:inline-flex;align-items:center;gap:8px;height:34px;padding:0 13px;border-radius:9px;
  border:1px solid rgba(246,244,239,.22);background:none;font:600 12.5px/1 var(--body);color:var(--ivory);
  flex:none;cursor:pointer}
.ws-mbtn:hover,.ws-mico:hover{background:rgba(246,244,239,.08)}
.ws-mico{width:34px;height:34px;border-radius:9px;border:1px solid rgba(246,244,239,.22);background:none;
  display:flex;align-items:center;justify-content:center;color:var(--ivory);position:relative;flex:none;cursor:pointer}
.ws-mico .dot{position:absolute;top:6px;right:6px;width:7px;height:7px;border-radius:50%;background:var(--brass-bright)}
.ws-mast .ws-signout{flex:none;display:flex}
.ws-mast .ws-bell{position:relative;flex:none}
/* On a phone the bell is not the last control in the row: the avatar and the way out sit to its
   right. Anchoring the panel to the bell's own right edge therefore pushed a 330px panel off the
   left of the window, by 62px at 360 and 49px at 390. Releasing the anchor lets the panel span
   the window with even gutters instead: the masthead is sticky, so it is already a positioned
   ancestor, and with the bell itself unpositioned the offsets are measured from the window
   rather than from the button. No control added to or removed from the cluster can move the
   panel again, and above this width it still hangs under its own bell. */
@media (max-width:719px){
  .ws-mast .ws-bell{position:static}
  .ws-mast .ws-bell-pop{right:16px}
}

.ws-nav{background:var(--oxford);color:var(--ivory);display:flex;align-items:stretch;gap:22px;
  padding:0 30px;overflow-x:auto;flex:none;scrollbar-width:none}
.ws-nav::-webkit-scrollbar{display:none}
.ws-nav .ws-ng{font:500 9.5px/1 var(--mono);letter-spacing:.2em;color:rgba(246,244,239,.5);
  text-transform:uppercase;padding:0 9px 0 0;margin-right:3px;border-right:1px solid rgba(246,244,239,.18);
  align-self:center;flex:none}
.ws-nav a{display:flex;align-items:center;gap:9px;padding:12px;border-bottom:2.5px solid transparent;
  font:500 13px/1 var(--body);color:rgba(246,244,239,.72);white-space:nowrap;flex:none}
.ws-nav a svg{flex:none;opacity:.9;width:17px;height:17px}
.ws-nav a:hover{color:var(--ivory)}
.ws-nav a.on{color:var(--ivory);font-weight:600;border-bottom-color:var(--brass-bright)}
.ws-main{min-width:0;display:flex;flex-direction:column;flex:1}

@media (max-width:1023px){
  .ws-mast{padding:11px 18px;gap:12px}
  .ws-mast .ws-tm .tn,.ws-mast .ws-tm .tr{display:none}
  .ws-mbtn .mbl{display:none}
  .ws-mbtn{padding:0 10px}
  .ws-nav{padding:0 18px;gap:16px}
}
@media (max-width:719px){
  .ws-rail nav{padding:0 14px;gap:12px}
  .ws-rail .ws-ng{display:none}
  .ws-rail nav a{padding:11px 9px;font-size:12.5px}
  .ws-mast{padding:10px 14px;gap:10px}
  .ws-mast .brand .bs{display:none}
  .ws-nav{padding:0 14px;gap:12px}
  .ws-nav .ws-ng{display:none}
  .ws-nav a{padding:11px 9px;font-size:12.5px}
}

/* A candidate's monogram on a results tally, the same disc the ballot uses. */
.ws-mono-av{width:26px;height:26px;border-radius:50%;background:var(--ws-cloud);overflow:hidden;flex:none;
  display:flex;align-items:center;justify-content:center;font:700 10px/1 var(--display);color:var(--oxford-700)}
.ws-mono-av img{width:100%;height:100%;object-fit:cover}

/* ---------- settings: a stated setting with its consequence and its control ---------- */
.ws-set{display:flex;gap:14px;padding:14px 18px;align-items:flex-start;border-top:1px solid var(--ws-line-2)}
.ws-set:first-of-type{border-top:none}
.ws-set .st{font:600 13.5px/1.3 var(--body);color:var(--ink)}
.ws-set .sd{font:400 12.5px/1.55 var(--body);color:var(--ink-62);margin-top:3px;display: block}
.ws-set .sa{margin-left:auto;flex:none;display:flex;align-items:center;gap:9px}
/* A switch that reads as on or off at a glance, driven by the checkbox it wraps. */
.ws-switch{position:relative;display:inline-flex;flex:none;cursor:pointer}
.ws-switch input{position:absolute;inset:0;opacity:0;margin:0;cursor:pointer;z-index:1}
.ws-switch i{width:42px;height:25px;border-radius:14px;background:rgba(20,23,42,.18);display:block;
  position:relative;transition:background .15s}
.ws-switch i::after{content:"";position:absolute;top:3px;left:3px;width:19px;height:19px;border-radius:50%;
  background:#fff;box-shadow:0 1px 3px rgba(20,23,42,.3);transition:left .15s}
.ws-switch input:checked + i{background:var(--oxford)}
.ws-switch input:checked + i::after{left:20px}
.ws-switch input:disabled{cursor:default}
.ws-switch input:disabled + i{opacity:.5}
.ws-switch input:focus-visible + i{outline:2px solid var(--oxford);outline-offset:2px}
/* A number or a short value stated inside the settings row rather than as a form field. */
.ws-setnum{width:86px;padding:7px 10px;border:1px solid var(--ws-line);border-radius:9px;background:var(--paper);
  font:500 13px/1 var(--mono);color:var(--ink);text-align:right}
.ws-setsel{padding:7px 11px;border:1px solid var(--ws-line);border-radius:9px;background:var(--paper);
  font:400 13px/1.2 var(--body);color:var(--ink);max-width:100%}
@media (max-width:719px){
  .ws-set{flex-wrap:wrap}
  .ws-set .sa{margin-left:0;width:100%}
}

/* ---------- settings: choices stated as segments, and the share block ---------- */
/* A segmented control backed by radio inputs. The link form above is for navigation; this one
   carries a form value, so a setting with three or fewer choices can be seen and picked in one
   glance instead of being hidden inside a select. The checked state is driven by the adjacent
   sibling rather than :has(), so it holds on older engines too. */
.ws-seg .ws-segopt{position:relative;display:inline-flex;flex:none}
.ws-seg .ws-segopt input{position:absolute;inset:0;opacity:0;margin:0;cursor:pointer;z-index:1}
.ws-seg .ws-segopt span{padding:7px 14px;border-radius:8px;font:600 12px/1 var(--body);color:var(--ink-62);
  white-space:nowrap;transition:background .14s ease,color .14s ease}
.ws-seg .ws-segopt input:checked + span{background:var(--paper);color:var(--ink);box-shadow:0 1px 2px rgba(20,23,42,.06)}
.ws-seg .ws-segopt input:focus-visible + span{outline:2px solid var(--oxford);outline-offset:1px}
.ws-seg .ws-segopt input:disabled{cursor:default}
.ws-seg .ws-segopt input:disabled + span{opacity:.55}

/* The share link sits on its own line and may be long, so it fills its column and puts the copy
   affordance at the far end rather than letting the address push it out of the card. */
.ws-hashchip.block{display:flex;width:100%;justify-content:space-between;gap:10px;align-items:center;
  white-space:normal;word-break:break-all;text-align:left}
.ws-hashchip.block .hc-copy{flex:none;color:var(--ink-62);background:none;border:0;padding:0;cursor:pointer;
  display:inline-flex;align-items:center}
.ws-hashchip.block .hc-copy:hover{color:var(--oxford)}

/* The access code is read aloud and typed in by hand, so it is set larger and looser than the
   evidence hashes that only ever get compared by eye. */
.ws-accesscode{font:500 19px/1 var(--mono);letter-spacing:.16em;color:var(--ink)}

/* A settings row whose control is wide enough to need the whole line beneath its explanation. */
.ws-set.stacked{flex-direction:column;align-items:stretch}
.ws-set.stacked .sa{margin-left:0;width:100%}

/* ---------- the board and the key ceremony ---------- */
/* A verdict spoken back to the reader: the result of an action they just took, or a warning about
   one they are about to. The tone is carried by a left edge and a tint rather than a filled block,
   so a page can hold several without any of them shouting. The poller writes these class names, so
   changing them means changing it too. */
.ws-msg{border:1px solid var(--ws-line-2);border-left:3px solid var(--ws-line);border-radius:10px;
  background:var(--paper);padding:12px 15px;font:400 13px/1.6 var(--body);color:var(--ink-80)}
.ws-msg strong{color:var(--ink);font-weight:600}
.ws-msg.ok{border-left-color:var(--verified);background:rgba(46,107,79,.045)}
.ws-msg.bad{border-left-color:var(--oxblood);background:rgba(140,47,47,.05)}
.ws-msg.info{border-left-color:var(--brass);background:rgba(168,132,60,.05)}

/* A standalone control with no label wrapping it: the passphrase beside a button, the file to
   restore from. Matches the field inside .ws-fld so a form does not change texture halfway down. */
.ws-input{width:100%;border:1px solid var(--ws-line);border-radius:9px;padding:9px 11px;background:var(--paper);
  font:400 13.5px/1.35 var(--body);color:var(--ink)}
.ws-input:focus{outline:none;border-color:var(--oxford)}
.ws-input::placeholder{color:var(--ink-42)}
.ws-input[type=file]{padding:7px 9px;font-size:12.5px}

/* The holder's four ceremony steps. Each is a row rather than a card, because they are one
   sequence and drawing four cards would suggest four separate errands. The marker carries the
   step's state: a number while it waits, a tick once it is done. */
.ws-cstep{list-style:none;margin:14px 0 0;padding:0;display:flex;flex-direction:column;gap:2px}
.ws-cstep > li{display:flex;gap:13px;padding:13px 0;border-top:1px solid var(--ws-line-2)}
.ws-cstep > li:first-child{border-top:none}
.ws-cstep .cm{width:23px;height:23px;border-radius:50%;border:1px solid var(--ws-line);flex:none;
  display:flex;align-items:center;justify-content:center;font:500 11px/1 var(--mono);color:var(--ink-62);
  background:var(--paper);margin-top:1px}
.ws-cstep > li.done .cm{background:var(--verified);border-color:var(--verified);color:var(--paper)}
.ws-cstep .cb{min-width:0;flex:1}
.ws-cstep .ct{font:600 13.5px/1.3 var(--body);color:var(--ink);display:block}
.ws-cstep .cd{font:400 12.5px/1.55 var(--body);color:var(--ink-62);margin-top:4px;display:block}
.ws-cstep .ca{margin-top:10px;display:flex;gap:9px;flex-wrap:wrap;align-items:center}

/* Choosing who holds a share. A row per person, ticked to include them, with the owner shown as a
   fixed member rather than an option, because they hold one by rule. */
.ws-choice{display:flex;flex-direction:column;gap:8px;margin-top:10px}
.ws-choice label{display:flex;align-items:center;gap:12px;padding:11px 13px;border:1px solid var(--ws-line-2);
  border-radius:10px;background:var(--paper);cursor:pointer;transition:border-color .14s ease,background .14s ease}
.ws-choice label:hover{border-color:var(--ws-line)}
.ws-choice label:has(input:checked){border-color:var(--oxford);background:rgba(30,58,95,.035)}
.ws-choice label.fixed{cursor:default;background:var(--ws-cloud)}
.ws-choice input[type=checkbox]{width:16px;height:16px;accent-color:var(--oxford);flex:none;margin:0}
.ws-choice .cw{min-width:0;flex:1}
.ws-choice .cn{font:600 13px/1.3 var(--body);color:var(--ink);display:block;overflow:hidden;
  text-overflow:ellipsis;white-space:nowrap}
.ws-choice .ce{font:400 11.5px/1.4 var(--body);color:var(--ink-62);display:block;margin-top:2px;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}

/* The threshold stepper: a number nudged rather than typed, because the useful range is small and
   the bounds are what matter. */
.ws-numstep{display:inline-flex;align-items:center;border:1px solid var(--ws-line);border-radius:9px;
  background:var(--paper);overflow:hidden;flex:none}
.ws-numstep button{width:34px;height:36px;border:none;background:none;cursor:pointer;color:var(--ink-62);
  font:400 17px/1 var(--body);display:flex;align-items:center;justify-content:center}
.ws-numstep button:hover:not(:disabled){background:var(--ws-cloud);color:var(--ink)}
.ws-numstep button:disabled{opacity:.35;cursor:default}
.ws-numstep input{width:46px;height:36px;border:none;border-left:1px solid var(--ws-line-2);
  border-right:1px solid var(--ws-line-2);text-align:center;font:500 15px/1 var(--mono);color:var(--ink);
  background:none;-moz-appearance:textfield}
.ws-numstep input::-webkit-outer-spin-button,.ws-numstep input::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}
.ws-numstep input:focus{outline:none}

/* The QR the handover draws into, and the short code beside it. */
.ws-qr{width:200px;height:200px;padding:11px;background:#fff;border:1px solid var(--ws-line-2);border-radius:10px;flex:none}
.ws-qr canvas,.ws-qr img,.ws-qr svg{width:100%;height:100%;display:block}

/* ---------- selects and file pickers inside a field ---------- */
/* The field atom dressed its inputs and textareas and left selects and file pickers to the
   browser, so a styled frame sat around an unstyled control: a grey native box with its own
   font, its own chevron and its own baseline. These finish the set. */
.ws-fld:has(select){position:relative}
.ws-fld:has(select)::after{content:"";position:absolute;right:14px;top:50%;width:8px;height:8px;
  margin-top:-1px;pointer-events:none;border-right:1.6px solid var(--ink-62);
  border-bottom:1.6px solid var(--ink-62);transform:translateY(-50%) rotate(45deg)}
.ws-fld select{width:100%;border:0;outline:0;background:none;margin-top:4px;padding:0 24px 0 0;
  font:400 14px/1.35 var(--body);color:var(--ink);display:block;cursor:pointer;
  appearance:none;-webkit-appearance:none;-moz-appearance:none}
.ws-fld select:disabled{color:var(--ink-42);cursor:default}

/* A file picker's own button is the one part of it a page can style, so it is dressed as the
   ghost button it stands in for rather than left as the browser's grey slab. */
.ws-fld input[type=file]{margin-top:6px;font:400 12.5px/1.4 var(--body);color:var(--ink-62);cursor:pointer}
.ws-fld input[type=file]::file-selector-button{font:600 12px/1 var(--body);color:var(--ink);
  background:var(--paper);border:1px solid var(--ws-line);border-radius:8px;padding:7px 12px;
  margin-right:11px;cursor:pointer;transition:border-color .14s ease,background .14s ease}
.ws-fld input[type=file]::file-selector-button:hover{border-color:var(--ink-42);background:var(--ws-cloud)}

/* A standalone select carries its own frame, so its chevron is drawn on itself. */
select.ws-input{appearance:none;-webkit-appearance:none;-moz-appearance:none;cursor:pointer;
  padding-right:32px;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='11' height='7' viewBox='0 0 11 7' fill='none'%3E%3Cpath d='M1 1l4.5 4.5L10 1' stroke='%2314172A' stroke-opacity='.62' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat:no-repeat;background-position:right 11px center}

/* ---------- a select you can search ---------- */
/* Some lists are too long to scroll: the timezone list runs to several hundred entries, and
   finding one in a native select means either knowing its exact spelling or holding a key down.
   A select marked data-cv-search is upgraded into this at runtime. The native select stays in the
   form and keeps the value, so with no JavaScript the page still works exactly as it did. */
.ws-combo{position:relative;display:block}
.ws-combo > select{position:absolute;width:1px;height:1px;opacity:0;pointer-events:none;margin:0}
.ws-combo-btn{width:100%;border:0;outline:0;background:none;margin-top:4px;padding:0 24px 0 0;
  font:400 14px/1.35 var(--body);color:var(--ink);text-align:left;cursor:pointer;display:block;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
/* Anchored to the field's left edge and capped, rather than stretched to whatever width the field
   happens to have. A zone name is short; a panel as wide as the page is harder to read down, not
   easier. */
.ws-combo-panel{position:absolute;z-index:60;left:-13px;top:calc(100% + 11px);
  width:calc(100% + 26px);max-width:26rem;min-width:15rem;
  background:var(--paper);border:1px solid var(--ws-line);border-radius:12px;padding:9px;
  box-shadow:0 18px 44px -20px rgba(20,23,42,.4);display:none}
.ws-combo.open .ws-combo-panel{display:block}
/* Scoped through .ws-combo so it outranks `.ws-fld input`, which strips the border, the padding
   and the background from anything it wraps. Unscoped, this box arrived inside a field and was
   flattened into bare text with a placeholder, which is what it looked like: a label, not a box
   to type in. */
.ws-combo .ws-combo-search{width:100%;border:1px solid var(--ws-line-2);border-radius:9px;
  padding:8px 11px;margin:0;font:400 13px/1.35 var(--body);color:var(--ink);background:var(--ws-cloud)}
.ws-combo .ws-combo-search:focus{outline:none;border-color:var(--oxford);background:var(--paper)}
.ws-combo .ws-combo-search::placeholder{color:var(--ink-42)}
/* Deliberately not a flex column. A flex child shrinks before its parent overflows, so a capped
   list of several hundred options squeezed every row to a fraction of its line height instead of
   scrolling: the text was clipped top and bottom, the rows ran into each other, and no scrollbar
   ever appeared. Block layout lets the list overflow, which is what makes it scroll. */
.ws-combo-list{max-height:17rem;overflow-y:auto;overscroll-behavior:contain;margin-top:8px;display:block}
.ws-combo-opt{display:block;width:100%;min-height:34px;text-align:left;border:0;background:none;
  cursor:pointer;padding:8px 10px;border-radius:8px;font:400 13px/1.4 var(--body);color:var(--ink);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;scroll-margin:6px}
.ws-combo-opt:hover,.ws-combo-opt.active{background:var(--ws-cloud)}
.ws-combo-opt.on{font-weight:600;color:var(--oxford)}
.ws-combo-empty{padding:11px 10px;font:400 12.5px/1.5 var(--body);color:var(--ink-62)}

/* ---------- pagination ---------- */
/* Laravel's default paginator is a Tailwind view, and this platform does not load Tailwind, so
   every class on it was inert: the links rendered as bare text and both of its width variants
   showed at once. This is the replacement, and it is one control at every width. */
.ws-pager{display:flex;align-items:center;gap:14px;flex-wrap:wrap;margin-top:16px}
.ws-pager-count{font:400 12.5px/1.5 var(--body);color:var(--ink-62);flex:1;min-width:180px}
.ws-pager-count b{font-weight:600;color:var(--ink)}
.ws-pager-links{display:flex;align-items:center;gap:6px;flex-wrap:wrap}
.ws-pager-pages{display:flex;align-items:center;gap:6px}
.ws-pager-btn{display:inline-flex;align-items:center;justify-content:center;min-width:34px;height:34px;
  padding:0 11px;border:1px solid var(--ws-line-2);border-radius:9px;background:var(--paper);
  font:600 12.5px/1 var(--body);color:var(--ink);text-decoration:none;
  transition:border-color .14s ease,background .14s ease}
.ws-pager-btn:hover{border-color:var(--ws-line);background:var(--ws-cloud)}
.ws-pager-btn.is-on{background:var(--oxford);border-color:var(--oxford);color:var(--paper)}
.ws-pager-btn.is-off{color:var(--ink-42);background:var(--ws-cloud);cursor:default}
.ws-pager-btn.is-off:hover{border-color:var(--ws-line-2);background:var(--ws-cloud)}
.ws-pager-gap{font:400 12.5px/1 var(--body);color:var(--ink-42);padding:0 2px}
/* On a phone the numbers go and the two directions stay, which is what there is room for. */
@media (max-width:719px){
  .ws-pager-pages{display:none}
  .ws-pager-count{flex:1 0 100%}
}

/* ============================ auth and onboarding ============================ */
/* The signed-out screens and the first-sign-in wizard, brought onto the workspace atoms. The
   card shell (auth-card, auth-header, auth-body, auth-footer) stays in the shared stylesheet;
   what lives here is the field-with-reveal shape and the full-width button the narrow card
   needs, so a password box on the login page is the same object as one in the workspace. */
.ws-fld.pwf{position:relative;padding-right:46px}
.ws-fld.pwf .pwt{position:absolute;right:6px;top:50%;transform:translateY(-50%);width:32px;height:32px;
  display:flex;align-items:center;justify-content:center;border:0;background:transparent;
  color:var(--ink-62);cursor:pointer;border-radius:8px}
.ws-fld.pwf .pwt:hover{color:var(--ink)}
.ws-fld.pwf .pwt svg{width:18px;height:18px}
.ws-btn.wide{width:100%;justify-content:center}
.auth-header .ws-eyebrow{margin-bottom:8px}
.ws-authrow{display:flex;gap:10px;flex-wrap:wrap;justify-content:center}
/* A cautionary panel for the board decision surface: the brass-edged tone the voting page's
   warning box carries, available inside the workspace where that scoped rule cannot reach. */
.ws-warnbox{background:#F4ECD9;border:1px solid rgba(168,132,60,.4);border-left:4px solid var(--brass);
  border-radius:0 10px 10px 0;padding:13px 15px}
.ws-warnbox strong{color:#7A560F;display:block;margin-bottom:3px}
.ws-warnbox p{color:#8A6314;font:400 13px/1.55 var(--body)}
