/* main.css — layout and components. */
  /* connector line drawn from the dot toward the frame */

  /* ================= stage ================= */
  .stage{position:fixed;inset:var(--gap);z-index:1}

  /* the content frame: chamfered on all four corners */
  .frame{position:absolute;inset:0;background:var(--panel);overflow:hidden;
    clip-path:polygon(
      var(--n) 0, calc(100% - var(--n)) 0, 100% var(--n),
      100% calc(100% - var(--n)), calc(100% - var(--n)) 100%,
      var(--n) 100%, 0 calc(100% - var(--n)), 0 var(--n))}
  .frame::before{content:"";position:absolute;inset:0;pointer-events:none;z-index:1;
    background:radial-gradient(58% 46% at 50% 42%, rgba(94,234,212,.06), transparent 70%)}

  /* decoration layer sits slightly outside the frame */
  .deco{position:absolute;inset:-14px;z-index:4;pointer-events:none}
  .deco .cnr{position:absolute;display:block;filter:drop-shadow(0 0 4px var(--hud-glow))}
  .deco .cnr.tl{top:0;left:0}
  .deco .cnr.tr{top:0;right:0;transform:scaleX(-1)}
  .deco .cnr.bl{bottom:0;left:0;transform:scaleY(-1)}
  .deco .cnr.br{bottom:0;right:0;transform:scale(-1,-1)}

  /* straight runs between the corners */
  .ln{position:absolute;background:var(--hud);box-shadow:0 0 5px var(--hud-glow);opacity:.85}
  .ln.h{height:1px;left:170px;right:170px}
  .ln.v{width:1px;top:154px;bottom:154px}
  .ln.t{top:14px}.ln.b{bottom:14px}.ln.l{left:14px}.ln.r{right:14px}
  /* dim outer run */
  .ln.out{opacity:.3;box-shadow:none}
  .ln.h.out{left:150px;right:150px}
  .ln.v.out{top:134px;bottom:134px}
  .ln.t.out{top:5px}.ln.b.out{bottom:5px}.ln.l.out{left:5px}.ln.r.out{right:5px}

  /* hatch blocks on the edges */
  .hatch{position:absolute;height:7px;opacity:.85;
    background:repeating-linear-gradient(112deg,var(--hud) 0 1px,transparent 1px 6px)}
  .hatch.a{top:8px;left:210px;width:96px}
  .hatch.b{top:8px;right:238px;width:64px}
  .hatch.c{bottom:8px;left:250px;width:70px}
  .hatch.d{bottom:8px;right:200px;width:104px}

  /* label plate */
  .plate{position:absolute;top:9px;left:calc(50% - 116px);z-index:7;
    display:flex;align-items:center;gap:9px;padding:4px 20px;
    font-family:"JetBrains Mono",monospace;font-size:.62rem;letter-spacing:.24em;
    color:var(--hud);background:#0a1219;border:1px solid var(--hud-dim);border-top:0;
    clip-path:polygon(13px 0,calc(100% - 13px) 0,100% 100%,0 100%)}
  .plate i{width:5px;height:5px;background:var(--alert);border-radius:50%;
    box-shadow:0 0 7px var(--alert);animation:pulse 3.8s cubic-bezier(.45,0,.55,1) infinite}

  /* ================= rail ================= */
  .rail{position:absolute;left:16px;top:50%;translate:0 -50%;z-index:8;--n:12px;
    padding:1px;background:var(--hud-dim);
    clip-path:polygon(var(--n) 0,100% 0,100% calc(100% - var(--n)),calc(100% - var(--n)) 100%,0 100%,0 var(--n))}
  .rail .fill{--n:12px;background:rgba(8,13,19,.92);padding:8px 6px;
    display:flex;flex-direction:column;gap:5px;
    clip-path:polygon(calc(var(--n) - 1px) 0,100% 0,100% calc(100% - var(--n) + 1px),calc(100% - var(--n) + 1px) 100%,0 100%,0 calc(var(--n) - 1px))}
  .rail a{display:grid;place-items:center;width:34px;height:34px;color:var(--faint);
    text-decoration:none;transition:color .18s,background-color .18s;
    clip-path:polygon(7px 0,100% 0,100% calc(100% - 7px),calc(100% - 7px) 100%,0 100%,0 7px)}
  .rail a:hover{color:var(--hover);background:var(--hover-wash)}
  .rail a.on{color:var(--alert);background:rgba(251,113,133,.14)}
  .rail svg{width:16px;height:16px}

  .prog{position:absolute;right:18px;top:50%;translate:0 -50%;z-index:8;
    display:flex;flex-direction:column;align-items:center;gap:9px}
  .prog i{display:block;width:3px;height:15px;background:var(--line);
    transition:background-color .2s,height .2s,box-shadow .2s}
  .prog i.on{background:var(--alert);height:27px;box-shadow:0 0 7px var(--alert-dim)}
  .prog b{font-family:"JetBrains Mono",monospace;font-size:.55rem;color:var(--faint);
    writing-mode:vertical-rl;letter-spacing:.2em;font-weight:400;margin-top:4px}

  /* ================= deck ================= */
  .deck{position:absolute;inset:0;z-index:2;overflow-y:scroll;
    scroll-snap-type:y mandatory;padding-left:var(--rail)}
  .card{position:relative;height:100%;scroll-snap-align:start;scroll-snap-stop:always;
    display:flex;align-items:center;padding:var(--s7) var(--s7) var(--s7) var(--s5);overflow:hidden}
  .card-inner{width:100%;max-width:min(64rem,64vw);margin-inline:auto;max-height:100%;overflow-y:auto}
  .card-tag{position:absolute;top:26px;right:58px;z-index:3;
    font-family:"JetBrains Mono",monospace;font-size:.64rem;letter-spacing:.2em;color:var(--faint)}

  .js-anim [data-anim]{opacity:0;transform:translateY(14px)}
  .js-anim .card.in [data-anim]{animation:rise .55s cubic-bezier(.22,.8,.3,1) forwards;
    animation-delay:calc(var(--i,0) * 85ms)}
  @keyframes rise{to{opacity:1;transform:none}}

  /* ================= type & panels ================= */
  .eyebrow{font-family:"JetBrains Mono",monospace;font-size:.68rem;letter-spacing:.2em;
    text-transform:uppercase;color:var(--hud);margin:0 0 var(--s3)}
  .eyebrow::before{content:"▸ ";opacity:.7}
  h1{font-family:"Space Grotesk",system-ui,sans-serif;font-size:2.9rem;font-weight:700;
    letter-spacing:-.03em;line-height:1.04;margin:0 0 .45rem}
  h2{font-family:"Space Grotesk",system-ui,sans-serif;font-size:2.1rem;font-weight:700;
    letter-spacing:-.025em;margin:0 0 .3rem}
  .sub{font-family:"JetBrains Mono",monospace;font-size:.7rem;color:var(--faint);
    letter-spacing:.16em;margin:0 0 var(--s5)}
  .role{font-size:1.15rem;color:var(--mut);margin:0 0 var(--s4)}
  .role b{color:var(--hud);font-weight:500}
  p{color:var(--mut);margin:0}
  .lede{max-width:50ch;margin-bottom:var(--s5)}
  .prose{display:flex;flex-direction:column;gap:var(--s4)}
  .acts{display:flex;gap:var(--s3);flex-wrap:wrap}
  .btn{--n:9px;display:inline-block;font-family:"JetBrains Mono",monospace;font-size:.72rem;
    letter-spacing:.1em;text-transform:uppercase;font-weight:500;padding:.65rem 1.25rem;
    text-decoration:none;cursor:pointer;color:#07100f;background:var(--hud);border:0;
    clip-path:polygon(var(--n) 0,100% 0,100% calc(100% - var(--n)),calc(100% - var(--n)) 100%,0 100%,0 var(--n));
    transition:background-color .18s,color .18s,box-shadow .18s}
  .btn:hover{background:var(--hover);color:var(--on-hover);text-decoration:none}

  /* the ghost button keeps the house colour on purpose: it is the one
     control that should still read as teal when the pointer is on it */
  .btn.ghost{background:transparent;color:var(--hud);box-shadow:inset 0 0 0 1px var(--hud-dim)}
  .btn.ghost:hover{background:rgba(94,234,212,.10);color:var(--hud);
    box-shadow:inset 0 0 0 1px var(--hud);text-decoration:none}
  .split{display:grid;grid-template-columns:1fr .92fr;gap:var(--s7);align-items:center}
  .panel{--n:14px;padding:1px;background:var(--hud-dim)}
  .panel,.panel > .fill{clip-path:polygon(var(--n) 0,100% 0,100% calc(100% - var(--n)),calc(100% - var(--n)) 100%,0 100%,0 var(--n))}
  .panel > .fill{background:var(--panel2)}
  .p-head{display:flex;justify-content:space-between;align-items:center;gap:var(--s3);
    padding:.55rem var(--s4);border-bottom:1px solid var(--line);
    font-family:"JetBrains Mono",monospace;font-size:.64rem;letter-spacing:.14em;color:var(--faint)}
  .rows{margin:0}
  .rrow{display:flex;justify-content:space-between;gap:var(--s4);padding:.6rem var(--s4);
    border-bottom:1px solid rgba(31,44,56,.7);font-size:.84rem}
  .rrow:last-child{border-bottom:0}
  .rrow dt{font-family:"JetBrains Mono",monospace;font-size:.68rem;color:var(--faint);letter-spacing:.08em}
  .rrow dd{margin:0;text-align:right;color:var(--txt)}
  .pill{font-family:"JetBrains Mono",monospace;font-size:.62rem;letter-spacing:.12em;
    padding:3px 9px;color:var(--hud);background:rgba(94,234,212,.1);
    box-shadow:inset 0 0 0 1px rgba(94,234,212,.32);
    clip-path:polygon(6px 0,100% 0,100% calc(100% - 6px),calc(100% - 6px) 100%,0 100%,0 6px)}
  .label{font-family:"JetBrains Mono",monospace;font-size:.66rem;letter-spacing:.2em;
    text-transform:uppercase;color:var(--faint);margin:var(--s6) 0 var(--s4)}
  .label::before{content:"// "}
  .caps{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:var(--s3);list-style:none;padding:0;margin:0}
  .caps li{--n:10px;padding:1px;background:var(--line);transition:background-color .2s}
  .caps li,.caps li > .fill{clip-path:polygon(var(--n) 0,100% 0,100% calc(100% - var(--n)),calc(100% - var(--n)) 100%,0 100%,0 var(--n))}
  .caps li > .fill{background:var(--panel2);padding:var(--s4);height:100%}
  .caps li:hover{background:var(--hover-dim)}
  .caps h3{margin:0 0 .25rem;font-family:"Space Grotesk",system-ui,sans-serif;font-size:.9rem}
  .caps p{font-size:.79rem;line-height:1.5}
  .meta{font-family:"JetBrains Mono",monospace;font-size:.68rem;color:var(--faint);
    letter-spacing:.08em;margin-bottom:var(--s4)}
  .tags{display:flex;flex-wrap:wrap;gap:.45rem;list-style:none;padding:0;margin:var(--s4) 0}
  .tags li{font-family:"JetBrains Mono",monospace;font-size:.66rem;color:var(--mut);
    padding:4px 9px;background:rgba(16,26,36,.9);box-shadow:inset 0 0 0 1px var(--line);
    clip-path:polygon(6px 0,100% 0,100% calc(100% - 6px),calc(100% - 6px) 100%,0 100%,0 6px)}
  .more{color:var(--hud);text-decoration:none;transition:color .18s;font-family:"JetBrains Mono",monospace;
    font-size:.72rem;letter-spacing:.1em;text-transform:uppercase}
  .shot{--n:14px;padding:1px;background:var(--hud-dim);margin:0}
  .shot,.shot > .fill{clip-path:polygon(var(--n) 0,100% 0,100% calc(100% - var(--n)),calc(100% - var(--n)) 100%,0 100%,0 var(--n))}
  .shot > .fill{background:var(--panel)}
  .shot-bar{display:flex;align-items:center;gap:7px;padding:.5rem var(--s4);
    border-bottom:1px solid var(--line);font-family:"JetBrains Mono",monospace;
    font-size:.62rem;letter-spacing:.12em;color:var(--faint)}
  .shot-bar em{font-style:normal;color:var(--hud);opacity:.85}
  .shot-body{min-height:11rem;display:grid;place-items:center;padding:var(--s6) var(--s5);
    background:repeating-linear-gradient(45deg,rgba(94,234,212,.028) 0 7px,transparent 7px 14px)}
  .shot-body span{font-family:"JetBrains Mono",monospace;font-size:.68rem;color:var(--faint);
    text-align:center;line-height:1.95;letter-spacing:.04em}
  .shot-body span em{font-style:normal;color:var(--hud);display:block;margin-bottom:.4rem;opacity:.85}
  .links{list-style:none;padding:0;margin:var(--s4) 0 0;display:flex;flex-direction:column;gap:.45rem}
  .links a{font-family:"JetBrains Mono",monospace;font-size:.8rem;color:var(--hud);text-decoration:none}
  .links a:hover{color:var(--hover);text-decoration:underline;text-underline-offset:4px}
  .field{display:flex;flex-direction:column;gap:.45rem;margin-bottom:var(--s4)}
  .foot{display:flex;justify-content:space-between;gap:var(--s4);flex-wrap:wrap;
    color:var(--faint);font-family:"JetBrains Mono",monospace;font-size:.66rem;letter-spacing:.1em;
    margin-top:var(--s5);padding-top:var(--s4);border-top:1px solid var(--line)}


  /* ================= project cards ================= */
  /* ---- ONE attribute drives every difference between states ---- */
  .hc-wrap{--seg:var(--alert);--seg-glow:var(--alert-dim);--st:var(--line);--st-hi:var(--line-hi);--st-glow:transparent;--beam:.07;--thumb:.42;--lift:-2px}
  .hc-wrap[data-status="active"]  {--st:var(--alert);  --st-hi:var(--alert-hi);--st-glow:var(--alert-dim);       --beam:.26;--thumb:1;  --lift:-4px}
  .hc-wrap[data-status="complete"]{--seg:var(--hud);--seg-glow:var(--hud-glow);--st:var(--hud-dim);--st-hi:var(--hud);--st-glow:rgba(94,234,212,.32);   --beam:.16;--thumb:.9; --lift:-3px}

  .hc-wrap::after{background:radial-gradient(52% 100% at 50% 0%, var(--st-glow), transparent 74%);
    opacity:var(--beam)}
  .hc-wrap:hover::after{opacity:calc(var(--beam) + .34)}
  .hc{background:var(--st)}
  .hc::after{background:var(--st);box-shadow:0 0 9px var(--st-glow)}
  .hc-thumb{opacity:var(--thumb)}
  /* rose now MEANS "in progress", so it can't double as the hover colour —
     a hovered complete card would have read as active. Each card brightens
     its own --st instead, which keeps the status legible while hovered. */
  .hc-wrap:hover .hc{background:var(--st-hi);transform:translateY(var(--lift))}
  .hc-wrap[data-status="scheduled"] h3{color:var(--mut)}

  /* pill colour follows the status; the WORD stays in the html */
  [data-status="active"]   .hc-top .pill{color:var(--alert);background:rgba(251,113,133,.1);
    box-shadow:inset 0 0 0 1px var(--alert-dim)}
  [data-status="scheduled"] .hc-top .pill{color:var(--faint);background:transparent;
    box-shadow:inset 0 0 0 1px var(--line)}
  [data-status="active"] .tk-top .pill{color:var(--alert);background:rgba(251,113,133,.1);
    box-shadow:inset 0 0 0 1px var(--alert-dim)}
  [data-status="complete"] .hc-top .pill{color:var(--hud);background:rgba(94,234,212,.1);
    box-shadow:inset 0 0 0 1px rgba(94,234,212,.32)}

  /* footer swaps itself */
  .hc .more,.hc .soon{display:none}
  [data-status="active"] .more,[data-status="complete"] .more{display:inline-flex}
  [data-status="scheduled"] .soon{display:inline-flex}

  /* progress: one number, no per-segment classes */
  [data-progress="1"] .segbar i:nth-child(-n+1),
  [data-progress="2"] .segbar i:nth-child(-n+2),
  [data-progress="3"] .segbar i:nth-child(-n+3),
  [data-progress="4"] .segbar i:nth-child(-n+4),
  [data-progress="5"] .segbar i:nth-child(-n+5),
  [data-progress="6"] .segbar i:nth-child(-n+6){background:var(--seg);box-shadow:0 0 6px var(--seg-glow)}


  /* ---- travelling edge light, active cards only ----
     a big conic-gradient disc spins *behind* the fill; because the fill is
     opaque and inset by 1px, the only place the disc shows is the border ring,
     and the card's clip-path bends that ring around the chamfers for free. */
  .hc > .fill{position:relative;z-index:1}
  /* base ring goes quieter on the active card so the travelling light reads */


  .grid3{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:var(--s5);align-items:stretch}

  /* work fits its screen: nothing stretches, the thumb has a real aspect ratio */
  #work .card-inner{max-width:min(96rem,84vw);overflow:visible}
  #work .hc-thumb{flex:none;aspect-ratio:16/9;min-height:0}
  #work .hc-body{flex:none}
  @media (max-height:820px){ #work .hc-thumb{aspect-ratio:16/9} #work .hc p{display:none} }

  /* wrapper is unclipped, so the beam underneath can escape the card shape */
  .hc-wrap{position:relative;display:flex}
  /* geometry only — the colour and opacity of the beam come from --st-glow and
     --beam in the state block above. Repeating them here overrode the status. */
  .hc-wrap::after{content:"";position:absolute;left:14%;right:14%;bottom:-18px;height:28px;
    transition:opacity .25s,background .25s;pointer-events:none}

  /* likewise: no background here, or every card's border becomes the same colour */
  .hc{position:relative;padding:1px;flex:1;
    transition:background-color .22s,transform .22s,filter .22s}
  .hc-wrap:hover .hc{filter:drop-shadow(0 0 11px var(--st-glow))}
  .hc,.hc > .fill{
    clip-path:polygon(18px 0,calc(100% - 32px) 0,100% 28px,100% 100%,32px 100%,0 calc(100% - 28px),0 18px)}
  .hc.v2,.hc.v2 > .fill{
    clip-path:polygon(0 0,calc(100% - 18px) 0,100% 18px,100% calc(100% - 30px),calc(100% - 30px) 100%,0 100%)}
  .hc.v3,.hc.v3 > .fill{
    clip-path:polygon(26px 0,100% 0,100% calc(100% - 18px),calc(100% - 18px) 100%,0 100%,0 26px)}
  .hc > .fill{background:var(--panel2);height:100%;display:flex;flex-direction:column}

  /* second outline: a 1px ring 7px inside the first, same chamfered shape.
     clip-path can't carry a border, so the ring is cut out of a solid block
     with two masks composited to leave only the 1px padding band. */
  .edge2{position:absolute;inset:7px;z-index:3;pointer-events:none;
    background:var(--st);opacity:.45;padding:1px;
    -webkit-mask:linear-gradient(#000 0 0) content-box,linear-gradient(#000 0 0);
            mask:linear-gradient(#000 0 0) content-box,linear-gradient(#000 0 0);
    -webkit-mask-composite:xor;mask-composite:exclude;
    transition:opacity .22s}
  .hc-wrap:hover .edge2{opacity:.8}
  .hc .edge2{clip-path:polygon(14px 0,calc(100% - 28px) 0,100% 24px,100% 100%,28px 100%,0 calc(100% - 24px),0 14px)}
  .hc.v2 .edge2{clip-path:polygon(0 0,calc(100% - 14px) 0,100% 14px,100% calc(100% - 26px),calc(100% - 26px) 100%,0 100%)}
  .hc.v3 .edge2{clip-path:polygon(22px 0,100% 0,100% calc(100% - 14px),calc(100% - 14px) 100%,0 100%,0 22px)}
  .hc.v4,.hc.v4 > .fill{
    clip-path:polygon(0 0,100% 0,100% calc(100% - 26px),calc(100% - 26px) 100%,20px 100%,0 calc(100% - 20px))}
  .hc.v4 .edge2{clip-path:polygon(0 0,100% 0,100% calc(100% - 22px),calc(100% - 22px) 100%,16px 100%,0 calc(100% - 16px))}
  .hc.v4::after{left:auto;right:0;top:auto;bottom:20%;height:26%}
  .hc-wrap:not([data-status="active"]):hover .hc.v4::after{bottom:14%}

  /* ---------------- training tracks ---------------- */
  #training .card-inner{max-width:min(76rem,72vw);overflow:visible}
  /* ---------- about: capabilities + skills, side by side ---------- */
  .about-grid{display:grid;grid-template-columns:1fr 1fr;gap:var(--s5);
    margin-top:var(--s4);align-items:start}
  #about .caps{grid-template-columns:repeat(2,minmax(0,1fr))}
  .skills{display:flex;flex-direction:column;gap:.55rem;margin:0;padding:0;list-style:none}
  .skills > li{display:grid;grid-template-columns:5.4rem 1fr;gap:.6rem;align-items:baseline}
  .skills .k{font-family:"JetBrains Mono",monospace;font-size:.58rem;letter-spacing:.16em;
    text-transform:uppercase;color:var(--faint);padding-top:.22rem}
  .skills .v{display:flex;flex-wrap:wrap;gap:.3rem}
  .skills .v span{font-family:"JetBrains Mono",monospace;font-size:.62rem;letter-spacing:.04em;
    color:var(--mut);padding:3px 7px;background:var(--panel2);
    box-shadow:inset 0 0 0 1px var(--line);
    clip-path:polygon(5px 0,100% 0,100% calc(100% - 5px),calc(100% - 5px) 100%,0 100%,0 5px);
    transition:box-shadow .18s,color .18s}
  .skills .v span:hover{color:var(--txt);box-shadow:inset 0 0 0 1px var(--hover-dim)}

  .tracks{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--s5);
    list-style:none;padding:0;margin:var(--s5) 0 0;align-items:stretch}
  .tk-wrap{position:relative;display:flex;--st:var(--hud-dim);--st-hi:var(--hud);--st-glow:rgba(94,234,212,.32)}
  /* the in-progress track is rose: the same "this one is live" signal the
     in-progress project card gives with its pill and progress bar. */
  .tk-wrap[data-status="active"]{--st:var(--alert);--st-hi:var(--alert-hi);--st-glow:var(--alert-dim)}
  .tk{position:relative;padding:1px;background:var(--st);flex:1;
    transition:background-color .22s,transform .22s,filter .22s}
  .tk-wrap:hover .tk{background:var(--st-hi);transform:translateY(-3px);
    filter:drop-shadow(0 0 10px var(--st-glow))}
  .tk,.tk > .fill{clip-path:polygon(20px 0,100% 0,100% calc(100% - 20px),calc(100% - 20px) 100%,0 100%,0 20px)}
  .tk > .fill{background:var(--panel2);padding:.85rem 1rem 1rem;display:flex;flex-direction:column;
    gap:.45rem;height:100%}
  .tk .edge2{clip-path:polygon(16px 0,100% 0,100% calc(100% - 16px),calc(100% - 16px) 100%,0 100%,0 16px)}
  .tk::after{content:"";position:absolute;width:4px;background:var(--st);
    box-shadow:0 0 9px var(--st-glow);z-index:2;left:0;top:28%;height:22%;
    transition:height .25s,top .25s}
  .tk-wrap:not([data-status="active"]):hover .tk::after{height:44%}
  .tk-wrap[data-status="active"] .tk::after{
    top:0;bottom:auto;animation:shuttle 3.2s cubic-bezier(.45,0,.55,1) infinite}
  @media (prefers-reduced-motion:reduce){
    .tk-wrap[data-status="active"] .tk::after{animation:none;top:28%;height:22%}}

  .tk-top{display:flex;align-items:center;justify-content:space-between;gap:.5rem;
    padding-bottom:.45rem;border-bottom:1px solid var(--line)}
  .tk-id{font-family:"JetBrains Mono",monospace;font-size:.58rem;letter-spacing:.18em;color:var(--faint)}
  .tk h3{margin:.1rem 0 .1rem;font-family:"Space Grotesk",system-ui,sans-serif;
    font-size:.98rem;letter-spacing:-.01em}
  .crs{list-style:none;padding:0;margin:0;display:flex;flex-direction:column;gap:.32rem}
  .crs li{display:flex;align-items:baseline;gap:.5rem;font-size:.74rem;color:var(--mut);line-height:1.35}
  .crs .nm{flex:1}
  .crs .pv{font-family:"JetBrains Mono",monospace;font-size:.56rem;letter-spacing:.06em;
    color:var(--faint);text-align:right;flex:none;max-width:44%}
  .crs .st{width:6px;height:6px;border-radius:50%;background:var(--hud);
    box-shadow:0 0 5px var(--hud-glow);flex:none;align-self:center}
  .crs .st.now{background:var(--alert);box-shadow:0 0 7px var(--alert);
    animation:pulse 3.4s cubic-bezier(.45,0,.55,1) infinite;will-change:opacity}
  /* A dot that only drops opacity reads as a blink, because its glow stays put
     while the dot fades. Fading the two together — slowly, and not all the way —
     reads as breathing. cubic-bezier(.45,0,.55,1) is a sine curve: no hard stop
     at either end, which is what made the old 1.5s ease-in-out flicker. */
  @keyframes pulse{
    0%,100%{opacity:1;   box-shadow:0 0 7px var(--alert)}
    50%    {opacity:.62; box-shadow:0 0 3px var(--alert-dim)}
  }

  .certs{margin-top:auto;padding-top:.7rem;display:flex;gap:.4rem;flex-wrap:wrap;align-items:center}
  .certs .lbl{font-family:"JetBrains Mono",monospace;font-size:.55rem;letter-spacing:.16em;
    color:var(--faint);text-transform:uppercase;margin-right:.15rem}
  .cert{position:relative;width:3.35rem;aspect-ratio:1.414;flex:none;overflow:hidden;
    background:repeating-linear-gradient(45deg,rgba(94,234,212,.05) 0 6px,transparent 6px 12px);
    box-shadow:inset 0 0 0 1px var(--line);
    clip-path:polygon(6px 0,100% 0,100% calc(100% - 6px),calc(100% - 6px) 100%,0 100%,0 6px);
    display:grid;place-items:center;transition:box-shadow .2s,transform .2s}
  .cert img{width:100%;height:100%;object-fit:cover;display:block;
    filter:grayscale(.2) brightness(.72) contrast(1.05);transition:filter .22s}
  /*.cert:hover img{filter:none}*/
  .tk-wrap:hover .cert:not(.rest){box-shadow:inset 0 0 0 1px var(--hover-dim)}
  .cert:not(.rest):hover{transform:translateY(-2px);box-shadow:inset 0 0 0 1px var(--hover)}
  .certs .cert:nth-of-type(n+6){display:none}
  /* the +N chip is deliberately inert — no hover state at all.
     cursor:zoom-in is left as the only signal that it is clickable. */
  .cert.rest{display:flex;flex-direction:row;align-items:center;justify-content:center;gap:0;
    background:var(--line);box-shadow:inset 0 0 0 1px var(--line);cursor:zoom-in;color:var(--mut)}
  .cert.rest svg{width:20px;height:20px;flex:none;margin-left:-3px}
  .cert.rest b{font-family:"JetBrains Mono",monospace;font-size:.62rem;font-weight:500;
    letter-spacing:.02em;line-height:1}
  .lb-nav{position:absolute;top:50%;transform:translateY(-50%);z-index:4;width:38px;height:56px;
    display:grid;place-items:center;border:1px solid var(--hud-dim);background:var(--panel);
    color:var(--hud);cursor:pointer;font-size:1rem;line-height:1}
  .lb-nav:hover{background:var(--hover);color:var(--bg)}
  .lb-nav.prev{left:-19px} .lb-nav.next{right:-19px}
  .lb-nav[hidden],.lb-meta [hidden]{display:none}
  .lb-count{font-family:"JetBrains Mono",monospace;font-size:.6rem;letter-spacing:.12em;color:var(--faint)}
  a.cert{cursor:zoom-in}
  a.cert::after{content:"";position:absolute;inset:0;
    background:linear-gradient(180deg,transparent 55%,rgba(6,10,15,.55));
    opacity:0;transition:opacity .2s}
  a.cert:hover::after{opacity:1}

  /* ---- certificate lightbox (native <dialog>) ---- */
  .lb{position:relative;border:0;padding:0;background:transparent;max-width:min(92vw,56rem);
    max-height:92vh;color:var(--txt);overflow:visible}
  .lb::backdrop{background:rgba(3,6,10,.86);backdrop-filter:blur(3px)}
  .lb-frame{position:relative;padding:1px;background:var(--hud-dim)}
  .lb-frame,.lb-frame > .fill{
    clip-path:polygon(22px 0,100% 0,100% calc(100% - 22px),calc(100% - 22px) 100%,0 100%,0 22px)}
  .lb-frame > .fill{background:var(--panel2);padding:14px}
  .lb img{display:block;width:100%;height:auto;max-height:72vh;object-fit:contain;background:#fff}
  .lb-meta{display:flex;align-items:center;gap:1rem;justify-content:space-between;
    padding-top:.7rem;font-size:.76rem;color:var(--mut)}
  .lb-note{font-family:"JetBrains Mono",monospace;font-size:.6rem;letter-spacing:.1em;
    text-transform:uppercase;color:var(--faint);white-space:nowrap}
  .lb-meta a{font-family:"JetBrains Mono",monospace;font-size:.66rem;letter-spacing:.1em;
    text-transform:uppercase;white-space:nowrap}
  .lb-x{position:absolute;top:-17px;right:-17px;z-index:4;width:34px;height:34px;
    display:grid;place-items:center;
    border:1px solid var(--hud);background:var(--panel);color:var(--hud);
    font-size:.85rem;line-height:1;cursor:pointer;border-radius:50%;
    box-shadow:0 0 10px rgba(94,234,212,.35)}
  .lb-x:hover{background:var(--hover);color:var(--bg)}

  /* bright side tab */
  /* geometry only — colour and glow come from --st / --st-glow above */
  .hc::after{content:"";position:absolute;width:4px;
    z-index:2;left:0;top:34%;height:24%;
    transition:height .25s,top .25s}
  .hc.v2::after{left:auto;right:0;top:22%;height:30%}
  .hc.v3::after{top:auto;bottom:16%;height:22%}
  .hc-wrap:not([data-status="active"]):hover .hc::after{height:46%}
  .hc-wrap:hover .hc.v3::after{bottom:12%}

  /* active only: the bright side tab shuttles up and down its own edge */
  .hc-wrap[data-status="active"] .hc::after{
    top:0;bottom:auto;animation:shuttle 3.2s cubic-bezier(.45,0,.55,1) infinite}
  @keyframes shuttle{
    0%   {top:6%;  height:16%}
    50%  {top:62%; height:30%}
    100% {top:6%;  height:16%}
  }
  @media (prefers-reduced-motion:reduce){
    .hc-wrap[data-status="active"] .hc::after{animation:none;top:34%;height:24%}
  }

  /* thumbnail area */
  .hc-thumb{position:relative;overflow:hidden;min-height:122px;display:grid;place-items:center;
    border-bottom:1px solid var(--line);
    background:repeating-linear-gradient(45deg,rgba(94,234,212,.03) 0 7px,transparent 7px 14px)}
  .hc-thumb > span{font-family:"JetBrains Mono",monospace;font-size:.6rem;letter-spacing:.1em;
    color:var(--faint);text-align:center;line-height:1.85;z-index:1;padding:0 .6rem}
  /* TBD node — the screenshot slot for a build that does not exist yet.
     A HUD node: circuit traces feeding a segmented ring, drawn once as a
     <symbol> and reused. currentColor, so it follows the slot's colour. */
  .hc-thumb .tbd-ring,.hc-thumb .tbd{grid-area:1/1;align-self:center;justify-self:center}
  .hc-thumb .tbd-ring{width:100%;max-width:19rem;height:auto;color:var(--hud);
    opacity:.58;pointer-events:none}
  .hc-thumb .tbd{position:relative;z-index:1;display:grid;place-items:center;
    color:var(--mut);text-align:center}
  .hc-thumb .tbd b{font-family:"Space Grotesk",system-ui,sans-serif;font-size:1.35rem;
    font-weight:700;letter-spacing:.2em;text-indent:.2em;line-height:1;color:var(--hud)}
  /* the caption hangs below the ring so TBD stays centred in the circle */

  .scan{position:absolute;left:0;right:0;height:2px;top:-8%;z-index:1;opacity:0;
    background:linear-gradient(90deg,transparent,var(--st-hi),transparent)}
  .hc-wrap:hover .scan{opacity:.7;animation:scanline 1.6s ease-in-out infinite}
  @keyframes scanline{from{top:-6%}to{top:104%}}

  /* body */
  .hc-body{padding:.85rem 1rem 1.05rem;display:flex;flex-direction:column;gap:.45rem;flex:1}
  .hc-top{display:flex;align-items:center;justify-content:space-between;gap:.5rem;
    padding-bottom:.45rem;border-bottom:1px solid var(--line)}
  .hc-id{font-family:"JetBrains Mono",monospace;font-size:.58rem;letter-spacing:.18em;color:var(--faint)}
  .hc h3{margin:.15rem 0 0;font-family:"Space Grotesk",system-ui,sans-serif;font-size:1.02rem;letter-spacing:-.01em}
  .hc .meta{font-size:.63rem;margin:0}
  .hc p{font-size:.77rem;line-height:1.5}
  .hc .tags{margin:.2rem 0 0}
  .hc .tags li{font-size:.59rem;padding:3px 7px}

  /* segmented progress strip */
  .segbar{display:flex;gap:3px;margin-top:.35rem}
  .segbar i{flex:1;height:5px;background:var(--line);
    clip-path:polygon(2px 0,100% 0,calc(100% - 2px) 100%,0 100%)}

  .hc .more{margin-top:auto;padding-top:.6rem;font-size:.66rem;
    align-items:center;gap:.4rem}
  .hc-wrap:hover .more{color:var(--st-hi)}
  .hc .more b{font-weight:400;transition:transform .22s}
  .hc-wrap:hover .more b{transform:translateX(4px)}
  .hc .soon{margin-top:auto;padding-top:.6rem;font-family:"JetBrains Mono",monospace;
    font-size:.64rem;letter-spacing:.14em;text-transform:uppercase;color:var(--faint);
    align-items:center;gap:.4rem}
  .hc .soon::before{content:"";width:6px;height:6px;background:var(--line);
    clip-path:polygon(50% 0,100% 50%,50% 100%,0 50%)}

  /* scheduled = visibly dormant */


  @media (max-width:70rem){
    :root{--gap:26px}
    .ln.h{left:150px;right:150px}.ln.h.out{left:132px;right:132px}
    .hatch.b,.hatch.c{display:none}
  }
  @media (max-width:66rem){
    .split{grid-template-columns:1fr;gap:var(--s5)}
    .caps{grid-template-columns:repeat(2,minmax(0,1fr))}
    .grid3{grid-template-columns:1fr}
  }
  /* ─────────────────────────────────────────────────────────────────────
     PHONES AND SHORT WINDOWS — the deck stops being a deck.

     Everything above assumes one section = one screen. That premise cannot
     hold on a phone: Work alone needs four screens for four stacked cards,
     and a fixed-height section simply CLIPS the rest (measured: 1007px of
     Work unreachable on an iPhone 14). So below this breakpoint the sections
     become ordinary stacked blocks and the page scrolls continuously.
     ───────────────────────────────────────────────────────────────────── */
  /* ---------- slider control (mobile only; main.js builds it) ---------- */
  /* Hidden above the breakpoint, where Work and Training are grids and there is
     nothing to page through. It is built in JS rather than written into the
     HTML so the buttons cannot exist without the code that makes them work. */
  .sld-bar{display:none}
  .sld-btn{--n:7px;display:grid;place-items:center;width:38px;height:38px;flex:none;
    background:var(--panel2);color:var(--hud);cursor:pointer;border:0;padding:0;
    box-shadow:inset 0 0 0 1px var(--hud-dim);
    transition:color .18s,box-shadow .18s,background-color .18s;
    clip-path:polygon(var(--n) 0,100% 0,100% calc(100% - var(--n)),calc(100% - var(--n)) 100%,0 100%,0 var(--n))}
  .sld-btn:hover:not(:disabled){background:var(--hud);color:var(--on-hover)}
  .sld-btn svg{width:17px;height:17px}
  .sld-count{font-family:"JetBrains Mono",monospace;font-size:.66rem;letter-spacing:.18em;
    text-transform:uppercase;color:var(--faint);white-space:nowrap}
  .sld-count b{color:var(--hud);font-weight:500}
  @media (pointer:coarse){ .sld-btn{width:44px;height:44px} }

  /* ---------- Work & Training: desktop coverflow ---------- */
  /* Above the mobile breakpoint Work and Training stop being grids and become
     focus carousels: the centred card is full size and the others sit back,
     smaller and desaturated. main.js marks .is-current / .is-near from scroll
     position, so it stays correct however the row was moved. */
  @media (min-width:60.0625rem) and (min-height:30.0625rem){
    #work .grid3,
    #training .tracks{
      /* A LENGTH, not a percentage: flex-basis resolves against the content
         box, which the padding below has already narrowed, so a percentage
         compounds with itself and the card comes out half the size asked for. */
      --cw:min(34rem, 44vw);
      --tuck:clamp(46px, 6vw, 104px);   /* how far the neighbours sit under */
      display:flex;grid-template-columns:none;align-items:center;
      gap:0;
      overflow-x:auto;overscroll-behavior-x:contain;
      scroll-snap-type:x mandatory;
      scrollbar-width:none;
      /* room for the scaled card and for the glow that hangs below it — the
         row must not gain vertical overflow or it steals the wheel */
      padding:26px calc((100% - var(--cw)) / 2) 50px;
      margin-bottom:-28px}
    #work .grid3::-webkit-scrollbar,
    #training .tracks::-webkit-scrollbar{display:none}

    /* Overlap: each card is pulled under its neighbour, so the row reads as a
       stack with one card lifted out of it rather than a line of tiles. */
    #work .grid3 > *,
    #training .tracks > *{
      flex:0 0 var(--cw);
      margin-inline:calc(var(--tuck) / -2);
      scroll-snap-align:center;scroll-snap-stop:always;
      /* The cards carry data-anim, so the `rise` entry animation runs on them
         with fill-mode:forwards — and a filled animation's value beats a normal
         declaration at ANY specificity. It was holding transform:none and
         opacity:1 and quietly cancelling everything below. The carousel is the
         entrance here, so the animation is switched off for these children. */
      animation:none;
      transform:scale(.66);opacity:.22;filter:saturate(.35);
      transition:transform .5s cubic-bezier(.22,.8,.3,1),opacity .5s,filter .5s;
      z-index:1}
    #work .grid3 > .is-near,
    #training .tracks > .is-near   {transform:scale(.8);opacity:.55;filter:saturate(.7);z-index:2}
    #work .grid3 > .is-current,
    #training .tracks > .is-current{transform:scale(1);opacity:1;filter:none;z-index:5}

    /* A card that is not centred is a target for FOCUSING, not for following
       its link — main.js intercepts the click and brings it forward instead. */
    /* Training cards are wider: they hold a list of courses with a provider and
       year on each row, and only one is on screen at a time now. */
    #training .tracks{--cw:min(46rem, 58vw)}

    #work .grid3 > :not(.is-current),
    #training .tracks > :not(.is-current){cursor:pointer}
    #work .grid3 > :not(.is-current) *,
    #training .tracks > :not(.is-current) *{pointer-events:none}

    #work .sld-bar,
    #training .sld-bar{display:flex;justify-content:center;gap:var(--s4);margin-top:var(--s4)}
  }

  @media (max-width:60rem), (max-height:30rem){
    :root{--rail:0px;--gap:12px;--n:22px}
    .rail{left:50%;top:auto;bottom:12px;translate:-50% 0}
    /* the rail floats over scrolling content now, so it needs to read as a layer
       above the page rather than text tangled with text */
    /* Solid, not translucent. Text sliding under a see-through bar reads as a
       rendering fault; text disappearing behind a solid one reads as a bar. */
    .rail .fill{flex-direction:row;background:var(--panel2);
      box-shadow:0 10px 30px rgba(3,6,10,.9)}
    .rail{bottom:calc(12px + env(safe-area-inset-bottom,0px))}   /* home indicator */
    .prog,.plate,.hatch{display:none}

    /* The DOCUMENT scrolls below this breakpoint, not an inner box.
       A fixed .stage with an overflow container inside means the page itself
       never moves: Safari never collapses its address bar, so ~100px of screen
       is lost for good, and momentum and rubber-banding come from the wrong
       element. Everything here goes back into normal flow. */
    body{height:auto;overflow:visible}
    /* relative, not static: .deco is absolutely positioned inside .stage, and
       this is what makes it span the whole document instead of the viewport. */
    .stage{position:relative;inset:auto;margin:var(--gap)}
    .frame{position:relative;inset:auto;overflow:visible}
    .deck{position:static;inset:auto;overflow:visible;padding-left:0}
    /* the rail was absolute inside .stage; with .stage in normal flow it has to
       hold itself against the viewport instead */
    .rail{position:fixed}

    /* The decoration layer is fixed-size chrome designed for one screen holding
       one section. Against a continuously scrolling page it stops being a frame
       and becomes an overlay — corner brackets landing mid-paragraph, chamfer
       diagonals cutting across sentences. The frame's own outline is enough. */
    /* The decoration stays, but it scrolls WITH the page. .stage is relative so
       .deco spans the whole document rather than the viewport: the corner
       brackets land at the very top and bottom of the page and the edge lines
       run its full length. Pinned to the viewport they crossed paragraphs. */
    .deco{inset:-10px}

    /* Work and Training were 1868px and 1238px of vertical scrolling — four
       near-identical cards each, read one after another. As horizontal sliders
       they are one card tall and swiped instead. The card is 86% wide so the
       next one always peeks: that sliver is the only thing that tells anyone
       the row scrolls at all. */
    #work .grid3,
    #training .tracks{
      display:flex;grid-template-columns:none;gap:var(--s4);
      overflow-x:auto;overscroll-behavior-x:contain;
      scroll-snap-type:x mandatory;
      /* Setting overflow-x:auto forces overflow-y to compute to auto too — one
         axis cannot scroll while the other stays visible. So ANY vertical
         overflow inside this row turns it into a vertical scroll container,
         and a swipe over the cards scrolls that instead of the page. The card
         glow (.hc-wrap::after) hangs 18px below the card, which was exactly
         enough to do it. The padding contains it; the row now overflows in x
         only. Check scrollHeight === clientHeight if you ever touch this. */
      padding:10px 2px 34px;margin-inline:-2px;margin-bottom:calc(var(--s3) * -1);
      scrollbar-width:none}
    #work .grid3::-webkit-scrollbar,
    #training .tracks::-webkit-scrollbar{display:none}
    #work .grid3 > *,
    #training .tracks > *{
      /* 92%: the 8% left over is the peek. Push this to 100% and the row reads
         as one fixed card — only the arrows would say otherwise. */
      flex:0 0 92%;scroll-snap-align:center;scroll-snap-stop:always}

    /* the slider control: counter + arrows, built by main.js */
    .sld-bar{display:flex;align-items:center;justify-content:flex-end;
      gap:var(--s3);margin-top:var(--s3)}
    h1{font-size:2rem}h2{font-size:1.55rem}

    /* no snapping: it needs slides, and these are no longer slides */
    .deck{scroll-snap-type:none;scroll-padding-top:var(--s5)}
    .card{height:auto;min-height:auto;display:block;overflow:visible;
      scroll-snap-align:none;scroll-snap-stop:normal;
      padding:var(--s7) var(--s5) var(--s6)}
    .card:last-child{padding-bottom:96px}          /* clear the floating rail */
    .card + .card{border-top:1px solid var(--line)}
    .card-inner,
    #work .card-inner,
    #training .card-inner,
    #about .card-inner{max-width:100%;max-height:none;overflow:visible}
    .card-tag{position:static;display:block;margin-bottom:var(--s3)}

    /* one column everywhere */
    .split,.about-grid,.tracks,.grid3,.caps{grid-template-columns:1fr;gap:var(--s5)}
    #about .caps{grid-template-columns:1fr}
    .shot-body{min-height:8rem}
    #work .hc-thumb{aspect-ratio:2.6/1}   /* a strip, not a panel — the card was 396px */
    #work .hc p{display:block}

    /* the certificate strip wraps instead of running off the edge */
    .certs{gap:.35rem}
    .cert{width:3rem}
    .skills > li{grid-template-columns:4.6rem 1fr}

    /* the gallery arrows hang outside the dialog; on a phone that is off-screen */
    .lb-nav{width:34px;height:48px}
    .lb-nav.prev{left:8px} .lb-nav.next{right:8px}
    .lb-x{top:-14px;right:-6px}
  }

  /* Touch targets. A 39x28 tile is fine for a mouse and too small for a thumb —
     the usual floor is about 44px. Keyed to the POINTER, not the screen width,
     because a small window on a laptop still has a precise cursor. */
  @media (pointer:coarse){
    .cert{width:4rem;aspect-ratio:1.2}
    .certs{gap:.45rem}
    .rail a{width:44px;height:44px}
  }
  @media (prefers-reduced-motion:reduce){
    *{animation:none!important}html{scroll-behavior:auto}
    .js-anim [data-anim]{opacity:1;transform:none}
  }

  /* ---------- contact form ---------- */
  .field label{font-family:"JetBrains Mono",monospace;font-size:.64rem;letter-spacing:.18em;
    text-transform:uppercase;color:var(--faint)}
  /* 2px, not 1px, on purpose. The page is laid out from a fluid rem scale, so
     these boxes land on fractional device pixels; a 1px border then splits its
     coverage across two rows and both come out dim — the edge looked missing at
     some window sizes and fine at others. 2px always fully covers one device
     pixel, whatever the offset. */
  .field input,.field textarea{--n:8px;display:block;width:100%;
    padding:.6rem .75rem;background:rgba(6,10,15,.9);color:var(--txt);
    border:2px solid var(--field-line);border-radius:0;
    clip-path:polygon(var(--n) 0,100% 0,100% calc(100% - var(--n)),calc(100% - var(--n)) 100%,0 100%,0 var(--n));
    transition:border-color .18s,box-shadow .18s}
  .field input{height:2.6rem}
  .field textarea{min-height:5.5rem;resize:vertical;line-height:1.5}
  .field input:focus,.field textarea:focus{outline:none;border-color:var(--hud);
    box-shadow:0 0 0 2px var(--hud-dim)}
  .field input:user-invalid,.field textarea:user-invalid{border-color:var(--alert)}

  /* ---------- send / confirmation ---------- */

  .send{display:block}

  /* Always rendered, usually empty. Reserving the line means the box does not
     grow when a message appears — no shift in a vertically centred column. */
  .send-note{margin:var(--s3) 0 0;min-height:1.1rem;
    font-family:"JetBrains Mono",monospace;font-size:.68rem;
    letter-spacing:.16em;text-transform:uppercase;color:var(--hud)}
  .send-note.bad{color:var(--alert)}

  /* [hidden] is the weakest rule in the cascade and .sent gets display:grid
     below. Without this the panel is visible on load. Same bug as .lb-nav. */
  .sent[hidden]{display:none}

  /* The confirmation is a state of the whole section, not of the form: it lies
     over #contact and the card's contents are hidden underneath. The frame,
     rail and corner brackets live outside #contact, so they stay put. */
  #contact{position:relative}
  .sent{position:absolute;inset:0;z-index:4;display:grid;align-content:center;
    justify-items:center;gap:var(--s5);padding:0 var(--s5);
    text-align:center;color:var(--hud)}
  #contact .card-inner{transition:opacity .25s}
  #contact.busy .card-inner{opacity:0;visibility:hidden}

  .sent-cap{margin:0;font-family:"JetBrains Mono",monospace;font-size:.74rem;
    letter-spacing:.18em;text-transform:uppercase;color:var(--mut)}

  /* The viewBox is the full 260x150 so the trace end-points are inside it; the
     width is scaled up to keep the node the same size on screen. */
  .sent-ring{width:42rem;max-width:92%;height:auto;
    filter:drop-shadow(0 0 5px var(--hud-glow)) drop-shadow(0 0 20px var(--hud-dim))}

  /* both animated strokes start fully retracted */
  .sr-ring,.sr-check{stroke-dasharray:100;stroke-dashoffset:100}
  .sent.go .sr-ring {animation:draw .75s cubic-bezier(.4,0,.2,1) forwards}
  .sent.go .sr-check{animation:draw .3s ease-out .6s forwards}
  @keyframes draw{to{stroke-dashoffset:0}}

  /* failure — rose, the same word it means everywhere else on this page */

  .send > form{transition:opacity .25s}
  .send.sending > form{opacity:.45;pointer-events:none}

  /* Your global reduced-motion rule is `*{animation:none!important}`. That kills
     the draw — but a draw-on animation's START state is "invisible", so the ring
     would never appear at all. Reset the offset so it renders complete. */
  @media (prefers-reduced-motion:reduce){
    .sr-ring,.sr-check{stroke-dashoffset:0}
  }

  /* ---------- focus rings on chamfered controls ---------- */
  /* clip-path clips everything an element paints — including its outline and
     its box-shadow. Every control here has a chamfer, so the global
     :focus-visible ring (drawn at outline-offset:3px, i.e. OUTSIDE the box)
     was clipped away completely: keyboard focus moved with no visible change.
     Draw the ring on the inside instead, where the clip cannot reach it. */
  .btn:focus-visible,
  .rail a:focus-visible,
  .sld-btn:focus-visible,
  .cert:focus-visible,
  .field input:focus-visible,
  .field textarea:focus-visible{
    outline:none;
    box-shadow:inset 0 0 0 2px var(--hud), 0 0 0 1px var(--hud-dim)}
  .field input:focus-visible,
  .field textarea:focus-visible{border-color:var(--hud)}
