/* ==========================================================================
   Second Lens Hiring Ledger
   Built to Second Lens Style Guide V1.1. Section numbers below refer to it.

   One stylesheet, no inline style anywhere in the product, which is what lets
   netlify.toml carry a Content Security Policy with no 'unsafe-inline' and no
   hashes. Runtime values are written through a stylesheet main.mjs constructs,
   never through a style attribute.

   Fonts: Poppins and Inter are named first and system-ui is the fallback, which
   section 6 states is acceptable. Nothing is fetched from a CDN, per section 19.
   ========================================================================== */

:root{
  /* surfaces */
  --bg:#F3F4F7; --surf:#FFFFFF; --rail:#FAFBFC;
  /* text */
  --ink:#0D1B2A; --mid:#5C6472; --soft:#8A92A1;
  /* lines */
  --line:#E1E4EA; --line2:#EDEFF3;
  /* action, the only blue */
  --act:#0B5FBF; --act-h:#094D9B; --act-t:#E8F1FB;
  /* status signals */
  --red:#C4314B; --red-t:#FBEBEE; --amb:#B0770B; --amb-t:#FCF4E3;
  /* Measured deviation, recorded rather than hidden. Section 11 pairs each status
     colour with its own tint as a chip. Measured, five of the six pairs clear 4.5:1
     (red 4.69, green 4.66, grey 5.32, action 5.41, violet 6.07) and amber does not,
     at 3.50. So amber keeps --amb as a mark and takes a darkened variant as text on
     its tint, at 5.26:1. The mark colour is unchanged, so nothing else moves. */
  --amb-on-tint:#8A5D08;
  --grn:#107C41; --grn-t:#E7F4EC; --gry:#98A0AE; --gry-t:#F0F2F5;
  --vio:#5B4B9E; --vio-t:#EEEBF7;
  /* dark navigation surface */
  --nav:#0D1B2A; --nav-fg:rgba(255,255,255,.86); --nav-dim:rgba(255,255,255,.58);
  --nav-accent:#E63946;
  --nav-red:#F0788C; --nav-amb:#E8A33D; --nav-grn:#57C98A; --nav-gry:#9AA3B0;
  /* elevation */
  --sh:0 1px 2px rgba(13,27,42,.06), 0 1px 3px rgba(13,27,42,.10);
  --sh2:0 2px 4px rgba(13,27,42,.06), 0 8px 16px rgba(13,27,42,.12);
  --sh3:0 4px 8px rgba(13,27,42,.07), 0 16px 32px rgba(13,27,42,.16);
  /* corners */
  --r-s:8px; --r-m:12px; --r-l:16px; --r-full:999px;
  /* type */
  --disp:'Poppins',system-ui,-apple-system,'Segoe UI',sans-serif;
  --ui:'Inter',system-ui,-apple-system,'Segoe UI',Roboto,sans-serif;
  --mono:ui-monospace,'SFMono-Regular',Menlo,Consolas,'Liberation Mono',monospace;

  /* type scale, section 6. Seven steps. Use a step, never an arbitrary value. */
  --t-xs:11px; --t-s:12.5px; --t-b:13.5px; --t-m:15px; --t-l:19px; --t-xl:26px; --t-2xl:40px;

  /* spacing, section 7. 4px rhythm. */
  --sp-1:4px; --sp-2:8px; --sp-3:12px; --sp-4:16px; --sp-5:24px; --sp-6:32px; --sp-7:48px;

  /* motion, section 15 */
  --m-state:.14s; --m-lift:.16s; --m-panel:.26s;
  --ease-panel:cubic-bezier(.22,1,.36,1);
  /* Narrative motion. Longer than the state durations on purpose: these are the four
     moments where something is being explained rather than a control changing state. */
  --m-tell:.6s; --m-scan:1.6s;

  /* product identity, section 2. Added per the rules for adding a product:
     rule colour clears 4.5:1 on white at 5.39, blade clears 3.2:1 on navy at 3.47. */
  --prod:#0E7A47; --prod-blade:#1A7F4D; --prod-t:#E6F3EC;
}
*{box-sizing:border-box}

/* Any author rule setting display beats the user agent's [hidden]{display:none},
   which quietly leaves a hidden element on the page still taking pointer events.
   Found by measurement: the modal backdrop was covering the whole interface while
   invisible, so nothing behind it could be clicked. */
[hidden]{display:none!important}

/* Section 15. The CSS backstop, so nothing animates even if the script check fails. */
@media (prefers-reduced-motion:reduce){
  *{animation:none!important;transition:none!important;scroll-behavior:auto!important}
}
/* The visible toggle, which section 15 also requires. */
:root[data-motion="off"] *{animation:none!important;transition:none!important}

/* Text size adjustment is set on the root, not on the body. Safari's automatic text
   inflation keys off the block container it is laying out, so declaring it on the body
   alone leaves anything outside the normal flow to be inflated anyway, which is how a
   page ends up with a 13px label rendering at 26px next to a 26px heading. 100% stops
   the automatic inflation. It does not stop the reader zooming, which 1.4.4 requires
   and which is a different mechanism. */
html{
  scroll-behavior:smooth;
  -webkit-text-size-adjust:100%;
  text-size-adjust:100%;
}
body{
  margin:0;background:var(--bg);color:var(--ink);
  font:400 var(--t-b)/1.55 var(--ui);
}
h1,h2,h3{font-family:var(--disp);line-height:1.25;margin:0}
h1{font-size:var(--t-xl);font-weight:600}
h2{font-size:var(--t-l);font-weight:600}
h3{font-size:var(--t-m);font-weight:600}
p{margin:0}
ul,ol{margin:0;padding:0;list-style:none}

.defs{position:absolute;width:0;height:0;overflow:hidden}
.mono{font-family:var(--mono);font-size:var(--t-s);letter-spacing:-.01em}

/* Section 13. Load bearing: an SVG with a viewBox and no dimensions fills its parent. */
svg{width:1.05em;height:1.05em;flex:none}
.i{display:inline-flex;align-items:center;justify-content:center;flex:none}
.i svg{width:1.05em;height:1.05em}
.i-lg{font-size:32px}

