
@font-face {
  font-family: "JGS7";
  src: url("/assets/gen/jgs7.bcfc718a.ttf") format("truetype");
  font-display: swap;
  font-style: normal;
  font-weight: 400;
}

:root,
[data-theme='light'] {
  font-family: 'IBM Plex Sans', Helvetica, Arial, sans-serif;
  line-height: 1.6;
  font-weight: 400;
  color: #1a1a1a;
  background-color: #ffffff;
  text-rendering: optimizeLegibility;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}



a {
  
  text-decoration: none;
}

a:hover {
  text-decoration: underline;
}

body {
  margin: 0;
  
  
  
}

* {
  box-sizing: border-box;
}

button {
  font-family: inherit;
}





.scrollbar-styled {
  scrollbar-width: thin;
  scrollbar-color: var(--color-border, #c8c8c8) transparent;
}

.scrollbar-styled::-webkit-scrollbar {
  width: 6px;
  height: 6px;
}

.scrollbar-styled::-webkit-scrollbar-track {
  background: transparent;
  border-radius: 0;
}

.scrollbar-styled::-webkit-scrollbar-thumb {
  background: var(--color-border, #c8c8c8);
  border-radius: 0;
  transition: background 0.2s ease;
}

.scrollbar-styled::-webkit-scrollbar-thumb:hover {
  background: var(--color-text-muted, #5c5c5c);
}

.scrollbar-styled::-webkit-scrollbar-corner {
  background: transparent;
}

.scrollbar-hide {
  -ms-overflow-style: none;
  scrollbar-width: none;
}

.scrollbar-hide::-webkit-scrollbar {
  display: none;
}
:root,
[data-theme='light'] {
  color-scheme: light;

  --color-bg-deep: #ffffff;
  --color-bg-2: #ebebeb;
  --color-text: #1a1a1a;
  --color-text-muted: #5c5c5c;
  --color-text-dim: #888888;
  --color-border: #c8c8c8;
  --color-border-strong: #1a1a1a;
  --color-border-edge: transparent;
  --color-accent: #1a1a1a;
  --color-accent-alt: #006600;

  /* Retro stroke — chunkier than modern 1px hairlines */
  --retro-stroke: 2px;
  --retro-stroke-heavy: 3px;

  --font-display: 'IBM Plex Sans', Helvetica, Arial, sans-serif;
  --font-mono: 'Courier New', Courier, monospace;

  /* Legacy aliases — map old forge tokens to terminal palette */
  --color-gold: var(--color-accent);
  --color-gold-bright: var(--color-accent-alt);
  --color-gold-deep: var(--color-text);
  --color-sapphire-bright: var(--color-accent-alt);
}

[data-theme='dark'] {
  

  --color-bg-deep: #0a0a0a;
  --color-bg-2: #1a1a1a;
  --color-text: #e8e8e8;
  --color-text-muted: #aaaaaa;
  --color-text-dim: #777777;
  --color-border: #333333;
  --color-border-strong: #e8e8e8;
  --color-border-edge: transparent;
  --color-accent: #e8e8e8;
  --color-accent-alt: #39ff14;
}

/* :where(:not(...)) keeps this out of the MineCart subtree without raising
   specificity above a bare element — single-class rules must still win. */
:is(h1, h2, h3):where(:not(.minecart-site *, .ck-screen *)),
.page-title,
.card-title,
.quick-link-heading,
.leader-name,
.leadership-title,
.display-heading,
.hero-heading,
.vision-label,
.video-hero__headline {
  
  
  letter-spacing: 0.03em;
}











.brand-button:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 6px;
  border-radius: 0;
}









.mobile-nav-toggle:hover {
  background: rgba(255, 255, 255, 0.06);
  border-color: rgba(255, 255, 255, 0.18);
}

.mobile-nav-toggle:focus-visible {
  outline: 2px solid var(--color-gold);
  outline-offset: 4px;
}





/* Staggered Closed State (Matching your Image 1) */






/* X Open State (Centered) */
















.mobile-nav-link:hover {
  transform: none;
  border-color: var(--color-border-strong);
  background: var(--color-bg-deep);
}

.mobile-nav-link:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 3px;
}





.nav-indicator {
  position: absolute;
  width: 96px;
  height: 70px;
  /* Subtle 2-stop brass — gentle top-left highlight to bottom-right shadow,
     no bright specular band. Reads as warm metal without feeling shiny. */
  background: linear-gradient(
    135deg,
    var(--color-gold) 0%,
    var(--color-gold-deep) 100%
  );
  mask-image: url("/assets/gen/notch.352f8823.svg");
  mask-size: contain;
  mask-position: center;
  mask-repeat: no-repeat;
  -webkit-mask-image: url("/assets/gen/notch.352f8823.svg");
  -webkit-mask-size: contain;
  -webkit-mask-position: center;
  -webkit-mask-repeat: no-repeat;
  pointer-events: none;
  filter: drop-shadow(0 6px 14px rgba(141, 107, 47, 0.3));
  transition: transform 260ms ease, opacity 160ms ease, filter 260ms ease;
  opacity: 0;
}



.nav-link:focus-visible {
  outline: 2px solid var(--color-gold);
  outline-offset: 6px;
}





.nav-link:hover .nav-label {
  color: var(--color-gold-bright);
}



/* External link styling — WeaveCast pill button (sapphire gemstone) */




.nav-link--external:hover {
  background: var(--color-bg-deep);
  border-color: var(--color-accent-alt);
  box-shadow: none;
  transform: none;
}

.nav-link--external:hover .nav-label {
  color: var(--color-accent-alt);
}

.nav-link--external:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 3px;
}



.nav-link--external:hover .external-icon {
  opacity: 1;
  color: var(--color-text);
}

/* Mobile WeaveCast pill button styling (sapphire) */


.mobile-nav-link--external:hover {
  background: var(--color-bg-deep);
  border-color: var(--color-accent-alt);
  box-shadow: none;
  transform: none;
  color: var(--color-accent-alt);
}

.mobile-nav-link--external:focus-visible {
  outline: 2px solid var(--color-sapphire-bright);
  outline-offset: 3px;
}



.mobile-nav-link--external:hover .external-icon {
  opacity: 1;
  color: var(--color-text);
}



/* ============================================
   FOOTER STYLES
   ============================================ */






/* Brand Column */




.footer-logo-btn:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 4px;
  border-radius: 0;
}











.footer-social-link:hover {
  background: var(--color-bg-2);
  border-color: var(--color-border-strong);
  color: var(--color-accent-alt);
  transform: none;
  text-decoration: none;
}

.footer-social-link:focus-visible {
  outline: 2px solid var(--color-gold);
  outline-offset: 2px;
}

/* Navigation Columns */








.footer-link:hover {
  color: var(--color-text);
  text-decoration: none;
}

.footer-link:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
  border-radius: 0;
}

/* Investor CTA Column (sapphire) */






.footer-investor-cta:hover {
  background: var(--color-bg-deep);
  border-color: var(--color-accent-alt);
  box-shadow: none;
  transform: none;
  text-decoration: none;
  color: var(--color-accent-alt);
}

.footer-investor-cta:focus-visible {
  outline: 2px solid var(--color-sapphire-bright);
  outline-offset: 2px;
}





.footer-investor-cta:hover .footer-investor-cta-arrow {
  transform: translateX(3px);
}



.footer-contact-btn:hover {
  background: var(--color-bg-deep);
  border-color: var(--color-accent-alt);
  color: var(--color-accent-alt);
  transform: none;
}

.footer-contact-btn:focus-visible {
  outline: 2px solid var(--color-gold);
  outline-offset: 2px;
}

/* Footer Bottom Bar */










.footer-legal-link:hover {
  color: var(--color-text);
  text-decoration: none;
}



.footer-inline-link {
  
  
  transition: color 180ms ease;
}

.footer-inline-link:hover {
  color: var(--color-gold);
  text-decoration: none;
}

/* Footer Responsive Styles */





.investor-cta .cta-button.secondary:hover {
  background: linear-gradient(135deg, rgba(61, 111, 168, 0.32), rgba(94, 143, 199, 0.32));
  border-color: rgba(94, 143, 199, 0.7);
  transform: translateY(-2px);
}

.page {
  
  display: flex;
  flex-direction: column;
  
}























.cta-button.primary:hover {
  transform: none;
  background: var(--color-accent-alt);
  color: var(--color-bg-deep);
  box-shadow: none;
}



.cta-button.secondary:hover {
  background: var(--color-bg-2);
  border-color: var(--color-border-strong);
  transform: none;
}







































/* WeaveCast CTA Link — sapphire gemstone */


.weavecast-cta-link:hover {
  background: var(--color-bg-2);
  border-color: var(--color-accent-alt);
  box-shadow: none;
  color: var(--color-accent-alt);
  transform: none;
}

.weavecast-cta-link:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 3px;
}



.weavecast-cta-link:hover svg {
  transform: translate(2px, -2px);
}







.dl-orbit {
  transform-origin: 120px 118px;
  animation: dl-rotate 16s linear infinite;
}

.dl-nodes circle {
  transform-origin: center;
  animation: dl-pulse 2.6s ease-in-out infinite;
}









@keyframes dl-rotate {
  from {
    transform: rotate(0deg);
  }
  to {
    transform: rotate(360deg);
  }
}

@keyframes dl-pulse {
  0%,
  100% {
    transform: scale(1);
    opacity: 0.9;
  }
  50% {
    transform: scale(1.25);
    opacity: 0.65;
  }
}

@media (max-width: 900px) {
  

  /* Mobile-only ordering: WeaveCast text → WeaveCast animation → DeepLoom animation → DeepLoom text */
  

  

  

  
}

@media (prefers-reduced-motion: reduce) {
  .dl-orbit,
  .dl-nodes circle,
  .wc-dot--one,
  .wc-dot--two,
  .wc-spark,
  .wc-pulse {
    animation: none !important;
  }
}

.quick-link-card {
  position: relative;
  background: rgba(35, 32, 27, 0.85);
  border: none;
  border-radius: 0;
  padding: 1.5rem 2rem 2rem;
  min-height: 220px;
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
  align-items: center;
  text-align: center;
  transition: transform 200ms ease, border-color 200ms ease, box-shadow 200ms ease, filter 200ms ease;
  mask-image: url("/assets/gen/notch.352f8823.svg");
  mask-size: contain;
  mask-position: center;
  mask-repeat: no-repeat;
  -webkit-mask-image: url("/assets/gen/notch.352f8823.svg");
  -webkit-mask-size: contain;
  -webkit-mask-position: center;
  -webkit-mask-repeat: no-repeat;
  overflow: hidden;
}

.quick-link-card:hover {
  transform: translateY(-6px);
  filter: drop-shadow(0 10px 20px rgba(20, 17, 13, 0.5));
}

.quick-link-card::after {
  content: '';
  position: absolute;
  inset: 0;
  /* Subtle brass crest border revealed on hover — matches the softer
     active-nav gradient. */
  background: linear-gradient(
    135deg,
    var(--color-gold) 0%,
    var(--color-gold-deep) 100%
  );
  mask-image: url("/assets/gen/notch.352f8823.svg"), url("/assets/gen/notch.352f8823.svg");
  mask-size: contain, 98% 98%;
  mask-position: center, center;
  mask-repeat: no-repeat, no-repeat;
  mask-composite: exclude;
  -webkit-mask-image: url("/assets/gen/notch.352f8823.svg"), url("/assets/gen/notch.352f8823.svg");
  -webkit-mask-size: contain, 98% 98%;
  -webkit-mask-position: center, center;
  -webkit-mask-repeat: no-repeat, no-repeat;
  -webkit-mask-composite: xor;
  opacity: 0;
  transition: opacity 200ms ease;
  pointer-events: none;
  z-index: 0;
}

.quick-link-card:hover::after {
  opacity: 1;
}









.quick-link-action:hover {
  background: none;
  color: var(--color-accent-alt);
  transform: none;
}

.quick-link-action:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 4px;
  border-radius: 0;
}



.text-link-button:hover {
  color: var(--color-gold);
  text-decoration: underline;
  text-decoration-color: rgba(200, 162, 89, 0.6);
}

.text-link-button:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 4px;
  border-radius: 0;
}







.card:hover {
  transform: translateY(-4px);
  border-color: rgba(200, 162, 89, 0.45);
  box-shadow:
    0 18px 38px rgba(20, 17, 13, 0.45),
    0 0 18px rgba(200, 162, 89, 0.1),
    inset 0 1px 0 rgba(255, 240, 210, 0.08);
}











.card.card--static:hover {
  transform: none;
  border-color: var(--color-border);
  box-shadow:
    inset 0 1px 0 var(--color-border-edge),
    0 1px 0 rgba(20, 17, 13, 0.4);
}



.inline-link:hover {
  color: var(--color-gold);
  border-color: var(--color-gold);
}













.contact-form input:focus,
.contact-form textarea:focus {
  outline: none;
  border-color: var(--color-border-strong);
  box-shadow: none;
}



/* Contact Page - Investor Card Redesign (sapphire gemstone) */

















.contact-investor-cta:hover {
  background: linear-gradient(135deg, rgba(61, 111, 168, 0.4), rgba(94, 143, 199, 0.4));
  border-color: rgba(94, 143, 199, 0.8);
  box-shadow:
    0 0 25px rgba(61, 111, 168, 0.4),
    0 8px 20px rgba(20, 17, 13, 0.4);
  transform: translateY(-2px);
  text-decoration: none;
  color: var(--color-text);
}

.contact-investor-cta:focus-visible {
  outline: 2px solid var(--color-sapphire-bright);
  outline-offset: 3px;
}



.contact-investor-cta:hover .contact-investor-arrow {
  transform: translateX(4px);
}

@media (max-width: 720px) {
  

  

  .nav-indicator {
    display: none;
  }

  

  

  

  

  

  

  

  

  

  

  

  

  
}



















.video-hero__scroll-nudge:focus-visible {
  outline: 2px solid var(--color-gold);
  outline-offset: 4px;
  border-radius: 4px;
}

@media (max-width: 1024px) {
  

  

  .quick-link-card {
    padding: 1.4rem 1.8rem 1.8rem;
    min-height: 200px;
    mask-size: contain;
    -webkit-mask-size: contain;
  }

  
}

@media (max-width: 640px) {
  

  

  .quick-link-card {
    padding: 1.3rem 1.5rem 1.5rem;
    min-height: 180px;
    mask-size: contain;
    -webkit-mask-size: contain;
  }

  
}

@media (max-width: 720px) {
  .quick-link-card {
    min-height: 0;
    padding: 1.2rem 1.4rem 1.4rem;
  }

  

  
}

@media (max-width: 520px) {
  

  

  .content {
    padding: 2.4rem 5vw;
  }

  

  

  

  

  

  

  

  
}

@media (max-width: 720px) and (max-height: 560px) {
  .video-hero {
    height: min(calc(100vw * 9 / 16), 65vh);
    min-height: 45vh;
  }
}

/* ── Brand Callout ────────────────────────────────────────────
   Shared treatment for emphasized inline blocks (About "Our Belief",
   Showcase "From Mission to Vision", and similar). Replaces duplicated
   inline styles in JSX with one tokenized class. */














/* Helpers for the previously-inline patterns on About and Showcase cards. */
/* 80s terminal aesthetic overrides — loaded after App.css base rules */







/* ── Navbar ─────────────────────────────────────────────── */




.brand-button:focus-visible,
.mobile-nav-toggle:focus-visible,
.nav-link:focus-visible,
.theme-toggle:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 3px;
  border-radius: 0;
}



.mobile-nav-toggle:hover {
  background: var(--color-bg-deep);
  border-color: var(--color-border-strong);
}



.nav-indicator {
  display: none !important;
}





.nav-link:hover {
  transform: none;
}





.nav-link:hover .nav-label {
  color: var(--color-text);
}







.nav-link--external:hover {
  background: var(--color-bg-2);
  border-color: var(--color-border-strong);
  box-shadow: none;
  transform: none;
}

