@charset "UTF-8";
/* =====================================================================
   Pinlocus 1.0 — design system

   The product is a code that gets written on a parcel, read down a phone
   and keyed in by a stranger. So the code is the one loud thing on any
   screen, and everything around it reads as a clean administrative
   ledger: aligned columns, hairlines, no nested boxes.

   Two rules hold the whole thing together:
     RED   = identity and danger. The Pinlocus id, and actions that
             destroy, freeze or suspend. Nothing else, ever.
     BLUE  = every ordinary action.
   Red that also meant "save" would make the freeze button meaningless.

   Colours are sampled from the Pinlocus mark itself.
   No webfonts and no external requests: the host has an allowlist.
   ===================================================================== */

:root{
  /* Brand, vectorised from the original artwork (PINLOCUS ok.EPS).
     --red and --blue are the logo exactly. Pure red only reaches 4.0:1 on
     white, which carries large text but not small, so --red-ink is the
     darker shade used for buttons and anything set small. */
  --red:#FF0000;
  --red-ink:#D40000;
  --red-wash:#FFF0F0;
  --blue:#0079C1;
  --blue-ink:#00639F;
  --blue-wash:#EAF4FB;

  /* neutrals: cool paper, never warm cream */
  --ink:#16202A;
  --ink-2:#44535F;
  --muted:#6B7A88;
  --rule:#D8DEE4;
  --rule-soft:#E8ECF0;
  --paper:#FFFFFF;
  --stock:#F2F4F6;
  --stock-2:#E9EDF1;

  /* state: used sparingly, always with a word beside the colour */
  --ok:#0F7A52;      --ok-wash:#EAF6F0;
  --warn:#8A5A00;    --warn-wash:#FDF4E3;
  --err:#B3200F;     --err-wash:#FDEFEC;

  /* type scale */
  --t-xs:12px; --t-sm:13.5px; --t-base:15px; --t-md:17px;
  --t-lg:21px; --t-xl:27px; --t-2xl:34px;

  --sans:system-ui,-apple-system,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;
  /* reserved for codes only — never for small labels */
  --mono:ui-monospace,"SF Mono",SFMono-Regular,"Cascadia Mono","Roboto Mono",Consolas,monospace;

  /* radius by role, not one value everywhere */
  --r-field:6px; --r-card:10px; --r-pill:999px;
}

*,*::before,*::after{box-sizing:border-box}

html{-webkit-text-size-adjust:100%}

body{
  margin:0;
  font-family:var(--sans);
  font-size:var(--t-base);
  line-height:1.55;
  color:var(--ink);
  background:var(--stock);
  -webkit-font-smoothing:antialiased;
}

h1,h2,h3,h4{margin:0 0 .5em;line-height:1.2;letter-spacing:-.011em;font-weight:650}
h1{font-size:var(--t-2xl);letter-spacing:-.02em}
h2{font-size:var(--t-lg)}
h3{font-size:var(--t-md);font-weight:600}
p{margin:0 0 .9em}
p:last-child{margin-bottom:0}

a{color:var(--blue);text-decoration:none}
a:hover{text-decoration:underline;text-underline-offset:2px}

:focus-visible{outline:2px solid var(--blue);outline-offset:2px;border-radius:3px}

img{max-width:100%;height:auto}
/* The logo partial passes its intended height as --logo-px; a context
   that wants another size overrides the height below. */
.logo-img{display:block;width:auto;height:var(--logo-px,26px)}
.thumb{width:100%;aspect-ratio:4/3;object-fit:contain;background:var(--stock);border-radius:var(--r-field)}

/* ---------------------------------------------------------------- shell */
.container{max-width:1060px;margin:0 auto;padding:0 20px}
.container.narrow{max-width:560px}
.container.mid{max-width:820px}

header.top{background:var(--paper);border-bottom:1px solid var(--rule)}
.topbar{display:flex;align-items:center;gap:20px;padding-top:13px;padding-bottom:13px;flex-wrap:wrap}

.brand{display:flex;align-items:center;gap:9px;font-size:var(--t-md);font-weight:680;
  color:var(--ink);letter-spacing:-.015em}
