/* ==========================================================================
   RYAN MALINAO MORAO: PORTFOLIO STYLESHEET (WINDOWS DESKTOP THEME)
   The boot screen styles are inlined in index.html so they paint first.
   Older themes are kept in _backup-light-theme/ and _backup-terminal-theme/.

   On computers, the page is a desktop: script.js adds .os to <html> and wraps every
   [data-window] section in a window. On phones, and without JavaScript, the
   sections show as a normal scrolling page (see "Phone page" below).
   ========================================================================== */

/* ---------- Tokens ---------- */
:root{
  --c-bg:#202020;
  --c-card:#2b2b2b;
  --c-card-hover:#323232;
  --c-tint:#1a1a1a;
  --c-subtle:rgba(255,255,255,.06);
  --c-subtle-hover:rgba(255,255,255,.09);
  --c-border:rgba(255,255,255,.08);
  --c-border-strong:rgba(255,255,255,.14);
  --c-text:#ffffff;
  --c-text-dim:#c5c5c5;
  --c-text-faint:#9a9a9a;
  --c-accent:#4ade80;
  --c-accent-hover:#6ee7a0;
  --c-accent-ink:#052e16;
  --c-error:#ff99a4;
  --c-close:#c42b1c;
  --c-overlay:rgba(0,0,0,.55);
  --c-acrylic:rgba(36,36,36,.82);

  /* Terminal (Windows Terminal colours, with the green from the old theme) */
  --t-bg:#0c0c0c;
  --t-fg:#cccccc;
  --t-green:#4ade80;
  --t-yellow:#f5c065;
  --t-cyan:#61d6d6;
  --t-red:#e74856;
  --t-dim:#8a8a8a;

  --font-ui:'Segoe UI Variable Text','Segoe UI',Inter,system-ui,-apple-system,Roboto,sans-serif;
  --font-display:'Segoe UI Variable Display','Segoe UI',Inter,system-ui,-apple-system,Roboto,sans-serif;
  --font-mono:'Cascadia Mono','JetBrains Mono',Consolas,ui-monospace,'SF Mono',Menlo,monospace;

  --taskbar-h:48px;
  --radius:8px;
  --radius-sm:4px;
  --shadow-win:0 32px 64px rgba(0,0,0,.5),0 2px 21px rgba(0,0,0,.45);
  color-scheme:dark;
}