.nav-link--external:hover .nav-label,
.nav-link--external:hover .external-icon {
  color: var(--color-accent-alt);
}







.theme-toggle:hover {
  border-color: var(--color-border-strong);
  background: var(--color-bg-deep);
}







.mobile-nav-link:hover {
  transform: none;
  background: var(--color-bg-deep);
  border-color: var(--color-border-strong);
}





.mobile-nav-link--external:hover {
  background: var(--color-bg-2);
  box-shadow: none;
  transform: none;
  color: var(--color-accent-alt);
}





/* ── Footer ─────────────────────────────────────────────── */










.footer-investor-cta:hover,
.footer-contact-btn:hover {
  background: var(--color-bg-2);
  box-shadow: none;
  transform: none;
}



.footer-social-link:hover {
  background: var(--color-bg-2);
}

/* ── Cards & pages ──────────────────────────────────────── */


.card:hover {
  transform: none;
  border-color: var(--color-border-strong);
  box-shadow: none;
}

.card.card--static:hover {
  border-color: var(--color-border);
}











.cta-button:hover {
  background: var(--color-accent-alt);
  color: var(--color-bg-deep);
  box-shadow: none;
  transform: none;
}



.text-link-button:hover,
.inline-link:hover,
.quick-link-action:hover,
.weavecast-cta-link:hover {
  color: var(--color-accent-alt);
  text-decoration-color: var(--color-accent-alt);
}



.contact-form input:focus,
.contact-form textarea:focus {
  border-color: var(--color-border-strong);
  box-shadow: none;
}







.contact-investor-cta:hover {
  background: var(--color-bg-deep);
  box-shadow: none;
  transform: none;
}



/* ── Home page ──────────────────────────────────────────── */





/* ── Hero video ─────────────────────────────────────────── */


/* Light mode: inverted treatment, softer contrast */


/* Dark mode: regular grayscale, lightly lifted */


















.video-hero__scroll-nudge:focus-visible {
  outline: 2px solid var(--color-accent);
  border-radius: 0;
}





/* ── Other main-site pages ──────────────────────────────── */




.footer-link,
.footer-legal-link,
.footer-inline-link {
  font-family: var(--font-mono);
  font-size: 0.88rem;
  
}

.footer-link:hover,
.footer-legal-link:hover,
.footer-inline-link:hover {
  color: var(--color-accent-alt);
}







.footer-legal-link:hover {
  color: var(--color-text);
}





/* :not(.minecart-site *) keeps these off the MineCart legal pages, which
   have their own .legal-content styling in pages/minecart/minecart.css. */

/* Cassette-futurist printer the page feeds out of: a beige slab with side
   vents, a status LED, and a dark slot the paper emerges from. */
/* "back" key on the faceplate, echoing the nav cluster */
.paper-return {
  display: flex;
  align-items: center;
  gap: 0.9rem;
}
.paper-return__label {
  font-size: 0.72rem;
  
  text-transform: uppercase;
}

/* full width of the section, same span as the CRT screens */
.paper-printer {
  position: relative;
  
  
  padding: 0.8rem 1.4rem 1rem;
  background: linear-gradient(#ece6d8, #c9c2b0);
  /* the .ck-frame treatment: 10px radius, shadow-ring border, inset bevel */
  border-radius: 10px 10px 0 0;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.35),
    inset 0 -1px 0 rgba(0, 0, 0, 0.18),
    0 0 0 1px rgba(0, 0, 0, 0.1),
    0 6px 18px rgba(0, 0, 0, 0.3);
  font-family: 'IBM Plex Mono', 'Courier New', Courier, monospace;
  font-size: 0.6rem;
  letter-spacing: 0.18em;
  color: #7a7364;
}
.paper-printer::before {
  /* cooling vents */
  content: '';
  position: absolute;
  top: 0.7rem;
  right: 3rem;
  width: 6.5rem;
  height: 0.8rem;
  background: repeating-linear-gradient(90deg, #a49c8a 0 3px, transparent 3px 9px);
}
.paper-printer__name {
  position: absolute;
  right: 1.4rem;
  bottom: 0.7rem;
}
.paper-printer::after {
  /* paper slot set into the bottom edge; the sheet tucks up into it, so the
     paper paints over the slot's lower half but never over the beige body */
  content: '';
  position: absolute;
  left: 50%;
  bottom: 0;
  transform: translateX(-50%);
  /* slightly wider than the 56rem sheet feeding out of it */
  width: min(calc(100% - 3rem), 58rem);
  height: 8px;
  background: #2a2620;
  border-radius: 3px;
  box-shadow: inset 0 2px 3px rgba(0, 0, 0, 0.8);
}
/* placement only — the LED itself is the nav's StatusLed (.ck-led) */
.paper-printer__led {
  position: absolute;
  top: 0.55rem;
  right: 1.2rem;
}

/* Printed technical document: a blog post renders as a typewritten page —
   IBM Plex Mono, black ink on white paper. Self-contained: every blog-post
   class is styled here and nowhere else. */
.paper-doc {
  font-family: 'IBM Plex Mono', 'Courier New', Courier, monospace;
  color: #111;
  background: #fff;
  max-width: 56rem;
  /* pulled up into the printer's slot; relative so the sheet paints over it */
  position: relative;
  margin: -5px auto 0;
  padding: clamp(1.6rem, 5vw, 3.2rem) clamp(1.1rem, 5vw, 3.6rem);
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.25);
}

/* App.css points h1-h3 at the sans display font — keep headings on the page font */




/* Document header closed by a double rule, typewriter style. */
.paper-doc .blog-post-header {
  border-bottom: 4px double #111;
  margin-bottom: 2.2rem;
  padding-bottom: 1.4rem;
}
.paper-doc .blog-post-title {
  font-size: clamp(1.4rem, 3vw, 1.85rem);
  
  
  line-height: 1.2;
  margin: 0 0 1.5rem;
}
.paper-doc .blog-post-meta {
  display: flex;
  gap: 1.5rem;
  flex-wrap: wrap;
  font-size: 0.82rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: #444;
}

/* Banner image: fit the column, never taller than most of the viewport. */
.paper-doc .blog-post-banner {
  display: block;
  width: 100%;
  max-height: 60vh;
  object-fit: contain;
  margin: 0 auto 2.2rem;
}

/* Body copy */
.paper-doc .blog-post-content {
  font-size: 0.98rem;
  line-height: 1.8;
}
.paper-doc .blog-post-content .lead {
  font-size: 1.02rem;
  line-height: 1.7;
  
  color: #111;
}
.paper-doc .blog-post-content p,
.paper-doc .blog-post-content ul,
.paper-doc .blog-post-content ol {
  color: #444;
}
.paper-doc .blog-post-content p { margin-bottom: 1.5rem; }
/* re-enable markers the SPA's Tailwind preflight stripped */
.paper-doc .blog-post-content ul,
.paper-doc .blog-post-content ol {
  margin: 1.5rem 0;
  padding-left: 2rem;
}


.paper-doc .blog-post-content li {
  margin-bottom: 0.75rem;
  line-height: 1.7;
}
.paper-doc .blog-post-content li strong,
.paper-doc .blog-post-content blockquote strong {
  color: #111;
  font-style: normal;
}
.paper-doc .blog-post-content a {
  color: #111;
  text-decoration: underline;
  text-underline-offset: 3px;
}
.paper-doc .blog-post-content a:hover { color: #000; }

/* Section heads: uppercase, hairline-underlined, mono-bold. */
.paper-doc .blog-post-content h2 {
  font-size: 1.15rem;
  
  text-transform: uppercase;
  letter-spacing: 0.05em;
  border-bottom: 1px solid #999;
  padding-bottom: 0.35rem;
  margin: 2.5rem 0 1rem;
  line-height: 1.3;
}
.paper-doc .blog-post-content h3 {
  font-size: 1.02rem;
  
  margin: 2rem 0 1rem;
}

/* Quotes, code, rules */
.paper-doc .blog-post-content blockquote {
  margin: 2rem 0;
  padding: 1.5rem 2rem;
  border-left: 3px solid #111;
  background: #f2f2f2;
  font-style: italic;
  
}
/* the SPA's Tailwind preflight gave code/pre its own mono stack — keep the page font */
.paper-doc .blog-post-content code,
.paper-doc .blog-post-content pre {
  font-family: inherit;
}
.paper-doc .blog-post-content code {
  font-size: 0.9em;
  padding: 0.2em 0.4em;
  background: #f2f2f2;
  border: 1px solid #999;
}
.paper-doc .blog-post-content pre {
  margin: 1.5rem 0;
  overflow-x: auto;
  padding: 1.25rem 1.5rem;
  background: #f2f2f2;
  border: 1px solid #999;
  border-left: 3px solid #111;
  font-size: 0.88rem;
  line-height: 1.65;
}
.paper-doc .blog-post-content pre code {
  display: block;
  padding: 0;
  
  border: none;
}
.paper-doc .blog-post-content hr {
  margin: 2rem 0;
  border: none;
  border-top: 1px dashed #999;
}


/* In-document boxes (TL;DR, author bio): the TUI rectangle — 1px rule with
   the label set into the border between ┤ ├ brackets; a white patch behind
   the label fakes the border gap. */
.paper-doc .tldr-block,
.paper-doc .author-bio {
  position: relative;
  border: 1px solid #111;
  padding: 1.3rem 1.25rem 1rem;
}
.paper-doc .tldr-block { margin-bottom: 2rem; }
.paper-doc .tldr-text {
  margin: 0;
  line-height: 1.7;
}
.paper-doc .tldr-label,
.paper-doc .author-bio__label {
  position: absolute;
  top: -0.7em;
  left: 10px;
  margin: 0;
  padding: 0 0.6ch;
  background: #fff;
  font-size: 0.8rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  line-height: 1.2;
  
}
.paper-doc :is(.tldr-label, .author-bio__label)::before { content: '┤ '; }
.paper-doc :is(.tldr-label, .author-bio__label)::after { content: ' ├'; }

.paper-doc .author-bio {
  display: flex;
  gap: 1.25rem;
  
  margin-top: 2.5rem;
}
.paper-doc .author-bio__photo {
  width: 72px;
  height: 72px;
  
  flex-shrink: 0;
  border: 1px solid #999;
}

.paper-doc .author-bio__name {
  font-size: 1.1rem;
  font-weight: 700;
  margin: 0 0 0.15rem;
}
.paper-doc .author-bio__title,
.paper-doc .author-bio__text {
  font-size: 0.9rem;
  
  
}
.paper-doc .author-bio__text { line-height: 1.6; }
.paper-doc .author-bio__link {
  font-size: 0.85rem;
  
  
  
}

@media (max-width: 720px) {
  .paper-doc { padding: 1.4rem 1rem; }
  .paper-doc .blog-post-content ul,
  .paper-doc .blog-post-content ol { padding-left: 1.5rem; }
  .paper-doc .blog-post-content blockquote { padding: 1rem 1.5rem; }
}
@media (max-width: 520px) {
  .paper-doc .author-bio {
    flex-direction: column;
    align-items: center;
    text-align: center;
  }
}
/* Retro line treatment — chunky strokes, dashed rules, double frames */



/* ── Shell chrome (inset dashed rules — not edge-to-edge) ── */














/* ── Controls & nav ─────────────────────────────────────── */






/* ── Cards & panels (single-line frames) ────────────────── */


.app .card:hover {
  border-color: var(--color-border-strong);
}

.app .card.card--static:hover {
  border-color: var(--color-border);
}

/* ── Team & misc pages ──────────────────────────────────── */


.app .leader-card:hover {
  border-color: var(--color-border-strong);
}
/* ============================================================================
   CONSOLE KIT — the terminal site's visual language as a reusable design
   system for the standard site. Own namespace (ck-*); material recipes are
   duplicated from the terminal's CSS — the four chrome stylesheets, merged
   verbatim into terminal-device.css — rather than imported: the terminal's CSS
   assumes full-viewport device geometry and must not be disturbed. Assets are
   shared (assets/).

   One fixed physical look: cream plastic chassis, dark CRT screens, grey-green
   LCDs. No light/dark theme — hardware doesn't have a dark mode.
   ========================================================================== */

@font-face {
  font-family: 'JGS7';
  src: url("/assets/gen/jgs7.bcfc718a.ttf") format('truetype');
  font-display: swap;
}
@font-face {
  font-family: 'DS-Digital';
  src: url("/assets/gen/DS-DIGIB.db992dcd.TTF") format('truetype');
  font-display: swap;
}
@font-face {
  font-family: 'Aulendur Brand';
  src: url("/assets/gen/aulegothic.5f7a5877.otf") format('opentype');
  font-display: swap;
}
@font-face {
  /* in-universe runic keycap glyphs (mirrors the terminal keyboard) */
  font-family: 'Starforge Runic';
  src: url("/assets/gen/StarforgeRunic-Regular.b3bd480c.ttf") format('truetype');
  font-display: swap;
}

/* ── Tokens ────────────────────────────────────────────────────────────── */
.ck-chassis {
  /* phosphor palette (mirrors .device-terminal) */
  --ck-bg: #0b0d0b;
  --ck-fg: #80ce8b;
  --ck-dim: color-mix(in srgb, var(--ck-fg) 80%, var(--ck-bg));
  --ck-bright: color-mix(in srgb, var(--ck-fg) 55%, white);   /* emphasis: phosphor driven toward white */
  --ck-accent: #ffb648;
  /* screens/art/chrome use the pixel font; long-form body reads in a smooth mono */
  --ck-font-screen: 'JGS7', 'Courier New', Courier, monospace;
  --ck-font-body: 'Iosevka Term Slab', monospace;
  /* engraved-into-plastic text (labels on the chassis) */
  --ck-engrave: #5a5340;
  --ck-label: #3a3527;   /* chassis print: the nav's logo mark + wordmark */
  /* LCD (mirrors the lcd bank / macro pad) */
  --ck-lcd-glass: #8a927e;
  --ck-lcd-glass-2: #767d68;
  --ck-lcd-seg: #171b11;
  --ck-lcd-ghost: rgba(23, 27, 17, 0.11);
  /* keys */
  --ck-key: 46px;
  --ck-key-shadow: 0 3px 3px rgba(0, 0, 0, 0.5);
  --ck-keycap: url("/assets/gen/key_a.f1b38f01.svg");
  /* the screen recess ring: sunk into the chassis. All external — the screen
     is too dark for interior shadows to read. Crisp top seam · shaded band
     where the plastic curves down into the cutout · lit bottom lip with a
     soft glare bloom on the chassis below (so no dark seam at the bottom,
     where the lip catches light). */
  --ck-recess:
    0 -1px 0 rgba(0, 0, 0, 0.35),
    0 -4px 6px -3px rgba(0, 0, 0, 0.55),
    -3px 0 5px -3px rgba(0, 0, 0, 0.3),
    3px 0 5px -3px rgba(0, 0, 0, 0.3),
    0 1px 0 rgba(255, 255, 255, 0.35),
    0 4px 6px -3px rgba(255, 255, 255, 0.45);
  /* ◀ THE spacing knob between page sections (the only one — legacy .page gap
     and .ck-section margins are both neutralized to defer to it) */
  --ck-section-gap: clamp(0.8rem, 1.6vw, 1.2rem);
  /* simulated 90s-beige-computer plastic: very fine generated speckle */
  /* one uniform plastic: flat tone + film-fine grain (strength baked into the
     tile so every consumer — chassis, label cuts — matches exactly) */
  --ck-plastic: #dfd9c9;
  --ck-grain: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120'%3E%3Cfilter id='g'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='1.5' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='120' height='120' filter='url(%23g)' opacity='0.9'/%3E%3C/svg%3E");
}

/* ── Chassis: the page IS the plastic ──────────────────────────────────── */
.ck-chassis {
  position: relative;
  
  
  /* cooler, near-uniform bone plastic (the terminal's warm cream read too
     yellow at page scale); flat so the label text-cuts match it anywhere */
  background: var(--ck-plastic);
  /* the plastic runs to the bottom of the window even when the page is short */
  min-height: 100vh;
  min-height: 100dvh;
  font-family: var(--ck-font-body);
}
.ck-chassis::before {
  content: '';
  position: absolute;
  inset: 0;
  
  
  background: var(--ck-grain);
  mix-blend-mode: overlay;
}
/* everything composed on the chassis floats above its texture layers */
.ck-chassis > * { position: relative; z-index: 1; }

/* ── Bezel: the molded frame a screen is installed in ──────────────────────
   Same recipe as .ck-frame around the nav keys: a faint face, a lit top edge,
   a shaded bottom edge, and a hairline outline. It is drawn just outside the
   screen, so page layout is unchanged; a one-cell grid so the screen still
   stretches to its row's height when screens sit side by side. */
.ck-bezel {
  /* ◀ bezel knobs */
  --ck-bezel-gap: 6px;           /* how far the frame sits outside the screen */
  --ck-bezel-outline: 0.1;       /* the hairline around the frame */
  --ck-bezel-lit: 0.35;          /* the lit top edge */
  --ck-bezel-shade: 0.18;        /* the shaded bottom edge */

  position: relative;
  display: grid;
}
.ck-bezel::before {
  content: '';
  position: absolute;
  inset: calc(-1 * var(--ck-bezel-gap));
  border-radius: calc(12px + var(--ck-bezel-gap));   /* concentric with the screen's 12px */
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.05), rgba(0, 0, 0, 0.05));
  box-shadow:
    inset 0 1px 0 rgb(255 255 255 / var(--ck-bezel-lit)),
    inset 0 -1px 0 rgb(0 0 0 / var(--ck-bezel-shade)),
    0 0 0 1px rgb(0 0 0 / var(--ck-bezel-outline));
  pointer-events: none;
}