.brand:hover{text-decoration:none}
.brand svg{display:block;flex:none}

nav.main{margin-left:auto;min-width:0;display:flex;gap:18px;align-items:center;flex-wrap:wrap}
nav.main a{color:var(--ink-2);font-size:var(--t-sm);font-weight:500}
nav.main a:hover{color:var(--ink)}
nav.main a.cta{background:var(--blue);color:#fff;padding:7px 15px;border-radius:var(--r-field);font-weight:600}
nav.main a.cta:hover{background:var(--blue-ink);text-decoration:none}

.langsw{font-size:var(--t-xs);color:var(--muted);letter-spacing:.02em}
.langsw a{color:var(--muted)}
.langsw a.on{color:var(--ink);font-weight:700}

main{padding:28px 0 64px;flex:1 0 auto}
/* A short page should still rest its footer on the bottom edge. */
body{min-height:100vh;display:flex;flex-direction:column}

footer.bottom{border-top:1px solid var(--rule);background:var(--paper);padding:20px 0;
  color:var(--muted);font-size:var(--t-sm)}
footer.bottom{flex:none}
footer.bottom .container{display:flex;gap:18px;flex-wrap:wrap;align-items:center}
footer.bottom a{color:var(--muted)}

/* ----------------------------------------------------------------- hero
   The lookup field is the hero. The product is "type a code, get the
   truth", so the code field is shown at the size the code deserves.
   The column is centred because the page's single job is the lookup. */
.hero{--logo-h:clamp(150px,46vw,260px);padding:44px 0 8px;max-width:680px;margin:0 auto}

/* The mark leads the page. It scales with the viewport so it stays large
   on a desktop without overwhelming a phone. */
.hero-logo{margin:0 0 20px}
/* The partial sets display:block inline, so the mark is centred with auto
   margins rather than text-align. */
.hero-logo img{height:var(--logo-h);margin-inline:auto}
.hero.compact .hero-logo{display:none}

/* Deliberately set below the wordmark inside the mark: the logo says who
   this is, the line underneath only says what it does. */
/* The tagline is an image of fixed proportions. Its width is written as
   the font size it should appear at, times the artwork's own ratio of
   width to font size (14.275), which keeps the two in step at every
   screen size. The wordmark's width is still the ceiling. */
.hero h1{margin:0 auto 24px;text-align:center;line-height:0;
  max-width:calc(var(--logo-h) * 0.938)}
.hero-tagline img{display:block;width:calc(clamp(9px,2.67vw,14px) * 14.2272);
  max-width:100%;height:auto;margin-inline:auto}

/* Once there is a result, the hero steps back so the answer leads. */
.hero.compact{padding:24px 0 4px}
.hero.compact h1{display:none}

.searchbox{display:flex;gap:0;align-items:stretch;border:2px solid var(--ink);
  border-radius:var(--r-field);background:var(--paper);overflow:hidden}
.searchbox:focus-within{border-color:var(--blue);box-shadow:0 0 0 3px var(--blue-wash)}
.searchbox input{
  flex:1;min-width:0;border:0;padding:15px 16px;background:transparent;
  font-family:var(--mono);font-size:var(--t-xl);font-weight:600;
  letter-spacing:.14em;text-transform:uppercase;color:var(--ink);
}
.searchbox input::placeholder{font-family:var(--sans);font-size:var(--t-md);
  letter-spacing:0;font-weight:400;color:var(--muted);text-transform:none}
.searchbox input:focus{outline:none}
.searchbox button{border:0;background:var(--blue);color:#fff;padding:0 26px;
  font-family:inherit;font-size:var(--t-base);font-weight:650;cursor:pointer}
.searchbox button:hover{background:var(--blue-ink)}

/* Scanning sits in the same box as typing, because they are the same task
   arrived at two ways. */
.searchbox-scan{display:flex;align-items:center;padding:0 14px;color:var(--muted);
  border-left:1px solid var(--rule-soft)}
.searchbox-scan:hover{color:var(--blue);background:var(--stock);text-decoration:none}
.searchbox-scan svg{display:block}

/* The character rule, printed as a legend. It is the reason a mistyped
   code still finds the right record, and it stops failed lookups. */
.legend{margin:11px 0 0;display:flex;flex-wrap:wrap;gap:4px 16px;align-items:baseline}
.legend .legend-note{font-size:var(--t-sm);color:var(--muted)}
.legend .pairs{display:flex;flex-wrap:wrap;gap:4px 12px;font-family:var(--mono);
  font-size:var(--t-sm);color:var(--ink-2);letter-spacing:.02em}
.legend .pairs b{font-weight:600;color:var(--ink)}

/* ----------------------------------------------------------------- card
   Hairline and surface, never a drop shadow. Shadows on every box is
   the look this design is trying not to have. */
.card{background:var(--paper);border:1px solid var(--rule);border-radius:var(--r-card);
  padding:22px;margin-bottom:18px}
.card > h2:first-child,.card > h3:first-child{margin-top:0}
.card h2{font-size:var(--t-md);font-weight:650;color:var(--ink)}
.card h3{margin:20px 0 8px;font-size:var(--t-base);font-weight:650;color:var(--ink)}

hr.sep{border:0;border-top:1px solid var(--rule-soft);margin:18px 0}

/* -------------------------------------------------------------- the id
   The one loud thing. Tabular, spaced for reading aloud, brand red. */
/* An id is read aloud and copied by eye, so it must stay on one line.
   It scales with the screen rather than wrapping. */
.big-id{font-family:var(--mono);font-size:clamp(18px,5.8vw,34px);font-weight:700;
  color:var(--red);letter-spacing:.08em;line-height:1.15;white-space:nowrap}
.big-id.center{text-align:center;display:block}
.mono{font-family:var(--mono);font-size:.94em;letter-spacing:.01em}

/* the three closing points: a rule each, so they read as one set */
.points > div{border-top:2px solid var(--ink);padding-top:12px}
.points h3{margin:0 0 6px;font-size:var(--t-base)}

/* ---------------------------------------------------------------- grid */
.grid{display:grid;gap:18px}
.grid.two{grid-template-columns:repeat(2,minmax(0,1fr))}
.grid.three{grid-template-columns:repeat(3,minmax(0,1fr))}
.grid.four{grid-template-columns:repeat(4,minmax(0,1fr))}
@media(max-width:860px){
  .grid.two,.grid.three,.grid.four{grid-template-columns:1fr}
}

/* --------------------------------------------------------------- forms */
label{display:block;font-size:var(--t-sm);font-weight:600;margin:14px 0 5px;color:var(--ink-2)}
input[type=text],input[type=email],input[type=password],input[type=number],
input[type=date],input[type=url],input[type=search],select,textarea{
  width:100%;padding:9px 11px;border:1px solid var(--rule);border-radius:var(--r-field);
  font-size:var(--t-base);font-family:inherit;background:var(--paper);color:var(--ink)}
textarea{min-height:112px;resize:vertical;line-height:1.5}
input:focus,select:focus,textarea:focus{outline:none;border-color:var(--blue);
  box-shadow:0 0 0 3px var(--blue-wash)}
input:disabled,select:disabled{background:var(--stock);color:var(--muted)}
.help{font-size:var(--t-xs);color:var(--muted);margin-top:4px;line-height:1.45}

.row{display:flex;gap:12px;flex-wrap:wrap;align-items:flex-end}
.row > div{flex:1;min-width:150px}
.inline{display:inline}

/* ------------------------------------------------------------- buttons */
.btn{display:inline-block;background:var(--blue);color:#fff;border:1px solid var(--blue);
  padding:9px 16px;border-radius:var(--r-field);font-size:var(--t-sm);font-weight:600;
  font-family:inherit;cursor:pointer;line-height:1.4;text-align:center}
.btn:hover{background:var(--blue-ink);border-color:var(--blue-ink);color:#fff;text-decoration:none}
.btn.ghost{background:var(--paper);color:var(--ink);border-color:var(--rule)}
.btn.ghost:hover{background:var(--stock);color:var(--ink);border-color:var(--muted)}
/* red is reserved: destroy, freeze, suspend, close an account */
.btn.red{background:var(--red-ink);border-color:var(--red-ink)}
.btn.red:hover{background:#B00000;border-color:#B00000}
.btn.sm{padding:5px 11px;font-size:var(--t-xs)}
/* for the dark header bar: present but not shouting */
.btn.quiet{background:transparent;border-color:rgba(255,255,255,.35);color:#fff}
.btn.quiet:hover{background:rgba(255,255,255,.12);border-color:rgba(255,255,255,.6);color:#fff}
.btn[disabled],.btn:disabled{opacity:.45;cursor:not-allowed}

/* ---------------------------------------------------------------- tabs */
.tabs{display:flex;gap:4px;border-bottom:1px solid var(--rule);margin-bottom:20px}
.tabs a{padding:9px 2px;margin-right:22px;font-size:var(--t-base);font-weight:600;
  color:var(--muted);border-bottom:2px solid transparent;margin-bottom:-1px}
.tabs a.on{color:var(--ink);border-bottom-color:var(--red)}
.tabs a:hover{color:var(--ink);text-decoration:none}

/* -------------------------------------------------------------- alerts
   An alert says what happened and what to do. Colour supports the
   words; it never carries the meaning alone. */
.alert{padding:11px 14px;border-radius:var(--r-field);margin-bottom:16px;
  font-size:var(--t-sm);border:1px solid;border-left-width:3px}
.alert.ok{background:var(--ok-wash);color:var(--ok);border-color:#BEE3D2;border-left-color:var(--ok)}
.alert.error{background:var(--err-wash);color:var(--err);border-color:#F5CCC4;border-left-color:var(--err)}
.alert.warn{background:var(--warn-wash);color:var(--warn);border-color:#F0DCB4;border-left-color:var(--warn)}
.alert ul{margin:6px 0 0;padding-left:18px}
.alert li+li{margin-top:3px}

/* -------------------------------------------------------------- tables
   A ledger: aligned columns and hairlines. Headings are sentence case
   and earn their weight from type, not from capitals. */
.table-wrap{overflow-x:auto;margin:0 -2px}
table{width:100%;border-collapse:collapse;font-size:var(--t-sm)}
th,td{text-align:left;padding:9px 12px;border-bottom:1px solid var(--rule-soft);
  vertical-align:top}
th{font-size:var(--t-xs);font-weight:650;color:var(--muted);
  white-space:nowrap;border-bottom:1px solid var(--rule)}
th:first-child,td:first-child{padding-left:2px}
tbody tr:hover td{background:#FBFCFD}
td .mono{color:var(--ink)}

/* ---------------------------------------------------------------- pill */
.pill{display:inline-block;padding:2px 9px;border-radius:var(--r-pill);
  font-size:var(--t-xs);font-weight:650;background:var(--stock-2);color:var(--ink-2);
  line-height:1.6;white-space:nowrap}
.pill.ok{background:var(--ok-wash);color:var(--ok)}
.pill.off{background:var(--stock-2);color:var(--muted)}
.pill.red{background:var(--red-wash);color:#A80000}
.pill.blue{background:var(--blue-wash);color:var(--blue-ink)}

/* ---------------------------------------------------------------- misc */
.muted{color:var(--muted)}
.small{font-size:var(--t-sm)}
.right{text-align:right}
.center{text-align:center}

.stat{background:var(--paper);border:1px solid var(--rule);border-radius:var(--r-card);padding:16px}
.stat .n{font-size:var(--t-xl);font-weight:700;color:var(--ink);line-height:1.1;
  font-variant-numeric:tabular-nums}
.stat .l{font-size:var(--t-xs);color:var(--muted);margin-top:3px}

/* a record row in the profile editor */
.record{border:1px solid var(--rule);border-radius:var(--r-field);padding:13px 14px;
  margin-bottom:9px;background:var(--paper)}
.record.active{border-color:var(--blue);background:var(--blue-wash)}
.record .head{display:flex;gap:10px;align-items:center;flex-wrap:wrap}
.record .val{font-weight:600;flex:1;min-width:140px;word-break:break-word}

.addr-lines{white-space:pre-line}
.map{width:100%;height:270px;border:1px solid var(--rule);border-radius:var(--r-field)}
#qrbox{display:flex;justify-content:center;padding:18px;background:var(--paper)}

/* resolved record: a label column and a value column, read as a manifest */
.field{display:grid;grid-template-columns:104px 1fr;gap:4px 16px;padding:11px 0;
  border-bottom:1px solid var(--rule-soft)}
.field:last-child{border-bottom:0}
.field > dt{font-size:var(--t-sm);color:var(--muted);font-weight:500}
.field > dd{margin:0;font-weight:500;display:flex;flex-wrap:wrap;
  align-items:baseline;gap:4px 8px}
.field > dd > .addr-lines{flex-basis:100%}
@media(max-width:520px){.field{grid-template-columns:1fr;gap:2px}}

/* ========================================================= back office */
body.bo{display:flex;flex-direction:column;min-height:100vh;background:var(--stock)}

.bo-top{display:flex;align-items:center;gap:16px;padding:0 18px;height:54px;
  background:var(--ink);color:#fff;position:sticky;top:0;z-index:40;flex-wrap:wrap}
.bo-brand{display:flex;align-items:center;gap:8px;font-weight:680;font-size:var(--t-base);
  color:#fff;letter-spacing:-.01em}
.bo-brand:hover{text-decoration:none;color:#fff}
.bo-burger{display:none;background:none;border:1px solid rgba(255,255,255,.3);
  color:#fff;border-radius:var(--r-field);font-size:16px;padding:3px 10px;cursor:pointer}

.bo-site{display:flex;align-items:center;gap:8px;padding-left:16px;
  border-left:1px solid rgba(255,255,255,.18)}
.bo-site select{padding:4px 8px;font-size:var(--t-sm);max-width:210px;
  background:rgba(255,255,255,.1);color:#fff;border-color:rgba(255,255,255,.25)}
.bo-site select option{color:var(--ink)}
.bo-sitename{font-weight:600;font-size:var(--t-sm);color:#fff}

.bo-user{margin-left:auto;display:flex;align-items:center;gap:12px;flex-wrap:wrap}
.bo-username{font-size:var(--t-sm);font-weight:600;color:#fff}
.bo-top .pill.blue{background:rgba(255,255,255,.16);color:#fff}
.bo-top .langsw,.bo-top .langsw a{color:rgba(255,255,255,.7)}
.bo-top .langsw a.on{color:#fff}

.bo-body{display:flex;flex:1;min-height:0;align-items:stretch}

.bo-nav{width:232px;flex:0 0 232px;background:var(--paper);border-right:1px solid var(--rule);
  overflow-y:auto;max-height:calc(100vh - 54px);position:sticky;top:54px;
  display:flex;flex-direction:column}

.bo-docs{border-bottom:1px solid var(--rule);padding:7px 0;background:var(--stock)}
.bo-docs a{display:block;padding:5px 18px;font-size:var(--t-xs);color:var(--muted)}
.bo-docs a:hover{color:var(--ink);text-decoration:none}
.bo-docs a.on{color:var(--ink);font-weight:650}

.bo-dash{display:block;padding:13px 18px;font-weight:650;color:var(--ink);
  font-size:var(--t-base);border-bottom:1px solid var(--rule)}
.bo-dash:hover{background:var(--stock);text-decoration:none;color:var(--ink)}
.bo-dash.on{color:var(--ink);box-shadow:inset 3px 0 0 var(--red);background:var(--stock)}
.bo-top{border-bottom:3px solid var(--red)}

.bo-groups{flex:1}
.bo-group + .bo-group{border-top:1px solid var(--rule-soft)}
.bo-ghead{display:flex;align-items:center;justify-content:space-between;width:100%;
  background:none;border:0;padding:11px 18px;font:inherit;font-size:var(--t-sm);
  font-weight:650;color:var(--ink-2);cursor:pointer;text-align:left}
.bo-ghead:hover{background:var(--stock);color:var(--ink)}
.bo-ghead .chev{transition:transform .15s ease;font-size:15px;color:var(--muted);line-height:1}
@media(prefers-reduced-motion:reduce){.bo-ghead .chev{transition:none}}
.bo-group.open .bo-ghead{color:var(--ink)}
.bo-group.open .bo-ghead .chev{transform:rotate(90deg)}
.bo-gitems{display:none;padding-bottom:5px}
.bo-group.open .bo-gitems{display:block}
.bo-gitems a{display:block;padding:7px 18px 7px 30px;font-size:var(--t-sm);color:var(--ink-2)}
.bo-gitems a:hover{background:var(--stock);color:var(--ink);text-decoration:none}
.bo-gitems a.on{color:var(--ink);font-weight:650;background:var(--stock);
  box-shadow:inset 3px 0 0 var(--red)}

.bo-credit{padding:14px 18px;border-top:1px solid var(--rule);background:var(--stock);
  color:var(--muted);font-size:var(--t-xs);line-height:1.5}
.bo-credit-title{font-size:var(--t-xs);font-weight:650;color:var(--ink-2);margin-bottom:3px}

.bo-main{flex:1;min-width:0;padding:24px;overflow-x:hidden}
.bo-main > .card:last-child{margin-bottom:0}

/* page heading inside the back office */
.bo-head{display:flex;align-items:flex-start;gap:14px;flex-wrap:wrap;margin-bottom:18px}
.bo-head h1{font-size:var(--t-xl);margin:0}
.bo-head .sub{color:var(--muted);font-size:var(--t-sm);margin:3px 0 0;max-width:62ch}
.bo-head .actions{margin-left:auto;display:flex;gap:8px;flex-wrap:wrap}

@media(max-width:860px){
  .bo-burger{display:block;order:-1}
  .bo-nav{position:fixed;left:0;top:54px;bottom:0;transform:translateX(-100%);
    transition:transform .18s ease;z-index:50;max-height:none;
    box-shadow:0 0 0 100vmax rgba(22,32,42,.4)}
  body.nav-open .bo-nav{transform:translateX(0)}
  .bo-user{gap:8px}
  .bo-site{padding-left:0;border-left:0;width:100%;order:4}
  .bo-main{padding:16px}
  .bo-top{height:auto;padding:10px 14px}
}
@media(prefers-reduced-motion:reduce){.bo-nav{transition:none}}

/* ------------------------------------------- authorization matrix grid */
.matrix th,.matrix td{text-align:center;padding:7px 8px}
.matrix th:first-child,.matrix td:first-child{text-align:left}
.matrix input[type=checkbox]{width:16px;height:16px;accent-color:var(--blue);cursor:pointer}
.matrix tr.module-head td{background:var(--stock-2);font-weight:650;color:var(--ink);
  font-size:var(--t-xs);text-align:left}
.matrix tbody tr:hover td{background:var(--blue-wash)}

/* --------------------------------------------------------------- print */
.label-sheet{background:#fff;border:1px solid var(--rule);border-radius:var(--r-card);
  padding:22px;max-width:420px;margin:22px auto}
/* The id runs along the foot of the label on one line, always. A code
   that wraps is read wrong, and on a parcel that means a wrong delivery. */
.label-sheet .lid{display:flex;align-items:baseline;gap:8px;white-space:nowrap;
  margin-top:14px;padding-top:12px;border-top:1px solid var(--rule)}
.label-sheet .lid-cap{font-size:var(--t-xs);font-weight:600;color:var(--muted);
  text-transform:uppercase;letter-spacing:.09em}
/* flex:none so the box is the text's own width: a shrunk box would let
   the glyphs spill past it unnoticed. */
.label-sheet .lid-no{flex:none;font-family:var(--mono);font-size:17px;font-weight:700;
  color:var(--red);letter-spacing:.06em}

@media print{
  .noprint{display:none!important}
  body{background:#fff}
  header.top,footer.bottom,.bo-top,.bo-nav{display:none!important}
  .card,.label-sheet{border:1px solid #999;break-inside:avoid}
  .label-sheet{border-style:dashed;margin:0;max-width:none}
  a[href]::after{content:""}
}

/* ------------------------------------------------------------ scanner */
.scan-viewport{position:relative;width:100%;aspect-ratio:1;max-width:420px;margin:0 auto;
  background:#000;border-radius:var(--r-card);overflow:hidden}
.scan-viewport video{width:100%;height:100%;object-fit:cover;display:block}
/* A target the code can be held inside, drawn as four corners rather than
   a full box so it never hides what is being aimed at. */
.scan-frame{position:absolute;inset:14%;border-radius:8px;
  background:
    linear-gradient(var(--red),var(--red)) left top/26px 3px no-repeat,
    linear-gradient(var(--red),var(--red)) left top/3px 26px no-repeat,
    linear-gradient(var(--red),var(--red)) right top/26px 3px no-repeat,
    linear-gradient(var(--red),var(--red)) right top/3px 26px no-repeat,
    linear-gradient(var(--red),var(--red)) left bottom/26px 3px no-repeat,
    linear-gradient(var(--red),var(--red)) left bottom/3px 26px no-repeat,
    linear-gradient(var(--red),var(--red)) right bottom/26px 3px no-repeat,
    linear-gradient(var(--red),var(--red)) right bottom/3px 26px no-repeat}

/* ------------------------------------------------------ narrow header
   Below this width the nav cannot sit beside the wordmark without
   wrapping into ragged rows, so it is given a row of its own.
*/
@media (max-width:640px){
  .topbar{gap:8px 14px;padding-top:11px;padding-bottom:11px}
  nav.main{margin-left:0;width:100%;gap:8px 16px}
  nav.main .langsw{margin-left:auto}
}

/* --------------------------------------------------------- map picker
   A dialog rather than an inline map: the address form is already long,
   and a map only matters while a point is being chosen.
*/
.mapdlg-back{position:fixed;inset:0;z-index:70;background:rgba(17,24,28,.55);
  display:flex;align-items:center;justify-content:center;padding:16px}
.mapdlg{background:var(--paper);border-radius:var(--r-card);width:min(760px,100%);
  max-height:min(760px,92vh);display:flex;flex-direction:column;overflow:hidden;
  box-shadow:0 18px 50px rgba(17,24,28,.28)}
.mapdlg-head{display:flex;align-items:center;justify-content:space-between;gap:12px;
  padding:14px 16px;border-bottom:1px solid var(--rule)}
.mapdlg-search{display:flex;gap:8px;padding:12px 16px 0}
.mapdlg-search input{flex:1;min-width:0}
.mapdlg-hits{padding:0 16px;max-height:148px;overflow:auto}
.mapdlg-hit{display:block;width:100%;text-align:left;background:none;border:0;
  border-bottom:1px solid var(--rule);padding:9px 2px;font:inherit;font-size:var(--t-sm);
  color:var(--ink-2);cursor:pointer}
.mapdlg-hit:hover{color:var(--ink);background:var(--stock)}
.mapdlg-note{padding:9px 2px;font-size:var(--t-sm);color:var(--muted)}
.mapdlg-map{flex:1;min-height:300px;margin:12px 16px 0;border:1px solid var(--rule);
  border-radius:var(--r-field);overflow:hidden}
.mapdlg-foot{display:flex;align-items:center;justify-content:space-between;gap:12px;
  flex-wrap:wrap;padding:12px 16px}
.mapdlg-acts{display:flex;gap:8px}
.mapdlg-read{color:var(--muted)}
@media(max-width:560px){
  .mapdlg-back{padding:0}
  .mapdlg{width:100%;max-height:100%;height:100%;border-radius:0}
}

/* A row of buttons that belongs to the field above it. */
.btn-row{display:flex;gap:8px;flex-wrap:wrap;margin:0 0 10px}

/* -------------------------------------------------------- share dialog
   The QR is rendered with the page, so opening this costs no request.
*/
.sharedlg-back{position:fixed;inset:0;z-index:70;background:rgba(17,24,28,.55);
  display:flex;align-items:center;justify-content:center;padding:16px}
.sharedlg-back[hidden]{display:none}
.sharedlg{background:var(--paper);border-radius:var(--r-card);width:min(380px,100%);
  overflow:hidden;box-shadow:0 18px 50px rgba(17,24,28,.28)}
.sharedlg-head{display:flex;align-items:center;justify-content:space-between;gap:12px;
  padding:14px 16px;border-bottom:1px solid var(--rule)}
.sharedlg-body{padding:18px 16px;text-align:center}
.sharedlg-qr svg{display:block;margin:0 auto}
.sharedlg-id{margin-top:12px;font-family:var(--mono);font-size:var(--t-lg);font-weight:700;
  color:var(--red-ink);letter-spacing:.06em}
.sharedlg-link{margin-top:10px;padding:8px 10px;background:var(--stock);
  border-radius:var(--r-field);word-break:break-all;color:var(--muted)}
.sharedlg-acts{display:flex;gap:8px;justify-content:center;margin-top:14px;flex-wrap:wrap}

/* ------------------------------------------------------- id card
   The owner's own landing card: the mark, then the id, centred, at a
   size that holds one line on a phone.
*/
.idcard{text-align:center}
.idcard-mark{margin-bottom:14px}
.idcard-mark img{height:clamp(96px,26vw,200px);margin-inline:auto}
.idcard-acts{display:flex;gap:8px;flex-wrap:wrap;justify-content:center;margin-top:16px}

/* A scanned code lands here, so the id itself leads: centred, one line. */
.reshead{text-align:center;margin-bottom:6px}
.reshead .big-id{margin-bottom:8px}
.reshead-acts{display:flex;gap:8px;flex-wrap:wrap;justify-content:center;margin-top:12px}

/* The editor for a saved record, folded away until it is wanted. */
.rec-edit{border-top:1px solid var(--rule);margin-top:10px;padding-top:8px}
.rec-edit>summary{cursor:pointer;color:var(--blue);font-weight:600;font-size:var(--t-sm)}
.rec-edit[open]>summary{margin-bottom:4px}

/* A labelled rule between two ways of signing in. */
.or-rule{display:flex;align-items:center;gap:12px;margin:18px 0;color:var(--muted);
  font-size:var(--t-xs);text-transform:uppercase;letter-spacing:.08em}
.or-rule::before,.or-rule::after{content:"";flex:1;height:1px;background:var(--rule)}
.gbtn{display:inline-flex;align-items:center;gap:10px;width:100%;justify-content:center}

/* ------------------------------------------------- record actions
   A scanned record is usually acted on at once: ring the number, write
   to the address, drive to the place. The action sits beside its value
   rather than in a row at the bottom, so there is never a doubt about
   which number is being called.
*/
.act-row{display:flex;align-items:flex-start;gap:10px;flex-wrap:wrap;justify-content:space-between}
.act-row>span{min-width:0}
.act-line{display:flex;gap:8px;flex-wrap:wrap;margin:10px 0 0}
.act-btn{display:inline-flex;align-items:center;gap:6px;white-space:nowrap}
.act-btn svg{width:15px;height:15px;fill:currentColor;flex:none}

/* A row of tick boxes that reads as one field. */
.checks{display:flex;gap:14px;flex-wrap:wrap;margin:0;padding:9px 0 0}
.check{display:inline-flex;align-items:center;gap:6px;margin:0;font-weight:500;
  font-size:var(--t-sm);cursor:pointer}
.check input{width:auto;margin:0}

/* A block of code or a response body: readable, scrollable, never wrapped
   in a way that changes what it says. */
.codebox{margin:0;padding:12px 14px;background:var(--stock);border-radius:var(--r-field);
  font-family:var(--mono);font-size:var(--t-sm);line-height:1.5;color:var(--ink);
  overflow:auto;max-height:420px;white-space:pre;-webkit-overflow-scrolling:touch}

/* Pass, fail and skipped marks on the API test. */
.at-mark{font-weight:700;font-size:16px;text-align:center}
.at-pass{color:#0b7a4b}
.at-fail{color:var(--red-ink)}
.at-skip{color:var(--muted)}