/* Section 17. Visible focus on everything interactive. */
:where(a,button,input,select,textarea,[tabindex]):focus-visible{
  outline:2px solid var(--act);outline-offset:2px;border-radius:var(--r-s)
}
.bar :where(a,button):focus-visible{outline:2px solid #fff}

.skip{
  position:absolute;left:var(--sp-3);top:-56px;z-index:60;
  background:var(--surf);color:var(--act);border:1px solid var(--act);
  padding:var(--sp-2) var(--sp-4);border-radius:var(--r-s);font-weight:600;
  text-decoration:none;box-shadow:var(--sh2);transition:top var(--m-state)
}
.skip:focus{top:var(--sp-3)}

/* ==========================================================================
   Application bar. Section 3, product mark at 28px, top left.
   ========================================================================== */
.bar{
  position:sticky;top:0;z-index:40;display:flex;align-items:center;gap:var(--sp-5);
  padding:var(--sp-3) var(--sp-5);background:var(--nav);color:var(--nav-fg);
  border-bottom:1px solid rgba(255,255,255,.08);flex-wrap:wrap
}
.bar-brand{display:flex;align-items:center;gap:var(--sp-3);text-decoration:none;color:inherit;min-height:28px}
.bar-brand img{width:28px;height:28px;border-radius:6px}
.bar-names{display:flex;flex-direction:column;line-height:1.15}
.bar-parent{font-size:9.5px;font-weight:700;letter-spacing:.06em;color:var(--nav-dim)}
.bar-product{font-family:var(--disp);font-size:var(--t-m);font-weight:600;color:#fff}
.bar-nav{display:flex;gap:var(--sp-1);flex:1 1 auto;flex-wrap:wrap}
.navlink{
  background:transparent;border:none;color:var(--nav-dim);cursor:pointer;
  font:600 var(--t-b) var(--ui);padding:var(--sp-2) var(--sp-3);border-radius:var(--r-s);
  min-height:32px;transition:background var(--m-state),color var(--m-state)
}
.navlink .i{display:inline-flex}
/* The short label exists only for the bottom tab bar. Exactly one of the two is
   displayed at any width, so a screen reader never meets both. */
.navlink-s{display:none}
/* The menu tab exists only where the controls have nowhere else to live. On a pointer
   that hovers they sit in the bar itself, so it is not shown and not in the tab order. */
.navlink-menu{display:none}
.navlink:hover{background:rgba(255,255,255,.08);color:#fff}
.navlink:active{background:rgba(255,255,255,.14)}
.navlink[aria-current="page"]{background:rgba(255,255,255,.12);color:#fff}
.bar-tools{display:flex;align-items:center;gap:var(--sp-3)}
.ghost-nav{background:rgba(255,255,255,.08);border-color:rgba(255,255,255,.18);color:var(--nav-fg);box-shadow:none}
.ghost-nav:hover{background:rgba(255,255,255,.16);border-color:rgba(255,255,255,.3)}
.ver{
  font-family:var(--mono);font-size:var(--t-xs);color:var(--nav-dim);
  background:rgba(255,255,255,.08);padding:3px var(--sp-2);border-radius:var(--r-full)
}

/* ==========================================================================
   Layout
   ========================================================================== */
main{display:block}
main:focus{outline:none}
.view{max-width:1080px;margin:0 auto;padding:var(--sp-6) var(--sp-5) var(--sp-7)}
.view-wide{max-width:1400px}
.page-h{margin-bottom:var(--sp-2)}
.page-lede{color:var(--mid);font-size:var(--t-m);max-width:64ch;margin-bottom:var(--sp-5)}

/* Section 11 */
.card{background:var(--surf);border:1px solid var(--line);border-radius:var(--r-m);box-shadow:var(--sh2)}
.card-h{font-size:var(--t-m);display:flex;align-items:center;gap:var(--sp-2)}

/* ==========================================================================
   Buttons, section 10. Four tiers, each with a press state.
   ========================================================================== */
.btn{
  background:var(--act);color:#fff;border:1px solid var(--act);border-radius:var(--r-s);
  padding:7px 13px;font:600 13px var(--ui);cursor:pointer;display:inline-flex;align-items:center;gap:6px;
  box-shadow:var(--sh2);transition:box-shadow var(--m-state),transform var(--m-lift),background var(--m-state);
  min-height:32px
}
.btn:hover{background:var(--act-h);border-color:var(--act-h);box-shadow:var(--sh3);transform:translateY(-1px)}
.btn:active{background:var(--act-h);box-shadow:var(--sh);transform:translateY(1px)}
/* An inactive control is outside WCAG 1.4.3, but a solid grey plate with white text
   measured 2.63:1 and was simply hard to read. A light surface with --mid text reads
   as unmistakably inactive and clears 5.32:1 anyway. */
.btn:disabled{background:var(--gry-t);border-color:var(--line);color:var(--mid);
  cursor:not-allowed;box-shadow:none;transform:none}
.btn:disabled .i{color:var(--soft)}
.btn-lg{padding:11px 20px;font-size:var(--t-m);min-height:44px}
.btn-block{width:100%;justify-content:center}

.ghost{
  background:var(--surf);border:1px solid var(--line);border-radius:var(--r-s);
  padding:6px 11px;font:500 13px var(--ui);cursor:pointer;display:inline-flex;align-items:center;gap:6px;
  box-shadow:var(--sh);transition:box-shadow var(--m-state),transform var(--m-lift),background var(--m-state);
  color:var(--ink);min-height:32px
}
.ghost:hover{background:var(--gry-t);border-color:var(--soft);box-shadow:var(--sh2)}
.ghost:active{background:var(--gry-t);box-shadow:none;transform:translateY(1px)}
.ghost-lg{padding:10px 18px;font-size:var(--t-m);min-height:44px}
.ghost-block{width:100%;justify-content:center}
.ghost-s{padding:4px 9px;font-size:var(--t-s);min-height:26px}

.tile{
  background:var(--surf);border:1px solid var(--line);border-radius:var(--r-m);
  box-shadow:var(--sh2);cursor:pointer;text-align:left;transition:transform var(--m-lift),box-shadow var(--m-lift)
}
.tile:hover{transform:translateY(-3px);box-shadow:var(--sh3)}
.tile:active{transform:translateY(-1px);box-shadow:var(--sh2)}

/* Tier 4, rows in a list. No resting shadow. A list has to stay a list. */
.row{background:var(--surf);border:none;cursor:pointer;text-align:left;transition:background var(--m-state),box-shadow var(--m-state)}
.row:hover{background:#F7F9FC;box-shadow:var(--sh)}
.row:active{box-shadow:none}

.x{
  background:var(--gry-t);border:none;font-size:19px;color:var(--mid);cursor:pointer;
  width:28px;height:28px;padding:0;border-radius:var(--r-full);box-shadow:var(--sh);
  display:inline-flex;align-items:center;justify-content:center;
  transition:box-shadow var(--m-state),transform var(--m-lift),background var(--m-state),color var(--m-state)
}
.x:hover{background:var(--line);color:var(--ink);box-shadow:var(--sh2)}
.x:active{box-shadow:none;transform:translateY(1px)}

.lnk{color:var(--act);text-decoration:underline;text-underline-offset:2px}
.lnkbtn{background:none;border:none;color:var(--act);font:inherit;cursor:pointer;padding:2px 0;text-decoration:underline;text-underline-offset:2px;min-height:24px}
.lnkbtn:hover{color:var(--act-h)}

/* Segmented control, section 10. Unselected segments need a surface. */
.seg{display:inline-flex;background:var(--gry-t);border-radius:var(--r-s);padding:3px;gap:2px;max-width:100%;overflow-x:auto}
.seg button{
  background:rgba(255,255,255,.55);border:none;padding:6px 14px;border-radius:var(--r-s);
  font:600 13px var(--ui);color:var(--mid);cursor:pointer;white-space:nowrap;min-height:30px;
  transition:background var(--m-state),color var(--m-state),box-shadow var(--m-state)
}
.seg button:hover{background:rgba(255,255,255,.85);color:var(--ink)}
.seg button.on{background:var(--surf);color:var(--act);box-shadow:var(--sh)}
.seg-s button{padding:4px 10px;font-size:var(--t-s);min-height:26px}

/* Chips, section 11. Tint background, matching saturated foreground. */
/* nowrap keeps a chip on one line, which is right until the line is wider than the
   screen. max-width plus a wrap at the narrowest widths lets a long citation chip fold
   instead of pushing the page sideways. */
.chip{display:inline-flex;align-items:center;gap:5px;font-size:11.5px;font-weight:600;padding:2px 8px;border-radius:var(--r-s);white-space:nowrap;max-width:100%}
@media (max-width:400px){
  .chip{white-space:normal;text-align:left}
}
.chip svg{width:11px;height:11px}
.chip-red{background:var(--red-t);color:var(--red)}
.chip-amb{background:var(--amb-t);color:var(--amb-on-tint)}
.chip-grn{background:var(--grn-t);color:var(--grn)}
.chip-gry{background:var(--gry-t);color:var(--mid)}
.chip-act{background:var(--act-t);color:var(--act)}
.chip-vio{background:var(--vio-t);color:var(--vio)}
.count-pill{background:var(--gry-t);color:var(--mid);font-size:var(--t-xs);font-weight:600;padding:2px 8px;border-radius:var(--r-full);font-family:var(--ui)}

/* Forms, section 12 */
.f select,.f input[type=text],.f input[type=file],.f textarea{
  width:100%;border:1px solid var(--line);border-radius:var(--r-s);
  padding:8px 10px;font:inherit;font-size:13px;background:var(--surf);color:var(--ink)
}
.f select:focus,.f input:focus,.f textarea:focus{outline:2px solid var(--act);outline-offset:-1px;border-color:var(--act)}
/* Scoped to a class rather than the bare element. A bare `label` selector here reaches
   every label in the form, including ones that are switches or buttons, and it wins
   because it comes later in the sheet. That collapsed the three role switches into
   uppercase text with the knob sitting on top of it, and it had already broken the file
   button once. A class cannot do that. */
.f label.lbl{display:block;font:700 11px var(--ui);letter-spacing:.05em;color:var(--mid);
  text-transform:uppercase;margin-bottom:5px}
.f label.lbl .tag{margin-left:6px}
.f textarea{min-height:200px;resize:vertical;line-height:1.6;font-family:var(--mono);font-size:var(--t-s)}
.hint{color:var(--mid);font-size:var(--t-s);margin:var(--sp-1) 0 var(--sp-4)}
.hint-tight{margin-bottom:var(--sp-2)}

/* ==========================================================================
   Front door
   ========================================================================== */
.hero{
  display:grid;grid-template-columns:minmax(0,1.15fr) minmax(0,1fr);gap:var(--sp-7);
  align-items:center;padding:var(--sp-6) 0 var(--sp-7)
}
.eyebrow{font-size:var(--t-xs);font-weight:700;letter-spacing:.06em;color:var(--prod);text-transform:uppercase;margin-bottom:var(--sp-2)}
.hero h1{font-size:var(--t-2xl);letter-spacing:-.02em;margin-bottom:var(--sp-4)}
.lede{font-size:var(--t-m);color:var(--ink);max-width:52ch;margin-bottom:var(--sp-4);font-weight:500}
.pitch{color:var(--mid);max-width:56ch;margin-bottom:var(--sp-5)}
.hero-actions{display:flex;gap:var(--sp-3);flex-wrap:wrap;margin-bottom:var(--sp-4)}
.hero-note{font-size:var(--t-s);color:var(--mid)}

/* Hero illustration. A document being read and two flags rising out of it.
   Decorative, aria-hidden, and it stops entirely when motion is off. */
.hero-art{position:relative;min-height:340px}
.art-stack{position:relative;height:100%;display:grid;place-items:center}
.art-doc{
  position:relative;width:min(300px,86%);background:var(--surf);border:1px solid var(--line);
  border-radius:var(--r-m);box-shadow:var(--sh3);padding:var(--sp-5) var(--sp-4);
  display:flex;flex-direction:column;gap:var(--sp-3);overflow:hidden;
  transform:rotate(-2deg)
}
.art-line{height:8px;border-radius:3px;background:var(--line2);display:block}
.art-line.w40{width:40%}.art-line.w50{width:50%}.art-line.w60{width:60%}
.art-line.w70{width:70%}.art-line.w75{width:75%}.art-line.w85{width:85%}.art-line.w90{width:90%}
.art-hit{background:var(--red-t);box-shadow:inset 0 0 0 1px var(--red);animation:hitpulse 3.2s var(--m-tell) infinite}
.art-hit2{background:var(--amb-t);box-shadow:inset 0 0 0 1px var(--amb);animation:hitpulse 3.2s 1.4s infinite}
@keyframes hitpulse{0%,72%,100%{opacity:.55}82%{opacity:1}}
.art-scan{
  position:absolute;left:0;right:0;height:64px;top:-64px;
  background:linear-gradient(180deg,transparent,rgba(14,122,71,.16),transparent);
  animation:artscan 4.4s ease-in-out infinite
}
@keyframes artscan{0%{top:-64px}55%,100%{top:110%}}
.art-card{
  position:absolute;background:var(--surf);border:1px solid var(--line);border-radius:var(--r-m);
  box-shadow:var(--sh3);padding:var(--sp-3);width:210px;display:flex;flex-direction:column;gap:6px
}
.art-card-1{top:12%;right:-6%;animation:float1 6s ease-in-out infinite}
.art-card-2{bottom:10%;left:-8%;animation:float2 7s ease-in-out infinite}
@keyframes float1{0%,100%{transform:translateY(0)}50%{transform:translateY(-10px)}}
@keyframes float2{0%,100%{transform:translateY(0)}50%{transform:translateY(8px)}}
.art-sev{width:34px;height:5px;border-radius:2px;display:block}
.art-sev-high{background:var(--red)}
.art-sev-med{background:var(--amb)}
.art-cardline{height:7px;border-radius:3px;background:var(--line2);display:block}
.art-cardline.w55{width:55%}.art-cardline.w70{width:70%}.art-cardline.w80{width:80%}
.art-cite{font-family:var(--mono);font-size:10px;color:var(--prod);font-weight:600}

/* Reveals. Scroll driven where supported, a simple entrance where not. */
.reveal{animation:rise var(--m-tell) var(--ease-panel) backwards}
.reveal[data-reveal="0"]{animation-delay:.02s}
.reveal[data-reveal="1"]{animation-delay:.08s}
.reveal[data-reveal="2"]{animation-delay:.16s}
.reveal[data-reveal="3"]{animation-delay:.24s}
.reveal[data-reveal="4"]{animation-delay:.32s}
.reveal[data-reveal="5"]{animation-delay:.4s}
@keyframes rise{from{opacity:0;transform:translateY(14px)}to{opacity:1;transform:none}}

@supports (animation-timeline:view()){
  .reveal-up{animation:rise var(--m-tell) var(--ease-panel) both;animation-timeline:view();animation-range:entry 5% cover 26%}
}

.band{padding:var(--sp-7) 0;border-top:1px solid var(--line)}
.band-h{margin-bottom:var(--sp-5)}
.two{display:grid;grid-template-columns:1fr 1fr;gap:var(--sp-5)}

.claims{display:grid;grid-template-columns:repeat(3,1fr);gap:var(--sp-5);counter-reset:c}
.claim{padding:var(--sp-5);position:relative;overflow:hidden}
.claim-n{font-family:var(--mono);font-size:var(--t-xs);font-weight:700;color:var(--prod);letter-spacing:.08em}
.claim h3{margin:var(--sp-2) 0 var(--sp-2)}
.claim p{color:var(--mid);font-size:var(--t-b)}
.claim::after{content:"";position:absolute;inset:auto 0 0 0;height:3px;background:var(--prod);transform:scaleX(0);transform-origin:left;transition:transform var(--m-panel) var(--ease-panel)}
.claim:hover::after{transform:scaleX(1)}

/* Section 5. Never a pale tint as a card background. Where a domain needs presence,
   the full colour is used as a block with a white foreground. */
.panel{overflow:hidden;padding:0}
.panel-h{display:flex;align-items:center;gap:var(--sp-2);padding:var(--sp-3) var(--sp-4);color:#fff;font-size:var(--t-m)}
.panel-h-is{background:var(--prod)}
.panel-h-isnt{background:#4A5262}
.panel ul{padding:var(--sp-4);display:flex;flex-direction:column;gap:var(--sp-3)}
.panel li{position:relative;padding-left:26px;color:var(--mid)}
.ticks li::before,.crosses li::before{
  position:absolute;left:0;top:1px;width:18px;height:18px;border-radius:var(--r-full);
  display:grid;place-items:center;font-size:11px;font-weight:700
}
.ticks li::before{content:"\2713";background:var(--grn-t);color:var(--grn)}
.crosses li::before{content:"\2715";background:var(--red-t);color:var(--red)}

.caps{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(258px,100%),1fr));gap:var(--sp-4)}
.cap{padding:var(--sp-5);transition:transform var(--m-lift),box-shadow var(--m-lift)}
.cap:hover{transform:translateY(-3px);box-shadow:var(--sh3)}
.cap-plate{
  width:38px;height:38px;border-radius:var(--r-s);background:var(--prod);color:#fff;
  display:grid;place-items:center;margin-bottom:var(--sp-3);font-size:19px
}
.cap h3{margin-bottom:var(--sp-2)}
.cap p{color:var(--mid);font-size:var(--t-s)}

.steps{display:grid;grid-template-columns:repeat(4,1fr);gap:var(--sp-4);counter-reset:s}
.step{display:flex;gap:var(--sp-3);align-items:flex-start;padding:var(--sp-4);background:var(--surf);border:1px solid var(--line);border-radius:var(--r-m);box-shadow:var(--sh2)}
.step-n{
  width:26px;height:26px;flex:none;border-radius:var(--r-full);background:var(--prod);color:#fff;
  display:grid;place-items:center;font-weight:700;font-size:var(--t-s)
}
.step h3{font-size:var(--t-b);margin-bottom:2px}
.step p{color:var(--mid);font-size:var(--t-s)}

.honest{padding:var(--sp-5)}
.honest dt{font-weight:600;color:var(--ink);margin-top:var(--sp-4);font-size:var(--t-m);font-family:var(--disp)}
.honest dt:first-child{margin-top:0}
.honest dd{margin:var(--sp-2) 0 0;color:var(--mid);max-width:86ch}

/* What a copy does not come with. Two columns on a wide screen, one on a narrow one,
   with the icon on its own so the heading stays on the text column. */
.copy-list{display:grid;grid-template-columns:1fr 1fr;gap:var(--sp-4);margin-top:var(--sp-5)}
.copy-item{display:grid;grid-template-columns:auto 1fr;gap:var(--sp-4);padding:var(--sp-5);align-items:start}
.copy-i{color:var(--prod);font-size:22px;margin-top:2px}
.copy-item h3{margin-bottom:var(--sp-2)}
.copy-item p{color:var(--mid);font-size:var(--t-b)}
.copy-honest{
  margin-top:var(--sp-4);padding:var(--sp-4);border-radius:var(--r-s);background:var(--rail);
  border-left:3px solid var(--soft);color:var(--mid);font-size:var(--t-b);max-width:86ch
}

/* The pinned Check bar. Fixed at the foot, above the tab bar where there is one.
   It is a raised control on its own surface rather than a floating pill, because it
   is the same button as the one in the card and should not read as a different one. */
.runbar{
  position:fixed;left:0;right:0;bottom:0;z-index:44;
  display:flex;align-items:center;justify-content:space-between;gap:var(--sp-4);
  padding:var(--sp-3) var(--sp-5) calc(var(--sp-3) + env(safe-area-inset-bottom,0px));
  background:var(--surf);border-top:1px solid var(--line);box-shadow:var(--sh3);
  animation:runbar-in var(--m-panel) var(--ease-panel) both
}
@keyframes runbar-in{from{transform:translateY(100%)}to{transform:translateY(0)}}
.runbar-s{font-size:var(--t-s);color:var(--mid);min-width:0}
.runbar .btn{flex:none}
.runbar .btn[aria-busy="true"]{opacity:.6}

/* What was noticed about a document that looks like part of one. Amber, because it
   is a caution rather than a failure, and each line says one specific thing. */
.partial-list{display:flex;flex-direction:column;gap:var(--sp-2);margin:var(--sp-4) 0}
.partial-list li{
  display:flex;gap:var(--sp-2);align-items:flex-start;background:var(--amb-t);
  color:var(--amb-on-tint);border-radius:var(--r-s);padding:var(--sp-2) var(--sp-3);font-size:var(--t-s)
}
.partial-list .i{flex:none;margin-top:1px}

/* ==========================================================================
   The operations console.

   Read only throughout, so it takes the flat output language: on the rail, no
   raised affordance, a rule down the left of the table. The one thing that is not
   read only is the password field, which is inset like every other field a person
   types into.
   ========================================================================== */

.visually-hidden{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}

.admin-lock{padding:var(--sp-6);max-width:520px}
.admin-lock .btn{margin-top:var(--sp-4)}
.admin-lock code{font-family:var(--mono);font-size:var(--t-s);background:var(--gry-t);padding:1px 5px;border-radius:4px}

.admin-head{display:flex;align-items:flex-end;justify-content:space-between;gap:var(--sp-4);flex-wrap:wrap;margin-bottom:var(--sp-5)}
.admin-day{min-width:min(260px,100%)}
.admin-actions{display:flex;gap:var(--sp-2);flex-wrap:wrap}

.admin-tiles{
  display:grid;grid-template-columns:repeat(auto-fit,minmax(min(130px,100%),1fr));
  gap:var(--sp-3);margin-bottom:var(--sp-5)
}
.admin-tile{
  background:var(--rail);border-radius:var(--r-s);padding:var(--sp-3) var(--sp-4);
  border-left:3px solid var(--prod);display:flex;flex-direction:column;gap:2px;min-width:0
}
.admin-tile-n{font-family:var(--disp);font-size:var(--t-xl);font-weight:600;line-height:1}
.admin-tile-l{font-size:var(--t-s);color:var(--mid)}

/* A wide table on a narrow screen scrolls inside its own box rather than taking
   the page sideways with it. */
.admin-table-wrap{overflow-x:auto;background:var(--rail);border-radius:var(--r-s);border-left:3px solid var(--line)}
.admin-table{width:100%;border-collapse:collapse;font-size:var(--t-s);min-width:520px}
.admin-table th{
  text-align:left;font:700 var(--t-xs) var(--ui);letter-spacing:.05em;text-transform:uppercase;
  color:var(--mid);padding:var(--sp-3) var(--sp-3);border-bottom:1px solid var(--line);white-space:nowrap
}
.admin-table td{padding:var(--sp-2) var(--sp-3);border-bottom:1px solid var(--line);vertical-align:top}
.admin-table tr:last-child td{border-bottom:none}
.admin-row-bad td{background:var(--red-t)}
.admin-what{font-weight:600;display:block}
.admin-src{font-size:var(--t-xs);color:var(--mid)}
.admin-detail{color:var(--mid);word-break:break-word}
.admin-where{color:var(--mid);display:flex;flex-direction:column;gap:1px;font-size:var(--t-xs)}
.admin-empty{color:var(--mid);padding:var(--sp-5);text-align:center}

/* --------------------------------------------------------------------------
   The console's charts.

   Colour carries one meaning throughout and it is the product's own palette, run
   through the contrast and colour blindness validator rather than chosen by eye:
   green is the product working, amber is something refused, red is something that
   failed, blue is neutral measurement. Status colours are reserved and never used
   as a series.

   Every chart carries a single series. Green against red measures a colour
   blindness separation of 5.4 where 8 is the floor, so a stacked bar of checks,
   refusals and failures would be unreadable to a red-green colour blind reader.
   Three small multiples say the same thing to everybody.
   -------------------------------------------------------------------------- */

.tone-ok    { --tone:var(--prod); --tone-t:var(--prod-t) }
.tone-act   { --tone:var(--act);  --tone-t:var(--act-t) }
.tone-warn  { --tone:var(--amb);  --tone-t:var(--amb-t) }
.tone-bad   { --tone:var(--red);  --tone-t:var(--red-t) }
.tone-neutral { --tone:var(--mid); --tone-t:var(--gry-t) }

.admin-h{font-size:var(--t-l);margin:var(--sp-6) 0 var(--sp-4)}
.admin-charts{margin-bottom:var(--sp-6)}
.chart-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(340px,100%),1fr));gap:var(--sp-4)}
/* The failure names are long and a truncated one tells nobody anything, so this
   chart takes the full width rather than being squeezed into a quarter of it. */
#chart-failures,#chart-clients{grid-column:1/-1}
#chart-failures .bar-row,#chart-clients .bar-row{grid-template-columns:minmax(0,22rem) minmax(0,1fr) auto}
.chart{padding:var(--sp-5);margin:0;min-width:0}
.chart-cap{font-family:var(--disp);font-size:var(--t-m);font-weight:600;margin-bottom:var(--sp-4)}
.chart-note{font-size:var(--t-s);color:var(--mid);margin-top:var(--sp-3);max-width:60ch}
.chart-empty{font-size:var(--t-s);color:var(--mid);padding:var(--sp-4) 0}

/* Hourly small multiples */
.chart-rows{display:flex;flex-direction:column;gap:var(--sp-4)}
.hour-row{min-width:0}
.hour-head{display:flex;align-items:center;gap:7px;margin-bottom:5px;font-size:var(--t-s)}
.hour-key{width:9px;height:9px;border-radius:3px;flex:none;background:var(--tone)}
.key-ok{background:var(--prod)} .key-warn{background:var(--amb)} .key-bad{background:var(--red)}
.hour-label{font-weight:600}
.hour-total{margin-left:auto;font-family:var(--mono);color:var(--mid)}
.hour-svg{width:100%;height:46px;display:block}
.hour-svg .axis{stroke:var(--line);stroke-width:1}
/* --soft measures 3.13:1 and fails AA for text. It is the same trap decision 22
   recorded for form labels, and an axis label is text like any other. */
.hour-axis{display:flex;justify-content:space-between;font:500 var(--t-xs)/1 var(--mono);color:var(--mid);margin-top:2px}
/* Geometry is in attributes, colour is here, so no inline style is ever needed. */
.bar{transition:opacity var(--m-state)}
.bar-ok{fill:var(--prod)} .bar-warn{fill:var(--amb)} .bar-bad{fill:var(--red)} .bar-act{fill:var(--act)}
:root[data-motion="on"] .hour-svg .bar{animation:bar-rise var(--m-panel) var(--ease-panel) both}
@keyframes bar-rise{from{transform:scaleY(0);transform-origin:bottom}to{transform:scaleY(1)}}

/* Horizontal bars, one measure across identities */
.chart-bars{display:flex;flex-direction:column;gap:var(--sp-2)}
.bar-group{font:700 var(--t-xs) var(--ui);letter-spacing:.05em;text-transform:uppercase;color:var(--mid);margin-top:var(--sp-3)}
.bar-group:first-child{margin-top:0}
.bar-row{display:grid;grid-template-columns:minmax(0,9rem) minmax(0,1fr) auto;gap:var(--sp-3);align-items:center;font-size:var(--t-s)}
.bar-name{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-family:var(--mono);font-size:var(--t-xs)}
.bar-track{height:10px;background:var(--line2);border-radius:5px;overflow:hidden;min-width:0}
.bar-fill{display:block;height:100%;border-radius:5px;width:var(--w,0)}
.bar-fill.bar-ok{background:var(--prod)} .bar-fill.bar-warn{background:var(--amb)}
.bar-fill.bar-bad{background:var(--red)} .bar-fill.bar-act{background:var(--act)}
:root[data-motion="on"] .bar-fill{animation:bar-grow .6s var(--ease-panel) both;animation-delay:var(--delay,0ms)}
@keyframes bar-grow{from{width:0}to{width:var(--w,0)}}
.bar-value{font-family:var(--mono);font-size:var(--t-xs);color:var(--mid);white-space:nowrap}

/* Filter chips */
.admin-filters{display:flex;justify-content:space-between;gap:var(--sp-4);flex-wrap:wrap;margin-bottom:var(--sp-3)}
.chips{display:flex;gap:var(--sp-2);flex-wrap:wrap}
.chipf{
  display:inline-flex;align-items:center;gap:6px;padding:5px 11px;border-radius:var(--r-full);
  border:1px solid var(--line);background:var(--surf);color:var(--mid);cursor:pointer;
  font:600 var(--t-xs) var(--ui);min-height:30px;
  transition:background var(--m-state),border-color var(--m-state),color var(--m-state)
}
.chipf:hover{border-color:var(--soft)}
.chipf-dot{width:8px;height:8px;border-radius:var(--r-full);background:var(--tone,var(--mid));flex:none;opacity:.4}
.chipf.on{background:var(--tone-t,var(--gry-t));border-color:var(--tone,var(--soft));color:var(--ink)}
.chipf.on .chipf-dot{opacity:1}
.chipf-all{font-weight:700;text-decoration:underline;text-underline-offset:2px}
.admin-copy{display:flex;flex-direction:column;align-items:flex-end;gap:4px}
.admin-copy-note{font-size:var(--t-xs);color:var(--prod);min-height:14px}
.copy-out{width:100%;font-family:var(--mono);font-size:var(--t-xs);line-height:1.5;border:1px solid var(--line);border-radius:var(--r-s);padding:var(--sp-3)}

/* Rows take the same tone as everything else, so a failure looks like a failure
   wherever the reader meets it. */
.admin-table tr.tone-bad td{background:var(--red-t)}
.admin-table tr.tone-warn td{background:var(--amb-t)}
.row-key{width:8px;height:8px;border-radius:2px;background:var(--tone,var(--mid));display:inline-block;margin-right:6px}
:root[data-motion="on"] .admin-table tbody tr{animation:row-in var(--m-state) both;animation-delay:var(--delay,0ms)}
@keyframes row-in{from{opacity:0;transform:translateY(-3px)}to{opacity:1;transform:none}}
:root[data-motion="on"] .admin-tile{animation:tile-in var(--m-panel) var(--ease-panel) both;animation-delay:var(--delay,0ms)}
@keyframes tile-in{from{opacity:0;transform:translateY(6px)}to{opacity:1;transform:none}}
.admin-tile{border-left-color:var(--tone,var(--prod))}
.admin-tile .admin-tile-n{color:var(--ink)}
.admin-list-head{margin-top:var(--sp-5)}

/* The handheld menu. Rows rather than a list, because each one is a control and has to
   look like something you press. Forty four pixels tall, in a sheet that comes up from
   the bottom, which is where the thumb already is. */
.menu-sheet{display:flex;flex-direction:column;gap:var(--sp-2)}
.menu-cap{
  font:700 var(--t-xs) var(--ui);letter-spacing:.06em;text-transform:uppercase;color:var(--mid);
  margin-top:var(--sp-3)
}
.menu-cap:first-child{margin-top:0}
.menu-row{
  display:flex;align-items:center;gap:var(--sp-3);width:100%;text-align:left;min-height:52px;
  padding:var(--sp-3);background:var(--surf);border:1px solid var(--line);border-radius:var(--r-s);
  font:inherit;color:var(--ink);cursor:pointer;box-shadow:var(--sh);
  transition:background var(--m-state),border-color var(--m-state),box-shadow var(--m-state)
}
.menu-row:hover{background:var(--gry-t);border-color:var(--soft);box-shadow:var(--sh2)}
.menu-row:active{box-shadow:none;transform:translateY(1px)}
.menu-row .i{color:var(--mid);font-size:19px;flex:none}
.menu-row-here{border-color:var(--prod);background:var(--prod-t)}
.menu-row-here .i{color:var(--prod)}
.menu-row-t{display:flex;flex-direction:column;min-width:0;flex:1 1 auto}
.menu-row-h{font-weight:600}
.menu-row-s{font-size:var(--t-s);color:var(--mid)}
.menu-meta{display:grid;grid-template-columns:auto 1fr;gap:var(--sp-2) var(--sp-4);font-size:var(--t-s)}
.menu-meta dt{color:var(--mid)}
.menu-meta dd{margin:0;color:var(--ink)}

/* Where the rules came from. The same green and amber the rest of the product uses:
   green for a source that was fetched and read, amber for one that could not be
   reached. Both are listed. Each also says which it is in words. */
.sources{margin-top:var(--sp-7);border-top:1px solid var(--line);padding-top:var(--sp-6)}
.sources h2{margin-bottom:var(--sp-2)}
.src-list{display:flex;flex-direction:column;gap:var(--sp-3);margin-top:var(--sp-5)}
.src-item{
  background:var(--surf);border:1px solid var(--line);border-left-width:3px;border-radius:var(--r-s);
  padding:var(--sp-4)
}
.src-on{border-left-color:var(--prod)}
.src-off{border-left-color:var(--amb)}
.src-head{display:flex;align-items:center;gap:var(--sp-2);flex-wrap:wrap;margin-bottom:var(--sp-2)}
.src-on .src-head .i{color:var(--prod)}
.src-off .src-head .i{color:var(--amb-on-tint)}
.src-title{font-weight:600;font-size:var(--t-m);font-family:var(--disp)}
.src-pub{font-size:var(--t-s);color:var(--mid)}
.src-note-line{font-size:var(--t-s);color:var(--mid);margin-top:var(--sp-2);max-width:86ch}
.src-body .lnk{font-family:var(--mono);font-size:var(--t-xs);word-break:break-all}
.src-note{
  margin-top:var(--sp-4);padding:var(--sp-4);border-radius:var(--r-s);background:var(--rail);
  border-left:3px solid var(--soft);color:var(--mid);font-size:var(--t-b);max-width:86ch
}

.band-cta{border-top:none}
.cta{padding:var(--sp-6);text-align:center;background:var(--nav);border-color:var(--nav)}
.cta h2{color:#fff;margin-bottom:var(--sp-2)}
.cta p{color:var(--nav-dim);margin-bottom:var(--sp-5)}

/* ==========================================================================
   What is checked
   ========================================================================== */
.rule-list{display:grid;gap:var(--sp-3);margin-top:var(--sp-5)}
.rule{padding:var(--sp-4);display:grid;grid-template-columns:1fr auto;gap:var(--sp-3) var(--sp-4);align-items:start}
.rule-main h3{font-size:var(--t-m);margin-bottom:var(--sp-1)}
.rule-why{color:var(--mid);font-size:var(--t-s);max-width:84ch}
.rule-cite{font-family:var(--mono);font-size:var(--t-s);color:var(--prod);font-weight:600;margin-top:var(--sp-2);display:block}
.rule-tags{display:flex;gap:var(--sp-1);flex-wrap:wrap;justify-content:flex-end}
.rule-applies{display:flex;gap:var(--sp-1);flex-wrap:wrap;margin-top:var(--sp-2)}

/* ==========================================================================
   Check screen. Deliberately plain: upload or paste, then check.
   ========================================================================== */
.check-grid{display:grid;grid-template-columns:minmax(0,1.55fr) minmax(min(300px,100%),1fr);gap:var(--sp-5);align-items:start}
.drop-card{padding:var(--sp-5)}
.drop{
  border:2px dashed var(--line);border-radius:var(--r-m);padding:var(--sp-6) var(--sp-4);
  text-align:center;background:var(--rail);transition:background var(--m-state),border-color var(--m-state),transform var(--m-lift)
}
.drop:focus{outline:none}
.drop.over{background:var(--act-t);border-color:var(--act);transform:scale(1.008)}
.drop-inner{display:flex;flex-direction:column;align-items:center;gap:var(--sp-2)}
.drop-inner .i-lg{color:var(--soft)}
.drop.over .i-lg{color:var(--act)}
.drop-h{font-family:var(--disp);font-size:var(--t-m);font-weight:600}
.drop-s{color:var(--mid);font-size:var(--t-s);max-width:46ch}
.btn-file{margin-top:var(--sp-2)}
/* The input stays focusable, it is only visually hidden, so the keyboard route is intact.
   The label is the visible control, so the focus ring is drawn on the label instead. */
#file{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}
.drop-inner:has(#file:focus-visible) .btn-file{outline:2px solid var(--act);outline-offset:2px}
.or{display:flex;align-items:center;gap:var(--sp-3);color:var(--mid);font-size:var(--t-s);margin:var(--sp-5) 0}
.or::before,.or::after{content:"";height:1px;background:var(--line);flex:1}
.counter{font-size:var(--t-s);color:var(--mid);margin-top:var(--sp-2)}
.counter-note{display:block;color:var(--mid)}
.counter.over{color:var(--red);font-weight:600}
.count-rail{height:3px;background:var(--line2);border-radius:2px;margin-top:var(--sp-2);overflow:hidden}
.count-fill{display:block;height:100%;width:0;background:var(--act);border-radius:2px;transition:width var(--m-panel) var(--ease-panel)}
.count-rail.over .count-fill{background:var(--red)}

/* Same trap as the collapsed grids above. A single column grid declared with nothing
   but a gap gets an `auto` track, whose minimum is min-content, so one unbreakable
   label inside a card widens the column past the screen. */
.check-side{display:grid;grid-template-columns:minmax(0,1fr);gap:var(--sp-4)}
.side-card{padding:var(--sp-5);min-width:0}
.side-h{font-size:var(--t-m);margin-bottom:var(--sp-4)}
.side-actions{display:grid;grid-template-columns:minmax(0,1fr);gap:var(--sp-3)}
.sidefoot{font-size:var(--t-s);color:var(--mid);text-align:center}
.rc{border:1px solid var(--line);border-radius:var(--r-s);padding:var(--sp-3);margin:0}
.rc legend{font:700 11px var(--ui);letter-spacing:.05em;color:var(--mid);text-transform:uppercase;padding:0 var(--sp-1)}

/* Switches. Colour is never the only carrier: the knob position carries it too. */
.sw{display:flex;align-items:center;gap:var(--sp-3);padding:var(--sp-2) 0;cursor:pointer;min-height:32px}
.sw input{position:absolute;opacity:0;width:1px;height:1px}
.sw-box{
  width:38px;height:22px;border-radius:var(--r-full);background:var(--gry);position:relative;flex:none;
  transition:background var(--m-state)
}
.sw-box::after{
  content:"";position:absolute;top:3px;left:3px;width:16px;height:16px;border-radius:var(--r-full);
  background:#fff;box-shadow:var(--sh);transition:transform var(--m-lift)
}
.sw input:checked + .sw-box{background:var(--act)}
.sw input:checked + .sw-box::after{transform:translateX(16px)}
.sw input:focus-visible + .sw-box{outline:2px solid var(--act);outline-offset:2px}
.sw-text{font-size:var(--t-b)}

/* ==========================================================================
   Running
   ========================================================================== */
.running-grid{display:grid;grid-template-columns:minmax(0,1.4fr) minmax(0,1fr);gap:var(--sp-5);align-items:start}
.scan-card{padding:var(--sp-5);position:relative;overflow:hidden;min-height:320px}
.scan-doc{display:flex;flex-direction:column;gap:var(--sp-3)}
.scan-doc span{height:9px;border-radius:3px;background:var(--line2);display:block}
.scan-beam{
  position:absolute;left:0;right:0;height:90px;top:-90px;pointer-events:none;
  background:linear-gradient(180deg,transparent,rgba(11,95,191,.18),rgba(14,122,71,.12),transparent);
  animation:beam var(--m-scan) linear infinite
}
@keyframes beam{from{top:-90px}to{top:100%}}
.skel-list{display:grid;gap:var(--sp-3)}
.skel{padding:var(--sp-4);display:flex;flex-direction:column;gap:var(--sp-2)}
.sk{display:block;background:var(--gry-t);border-radius:var(--r-s);animation:shimmer 1.4s ease-in-out infinite}
.sk-chip{width:96px;height:16px}
.sk-l{height:11px}
.sk-l.w40{width:40%}.sk-l.w50{width:50%}.sk-l.w60{width:60%}.sk-l.w70{width:70%}.sk-l.w80{width:80%}.sk-l.w85{width:85%}
.skel:nth-child(2) .sk{animation-delay:.12s}
.skel:nth-child(3) .sk{animation-delay:.24s}
@keyframes shimmer{0%,100%{opacity:1}50%{opacity:.5}}

/* ==========================================================================
   Decide. The one screen that matters.
   ========================================================================== */
.decide-head{display:flex;align-items:flex-start;justify-content:space-between;gap:var(--sp-5);flex-wrap:wrap;margin-bottom:var(--sp-4)}
.score{position:relative;width:132px;text-align:center;flex:none}
.dial{width:120px;height:120px;transform:rotate(-90deg)}
.dial-track{fill:none;stroke:var(--line2);stroke-width:10}
.dial-fill{
  fill:none;stroke:var(--grn);stroke-width:10;stroke-linecap:round;
  stroke-dasharray:326.7;stroke-dashoffset:326.7;
  transition:stroke-dashoffset 1s var(--ease-panel),stroke var(--m-panel)
}
.score.tone-ok .dial-fill{stroke:var(--act)}
.score.tone-warn .dial-fill{stroke:var(--amb)}
.score.tone-bad .dial-fill{stroke:var(--red)}
.score-mid{position:absolute;top:34px;left:0;right:0;display:flex;flex-direction:column;line-height:1}
.score-n{font-family:var(--disp);font-size:var(--t-xl);font-weight:600}
.score-of{font-size:var(--t-xs);color:var(--mid)}
.score-band{font-size:var(--t-s);color:var(--mid);margin-top:var(--sp-1)}

.decide-grid{display:grid;grid-template-columns:minmax(0,1.05fr) minmax(0,1.15fr) minmax(min(280px,100%),.85fr);gap:var(--sp-4);align-items:start}
.doc-card{padding:var(--sp-4);position:sticky;top:84px;max-height:calc(100vh - 108px);display:flex;flex-direction:column}
.doc-head{display:flex;align-items:center;justify-content:space-between;gap:var(--sp-3);margin-bottom:var(--sp-3);flex-wrap:wrap}
.doc-tools{display:flex;gap:var(--sp-2)}
.doc-body{
  overflow:auto;white-space:pre-wrap;word-break:break-word;font-family:var(--mono);
  font-size:var(--t-s);line-height:1.7;padding-right:var(--sp-2);flex:1
}
.doc-body:focus-visible{outline:2px solid var(--act);outline-offset:2px}

/* A highlight is a button so it is reachable by keyboard and by voice control.
   Severity is carried by an underline weight and a label as well as by colour. */
.hl{
  background:none;border:none;padding:0 1px;font:inherit;cursor:pointer;text-align:left;
  border-radius:3px;transition:background var(--m-state),box-shadow var(--m-state)
}
.hl-high{background:var(--red-t);box-shadow:inset 0 -2px 0 var(--red)}
.hl-medium{background:var(--amb-t);box-shadow:inset 0 -2px 0 var(--amb)}
.hl-advisory{background:var(--act-t);box-shadow:inset 0 -2px 0 var(--act)}
.hl-opportunity{background:var(--grn-t);box-shadow:inset 0 -2px 0 var(--grn)}
.hl-horizon{background:var(--vio-t);box-shadow:inset 0 -2px 0 var(--vio)}
.hl:hover{box-shadow:inset 0 -3px 0 currentColor}
.hl.sel{outline:2px solid var(--act);outline-offset:1px;animation:hlping .5s var(--ease-panel)}
.hl.done{background:var(--gry-t);box-shadow:inset 0 -2px 0 var(--gry);text-decoration:line-through;text-decoration-color:var(--soft)}
@keyframes hlping{from{transform:scale(1.04)}to{transform:none}}

.flags-col{display:flex;flex-direction:column;gap:var(--sp-3);min-width:0}
.flags-head{display:flex;align-items:center;justify-content:space-between;gap:var(--sp-3);flex-wrap:wrap}
.flag-list{display:flex;flex-direction:column;gap:var(--sp-3)}

/* Fix all. Raised, because it is a control, and green because everything it touches
   is something this can settle today. When there is nothing left for it to do it
   turns into a plain statement rather than disappearing. */
.fixall{
  display:flex;align-items:center;justify-content:space-between;gap:var(--sp-4);flex-wrap:wrap;
  background:var(--prod-t);border:1px solid var(--prod);border-radius:var(--r-m);
  padding:var(--sp-4);margin:var(--sp-3) 0
}
.fixall-said{display:flex;gap:var(--sp-3);align-items:flex-start;min-width:0;flex:1 1 240px}
.fixall-said .i{color:var(--prod);font-size:19px;margin-top:1px}
.fixall-h{font-weight:600;font-size:var(--t-m);font-family:var(--disp)}
.fixall-s{color:var(--mid);font-size:var(--t-s);margin-top:2px}
.fixall-do{display:flex;gap:var(--sp-2);align-items:center;flex-wrap:wrap}
.fixall-none{background:var(--rail);border-color:var(--line)}
.fixall-none .i{color:var(--soft)}

/* Why a flag is not a wording change. Amber, because it is a thing outstanding, and
   the same amber as the badge on the card it sits under. */
.flag-why{
  background:var(--amb-t);color:var(--amb-on-tint);border-radius:var(--r-s);
  padding:var(--sp-2) var(--sp-3);font-size:var(--t-s);margin-bottom:var(--sp-3)
}

/* The preview. Every change laid out before any of it happens. */
.fix-preview{display:flex;flex-direction:column;gap:var(--sp-3);margin-bottom:var(--sp-4)}
.fix-preview li{display:grid;gap:var(--sp-2);padding:var(--sp-3);background:var(--rail);border-radius:var(--r-s)}
.fix-p-label{font-weight:600;font-size:var(--t-s)}
.fix-p-was,.fix-p-now{font-family:var(--mono);font-size:var(--t-s);padding:var(--sp-2);border-radius:var(--r-s);background:var(--surf)}
.fix-p-was{color:var(--mid);text-decoration:line-through;text-decoration-color:var(--red)}
.fix-p-now{color:var(--ink);border-left:3px solid var(--prod)}
.fix-p-arrow{color:var(--soft);display:flex;justify-content:center}
.fix-p-left{border-top:1px solid var(--line);padding-top:var(--sp-4);margin-bottom:var(--sp-4)}
.fix-p-left-h{font-weight:700;font-size:var(--t-xs);letter-spacing:.05em;text-transform:uppercase;color:var(--amb-on-tint);margin-bottom:var(--sp-2)}
.fix-p-left ul{display:flex;flex-direction:column;gap:var(--sp-2)}
.fix-p-left li{font-size:var(--t-s);color:var(--mid)}
.flag{
  padding:var(--sp-4);scroll-margin-top:96px;
  animation:flagin var(--m-tell) var(--ease-panel) backwards;
  transition:box-shadow var(--m-lift),transform var(--m-lift),border-color var(--m-state)
}
@keyframes flagin{from{opacity:0;transform:translateY(12px) scale(.99)}to{opacity:1;transform:none}}
.flag:hover{box-shadow:var(--sh3)}
.flag.sel{border-color:var(--act);box-shadow:0 0 0 2px var(--act-t),var(--sh3)}
.flag.decided{background:var(--rail)}
.flag-top{display:flex;align-items:center;gap:var(--sp-2);flex-wrap:wrap;margin-bottom:var(--sp-2)}
.flag h3{font-size:var(--t-m);margin-bottom:var(--sp-2)}
.flag-quote{
  border-left:3px solid var(--line);padding:var(--sp-2) var(--sp-3);background:var(--rail);
  border-radius:0 var(--r-s) var(--r-s) 0;font-family:var(--mono);font-size:var(--t-s);
  margin-bottom:var(--sp-3);word-break:break-word
}
.flag-quote.sev-high{border-left-color:var(--red)}
.flag-quote.sev-medium{border-left-color:var(--amb)}
.flag-quote.sev-advisory{border-left-color:var(--act)}
.flag-reason{color:var(--ink);margin-bottom:var(--sp-3)}
.flag-basis{
  display:flex;align-items:center;gap:var(--sp-2);font-family:var(--mono);font-size:var(--t-s);
  color:var(--prod);font-weight:600;margin-bottom:var(--sp-3);flex-wrap:wrap
}
/* A horizon item is not law. It must not be able to be mistaken for a citation, so it
   takes the violet used for horizon everywhere, a clock rather than the scales, and it
   says what it is in words before it names anything. */
.flag-basis-horizon{color:var(--vio);font-family:var(--ui);font-weight:600}
.flag-horizon{border-left:3px solid var(--vio)}
.flag-quote.sev-horizon{border-left-color:var(--vio)}
.flag-note{background:var(--amb-t);color:var(--amb-on-tint);border-radius:var(--r-s);padding:var(--sp-2) var(--sp-3);font-size:var(--t-s);margin-bottom:var(--sp-3)}
.rewrite{margin-bottom:var(--sp-3)}
.rewrite-h{font:700 11px var(--ui);letter-spacing:.05em;color:var(--mid);text-transform:uppercase;margin-bottom:5px}
.rewrite textarea{width:100%;min-height:74px;border:1px solid var(--line);border-radius:var(--r-s);padding:var(--sp-2) var(--sp-3);font:inherit;font-size:var(--t-s);line-height:1.6;background:var(--grn-t);resize:vertical}
.rewrite textarea:focus{outline:2px solid var(--act);outline-offset:-1px}
.flag-actions{display:flex;gap:var(--sp-2);flex-wrap:wrap}
.flag-decided{display:flex;align-items:flex-start;gap:var(--sp-2);background:var(--grn-t);border-radius:var(--r-s);padding:var(--sp-3);font-size:var(--t-s);color:var(--ink)}
.flag-decided.over{background:var(--amb-t)}
.flag-decided.defer{background:var(--gry-t)}
.flag-decided p{margin-top:2px}
.flag-decided strong{font-weight:600}

.empty{text-align:center;padding:var(--sp-7) var(--sp-4);color:var(--mid)}
/* Icon only, so 3:1 applies rather than 4.5:1. --soft measures 3.13 on white. */
.empty .i{font-size:32px;color:var(--soft);margin-bottom:var(--sp-3)}
.empty h3{margin-bottom:var(--sp-2)}
.empty p{font-size:var(--t-s);max-width:44ch;margin:0 auto}

/* The record forming */
.rec-card{padding:var(--sp-4);position:sticky;top:84px}
.rec-sub{font-size:var(--t-s);color:var(--mid);margin:var(--sp-2) 0 var(--sp-4)}
.rec-meter{margin-bottom:var(--sp-4)}
.rec-meter-rail{height:6px;background:var(--line2);border-radius:3px;overflow:hidden}
.rec-meter-fill{display:block;height:100%;width:0;background:var(--prod);border-radius:3px;transition:width var(--m-panel) var(--ease-panel)}
.rec-meter-txt{font-size:var(--t-s);color:var(--mid);margin-top:var(--sp-2)}
.rec-rows{display:flex;flex-direction:column;gap:var(--sp-2);max-height:260px;overflow:auto;margin-bottom:var(--sp-3)}
.rec-row{
  display:grid;grid-template-columns:auto 1fr;gap:var(--sp-2);align-items:start;
  padding:var(--sp-2);border-radius:var(--r-s);background:var(--rail);font-size:var(--t-s);
  animation:recin var(--m-panel) var(--ease-panel) backwards
}
@keyframes recin{from{opacity:0;transform:translateX(10px)}to{opacity:1;transform:none}}
.rec-row .mono{font-size:var(--t-xs)}
.rec-row-t{font-weight:600}
.rec-row-r{color:var(--mid)}
.rec-empty{font-size:var(--t-s);color:var(--mid);padding:var(--sp-3);text-align:center;border:1px dashed var(--line);border-radius:var(--r-s);margin-bottom:var(--sp-3)}
.rec-meta{display:grid;grid-template-columns:auto 1fr;gap:var(--sp-1) var(--sp-3);font-size:var(--t-s);margin-bottom:var(--sp-4);padding-top:var(--sp-3);border-top:1px solid var(--line)}
.rec-meta dt{color:var(--mid);font-weight:600}
.rec-meta dd{margin:0;color:var(--mid);word-break:break-word}

/* ==========================================================================
   Sealed record
   ========================================================================== */
.sealed{max-width:740px;margin:0 auto;text-align:center}
.sealed-mark{width:96px;height:96px;margin:0 auto var(--sp-4)}
.sealed-mark svg{width:96px;height:96px}
.seal-ring{fill:none;stroke:var(--prod);stroke-width:6;stroke-dasharray:314;stroke-dashoffset:314;animation:draw .8s var(--ease-panel) forwards}
.seal-tick{fill:none;stroke:var(--prod);stroke-width:8;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:70;stroke-dashoffset:70;animation:draw .5s var(--ease-panel) .5s forwards}
@keyframes draw{to{stroke-dashoffset:0}}
.sealed-card{padding:var(--sp-5);text-align:left;margin-bottom:var(--sp-5)}
.sealed-meta{display:grid;grid-template-columns:auto 1fr;gap:var(--sp-2) var(--sp-4);margin-bottom:var(--sp-5)}
.sealed-meta dt{color:var(--mid);font-weight:600;font-size:var(--t-s)}
.sealed-meta dd{margin:0;word-break:break-all}
.sealed-meta .big{font-size:var(--t-m);font-weight:600;color:var(--prod)}
.hash{font-size:11px;color:var(--mid)}
.sealed-tally{display:flex;gap:var(--sp-2);flex-wrap:wrap;margin-bottom:var(--sp-5);padding-top:var(--sp-4);border-top:1px solid var(--line)}
.sealed-actions{display:flex;gap:var(--sp-3);flex-wrap:wrap}
.disclaimer{font-size:var(--t-s);color:var(--mid);text-align:left;background:var(--gry-t);border-radius:var(--r-m);padding:var(--sp-4);max-width:86ch}

/* ==========================================================================
   Notices, section 16
   ========================================================================== */
.notice{border-radius:var(--r-m);padding:var(--sp-3) var(--sp-4);margin-bottom:var(--sp-4);font-size:var(--t-b)}
.notice-error{background:var(--red-t);color:var(--red)}
.notice-error strong{color:var(--red)}
.notice-info{background:var(--act-t);color:var(--act)}
.notice-warn{background:var(--amb-t);color:var(--amb-on-tint)}
.notice-standalone{margin:var(--sp-5)}
.notice h3{font-size:var(--t-m);margin-bottom:var(--sp-1)}
.notice p + p{margin-top:var(--sp-2)}

/* Modal, section 11 */
.scrim{position:fixed;inset:0;background:rgba(13,27,42,.55);display:grid;place-items:center;padding:var(--sp-4);z-index:50;animation:fade var(--m-panel) both}
@keyframes fade{from{opacity:0}to{opacity:1}}
.modal{
  background:var(--surf);border-radius:var(--r-l);width:min(620px,100%);max-height:88vh;overflow:auto;
  box-shadow:0 20px 60px rgba(0,0,0,.3);animation:pop var(--m-panel) var(--ease-panel) both
}
@keyframes pop{from{opacity:0;transform:translateY(12px) scale(.98)}to{opacity:1;transform:none}}
.modal-head{display:flex;align-items:center;justify-content:space-between;gap:var(--sp-3);padding:var(--sp-4) var(--sp-5);border-bottom:1px solid var(--line)}
.modal-body{padding:var(--sp-5)}
.modal-body .hint{margin-bottom:var(--sp-3)}
.modal-actions{display:flex;justify-content:space-between;gap:var(--sp-3);margin-top:var(--sp-5)}
.modal-body textarea{width:100%;min-height:110px;border:1px solid var(--line);border-radius:var(--r-s);padding:var(--sp-3);font:inherit;font-size:var(--t-b);line-height:1.6;resize:vertical}
.modal-body textarea:focus{outline:2px solid var(--act);outline-offset:-1px}
.modal-quote{border-left:3px solid var(--line);padding:var(--sp-2) var(--sp-3);background:var(--rail);font-family:var(--mono);font-size:var(--t-s);margin-bottom:var(--sp-4)}
.err{color:var(--red);font-size:var(--t-s);font-weight:600;margin-top:var(--sp-2)}
.nc-list{display:flex;flex-direction:column;gap:var(--sp-3)}
.nc-item{padding:var(--sp-3);background:var(--rail);border-radius:var(--r-s)}
.nc-item h3{font-size:var(--t-b);margin-bottom:var(--sp-1)}
.nc-item p{font-size:var(--t-s);color:var(--mid)}

/* Toasts */
.toast-rail{position:fixed;right:var(--sp-4);bottom:var(--sp-4);z-index:55;display:flex;flex-direction:column;gap:var(--sp-2);max-width:min(380px,calc(100vw - 32px))}
.toast{
  background:var(--nav);color:#fff;border-radius:var(--r-s);padding:var(--sp-3) var(--sp-4);
  box-shadow:var(--sh3);font-size:var(--t-s);animation:toastin var(--m-panel) var(--ease-panel) both
}
@keyframes toastin{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:none}}
.toast-warn{background:var(--amb);color:#231701}

/* ==========================================================================
   Footer
   ========================================================================== */
.foot{border-top:1px solid var(--line);background:var(--surf);margin-top:var(--sp-7)}
.foot-in{max-width:1080px;margin:0 auto;padding:var(--sp-5);display:flex;gap:var(--sp-4);align-items:flex-start;flex-wrap:wrap}
.foot-in img{width:24px;height:24px;border-radius:5px}
.foot p{font-size:var(--t-s);color:var(--mid);max-width:70ch}
.foot-note{color:var(--mid);flex-basis:100%}

/* ==========================================================================
   Reflow. Section 17: no horizontal scroll at 320px. Control rows wrap.
   ========================================================================== */
@media (max-width:1180px){
  .decide-grid{grid-template-columns:minmax(0,1fr) minmax(0,1fr)}
  .rec-card{grid-column:1 / -1;position:static;max-height:none}
}
/* Every collapse below uses minmax(0,1fr), never a bare 1fr.
   A bare 1fr is minmax(auto,1fr), and `auto` as a minimum resolves to the track's
   min-content width, so a grid item holding anything that will not wrap makes the
   track wider than its container and the whole page gains a horizontal scrollbar.
   It is the most common way a layout that reflows at 320 stops reflowing at 240. */
@media (max-width:1000px){
  .hero{grid-template-columns:minmax(0,1fr);gap:var(--sp-6)}
  .hero-art{min-height:280px;order:-1}
  .claims,.steps{grid-template-columns:minmax(0,1fr) minmax(0,1fr)}
  .check-grid{grid-template-columns:minmax(0,1fr)}
  .running-grid{grid-template-columns:minmax(0,1fr)}
  .two{grid-template-columns:minmax(0,1fr)}
}
@media (max-width:820px){
  .decide-grid{grid-template-columns:minmax(0,1fr)}
  .doc-card{position:static;max-height:420px}
  .bar{gap:var(--sp-3)}
  .bar-nav{order:3;flex-basis:100%}
}
@media (max-width:620px){
  .view{padding:var(--sp-5) var(--sp-4) var(--sp-6)}
  .hero h1{font-size:30px}
  .claims,.steps{grid-template-columns:minmax(0,1fr)}
  .copy-list{grid-template-columns:minmax(0,1fr)}
  .rule{grid-template-columns:minmax(0,1fr)}
  .rule-tags{justify-content:flex-start}
  .sealed-meta,.rec-meta{grid-template-columns:minmax(0,1fr)}
  .sealed-meta dt,.rec-meta dt{margin-top:var(--sp-2)}
  .band{padding:var(--sp-6) 0}
  .art-card-1{right:0}
  .art-card-2{left:0}
}
@media (max-width:380px){
  .art-card{width:150px}
  .hero-actions .btn-lg,.hero-actions .ghost-lg{width:100%;justify-content:center}
}

/* ==========================================================================
   Handheld. Added in V1.3.

   The wrapping header was the whole problem: brand, tools and three navigation
   links each took a row, and the header is sticky, so 355 of 844 pixels were
   permanently spent on chrome. Below 620px it becomes what a person expects on a
   phone instead. One compact row at the top carrying identity, and the three
   destinations as a bottom tab bar within thumb reach, each with an icon and a
   short word rather than an icon alone.

   Everything else here is the ordinary handheld set. Sixteen pixel form text,
   because anything smaller makes iOS Safari zoom the page on focus and leave it
   zoomed. Forty four pixel targets. Dialogs as bottom sheets. Native selects left
   native, because the platform's own picker is the one thing every person on a
   phone already knows how to use, and replacing it with a bespoke listbox would be
   worse in every way that matters.
   ========================================================================== */

/* The trigger is deliberately not width alone.
   
   A phone does not always report a narrow layout viewport. Request Desktop Website
   lays the page out at 980 CSS pixels and ignores width=device-width entirely, and
   when that happens a width-only breakpoint leaves a phone running the desktop
   layout: three rows of sticky header, content wider than the screen, and text the
   reader has to zoom into and then scroll sideways through. That is exactly the
   failure this block exists to prevent, so it also fires on any coarse pointer up to
   a tablet width, which is true of a handheld whatever it claims its width is. */
@media (max-width:620px), (pointer:coarse) and (max-width:1024px){
  /* One row, and it stays one row. */
  .bar{
    flex-wrap:nowrap;gap:var(--sp-3);padding:var(--sp-2) var(--sp-4);
    min-height:52px;justify-content:space-between
  }
  .bar-brand{flex:0 1 auto;min-width:0}
  .bar-product{font-size:var(--t-b);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .bar-tools{flex:none;gap:var(--sp-2)}
  /* The word is dropped, not the accessible name: the button keeps an aria-label. */
  .bar-tools .motion-label{
    position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;
    clip:rect(0 0 0 0);white-space:nowrap;border:0
  }
  .ghost-nav{padding:0;width:44px;height:44px;justify-content:center}

  /* The tab bar. Fixed, above the safe area, and it does not scroll away.
     Its height is a token rather than whatever the content happens to add up to,
     because the clearance the page leaves underneath has to match it exactly and a
     number derived twice is a number that drifts apart. */
  :root{--tabbar:66px}
  .bar-nav{
    position:fixed;left:0;right:0;bottom:0;z-index:45;order:0;flex-basis:auto;
    display:flex;gap:0;background:var(--nav);box-sizing:border-box;
    border-top:1px solid rgba(255,255,255,.1);
    height:calc(var(--tabbar) + env(safe-area-inset-bottom,0px));
    padding:5px var(--sp-2) calc(5px + env(safe-area-inset-bottom,0px))
  }
  .navlink{
    /* min-width:0 is the load bearing part. Without it each tab keeps its label's
       min-content width and four of them stop the bar shrinking, which puts a
       horizontal scrollbar on the whole page at the widths a zoomed reader uses. */
    flex:1 1 0;min-width:0;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:3px;
    min-height:48px;padding:var(--sp-2) 3px;font-size:var(--t-xs);border-radius:var(--r-s);
    line-height:1.1;text-align:center
  }
  .navlink-s{max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .navlink .i{font-size:20px}
  .navlink-t{display:none}
  .navlink-s{display:inline}
  .navlink-menu{display:flex}
  /* The controls move into the menu, so the top bar carries identity and nothing else. */
  .bar-tools{display:none}
  .navlink[aria-current="page"]{background:rgba(255,255,255,.14);color:#fff}
  /* Nothing hides behind the tab bar, including the last line of the footer. */
  body{padding-bottom:calc(var(--tabbar) + env(safe-area-inset-bottom,0px) + var(--sp-2))}
  /* Toasts move to the top on a handheld. The bottom of the screen belongs to the tab
     bar and to any sheet that comes up over it, and a toast that lands on top of a
     dialog's own buttons is worse than one nobody sees. A banner from the top is also
     what a phone does with every other transient message. */
  .toast-rail{
    right:var(--sp-3);left:var(--sp-3);max-width:none;
    top:calc(52px + var(--sp-3));bottom:auto;flex-direction:column-reverse
  }
  /* Above the tab bar, never over it. */
  .runbar{
    bottom:calc(var(--tabbar) + env(safe-area-inset-bottom,0px));
    padding:var(--sp-3) var(--sp-4);gap:var(--sp-3)
  }
  .runbar-s{font-size:var(--t-xs)}
  .runbar .btn{padding:12px 16px;min-height:48px}
  .skip{top:-72px}
  .skip:focus{top:var(--sp-3)}

  /* Sixteen pixels, or the page zooms itself on focus and stays zoomed. */
  .f select,.f input[type=text],.f textarea,.modal-body textarea,.rewrite textarea{font-size:16px}
  .f select,.f input[type=text]{min-height:44px;padding:10px 12px}
  .f select{padding-right:38px}
  .f textarea{min-height:180px}

  /* Forty four pixels on anything pressed with a thumb. */
  .btn,.ghost,.btn-lg,.ghost-lg,.btn-file,.cap-more,.scope-opt,.seg button,.fold-sum,.faq-q{min-height:44px}
  .btn,.ghost{padding:10px 14px}
  .doc-tools,.flag-actions,.hero-actions,.rec-actions{gap:var(--sp-2)}
  .flag-actions button{flex:1 1 auto}

  /* A dialog on a phone is a sheet that comes up from the bottom. */
  .scrim{place-items:end center;padding:0}
  .modal{
    width:100%;max-width:none;max-height:88dvh;overflow:auto;
    border-radius:var(--r-m) var(--r-m) 0 0;
    padding-bottom:calc(var(--sp-4) + env(safe-area-inset-bottom,0px))
  }
  .modal-actions{flex-direction:column-reverse;align-items:stretch}
  .modal-actions button{width:100%;justify-content:center}

  /* The pitch comes first on a phone. At 1000px the art is moved above the words,
     which is right on a tablet and wrong on a handset, where it spent most of the
     first screen on decoration and pushed the sentence that sells this below the
     fold. It stays, smaller, underneath. */
  .hero-art{order:1;min-height:210px;overflow:hidden}
  .hero-actions{flex-direction:column;align-items:stretch}
  .hero-actions .btn-lg,.hero-actions .ghost-lg{width:100%;justify-content:center}
  .hero{gap:var(--sp-5)}
  .art-doc{transform:scale(.82)}

  /* The demonstration says the same sentence twice on a narrow screen, because the
     stage is stacked and the step list is already showing it. The live region stays,
     it just stops being the visible copy. */
  .demo-say{
    position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;
    clip:rect(0 0 0 0);white-space:nowrap;border:0;min-height:0
  }
  .demo{padding:var(--sp-4)}
  .demo-head{margin-bottom:var(--sp-4)}
  .demo-steps{grid-template-columns:minmax(0,1fr);margin-top:0}
}

@media (max-width:620px) and (display-mode:standalone), (pointer:coarse) and (max-width:1024px) and (display-mode:standalone){
  /* Installed to the home screen there is no browser chrome to scroll away, so the
     header can hold its place without costing anything. */
  .bar{position:fixed;left:0;right:0;top:0}
  main{padding-top:52px}
}

/* Print. A person will print the decision screen. */
@media print{
  .bar,.foot,.toast-rail,.runbar,.hero-art,.flag-actions,.doc-tools,.seg{display:none!important}
  .card{box-shadow:none;border:1px solid #999}
  .view{max-width:none;padding:0}
}

/* ==========================================================================
   Deployment modes and the enterprise capability gate, added in V1.1.

   The rule everywhere below: unavailable is shown, not hidden, and it carries
   the reason. Section 17 also means an unavailable control has to stay
   reachable, so nothing here uses the `disabled` attribute, which removes an
   element from the tab order and leaves a keyboard or screen reader user
   unable to find out why it is greyed out. `aria-disabled` keeps it focusable
   and announced, and pressing it explains itself.
   ========================================================================== */

.band-lede{color:var(--mid);max-width:78ch;margin:calc(var(--sp-5) * -1) 0 var(--sp-5)}
.band-foot{color:var(--mid);font-size:var(--t-s);max-width:82ch;margin-top:var(--sp-4)}

.modes{display:grid;grid-template-columns:1fr 1fr;gap:var(--sp-5);align-items:start}
.mode-card{padding:0;overflow:hidden;display:flex;flex-direction:column}
.mode-head{display:flex;align-items:center;gap:var(--sp-3);padding:var(--sp-4);color:#fff}
.mode-head .i{font-size:22px}
.mode-head h3{color:#fff}
.mode-head p{font-size:var(--t-s);opacity:.85}
/* Availability decides the colour, not aspiration. Hosted is what works on this
   instance today, so it is green. Inside your boundary is not available here, so it is
   grey. These were the other way round, which read as an advertisement rather than a
   description of what you can actually do. */
.mode-head-hosted{background:var(--prod)}
.mode-head-ent{background:#5C6472}

/* Zones read as containment. Section 14: a zone is a boundary and the nesting is
   the point. Geometry is not hard-coded anywhere here, it is flex and grid, so a
   retyped label cannot push a node through the bottom of its zone. */
.zone{margin:var(--sp-4);border:2px solid var(--line);border-radius:var(--r-m);padding:var(--sp-3);background:var(--rail)}
.zone-out{border-style:dashed;border-color:var(--soft)}
.zone-full{border-color:var(--gry);border-width:2px;border-style:dashed;background:var(--gry-t);flex:1}
.zone-label{font:700 11px var(--ui);letter-spacing:.05em;text-transform:uppercase;color:var(--mid);margin-bottom:var(--sp-2)}
.zone-full .zone-label{color:var(--mid)}
.zone-inner{display:flex;flex-wrap:wrap;gap:var(--sp-2)}
.zone-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(132px,100%),1fr))}
.node{
  display:inline-flex;align-items:center;gap:6px;background:var(--surf);border:1px solid var(--line);
  border-radius:var(--r-s);padding:6px 10px;font-size:var(--t-s);font-weight:500;box-shadow:var(--sh)
}
.node-on{border-color:var(--prod);color:var(--ink)}
.node-on .i{color:var(--prod)}

.flow{display:flex;align-items:center;gap:var(--sp-2);margin:0 var(--sp-4)}
.flow-line{flex:1;height:2px;background:repeating-linear-gradient(90deg,var(--soft) 0 6px,transparent 6px 12px)}
.flow-word{font-size:var(--t-xs);font-weight:700;letter-spacing:.05em;text-transform:uppercase;color:var(--mid)}

.mode-notes{padding:var(--sp-4);display:flex;flex-direction:column;gap:var(--sp-2);border-top:1px solid var(--line);margin-top:auto}
.mode-notes li{position:relative;padding-left:18px;color:var(--mid);font-size:var(--t-s)}
.mode-notes li::before{content:"";position:absolute;left:0;top:7px;width:6px;height:6px;border-radius:2px;background:var(--soft)}
.mode-card-ent .mode-notes li::before{background:var(--gry)}
.mode-card-ent .node{border-color:var(--line);color:var(--mid)}
.mode-card-ent .node .i{color:var(--soft)}

/* ---- The panel on the check screen ---- */
.dep-card{padding:var(--sp-4)}
.dep-head{display:flex;align-items:center;justify-content:space-between;gap:var(--sp-3);margin-bottom:var(--sp-2)}
.dep-head .side-h{margin-bottom:0}

.policy-drop{
  display:flex;align-items:center;gap:var(--sp-3);padding:var(--sp-3);margin-bottom:var(--sp-4);
  border:2px dashed var(--line);border-radius:var(--r-m);background:var(--rail)
}
.policy-drop .i{font-size:20px;color:var(--soft)}
.policy-text{flex:1;min-width:0}
.policy-h{font-weight:600;font-size:var(--t-s)}
.policy-s{font-size:var(--t-s);color:var(--mid)}
.policy-drop.on{border-style:solid;border-color:var(--prod);background:var(--prod-t)}
.policy-drop.on .i{color:var(--prod)}

.caplist{display:flex;flex-direction:column;gap:var(--sp-2);margin-bottom:var(--sp-4)}
.cap-row{display:grid;grid-template-columns:auto 1fr auto;gap:var(--sp-2);align-items:start;font-size:var(--t-s)}
.cap-row .i{font-size:15px;margin-top:2px}
.cap-on .i{color:var(--prod)}
.cap-off .i{color:var(--soft)}
.cap-off .cap-label{color:var(--mid)}
.cap-label{line-height:1.4}
.cap-more{
  background:none;border:none;padding:2px 4px;margin:-2px -4px;cursor:pointer;color:var(--act);
  font:600 var(--t-xs) var(--ui);min-height:24px;min-width:24px;text-decoration:underline;text-underline-offset:2px
}
.cap-more:hover{color:var(--act-h)}

/* ---- Role scope. The unavailable choice stays focusable and explains itself. ---- */
.rc-scope{margin-bottom:var(--sp-4)}
.scope{display:flex;flex-direction:column;gap:var(--sp-2)}
.scope-opt{
  display:flex;align-items:flex-start;gap:var(--sp-3);padding:var(--sp-3);cursor:pointer;text-align:left;
  background:var(--surf);border:1px solid var(--line);border-radius:var(--r-s);width:100%;
  font:inherit;color:var(--ink);transition:border-color var(--m-state),background var(--m-state),box-shadow var(--m-state)
}
.scope-opt:hover{border-color:var(--soft);box-shadow:var(--sh)}
.scope-opt:active{box-shadow:none;transform:translateY(1px)}
.scope-opt[aria-checked="true"]{border-color:var(--act);background:var(--act-t);box-shadow:var(--sh)}
.scope-dot{
  width:18px;height:18px;border-radius:var(--r-full);border:2px solid var(--soft);flex:none;margin-top:1px;
  display:grid;place-items:center;transition:border-color var(--m-state)
}
.scope-opt[aria-checked="true"] .scope-dot{border-color:var(--act)}
.scope-opt[aria-checked="true"] .scope-dot::after{content:"";width:8px;height:8px;border-radius:var(--r-full);background:var(--act)}
.scope-body{min-width:0}
.scope-title{font-weight:600;display:flex;align-items:center;gap:6px;flex-wrap:wrap}
.scope-hint{font-size:var(--t-s);color:var(--mid);margin-top:2px}

/* Unavailable, and visibly so, without leaving the keyboard behind. */
.scope-opt[aria-disabled="true"]{
  background:var(--gry-t);border-style:dashed;cursor:not-allowed;
  background-image:repeating-linear-gradient(135deg,transparent 0 7px,rgba(92,100,114,.05) 7px 14px)
}
.scope-opt[aria-disabled="true"]:hover{border-color:var(--line);box-shadow:none}
.scope-opt[aria-disabled="true"]:active{transform:none}
.scope-opt[aria-disabled="true"] .scope-dot{border-color:var(--line);border-style:dashed}
.scope-opt[aria-disabled="true"] .scope-title{color:var(--mid)}
/* Availability, in the one colour pair that means it everywhere in this product:
   green for what this instance can do today, grey for what needs your own boundary.
   The marker is a left edge rather than a fill, so it survives the selected state
   and the disabled hatching without either of them having to know about it. Colour
   is never the only carrier: each option also states its availability in words. */
.scope-opt{border-left-width:3px}
.scope-on{border-left-color:var(--prod)}
.scope-off{border-left-color:var(--gry)}
.scope-opt[aria-checked="true"].scope-on{border-left-color:var(--prod)}
.scope-opt[aria-disabled="true"].scope-off{border-left-color:var(--gry);border-left-style:solid}

.scope-why{
  font-size:var(--t-s);color:var(--amb-on-tint);background:var(--amb-t);border-radius:var(--r-s);
  padding:var(--sp-2) var(--sp-3);margin-top:var(--sp-2)
}
.scope-why:empty{display:none}

.ghost[aria-disabled="true"]{
  background:var(--gry-t);border-style:dashed;color:var(--mid);cursor:not-allowed;box-shadow:none
}
.ghost[aria-disabled="true"]:hover{background:var(--gry-t);border-color:var(--line);box-shadow:none}
.ghost[aria-disabled="true"]:active{transform:none}

/* ---- The self-hosting dialog ---- */
.sh-list{display:flex;flex-direction:column;gap:var(--sp-3);margin:var(--sp-4) 0}
.sh-item{display:grid;grid-template-columns:auto 1fr;gap:var(--sp-3);padding:var(--sp-3);background:var(--rail);border-radius:var(--r-s)}
.sh-item .i{font-size:19px;color:var(--prod);margin-top:2px}
.sh-item h3{font-size:var(--t-b);margin-bottom:2px}
.sh-item p{font-size:var(--t-s);color:var(--mid)}
.sh-item.off .i{color:var(--soft)}
.env{background:var(--nav);color:rgba(255,255,255,.9);border-radius:var(--r-s);padding:var(--sp-3);
  font-family:var(--mono);font-size:var(--t-s);overflow-x:auto;white-space:pre;margin-top:var(--sp-2)}

@media (max-width:1000px){
  .modes{grid-template-columns:1fr}
}

/* ==========================================================================
   Input, control, output. Three visual languages, applied everywhere.

   The convention this follows is the common one across design systems, and it
   is about affordance rather than decoration.

     Something you type into is a well. It is inset, so the surface reads as
     recessed and invites a cursor. White ground, solid border, text cursor.

     Something you press or choose from is raised. It sits on --sh with a
     hover lift and a press state, which is the button language in section 10
     of the style guide, extended to selects and switches so that every
     pressable thing in the product looks pressable.

     Something the application produced and you only read is flat. No inset,
     no lift, tinted ground, a rule down the left edge. Nothing about it
     suggests a cursor, because there is nothing to type.

   Every one of the three also carries a word, not only a treatment. Colour and
   depth are never the sole carrier of meaning, which is section 17.
   ========================================================================== */

/* ---- 1. Type into it ---- */
.io-in,
.f textarea,
.f input[type=text],
.modal-body textarea,
.rewrite textarea{
  background:var(--surf);
  border:1px solid var(--line);
  border-radius:var(--r-s);
  /* The inset is the signal. It is the difference between a well and a plate. */
  box-shadow:inset 0 1px 2px rgba(13,27,42,.10);
  cursor:text
}
.io-in:hover,.f textarea:hover,.f input[type=text]:hover,.modal-body textarea:hover,.rewrite textarea:hover{
  border-color:var(--soft)
}
.io-in:focus,.f textarea:focus,.f input[type=text]:focus,.modal-body textarea:focus,.rewrite textarea:focus{
  outline:2px solid var(--act);outline-offset:-1px;border-color:var(--act);
  box-shadow:inset 0 1px 2px rgba(13,27,42,.06)
}
/* A suggested rewrite is still something you type into, so it keeps the well.
   The green says where it came from, the inset says you may change it. */
.rewrite textarea{background:var(--grn-t)}

/* ---- 2. Press it or choose from it ---- */
/* A select is a control, not a field, so it is raised rather than inset and it
   carries a chevron. Without the chevron a native select on some platforms is
   indistinguishable from a text input, which is the confusion this is fixing. */
.f select{
  background:var(--surf);
  border:1px solid var(--line);
  border-radius:var(--r-s);
  box-shadow:var(--sh);
  cursor:pointer;
  appearance:none;
  padding-right:34px;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%235C6472' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
  background-repeat:no-repeat;
  background-position:right 10px center;
  background-size:16px 16px;
  transition:box-shadow var(--m-state),border-color var(--m-state)
}
.f select:hover{border-color:var(--soft);box-shadow:var(--sh2)}
.f select:active{box-shadow:none;transform:translateY(1px)}
.f select:focus{outline:2px solid var(--act);outline-offset:-1px;border-color:var(--act);box-shadow:var(--sh)}

/* ---- 3. Read it ---- */
.io-out{
  background:var(--rail);
  border:1px solid var(--line2);
  border-left:3px solid var(--line);
  border-radius:0 var(--r-s) var(--r-s) 0;
  box-shadow:none;
  cursor:default
}
/* The checked document is output. It was previously bare text with no surface at
   all, which made it ambiguous next to the textarea it had just come from. */
.doc-body{
  background:var(--rail);
  border:1px solid var(--line2);
  border-left:3px solid var(--prod);
  border-radius:0 var(--r-s) var(--r-s) 0;
  padding:var(--sp-3);
  cursor:default
}
.flag-quote{box-shadow:none;cursor:default}
.env{cursor:default}

/* ---- The word that goes with the treatment ---- */
.tag{
  display:inline-flex;align-items:center;gap:4px;font:700 9.5px var(--ui);letter-spacing:.06em;
  text-transform:uppercase;padding:2px 6px;border-radius:var(--r-s);white-space:nowrap;vertical-align:middle
}
.tag svg{width:10px;height:10px}
.tag-in{background:var(--act-t);color:var(--act)}
.tag-out{background:var(--gry-t);color:var(--mid)}
.tag-locked{background:var(--amb-t);color:var(--amb-on-tint)}

.io-head{display:flex;align-items:center;gap:var(--sp-2);flex-wrap:wrap;margin-bottom:5px}
.io-head .lbl{margin-bottom:0}

/* ---- The three switches, which the bare label selector had collapsed ---- */
/* Belt and braces. The rule above is now class scoped so this cannot recur, but a
   switch is a control and stating its own layout at full strength costs nothing. */
label.sw{display:flex;text-transform:none;letter-spacing:normal;font:400 var(--t-b) var(--ui);
  color:var(--ink);margin-bottom:0}
.sw-box{box-shadow:var(--sh)}
.sw:hover .sw-box{box-shadow:var(--sh2)}
.sw:active .sw-box::after{transform:scale(.92)}
.sw input:checked + .sw-box::after{transform:translateX(16px)}
.sw:active input:checked + .sw-box::after{transform:translateX(16px) scale(.92)}

/* ==========================================================================
   Errors, V1.1.1.

   Shown twice on purpose. A dialog opens immediately, because an error that
   leaves the screen unchanged is worse than the error. The same error stays in
   a panel on the page afterwards, because a dialog loses its content the moment
   it is dismissed and the detail is often needed later.

   The dialog is an alertdialog rather than a dialog, so assistive technology
   announces it on open. Section 16 asks for role="alert" on an error that
   interrupts, and this is the modal form of that.
   ========================================================================== */

.modal-alert{border-top:4px solid var(--red)}
.modal-alert .modal-head{background:var(--red-t)}
.modal-alert .modal-head h2{color:var(--red)}

.err-meaning{font-size:var(--t-m);margin-bottom:var(--sp-3)}
.err-fault{background:var(--act-t);color:var(--act);border-radius:var(--r-s);
  padding:var(--sp-2) var(--sp-3);font-size:var(--t-s);margin-bottom:var(--sp-3)}
/* What the server actually said, quoted as output rather than paraphrased. */
.err-said{background:var(--rail);border-left:3px solid var(--line);border-radius:0 var(--r-s) var(--r-s) 0;
  padding:var(--sp-2) var(--sp-3);font-size:var(--t-s);color:var(--mid);margin-bottom:var(--sp-3)}
.err-h{font-size:var(--t-m);margin:var(--sp-4) 0 var(--sp-2)}
.err-do{display:flex;flex-direction:column;gap:var(--sp-2);margin-bottom:var(--sp-4)}
.err-do li{position:relative;padding-left:22px}
.err-do li::before{content:"";position:absolute;left:2px;top:7px;width:8px;height:8px;
  border-radius:2px;background:var(--act)}

.err-details{border:1px solid var(--line);border-radius:var(--r-s);background:var(--rail);padding:var(--sp-3)}
.err-details summary{cursor:pointer;font-weight:600;font-size:var(--t-s);color:var(--mid);
  min-height:24px;display:flex;align-items:center;padding:2px}
.err-details summary:hover{color:var(--ink)}
.err-details summary:focus-visible{outline:2px solid var(--act);outline-offset:2px;border-radius:var(--r-s)}
.err-details[open] summary{margin-bottom:var(--sp-3)}
.err-tech{display:flex;flex-direction:column;gap:2px;margin-bottom:var(--sp-3);
  background:var(--surf);border:1px solid var(--line2);border-radius:var(--r-s);padding:var(--sp-2)}
.err-row{display:grid;grid-template-columns:132px 1fr;gap:var(--sp-2);padding:3px 0;align-items:baseline}
.err-k{font:700 10px var(--ui);letter-spacing:.05em;text-transform:uppercase;color:var(--mid)}
.err-v{word-break:break-word;font-size:11.5px}

/* The panel that persists on the page after the dialog is closed. */
.notice-error h3{margin-bottom:var(--sp-1)}
.notice-error .err-said{background:var(--surf);border-left-color:var(--red)}
.notice-error .lnkbtn{color:var(--red);margin-top:var(--sp-2)}
.notice-error .lnkbtn:hover{color:var(--ink)}

@media (max-width:520px){
  .err-row{grid-template-columns:1fr}
  .err-k{margin-top:var(--sp-1)}
}

/* ==========================================================================
   V1.2.0. Availability as a colour, concertinas, and the animated comparison.

   One rule decides every colour below: green is what this instance can do
   today, grey is what it cannot. Nothing is green because it would be nice, or
   because it is the thing being sold. A page that paints the unavailable half
   in the brand colour is an advertisement rather than a description of what
   the person in front of it can actually do.

   Colour is never the only carrier. Every green and every grey is paired with
   a word, and the key under the hero says what the two mean.
   ========================================================================== */

.legend{display:flex;flex-wrap:wrap;gap:var(--sp-2) var(--sp-4);margin-top:var(--sp-3)}
.key{display:inline-flex;align-items:flex-start;gap:6px;font-size:var(--t-s);color:var(--mid);max-width:38ch}
.key-dot{width:10px;height:10px;border-radius:3px;flex:none;margin-top:5px}
.key-on .key-dot{background:var(--prod)}
.key-off .key-dot{background:var(--gry);border:1px dashed var(--soft)}

.dot{width:9px;height:9px;border-radius:3px;flex:none}
.dot-on{background:var(--prod)}
.dot-off{background:var(--gry)}

/* ---------- concertinas ----------
   Native details and summary. Keyboard operable, announced, and it works with
   JavaScript off, which the front door has to. */
.fold{border-top:1px solid var(--line);padding:0}
.fold-sum{
  display:flex;align-items:center;justify-content:space-between;gap:var(--sp-4);
  padding:var(--sp-6) 0;cursor:pointer;list-style:none
}
.fold-sum::-webkit-details-marker{display:none}
.fold-sum:focus-visible{outline:2px solid var(--act);outline-offset:4px;border-radius:var(--r-s)}
.fold-t{display:flex;flex-direction:column;gap:var(--sp-1);min-width:0}
.fold-t h2{margin:0}
.fold-s{font-size:var(--t-s);color:var(--mid)}
.fold-mark{
  width:32px;height:32px;flex:none;border-radius:var(--r-full);background:var(--gry-t);
  position:relative;transition:background var(--m-state),transform var(--m-panel) var(--ease-panel)
}
.fold-mark::before,.fold-mark::after{
  content:"";position:absolute;top:50%;left:50%;background:var(--mid);border-radius:2px;
  transform:translate(-50%,-50%);transition:transform var(--m-panel) var(--ease-panel),opacity var(--m-state)
}
.fold-mark::before{width:13px;height:2px}
.fold-mark::after{width:2px;height:13px}
.fold-sum:hover .fold-mark{background:var(--line)}
.fold[open] .fold-mark::after{transform:translate(-50%,-50%) rotate(90deg);opacity:0}
.fold[open] .fold-sum{padding-bottom:var(--sp-4)}
.fold-body{padding-bottom:var(--sp-7)}
.fold-body > .band-lede{margin-top:0}

/* Animating a details panel needs interpolate-size, which is recent. Where it is not
   supported the panel simply appears, which is correct behaviour rather than a fallback. */
@supports (interpolate-size: allow-keywords){
  :root{interpolate-size:allow-keywords}
  .fold::details-content{
    block-size:0;overflow:clip;opacity:0;
    transition:block-size var(--m-panel) var(--ease-panel),opacity var(--m-panel),content-visibility var(--m-panel) allow-discrete;
  }
  .fold[open]::details-content{block-size:auto;opacity:1}
}

/* ---------- FAQ ---------- */
.faq-item{border-bottom:1px solid var(--line2)}
.faq-item:first-of-type{border-top:1px solid var(--line2)}
.faq-q{
  display:flex;align-items:flex-start;gap:var(--sp-3);padding:var(--sp-4) 0;cursor:pointer;
  font-family:var(--disp);font-size:var(--t-m);font-weight:600;list-style:none;color:var(--ink)
}
.faq-q::-webkit-details-marker{display:none}
.faq-q:hover{color:var(--act)}
.faq-q:focus-visible{outline:2px solid var(--act);outline-offset:2px;border-radius:var(--r-s)}
.faq-mark{
  width:20px;height:20px;flex:none;margin-top:2px;border-radius:var(--r-s);
  position:relative;background:var(--prod-t);transition:background var(--m-state)
}
.faq-off .faq-mark{background:var(--gry-t)}
.faq-mark::before,.faq-mark::after{
  content:"";position:absolute;top:50%;left:50%;background:var(--prod);border-radius:1px;
  transform:translate(-50%,-50%);transition:transform var(--m-panel) var(--ease-panel),opacity var(--m-state)
}
.faq-off .faq-mark::before,.faq-off .faq-mark::after{background:var(--mid)}
.faq-mark::before{width:9px;height:2px}
.faq-mark::after{width:2px;height:9px}
.faq-item[open] .faq-mark::after{transform:translate(-50%,-50%) rotate(90deg);opacity:0}
.faq-a{padding:0 0 var(--sp-4) calc(20px + var(--sp-3))}
.faq-a p{color:var(--mid);max-width:82ch}
@supports (interpolate-size: allow-keywords){
  .faq-item::details-content{
    block-size:0;overflow:clip;opacity:0;
    transition:block-size var(--m-panel) var(--ease-panel),opacity var(--m-panel),content-visibility var(--m-panel) allow-discrete;
  }
  .faq-item[open]::details-content{block-size:auto;opacity:1}
}

/* ==========================================================================
   The animated comparison.

   It is reinforcement, never the only telling. The same sequence is written
   out underneath as a numbered list and narrated through a live region, so the
   information does not depend on seeing it move. It stops entirely under
   prefers-reduced-motion and under the motion toggle, and it has its own
   pause control because an animation that runs forever with no way to stop it
   fails 2.2.2 regardless of what the operating system says.
   ========================================================================== */

.band-first{border-top:none;padding-top:0}
.demo{background:var(--surf);border:1px solid var(--line);border-radius:var(--r-m);box-shadow:var(--sh2);padding:var(--sp-5)}
.demo-head{display:flex;align-items:center;justify-content:space-between;gap:var(--sp-3);flex-wrap:wrap;margin-bottom:var(--sp-5)}
.demo .seg button{display:inline-flex;align-items:center;gap:7px}

.stage{
  position:relative;display:grid;grid-template-columns:1fr auto 1fr;gap:var(--sp-4);
  align-items:stretch;min-height:170px;padding:var(--sp-4) 0
}
.lane{border:2px solid var(--line);border-radius:var(--r-m);padding:var(--sp-3);background:var(--rail);transition:border-color var(--m-panel),background var(--m-panel)}
.lane-in{border-color:var(--prod);background:var(--prod-t)}
.lane-out{border-style:dashed}
.lane-label{font:700 10px var(--ui);letter-spacing:.06em;text-transform:uppercase;color:var(--mid);margin-bottom:var(--sp-2)}
.lane-in .lane-label{color:var(--prod)}
.lane-body{display:flex;flex-direction:column;gap:var(--sp-2)}
.chipnode{
  display:inline-flex;align-items:center;gap:7px;background:var(--surf);border:1px solid var(--line);
  border-radius:var(--r-s);padding:7px 10px;font-size:var(--t-s);font-weight:500;box-shadow:var(--sh);
  transition:opacity var(--m-panel),border-color var(--m-panel),transform var(--m-panel) var(--ease-panel)
}
.chipnode .i{color:var(--soft)}
.n-pol{opacity:.35}
.demo[data-mode="internal"] .n-pol{opacity:1;border-color:var(--gry);border-style:dashed}
.demo[data-mode="external"] .n-doc .i{color:var(--prod)}
.demo[data-mode="external"] .n-doc{border-color:var(--prod)}

/* The boundary itself */
.wall{position:relative;width:92px;display:grid;place-items:center}
.wall-line{
  position:absolute;top:0;bottom:0;left:50%;width:3px;transform:translateX(-50%);border-radius:2px;
  background:repeating-linear-gradient(180deg,var(--prod) 0 8px,transparent 8px 16px);
  transition:background var(--m-panel)
}
.demo[data-mode="internal"] .wall-line{background:repeating-linear-gradient(180deg,var(--red) 0 8px,transparent 8px 16px)}
.wall-label{
  position:absolute;top:50%;left:50%;transform:translate(-50%,-50%) rotate(-90deg);white-space:nowrap;
  font:700 9.5px var(--ui);letter-spacing:.06em;text-transform:uppercase;color:var(--mid);
  background:var(--surf);padding:3px 6px
}
.wall-block{
  position:absolute;top:50%;left:50%;transform:translate(-50%,-50%) scale(0);
  width:34px;height:34px;border-radius:var(--r-full);background:var(--red);color:#fff;
  display:grid;place-items:center;box-shadow:var(--sh2);z-index:2;
  transition:transform var(--m-panel) var(--ease-panel)
}
.demo[data-mode="internal"][data-step="2"] .wall-block,
.demo[data-mode="internal"][data-step="3"] .wall-block{transform:translate(-50%,-50%) scale(1)}
/* The block sits where the label is, so the label gets out of its way. The boundary is
   still named by the dashed line and by the sentence underneath. */
.wall-label{transition:opacity var(--m-state)}
.demo[data-mode="internal"][data-step="2"] .wall-label,
.demo[data-mode="internal"][data-step="3"] .wall-label{opacity:0}

/* Internal is the path this instance cannot take, so its lane carries the grey rather
   than the green. Availability is the same colour pair everywhere in this product. */
.demo[data-mode="internal"] .lane-in{border-color:var(--gry);background:var(--gry-t)}
.demo[data-mode="internal"] .lane-in .lane-label{color:var(--mid)}

/* The travelling document */
.packet{
  position:absolute;top:50%;left:14%;width:34px;height:34px;border-radius:var(--r-s);
  background:var(--prod);color:#fff;display:grid;place-items:center;box-shadow:var(--sh2);z-index:3;
  opacity:0;transform:translate(-50%,-50%) scale(.6);
  transition:left .9s var(--ease-panel),opacity var(--m-panel),transform var(--m-panel) var(--ease-panel),background var(--m-panel)
}
.demo[data-step="1"] .packet,.demo[data-step="2"] .packet,
.demo[data-step="3"] .packet,.demo[data-step="4"] .packet{opacity:1;transform:translate(-50%,-50%) scale(1)}
.demo[data-mode="external"][data-step="2"] .packet{left:50%}
.demo[data-mode="external"][data-step="3"] .packet{left:86%}
.demo[data-mode="external"][data-step="4"] .packet{left:86%;opacity:.25}
.demo[data-mode="internal"] .packet{background:var(--gry)}
.demo[data-mode="internal"][data-step="2"] .packet{left:41%}
.demo[data-mode="internal"][data-step="3"] .packet{left:41%;transform:translate(-50%,-50%) scale(.86) rotate(-8deg)}

/* What comes back */
.flagback{
  position:absolute;top:50%;right:2%;transform:translateY(-50%) translateX(14px);opacity:0;
  display:inline-flex;align-items:center;gap:6px;background:var(--surf);border:1px solid var(--prod);
  border-radius:var(--r-s);padding:6px 9px;font-family:var(--mono);font-size:11px;color:var(--prod);
  font-weight:600;box-shadow:var(--sh2);z-index:4;
  transition:opacity var(--m-panel),transform var(--m-panel) var(--ease-panel)
}
.demo[data-mode="external"][data-step="4"] .flagback{opacity:1;transform:translateY(-50%) translateX(0)}

.demo-say{
  margin-top:var(--sp-4);padding:var(--sp-3) var(--sp-4);border-radius:var(--r-s);
  background:var(--prod-t);color:var(--ink);font-size:var(--t-m);min-height:52px;
  border-left:3px solid var(--prod)
}
.demo[data-mode="internal"] .demo-say{background:var(--gry-t);border-left-color:var(--gry)}

.demo-steps{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(190px,100%),1fr));gap:var(--sp-2);margin-top:var(--sp-4)}
.demo-steps li{
  display:flex;gap:var(--sp-2);align-items:flex-start;padding:var(--sp-2) var(--sp-3);border-radius:var(--r-s);
  background:var(--rail);font-size:var(--t-s);color:var(--mid);transition:background var(--m-state),color var(--m-state)
}
.demo-steps li.on{background:var(--prod-t);color:var(--ink)}
.demo[data-mode="internal"] .demo-steps li.on{background:var(--gry-t)}
.demo-steps .n{
  width:19px;height:19px;flex:none;border-radius:var(--r-full);background:var(--line);color:var(--mid);
  display:grid;place-items:center;font-size:10px;font-weight:700;margin-top:1px
}
.demo-steps li.on .n{background:var(--prod);color:#fff}
.demo[data-mode="internal"] .demo-steps li.on .n{background:var(--mid);color:#fff}

@media (max-width:720px){
  .stage{grid-template-columns:minmax(0,1fr);min-height:0;gap:var(--sp-3)}
  .wall{width:auto;height:52px}
  .wall-line{top:50%;bottom:auto;left:0;right:0;width:auto;height:3px;transform:translateY(-50%);
    background:repeating-linear-gradient(90deg,var(--prod) 0 8px,transparent 8px 16px)}
  .demo[data-mode="internal"] .wall-line{background:repeating-linear-gradient(90deg,var(--red) 0 8px,transparent 8px 16px)}
  .wall-label{transform:translate(-50%,-50%)}
  /* The packet travels top to bottom on a narrow screen, so it stops moving sideways. */
  .packet,.flagback{display:none}
}