/* ── CRT screen: recessed dark panel with scanlines + vignette ─────────── */
.ck-screen {
  position: relative;
  border-radius: 12px;
  overflow: hidden;
  --ck-vignette: 0.75;
  /* layers, top to bottom: bulged-glass bloom (the tube's center sits closest
     to the viewer), in-glass vignette, phosphor-dark base. The vignette is a
     gradient rather than an inset shadow so the bloom always paints above it. */
  background:
    radial-gradient(ellipse at 50% 42%, color-mix(in srgb, var(--ck-bright) 6.5%, transparent), transparent 72%),
    radial-gradient(ellipse at center, transparent 55%, rgba(0, 0, 0, var(--ck-vignette))),
    var(--ck-bg);
  color: var(--ck-fg);
  font-family: var(--ck-font-screen);
  --ck-font-body: var(--ck-font-screen);   /* on-screen text is all phosphor — no mixed faces */
  box-shadow: var(--ck-recess);
  padding: clamp(0.4rem, 1vw, 0.7rem) clamp(0.8rem, 2vw, 1.4rem) clamp(0.8rem, 2vw, 1.4rem);
  font-size: clamp(0.9rem, 1.6vw, 1.05rem);
  
  /* phosphor halo: tight glow + wide falloff, in each run's own color */
  text-shadow:
    0 0 4px color-mix(in srgb, currentcolor 35%, transparent),
    0 0 13px color-mix(in srgb, currentcolor 18%, transparent);
}
/* semantic defaults for on-screen markup: prose is dim, <strong> is the
   accent lead-in, <em> is bright phosphor. :where() keeps specificity at
   class level so utility classes and component rules below still win. */
.ck-screen :where(h1, h2, h3) { font-size: inherit; }
.ck-screen :where(p) { margin: 0 0 0.7rem; color: var(--ck-dim); }
.ck-screen :where(p:last-child) { margin-bottom: 0; }
.ck-screen :where(strong) { color: var(--ck-accent); font-weight: normal; }

.ck-screen::before {
  /* scanlines */
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 4;
  border-radius: inherit;
  background: repeating-linear-gradient(
    to bottom,
    rgba(0, 0, 0, 0) 0,
    rgba(0, 0, 0, 0) 2px,
    rgba(0, 0, 0, 0.16) 3px
  );
  mix-blend-mode: multiply;
  opacity: 0.55;
}
/* long-form variant: same material, gentler effects, comfier reading */
.ck-screen--soft::before { opacity: 0.28; }
.ck-screen--soft { --ck-vignette: 0.5; }
/* one-shot power-on flicker — hero screens only (.ck-screen--boot) */
@keyframes ck-power-on {
  0% { opacity: 0; }
  8% { opacity: 0.55; }
  13% { opacity: 0.28; }
  22% { opacity: 1; }
  100% { opacity: 1; }
}
.ck-screen--boot { animation: ck-power-on 0.85s ease-out both; }

.ck-screen ::selection { background: var(--ck-fg); color: var(--ck-bg); }

/* on-screen ASCII art (figlet banners etc.) */
.ck-ascii-art {
  margin: 0 0 0.7rem;
  font-family: 'Courier New', Courier, monospace;
  font-size: clamp(6px, 1vw, 9px);
  line-height: 1;   /* █ rows must tile — leading shows as stripes when inverted */
  color: var(--ck-accent);
  
}

/* phosphor text helpers */

.ck-accent { color: var(--ck-accent); }




/* ── Links: the terminal's token language ──────────────────────────────── */
.ck-link,
.ck-prose a {
  /* inline-block: <a> and <button> tokens get identical highlight boxes */
  display: inline-block;
  
  
  color: var(--ck-accent);
  
  
  
  padding: 0 2px;
  
  
     /* button UA centering shears wrapped pre art */
}
.ck-link:hover,
.ck-link:focus-visible,
.ck-prose a:hover,
.ck-prose a:focus-visible {
  color: var(--ck-bg);
  background: var(--ck-accent);
  outline: none;
  text-decoration: none;   /* the global a:hover underline must not win */
  text-shadow: none;       /* inverted ink doesn't glow — only lit phosphor does */
}
.ck-link--plain { color: var(--ck-fg); }
.ck-link--plain:hover,
.ck-link--plain:focus-visible { background: var(--ck-fg); color: var(--ck-bg); }
/* art links: hover shows a `<` selector beside the banner instead of a
   highlight slab — the art stays lit phosphor throughout */
.ck-link--art {
  display: inline-flex;
  align-items: center;
  
}
.ck-link--art:hover,
.ck-link--art:focus-visible {
  color: var(--ck-accent);
  background: transparent;
  text-shadow: inherit;
}
.ck-art-cursor { visibility: hidden; }   /* not display — the art must not shift on hover */
.ck-link--art:hover .ck-art-cursor,
.ck-link--art:focus-visible .ck-art-cursor { visibility: visible; }
.ck-link .ck-ascii-art { margin-bottom: 0; }
.ck-link:has(.ck-ascii-art) { margin-bottom: 0.7rem; }

/* ── TUI box: bordered panel with the title set into the border ────────── */
.ck-box {
  position: relative;
     /* fieldsets default to min-content and refuse to shrink in grids */
  border: 1px solid var(--ck-dim);
  padding: 0.5rem 1.1rem 0.9rem;
  margin: 0;
}
.ck-box__title {
  /* legend: sits in a real gap in the border — the glass shows through */
  padding: 0 0.6ch;
  margin-left: 10px;
  color: var(--ck-dim);
  letter-spacing: 0.08em;
  line-height: 1.2;
  
}
/* literal stack, not --ck-font-body: JGS7's box-drawing glyphs are slanted */
.ck-box__title::before { content: '┤ '; font-family: 'Courier New', Courier, monospace; }
.ck-box__title::after { content: ' ├'; font-family: 'Courier New', Courier, monospace; }
.ck-box--accent { border-color: var(--ck-accent); }
.ck-box--accent > .ck-box__title { color: var(--ck-accent); }

/* a blog list entry: its text, and the post's banner as a blocky thumbnail at
   the box's right edge, as tall as the entry (the box's padding is the cell of
   space around it). A post without a banner has no thumbnail and no reserved
   space — the text runs the full width. */
.ck-post-entry {
  /* ◀ thumbnail knobs */
  --ck-thumb-max: 140px;   /* largest the thumbnail grows, and the text column's reserve */
  --ck-thumb-gap: 1.2rem;  /* space between the text and the thumbnail */
  position: relative;
}
.ck-post-entry--thumb > .ck-post-entry__text {
  padding-right: calc(var(--ck-thumb-max) + var(--ck-thumb-gap));
}
.ck-post-entry__thumb {
  position: absolute;
  top: 0;
  right: 0;
  height: 100%;
  max-height: var(--ck-thumb-max);
  aspect-ratio: 1;
  /* a 32-pixel source scaled up with hard edges, like the leadership
     portraits' block art; framed like their portrait slot */
  image-rendering: pixelated;
  padding: 3px;
  border: 1px solid var(--ck-dim);
  border-radius: 3px;
  background: var(--ck-bg);
}
@media (max-width: 560px) {
  .ck-post-entry { --ck-thumb-max: 84px; --ck-thumb-gap: 0.9rem; }
}


/* an h2 leading a box is the box's headline, not a screen-level heading */


/* ── Embossing: raised forms in a pressed-in panel ─────────────────────────
   Molded like a maker's badge on a case: a shallow rounded panel sunk into the
   plastic (.ck-emboss) with forms standing up from its floor
   (.ck-emboss__raised), read through light and shadow. Walls facing the light
   catch a highlight; walls facing away fall into shadow. Used by the section
   labels and the nav's brand panel; each sets its own depths. */
.ck-emboss {
  /* ◀ emboss knobs, shared by every embossed panel (alphas 0–1) */
  --ck-emboss-shadow: 10 5 5;        /* shadow color, as space-separated R G B */
  --ck-emboss-light-x: 0;            /* which way shadows fall: 1 right, -1 left, 0 neither; */
  --ck-emboss-light-y: 1;            /* 1 down, -1 up. Highlights take the opposite side */
  --ck-emboss-floor: 0.03;           /* the panel floor's darkening (it sits lower, in less light) */
  --ck-emboss-recess: 0.28;          /* shadow the panel's walls cast onto the floor */
  --ck-emboss-wall-lit: 0.55;        /* the panel walls catching the light */
  --ck-emboss-rim: 0.5;              /* highlight on the panel's outer edge, light side */
  --ck-emboss-raised-lit: 0.7;       /* the raised forms' lit edges */
  --ck-emboss-raised-shadow: 0.4;    /* the shadow the raised forms cast onto the floor */
  /* depths — em defaults scale with the section labels; the nav sets px */
  --ck-emboss-recess-depth: 0.035em; /* how far the panel's wall shadow reaches */
  --ck-emboss-raise: 0.03em;         /* how far raised forms stand up (their shadow's reach) */

  /* shadow and highlight offsets: shadows fall along the light direction,
     highlights sit on the side facing the light */
  --ck-emboss-sx: var(--ck-emboss-light-x);
  --ck-emboss-sy: var(--ck-emboss-light-y);
  /* the floor: the chassis itself (its grain shows through), a touch darker */
  background: rgb(var(--ck-emboss-shadow) / var(--ck-emboss-floor));
  box-shadow:
    /* inside the panel: walls facing away from the light shade the floor,
       walls facing it are lit */
    inset calc(var(--ck-emboss-recess-depth) * var(--ck-emboss-sx)) calc(var(--ck-emboss-recess-depth) * var(--ck-emboss-sy)) calc(var(--ck-emboss-recess-depth) * 1.4) rgb(var(--ck-emboss-shadow) / var(--ck-emboss-recess)),
    inset calc(-1px * var(--ck-emboss-sx)) calc(-1px * var(--ck-emboss-sy)) 0 rgb(255 255 255 / var(--ck-emboss-wall-lit)),
    /* on the case: the panel's rim on the light side catches the light */
    calc(-1px * var(--ck-emboss-sx)) calc(-1px * var(--ck-emboss-sy)) 0 rgb(255 255 255 / var(--ck-emboss-rim));
}
.ck-emboss__raised {
  /* lit edges on the light side, then the shadow cast away from the light
     onto the floor: a crisp contact line where each wall meets the floor, and
     a soft falloff */
  filter:
    drop-shadow(calc(-1px * var(--ck-emboss-sx)) calc(-1px * var(--ck-emboss-sy)) 0 rgb(255 255 255 / var(--ck-emboss-raised-lit)))
    drop-shadow(calc(var(--ck-emboss-raise) * 0.5 * var(--ck-emboss-sx)) calc(var(--ck-emboss-raise) * 0.5 * var(--ck-emboss-sy)) 0 rgb(var(--ck-emboss-shadow) / calc(var(--ck-emboss-raised-shadow) * 0.6)))
    drop-shadow(calc(var(--ck-emboss-raise) * var(--ck-emboss-sx)) calc(var(--ck-emboss-raise) * var(--ck-emboss-sy)) var(--ck-emboss-raise) rgb(var(--ck-emboss-shadow) / var(--ck-emboss-raised-shadow)));
}

/* ── Section label: an enamel name plate screwed to the chassis ───────────
   Control-room tagging: a white enamel plate standing just off the case, sized
   to its lettering and centered over the section, held by a slotted screw at
   each end, with bold black lettering embossed shallow into it. Light comes
   from above. */
.ck-plate {
  /* ◀ label knobs (lengths scale with the label's font size) */
  --ck-plate-pad-y: 0.16em;          /* plate showing above and below the letters */
  --ck-plate-pad-x: 0.6;             /* plate past each end of the lettering, in em — a
                                        bare number: the fit formula below adds it; keep
                                        it past the screws (inset + half their size) */
  --ck-plate-radius: 1px;            /* corner rounding — sharp, like cut sheet */
  --ck-plate-enamel: #f3f1ea;        /* the plate's white */
  --ck-plate-gloss: 0.55;            /* the enamel's sheen across its top */
  --ck-plate-lift: 0.03em;           /* how far the plate stands off the case (its shadow) */
  --ck-plate-ink: #141414;           /* letter color */
  --ck-plate-ink-lit: 30%;           /* how much the letters' top edges catch the light */
  --ck-plate-ink-raise: 0.012em;     /* how far the letters stand off the plate */
  --ck-plate-rivet: 0.3em;           /* screw head diameter */
  --ck-plate-rivet-inset: 0.3em;     /* screw centre from each end of the plate */
  --ck-plate-slot-angle: 90deg;      /* screw slot: 90deg vertical, 0deg horizontal */

  position: relative;
  /* Full size where it fits; on narrow screens, shrink to exactly the
     section's width. --ck-plate-text is the label's text width in em, summed
     from measured glyph advances by the section_head macro (see
     PLATE_ADVANCES in sitegen/config.py), plus the two side paddings, which
     also hold the screws. Kerning is off so that sum is exact. */
  font-size: min(4em, 100cqi / (var(--ck-plate-text, 12) + 2 * var(--ck-plate-pad-x)));
  font-kerning: none;
  font-family: 'Aulendur Brand', 'IBM Plex Sans', Helvetica, Arial, sans-serif;
  font-weight: 700;
  letter-spacing: 0.2em;   /* PLATE_LETTER_SPACING in sitegen/config.py */
  text-box: trim-both cap alphabetic;   /* padding measures from the cap height */
  white-space: nowrap;
  text-transform: uppercase;
  /* the plate hugs its lettering, centered over the section; a label too long
     to fit shrinks until the plate spans the section exactly */
  margin-inline: auto;
  padding: var(--ck-plate-pad-y) calc(var(--ck-plate-pad-x) * 1em);
  border-radius: var(--ck-plate-radius);
  /* layers, top to bottom: the enamel's sheen, a faint falloff toward the
     bottom edge, the enamel */
  background:
    linear-gradient(180deg, rgb(255 255 255 / var(--ck-plate-gloss)), rgb(255 255 255 / 0) 45%),
    linear-gradient(0deg, rgb(0 0 0 / 0.05), rgb(0 0 0 / 0) 40%),
    var(--ck-plate-enamel);
  box-shadow:
    /* the cut edge: lit along the top, shaded along the bottom */
    inset 0 1px 0 rgb(255 255 255 / 0.95),
    inset 0 -1px 0 rgb(0 0 0 / 0.12),
    /* a hairline where the plate meets the case, and its shadow on the case */
    0 0 0 1px rgb(0 0 0 / 0.16),
    0 var(--ck-plate-lift) calc(var(--ck-plate-lift) * 1.5) rgb(0 0 0 / 0.28);
}
/* the screws: domed silver heads, lit from above, each cut with a slot (dark,
   its far wall catching the light) and sitting in its own small shadow on the
   enamel */