/* ---------- Base ---------- */
*,*::before,*::after{box-sizing:border-box;margin:0;padding:0;}
html{background:#000;}
body{
  background:var(--c-bg);
  color:var(--c-text);
  font-family:var(--font-ui);
  font-size:14px;
  line-height:1.55;
  -webkit-font-smoothing:antialiased;
}
.os body{overflow:hidden;background:#000;}
img,svg{display:block;max-width:100%;}
img{height:auto;}
a{color:inherit;text-decoration:none;}
button,input,textarea{font:inherit;color:inherit;background:none;border:none;}
button{cursor:pointer;}
ul,ol{list-style:none;}
h1,h2,h3,h4{font-family:var(--font-display);font-weight:600;line-height:1.25;}
:focus-visible{outline:2px solid #fff;outline-offset:2px;border-radius:var(--radius-sm);}
::selection{background:var(--c-accent);color:var(--c-accent-ink);}
*{scrollbar-width:thin;scrollbar-color:rgba(255,255,255,.28) transparent;}

/* ---------- Desktop ---------- */
.desktop-icons,.taskbar,.start-menu{display:none;}

.os .desktop{
  position:fixed;inset:0 0 var(--taskbar-h) 0;overflow:hidden;
  /* Wallpaper: the Windows 11 "Bloom" (--wall-windows, under "Virtual Machines app"). */
  background:var(--wall-windows);
}
/* Two fixed columns, like a tidy Windows desktop: the eight sections down the
   first column, then the CV, chat, and profile links in the second. Rows shrink
   on short screens so the columns never reflow. */
.os .desktop-icons{
  position:absolute;inset:0;z-index:1;
  display:grid;grid-auto-flow:column;
  grid-template-rows:repeat(8,minmax(0,86px));grid-auto-columns:84px;
  align-content:start;gap:2px 4px;padding:8px 6px;
}
.desk-icon{
  display:flex;flex-direction:column;align-items:center;justify-content:flex-start;gap:4px;
  height:100%;min-height:0;overflow:hidden;padding:6px 2px;
  border-radius:var(--radius-sm);border:1px solid transparent;
  color:#fff;font-size:12px;line-height:1.25;text-align:center;
  text-shadow:0 1px 2px rgba(0,0,0,.95),0 0 6px rgba(0,0,0,.55);
}
.desk-icon svg{width:42px;height:42px;flex:none;filter:drop-shadow(0 2px 3px rgba(0,0,0,.35));}
@media (max-height:700px){
  .desk-icon{gap:2px;padding:3px 2px;}
  .desk-icon svg{width:32px;height:32px;}
}
/* Wallpaper and design credit in the bottom-right corner, like the Windows
   build watermark. Only the desktop shows the wallpaper, so only it shows this. */
.desktop-credit{display:none;}
.os .desktop-credit{
  display:block;position:absolute;right:16px;bottom:10px;z-index:1;max-width:min(520px,60vw);
  margin:0;color:rgba(255,255,255,.92);font-size:11px;line-height:1.45;text-align:right;
  text-shadow:0 1px 2px rgba(0,0,0,.8),0 0 6px rgba(0,0,0,.45);pointer-events:none;
}
/* Desktop pets: above the wallpaper and icon grid, under the windows. Only the
   pets themselves take clicks, and they keep out of the icon columns. */
.desk-pets{display:none;}
.os .desk-pets{display:block;position:absolute;inset:0;z-index:1;overflow:hidden;pointer-events:none;}
.os .desk-pets[hidden]{display:none;}
.desk-pet{position:absolute;left:0;bottom:2px;width:60px;height:45px;pointer-events:auto;cursor:pointer;will-change:transform;}
.desk-pet-body{width:100%;height:100%;}
.desk-pet.is-left .desk-pet-body{transform:scaleX(-1);}
.desk-pet svg{display:block;width:100%;height:100%;overflow:visible;filter:drop-shadow(0 2px 2px rgba(0,0,0,.35));}
.pet-leg{transform-box:fill-box;transform-origin:50% 0;}
.pet-tail{transform-box:view-box;animation:pet-wag 1.1s ease-in-out infinite alternate;}
.pet-tongue{display:none;}
.desk-pet.is-moving .leg-a{animation:pet-step var(--step) ease-in-out infinite alternate;}
.desk-pet.is-moving .leg-b{animation:pet-step var(--step) ease-in-out infinite alternate-reverse;}
.desk-pet.is-moving .pet-bob{animation:pet-bob var(--step) ease-in-out infinite alternate;}
.desk-pet.is-moving .pet-tail{animation-duration:.25s;}
.desk-pet{--step:.3s;}
.desk-pet.is-running{--step:.14s;}
.desk-pet.is-running .pet-tongue{display:inline;}
.desk-pet.is-hop .desk-pet-body{animation:pet-hop .5s ease-out;}
@keyframes pet-step{from{transform:rotate(26deg);}to{transform:rotate(-26deg);}}
@keyframes pet-bob{to{transform:translateY(-1.5px);}}
@keyframes pet-wag{from{transform:rotate(-10deg);}to{transform:rotate(14deg);}}
@keyframes pet-hop{40%{translate:0 -16px;}}
.pet-bubble{
  position:absolute;bottom:100%;left:50%;margin-bottom:2px;padding:2px 8px;border-radius:10px;
  background:#fff;color:#222;font:600 11px/1.5 var(--font-ui);white-space:nowrap;
  box-shadow:0 2px 6px rgba(0,0,0,.3);pointer-events:none;transform:translateX(-50%);
  animation:pet-bubble 1.5s ease-out forwards;
}
.pet-bubble b{color:#e5484d;}
/* The butterfly they chase. It never takes clicks. */
.desk-butterfly{position:absolute;left:0;bottom:0;width:34px;height:30px;pointer-events:none;will-change:transform;}
.desk-butterfly[hidden]{display:none;}
.desk-butterfly svg{display:block;width:100%;height:100%;overflow:visible;filter:drop-shadow(0 2px 2px rgba(0,0,0,.3));}
.bf-wing{transform-box:view-box;transform-origin:16px 14px;animation:bf-flap .16s ease-in-out infinite alternate;}
@keyframes bf-flap{to{transform:scaleX(.3);}}
.desk-butterfly.is-fleeing .bf-wing{animation-duration:.07s;}
@keyframes pet-bubble{
  0%{opacity:0;transform:translate(-50%,4px);}
  15%,75%{opacity:1;transform:translate(-50%,0);}
  100%{opacity:0;transform:translate(-50%,-8px);}
}

.desk-icon:hover{background:rgba(255,255,255,.1);border-color:rgba(255,255,255,.12);}
.desk-icon:focus-visible{background:rgba(74,222,128,.2);border-color:rgba(74,222,128,.5);outline:none;}

/* ---------- Windows ---------- */
.os .windows{position:absolute;inset:0;z-index:2;pointer-events:none;}
.win{
  position:absolute;display:flex;flex-direction:column;
  min-width:320px;min-height:220px;max-width:100%;max-height:100%;
  pointer-events:auto;overflow:hidden;resize:both;
  background:var(--c-bg);border:1px solid var(--c-border-strong);border-radius:var(--radius);
  box-shadow:var(--shadow-win);
  animation:win-open .18s cubic-bezier(.1,.9,.2,1);
}
.win[hidden]{display:none !important;}
.win:focus{outline:none;}
.win.is-max{inset:0 !important;width:auto !important;height:auto !important;border-radius:0;border:none;resize:none;}
.win:not(.is-active){box-shadow:0 16px 40px rgba(0,0,0,.4);}
@keyframes win-open{from{opacity:0;transform:scale(.96);}}

.win-bar{
  display:flex;align-items:center;gap:10px;flex:none;
  height:36px;padding-left:12px;
  background:#1c1c1c;
  font-size:12px;color:var(--c-text);
  user-select:none;-webkit-user-select:none;touch-action:none;
}
.win:not(.is-active) .win-bar{color:var(--c-text-faint);}
.win:not(.is-active) .win-bar > svg{opacity:.6;}
.win-bar > svg{width:16px;height:16px;flex:none;}
.win-title{flex:1;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
.win-btn{
  display:flex;align-items:center;justify-content:center;flex:none;
  width:46px;height:36px;color:inherit;transition:background-color .1s;
}
.win-btn svg{width:10px;height:10px;}
.win-btn:hover{background:rgba(255,255,255,.08);}
.win-close:hover{background:var(--c-close);color:#fff;}
.win-body{flex:1;min-height:0;overflow:auto;overscroll-behavior:contain;}

/* ---------- Taskbar ---------- */
.os .taskbar{
  position:fixed;left:0;right:0;bottom:0;z-index:250;height:var(--taskbar-h);
  display:flex;align-items:center;justify-content:center;
  background:rgba(28,28,28,.86);
  backdrop-filter:blur(30px) saturate(1.4);-webkit-backdrop-filter:blur(30px) saturate(1.4);
  border-top:1px solid var(--c-border);
}
.task-center{display:flex;align-items:center;gap:4px;}
.task-apps{display:flex;align-items:center;gap:4px;}
.task-btn{
  position:relative;display:flex;align-items:center;justify-content:center;
  width:44px;height:40px;border-radius:var(--radius-sm);
  transition:background-color .1s;
}
.task-btn:hover,.task-btn.is-active{background:rgba(255,255,255,.08);}
.task-btn:active svg,.task-btn:active img{transform:scale(.88);}
.task-btn svg,.task-btn img{width:24px;height:24px;transition:transform .1s;}
.task-start img{width:26px;height:26px;border-radius:5px;}
.task-btn::after{
  content:'';position:absolute;bottom:2px;left:50%;
  width:0;height:3px;border-radius:2px;background:var(--c-text-faint);
  transform:translateX(-50%);transition:width .15s,background-color .15s;
}
.task-btn.is-open::after{width:6px;}
.task-btn.is-focused::after{width:16px;background:var(--c-accent);}
.task-tray{position:absolute;right:8px;top:0;bottom:0;display:flex;align-items:center;gap:2px;}
.tray-btn{width:40px;}
.tray-btn svg{width:20px;height:20px;}
.tray-status{display:flex;align-items:center;gap:8px;height:40px;padding:0 10px;border-radius:var(--radius-sm);}
.tray-status svg{width:16px;height:16px;}
.tray-sound{display:grid;place-items:center;width:24px;height:24px;margin:0 -4px;padding:0;border:0;border-radius:4px;background:none;color:inherit;cursor:pointer;}
.tray-sound:hover{background:rgba(255,255,255,.1);}
.tray-sound:focus-visible{outline:2px solid var(--c-accent);outline-offset:1px;}
.tray-clock{display:flex;flex-direction:column;align-items:flex-end;justify-content:center;height:40px;padding:0 10px;font-size:12px;line-height:1.35;border-radius:var(--radius-sm);}
.tray-status:hover,.tray-clock:hover{background:rgba(255,255,255,.06);}

/* ---------- Start menu ---------- */
.os .start-menu:not([hidden]){
  position:fixed;z-index:260;left:50%;bottom:calc(var(--taskbar-h) + 12px);
  display:flex;flex-direction:column;
  width:min(640px,calc(100vw - 16px));max-height:calc(100dvh - var(--taskbar-h) - 24px);
  transform:translateX(-50%);
  background:var(--c-acrylic);
  backdrop-filter:blur(40px) saturate(1.5);-webkit-backdrop-filter:blur(40px) saturate(1.5);
  border:1px solid var(--c-border-strong);border-radius:var(--radius);
  box-shadow:var(--shadow-win);
  animation:start-in .2s cubic-bezier(.1,.9,.2,1);
}
@keyframes start-in{from{opacity:0;transform:translate(-50%,24px);}}
.start-search{
  display:flex;align-items:center;gap:10px;margin:24px 32px 0;padding:0 14px;height:36px;
  background:rgba(0,0,0,.28);border:1px solid var(--c-border);border-bottom-color:rgba(255,255,255,.4);
  border-radius:20px;
}
.start-search:focus-within{border-bottom:2px solid var(--c-accent);}
.start-search svg{width:16px;height:16px;flex:none;color:var(--c-text-dim);}
.start-search input{flex:1;min-width:0;height:100%;outline:none;font-size:13px;}
.start-search input::placeholder{color:var(--c-text-faint);}
.start-body{flex:1;min-height:0;overflow-y:auto;padding:20px 32px 12px;}
.start-head{font-size:14px;font-weight:600;margin:0 10px 10px;}
.start-grid{display:grid;grid-template-columns:repeat(6,1fr);gap:4px;margin-bottom:22px;}
.start-app{
  display:flex;flex-direction:column;align-items:center;gap:6px;
  padding:12px 4px 10px;border-radius:var(--radius-sm);
  font-size:12px;line-height:1.25;text-align:center;
}
.start-app svg{width:32px;height:32px;}
.start-app:hover,.start-rec:hover{background:rgba(255,255,255,.07);}
.start-app[hidden],.start-recs[hidden],.start-head[hidden]{display:none;}
.start-empty{padding:12px 10px;color:var(--c-text-faint);font-size:13px;}
.start-empty[hidden]{display:none;}
.start-recs{display:grid;grid-template-columns:repeat(2,1fr);gap:4px;}
.start-rec{display:flex;align-items:center;gap:12px;width:100%;padding:8px 10px;border-radius:var(--radius-sm);text-align:left;}
.start-rec svg{width:32px;height:32px;flex:none;}
.start-rec span{display:flex;flex-direction:column;min-width:0;font-size:12px;}
.start-rec small{color:var(--c-text-faint);font-size:11px;}
.start-footer{
  display:flex;align-items:center;justify-content:space-between;gap:12px;
  padding:12px 48px;border-top:1px solid var(--c-border);
  background:rgba(0,0,0,.18);border-radius:0 0 var(--radius) var(--radius);
}
.start-user{display:flex;align-items:center;gap:12px;font-size:12px;}
.start-user img{width:32px;height:32px;border-radius:50%;object-fit:cover;object-position:center 15%;}
.start-user small{display:block;color:var(--c-text-faint);font-size:11px;}
.start-power{width:40px;height:40px;display:flex;align-items:center;justify-content:center;border-radius:var(--radius-sm);}
.start-power:hover{background:rgba(255,255,255,.08);}
.start-power svg{width:16px;height:16px;}

/* ---------- Shared content ---------- */
.section{padding:28px 32px 40px;container-type:inline-size;}
html:not(.os) .section{max-width:1080px;margin:0 auto;border-bottom:1px solid var(--c-border);}
.section-container{max-width:none;}
.section-title{font-size:28px;margin-bottom:20px;}
.section-title:has(+ .section-intro){margin-bottom:4px;}
.section-intro{color:var(--c-text-dim);margin-bottom:20px;}

.btn{
  display:inline-flex;align-items:center;justify-content:center;gap:8px;
  min-height:32px;padding:5px 14px;border-radius:var(--radius-sm);
  font-size:14px;white-space:nowrap;border:1px solid transparent;
  transition:background-color .1s,border-color .1s;
}
.btn-primary{background:var(--c-accent);color:var(--c-accent-ink);border-color:rgba(255,255,255,.08);}
.btn-primary:hover{background:var(--c-accent-hover);}
.btn-primary:disabled{opacity:.55;cursor:default;}
.btn-outline{background:var(--c-subtle);border-color:var(--c-border);}
.btn-outline:hover{background:var(--c-subtle-hover);}
.btn-sm{min-height:28px;padding:3px 12px;font-size:13px;}

.icon-btn{
  width:32px;height:32px;flex:none;border-radius:var(--radius-sm);
  display:flex;align-items:center;justify-content:center;
  color:var(--c-text);background:var(--c-subtle);border:1px solid var(--c-border);
  transition:background-color .1s;
}
.icon-btn:hover{background:var(--c-subtle-hover);}
.icon-btn svg{width:16px;height:16px;}

.text-link{display:inline-flex;align-items:center;gap:4px;font-size:13px;color:var(--c-accent);}
.text-link:hover{text-decoration:underline;}

.card,.job,.gallery-card,.project-card,.skill-group,.cert-card,.award-list li,.info-grid,.stats-row div,.contact-form{
  background:var(--c-card);border:1px solid var(--c-border);border-radius:var(--radius);
}

/* Hidden only after script.js confirms it can reveal them again. */
.reveal-ready [data-animate]:not(.in-view){opacity:0;transform:translateY(8px);}
.reveal-ready [data-animate]{transition:opacity .35s ease,transform .35s ease;}

/* ---------- Terminal window (the old hero) ---------- */
.terminal-app{
  min-height:100%;padding:16px 20px 18px;
  background:var(--t-bg);color:var(--t-fg);
  font-family:var(--font-mono);font-size:13.5px;line-height:1.55;
  container-type:inline-size;
}
.terminal-app ::selection{background:var(--t-fg);color:var(--t-bg);}
.term-body{display:grid;grid-template-columns:minmax(0,1fr) 300px;gap:24px;align-items:start;}
.term-banner{color:var(--t-fg);margin-bottom:14px;}
/* Phones (no .os class) skip the terminal's version and copyright lines. */
html:not(.os) .term-banner{display:none;}
/* pre keeps Kali's two-line prompt on two lines. */
.ps1{color:var(--t-green);white-space:pre;}
.ps1 .p-frame{color:var(--t-green);}
.ps1 .p-user{color:#5c9cff;font-weight:700;}
.ps1 .p-path{color:#fff;font-weight:700;}
.ps1 .p-plain{color:var(--t-fg);}
.term-line{margin-top:12px;}
.term-banner + .term-line{margin-top:0;}
.typed{display:inline-block;vertical-align:bottom;white-space:nowrap;overflow:hidden;}
.hero-name{
  font-family:var(--font-mono);font-weight:700;
  font-size:clamp(1.3rem,5.4cqw,2.3rem);line-height:1.15;margin-top:2px;
  color:var(--t-green);text-shadow:0 0 16px rgba(74,222,128,.3);
}
.hero-role{color:var(--t-yellow);margin-top:2px;}
.hero-desc{color:var(--t-fg);opacity:.85;margin-top:2px;max-width:640px;}
.hero-buttons{display:flex;flex-wrap:wrap;gap:8px;margin-top:8px;font-family:var(--font-ui);}
.social-row{display:flex;gap:6px;margin-top:10px;}
.social-icon{
  width:34px;height:34px;border-radius:var(--radius-sm);
  display:flex;align-items:center;justify-content:center;
  color:var(--t-fg);background:rgba(255,255,255,.05);border:1px solid rgba(255,255,255,.08);
}
.social-icon:hover{background:rgba(255,255,255,.1);color:#fff;}

/* Lines appear one after another once the boot screen lifts. */
.js .terminal-app [data-step]{opacity:0;}
.js:not(.is-loading) .terminal-app [data-step]{animation:term-show .01s linear forwards;animation-delay:calc(var(--s) * 280ms + 150ms);}
.js .terminal-app .typed{width:0;}
/* term-done sets the width to auto once typing ends. Rounding can stop term-type one character short. */
.js:not(.is-loading) .terminal-app .typed{
  animation:term-type 260ms steps(var(--n)) forwards,term-done 1ms forwards;
  animation-delay:calc(var(--s) * 280ms + 150ms),calc(var(--s) * 280ms + 430ms);
}
@keyframes term-show{to{opacity:1;}}
@keyframes term-type{to{width:calc(var(--n) * 1ch);}}
@keyframes term-done{from,to{width:auto;}}

.term-output{margin-top:12px;}
.term-output:empty{display:none;}
.term-output p{white-space:pre-wrap;overflow-wrap:anywhere;}
.term-output .t-cmd{color:var(--t-fg);}
.term-output .t-dim{color:var(--t-dim);}
.term-output .t-ok{color:var(--t-green);}
.term-output .t-warn{color:var(--t-yellow);}
.term-output .t-err{color:var(--t-red);}
.term-output .t-key{color:var(--t-cyan);display:inline-block;min-width:16ch;}
.term-output a{color:var(--t-cyan);text-decoration:underline;}
.term-prompt{display:flex;align-items:last baseline;gap:8px;margin-top:12px;}
.term-prompt input{flex:1;min-width:0;padding:2px 0;outline:none;color:var(--t-fg);caret-color:var(--t-fg);}
.term-prompt input::placeholder{color:var(--t-dim);}

/* ASCII portrait. Shown only after script.js has drawn it (.is-ascii). */
.term-art .term-line{margin-top:0;margin-bottom:8px;}
/* The `jp2a` command only makes sense above the ASCII version. */
.term-art:not(.is-ascii) .term-line{display:none;}
.hero-photo img{width:100%;aspect-ratio:1/1.06;object-fit:cover;object-position:center 10%;border-radius:var(--radius-sm);}
.ascii-frame{position:relative;container-type:inline-size;}
.ascii-art{display:none;}
.hero-photo.is-ascii .ascii-art{
  display:block;margin:0;
  /* Fits --cols characters (0.6em wide each) into the frame width. */
  font-family:'JetBrains Mono',var(--font-mono);font-size:calc(100cqw / (var(--cols) * .6));
  line-height:1;letter-spacing:0;white-space:pre;overflow:hidden;
  color:var(--t-green);text-shadow:0 0 6px rgba(74,222,128,.4);
  -webkit-user-select:none;user-select:none;
}
.hero-photo.is-ascii img{position:absolute;inset:0;height:100%;aspect-ratio:auto;opacity:0;transition:opacity .25s;}
@media (hover:hover){
  .hero-photo.is-ascii .ascii-frame:hover img{opacity:1;}
}
/* Prints row by row once the boot screen lifts. ascii-done clears the clip,
   because rounding can stop the stepped animation one row short. */
.js:not(.is-loading) .hero-photo.is-ascii .ascii-art{
  animation:ascii-print 900ms steps(var(--rows)) both,ascii-done 1ms forwards;
  animation-delay:400ms,1350ms;
}
@keyframes ascii-print{from{clip-path:inset(0 0 100% 0);}to{clip-path:inset(0);}}
@keyframes ascii-done{from,to{clip-path:none;}}

@container (max-width:680px){
  .term-body{grid-template-columns:1fr;}
  .term-art{order:-1;width:min(300px,100%);}
}

/* ---------- About ---------- */
.about-grid{display:grid;grid-template-columns:240px 1fr;gap:28px;align-items:start;}
.about-photo{aspect-ratio:4/5;border-radius:var(--radius);overflow:hidden;background:var(--c-card);border:1px solid var(--c-border);}
.about-photo img{width:100%;height:100%;object-fit:cover;}
.about-content > p{color:var(--c-text-dim);margin-bottom:14px;max-width:680px;}
.info-grid{display:grid;grid-template-columns:repeat(2,1fr);gap:0;margin:20px 0;overflow:hidden;}
.info-grid div{padding:10px 16px;border-bottom:1px solid var(--c-border);}
.info-grid div:nth-last-child(-n+2){border-bottom:none;}
.info-grid dt{font-size:12px;color:var(--c-text-faint);}
.info-grid dd{font-weight:600;}
.stats-row{display:grid;grid-template-columns:repeat(3,1fr);gap:8px;}
.stats-row div{display:flex;flex-direction:column;padding:12px 16px;}
.stats-row dd{font-family:var(--font-display);font-size:26px;font-weight:600;line-height:1.2;color:var(--c-accent);}
.stats-row dt{font-size:12px;color:var(--c-text-dim);margin-top:2px;}

/* ---------- Experience ---------- */
.job{padding:18px 20px;margin-bottom:8px;}
.job-head{display:flex;justify-content:space-between;align-items:flex-start;gap:16px;margin-bottom:10px;}
.job-head h3{font-size:16px;}
.job-title-row{display:flex;align-items:center;gap:12px;}
.job-logo{flex:none;width:40px;height:40px;padding:3px;border-radius:var(--radius-sm);background:#fff;}
.job-link{margin-top:8px;}
.job-org{color:var(--c-text-dim);font-size:13px;margin-top:2px;}
.job-date{flex:none;padding:2px 10px;border-radius:12px;background:var(--c-subtle);font-size:12px;color:var(--c-text-dim);white-space:nowrap;}
.job-list,.training-list{list-style:disc;padding-left:20px;color:var(--c-text-dim);}
.job-list li,.training-list li{margin-bottom:4px;}
.job-list li::marker,.training-list li::marker{color:var(--c-accent);}

.gallery-title,.training-title{font-size:16px;margin:28px 0 12px;}
.gallery-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:8px;}
.gallery-card{
  display:flex;flex-direction:column;text-align:left;overflow:hidden;
  transition:background-color .1s,border-color .1s,opacity .35s ease,transform .35s ease;
}
.gallery-card:hover{background:var(--c-card-hover);border-color:var(--c-border-strong);}
.gallery-card img{width:100%;aspect-ratio:16/10;object-fit:cover;background:var(--c-tint);}
.gallery-body{display:flex;flex-direction:column;gap:2px;padding:10px 12px 12px;flex:1;}
.gallery-name{font-weight:600;font-size:14px;}
.gallery-desc{font-size:12px;color:var(--c-text-dim);flex:1;}
.gallery-count{font-size:12px;color:var(--c-accent);margin-top:4px;}

/* ---------- Projects ---------- */
.project-filters{display:flex;flex-wrap:wrap;gap:6px;margin-bottom:16px;}
.filter-btn{
  padding:4px 14px;border-radius:16px;font-size:13px;
  background:var(--c-subtle);border:1px solid var(--c-border);color:var(--c-text-dim);
  transition:background-color .1s,color .1s;
}
.filter-btn:hover{background:var(--c-subtle-hover);color:var(--c-text);}
.filter-btn.active{background:var(--c-accent);border-color:var(--c-accent);color:var(--c-accent-ink);}
.projects-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:8px;}
.project-card{
  display:flex;flex-direction:column;overflow:hidden;
  transition:background-color .1s,border-color .1s,opacity .35s ease,transform .35s ease;
}
.project-card:hover{background:var(--c-card-hover);border-color:var(--c-border-strong);}
.project-card.filtered-out{display:none;}
.project-body{display:flex;flex-direction:column;align-items:flex-start;gap:6px;padding:16px;flex:1;}
.project-meta{font-size:12px;color:var(--c-text-faint);}
.project-body h3{font-size:15px;}
.project-body p{font-size:13px;color:var(--c-text-dim);flex:1;}
.project-featured{grid-column:1/-1;flex-direction:row;}
.project-shot{flex:0 0 46%;background:var(--c-tint);}
.project-shot img{width:100%;height:100%;object-fit:cover;object-position:top;aspect-ratio:16/10;}
.project-featured .project-body{padding:22px;justify-content:center;}
.project-featured h3{font-size:19px;}
.project-featured .project-body p{flex:none;font-size:14px;}
.tech-badges{display:flex;flex-wrap:wrap;gap:4px;}
.project-links{display:flex;flex-wrap:wrap;gap:4px 16px;}
.badge{font-size:11px;padding:1px 8px;border-radius:var(--radius-sm);background:var(--c-subtle);color:var(--c-text-dim);border:1px solid var(--c-border);}

/* ---------- Skills ---------- */
.skills-grid{display:grid;grid-template-columns:repeat(2,1fr);gap:8px;}
.skill-group{padding:16px 18px;}
.skill-group h3{font-size:15px;margin-bottom:10px;}
.chip-list{display:flex;flex-wrap:wrap;gap:6px;}
.chip-list li{font-size:13px;padding:3px 10px;border-radius:var(--radius-sm);background:var(--c-subtle);border:1px solid var(--c-border);}

/* ---------- Education ---------- */
.timeline{max-width:720px;border-left:2px solid var(--c-border-strong);margin-left:6px;padding-left:22px;}
.timeline li{position:relative;padding-bottom:22px;}
.timeline li:last-child{padding-bottom:0;}
.timeline li::before{
  content:'';position:absolute;left:-29px;top:6px;
  width:12px;height:12px;border-radius:50%;
  background:var(--c-bg);border:3px solid var(--c-accent);
}
.timeline-date{font-size:12px;color:var(--c-text-faint);}
.timeline h3{font-size:16px;margin:2px 0;}
.timeline p{color:var(--c-text-dim);font-size:13px;}

/* ---------- Certificates ---------- */
.award-list{display:grid;grid-template-columns:repeat(2,1fr);gap:8px;margin-bottom:8px;}
.award-list li{padding:16px 18px;border-left:3px solid var(--c-accent);}
.award-list h3{font-size:15px;margin-bottom:4px;}
.award-list p{font-size:13px;color:var(--c-text-dim);}
.training-list{font-size:13px;}
.cert-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:8px;}
.cert-card{display:flex;flex-direction:column;padding:12px;}
.cert-preview{display:block;width:100%;padding:0;aspect-ratio:16/11;border-radius:var(--radius-sm);overflow:hidden;background:var(--c-tint);margin-bottom:10px;border:1px solid var(--c-border);}
.cert-preview:hover{border-color:var(--c-accent);}
.cert-preview img{width:100%;height:100%;object-fit:cover;object-position:top;}
.cert-card h3{font-size:14px;margin-bottom:4px;line-height:1.35;}
.cert-card p{font-size:12px;color:var(--c-text-dim);}
.cert-preview img,.is-protected .lightbox-img-box img,.is-protected .lightbox-thumb img{
  pointer-events:none;
  -webkit-user-select:none;user-select:none;
  -webkit-touch-callout:none;-webkit-user-drag:none;
}
.cert-id{font-size:12px !important;margin-top:4px;overflow-wrap:anywhere;color:var(--c-text-faint) !important;}

/* ---------- Contact ---------- */
.contact-grid{display:grid;grid-template-columns:1fr 1.2fr;gap:28px;align-items:start;}
.contact-lead{color:var(--c-text-dim);margin-bottom:14px;}
.contact-list li{display:flex;align-items:center;gap:12px;padding:8px 4px;font-size:14px;overflow-wrap:anywhere;border-bottom:1px solid var(--c-border);}
.contact-list li:last-child{border-bottom:none;}
.contact-list svg{flex:none;color:var(--c-accent);}
.contact-list a:hover{color:var(--c-accent);text-decoration:underline;}
.contact-form{display:flex;flex-direction:column;align-items:flex-start;gap:14px;padding:18px;}
.form-row{display:grid;grid-template-columns:1fr 1fr;gap:14px;width:100%;}
.form-group{display:flex;flex-direction:column;gap:4px;width:100%;}
.form-group label{font-size:13px;}
.form-group input,.form-group textarea{
  width:100%;padding:6px 10px;border-radius:var(--radius-sm);
  background:rgba(255,255,255,.04);border:1px solid var(--c-border);border-bottom-color:rgba(255,255,255,.45);
}
.form-group textarea{resize:vertical;}
.form-group input:hover,.form-group textarea:hover{background:rgba(255,255,255,.07);}
.form-group input:focus,.form-group textarea:focus{outline:none;background:#1e1e1e;border-bottom:2px solid var(--c-accent);}
.form-group.invalid input,.form-group.invalid textarea{border-bottom:2px solid var(--c-error);}
.form-error{font-size:12px;color:var(--c-error);}
.form-error:empty{display:none;}
.form-status{font-size:13px;color:#6ccb5f;}
.form-status:empty{display:none;}
.form-status.error{color:var(--c-error);}

/* ---------- Dialogs (photo viewer and CV) ---------- */
.lightbox-modal,.cv-modal{
  position:fixed;inset:0;z-index:300;
  display:flex;align-items:center;justify-content:center;
  padding:16px;
  visibility:hidden;opacity:0;
  transition:opacity .15s,visibility .15s;
}
.lightbox-modal.active,.cv-modal.active{visibility:visible;opacity:1;}
.lightbox-modal{background:var(--c-overlay);}
.lightbox-content,.cv-modal-wrapper{
  display:flex;flex-direction:column;
  max-height:100%;overflow:hidden;
  background:var(--c-bg);border:1px solid var(--c-border-strong);border-radius:var(--radius);
  box-shadow:var(--shadow-win);
}
.lightbox-content{width:min(920px,100%);overflow-y:auto;}
.lightbox-bar,.cv-modal-header{
  display:flex;align-items:center;justify-content:space-between;gap:12px;
  min-height:40px;padding:4px 4px 4px 14px;background:#1c1c1c;font-size:12px;color:var(--c-text);
}
.lightbox-bar-right,.cv-header-actions{display:flex;align-items:center;gap:8px;flex:none;}
#lightboxCounter{color:var(--c-text-faint);}
#lightboxClose,#cvModalClose{width:46px;height:32px;border:none;background:none;border-radius:var(--radius-sm);}
#lightboxClose:hover,#cvModalClose:hover{background:var(--c-close);}
#lightboxClose svg,#cvModalClose svg{width:10px;height:10px;}
.lightbox-img-box{position:relative;display:flex;align-items:center;justify-content:center;background:#111;min-height:220px;}
.lightbox-img-box img{max-width:100%;max-height:60vh;width:auto;object-fit:contain;transition:opacity .15s;}
.lightbox-img-box img.is-loading{opacity:.3;}
.lightbox-nav{position:absolute;top:50%;transform:translateY(-50%);z-index:1;background:rgba(32,32,32,.8);}
.lightbox-prev{left:10px;}
.lightbox-next{right:10px;}
.lightbox-thumbnails{display:flex;gap:6px;padding:10px 14px 0;overflow-x:auto;}
.lightbox-thumbnails[hidden]{display:none;}
.lightbox-thumb{flex:none;width:52px;height:52px;padding:0;border-radius:var(--radius-sm);overflow:hidden;border:2px solid transparent;opacity:.6;}
.lightbox-thumb img{width:100%;height:100%;object-fit:cover;}
.lightbox-thumb:hover{opacity:1;}
.lightbox-thumb.active{opacity:1;border-color:var(--c-accent);}
.lightbox-info{padding:14px;}
.lightbox-info h3{font-size:16px;margin-bottom:4px;}
.lightbox-info p{font-size:13px;color:var(--c-text-dim);margin-bottom:6px;}

.cv-modal-backdrop{position:absolute;inset:0;background:var(--c-overlay);}
.cv-modal-wrapper{position:relative;width:min(820px,100%);}
.cv-modal-header h2{font-family:var(--font-ui);font-size:12px;font-weight:400;}
.cv-download-form{display:flex;flex-direction:column;gap:8px;padding:12px 16px;border-bottom:1px solid var(--c-border);font-size:13px;color:var(--c-text-dim);}
.cv-download-form[hidden]{display:none;}
.cv-download-row{display:flex;gap:8px;}
.cv-download-row input{flex:1;min-width:0;max-width:280px;padding:5px 10px;border-radius:var(--radius-sm);background:rgba(255,255,255,.04);border:1px solid var(--c-border);border-bottom-color:rgba(255,255,255,.45);}
.cv-download-row input:focus{outline:none;border-bottom:2px solid var(--c-accent);}
/* The CV looks like a page open in a PDF reader. */
.cv-modal-body{overflow-y:auto;padding:20px;background:#2b2b2b;}
.cv-paper{max-width:680px;margin:0 auto;padding:36px;border-radius:2px;background:#fff;color:#1c2430;font-size:13px;line-height:1.5;box-shadow:0 4px 16px rgba(0,0,0,.4);}
.cv-paper-head{text-align:center;padding-bottom:14px;margin-bottom:14px;border-bottom:2px solid #1c2430;}
.cv-paper-head h3{font-size:22px;}
.cv-paper-title{font-weight:600;color:#005a9e;}
.cv-paper-contacts{font-size:12px;color:#4a5564;margin-top:4px;}
.cv-paper section{margin-bottom:16px;}
.cv-paper section:last-child{margin-bottom:0;}
.cv-paper h4{font-size:13px;text-transform:uppercase;letter-spacing:.04em;color:#22344d;padding-bottom:3px;margin-bottom:8px;border-bottom:1px solid #cfd6df;}
.cv-row{display:flex;justify-content:space-between;gap:12px;}
.cv-row span{flex:none;color:#4a5564;font-size:12px;}
.cv-paper p + .cv-row{margin-top:8px;}
.cv-paper ul{list-style:disc;padding-left:18px;}
.cv-paper li{margin-bottom:3px;}

/* ---------- Ask Ryan (a flyout above the taskbar) ---------- */
.ai-chat-window{
  position:fixed;z-index:255;right:12px;bottom:calc(var(--taskbar-h) + 12px);
  display:flex;flex-direction:column;
  width:min(380px,calc(100vw - 24px));height:min(540px,calc(100dvh - var(--taskbar-h) - 24px));
  background:var(--c-acrylic);
  backdrop-filter:blur(40px) saturate(1.5);-webkit-backdrop-filter:blur(40px) saturate(1.5);
  border:1px solid var(--c-border-strong);border-radius:var(--radius);
  box-shadow:var(--shadow-win);overflow:hidden;
  visibility:hidden;opacity:0;transform:translateY(16px);
  transition:opacity .15s,visibility .15s,transform .2s cubic-bezier(.1,.9,.2,1);
}
html:not(.js) .ai-assistant-widget{display:none;}
.ai-chat-window.active{visibility:visible;opacity:1;transform:none;}
.ai-chat-header{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:12px 12px 12px 16px;}
.ai-chat-header h3{font-size:15px;}
.ai-chat-header p{font-size:12px;color:var(--c-text-faint);}
.ai-quick-prompts{display:flex;flex-wrap:wrap;gap:6px;padding:0 16px;}
.ai-prompt-chip{font-size:12px;padding:3px 10px;border-radius:14px;background:var(--c-subtle);border:1px solid var(--c-border);}
.ai-prompt-chip:hover{background:var(--c-subtle-hover);}
.ai-chat-body{flex:1;overflow-y:auto;padding:14px 16px;display:flex;flex-direction:column;gap:8px;}
.ai-msg{max-width:88%;padding:8px 12px;border-radius:var(--radius);font-size:13px;line-height:1.45;}
.ai-msg ul{list-style:disc;padding-left:16px;}
.ai-msg p + p{margin-top:6px;}
.ai-msg-bot{align-self:flex-start;background:rgba(255,255,255,.07);border:1px solid var(--c-border);}
.ai-msg-user{align-self:flex-end;background:var(--c-accent);color:var(--c-accent-ink);}
.ai-typing-indicator{padding:0 16px 8px;font-size:12px;color:var(--c-text-faint);}
.ai-typing-indicator[hidden]{display:none;}
.ai-chat-input-form{display:flex;gap:8px;padding:12px 16px;border-top:1px solid var(--c-border);}
.ai-chat-input{flex:1;min-width:0;padding:6px 10px;border-radius:var(--radius-sm);background:rgba(0,0,0,.25);border:1px solid var(--c-border);border-bottom-color:rgba(255,255,255,.45);font-size:13px;}
.ai-chat-input:focus{outline:none;border-bottom:2px solid var(--c-accent);}

/* ---------- Phone page ---------- */
/* Phones, and browsers without JavaScript, get a normal scrolling page: a
   sticky section menu, the terminal intro, then each section in turn. */
.phone-nav,.page-footer{display:none;}
html:not(.os){scroll-padding-top:60px;}
@media (prefers-reduced-motion:no-preference){
  html:not(.os){scroll-behavior:smooth;}
}
html:not(.os) .phone-nav{
  position:sticky;top:0;z-index:100;
  display:flex;align-items:center;gap:12px;height:52px;padding-left:16px;
  background:rgba(28,28,28,.9);
  backdrop-filter:blur(20px) saturate(1.4);-webkit-backdrop-filter:blur(20px) saturate(1.4);
  border-bottom:1px solid var(--c-border);
}
.phone-brand{display:flex;align-items:center;gap:8px;flex:none;font-weight:600;}
.phone-brand img{width:24px;height:24px;border-radius:5px;}
.phone-links{
  display:flex;gap:6px;min-width:0;overflow-x:auto;scrollbar-width:none;padding-right:16px;
  -webkit-mask-image:linear-gradient(to right,transparent,#000 12px,#000 calc(100% - 28px),transparent);
  mask-image:linear-gradient(to right,transparent,#000 12px,#000 calc(100% - 28px),transparent);
}
.phone-links::-webkit-scrollbar{display:none;}
.phone-links li:first-child{padding-left:12px;}
.phone-links a{
  display:block;white-space:nowrap;padding:4px 12px;border-radius:16px;font-size:13px;
  color:var(--c-text-dim);background:var(--c-subtle);border:1px solid var(--c-border);
}
.phone-links a.active{background:var(--c-accent);border-color:var(--c-accent);color:var(--c-accent-ink);}
html:not(.os) .terminal-app{min-height:0;padding:20px 16px 24px;border-bottom:1px solid var(--c-border);}
html:not(.os) .term-body{max-width:1080px;margin:0 auto;}
html:not(.os) .term-art{width:112px;justify-self:center;margin-top:4px;}
html:not(.os) .term-art img{
  aspect-ratio:1;border-radius:50%;object-position:center 12%;
  border:2px solid var(--t-green);
  box-shadow:0 0 0 4px rgba(74,222,128,.14),0 0 28px rgba(74,222,128,.25);
}
html:not(.os) .page-footer{display:block;padding:24px 16px 96px;text-align:center;font-size:12px;color:var(--c-text-faint);}
@media (max-width:760px){
  html:not(.os) .section{padding:32px 16px 36px;}
  html:not(.os) .section-title{font-size:24px;}
  html:not(.os) .section-title::after{
    content:'';display:block;width:32px;height:3px;margin-top:8px;
    border-radius:2px;background:var(--c-accent);
  }

  /* About: a wide, shorter photo, and the details in two columns. */
  html:not(.os) .about-photo{max-width:none;aspect-ratio:4/3;}
  html:not(.os) .about-photo img{object-position:center 62%;}
  html:not(.os) .info-grid{grid-template-columns:repeat(2,1fr);}
  html:not(.os) .info-grid div:nth-last-child(-n+2){border-bottom:none;}
  html:not(.os) .info-grid div{padding:10px 14px;}
  html:not(.os) .stats-row div{padding:10px 12px;}
  html:not(.os) .stats-row dt{font-size:11px;}

  /* Photo albums and certificates swipe sideways instead of stacking,
     which keeps the page much shorter. The next card peeks in at the edge. */
  html:not(.os) .gallery-grid,
  html:not(.os) .cert-grid{
    display:flex;gap:10px;
    margin:0 -16px;padding:2px 16px 8px;
    overflow-x:auto;overscroll-behavior-x:contain;
    scroll-snap-type:x mandatory;scroll-padding:0 16px;scrollbar-width:none;
  }
  html:not(.os) .gallery-grid::-webkit-scrollbar,
  html:not(.os) .cert-grid::-webkit-scrollbar{display:none;}
  html:not(.os) .gallery-grid > *,
  html:not(.os) .cert-grid > *{flex:0 0 78%;scroll-snap-align:start;}
  html:not(.os) .gallery-title{margin:24px 0 10px;}
  html:not(.os) .gallery-title::after{
    content:'Swipe for more \2192';
    content:'Swipe for more \2192' / '';
    display:block;margin-top:2px;font-size:12px;font-weight:400;color:var(--c-text-faint);
  }
}

/* The Ask Ryan button floats in the corner instead of sitting in a taskbar. */
html:not(.os) .ai-assistant-widget .tray-btn{
  position:fixed;right:16px;bottom:16px;z-index:200;
  width:52px;height:52px;border-radius:50%;
  background:#2b2b2b;border:1px solid var(--c-border-strong);box-shadow:0 8px 24px rgba(0,0,0,.5);
}
html:not(.os) .ai-assistant-widget .tray-btn svg{width:26px;height:26px;}
html:not(.os) .ai-assistant-widget .tray-btn::after{display:none;}
html:not(.os) .ai-chat-window{bottom:80px;}

/* Phones get a light page with a dark terminal at the top. Green is the
   main colour and blue the second one. The computer desktop keeps its own
   dark Windows theme. */
html:not(.os){
  --c-bg:#ffffff;
  --c-card:#ffffff;
  --c-card-hover:#f6fbf7;
  --c-tint:#eef2ef;
  --c-subtle:rgba(0,0,0,.04);
  --c-subtle-hover:rgba(0,0,0,.07);
  --c-border:rgba(0,0,0,.09);
  --c-border-strong:rgba(0,0,0,.16);
  --c-text:#14201a;
  --c-text-dim:#47524c;
  --c-text-faint:#6b746f;
  --c-accent:#15803d;
  --c-accent-hover:#166534;
  --c-accent-ink:#ffffff;
  --c-blue:#0b63c5;
  --c-green-soft:rgba(21,128,61,.08);
  --c-green-line:rgba(21,128,61,.22);
  --c-blue-soft:rgba(11,99,197,.07);
  --c-blue-line:rgba(11,99,197,.2);
  --c-gradient:linear-gradient(90deg,#16a34a,#0b63c5);
  --c-error:#c42b1c;
  --c-overlay:rgba(0,0,0,.45);
  --c-acrylic:rgba(250,252,251,.95);
  --c-shadow:0 1px 2px rgba(16,40,24,.05),0 4px 14px rgba(16,40,24,.06);
  --shadow-win:0 24px 48px rgba(0,0,0,.18),0 2px 12px rgba(0,0,0,.1);
  color-scheme:light;
  background:#fff;
}
html:not(.os) :focus-visible{outline-color:var(--c-accent);}
html:not(.os) *{scrollbar-color:rgba(0,0,0,.3) transparent;}
html:not(.os) ::selection{background:#bbf7d0;color:#052e16;}

/* Menu bar */
html:not(.os) .phone-nav{background:rgba(255,255,255,.9);box-shadow:0 1px 0 rgba(0,0,0,.04);}
html:not(.os) .phone-links a.active{background:var(--c-gradient);border-color:transparent;}

/* The terminal stays dark, with the green glowing from the top. */
html:not(.os) .terminal-app{
  --c-text:#ffffff;
  --c-subtle:rgba(255,255,255,.06);
  --c-subtle-hover:rgba(255,255,255,.1);
  --c-border:rgba(255,255,255,.1);
  --c-accent:#4ade80;
  --c-accent-hover:#6ee7a0;
  --c-accent-ink:#052e16;
  color-scheme:dark;
  background:
    radial-gradient(120% 70% at 50% 0%,rgba(74,222,128,.16),transparent 65%),
    linear-gradient(180deg,#0c0c0c,#08110b);
  border-bottom:none;
}
html:not(.os) .terminal-app ::selection{background:#4ade80;color:#052e16;}
html:not(.os) .terminal-app :focus-visible{outline-color:#4ade80;}
html:not(.os) .terminal-app .btn-primary{box-shadow:0 0 18px rgba(74,222,128,.35);}
html:not(.os) .social-icon:hover{color:#4ade80;border-color:rgba(74,222,128,.4);}

/* The project demos stay dark consoles too, with a fixed-height screen. */
html:not(.os) .demo-app{
  --c-text:#ffffff;
  --c-text-dim:#c5c5c5;
  --c-text-faint:#9a9a9a;
  --c-tint:#161616;
  --c-subtle:rgba(255,255,255,.06);
  --c-subtle-hover:rgba(255,255,255,.1);
  --c-border:rgba(255,255,255,.1);
  color-scheme:dark;
  height:auto;
}
html:not(.os) .demo-screen{flex:none;height:min(70vh,560px);font-size:12px;}
html:not(.os) .bank-stage,html:not(.os) .mon-stage{flex:none;height:min(78vh,680px);}
html:not(.os) .esp-stage{flex:none;}
html:not(.os) .demo-app ::selection{background:#4ade80;color:#052e16;}

/* Section headings: a green-to-blue underline. */
html:not(.os) .section{border-bottom:none;}
html:not(.os) .section-title::after{width:44px;background:var(--c-gradient);}

/* Cards are white and lift off the page with a soft shadow. */
html:not(.os) :is(.card,.job,.gallery-card,.project-card,.skill-group,.cert-card,.award-list li,.info-grid,.stats-row div,.contact-form){box-shadow:var(--c-shadow);}
html:not(.os) .award-list li{border-left-color:var(--c-accent);}
html:not(.os) .stats-row div{background:linear-gradient(160deg,#f0fdf4,#eff6ff);}
html:not(.os) .stats-row dd{
  background:var(--c-gradient);-webkit-background-clip:text;background-clip:text;
  color:transparent;
}
html:not(.os) .job-date{background:var(--c-green-soft);color:var(--c-accent-hover);}
html:not(.os) .chip-list li{background:var(--c-green-soft);border-color:var(--c-green-line);color:#14532d;}
html:not(.os) .badge{background:var(--c-blue-soft);border-color:var(--c-blue-line);color:#0a4f9e;}
html:not(.os) .filter-btn.active{background:var(--c-gradient);border-color:transparent;}

/* Links are blue, so they stand apart from the green highlights. */
html:not(.os) :is(.text-link,.gallery-count,.contact-list a:hover){color:var(--c-blue);}
html:not(.os) .contact-list svg{color:var(--c-accent);}

/* Forms */
html:not(.os) :is(.form-group input,.form-group textarea,.cv-download-row input,.ai-chat-input){
  background:#fff;border-color:var(--c-border-strong);border-bottom-color:rgba(0,0,0,.45);
}
html:not(.os) :is(.form-group input,.form-group textarea):hover{background:#fafafa;}
html:not(.os) :is(.form-group input,.form-group textarea):focus{background:#fff;}
html:not(.os) .form-status{color:#15803d;}

/* Dialogs and the chat */
html:not(.os) :is(.lightbox-bar,.cv-modal-header){background:#f3f5f4;}
html:not(.os) .lightbox-nav{background:rgba(255,255,255,.85);}
html:not(.os) .cv-modal-body{background:#e8ebe9;}
html:not(.os) .cv-paper{box-shadow:0 2px 10px rgba(0,0,0,.15);}
html:not(.os) .ai-msg-bot{background:var(--c-subtle);}
html:not(.os) .ai-msg-user{background:var(--c-accent);}
html:not(.os) .ai-assistant-widget .tray-btn{background:#fff;box-shadow:0 6px 20px rgba(16,40,24,.18);}

html:not(.os) .page-footer{background:#0c0c0c;color:#8a8a8a;}

/* ---------- Narrow windows (container queries) ---------- */
@container (max-width:820px){
  .gallery-grid,.projects-grid,.cert-grid{grid-template-columns:repeat(2,1fr);}
}
@container (max-width:640px){
  .about-grid,.contact-grid{grid-template-columns:1fr;gap:20px;}
  .about-photo{max-width:240px;}
  .project-featured{flex-direction:column;}
  .project-shot{flex:none;}
  .project-shot img{height:auto;}
  .skills-grid,.form-row{grid-template-columns:1fr;}
}
@container (max-width:480px){
  .gallery-grid,.projects-grid,.cert-grid,.award-list,.info-grid{grid-template-columns:1fr;}
  .info-grid div:nth-last-child(2){border-bottom:1px solid var(--c-border);}
  .stats-row dd{font-size:20px;}
  .job-head{flex-direction:column;gap:6px;}
  .section{padding:20px 18px 28px;}
}

/* ---------- Virtual Machines app ---------- */
/* Each desktop's wallpaper, also used for the previews in the app. The Kali
   wallpaper lies over a dark gradient, which shows while it loads or if the
   file is missing. */
:root{
  --wall-windows:#9fbbd2 url("images/wallpaper-bloom.webp") 55% 50% / cover no-repeat;
  --wall-kali:
    url("images/wallpaper-kali.webp") center / cover no-repeat,
    radial-gradient(55% 45% at 50% 48%,rgba(54,123,240,.3),transparent 70%),
    linear-gradient(115deg,transparent 38%,rgba(54,123,240,.13) 50%,transparent 62%),
    repeating-linear-gradient(0deg,rgba(120,170,255,.05) 0 1px,transparent 1px 48px),
    repeating-linear-gradient(90deg,rgba(120,170,255,.05) 0 1px,transparent 1px 48px),
    radial-gradient(120% 100% at 50% 100%,#0d1b33 0%,#070b14 60%,#030509 100%);
  /* macOS Sequoia "Sequoia Forest", resized to 2560x1440. */
  --wall-macos:#24301c url("images/wallpaper-macos.webp") center / cover no-repeat;
}
.vm-shot-windows{background:var(--wall-windows);}
.vm-shot-kali{background:var(--wall-kali);}
.vm-shot-macos{background:var(--wall-macos);}

html:not(.os) .vm-app{display:none;}
.vm-app{display:flex;flex-direction:column;height:100%;background:var(--c-bg);container-type:inline-size;}
.vm-toolbar{display:flex;align-items:center;gap:12px;flex:none;padding:8px 12px;background:var(--c-tint);border-bottom:1px solid var(--c-border);}
.vm-tool{display:inline-flex;align-items:center;gap:6px;height:32px;padding:0 12px;border-radius:var(--radius-sm);font-size:13px;font-weight:600;}
.vm-tool:hover:not(:disabled){background:var(--c-subtle-hover);}
.vm-tool:disabled{opacity:.45;cursor:default;}
.vm-tool svg{width:18px;height:18px;}
.vm-tool-note{font-size:12px;color:var(--c-text-faint);}
.vm-layout{flex:1;min-height:380px;display:grid;grid-template-columns:220px minmax(0,1fr);}
.vm-list{display:flex;flex-direction:column;gap:2px;padding:8px;overflow-y:auto;border-right:1px solid var(--c-border);}
.vm-item{display:flex;align-items:center;gap:10px;width:100%;padding:8px;border-radius:var(--radius-sm);text-align:left;font-size:13px;font-weight:600;}
.vm-item:hover{background:var(--c-subtle);}
.vm-item.is-selected{background:color-mix(in srgb,var(--c-accent) 24%,transparent);}
.vm-item small{display:block;font-size:11px;font-weight:400;color:var(--c-text-faint);}
.vm-item small.is-running{color:#4ade80;}
.vm-thumb{width:52px;height:32px;flex:none;border-radius:4px;border:1px solid rgba(255,255,255,.18);}
.vm-detail{padding:16px 20px 20px;overflow-y:auto;}
.vm-preview{
  display:flex;align-items:flex-end;width:100%;max-width:300px;aspect-ratio:16/9;padding:8px;
  border:1px solid var(--c-border-strong);border-radius:6px;
}
.vm-preview span{padding:2px 8px;border-radius:10px;background:rgba(0,0,0,.55);font-size:11px;}
.vm-name{margin:14px 0 8px;font-size:18px;}
.vm-specs{display:grid;grid-template-columns:max-content 1fr;gap:4px 16px;font-size:13px;}
.vm-specs dt{color:var(--c-text-faint);}
@container (max-width:540px){
  .vm-layout{grid-template-columns:1fr;grid-template-rows:auto 1fr;}
  .vm-list{border-right:0;border-bottom:1px solid var(--c-border);}
  .vm-tool-note{display:none;}
}

/* ---------- Project demos (Hero Drafting, Playlist Manager) ---------- */
/* Looks like a Windows console: black screen, grey monospaced text. The output
   keeps the C++ program's column layout, so narrow screens scroll it sideways. */
.demo-app{display:flex;flex-direction:column;height:100%;background:var(--t-bg);color:var(--t-fg);}
.demo-app[hidden]{display:none;}
.demo-toolbar{display:flex;flex-wrap:wrap;align-items:center;gap:8px 16px;flex:none;padding:8px 12px;background:var(--c-tint);border-bottom:1px solid var(--c-border);}
.demo-note{flex:1 1 260px;font-size:12px;color:var(--c-text-dim);}
.demo-actions{display:flex;flex-wrap:wrap;gap:6px;}
/* On the desktop the window's own close button does this. */
.os .demo-close{display:none;}
.demo-screen{
  flex:1;min-height:0;overflow:auto;overscroll-behavior:contain;padding:12px 14px 16px;
  font-family:var(--font-mono);font-size:13px;line-height:1.4;white-space:pre;cursor:text;
}
.demo-screen ::selection{background:var(--t-fg);color:var(--t-bg);}
/* Menu lines in the latest menu can be clicked instead of typing the number. */
.demo-opt{white-space:pre;text-align:left;cursor:pointer;border-radius:2px;}
.demo-opt:hover,.demo-opt:focus-visible{background:rgba(74,222,128,.16);color:#fff;outline:none;}
.demo-form{display:inline;}
.demo-input{width:min(40ch,100%);padding:0;outline:none;color:#fff;caret-color:var(--t-green);}
.demo-legend{flex:none;padding:8px 12px;font-size:12px;color:var(--c-text-faint);background:var(--c-tint);border-top:1px solid var(--c-border);}
.demo-legend code{font-family:var(--font-mono);font-size:11.5px;color:var(--c-text-dim);}
/* Console colours the C++ programs set, from the Windows Terminal "Campbell" scheme. */
.demo-screen .k-cyan{color:#61d6d6;}
.demo-screen .k-green{color:#16c60c;}
.demo-screen .k-yellow{color:#f9f1a5;}
.demo-screen .k-gold{color:#c19c00;}
.demo-screen .k-blue{color:#3b78ff;}
.demo-screen .k-red{color:#e74856;}
.demo-screen .k-magenta{color:#b4009e;}
.demo-screen .k-bg-blue{background:#0037da;}
.demo-screen .k-bg-red{background:#c50f1f;}

/* ---------- Bank System demo ---------- */
/* Looks like the original WinForms app: DodgerBlue and AliceBlue forms, Tahoma
   text, grey buttons, and Windows message boxes. */
.bank-app{position:relative;}
.bank-stage{
  flex:1;min-height:0;overflow:auto;overscroll-behavior:contain;container-type:inline-size;
  background:#f0f0f0;color:#000;font-family:Tahoma,Verdana,'Segoe UI',sans-serif;font-size:13px;line-height:1.35;color-scheme:light;
}
/* The window sizes itself to its content when it first opens, before the app
   has shown a screen, so the stage needs a height of its own. */
.os .bank-stage{min-height:480px;}
.bank-stage [hidden]{display:none !important;}
.bank-stage :focus-visible{outline:2px dotted #000;outline-offset:1px;}
.bank-stage ::selection{background:#0078d7;color:#fff;}
.bank-screen{min-height:100%;display:flex;flex-direction:column;gap:14px;padding:16px 20px 24px;}
.bank-screen.is-blue{background:#1e90ff;}
.bank-screen.is-light{background:#f0f8ff;}
.bank-brand{font:700 clamp(22px,6cqw,36px)/1.15 Arial,sans-serif;color:#0000c0;text-align:center;}
.bank-title,.bank-sub{text-align:center;font-size:16px;font-weight:700;color:#00008b;}
.bank-welcome{text-align:center;font-size:15px;}
.bank-progress{height:17px;background:#e6e6e6;border:1px solid #bcbcbc;}
.bank-progress i{display:block;width:0;height:100%;background:#06b025;}
.bank-loadrow{display:flex;justify-content:space-between;gap:12px;font-size:15px;color:#0000ff;}
.is-blue .bank-loadrow{color:#00008b;}

.bank-home{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,320px);gap:20px;align-items:start;}
.bank-menu{display:grid;gap:10px;}
.bank-big{
  min-height:52px;padding:8px 16px;border:1px solid #0b5fb3;border-radius:2px;
  background:#1e90ff;box-shadow:inset 0 0 0 1px rgba(255,255,255,.45);
  font:700 16px 'Microsoft Sans Serif',Tahoma,sans-serif;color:#0000cd;
}
.bank-big:hover{background:#45a5ff;}
.bank-lang{margin-top:auto;}

.bank-panel{display:grid;gap:10px;padding:14px;background:#fff;border:1px solid #a0a0a0;}
.bank-panel label{display:grid;gap:3px;}
.bank-panel label > span{font-weight:700;}
.bank-stage input:not([type=checkbox]),.bank-stage select,.bank-stage output{
  display:block;width:100%;min-height:28px;padding:2px 6px;border:1px solid #7a7a7a;border-radius:0;
  background:#fff;color:#000;font:14px Tahoma,Verdana,sans-serif;
}
.bank-stage input::placeholder{color:#a9a9a9;}
.bank-stage output{line-height:22px;background:#e3eef9;overflow-wrap:anywhere;}
.bank-panel label.bank-check{display:flex;align-items:center;gap:6px;}
.bank-panel label.bank-check > span{font-weight:400;}
.bank-register,.bank-info{grid-template-columns:repeat(2,minmax(0,1fr));column-gap:16px;}
.bank-wide{grid-column:1/-1;}
.bank-account{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:14px;align-items:start;}
.bank-account .bank-info,.bank-money{grid-template-columns:1fr;}
.bank-money output{font-size:16px;}

.bank-row{display:flex;flex-wrap:wrap;align-items:center;gap:8px;}
.wf-btn{
  min-height:30px;padding:4px 14px;border:1px solid #adadad;border-radius:2px;
  background:#e1e1e1;color:#000;font:700 13px Tahoma,Verdana,sans-serif;
}
.wf-btn:hover{background:#e5f1fb;border-color:#0078d7;}
.wf-btn.is-green{color:#2e8b57;}
.wf-btn.is-red{color:#e00;}
.wf-btn.is-darkred{color:#8b0000;}
.wf-btn.is-blue{color:#0000ff;}
.bank-act{min-width:140px;min-height:48px;font-size:15px;}
.bank-link{padding:0;color:#0000ff;font-size:14px;text-decoration:underline;justify-self:start;}
.is-blue .bank-link{color:#00008b;}
.bank-hint{font-size:12px;color:#444;}
.bank-small{font-size:11px;color:#228b22;}
.bank-backbar{width:100%;min-height:30px;border:1px solid #d9a0aa;background:#ffb6c1;font:700 13px Tahoma,Verdana,sans-serif;}
.bank-backbar:hover{background:#ffc6cf;}
.bank-welcome-user{font-size:14px;font-weight:700;color:#00008b;}
.bank-welcome-user .bank-link{font-weight:700;}

@container (max-width:620px){
  .bank-home,.bank-register,.bank-info,.bank-account{grid-template-columns:1fr;}
  .bank-screen{padding:14px 12px 20px;}
}

/* ---------- Computer Monitoring System demo ---------- */
/* Looks like the original window: a gray form, etched group boxes, green
   buttons, and dark red PC labels. The station table scrolls sideways on
   narrow screens instead of shrinking. */
.mon-app{position:relative;}
.mon-speed{white-space:nowrap;}
.mon-speed select{margin-left:4px;padding:1px 4px;border:1px solid var(--c-border);border-radius:var(--radius-sm);background:var(--c-subtle);color:inherit;font-size:12px;}
.mon-stage{
  flex:1;min-height:0;overflow:auto;overscroll-behavior:contain;container-type:inline-size;
  background:#808080;color:#000;font:700 12px 'Microsoft Sans Serif',Tahoma,Verdana,sans-serif;color-scheme:light;
}
.os .mon-stage{min-height:480px;}
.mon-stage [hidden]{display:none !important;}
.mon-stage :focus-visible{outline:2px dotted #000;outline-offset:1px;}
.mon-form{position:relative;display:flex;flex-direction:column;gap:10px;min-height:100%;padding:12px 16px 18px;}
.mon-title{text-align:center;font:italic 900 22px/1.2 Elephant,'Bookman Old Style',Georgia,serif;color:#00008b;letter-spacing:.5px;}
.mon-group{min-width:0;padding:8px 12px 12px;border:2px groove #d4d4d4;}
.mon-group legend{padding:0 4px;font-size:12px;}
.mon-stage output,.mon-stage input:not([type=checkbox]),.mon-stage select{
  display:inline-block;min-width:56px;min-height:22px;padding:1px 4px;border:1px solid #7a7a7a;border-radius:0;
  background:#fff;color:#000;font:400 12px 'Microsoft Sans Serif',Tahoma,sans-serif;line-height:18px;vertical-align:middle;
}
.mon-stage output{text-align:right;}
.mon-stage output:empty::before{content:"\200b";}

.mon-top{display:grid;grid-template-columns:minmax(0,auto) minmax(0,1fr) auto;gap:10px 24px;align-items:start;}
.mon-money{display:grid;gap:8px;}
.mon-line{display:flex;flex-wrap:wrap;align-items:center;gap:6px 8px;}
.mon-line > span{min-width:150px;text-align:right;}
.mon-line output{background:#f0f0f0;min-width:70px;}
.mon-middle{display:grid;gap:14px;align-content:start;}
.mon-status{display:flex;flex-wrap:wrap;gap:4px 28px;}
.mon-buttons{display:flex;flex-wrap:wrap;gap:12px;}
.mon-clock{display:grid;gap:4px;justify-items:center;}
.mon-clock output{text-align:center;font-weight:700;}

.mon-table-wrap{overflow-x:auto;}
.mon-table{border-collapse:separate;border-spacing:6px 4px;white-space:nowrap;}
.mon-table th{font-size:11px;text-align:center;}
.mon-table .mon-units th{color:#3a3a3a;}
.mon-table td output{width:44px;min-width:0;text-align:center;background:#f0f0f0;}
.mon-table td output.is-wide{width:64px;}
.mon-table td output.is-money{width:72px;text-align:right;background:#fff;}
.mon-pc{display:inline-block;padding:2px 6px;background:#8b0000;font-weight:700;}
.mon-foot{display:flex;flex-wrap:wrap;align-items:center;gap:8px;margin-top:6px;}
.mon-foot output{background:#f0f0f0;min-width:80px;}
.mon-foot .wf-btn{margin-left:auto;}

.mon-stage .wf-btn{font:700 11px 'Microsoft Sans Serif',Tahoma,sans-serif;}
.mon-stage .wf-btn:disabled{opacity:.55;cursor:default;}
.mon-login{background:#0f0;color:#0000cd;}
.mon-green{background:#32cd32;color:#0000cd;}
.mon-paid{color:#008000;}
.mon-sky{min-height:40px;background:#87cefa;}
.mon-lavender{min-height:30px;background:#e6e6fa;color:#1e90ff;}
.mon-top .mon-lavender{min-height:40px;color:#000;}

/* The Snacks/Other services panel covers the form, like the original Panel1. */
.mon-panel{position:absolute;inset:150px 16px 16px;z-index:2;display:flex;flex-direction:column;padding:10px;background:#808080;border:1px solid #5a5a5a;}
.mon-tabs{display:flex;flex-wrap:wrap;gap:2px;}
.mon-tabs button{padding:3px 8px;border:1px solid #9a9a9a;border-bottom:0;background:#e9e9e9;font:700 11px 'Microsoft Sans Serif',Tahoma,sans-serif;}
.mon-tabs button[aria-selected="true"]{background:#bc8f8f;}
.mon-tab{flex:1;min-height:0;overflow:auto;display:flex;flex-direction:column;gap:12px;padding:14px;background:#bc8f8f;border:1px solid #9a9a9a;}
.mon-snacks{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:10px;}
.mon-snacks fieldset{display:grid;gap:8px;padding:10px;background:#d3d3d3;border:2px groove #eee;}
.mon-snacks label{display:flex;align-items:center;gap:6px;}
.mon-snacks label output{margin-left:auto;}
.mon-prices{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:6px 16px;}
.mon-prices h4{grid-column:span 1;font-size:12px;text-align:center;}
.mon-prices .mon-col{display:grid;gap:6px;align-content:start;}
.mon-prices label{display:flex;align-items:center;justify-content:space-between;gap:8px;}
.mon-prices input{width:56px;}
.mon-tip,.mon-empty p{font-weight:400;}
.mon-empty p{max-width:520px;padding:12px;background:#d3d3d3;border:2px groove #eee;}
.mon-end{display:flex;justify-content:flex-end;}
.mon-closed{display:grid;place-content:center;gap:12px;min-height:100%;padding:24px;text-align:center;font-size:14px;}

@container (max-width:720px){
  .mon-top{grid-template-columns:1fr;}
  .mon-clock{justify-items:start;grid-auto-flow:column;justify-content:start;}
  .mon-snacks,.mon-prices{grid-template-columns:1fr;}
  .mon-line > span{min-width:0;text-align:left;}
  .mon-panel{inset:8px;}
}

/* MessageBox and InputBox. They cover the whole demo, like a modal dialog. */
.wf-dialog{position:absolute;inset:0;z-index:5;display:flex;align-items:center;justify-content:center;padding:16px;background:rgba(0,0,0,.3);}
.wf-dialog[hidden]{display:none;}
.wf-box{width:min(400px,100%);background:#fff;color:#000;border:1px solid #888;box-shadow:0 10px 30px rgba(0,0,0,.35);font:13px 'Segoe UI',Tahoma,sans-serif;}
.wf-box-title{padding:8px 12px;font-size:12px;border-bottom:1px solid #e5e5e5;}
.wf-box-body{display:flex;gap:12px;padding:18px 14px;}
.wf-box-body > div{flex:1;min-width:0;}
.wf-box-body p{white-space:pre-line;overflow-wrap:anywhere;}
.wf-icon{display:flex;align-items:center;justify-content:center;flex:none;width:32px;height:32px;border-radius:50%;color:#fff;font:700 17px 'Segoe UI',sans-serif;}
.wf-icon[data-icon="info"]{background:#0067c0;}
.wf-icon[data-icon="info"]::before{content:"i";}
.wf-icon[data-icon="error"]{background:#c42b1c;}
.wf-icon[data-icon="error"]::before{content:"\2715";}
.wf-icon[data-icon="warning"]{background:#ffb900;color:#000;}
.wf-icon[data-icon="warning"]::before{content:"!";}
.wf-box-input{margin-top:10px;}
.wf-box-buttons{display:flex;justify-content:flex-end;gap:8px;padding:10px 14px;background:#f0f0f0;border-top:1px solid #dfdfdf;}
.wf-box-buttons .wf-btn{min-width:80px;font-weight:400;}
.wf-box-buttons .wf-btn[hidden]{display:none;}
.wf-box [hidden]{display:none !important;}

/* Startup picker: choose a desktop before it opens. Sits above the loading screen. */
.os-picker{
  position:fixed;inset:0;z-index:1001;display:flex;align-items:center;justify-content:center;
  padding:24px 16px;overflow-y:auto;background:#000;color:#fff;font-family:var(--font-ui);
  transition:opacity .3s ease;animation:os-picker-in .3s ease;
}
.os-picker[hidden]{display:none;}
.os-picker.is-done{opacity:0;pointer-events:none;}
@keyframes os-picker-in{from{opacity:0;}}
.os-picker-inner{display:flex;flex-direction:column;align-items:center;width:min(720px,100%);margin:auto;text-align:center;}
.os-picker-logo{width:56px;height:56px;border-radius:14px;}
.os-picker-title{margin:20px 0 6px;font-size:24px;font-weight:600;}
.os-picker-sub{margin:0 0 28px;max-width:46ch;font-size:14px;color:var(--c-text-dim);}
.os-picker-list{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:16px;width:100%;}
.os-pick{
  display:flex;flex-direction:column;align-items:stretch;gap:4px;padding:10px 10px 14px;
  border:1px solid rgba(255,255,255,.12);border-radius:10px;background:#141414;
  text-align:left;transition:background .15s ease,border-color .15s ease,transform .15s ease;
}
.os-pick:hover{background:#1f1f1f;border-color:rgba(255,255,255,.3);transform:translateY(-2px);}
.os-pick:active{transform:translateY(0);}
.os-pick:focus-visible{outline:2px solid var(--c-accent);outline-offset:3px;border-radius:10px;}
.os-pick-shot{display:block;aspect-ratio:16/10;margin-bottom:8px;border-radius:6px;border:1px solid rgba(255,255,255,.12);}
.os-pick-name{display:flex;align-items:center;gap:8px;font-size:15px;font-weight:600;}
.os-pick-name small{padding:1px 7px;border-radius:9px;background:var(--c-accent);color:var(--c-accent-ink);font-size:11px;font-weight:600;}
.os-pick-note{font-size:12px;color:var(--c-text-faint);}
.os-picker-count{margin:28px 0 10px;font-size:13px;color:var(--c-text-faint);}
.os-picker-count b{color:#fff;font-variant-numeric:tabular-nums;}
.os-picker-bar{display:block;width:240px;max-width:100%;height:3px;overflow:hidden;border-radius:2px;background:#2a2a2a;}
.os-picker-bar i{display:block;height:100%;background:#fff;transform-origin:left;transition:transform .2s linear;}
@media (max-width:620px){
  .os-picker-list{grid-template-columns:1fr;}
  .os-pick{display:grid;grid-template-columns:96px 1fr;column-gap:12px;align-items:center;}
  .os-pick-shot{grid-row:span 2;margin:0;}
}

/* Boot screen shown while a machine starts. */
.vm-boot{
  position:fixed;inset:0;z-index:900;display:flex;align-items:center;justify-content:center;
  background:#000;color:#fff;transition:opacity .4s ease;
}
.vm-boot[hidden]{display:none;}
.vm-boot.is-done{opacity:0;pointer-events:none;}
.vm-boot-win,.vm-boot-mac{display:flex;flex-direction:column;align-items:center;gap:56px;}
.vm-boot img{width:72px;height:72px;border-radius:16px;}
.vm-boot-dots{position:relative;width:36px;height:36px;}
.vm-boot-dots i{position:absolute;inset:0;animation:vm-spin 1.8s cubic-bezier(.55,.1,.45,.9) infinite;}
.vm-boot-dots i::before{content:'';position:absolute;left:50%;top:0;width:5px;height:5px;margin-left:-2.5px;border-radius:50%;background:#fff;}
.vm-boot-dots i:nth-child(2){animation-delay:.1s;}
.vm-boot-dots i:nth-child(3){animation-delay:.2s;}
.vm-boot-dots i:nth-child(4){animation-delay:.3s;}
.vm-boot-dots i:nth-child(5){animation-delay:.4s;}
@keyframes vm-spin{to{transform:rotate(360deg);}}
.vm-boot-bar{width:180px;height:5px;overflow:hidden;border-radius:3px;background:#333;}
.vm-boot-bar i{display:block;width:0;height:100%;background:#fff;animation:vm-fill 2.2s ease-in-out forwards;}
@keyframes vm-fill{to{width:100%;}}
.vm-boot-kali{align-items:flex-start;justify-content:flex-start;padding:24px 28px;}
.vm-boot-log{font:13px/1.7 var(--font-mono);color:#d0d0d0;}
.vm-boot-log p{opacity:0;animation:term-show .01s linear forwards;animation-delay:calc(var(--i) * 280ms);}
.vm-boot-log b{color:#4ade80;font-weight:400;}

/* ---------- ESP32 MQTT simulation ---------- */
/* The board and the Serial Monitor on the left, the dashboard and the broker
   log on the right, and the flow strip across the top. One column on narrow
   windows. */
.esp-sound{display:inline-flex;align-items:center;gap:6px;font-size:12px;color:var(--c-text-dim);cursor:pointer;}
.esp-sound input{accent-color:var(--c-accent);}
.esp-stage{--esp-line:rgba(255,255,255,.2);flex:1;min-height:0;overflow:auto;overscroll-behavior:contain;container-type:inline-size;padding:10px;background:var(--t-bg);}
.os .esp-stage{min-height:480px;}
/* In a window the grid fills the stage, so the broker log and the Serial
   Monitor scroll inside their panels instead of stretching the page. */
.os .esp-grid{height:100%;min-height:560px;}
html:not(.os) .esp-log{max-height:260px;}
html:not(.os) .esp-serial-out{flex:none;height:260px;}
.esp-grid{
  display:grid;gap:10px;min-height:100%;
  grid-template-columns:minmax(0,1fr) minmax(0,1.1fr);
  grid-template-rows:auto auto minmax(0,1fr);
  grid-template-areas:"flow flow" "board dash" "serial dash";
}
.esp-panel{display:flex;flex-direction:column;min-width:0;min-height:0;padding:10px 12px;border:1px solid var(--c-border);border-radius:var(--radius);background:var(--c-tint);}
.esp-panel-title{display:flex;flex-wrap:wrap;align-items:center;gap:6px 8px;margin-bottom:8px;font-size:12.5px;font-weight:600;color:var(--c-text);}
.esp-baud{font:400 11px var(--font-mono);color:var(--c-text-faint);}
.esp-chip{display:inline-flex;align-items:center;gap:6px;padding:2px 9px;border-radius:999px;background:var(--c-subtle);font-size:11.5px;font-weight:500;color:var(--c-text-dim);}
.esp-chip::before{content:"";width:7px;height:7px;border-radius:50%;background:var(--t-dim);}
.esp-chip[data-state=ok]::before{background:var(--t-green);box-shadow:0 0 6px rgba(74,222,128,.7);}
.esp-chip[data-state=bad]::before{background:var(--t-red);}
.esp-chip[data-state=wait]::before{background:var(--t-yellow);}

/* The flow strip: messages ride along the dashed links as pills. */
.esp-flow{grid-area:flow;display:flex;align-items:center;padding:12px 14px;border:1px solid var(--c-border);border-radius:var(--radius);background:var(--c-tint);}
.esp-node{position:relative;z-index:1;flex:none;background:var(--c-tint);padding:4px 10px;border:1px solid var(--esp-line);border-radius:999px;font:600 12px var(--font-mono);color:var(--c-text);}
.esp-node.is-broker{border-color:rgba(97,214,214,.45);color:var(--t-cyan);}
.esp-lane{position:relative;flex:1;min-width:40px;height:2px;margin:0 8px;background:repeating-linear-gradient(90deg,var(--esp-line) 0 6px,transparent 6px 12px);}
.esp-pill{
  position:absolute;top:50%;left:0;translate:-50% -50%;padding:1px 7px;border-radius:999px;
  font:600 10.5px/1.5 var(--font-mono);white-space:nowrap;pointer-events:none;
  background:#4ade80;color:#052e16;box-shadow:0 0 10px rgba(0,0,0,.5);
}
.esp-pill.is-dash{background:#61d6d6;color:#062a2a;}
.esp-pill.is-will{background:#e74856;color:#fff;}

/* The board drawing */
.esp-board-panel{grid-area:board;}
.esp-board{flex:1;display:flex;align-items:center;justify-content:center;}
.esp-svg{display:block;width:100%;height:auto;max-height:250px;}
.esp-pcb{fill:#1d2a3d;stroke:#0d1522;stroke-width:2;}
.esp-usb{fill:#9ca3af;}
.esp-antenna{fill:none;stroke:#c9a227;stroke-width:1.6;}
.esp-shield{fill:#c3c7cd;stroke:#8d939b;}
.esp-pin{fill:#c9a227;}
.esp-tact{fill:#e5e7eb;stroke:#6b7280;}
.esp-pwr{fill:#ef4444;}
.esp-svg text{font-family:var(--font-mono);}
.esp-chipname{font-size:8px;font-weight:700;fill:#4b5563;}
.esp-silk{font-size:5.5px;fill:#cbd5e1;}
.esp-silk.is-big{font-size:7px;letter-spacing:.5px;}
.esp-chipname + .esp-silk{fill:#6b7280;}
.esp-pinname{font-size:5.5px;fill:#fde68a;}
.esp-label{font-size:8.5px;fill:var(--c-text-dim);}
.esp-wire{fill:none;stroke-width:2.5;stroke-linecap:round;stroke-linejoin:round;}
.esp-wire.is-gnd{stroke:#737373;}
.esp-wire.is-buzzer{stroke:#eab308;}
.esp-wire.is-led{stroke:#22c55e;}
.esp-wire.is-button{stroke:#3b82f6;}
.esp-resistor rect{fill:#d6c29b;}
.esp-resistor path{stroke-width:1.6;}
.esp-leg{stroke:#a3a3a3;stroke-width:2;stroke-linecap:round;}
.esp-led-body{fill:#5b1414;stroke:#2a0808;transition:fill .12s;}
.esp-led.is-on .esp-led-body{fill:#ff4d4d;}
.esp-led-glow{opacity:0;transition:opacity .12s;}
.esp-led.is-on .esp-led-glow{opacity:1;}
.esp-buzz-body{fill:#111;stroke:#404040;stroke-width:2;}
.esp-ring{fill:none;stroke:#f5c065;stroke-width:1.5;opacity:0;transform-box:fill-box;transform-origin:center;}
.esp-buzzer.is-on .esp-ring{opacity:.75;animation:esp-ring .5s ease-out infinite;}
.esp-buzzer.is-on .esp-ring + .esp-ring{animation-delay:.25s;}
@keyframes esp-ring{from{transform:scale(.85);opacity:.9;}to{transform:scale(1.15);opacity:0;}}
.esp-button{cursor:pointer;outline:none;touch-action:none;-webkit-tap-highlight-color:transparent;}
.esp-button-base{fill:#262626;stroke:#525252;}
.esp-button-cap{fill:#3f3f46;stroke:#111;transform-box:fill-box;transform-origin:center;transition:transform .05s;}
.esp-button:hover .esp-button-cap{fill:#52525b;}
.esp-button.is-down .esp-button-cap{fill:#18181b;transform:scale(.86);}
.esp-button:focus-visible .esp-button-base{stroke:var(--c-accent);stroke-width:2;}
.esp-tip{margin-top:6px;font-size:11.5px;color:var(--c-text-faint);text-align:center;}

/* The dashboard */
.esp-dash{grid-area:dash;}
.esp-cards{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:8px;}
.esp-card{display:flex;flex-direction:column;gap:10px;min-width:0;padding:10px;border:1px solid var(--c-border);border-radius:var(--radius-sm);background:var(--c-subtle);}
.esp-card-title{font-size:13px;font-weight:600;color:var(--c-text);}
.esp-card-title code{display:block;margin-top:2px;font:400 11px var(--font-mono);color:var(--c-text-faint);overflow-wrap:anywhere;}
.esp-card-foot{margin-top:auto;font-size:11.5px;line-height:1.4;color:var(--c-text-faint);}
.esp-card-foot.is-warn{color:var(--t-yellow);}
.esp-reading{display:flex;align-items:center;gap:8px;font-size:14px;color:var(--c-text);}
.esp-lamp{flex:none;width:18px;height:18px;border-radius:50%;background:#262626;border:1px solid var(--esp-line);transition:background .1s,box-shadow .1s;}
.esp-lamp.is-on{background:var(--t-green);box-shadow:0 0 12px rgba(74,222,128,.75);}
.esp-switch{display:inline-flex;align-items:center;gap:8px;align-self:flex-start;padding:0;border:0;background:none;font:inherit;font-size:14px;color:var(--c-text);cursor:pointer;}
.esp-track{position:relative;flex:none;width:40px;height:22px;border-radius:11px;background:#3a3a3a;transition:background .15s;}
.esp-track::after{content:"";position:absolute;top:3px;left:3px;width:16px;height:16px;border-radius:50%;background:#fff;transition:transform .15s;}
.esp-switch[aria-checked=true] .esp-track{background:var(--c-accent);}
.esp-switch[aria-checked=true] .esp-track::after{transform:translateX(18px);}
.esp-switch[aria-busy=true] .esp-track{opacity:.55;}
.esp-switch:focus-visible{outline:2px solid var(--c-accent);outline-offset:3px;border-radius:12px;}
.esp-log-title{margin:12px 0 6px;}
.esp-log{flex:1;min-height:120px;margin:0;padding:0;overflow:auto;overscroll-behavior:contain;list-style:none;font:11px/1.5 var(--font-mono);}
.esp-log li{display:grid;grid-template-columns:auto 9ch minmax(0,1fr) auto;gap:8px;padding:3px 0;border-bottom:1px solid var(--c-border);color:var(--c-text-dim);}
.esp-log time{color:var(--t-dim);}
.esp-log b{font-weight:600;color:var(--t-cyan);}
.esp-log b.is-connect{color:var(--t-green);}
.esp-log b.is-subscribe{color:var(--t-dim);}
.esp-log b:is(.is-will,.is-timeout){color:var(--t-red);}
.esp-log code{color:var(--t-yellow);}
.esp-log span{overflow-wrap:anywhere;}
.esp-log .esp-who{color:var(--c-text-faint);text-align:right;}

/* The Serial Monitor */
.esp-serial{grid-area:serial;}
.esp-serial-out{
  flex:1;min-height:150px;margin:0;padding:8px 10px;overflow:auto;overscroll-behavior:contain;
  border-radius:var(--radius-sm);background:#000;color:var(--t-fg);
  font:11.5px/1.45 var(--font-mono);white-space:pre-wrap;overflow-wrap:anywhere;
}
.esp-serial-out:focus-visible{outline:2px solid var(--c-accent);outline-offset:-2px;}
.esp-line{display:block;min-height:1.45em;}
.esp-line.is-dim{color:var(--t-dim);}
.esp-line.is-ok{color:var(--t-green);}
.esp-line.is-err{color:var(--t-red);}
.esp-line.is-in{color:var(--t-cyan);}

@container (max-width:720px){
  .esp-grid{grid-template-columns:minmax(0,1fr);grid-template-rows:none;grid-template-areas:"flow" "board" "dash" "serial";}
  .os .esp-grid{height:auto;}
  .esp-log{max-height:220px;}
  .esp-serial-out{height:220px;flex:none;}
}
@container (max-width:480px){
  .esp-cards{grid-template-columns:minmax(0,1fr);}
  .esp-node{padding:3px 7px;font-size:11px;}
  .esp-lane{margin:0 4px;}
  .esp-log li{grid-template-columns:auto 9ch minmax(0,1fr);}
  .esp-log .esp-who{grid-column:2 / -1;text-align:left;}
}

/* ---------- Guest desktops ---------- */
/* Text meant for one desktop only, such as each desktop's credit. */
[data-guest="windows"] [data-only]:not([data-only~="windows"]),
[data-guest="kali"] [data-only]:not([data-only~="kali"]),
[data-guest="macos"] [data-only]:not([data-only~="macos"]){display:none;}
.menubar{display:none;}

/* Kali Linux: an XFCE-style dark top panel and flat dark windows. */
.os[data-guest="kali"]{
  --c-bg:#1b1d23;--c-card:#23262d;--c-card-hover:#2a2e36;--c-tint:#16181d;
  --c-accent:#4ade80;--c-accent-hover:#6ee7a0;--c-accent-ink:#052e16;
  --c-acrylic:rgba(24,26,31,.97);
  --font-ui:'Cantarell','Noto Sans',Ubuntu,Inter,system-ui,sans-serif;
  --font-display:'Cantarell','Noto Sans',Ubuntu,Inter,system-ui,sans-serif;
  --font-mono:'Fira Code','DejaVu Sans Mono','JetBrains Mono',Consolas,monospace;
  --taskbar-h:34px;--radius:6px;
}
.os[data-guest="kali"] .desktop{inset:var(--taskbar-h) 0 0 0;background:var(--wall-kali);}
.os[data-guest="kali"] .taskbar{
  top:0;bottom:auto;justify-content:flex-start;padding:0 6px;
  background:#121419;border-top:0;border-bottom:1px solid rgba(255,255,255,.07);
  backdrop-filter:none;-webkit-backdrop-filter:none;
}
.os[data-guest="kali"] #searchBtn{display:none;}
.os[data-guest="kali"] .task-center,.os[data-guest="kali"] .task-apps{gap:2px;}
.os[data-guest="kali"] .task-apps{margin-left:4px;padding-left:6px;border-left:1px solid rgba(255,255,255,.12);}
.os[data-guest="kali"] .task-btn{width:36px;height:30px;border-radius:3px;}
.os[data-guest="kali"] .task-btn svg,.os[data-guest="kali"] .task-btn img{width:20px;height:20px;}
.os[data-guest="kali"] .task-btn::after{bottom:0;height:2px;border-radius:0;}
.os[data-guest="kali"] .task-btn.is-focused::after{width:24px;}
.os[data-guest="kali"] .tray-status,.os[data-guest="kali"] .tray-clock{height:30px;}
.os[data-guest="kali"] .tray-clock{flex-direction:row;align-items:center;gap:8px;font-weight:600;}
.os[data-guest="kali"] .start-menu:not([hidden]){
  top:calc(var(--taskbar-h) + 2px);bottom:auto;left:4px;transform:none;
  width:min(560px,calc(100vw - 8px));max-height:calc(100dvh - var(--taskbar-h) - 12px);
  border-radius:4px;animation-name:drop-in;
}
.os[data-guest="kali"] .ai-chat-window{top:calc(var(--taskbar-h) + 8px);bottom:auto;}
.os[data-guest="kali"] .win{border-color:rgba(255,255,255,.1);}
.os[data-guest="kali"] .win-bar{height:30px;padding-left:10px;background:#202329;}
.os[data-guest="kali"] .win-title{text-align:center;font-weight:600;}
.os[data-guest="kali"] .win-btn{width:32px;height:30px;}
.os[data-guest="kali"] .win-close:hover{background:#e0443e;}
.os[data-guest="kali"] .desktop-credit{bottom:12px;}

/* macOS: a top menu bar, a floating Dock, and traffic-light window buttons. */
.os[data-guest="macos"]{
  --c-bg:#1e1e1e;--c-card:#2a2a2c;--c-card-hover:#323234;--c-tint:#18181a;
  --c-accent:#30d158;--c-accent-hover:#5ade7a;--c-accent-ink:#052e16;
  --c-acrylic:rgba(38,38,40,.8);
  --font-ui:-apple-system,BlinkMacSystemFont,'SF Pro Text','Helvetica Neue',Inter,system-ui,sans-serif;
  --font-display:-apple-system,BlinkMacSystemFont,'SF Pro Display','Helvetica Neue',Inter,system-ui,sans-serif;
  --font-mono:'SF Mono',Menlo,Monaco,'JetBrains Mono',monospace;
  --menubar-h:26px;--taskbar-h:78px;--radius:10px;
}
/* The wallpaper sits on the page itself so it shows through the menu bar and Dock. */
/* Full height: everything on the page is fixed, so it would otherwise be 0px tall. */
.os[data-guest="macos"]{height:100%;background:var(--wall-macos);}
.os[data-guest="macos"] body{background:none;}
.os[data-guest="macos"] .desktop{inset:var(--menubar-h) 0 var(--taskbar-h) 0;background:none;}
.os[data-guest="macos"] .desktop-icons{direction:rtl;}
.os[data-guest="macos"] .desk-icon{direction:ltr;}
.os[data-guest="macos"] .desktop-credit{left:16px;right:auto;text-align:left;}

.os[data-guest="macos"] .menubar{
  position:fixed;top:0;left:0;right:0;z-index:250;height:var(--menubar-h);
  display:flex;align-items:center;gap:14px;padding:0 6px 0 10px;
  background:rgba(20,20,26,.4);color:#fff;font-size:13px;
  backdrop-filter:blur(30px) saturate(1.6);-webkit-backdrop-filter:blur(30px) saturate(1.6);
}
.menubar-logo{display:grid;place-items:center;width:30px;height:22px;border-radius:5px;}
.menubar-logo img{width:15px;height:15px;border-radius:3px;}
.menubar-logo:hover,.menubar-logo.is-active{background:rgba(255,255,255,.2);}
.menubar-app{font-weight:700;white-space:nowrap;}
.menubar-menus{display:flex;gap:16px;white-space:nowrap;opacity:.92;}
@media (max-width:900px){ .menubar-menus{display:none;} }
.menubar-tray{display:flex;align-items:center;height:100%;margin-left:auto;}
.os[data-guest="macos"] .task-tray{position:static;height:100%;}
.os[data-guest="macos"] .tray-btn{width:30px;height:22px;}
.os[data-guest="macos"] .tray-btn svg{width:16px;height:16px;}
.os[data-guest="macos"] .tray-btn::after{display:none;}
.os[data-guest="macos"] .tray-status,.os[data-guest="macos"] .tray-clock{height:22px;}
.os[data-guest="macos"] .tray-clock{flex-direction:row-reverse;align-items:center;gap:8px;font-size:13px;}

.os[data-guest="macos"] .taskbar{
  left:50%;right:auto;bottom:6px;height:66px;padding:0 8px;transform:translateX(-50%);
  background:rgba(255,255,255,.17);border:1px solid rgba(255,255,255,.24);border-radius:20px;
  box-shadow:0 10px 30px rgba(0,0,0,.3);
}
.os[data-guest="macos"] #searchBtn{display:none;}
.os[data-guest="macos"] .task-center,.os[data-guest="macos"] .task-apps{gap:6px;}
/* Dock icons only: the tray buttons now sit in the menu bar. */
.os[data-guest="macos"] .taskbar .task-btn{width:52px;height:52px;border-radius:12px;transition:transform .15s;}
.os[data-guest="macos"] .taskbar .task-btn:hover,.os[data-guest="macos"] .taskbar .task-btn.is-active{background:none;transform:translateY(-6px) scale(1.08);}
.os[data-guest="macos"] .taskbar .task-btn svg,.os[data-guest="macos"] .taskbar .task-btn img{width:48px;height:48px;}
.os[data-guest="macos"] .task-start img{border-radius:11px;}
.os[data-guest="macos"] .taskbar .task-btn::after{bottom:-5px;width:0;height:4px;border-radius:50%;background:rgba(255,255,255,.85);}
.os[data-guest="macos"] .taskbar .task-btn.is-open::after,.os[data-guest="macos"] .taskbar .task-btn.is-focused::after{width:4px;background:rgba(255,255,255,.85);}
.os[data-guest="macos"] .start-menu:not([hidden]){
  top:calc(var(--menubar-h) + 6px);bottom:auto;left:8px;transform:none;
  max-height:calc(100dvh - var(--menubar-h) - var(--taskbar-h) - 16px);
  border-radius:12px;animation-name:drop-in;
}
.os[data-guest="macos"] .ai-chat-window{height:min(540px,calc(100dvh - var(--taskbar-h) - var(--menubar-h) - 24px));}

.os[data-guest="macos"] .win{border-radius:12px;border-color:rgba(255,255,255,.16);}
.os[data-guest="macos"] .win.is-max{border-radius:0;}
.os[data-guest="macos"] .win-bar{height:34px;gap:8px;padding:0 12px;background:#2c2c2e;border-bottom:1px solid rgba(0,0,0,.4);}
.os[data-guest="macos"] .win-bar > svg{display:none;}
.os[data-guest="macos"] .win-title{padding-right:60px;text-align:center;font-size:13px;font-weight:600;}
.os[data-guest="macos"] .win-btn{width:12px;height:12px;border-radius:50%;color:rgba(0,0,0,.6);}
.os[data-guest="macos"] .win-btn svg{width:6px;height:6px;opacity:0;}
.os[data-guest="macos"] .win-bar:hover .win-btn svg,.os[data-guest="macos"] .win-btn:focus-visible svg{opacity:1;}
.os[data-guest="macos"] .win-close,.os[data-guest="macos"] .win-close:hover{order:-3;background:#ff5f57;color:rgba(0,0,0,.6);}
.os[data-guest="macos"] .win-min,.os[data-guest="macos"] .win-min:hover{order:-2;background:#febc2e;}
.os[data-guest="macos"] .win-max,.os[data-guest="macos"] .win-max:hover{order:-1;background:#28c840;}
.os[data-guest="macos"] .win:not(.is-active) .win-bar:not(:hover) .win-btn{background:#4a4a4c;}

@keyframes drop-in{from{opacity:0;transform:translateY(-8px);}}

/* ---------- Phones ---------- */
/* Windows always fill the screen, like apps on a phone. */
@media (max-width:760px){
  .win{inset:0 !important;width:auto !important;height:auto !important;border-radius:0;border:none;resize:none;animation-name:win-open-phone;}
  @keyframes win-open-phone{from{opacity:0;transform:translateY(24px);}}
  .win-max{display:none;}
  .os .desktop-icons{grid-auto-flow:row;grid-template-rows:none;grid-template-columns:repeat(4,1fr);grid-auto-columns:auto;padding:16px 8px;}
  .tray-status{display:none;}
  /* Apps on the left, tray on the right, so they never overlap. */
  .os .taskbar{justify-content:space-between;padding:0 4px;}
  .task-center{min-width:0;}
  .task-apps{min-width:0;overflow-x:auto;scrollbar-width:none;}
  .task-tray{position:static;flex:none;}
  .task-btn{width:40px;flex:none;}
  .start-grid{grid-template-columns:repeat(4,1fr);}
  .start-search,.start-body{margin-left:16px;margin-right:16px;padding-left:0;padding-right:0;}
  .start-recs{grid-template-columns:1fr;}
  .start-footer{padding:12px 24px;}
  .cv-paper{padding:20px 16px;}
}
@media (max-width:420px){
  .tray-clock{padding:0 6px;font-size:11px;}
}

@media print{
  .cert-preview,.lightbox-modal{display:none !important;}
}

@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{transition-duration:.01ms !important;animation:none !important;}
  .reveal-ready [data-animate]:not(.in-view){opacity:1;transform:none;}
  .js .terminal-app [data-step]{opacity:1;}
  .js .terminal-app .typed{width:auto;}
  .vm-boot-log p{opacity:1;}
  .vm-boot-bar i{width:100%;}
}