.ck-plate::before,
.ck-plate::after {
  content: '';
  position: absolute;
  top: 50%;
  width: var(--ck-plate-rivet);
  height: var(--ck-plate-rivet);
  margin-top: calc(var(--ck-plate-rivet) / -2);
  border-radius: 50%;
  background:
    linear-gradient(var(--ck-plate-slot-angle),
      transparent 43%, rgb(30 32 35 / 0.65) 43% 55%, rgb(255 255 255 / 0.55) 55% 60%, transparent 60%),
    radial-gradient(circle at 38% 30%, #fff 0%, #e6e8ea 16%, #b3b7bc 48%, #7b8085 80%, #575b60 100%);
  box-shadow:
    0 0.012em 0.02em rgb(0 0 0 / 0.45),
    0 0 0 0.006em rgb(0 0 0 / 0.3);
}
.ck-plate::before { left: calc(var(--ck-plate-rivet-inset) - var(--ck-plate-rivet) / 2); }
.ck-plate::after { right: calc(var(--ck-plate-rivet-inset) - var(--ck-plate-rivet) / 2); }
.ck-plate__text {
  /* black lettering, its top edges catching a little light */
  background: linear-gradient(180deg,
    color-mix(in srgb, var(--ck-plate-ink), white var(--ck-plate-ink-lit)) 0%,
    var(--ck-plate-ink) 28%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  margin-right: -0.2em;   /* trailing letter-spacing gap */
  /* embossed shallow: a fine shadow just below each stroke */
  filter: drop-shadow(0 var(--ck-plate-ink-raise) calc(var(--ck-plate-ink-raise) * 0.8) rgb(0 0 0 / 0.3));
}

/* ── Molded plastic frame (groups controls; mirrors .dv-plastic-frame) ─── */
.ck-frame {
  border-radius: 10px;
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.05), rgba(0, 0, 0, 0.05));
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.35),
    inset 0 -1px 0 rgba(0, 0, 0, 0.18),
    0 0 0 1px rgba(0, 0, 0, 0.1);
}

/* ── Console key: keycap + mini LCD function label (mirrors macro pad) ─── */
.ck-key {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 5px;
  border: 0;
  padding: 0;
  background: none;
  cursor: pointer;
  -webkit-user-select: none;
  user-select: none;
}
.ck-key__cap {
  
  width: var(--ck-key);
  height: var(--ck-key);
  background: var(--ck-keycap) center / contain no-repeat;
  filter: drop-shadow(var(--ck-key-shadow));
  transition: filter 0.05s ease, transform 0.05s ease;
  container-type: size;   /* cqh sizes the printed glyphs with the cap */
}
/* Cap printing — the terminal keyboard's language: the char as a crimson rune
   (primary, in-universe) + a small Latin reference legend beneath it. */
.ck-key__rune {
  position: absolute;
  left: 35%;
  top: 35%;
  transform: translate(-50%, -50%);
  font-family: 'Starforge Runic', serif;
  font-size: 54cqh;
  
  color: #8b0a1e;
  
}
.ck-key__legend {
  position: absolute;
  left: 70%;
  top: 65%;
  transform: translate(-50%, -50%);
  font-family: 'Iosevka Term Slab', 'Courier New', Courier, monospace;
  font-style: italic;
  font-weight: 700;
  font-size: 18cqh;
  
  text-transform: uppercase;
  color: #3a0a0a;
  mix-blend-mode: color-burn;
  
}
.ck-key:hover .ck-key__cap { filter: brightness(1.08) drop-shadow(var(--ck-key-shadow)); }
.ck-key:active .ck-key__cap,
.ck-key.is-down .ck-key__cap {
  transform: translateY(2px);
  filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.5));
}
.ck-key__lcd {
  position: relative;
  width: var(--ck-key);
  height: 17px;
  
  display: grid;
  place-items: center;
  border-radius: 3px;
  background: linear-gradient(180deg, var(--ck-lcd-glass), var(--ck-lcd-glass-2));
  box-shadow:
    inset 0 1px 2px rgba(0, 0, 0, 0.35),
    inset 0 0 0 1px rgba(0, 0, 0, 0.28),
    0 1px 0 rgba(255, 255, 255, 0.4);
  font-family: 'DS-Digital', 'Courier New', monospace;
  font-size: 13px;
  line-height: 1;
  letter-spacing: 1px;
}
.ck-key__ghost { color: var(--ck-lcd-ghost); }
.ck-key__lit {
  position: absolute;
  
  
  
  color: var(--ck-lcd-seg);
}

/* ── Knob (filmstrip; mirrors .dv-knob) ────────────────────────────────── */
.ck-knob {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 5px;
  cursor: ns-resize;
  -webkit-user-select: none;
  user-select: none;
  touch-action: none;
}
.ck-knob__frames {
  width: 100%;
  display: block;
  pointer-events: none;
  -webkit-user-drag: none;
}


/* ── Power/activity LED (mirrors .dv-led) ──────────────────────────────── */
.ck-led {
  
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: radial-gradient(circle at 38% 32%, #b6ffce, #46e07a 55%, #1faf57 100%);
  /* glow · dome highlight · cutout: seam ring + lit bottom lip (matches --ck-recess) */
  box-shadow:
    0 0 10px 2px rgba(70, 224, 122, 0.8),
    inset 0 1px 2px rgba(255, 255, 255, 0.6),
    0 0 0 1px rgba(0, 0, 0, 0.3),
    0 1px 0 rgba(255, 255, 255, 0.35);
  animation: ck-led-pulse 3.2s ease-in-out infinite;
}

@keyframes ck-led-pulse { 0%, 100% { opacity: 0.82; } 50% { opacity: 1; } }

/* ── ASCII banner (typed row-by-row when in view) ──────────────────────── */
/* Sizing avoids container units: the terminal's min(1em, 100cqi/…) formula
   resolved differently across engines (WebKit picked the uncapped branch and
   blew the art up ~1.6×, garbling it). Viewport units resolve the same
   everywhere, so the art shrinks to the viewport instead: full size where it
   fits, else the width left after the page and screen gutters — measured at
   about 64px + 11.5vw on narrow screens, taken as 80px + 11.5vw for headroom
   (a desktop scrollbar counts in 100vw) — divided by the art's width in em
   (--art-em, set by the banner macro: 0.5em per column). */
/* Not `ck-banner`: Fanboy's Annoyance List carries a generic `##.ck-banner`
   cosmetic filter (a cookie-consent library claims that class), so uBlock
   Origin hid the wordmark on the live domain. Keep `banner` out of the root
   class token. */
.ck-ascii-banner { overflow: hidden; }
.ck-ascii-banner__art {
  font-size: min(1em, (88.5vw - 80px) / var(--art-em, 33.5));
  margin: 0 auto;
  color: var(--ck-accent);
  
  line-height: 1.05;
  
}
/* Rows are fixed-height rails; glyph runs are absolutely placed on the 0.5em
   column grid (see AsciiBanner.jsx — nothing here is text-measured). */
.ck-ascii-banner__row {
  position: relative;
  height: 1.05em;
  
}
.ck-ascii-banner__run {
  position: absolute;
  
  
}
.ck-ascii-banner.is-live .ck-ascii-banner__row {
  animation: ck-row-in 0.26s ease-out both;
  animation-delay: calc(var(--i) * 42ms);
}
@keyframes ck-row-in {
  from { opacity: 0; transform: translateY(3px); }
  to { opacity: 1; transform: none; }
}

/* ── TUI accordion (FAQ) ───────────────────────────────────────────────── */
.ck-acc { border: 1px solid var(--ck-dim); border-radius: 3px; }
.ck-acc + .ck-acc { margin-top: 0.55rem; }
.ck-acc__q {
  display: block;
  width: 100%;
  padding: 0.55rem 0.9rem;
  cursor: pointer;
  color: var(--ck-fg);
  font: inherit;
  list-style: none;
  -webkit-user-select: none;
  user-select: none;
}
.ck-acc__q::-webkit-details-marker { display: none; }
.ck-acc__q::before { content: '▸ '; color: var(--ck-accent); }
.ck-acc[open] > .ck-acc__q::before { content: '▾ '; }
.ck-acc__q:hover { background: rgba(200, 242, 192, 0.07); }
.ck-acc__a {
  margin: 0 0.9rem 0.8rem 1.2rem;
  padding-left: 0.9rem;
  border-left: 1px solid var(--ck-dim);
  
  
}

/* ── TUI form fields ───────────────────────────────────────────────────── */
.ck-field { display: block; margin-bottom: 0.9rem; }
.ck-field__label { display: block; color: var(--ck-dim); margin-bottom: 0.25rem; }
.ck-field__label::before { content: '· '; color: var(--ck-accent); }
.ck-input {
  width: 100%;
  
  padding: 0.45rem 0.7rem;
  background: rgba(200, 242, 192, 0.05);
  border: 1px solid var(--ck-dim);
  border-radius: 3px;
  color: var(--ck-fg);
  font-family: var(--ck-font-body);
}
.ck-input:focus {
  outline: none;
  border-color: var(--ck-accent);
  box-shadow: 0 0 0 1px var(--ck-accent);
}
.ck-input--area { min-height: 7.5em; resize: vertical; }
.ck-input::placeholder { color: color-mix(in srgb, var(--ck-dim) 60%, transparent);  }
/* browser autofill would otherwise paint the field opaque white inside the CRT */
.ck-input:-webkit-autofill,
.ck-input:-webkit-autofill:hover,
.ck-input:-webkit-autofill:focus {
  -webkit-text-fill-color: var(--ck-fg);
  -webkit-box-shadow: 0 0 0 1000px #10140f inset;
  caret-color: var(--ck-fg);
}

/* TUI action button — the link token language with the weight of a key */
.ck-btn {
  
  background: transparent;
  border: 1px solid var(--ck-accent);
  border-radius: 3px;
  color: var(--ck-accent);
  font-family: var(--ck-font-screen);
  font-size: 1em;
  letter-spacing: 0.05em;
  padding: 0.42rem 0.9rem;
  cursor: pointer;
}
.ck-btn::before { content: '[ '; }
.ck-btn::after { content: ' ]'; }
.ck-btn:hover,
.ck-btn:focus-visible {
  background: var(--ck-accent);
  color: var(--ck-bg);
  outline: none;
}
.ck-btn:active { transform: translateY(1px); }

/* form submit acknowledgement line */
.ck-form__status { margin: 0.9rem 0 0; color: var(--ck-fg); }
.ck-form__status::before { content: '✓ '; color: var(--ck-accent); }

/* ── Page scaffolding ──────────────────────────────────────────────────── */
.ck-main {
  max-width: 1160px;
  margin: 0 auto;
  padding: clamp(1rem, 3vw, 2rem) clamp(0.9rem, 3vw, 1.6rem) 3rem;
}
/* Legacy App.css gives .page `gap: 2.75rem`, which was stacking with section
   margins. Sections carry NO margin; the flex gap (--ck-section-gap) is the
   single source of rhythm. */
.ck-main.page { gap: var(--ck-section-gap);  }

.ck-section__head {
  container-type: inline-size;   /* the section label sizes itself to this width */
  display: flex;
  
  
  margin-bottom: 0.7rem;
}

/* ── Nav bar: brand + key row (the site's "macro pad") ─────────────────── */
.ck-nav {
  
  
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  max-width: 1240px;
  margin: 0 auto;
  padding: 10px clamp(0.9rem, 3vw, 1.6rem) 6px;
  flex-wrap: wrap;
}
/* the brand panel: logo and power LED embossed together, stretching from the
   logo to just past the LED, beside the key frame */
.ck-nav__badge {
  /* ◀ nav panel depths (the shared look comes from the .ck-emboss knobs) */
  --ck-emboss-recess-depth: 2px;
  --ck-emboss-raise: 2px;
  flex: 1;
  align-self: stretch;   /* as tall as the key frame beside it, top and bottom */
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 8px 12px 8px 14px;
  border-radius: 10px;
}
.ck-nav__brand {
  display: flex;
  align-items: center;
  gap: 12px;
}
.ck-nav__mark {
  /* logo-black.svg drawn as a mask so its fill tracks the wordmark engrave color */
  height: 64px;
  aspect-ratio: 600 / 264;
  background-color: var(--ck-label);
  -webkit-mask: var(--brand-mark) center / contain no-repeat;
  mask: var(--brand-mark) center / contain no-repeat;
}
.ck-nav__word {
  display: flex;
  flex-direction: column;
  
  font-family: 'Aulendur Brand', 'IBM Plex Sans', Helvetica, Arial, sans-serif;
  color: var(--ck-label);   /* raised by .ck-emboss__raised on the brand link */
  line-height: 1;
  
}
.ck-nav__word strong { font-size: 34px;  letter-spacing: 0.15em; }
.ck-nav__word span { font-size: 15px; letter-spacing: 0.46em; margin-top: 5px; opacity: 0.75; }
.ck-nav__cluster { display: flex; align-items: center; }
.ck-nav__led { width: 17px; height: 17px; }
@media (max-width: 900px) {
  .ck-nav__mark { height: 46px; }
  .ck-nav__word strong { font-size: 24px; }
  .ck-nav__word span { font-size: 11px; }
}
.ck-nav__keys {
  display: flex;
  
  gap: 8px;
  padding: 7px 9px 6px;
}
/* latched key = the page you're on (physically pressed in) */
.ck-nav__keys .ck-key.is-down { cursor: default; }

@media (max-width: 760px) {
  .ck-chassis { --ck-key: 38px; }
  .ck-nav { justify-content: center; }
  .ck-nav__keys { flex-wrap: wrap; justify-content: center; }
}

/* ── Content + footer scaffolding around legacy pages ──────────────────── */
.ck-content {
  
  padding-bottom: 0.8rem;   /* the legacy .content padding-bottom is dead space here */
}
.ck-footer-wrap {
  
  
  max-width: 1160px;
  /* auto cross-axis margins disable flex stretch — width:100% above restores it */
  margin: 0 auto;
  padding: 0 clamp(0.9rem, 3vw, 1.6rem) 2.2rem;
}
.ck-footer__grid {
  /* content-sized columns: the long nav list gets the room it needs */
  display: flex;
  flex-wrap: wrap;
  gap: 1.1rem;
}
.ck-footer__list {
  list-style: none;
  margin: 0;
  padding: 0;
  
  /* one line when it fits, wrapping when it doesn't */
  display: flex;
  flex-wrap: wrap;
  column-gap: 1.2ch;
}
.ck-footer__list li { margin: 0.32rem 0; }
.ck-footer__list li + li::before { content: '· '; color: var(--ck-dim); }
.ck-footer__legal {
  /* stamped below the screen, straight on the plastic — not phosphor text.
     font-family: inherits var(--ck-font-body) from .ck-chassis. */
  margin: 1rem 0 0;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.1em;
  color: rgb(0 0 0 / 85%);   /* black, translucent so it reads with the plastic grain under it */
  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);   /* incised */
  text-align: center;
}


/* ── Layout helpers (home + section grids) ─────────────────────────────── */
.ck-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 1.1rem;
}

.ck-split {
  display: grid;
  grid-template-columns: minmax(280px, 5fr) minmax(320px, 7fr);
  gap: 1.4rem;
  align-items: start;   /* screens keep their natural height — no stretching */
}

@media (max-width: 900px) {
  .ck-split, .ck-split--flip { grid-template-columns: 1fr; }
}
/* grid items default to min-width:auto — one long unbreakable token (command
   output, cascade chains) would then hold the track open and overflow the
   page on phones. Let tracks shrink; overflow-wrap handles the text. */

.ck-hero { text-align: center; }
.ck-hero__title {
  margin: 1.1rem 0 0.4rem;
  font-size: clamp(1.1rem, 2.6vw, 1.6rem);
  font-weight: 400;
  letter-spacing: 0.06em;   /* snake_case syntax — keep it tight and code-like */
  
}
.ck-screen :is(h1, h2, h3) { margin-top: 1lh; }   /* one blank terminal line */
.ck-screen :is(h1, h2, h3):first-child { margin-top: 0; }
.ck-screen :is(h1, h2)::before { content: 'aulendur:~$ '; color: var(--ck-dim); }
.ck-screen .ck-box :is(h1, h2)::before { content: none; }   /* box headlines aren't shell prompts */

.ck-hero__mission {
  max-width: 62ch;
  margin: 0 auto 0.5rem;
  
  
}

.ck-caret {
  
  animation: ck-caret-blink 1.05s steps(1) infinite;
}
@keyframes ck-caret-blink {
  0%, 50% { opacity: 1; }
  50.01%, 100% { opacity: 0; }
}
/* tree leaves (mission domains) */
.ck-tree { list-style: none; margin: 0.4rem 0 0; padding: 0;  }
.ck-tree li { margin: 0.22rem 0;  }
.ck-tree li::before { content: '├─ '; color: var(--ck-dim); font-family: 'Courier New', Courier, monospace; }
.ck-tree li:last-child::before { content: '└─ '; }

/* ── AsciiGlobe ────────────────────────────────────────────────────────── */
.ck-globe {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  container-type: inline-size;
}
.ck-globe__stage {
  position: relative;
  line-height: 0;
  /* Both layers have 120 columns; the land layer is absolutely positioned. */
  width: 120ch;
  max-width: 100%;
  font-family: var(--ck-font-screen);
  font-size: clamp(3px, 0.75vw, 9.5px);
  font-size: clamp(3px, 1.25cqi, 9.5px);
}
.ck-globe__ocean,
.ck-globe__land {
  margin: 0;
  font-family: inherit;
  font-size: inherit;
  line-height: 1.06;
  letter-spacing: 0;
  white-space: pre;
}
.ck-globe__ocean { color: color-mix(in srgb, var(--ck-dim) 45%, transparent); }
.ck-globe__land {
  position: absolute;
  inset: 0;
  color: var(--ck-accent);
  text-shadow: 0 0 3px rgba(255, 182, 72, 0.28);
}
.ck-globe .ck-tui-keys { flex-wrap: wrap; justify-content: center; }
.ck-globe .ck-tui-key,
.ck-globe [data-globe-meter] { flex: 0 0 auto; white-space: nowrap; }
/* ── WeavecastTerm ─────────────────────────────────────────────────────── */
.ck-wterm__out {
  height: 15.4em;       /* FIXED — the screen can never grow; output scrolls */
  overflow-y: auto;
  scrollbar-width: thin;
  scrollbar-color: var(--ck-dim) rgba(0, 0, 0, 0.4);
  line-height: 1.5;
}
/* square TUI scrollbar: block thumb on a dark rail */
.ck-wterm__out::-webkit-scrollbar { width: 10px; }
.ck-wterm__out::-webkit-scrollbar-track { background: rgba(0, 0, 0, 0.4); }
.ck-wterm__out::-webkit-scrollbar-thumb {
  background: var(--ck-dim);
  border-radius: 0;
  border: 2px solid rgba(0, 0, 0, 0.55);
}
.ck-wterm__out::-webkit-scrollbar-thumb:hover { background: var(--ck-fg); }
/* anywhere (not break-word): long tokens must also shrink min-content */
.ck-wterm__line { white-space: pre-wrap; overflow-wrap: anywhere; }
.ck-wterm__line.is-dim { color: var(--ck-dim); }
.ck-wterm__line.is-accent { color: var(--ck-accent); }

.ck-wterm__caret.is-idle { opacity: 0.3;  }
/* ASCII mode keys: plain glyph buttons, lit when selected */
.ck-tui-keys { display: flex; gap: 1.5ch; margin-top: 0.4rem; }
.ck-tui-key {
  background: none;
  border: 0;
  padding: 0;
  font: inherit;
  color: var(--ck-dim);
  cursor: pointer;
}
.ck-tui-key:hover { color: var(--ck-fg); }
.ck-tui-key.is-down { color: var(--ck-accent); }
.ck-tui-key:disabled { opacity: 0.35; cursor: default; }
.ck-tui-key:disabled:hover { color: var(--ck-dim); }

/* ── Interior pages (showcase / about / blog) ──────────────────────────── */

.ck-quote {  font-style: italic; max-width: 76ch; line-height: 1.75; }

/* Leadership: portrait slot (awaiting ANSI art) + bio. */
.ck-leader { display: flex; gap: 1.1rem; align-items: flex-start; }
@media (max-width: 560px) { .ck-leader { flex-direction: column; } }
.ck-portrait {
  flex: 0 0 auto;
  
  
  display: grid;
  
  border: 1px solid var(--ck-dim);
  border-radius: 3px;
  
}

/* live feed: the slot wraps the art instead of centering the ghost */
.ck-portrait--live {
  width: 172px;
  
  
  padding: 4px;
  background: var(--ck-bg);
}
.ck-ansi-art {
  
  width: 100%;
  
  image-rendering: pixelated;
  border-radius: 2px;
}

/* ── Reduced motion ────────────────────────────────────────────────────── */
@media (prefers-reduced-motion: reduce) {
  .ck-screen--boot { animation: none; }
  .ck-ascii-banner__row,
  .ck-ascii-banner.is-live .ck-ascii-banner__row { animation: none;  }
  .ck-led { animation: none; }
  .ck-caret, .ck-wterm__caret { animation: none; }
}
/* Long-form Markdown prose on a console screen. The generator emits plain
   h2/p/a inside a .ck-prose wrapper; these rules give them the console look
   (links are covered by the .ck-prose a selectors beside .ck-link in
   console.css, so hover/focus behavior stays defined in one place). */
.ck-prose h2 {
  color: var(--ck-accent);
  margin: 1.4rem 0 0.4rem;
  
  
}
.ck-prose p {
  
  
  margin: 0 0 0.4rem;
  max-width: 78ch;
}
/* Console widget rules — the two things console.css cannot know about the
   generated markup for AsciiBanner and AsciiGlobe. Everything else the widget
   partials need (the globe grid, the wterm transcript, the portrait canvas)
   already lives in console.css; these exist so each widget reads correctly
   before — or entirely without — the scripts. */

/* AsciiBanner rows are hidden by console.css until the script latches
   `.is-live` to play the typed reveal. Without JavaScript nothing ever
   latches, so the wordmark would stay invisible: keep it visible until the
   reveal starts. (With `is-live` this rule no longer matches, and the
   animation's own fill takes over.) */
.ck-ascii-banner:not(.is-live) .ck-ascii-banner__row { opacity: 1; }

/* The globe stage is a fixed 68-column grid — the script's COLS. The ocean pre
   is the in-flow box; the land pre is absolutely overlaid on it, so both must
   be the full grid width. The generated rows are right-trimmed (a blank row
   would otherwise collapse the stage and pull the land layer off-centre). */
.ck-globe__ocean,
.ck-globe__land { width: 68ch; }

/* AnsiPortrait's static fallback: the author photo fills the portrait slot
   until the script swaps in the canvas — and is the slot's only content when
   the script never runs. The slot itself carries `.author-bio__photo`, so it is
   already the sized flex item (or `.ck-portrait` on the About page). */
/* ============================================================================
   TERMINAL DEVICE — the /terminal appliance, in the generator's own tree.

   Part 1 is the React chrome stylesheets copied verbatim (url() paths rebased to
   ../assets/), from the since-deleted src/terminal/{ui/terminal.css,
   device/device.css, device/lcd/lcd.css, device/macro/macro.css}. This copy is
   the only one: the React tree it came from is gone.

   Part 2 (from "STATIC-SITE LAYOUT" down) is new: the SPA authored every rect in
   JS (layout.js -> inline styles) and switched wide/compact/mobile in a React
   hook. Here the rects live in CSS custom properties and the mode switch is a
   media query, so the generator renders one chassis and the script writes a
   single property (--dev-scale).
   ========================================================================== */

/* ── copied from src/terminal/ui/terminal.css ───────────── */
/* Terminal — scoped, fixed palette (independent of the site's data-theme).
   Everything references --term-* tokens so light/dark mode never bleeds in. */
@font-face {
  font-family: 'JGS7';
  src: url("/assets/gen/jgs7.bcfc718a.ttf") format('truetype');
  font-display: swap;
}

.device-terminal {
  --term-bg: #0b0d0b;
  --term-fg: #c8f2c0;
  --term-dim: #5f8f5a;
  --term-accent: #ffb648;
  --term-error: #ff6b6b;
  /* swap the first family for 'Courier New' if you prefer a smooth mono */
  --term-font: 'JGS7', 'Courier New', Courier, monospace;
  --term-fs: clamp(0.82rem, 1.6vw, 1rem);

  position: fixed;
  inset: 0;
  display: flex;
  justify-content: center;
  background: var(--term-bg);
  color: var(--term-fg);
  font-family: var(--term-font);
  overflow: hidden;
  /* No accidental highlighting of chrome (knobs, keys, labels) while dragging.
     Re-enabled below for the scrollback (copyable output) and the real input. */
  -webkit-user-select: none;
  user-select: none;
}

/* Full-bleed stage used on narrow screens (no device bezel). */
.term-stage--bare {
  position: relative;
  display: flex;
  justify-content: center;
  width: 100%;
  height: 100%;
  overflow: hidden;
}

.term-screen {
  width: min(1100px, 100%);
  height: 100%;
  overflow-y: auto;
  padding: clamp(1rem, 3vw, 2.5rem);
  scrollbar-width: thin;
  scrollbar-color: var(--term-dim) rgba(0, 0, 0, 0.4);
}
/* square TUI scrollbar: block thumb on a dark rail */
.term-screen::-webkit-scrollbar { width: 10px; }
.term-screen::-webkit-scrollbar-track { background: rgba(0, 0, 0, 0.4); }
.term-screen::-webkit-scrollbar-thumb {
  background: var(--term-dim);
  border-radius: 0;
  border: 2px solid rgba(0, 0, 0, 0.55);
}
.term-screen::-webkit-scrollbar-thumb:hover { background: var(--term-fg); }

.term-scrollback {
  /* Query container so the ASCII banner can auto-fit its width (100cqi). */
  container-type: inline-size;
  font-size: var(--term-fs);
  line-height: 1.55;
  /* GLOW knob scales the phosphor bloom (baseline alpha ≈ 0.22). */
  text-shadow:
    0 0 4px color-mix(in srgb, currentcolor calc(35% * var(--term-glow, 1)), transparent),
    0 0 13px color-mix(in srgb, currentcolor calc(18% * var(--term-glow, 1)), transparent);
  /* terminal output stays selectable/copyable */
  -webkit-user-select: text;
  user-select: text;
}

.term-line {
  white-space: pre-wrap;
  word-break: break-word;
  margin: 0;
}
.term-line--system { color: var(--term-dim); margin-bottom: 0.35rem; }
.term-line--error { color: var(--term-error); }
.term-line--input { color: var(--term-fg); }

/* ASCII wordmark. Auto-fits the terminal width: font-size shrinks so --art-cols
   columns of monospace fit in the container (100cqi), capped so it stays crisp on
   desktop. Centered as a block; rows keep their exact spacing (white-space: pre). */
.term-art {
  width: fit-content;
  max-width: 100%;
  margin: 0.1em auto 0.7em;
  color: var(--term-accent);
  /* Render at the terminal text size (1em); only shrink below it if the art would
     overflow a narrow (mobile) screen. Never larger than the surrounding text. */
  font-size: min(1em, calc(100cqi / (var(--art-cols, 67) * 0.62)));
  line-height: 1.05;
}
.term-art__row {
  white-space: pre;
  animation: term-art-row-in 0.26s ease-out both;
  animation-delay: calc(var(--i) * 24ms);   /* keep in sync with ART_ROW_MS */
}
@keyframes term-art-row-in {
  from { opacity: 0; transform: translateY(3px); }
  to   { opacity: 1; transform: none; }
}

/* Boot intro cascade: text lines fade up in sequence (delay set inline per line). */
.term-line.is-reveal { animation: term-line-in 0.24s ease-out both; }
@keyframes term-line-in {
  from { opacity: 0; transform: translateY(2px); }
  to   { opacity: 1; transform: none; }
}

@media (prefers-reduced-motion: reduce) {
  .term-art__row,
  .term-line.is-reveal { animation: none; }
}

.term-seg { font: inherit; }
.term-seg.is-dim { color: var(--term-dim); }
.term-seg.is-accent { color: var(--term-accent); }
.term-seg.is-error { color: var(--term-error); }

/* Clickable entry tokens (dirs, files, links, programs). */
.term-token {
  /* inline-block: <a> and <button> tokens get identical highlight boxes */
  display: inline-block;
  font: inherit;
  line-height: inherit;
  color: var(--term-fg);
  background: transparent;
  border: 0;
  margin: 0;
  padding: 0 2px;
  cursor: pointer;
  text-decoration: none;
}
.term-token.is-accent { color: var(--term-accent); }
.term-token:hover,
.term-token:focus-visible {
  color: var(--term-bg);
  background: var(--term-fg);
  outline: none;
  text-decoration: none;   /* the global a:hover underline must not win */
}
.term-token.is-accent:hover,
.term-token.is-accent:focus-visible {
  background: var(--term-accent);
}

/* Trackball-roved selection highlight (driven by the device trackball). */
.term-token.is-tb-sel {
  color: var(--term-bg);
  background: var(--term-accent);
  box-shadow: 0 0 0 2px var(--term-accent);
}

/* Prompt / live input line. */
.term-promptline { position: relative; }
.term-prompt { color: var(--term-dim); }
.term-typed { color: var(--term-fg); }

.term-caret {
  display: inline-block;
  width: 0.6ch;
  margin-left: -0.1ch;
  color: var(--term-fg);
  animation: term-caret-blink 1.05s steps(1) infinite;
}
.term-caret.is-idle { opacity: 0.35; animation: none; }
@keyframes term-caret-blink {
  0%, 50% { opacity: 1; }
  50.01%, 100% { opacity: 0; }
}

/* Mid-line: the caret sits ON a character — render it as an inverted block over
   that char, blinking inverted↔normal so the char stays readable. */
.term-caret.has-char {
  width: auto;
  margin-left: 0;
  animation: term-caret-blink-inverse 1.05s steps(1) infinite;
}
.term-caret.is-idle.has-char {
  background: var(--term-fg);
  color: var(--term-bg);
  animation: none;
}
@keyframes term-caret-blink-inverse {
  0%, 50% { background: var(--term-fg); color: var(--term-bg); }
  50.01%, 100% { background: transparent; color: var(--term-fg); }
}

.term-hint {
  margin-left: 0.8ch;
  color: var(--term-dim);
  font-size: 0.85em;
  opacity: 0.7;
}

/* Real input: focusable + keyboard-raising, but visually invisible. Overlays
   the prompt line so tapping it focuses; we render the caret ourselves. */
.term-input {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
  border: 0;
  background: transparent;
  color: transparent;
  caret-color: transparent;
  font: inherit;
  outline: none;
  resize: none;
  -webkit-user-select: text;
  user-select: text;
}

/* ---- Minimal CRT paint (scoped to the screen surfaces) ---- */
/* Scanlines + vignette sit above the terminal text but never catch clicks.
   Applied to both the device screen recess and the bare mobile stage. */
.device-screen::before,
.term-stage--bare::before {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 4;
  background: repeating-linear-gradient(
    to bottom,
    rgba(0, 0, 0, 0) 0,
    rgba(0, 0, 0, 0) 2px,
    rgba(0, 0, 0, 0.16) 3px
  );
  mix-blend-mode: multiply;
  opacity: calc(0.55 * var(--term-glow, 1));
}
.device-screen::after,
.term-stage--bare::after {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 4;
  background: radial-gradient(ellipse at center, rgba(0, 0, 0, 0) 56%, rgba(0, 0, 0, 0.42) 100%);
}

/* Round the overlay corners too: a transformed ancestor (the scaled device) can
   break the screen's overflow-clip, leaving square corners on these layers. */
.device-screen::before,
.device-screen::after { border-radius: inherit; }

/* One-shot power-on flicker on load (cosmetic; full content is present the
   whole time, so the static HTML and SEO are unaffected). */
@keyframes term-power-on {
  0% { opacity: 0; }
  8% { opacity: 0.55; }
  13% { opacity: 0.28; }
  22% { opacity: 1; }
  100% { opacity: 1; }
}
.device-screen,
.term-stage--bare {
  animation: term-power-on 0.85s ease-out both;
}
@media (prefers-reduced-motion: reduce) {
  .device-screen,
  .term-stage--bare { animation: none; }
}

/* ── copied from src/terminal/device/device.css ───────────── */
/* Device frame. Authored at DEVICE.w × DEVICE.h; one transform: scale() fits it
   to the viewport. Until the real raster exists, .is-placeholder draws a CSS
   cassette-futurism bezel so the screen / AMOLED / buttons are all positionable. */

/* Brand wordmark font. */
@font-face {
  font-family: 'Aulendur Brand';
  src: url("/assets/gen/aulegothic.5f7a5877.otf") format('opentype');
  font-display: swap;
}

/* In-universe runic font for keycap legends. */
@font-face {
  font-family: 'Starforge Runic';
  src: url("/assets/gen/StarforgeRunic-Regular.b3bd480c.ttf") format('truetype');
  font-display: swap;
}

/* 7-segment LCD font for the info-panel clock + flex readout. */
@font-face {
  font-family: 'DS-Digital';
  src: url("/assets/gen/DS-DIGIB.db992dcd.TTF") format('truetype');
  font-display: swap;
}

.device-fit {
  position: relative;
  isolation: isolate;   /* keep the texture blends contained + behind the components */
  width: 100%;
  height: 100%;
  display: grid;
  place-items: center;
  /* The whole viewport IS the plastic chassis now — no device edge, no letterbox.
     Base tone + worn texture + edge grime; the components float on top. (Bare
     terminal mode uses its own dark stage, so that switch is unaffected.) */
  --chassis-grain: 0.75;             /* ◀ plastic surface texture strength */
  --chassis-blend: soft-light;       /* ◀ blend: soft-light | overlay | hard-light | multiply */
  --chassis-grime: 0.4;              /* ◀ edge grime / aging */
  background: linear-gradient(158deg, #f6e2a9 10%, #d6cfbb 55%, #e3d7b1 100%);
}
.device-fit::before,
.device-fit::after {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
}
.device-fit::before {   /* worn plastic surface */
  background: url("/assets/gen/plastictexture.4f59e70d.jpg") center / cover no-repeat;
  mix-blend-mode: var(--chassis-blend);
  opacity: var(--chassis-grain);
}
.device-fit::after {    /* broad aging + grime toward the viewport edges */
  background:
    radial-gradient(120% 120% at 50% 45%, transparent 55%, rgba(40, 32, 20, 0.32) 100%),
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='500' height='500'%3E%3Cfilter id='m'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.011' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='500' height='500' filter='url(%23m)'/%3E%3C/svg%3E");
  background-size: cover, 500px 500px;
  mix-blend-mode: multiply;
  opacity: var(--chassis-grime);
}

.device-inner {
  /* Anchored to the fit box's center and pulled back by half its own size (the
     translate in DeviceFrame's inline transform, before the scale). As a grid
     item, its unscaled design-space box would size the auto track and overflow
     right/down whenever the viewport is smaller than the design space —
     shifting the whole device off-center (compact at 800×600, for one). */
  position: absolute;
  left: 50%;
  top: 50%;
  z-index: 1;            /* components float ABOVE the full-viewport plastic texture */
  transform-origin: center;
  background-size: cover;
  background-position: center;
  /* "Plastic curves into the cutout" bevel, added around each recessed panel
     (screen / HUD / keyboard / trackball): crisp edge · lit top lip · soft
     concave shadow ringing it. One dial for the whole device. */
  --recess-shadow:
    0 0 0 1px rgba(0, 0, 0, 0.2),
    0 -1px 0 rgba(255, 255, 255, 0.35),
    0 0 11px 3px rgba(0, 0, 0, 0.60);
}

/* The plastic chassis now fills the whole viewport (see .device-fit); this inner
   body layer + its floating rounded bezel are no longer used. */
.device-body { display: none; }

/* Screen recess (the terminal lives here). Its outer recess ring is drawn by the
   .screen-ring sibling (drop-shadows of the notched silhouette), not box-shadow —
   box-shadow can only trace the rectangle, and the screen is notched for the
   power button. */
.device-screen {
  --term-fs: 17px;
  border-radius: 12px;
  overflow: hidden;
  background: var(--term-bg, #0b0d0b);
  box-shadow: inset 0 0 0 3px rgba(0, 0, 0, 0.55), inset 0 0 70px rgba(0, 0, 0, 0.75);
}
.device-inner.has-art .device-screen { background: transparent; box-shadow: none; }
.device-inner.has-art .screen-ring { display: none; }
.device-screen .term-screen { height: 100%; padding: 16px 20px; }

/* ----------------------------------------------------------------------------
   Power button — the screen's top-right corner is CUT OUT of the terminal with a
   CSS mask, so the REAL chassis (same gradient, texture, and grime, perfectly
   continuous with the plastic around it) shows through the notch. Nothing is
   repainted, so there is no seam: the notch IS the larger plastic. The recess
   shadow border is re-drawn by .screen-ring as drop-shadows of the same notched
   silhouette, so it runs along the screen edge, down around the notch, and back
   out — through the little border. The button face is a bevel-only pad molded
   from that visible chassis. "Bail out" link to /home.

   Geometry lives in shared custom props so the mask cut (.pw-mask on the screen
   + ring fill) and the <a> hit area (.power-frame overlays the same box) always
   agree. --pw-w must be %-free: a % inside the var would resolve against height
   when used in --pw-h / mask heights (that inverted the notch's aspect ratio).
   DeviceFrame sets it inline from the screen rect (wide/compact/calibration);
   mobile overrides with vw below (its screen is viewport-wide, unscaled). */
.pw-mask,
.power-frame {
  --pw-w: 69px;                            /* notch width (fallback; see above) */
  --pw-h: calc(var(--pw-w) / 1.14);        /* notch height */
}
/* Notched mask, square-cornered: [everything left of the cut] + [everything
   below it]. */
.pw-mask {
  -webkit-mask-image:
    linear-gradient(#000 0 0),
    linear-gradient(#000 0 0);
  -webkit-mask-size:
    calc(100% - var(--pw-w)) 100%,
    100% calc(100% - var(--pw-h));
  -webkit-mask-position:
    left top,
    left bottom;
  -webkit-mask-repeat: no-repeat;
  mask-image:
    linear-gradient(#000 0 0),
    linear-gradient(#000 0 0);
  mask-size:
    calc(100% - var(--pw-w)) 100%,
    100% calc(100% - var(--pw-h));
  mask-position:
    left top,
    left bottom;
  mask-repeat: no-repeat;
}
/* The recess ring, traced around the NOTCHED outline: drop-shadow() follows the
   silhouette of the masked fill (box-shadow could only trace the rectangle). The
   filter must sit on the parent — on the masked element itself, the mask would
   clip the shadows away. Order: crisp edge, lit lip, AO halo (≈ --recess-shadow). */
.screen-ring {
  position: absolute;
  pointer-events: none;
  filter:
    drop-shadow(0 0 1px rgba(0, 0, 0, 0.30))
    drop-shadow(0 -1px 0 rgba(255, 255, 255, 0.35))
    drop-shadow(0 0 5px rgba(0, 0, 0, 0.50))
    drop-shadow(0 0 5px rgba(0, 0, 0, 0.42));
}
.screen-ring__fill {
  position: absolute;
  inset: 0;
  border-radius: 12px;
  background: #0b0d0b;   /* sits exactly under the screen; only its shadows show */
}
/* Invisible overlay matching the screen rect; carries the notch link. */
.power-frame {
  position: absolute;
  pointer-events: none;
}
.power-notch {
  position: absolute;
  top: 0; right: 0;
  width: var(--pw-w);
  height: var(--pw-h);
  box-sizing: border-box;
  padding: 0 0 5px 5px;                   /* the chassis border strip between face and terminal */
  display: grid;
  pointer-events: auto;
  cursor: pointer;
  /* shadow the chassis tab casts down-left onto the recessed screen; negative
     spread keeps it off the seamless top/right chassis sides */
  box-shadow: -3px 3px 6px -4px rgba(0, 0, 0, 0.6);
}
/* The button face — a pad molded from the visible chassis itself: no fill, only
   the bevel + seam. Only the top-right corner is curved (echoing the screen
   corner it replaces); the others are square, like the cut. Hover/press feedback
   via background tint, NOT filter (a hover filter here flickers — see the macro
   pad fix in macro.css). */
.power-btn {
  position: relative;
  display: grid;
  place-items: center;
  border-radius: 0 10px 0 0;
  /* faint convex sheen — lighter crown, darker toward the bottom edge */
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.09), rgba(255, 255, 255, 0) 40%, rgba(0, 0, 0, 0.05));
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.6),     /* strong lit top edge — raised catch light */
    inset 1px 0 0 rgba(255, 255, 255, 0.25),    /* lit left lip */
    inset 0 -1px 0 rgba(0, 0, 0, 0.12),         /* dark under-edge as the face turns away */
    0 0 0 1px rgba(0, 0, 0, 0.08),              /* whisper of a molded seam */
    -1px 2px 2px rgba(0, 0, 0, 0.22),           /* crisp contact shadow, down-left */
    -2px 4px 7px -2px rgba(0, 0, 0, 0.28);      /* soft lifted shadow falling toward the screen (biased off the seamless top/right chassis) */
  transition: background-color 0.12s ease, transform 0.05s ease, box-shadow 0.08s ease;
}
.power-notch:hover .power-btn { background: rgba(255, 255, 255, 0.10); }
.power-notch:active .power-btn {
  transform: translateY(1px);
  background: rgba(0, 0, 0, 0.05);
  box-shadow:                                    /* pressed: the lift collapses */
    inset 0 1px 0 rgba(255, 255, 255, 0.4),
    inset 1px 0 0 rgba(255, 255, 255, 0.18),
    inset 0 -1px 0 rgba(0, 0, 0, 0.1),
    0 0 0 1px rgba(0, 0, 0, 0.08),
    -1px 1px 1px rgba(0, 0, 0, 0.18);
}
.power-btn__glyph {
  height: 52%;
  aspect-ratio: 502.59 / 632.07;
  background: #3a3320;                                  /* dark engraved glyph */
  filter: drop-shadow(0 1px 0.5px rgba(255, 255, 255, 0.35));   /* incised highlight */
  -webkit-mask: url("/assets/gen/power.c7ab6bb7.svg") center / contain no-repeat;
  mask: url("/assets/gen/power.c7ab6bb7.svg") center / contain no-repeat;
}
@media (prefers-reduced-motion: reduce) {
  .power-btn { transition: none; }
}

/* LCD bank — a transparent region of the plastic front. Each LCD panel + the
   engraved model plate sit directly on the chassis (panels carry their own
   recessed bezel; see device/lcd/lcd.css). No dark housing, no glow here. */
.device-lcdbank { overflow: visible; }

/* Shared "molded plastic" frame — a thin, mostly-flush bevel that groups a cluster
   of controls. Used by the macro pad and the knob cluster. */
.dv-plastic-frame {
  border-radius: 10px;
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.05), rgba(0, 0, 0, 0.05));
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.35),   /* top lip highlight (molded plastic) */
    inset 0 -1px 0 rgba(0, 0, 0, 0.18),         /* bottom shade */
    0 0 0 1px rgba(0, 0, 0, 0.10);              /* faint edge */
}

/* Decorative frame behind the knob cluster (knobs render on top). */
.device-knobs-panel { pointer-events: none; }

/* ============================================================================
   Wireframe controls — knobs / on-screen keyboard / trackball / LED / logo.
   All positioned absolutely from layout.js; these rules are pure presentation.
   Hidden once real device art is set (.has-art) so they don't double up.
   ========================================================================== */
.device-inner.has-art .dv-knob-wrap,
.device-inner.has-art .dv-kbd-wrap,
.device-inner.has-art .dv-trackball-wrap,
.device-inner.has-art .dv-logo,
.device-inner.has-art .dv-led-wrap { background: transparent; box-shadow: none; }

/* Brand mark = logo icon + wordmark. The wordmark uses --brand-font (declared
   via @font-face below). Drop your own font in assets/fonts/ and repoint the
   @font-face src; drop your own logo in assets/ and pass it to `device.chassis`
   in templates/pages/terminal.html. */
.dv-logo {
  --brand-font: 'Aulendur Brand', 'IBM Plex Sans', Helvetica, Arial, sans-serif;
  --mark-h: 44px;     /* ◀ TWEAK ME: height of the logo mark */
  --mark-ratio: 1001 / 430;  /* width/height of your logo file (update if you swap it) */
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: 12px;
  line-height: 1;
  color: #4a4536;
  pointer-events: none; /* purely decorative; never eats a drag */
}
/* Mask the logo image and fill it with the brand color so it tints to match the
   wordmark (currentColor = .dv-logo color). `contain` preserves the mark's shape. */
.dv-logo__mark {
  height: var(--mark-h);
  aspect-ratio: var(--mark-ratio);
  background-color: currentColor;
  -webkit-mask: var(--brand-mark) no-repeat center / contain;
  mask: var(--brand-mark) no-repeat center / contain;
}
.dv-logo__word { display: flex; flex-direction: column; font-family: var(--brand-font); }
.dv-logo__word strong { font-size: 24px; font-weight: 800; letter-spacing: 0.14em; }
.dv-logo__word span { font-size: 12px; letter-spacing: 0.44em; color: #7a7460; margin-top: 4px; }

/* Power/activity LED. */
.dv-led-wrap { display: grid; place-items: center; }
.dv-led {
  width: 18px; height: 18px; border-radius: 50%;
  background: radial-gradient(circle at 38% 32%, #b6ffce, #46e07a 55%, #1faf57 100%);
  box-shadow: 0 0 10px 2px rgba(70, 224, 122, 0.8), inset 0 1px 2px rgba(255, 255, 255, 0.6);
  animation: dv-led-pulse 3.2s ease-in-out infinite;
}
@keyframes dv-led-pulse { 0%, 100% { opacity: 0.82; } 50% { opacity: 1; } }
@media (prefers-reduced-motion: reduce) { .dv-led { animation: none; } }
/* Knobs. Rendered from a pre-baked filmstrip: the strip slides inside a
   one-frame window so the right frame shows for the current value. */
.dv-knob {
  width: 100%; height: 100%;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 5px;
  cursor: ns-resize; user-select: none; touch-action: none;
}
.dv-knob__film {
  --knob-size: 65px;        /* ◀ display size of the knob */
  width: var(--knob-size); height: var(--knob-size);
  flex-shrink: 0;           /* never let the label squeeze (crop) the knob */
  overflow: hidden;
}
.dv-knob__frames {
  width: 100%; display: block;
  pointer-events: none; -webkit-user-drag: none;
  /* transform: translateY(...) is set per-frame from JS */
}
.dv-knob__label {
  font-family: 'Courier New', Courier, monospace;
  font-size: 11px; font-weight: 700; letter-spacing: 0.1em; color: #5a5340;
  background: transparent;
}

/* On-screen keyboard recess. */
.dv-kbd-wrap {
  border-radius: 14px; padding: 12px;
  background: linear-gradient(180deg, #2c2824 0%, #1b1916 100%);
  box-shadow:
    inset 0 2px 4px rgba(10, 10, 10, 0.909),
    inset 0 0 28px rgba(0, 0, 0, 0.912),
    0 2px 0 rgba(19, 19, 19, 0.948),
    var(--recess-shadow);
}
.dv-kbd {
  /* Three zones: vertical spacebar | alpha block | special/nav clusters. */
  width: 100%; height: 100%; display: flex; flex-direction: row; align-items: stretch;
  gap: 6px; justify-content: flex-start;
  --key: 44px;            /* ◀ uniform size for EVERY key (spacebar excepted) */
  --key-shadow: 0 4px 4px rgba(0, 0, 0, 0.55);   /* ◀ key drop-shadow (depth) */
  --main-gap: 5px;        /* vertical gap between the alpha rows */
  /* Placeholder keycap art shared by every key (swap this one URL, or move to a
     per-letter map later). The real letter is printed on top as the legend. */
  --keycap: url("/assets/gen/key_a.f1b38f01.svg");
  /* Primary runic legend (in-universe). x/y are % of the cap face; size is % of
     cap height (cqh). The rune renders the same key char via the runic font. */
  --rune-x: 35%;
  --rune-y: 35%;
  --rune-size: 54cqh;
  --rune-color: #8b0a1e;
  --rune-font: 'Starforge Runic', serif;
  --rune-x-solo: 55%;  /* rune-only keys: center the lone rune on the cap face */
  --rune-y-solo: 50%;
  /* Latin reference legend — small, secondary, sits under the rune. */
  --legend-x: 70%;
  --legend-y: 65%;
  --legend-size: 18cqh;
  --legend-color: #3a0a0a;
  --legend-blend: color-burn;
  --legend-font: 'Iosevka Term Slab', 'Courier New', Courier, monospace;
}
/* Left rail: tall vertical spacebar (its own art). */
.dv-kbd__space {
  flex: 0 0 auto; align-self: center;
  /* match the alpha row-stack height (4 rows + 3 gaps), not the full recess, so
     the spacebar lines up top-and-bottom with the alpha keys */
  height: calc(4 * var(--key) + 3 * var(--main-gap));
  aspect-ratio: 212.12 / 946.52;   /* matches key_space.svg viewBox (hugs the art) */
  border: 0; padding: 0; cursor: pointer;
  background: url("/assets/gen/key_space.2207d442.svg") center / contain no-repeat;
  filter: drop-shadow(var(--key-shadow));
  transition: transform 0.05s ease, filter 0.05s ease;
}
.dv-kbd__space:hover { filter: brightness(1.06) drop-shadow(var(--key-shadow)); }
.dv-kbd__space:active,
.dv-kbd__space.is-pressed { transform: translateY(2px); filter: brightness(0.92) drop-shadow(0 1px 2px rgba(0, 0, 0, 0.5)); }

/* Center: the alpha/number grid, vertically centered, rows left-aligned so the
   columns line up (ortholinear). */
.dv-kbd__main {
  flex: 0 0 auto; min-width: 0;
  display: flex; flex-direction: column; gap: var(--main-gap); justify-content: center; align-items: flex-start;
}

/* Right: the two clusters side by side, so the keyboard stays one row-grid tall
   and every key can share the single --key size. */
.dv-kbd__right {
  flex: 0 0 auto;
  display: flex; flex-direction: row; gap: 14px; align-items: center;
  margin-left: none; 
  margin-right: auto;  /* push the clusters to the right edge; spacebar+alphas pack left */
}
.dv-kbd__cluster { display: grid; gap: 4px; }
.dv-kbd__cluster--special { grid-template-columns: repeat(4, var(--key)); grid-auto-rows: var(--key); }
.dv-kbd__cluster--nav { grid-template-columns: repeat(3, var(--key)); grid-auto-rows: var(--key); margin-top: 50px; margin-left: -10px; }
.dv-kbd__gap { pointer-events: none; } /* empty cell carving the +/T silhouette */

.dv-kbd__row { display: flex; gap: 4px; justify-content: flex-start; }
.dv-key {
  /* every key is the same fixed square (--key); the spacebar is the only exception */
  flex: 0 0 auto;
  width: var(--key); height: var(--key);
  border: 0; padding: 0; cursor: pointer; background: none;
  display: grid; place-items: center;
  transition: transform 0.05s ease, filter 0.05s ease;
}
.dv-key:hover { filter: brightness(1.06); }
.dv-key:active,
.dv-key.is-pressed { transform: translateY(2px); filter: brightness(0.92); }

/* Keycap face fills its (square) key; container-type scales the legend (cqh). */
.dv-key__cap {
  position: relative;
  width: 100%; height: 100%;
  background: var(--keycap) center / contain no-repeat;
  filter: drop-shadow(var(--key-shadow));   /* depth: keys sit up out of the recessed box */
  container-type: size;
}
.dv-key:active .dv-key__cap,
.dv-key.is-pressed .dv-key__cap { filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.5)); }
/* Rune-only keys (no Latin reference): center the lone rune. */
.dv-key__cap.is-solo { --rune-x: var(--rune-x-solo); --rune-y: var(--rune-y-solo); }
.dv-key__rune {
  position: absolute;
  left: var(--rune-x); top: var(--rune-y);
  transform: translate(-50%, -50%);
  font-family: var(--rune-font);
  font-size: var(--rune-size); line-height: 1;
  color: var(--rune-color);
  pointer-events: none;
}
.dv-key__legend {
  position: absolute;
  left: var(--legend-x); top: var(--legend-y);
  transform: translate(-50%, -50%);
  font-family: var(--legend-font);
  font-style: italic; font-weight: 700;
  font-size: var(--legend-size); line-height: 1;
  text-transform: uppercase;
  color: var(--legend-color);
  mix-blend-mode: var(--legend-blend);
  pointer-events: none;
}

/* (Spacebar is now the vertical .dv-kbd__space on the left rail, above.) */

/* Trackball — deep recessed module: a dark well with a circular socket the glassy
   sphere nests into, so it reads as inset into the chassis. */
.dv-trackball-wrap {
  border-radius: 16px; display: grid; place-items: center;
  background: radial-gradient(circle at 50% 42%, #191919, #060606 74%);
  box-shadow:
    inset 0 5px 10px rgba(0, 0, 0, 0.85),         /* recessed top lip */
    inset 0 -2px 4px rgba(255, 255, 255, 0.06),   /* bottom rim catch */
    inset 0 0 54px rgba(0, 0, 0, 0.95),           /* deep well */
    0 1px 0 rgba(255, 255, 255, 0.05),            /* outer top edge */
    var(--recess-shadow);
}
.dv-trackball { position: relative; display: grid; place-items: center; }
/* Circular socket the ball sits down into. */
.dv-trackball::before {
  content: '';
  position: absolute; inset: 0; margin: auto;
  width: 174px; height: 174px; border-radius: 50%;
  background: radial-gradient(circle at 50% 42%, #101010, #030303 72%);
  box-shadow:
    inset 0 9px 18px rgba(0, 0, 0, 0.95),
    inset 0 -4px 8px rgba(255, 255, 255, 0.05);
}
.dv-trackball__ball {
  position: relative;                              /* sits above the socket */
  width: 150px; height: 150px; border-radius: 50%;
  cursor: grab; touch-action: none;
  background: radial-gradient(circle at 38% 30%, #fdfdfd, #d6d6d6 38%, #999 70%, #686868 100%);
  box-shadow:
    inset 0 4px 10px rgba(255, 255, 255, 0.6),
    inset 0 -10px 22px rgba(0, 0, 0, 0.4),
    0 8px 18px rgba(0, 0, 0, 0.7);                 /* casts down into the socket */
}
.dv-trackball__ball:active { cursor: grabbing; }

/* ==========================================================================
   Phone-in-landscape rotate nudge (usePhoneLandscape). Full-viewport plastic
   (reuses .device-fit) with a phosphor card that echoes the terminal screen.
   ========================================================================== */
.rotate-notice__card {
  position: relative;
  z-index: 1;                          /* above the .device-fit plastic texture */
  display: flex; flex-direction: column; align-items: center;
  gap: 18px;
  padding: clamp(22px, 6vw, 40px) clamp(28px, 9vw, 56px);
  border-radius: 16px;
  background: var(--term-bg, #0b0d0b);
  color: var(--term-accent, #ffb648);
  font-family: var(--term-font, 'JGS7', 'Courier New', monospace);
  text-align: center;
  box-shadow:
    inset 0 0 0 3px rgba(0, 0, 0, 0.55),
    inset 0 0 60px rgba(0, 0, 0, 0.7),
    0 0 0 1px rgba(0, 0, 0, 0.25),
    0 10px 28px rgba(0, 0, 0, 0.5);
}
.rotate-notice__mark {
  --mark-h: 26px; --mark-ratio: 1001 / 430;
  color: var(--term-dim, #5f8f5a);
  opacity: 0.85;
}
.rotate-notice__phone {
  display: block; line-height: 0;
  color: var(--term-accent, #ffb648);
  transform-origin: center;
  animation: rotate-notice-turn 3s ease-in-out infinite;
}
@keyframes rotate-notice-turn {
  0%, 22% { transform: rotate(-90deg); }
  52%, 100% { transform: rotate(0deg); }
}
.rotate-notice__text {
  margin: 0;
  display: flex; flex-direction: column; gap: 5px;
  font-size: clamp(14px, 4vw, 18px);
  letter-spacing: 0.06em;
  color: var(--term-fg, #c8f2c0);
}
.rotate-notice__text span {
  font-size: 0.72em;
  color: var(--term-dim, #5f8f5a);
}
@media (prefers-reduced-motion: reduce) {
  .rotate-notice__phone { animation: none; }
}

/* ── copied from src/terminal/device/lcd/lcd.css ───────────── */
/* Classic grey-green REFLECTIVE (non-backlit) LCD bank. Discrete panels recessed
   into the device's cream plastic; segments read dark-on-murky, and the unlit
   "ghost" segments stay faintly visible behind the lit ones. No glow — reflective
   LCDs don't emit light. The one exception is the deeploom lamp, an actual LED. */

.lcd-bank {
  /* ── Reflective grey-green palette ─────────────────────────────────────── */
  --lcd-glass: #8a927e;                 /* murky olive-grey "off" glass          */
  --lcd-glass-2: #767d68;               /* darker toward the bottom of the glass */
  --lcd-seg: #171b11;                   /* near-black lit segment                */
  --lcd-ghost: rgba(23, 27, 17, 0.11);  /* faint always-on unlit segment         */
  --lcd-engrave: #5b5137;               /* engraved-plastic text (model/serial)  */
  --lcd-deeploom: #171b11;              /* the one emissive lamp                 */

  position: relative;
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 7px;
  padding: 2px;
  box-sizing: border-box;
  overflow: hidden;   /* the panels flex to fill this rect — never hang below it */
}

/* One recessed LCD cell. Panels flex to share the bank height, so the column
   always fits and its bottom lines up with the terminal's. */
.lcd-panel {
  position: relative;
  flex: 1 1 0;
  min-height: 0;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 5px;
  padding: 6px 10px;
  color: var(--lcd-seg);
  background: linear-gradient(180deg, var(--lcd-glass) 0%, var(--lcd-glass-2) 100%);
  box-shadow:
    inset 0 2px 4px rgba(0, 0, 0, 0.40),      /* under-glass depth               */
    inset 0 0 0 1px rgba(0, 0, 0, 0.30),      /* glass edge                      */
    0 1px 0 rgba(255, 255, 255, 0.45);        /* bezel lip highlight below       */
}

/* ── Seven-segment ghost + lit stack (88:88 behind, live value on top). ────── */
.lcd-7seg {
  display: inline-flex;
  font-family: 'DS-Digital', 'Courier New', monospace;
  line-height: 1;
}
/* Fixed-width digit cell (1ch = the font's digit advance) so cells never drift —
   DS-Digital's "1"/":" are narrower than "8". Ghost + lit stack in each cell. */
.lcd-7seg__cell {
  position: relative;
  display: flex; align-items: center; justify-content: center;
  width: 1ch;
}
.lcd-7seg__cell--colon { width: auto; }   /* the colon rides tight between the pairs */
/* Ghost is the in-flow base; lit is an absolute overlay (WebKit mis-paints
   overlapping grid items, so avoid grid-stacking). */
.lcd-7seg__ghost { color: var(--lcd-ghost); }
.lcd-7seg__lit {
  position: absolute; inset: 0;
  display: flex; align-items: center; justify-content: center;
  color: var(--lcd-seg);
}

/* Clock — the hero panel (a bit taller than the rest). */
.lcd-panel--clock { flex: 1.3 1 0; }
.lcd-panel--clock .lcd-7seg { font-size: 40px; }
.lcd-blink { animation: lcd-colon 1s step-end infinite; }
@keyframes lcd-colon {
  0%, 49.9% { opacity: 1; }
  50%, 100% { opacity: 0.05; }   /* colon drops to the ghost level, never fully off */
}

/* Flex readout — TYPE line + NAME line. */
.lcd-panel--flex {
  flex: 1.15 1 0;
  flex-direction: column;
  align-items: stretch;
  justify-content: center;
  gap: 5px;
}
.lcd-flex__line {
  display: flex;
  gap: 1px;
  font-family: 'DS-Digital', 'Courier New', monospace;
  line-height: 1;
}
.lcd-flex__line--type { font-size: 26px; }
.lcd-flex__line--name { font-size: 22px; }
/* Fixed-width character cell (1ch = the font's digit advance) so cells never drift
   even though DS-Digital's letters aren't all the same width. */
.lcd-flex__cell {
  position: relative;
  display: flex; align-items: center; justify-content: center;
  width: 1ch;
}
/* Ghost is the in-flow base; lit is an absolute overlay (WebKit mis-paints
   overlapping grid items, so avoid grid-stacking). */
.lcd-flex__ghost { color: var(--lcd-ghost); }
.lcd-flex__lit {
  position: absolute; inset: 0;
  display: flex; align-items: center; justify-content: center;
  color: var(--lcd-seg);
}
.lcd-panel--flex.is-idle .lcd-flex__lit { color: var(--lcd-ghost); }   /* idle: dim ---- */

/* Battery — the user's glyphs, masked so they tint to the LCD tones AND update
   whenever the SVGs change (the generator hashes the urls). battery_full.svg
   (all cells) is the ever-present ghost; battery.svg (current charge) is lit on
   top. The two share a viewBox, so the contain-fit masks align cell-for-cell. */
.lcd-panel--battery { flex: 0.95 1 0; }
.lcd-battery {
  position: relative;
  display: block;
  height: 40px;
  aspect-ratio: 213.15 / 97.56;
}
.lcd-battery__ghost,
.lcd-battery__lit {
  position: absolute;
  inset: 0;
  background: currentColor;
}
.lcd-battery__ghost {
  color: var(--lcd-ghost);
  -webkit-mask: url("/assets/gen/battery_full.50651224.svg") center / contain no-repeat;
  mask: url("/assets/gen/battery_full.50651224.svg") center / contain no-repeat;
}
.lcd-battery__lit {
  color: var(--lcd-seg);
  -webkit-mask: url("/assets/gen/battery.711c5561.svg") center / contain no-repeat;
  mask: url("/assets/gen/battery.711c5561.svg") center / contain no-repeat;
}

/* Status panel: drive-access flasher (darkens on VFS access) + the deeploom link,
   sharing one LCD. */
.lcd-panel--drive { flex: 0.8 1 0; gap: 16px; }
.lcd-panel--drive .lcd-drive__glyph {
  display: block;
  height: 22px;
  width: auto;
  color: var(--lcd-ghost);
  transition: color 90ms ease-out;
}
.lcd-panel--drive.is-busy .lcd-drive__glyph { color: var(--lcd-seg); }

/* Deeploom connectivity link: ghost underneath, lit on top blinking at the colon
   rate (.lcd-blink). Both are the masked deeploom.svg tinted via color. */
.lcd-deeploom {
  position: relative;
  display: block;
  height: 24px;
  aspect-ratio: 648.79 / 539.41;
}
.lcd-deeploom__ghost,
.lcd-deeploom__lit {
  position: absolute; inset: 0;
  background: currentColor;
  -webkit-mask: url("/assets/gen/deeploom.5b8609c6.svg") center / contain no-repeat;
  mask: url("/assets/gen/deeploom.5b8609c6.svg") center / contain no-repeat;
}
.lcd-deeploom__ghost { color: var(--lcd-ghost); }
.lcd-deeploom__lit { color: var(--lcd-deeploom); }

/* Engraved model/serial + power lamp header — on the plastic, NOT an LCD. The LED
   sits to the right of the ids; text is incised (dark with a light lower bevel). */
.lcd-plate {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 2px 8px 4px 4px;
  color: var(--lcd-engrave);
  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.4);   /* incised bevel */
  line-height: 1.3;
}
.lcd-plate__ids { display: flex; flex-direction: column; min-width: 0; }
.lcd-plate__value {
  font-size: 10px; letter-spacing: 0.03em; font-weight: 700;
  font-family: 'Courier New', monospace; white-space: nowrap;
}
.lcd-plate__value--serial { margin-top: 3px; }
.lcd-plate__led { flex: 0 0 auto; }

@media (prefers-reduced-motion: reduce) {
  .lcd-blink { animation: none; opacity: 1; }
  .lcd-panel--drive .lcd-drive__glyph { transition: none; }
}

/* ── copied from src/terminal/device/macro/macro.css ───────────── */
/* Contextual macro pad — 4 blank keycaps on a thin plastic frame, each with a mini
   reflective-LCD label (same grey-green ghost/lit language as the LCD bank). */
.macro-pad {
  width: 100%; height: 100%;
  display: flex; align-items: center; justify-content: center;

  /* Keycap vars (reuses the keyboard's .dv-key / .dv-key__cap look). */
  --key: 42px;
  --key-shadow: 0 3px 3px rgba(0, 0, 0, 0.5);
  --keycap: url("/assets/gen/key_a.f1b38f01.svg");

  /* LCD palette (shared visual language with the LCD bank). */
  --lcd-glass: #8a927e;
  --lcd-glass-2: #767d68;
  --lcd-seg: #171b11;
  --lcd-ghost: rgba(23, 27, 17, 0.11);
}

/* Keys are affixed to the shared .dv-plastic-frame (see device.css); this only
   adds the layout. */
.macro-pad__frame {
  display: flex;
  gap: 8px;
  padding: 7px 9px 6px;
}

/* One column: keycap over its LCD label. */
.macro-key {
  display: flex; flex-direction: column; align-items: center; gap: 5px;
}
/* Blank slots: cap looks the same but is fully inert (no hover/press/pointer). */
.macro-key.is-blank .dv-key { pointer-events: none; cursor: default; }

/* The cap's drop-shadow lives on .dv-key__cap and extends past the parent .dv-key
   box; the shared keyboard :hover/:active puts a filter on that parent, which clips
   the shadow and flickers the whole framed group. Neutralize the parent filter and
   brighten the cap directly (its own filter chain keeps the shadow). */
.macro-pad .dv-key:hover,
.macro-pad .dv-key:active,
.macro-pad .dv-key.is-pressed { filter: none; }
.macro-pad .dv-key:hover .dv-key__cap { filter: brightness(1.08) drop-shadow(var(--key-shadow)); }

/* Mini reflective-LCD label under each cap: ghost segments always visible, the
   live function name lit on top (both centered so segments register). */
.macro-key__lcd {
  position: relative;
  width: var(--key);
  height: 17px;
  box-sizing: border-box;
  display: grid; place-items: center;
  border-radius: 3px;
  background: linear-gradient(180deg, var(--lcd-glass), var(--lcd-glass-2));
  box-shadow:
    inset 0 1px 2px rgba(0, 0, 0, 0.35),
    inset 0 0 0 1px rgba(0, 0, 0, 0.28),
    0 1px 0 rgba(255, 255, 255, 0.4);
  font-family: 'DS-Digital', 'Courier New', monospace;
  font-size: 13px;
  line-height: 1;
  letter-spacing: 1px;
}
.macro-key__ghost { color: var(--lcd-ghost); }
.macro-key__lit {
  position: absolute; inset: 0;
  display: grid; place-items: center;
  color: var(--lcd-seg);
}

/* ============================================================================
   STATIC-SITE LAYOUT
   ========================================================================== */

/* The terminal page IS the appliance: /terminal renders without the standard
   site's nav/footer (see templates/pages/terminal.html). This bundle is loaded
   only by /terminal, so hiding them here cannot leak to another page. */
.ck-chassis > header,
.ck-chassis > footer { display: none; }

/* ── Geometry ────────────────────────────────────────────────────────────────
   Every rect from src/terminal/device/layout.js, as design-space px in
   --x/--y/--w/--h. CSS (not inline style) so the mode queries below can retune
   them. The script writes only --dev-scale. */
.dev-rect {
  position: absolute;
  left: calc(var(--x) * 1px);
  top: calc(var(--y) * 1px);
  width: calc(var(--w) * 1px);
  height: calc(var(--h) * 1px);
}
.device-inner {
  width: calc(var(--dev-w, 1280) * 1px);
  height: calc(var(--dev-h, 720) * 1px);
  transform: translate(-50%, -50%) scale(var(--dev-scale, 1));
}

/* Mode-inert chrome: the mobile handle/drawer row and the rotate nudge exist in
   every build so the script never has to create markup; CSS shows them only in
   their mode. The strip/screen wrappers are pure grouping — `display: contents`
   keeps the desktop box tree identical to the SPA's flat one. */
.device-handle,
.dv-kbd__row--ctrl,
.rotate-notice { display: none; }
.dv-led-wrap { display: none; }             /* wide keeps the lamp on the model plate */
.device-strip,
.device-screenwrap { display: contents; }

/* ── wide (base): 1280×720, aspect ≥ 31/20 ────────────────────────────────── */
[data-rect="logo"]         { --x: 40;   --y: 415; --w: 250; --h: 46; }
[data-rect="lcdbank"]      { --x: 1060; --y: 16;  --w: 180; --h: 364; }
[data-rect="screen"],
[data-rect="screen-ring"],
[data-rect="screen-power"] { --x: 40;   --y: 20;  --w: 1000; --h: 359; --pw-w: 69px; }
[data-rect="knob-panel"]   { --x: 352;  --y: 398; --w: 575; --h: 77; }
[data-rect="knob-text"]    { --x: 366;  --y: 388; --w: 74;  --h: 86; }
[data-rect="knob-glow"]    { --x: 485;  --y: 388; --w: 74;  --h: 86; }
[data-rect="knob-tint"]    { --x: 604;  --y: 388; --w: 74;  --h: 86; }
[data-rect="knob-scroll"]  { --x: 723;  --y: 388; --w: 74;  --h: 86; }
[data-rect="knob-sfx"]     { --x: 843;  --y: 388; --w: 74;  --h: 86; }
[data-rect="macros"]       { --x: 936;  --y: 394; --w: 320; --h: 84; }
[data-rect="keyboard"]     { --x: 40;   --y: 494; --w: 890; --h: 215; }
[data-rect="trackball"]    { --x: 950;  --y: 494; --w: 290; --h: 217; }

/* ── compact: 960×720 (4:3). ≥ 641px wide and 6/5 ≤ aspect < 31/20. ──────── */
@media (min-width: 641px) and (min-aspect-ratio: 6/5) and (max-aspect-ratio: 31/20) {
  .device-inner             { --dev-w: 960; --dev-h: 720; }
  [data-rect="logo"]        { --x: 24;  --y: 385; --w: 200; --h: 46; }
  [data-rect="led"]         { --x: 920; --y: 394; --w: 24;  --h: 24; }
  [data-rect="screen"],
  [data-rect="screen-ring"],
  [data-rect="screen-power"]{ --x: 20;  --y: 40;  --w: 920; --h: 320; --pw-w: 64px; }
  [data-rect="knob-panel"]  { --x: 476; --y: 368; --w: 194; --h: 77; }
  [data-rect="knob-text"]   { --x: 488; --y: 360; --w: 74;  --h: 86; }
  [data-rect="knob-scroll"] { --x: 584; --y: 360; --w: 74;  --h: 86; }
  [data-rect="macros"]      { --x: 690; --y: 363; --w: 220; --h: 86; }
  [data-rect="keyboard"]    { --x: 20;  --y: 456; --w: 920; --h: 234; }

  /* Dropped in 4:3: the LCD bank and trackball; only the two essential knobs. */
  .device-lcdbank,
  .dv-trackball-wrap,
  [data-rect="knob-glow"],
  [data-rect="knob-tint"],
  [data-rect="knob-sfx"]    { display: none; }
  .dv-led-wrap              { display: grid; }
}

/* ── mobile: ≤ 640px wide, or narrower than 4:3. The device reflows into a
   column — terminal on top, a logo/knob strip, then the keyboard drawer. Values
   from the SPA's MobileDevice + device.css `.mdev` block. ─────────────────── */
@media (max-width: 640px), (max-aspect-ratio: 6/5) {
  .device-inner {
    position: static;
    transform: none;
    width: 100%;
    height: 100%;
    display: flex;
    flex-direction: column;
    gap: 8px;
    padding: 10px;
    overflow: hidden;
  }
  .device-screenwrap {
    display: block;
    position: relative;
    order: 1;
    flex: 1 1 auto;
    min-height: 0;
  }
  .device-strip {
    display: flex;
    order: 2;
    flex: 0 0 auto;
    min-height: clamp(64px, 17vw, 92px);
    align-items: center;
    justify-content: flex-start;
    gap: clamp(6px, 2vw, 12px);
    padding: 4px 10px;
  }

  /* Dropped on a phone — the handle + LED replace them. Scoped to .device-inner
     (and kept out of the knob-wrap rule's way) so the two-essential-knob trim
     survives the strip's flex rules below. */
  .device-lcdbank,
  .dv-trackball-wrap,
  .device-knobs-panel,
  .device-inner .dv-logo,
  .device-inner [data-rect="knob-glow"],
  .device-inner [data-rect="knob-tint"],
  .device-inner [data-rect="knob-sfx"] { display: none; }

  /* The logo doubles as the drawer handle (tap toggles, drag sizes). */
  .device-handle {
    display: flex;
    flex: 0 0 auto;
    align-items: center;
    gap: 8px;
    border: 0;
    background: none;
    padding: 6px 4px;
    touch-action: none;
    cursor: grab;
    user-select: none;
    --mark-h: clamp(30px, 8vw, 54px);
    --mark-ratio: 1001 / 430;
    color: #3a3320;
  }
  .device-handle:active { cursor: grabbing; }
  .device-grip {
    width: 11px; height: 11px;
    border-top: 3px solid currentColor;
    border-right: 3px solid currentColor;
    border-radius: 2px;
    transform: rotate(-45deg);          /* points up: "pull up" */
    opacity: 0.5;
    transition: transform 0.28s ease;
  }
  .device-terminal.is-open .device-grip { transform: rotate(135deg); }  /* "pull down" */

  .dv-led-wrap { display: grid; margin-left: clamp(4px, 1.5vw, 10px); }
  .device-strip .dv-led { width: clamp(12px, 3.5vw, 18px); height: clamp(12px, 3.5vw, 18px); }

  /* Strip controls are content-sized; the knobs and macros pack right. The
     strip's first div child is .dv-logo, so no knob wrap is a :first-of-type —
     the template marks the leading knob instead. */
  .device-strip .dv-knob-wrap { position: static; left: auto; top: auto; width: auto; height: auto; }
  .device-strip .dv-knob-wrap--lead { margin-left: auto; }
  .device-strip .dv-knob { width: auto; height: auto; gap: 2px; }
  .device-strip .dv-knob__film { --knob-size: clamp(34px, 10vw, 62px); }
  .device-strip .dv-knob__label { font-size: clamp(8px, 2.2vw, 12px); letter-spacing: 0.04em; }
  .device-strip .device-macros { position: static; left: auto; top: auto; width: auto; height: auto; display: flex; align-items: center; flex: 0 0 auto; }
  .device-strip .macro-pad { width: auto; height: auto; --key: clamp(26px, 7vw, 40px); }
  .device-strip .macro-pad__frame { gap: clamp(3px, 0.9vw, 6px); padding: 4px 5px 3px; }
  .device-strip .macro-key__lcd { height: clamp(13px, 3.4vw, 17px); font-size: clamp(9px, 2.6vw, 12px); }

  /* The notched screen fills the wrap; the notch is viewport-relative now. */
  .device-screen,
  .screen-ring,
  .power-frame { inset: 0; width: auto; height: auto; }
  .device-screen {
    border-radius: 16px;
    box-shadow: inset 0 0 0 3px rgba(0, 0, 0, 0.55), inset 0 0 60px rgba(0, 0, 0, 0.7);
  }
  .screen-ring__fill { border-radius: 16px; }
  .device-screen .term-screen { padding: 14px 16px; }
  .device-screen,
  .screen-ring,
  .power-frame { --pw-w: clamp(44px, 7vw, 69px); }

  /* Keyboard drawer: height is the script's one layout write (--drawer-h). It
     drops the design-space rect entirely — the phone drawer is flow-positioned
     at the bottom of the column. */
  .dv-kbd-wrap {
    position: static;
    left: auto;
    top: auto;
    width: auto;
    order: 3;
    flex: 0 0 auto;
    height: var(--drawer-h, 0px);
    padding: 0;
    background: none;
    box-shadow: none;
    border-radius: 16px 16px 0 0;
    overflow: hidden;
    display: flex;
    flex-direction: column;
    justify-content: flex-end;
    transition: height 0.28s cubic-bezier(0.22, 1, 0.36, 1);
  }
  .dv-kbd {
    /* flex 0 0 auto: the closed drawer is 0 tall, and the keyboard must keep its
       natural height inside it (the script measures that for the open state). */
    flex: 0 0 auto;
    width: 100%;
    height: auto;
    display: flex;
    flex-direction: column;
    gap: 5px;
    padding: 10px;
    justify-content: center;
    align-items: stretch;
    background: linear-gradient(180deg, #2c2824 0%, #1b1916 100%);
    border-radius: 16px;
    box-shadow: 0 -8px 22px rgba(0, 0, 0, 0.45), inset 0 2px 4px rgba(255, 255, 255, 0.05);
  }
  .dv-kbd__main { flex: 1 1 auto; width: 100%; display: flex; flex-direction: column; gap: 5px; align-items: stretch; }
  .dv-kbd__row { display: flex; gap: 5px; justify-content: center; }
  .dv-kbd__main > .dv-kbd__row:nth-child(4) { display: none; }   /* number row */
  .dv-kbd__row--ctrl { display: flex; }
  .dv-kbd__space,
  .dv-kbd__right { display: none; }
  .dv-key { flex: 1 1 0; aspect-ratio: 1; width: auto; height: auto; min-width: 0; max-width: 46px; }
  .dv-key--space { flex: 6 1 0; aspect-ratio: auto; max-width: none; }
  .dv-key--space .dv-key__cap {
    background: linear-gradient(180deg, #e9e0cb 0%, #cfc4a8 100%);
    border-radius: 6px;
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.6), inset 0 -3px 5px rgba(0, 0, 0, 0.2);
  }
}

/* ── phone held in landscape: too little height for the console, ask for
   portrait instead (usePhoneLandscape). Last, so it wins over mobile. ─────── */
@media (pointer: coarse) and (orientation: landscape) and (max-height: 540px) {
  .device-inner { display: none; }
  .rotate-notice { display: block; }
}

@media (prefers-reduced-motion: reduce) {
  .device-grip { transition: none; }
  .dv-kbd-wrap { transition: none; }
}