/* ============================================================
   THE GLASS BOX — shared design system for ai-ronaghi.de (karo)
   Blueprint ink · dual-engine cyan + amber · self-monitored
   Ported from the live site (ai-ronaghi.de) as the new source of
   truth for palette, type and components. Served as one shared
   stylesheet for every page in this repo.
   ============================================================ */

:root{
  /* Palette — Color Hunt "1B3C53 / 234C6A / 456882 / D2C1B6" */
  --ink:        #16303F;   /* blueprint void */
  --ink-2:      #1B3C53;   /* base background */
  --panel:      #1E4258;   /* glass panel base */
  --panel-2:    #234C6A;   /* raised glass */
  --line:       rgba(210,193,182,0.10);
  --line-bright:rgba(210,193,182,0.22);

  --cyan:       #D2C1B6;   /* Engine 01 · Retrieval */
  --cyan-dim:   #A69686;
  --amber:      #456882;   /* Engine 02 · Metacognition */
  --amber-dim:  #35505F;
  --alert:      #FF5468;   /* failure / black-box (used sparingly) */

  --paper:      #F5F1EC;
  --paper-2:    #B7C3CC;
  --muted:      #7C8FA0;
  --muted-2:    #4D6478;

  --maxw: 1180px;
  --ease: cubic-bezier(.2,.7,.2,1);
}

*{ box-sizing:border-box; }
html{ scroll-behavior:smooth; }
body{
  margin:0;
  background:
    radial-gradient(1200px 700px at 80% -10%, rgba(210,193,182,0.07), transparent 60%),
    radial-gradient(1100px 800px at 5% 12%, rgba(69,104,130,0.06), transparent 55%),
    linear-gradient(180deg, var(--ink) 0%, var(--ink-2) 22%, var(--ink-2) 100%);
  color:var(--paper);
  font-family:"Inter", system-ui, -apple-system, sans-serif;
  font-size:17px;
  line-height:1.6;
  -webkit-font-smoothing:antialiased;
  overflow-x:hidden;
}
/* faint engineering grid wash */
body::before{
  content:"";
  position:fixed; inset:0; z-index:0; pointer-events:none;
  background-image:
    linear-gradient(var(--line) 1px, transparent 1px),
    linear-gradient(90deg, var(--line) 1px, transparent 1px);
  background-size:54px 54px;
  -webkit-mask-image:radial-gradient(120% 90% at 50% 0%, #000 35%, transparent 78%);
          mask-image:radial-gradient(120% 90% at 50% 0%, #000 35%, transparent 78%);
  opacity:.6;
}
.wrap{ position:relative; z-index:1; max-width:var(--maxw); margin:0 auto; padding:0 28px; }

a{ color:inherit; text-decoration:none; }
::selection{ background:rgba(210,193,182,0.28); color:#fff; }

/* ---------- Type ---------- */
.display{ font-family:"Archivo Expanded","Archivo",sans-serif; font-weight:800; letter-spacing:-0.01em; line-height:1.02; }
.mono{ font-family:"IBM Plex Mono",ui-monospace,monospace; }
.eyebrow{
  font-family:"IBM Plex Mono",monospace; font-size:12px; font-weight:500;
  letter-spacing:.26em; text-transform:uppercase; color:var(--muted);
  display:inline-flex; align-items:center; gap:10px;
}
.eyebrow::before{ content:""; width:26px; height:1px; background:currentColor; opacity:.55; }
.eye-cyan{ color:var(--cyan); } .eye-amber{ color:var(--amber); } .eye-alert{ color:var(--alert); }

h2.sec-title{ font-family:"Archivo Expanded",sans-serif; font-weight:800; font-size:clamp(28px,4.2vw,46px); margin:.5rem 0 0; letter-spacing:-0.015em; line-height:1.05; }
.lede{ color:var(--paper-2); font-size:clamp(16px,1.6vw,19px); max-width:64ch; }

/* ---------- Header / nav ---------- */
header.nav{
  position:sticky; top:0; z-index:50;
  backdrop-filter:blur(10px); -webkit-backdrop-filter:blur(10px);
  background:linear-gradient(180deg, rgba(22,48,63,0.82), rgba(22,48,63,0.45));
  border-bottom:1px solid var(--line);
}
.nav-in{ max-width:var(--maxw); margin:0 auto; padding:13px 28px; display:flex; align-items:center; justify-content:space-between; gap:18px; }
.brand{ display:flex; align-items:center; gap:12px; font-family:"IBM Plex Mono",monospace; font-size:12.5px; letter-spacing:.12em; color:var(--paper-2); }
.brand b{ color:var(--paper); font-weight:600; letter-spacing:.16em; }
.brand .dot{ width:9px; height:9px; border-radius:2px; background:var(--cyan); box-shadow:0 0 12px var(--cyan); transform:rotate(45deg); }
.byline{
  font-family:"IBM Plex Mono",monospace; font-size:12px; letter-spacing:.1em; color:var(--muted);
  display:flex; align-items:center; gap:8px; white-space:nowrap;
}
.byline::before{ content:""; width:18px; height:1px; background:var(--line-bright); }
.byline b{ color:var(--paper-2); font-weight:600; }
@media(max-width:560px){ .byline::before{ display:none; } }
nav.links{ display:flex; gap:6px; flex-wrap:wrap; margin-left:auto; }
nav.links a{
  font-family:"IBM Plex Mono",monospace; font-size:12px; letter-spacing:.08em; color:var(--muted);
  padding:7px 11px; border-radius:7px; transition:color .2s, background .2s;
}
nav.links a:hover, nav.links a:focus-visible{ color:var(--paper); background:rgba(255,255,255,0.05); }
nav.links a.active{ color:var(--cyan); background:rgba(210,193,182,0.08); }
:focus-visible{ outline:2px solid var(--cyan); outline-offset:3px; border-radius:4px; }
@media(max-width:1119px){ nav.links{ display:none; } }

/* My Projects / Meine Projekte flyout — added 2026-08-19 when My Researches
   was removed and this became the nav's one entry with a child (Dienstplan /
   Schedule). .nav-item sits in the flex row like any other nav `a`
   (nav.links a's font/padding rules reach it via descendant selector);
   .nav-sub is absolutely positioned and stays out of flow, so it doesn't
   affect nav width. On touch, :focus-within opens it on first tap — a known
   trade-off of hover-driven dropdowns, accepted rather than adding a full
   toggle script for a single-child menu.

   Both `:hover` rules below are gated on `body.nav-hover-ready` — a class
   `js/app.js` adds on the page's first real mousemove/touchstart. Without
   this gate, Safari (only Safari) evaluates `:hover` against wherever the
   system cursor already sits at paint time, with no real pointer event
   required first — "phantom hover". Reported 2026-08-19: on a fresh load
   of www.ai-ronaghi.de the flyout showed open before any interaction, and
   the Dienstplan link inside it didn't work — closing DE, opening EN, then
   returning to DE (each a real in-page navigation) always left it closed
   and working correctly, which is what pointed at load-time hover rather
   than anything wrong with the link itself. Gating removes the phantom
   state entirely: the menu now starts closed on every load and only ever
   opens from a real gesture. `:focus-within` stays ungated — a deliberate
   Tab keypress is a real, trusted user action, not a static cursor
   position, so keyboard users still get the menu on focus with no gesture
   needed first. See also the `.nav-suppress` rule below, a second, unrelated
   patch for a target=_blank tab-switch edge case. */
.nav-item{ position:relative; display:flex; }
.nav-item > a{ display:inline-flex; align-items:center; gap:4px; }
.nav-caret{ font-size:9px; line-height:1; opacity:.65; transition:transform .15s, opacity .15s; }
body.nav-hover-ready .nav-item:hover .nav-caret, .nav-item:focus-within .nav-caret{ transform:rotate(180deg); opacity:1; }
.nav-sub{
  position:absolute; top:100%; left:0; margin-top:6px; min-width:150px;
  background:rgba(22,48,63,0.97); border:1px solid var(--line-bright); border-radius:8px;
  padding:6px; box-shadow:0 12px 28px rgba(0,0,0,0.35);
  opacity:0; visibility:hidden; transform:translateY(-4px);
  transition:opacity .15s, transform .15s, visibility .15s; z-index:20;
}
body.nav-hover-ready .nav-item:hover .nav-sub, .nav-item:focus-within .nav-sub{ opacity:1; visibility:visible; transform:translateY(0); }
.nav-item.nav-suppress .nav-sub{ opacity:0!important; visibility:hidden!important; }
.nav-sub a{ display:block; padding:7px 10px; border-radius:6px; font-size:12px; white-space:nowrap; }
.nav-sub a:hover, .nav-sub a:focus-visible{ color:var(--paper); background:rgba(255,255,255,0.06); }
/* Six items since 2026-08-18 (My Projects). The German labels — Startseite /
   Über mich / Expertise / Lehre / Meine Projekte / Meine Forschungen — no
   longer fit beside the brand at the original 12px/.08em/11px-padding, and a
   wider viewport does not help because .nav-in is capped at --maxw: the brand
   and the last item both wrapped to a second line at *every* desktop width.
   Tightened here, above the stacking breakpoint only; the mobile block near
   the bottom of this file (nav on its own row) is what runs below it, and its
   breakpoint moved 820 → 1120 in the same pass so the ragged middle range
   stacks cleanly instead of half-wrapping. Re-measure both if a seventh item
   is ever added — this fits with roughly one item of slack, not more. */
@media(min-width:1120px){
  .brand{ flex:none; white-space:nowrap; }
  nav.links.site{ gap:4px; flex-wrap:nowrap; }
  nav.links.site a{ font-size:11.5px; letter-spacing:.045em; padding:7px 9px; white-space:nowrap; }
}

/* Language switcher — German | US flag. Original to this repo, not ported: the
   live site is English-only. Borrows nav.links' cyan-active treatment so it
   reads as another nav control, not a bolted-on widget.
   Sits after nav.links in .nav-in; below 1120px the nav wraps to its own row
   (order:3, width:100%) and this stays up top beside the brand, where
   .nav-in's space-between pins it right without an extra rule.
   The labels are flags, not text (changed 2026-08-07) — each anchor carries a
   title + aria-label naming the language, since the SVG is aria-hidden. The
   positive z-index keeps the control stacked above header.nav's own
   background/backdrop layers so the flags can never be painted over. */
.lang-switch{
  position:relative; z-index:2;
  display:flex; align-items:center; flex:0 0 auto;
  border:1px solid var(--line-bright); border-radius:8px; overflow:hidden;
}
.lang-switch a{
  position:relative; z-index:2;
  display:flex; align-items:center;
  padding:6px 9px; transition:background .2s;
}
.lang-switch a + a{ border-left:1px solid var(--line); }
.lang-switch a:hover, .lang-switch a:focus-visible{ background:rgba(255,255,255,0.05); }
.lang-switch a.active{ background:rgba(210,193,182,0.10); }
/* Inactive flags sit back; the current language reads at full colour. */
.lang-switch .flag{
  display:block; width:22px; height:14px; border-radius:2px;
  box-shadow:0 0 0 1px rgba(0,0,0,0.35);
  opacity:.55; filter:grayscale(.6); transition:opacity .2s, filter .2s;
}
.lang-switch a:hover .flag, .lang-switch a:focus-visible .flag,
.lang-switch a.active .flag{ opacity:1; filter:none; }

/* persistent site controls — stay visible on mobile */
.nav-site{ display:flex; align-items:center; gap:10px; }
.home-link{
  font-family:"IBM Plex Mono",monospace; font-size:12px; letter-spacing:.08em; color:var(--paper-2);
  padding:7px 12px; border-radius:7px; border:1px solid var(--line-bright);
  background:rgba(210,193,182,0.06); white-space:nowrap;
  transition:color .2s, background .2s, border-color .2s;
}
.home-link:hover, .home-link:focus-visible{ color:var(--ink); background:var(--cyan); border-color:var(--cyan); }
.lang-sw{ display:flex; align-items:center; gap:5px; font-family:"IBM Plex Mono",monospace; font-size:12px; letter-spacing:.06em; color:var(--muted); }
.lang-sw a{ padding:4px 5px; border-radius:5px; color:var(--muted); transition:color .2s; }
.lang-sw a.active{ color:var(--cyan); }
.lang-sw a:hover, .lang-sw a:focus-visible{ color:var(--paper); }
.lang-sw .sep{ opacity:.5; }
@media(max-width:700px){ .byline{ display:none; } }

/* ---------- Glass panel primitive ---------- */
.glass{
  position:relative;
  background:linear-gradient(160deg, rgba(255,255,255,0.045), rgba(255,255,255,0.012) 40%, rgba(22,48,63,0.2));
  border:1px solid var(--line-bright);
  border-radius:14px;
  box-shadow:inset 0 1px 0 rgba(255,255,255,0.06), 0 24px 50px -30px rgba(0,0,0,0.9);
}
.glass::before, .glass::after{ content:""; position:absolute; width:14px; height:14px; opacity:.7; pointer-events:none; }
.glass::before{ top:9px; left:9px; border-top:1.5px solid var(--line-bright); border-left:1.5px solid var(--line-bright); }
.glass::after{ bottom:9px; right:9px; border-bottom:1.5px solid var(--line-bright); border-right:1.5px solid var(--line-bright); }
.tint-cyan{ border-color:rgba(210,193,182,0.32); box-shadow:inset 0 1px 0 rgba(210,193,182,0.18), 0 0 0 1px rgba(210,193,182,0.04), 0 30px 60px -34px rgba(210,193,182,0.25); }
.tint-amber{ border-color:rgba(69,104,130,0.34); box-shadow:inset 0 1px 0 rgba(69,104,130,0.20), 0 0 0 1px rgba(69,104,130,0.05), 0 30px 60px -34px rgba(69,104,130,0.25); }
.tint-alert{ border-color:rgba(255,84,104,0.32); box-shadow:inset 0 1px 0 rgba(255,84,104,0.16), 0 30px 60px -34px rgba(255,84,104,0.22); }

/* ---------- Section spacing (single source of truth) ---------- */
.section{ padding:clamp(64px,9vh,118px) 0; position:relative; }
.section .head{ margin-bottom:42px; }
.divider{ height:1px; background:linear-gradient(90deg, transparent, var(--line-bright), transparent); }

/* ============ HERO ============ */
.hero{ padding:clamp(46px,7vh,84px) 0 clamp(56px,8vh,96px); }
.hero-grid{ display:grid; grid-template-columns:1.05fr 0.95fr; gap:48px; align-items:center; }
.hero-grid > *{ min-width:0; }
@media(max-width:920px){ .hero-grid{ grid-template-columns:1fr; gap:30px; } }
.hero h1{
  font-family:"Archivo Expanded",sans-serif; font-weight:900;
  font-size:clamp(36px,6.3vw,76px); line-height:0.98; letter-spacing:-0.02em; margin:18px 0 0;
}
.hero h1 .ghost{
  display:block; color:transparent;
  background:linear-gradient(180deg,#fff, #E7D9CA 55%, var(--cyan));
  -webkit-background-clip:text; background-clip:text;
  text-shadow:0 0 60px rgba(210,193,182,0.25);
}
.hero h1 small{ display:block; font-size:clamp(15px,2vw,21px); font-weight:600; letter-spacing:.02em; color:var(--paper-2); font-family:"Inter",sans-serif; margin-top:18px; max-width:30ch; line-height:1.4; }
.stack-row{ display:flex; flex-wrap:wrap; gap:9px; margin-top:30px; }
.chip{
  font-family:"IBM Plex Mono",monospace; font-size:12px; letter-spacing:.08em;
  padding:8px 13px; border-radius:8px; border:1px solid var(--line-bright);
  background:rgba(255,255,255,0.03); color:var(--paper-2);
}
.chip b{ color:var(--cyan); font-weight:600; }
.stack-tight{ gap:8px; flex-wrap:nowrap; overflow-x:auto; padding-bottom:2px; -webkit-overflow-scrolling:touch; }
.stack-tight .chip{ font-size:11px; letter-spacing:.05em; padding:7px 10px; white-space:nowrap; flex:none; }

/* ============ generic grids ============ */
.two{ display:grid; grid-template-columns:1fr 1fr; gap:22px; }
.three{ display:grid; grid-template-columns:repeat(3,1fr); gap:22px; }
@media(max-width:860px){ .two,.three{ grid-template-columns:1fr; } }
.pad{ padding:26px 26px 28px; }
.card-k{ font-family:"IBM Plex Mono",monospace; font-size:12px; letter-spacing:.14em; text-transform:uppercase; color:var(--muted); }
.card-h{ font-family:"Archivo Expanded",sans-serif; font-weight:700; font-size:21px; margin:10px 0 12px; letter-spacing:-0.01em; }
ul.ticks{ list-style:none; margin:0; padding:0; display:grid; gap:11px; }
ul.ticks li{ position:relative; padding-left:26px; color:var(--paper-2); font-size:15.5px; }
ul.ticks li::before{ content:""; position:absolute; left:2px; top:9px; width:9px; height:9px; transform:rotate(45deg); background:var(--cyan); box-shadow:0 0 9px var(--cyan); }
ul.ticks.amber li::before{ background:var(--amber); box-shadow:0 0 9px var(--amber); }
ul.ticks.alert li::before{ background:var(--alert); box-shadow:0 0 9px var(--alert); }

footer.ft{ border-top:1px solid var(--line); padding:34px 0 56px; color:var(--muted); }
.ft-in{ display:flex; justify-content:space-between; gap:18px; flex-wrap:wrap; font-family:"IBM Plex Mono",monospace; font-size:12px; letter-spacing:.06em; }
.ft-in a:hover{ color:var(--paper); }

/* ---------- reveal (dormant: no JS in this repo toggles .in) ---------- */
.reveal{ opacity:0; transform:translateY(26px); transition:opacity .8s var(--ease), transform .8s var(--ease); }
.reveal.in{ opacity:1; transform:none; }

@media (prefers-reduced-motion: reduce){
  *{ animation:none !important; transition:none !important; }
  .reveal{ opacity:1; transform:none; }
  html{ scroll-behavior:auto; }
}

/* ============================================================
   SITE COMPONENTS — reused across the six content pages,
   built only from the tokens + primitives above.
   ============================================================ */

/* Typed role line on the home hero (static text — no JS typewriter in this repo) */
.typed-line{ margin-top:20px; font-family:"IBM Plex Mono",monospace; font-size:clamp(14px,1.6vw,16px); letter-spacing:.04em; color:var(--paper-2); }
.typed-line .prompt{ color:var(--cyan); }
.typed-cursor{ display:inline-block; width:9px; height:1.05em; vertical-align:-2px; margin-left:2px; background:var(--cyan); box-shadow:0 0 10px var(--cyan); animation:caret 1s step-end infinite; }
@keyframes caret{ 0%,100%{ opacity:1; } 50%{ opacity:0; } }
@media (prefers-reduced-motion: reduce){ .typed-cursor{ animation:none; } }

/* Circular portrait — home + about */
.portrait{ position:relative; width:100%; max-width:342px; aspect-ratio:1/1; margin-inline:auto; }
@media(min-width:921px){ .portrait{ transform:translate(-20px,-28px); } }
.portrait img{ width:100%; height:100%; border-radius:50%; object-fit:cover; object-position:center top; display:block; border:1px solid var(--line-bright); }
.portrait::before{
  content:""; position:absolute; inset:-14px; border-radius:50%; pointer-events:none;
  background:conic-gradient(from 0deg, var(--cyan), transparent 55%, transparent 78%, var(--amber));
  -webkit-mask:radial-gradient(farthest-side, transparent calc(100% - 1.5px), #000 100%);
          mask:radial-gradient(farthest-side, transparent calc(100% - 1.5px), #000 100%);
  opacity:.8; animation:spin 22s linear infinite;
}
.portrait::after{ content:""; position:absolute; inset:0; border-radius:50%; box-shadow:0 0 50px rgba(210,193,182,0.18), inset 0 0 40px rgba(210,193,182,0.10); pointer-events:none; }
@keyframes spin{ to{ transform:rotate(360deg); } }
@media (prefers-reduced-motion: reduce){ .portrait::before{ animation:none; } }

/* Stats band (home + about facts) */
.stats-band{ display:grid; grid-template-columns:repeat(3,1fr); gap:18px; }
@media(max-width:860px){ .stats-band{ grid-template-columns:1fr; } }
.stat-cell{ padding:28px 26px; }
.stat-num{ font-family:"Archivo Expanded",sans-serif; font-weight:900; font-size:clamp(38px,5vw,56px); line-height:1; color:var(--cyan); text-shadow:0 0 34px rgba(210,193,182,0.3); }
.stat-num sup{ font-size:.5em; color:var(--amber); }
.stat-num .count{ font-variant-numeric:tabular-nums; }
.stat-label{ font-family:"IBM Plex Mono",monospace; font-size:12px; letter-spacing:.16em; text-transform:uppercase; color:var(--muted); margin-top:12px; }

/* Directory / link cards (home explore · teaching · projects) */
.dir-grid{ display:grid; grid-template-columns:repeat(2,1fr); gap:18px; }
@media(max-width:860px){ .dir-grid{ grid-template-columns:1fr; } }
.link-card{ display:block; padding:26px 26px 60px; position:relative; color:inherit; transition:transform .3s var(--ease), border-color .3s; overflow:hidden; }
.link-card .lc-wash{ content:""; position:absolute; inset:0; border-radius:inherit; opacity:0; transition:opacity .3s; pointer-events:none;
  background:radial-gradient(420px circle at var(--mx,50%) var(--my,50%), rgba(210,193,182,0.12), transparent 60%); }
.link-card:hover{ transform:translateY(-5px); border-color:rgba(210,193,182,0.5); }
.link-card:hover .lc-wash{ opacity:1; }
.lc-ico{ font-size:30px; line-height:1; display:block; margin-bottom:16px; }
.lc-k{ font-family:"IBM Plex Mono",monospace; font-size:11.5px; letter-spacing:.16em; text-transform:uppercase; color:var(--cyan); }
.lc-h{ font-family:"Archivo Expanded",sans-serif; font-weight:700; font-size:21px; margin:10px 0 10px; letter-spacing:-0.01em; }
.lc-p{ margin:0; color:var(--paper-2); font-size:14.5px; line-height:1.65; }
.lc-tags{ font-family:"IBM Plex Mono",monospace; font-size:11px; letter-spacing:.1em; color:var(--muted); margin-top:14px; }
.lc-arrow{ position:absolute; left:26px; bottom:24px; color:var(--cyan); font-family:"IBM Plex Mono",monospace; transition:transform .3s; }
.link-card:hover .lc-arrow{ transform:translateX(8px); }

/* About prose */
.prose{ padding:34px 36px; }
.prose p{ margin:0 0 18px; color:var(--paper-2); }
.prose p:last-child{ margin-bottom:0; }
.prose .lead::first-letter{ float:left; font-family:"Archivo Expanded",sans-serif; font-weight:900; font-size:62px; line-height:0.8; color:var(--cyan); padding:6px 14px 0 0; text-shadow:0 0 30px rgba(210,193,182,0.3); }
.pullquote{ padding:30px 32px; }
.pullquote blockquote{ margin:0; font-family:"Archivo Expanded",sans-serif; font-weight:700; font-size:clamp(19px,2.2vw,24px); line-height:1.3; color:var(--paper); }
.pullquote cite{ display:block; font-style:normal; font-family:"IBM Plex Mono",monospace; font-size:11px; letter-spacing:.16em; text-transform:uppercase; color:var(--amber); margin-top:16px; }
.about-grid{ display:grid; grid-template-columns:1.4fr 0.9fr; gap:36px; align-items:start; }
@media(max-width:920px){ .about-grid{ grid-template-columns:1fr; gap:28px; } }
.about-aside{ display:grid; gap:24px; position:sticky; top:90px; }
@media(max-width:920px){ .about-aside{ position:static; } }

/* Expertise ledger */
.ledger{ display:grid; gap:0; border-top:1px solid var(--line); }
.ledger-row{
  display:grid; grid-template-columns:54px 40px 230px 1fr auto; gap:24px; align-items:center;
  padding:22px 12px; border-bottom:1px solid var(--line); position:relative; transition:background .3s;
}
.ledger-row::before{ content:""; position:absolute; left:0; top:0; bottom:0; width:2px; background:var(--cyan); box-shadow:0 0 12px var(--cyan); transform:scaleY(0); transform-origin:top; transition:transform .35s; }
.ledger-row:hover{ background:rgba(210,193,182,0.04); }
.ledger-row:hover::before{ transform:scaleY(1); }
.lr-idx{ font-family:"IBM Plex Mono",monospace; font-size:12px; letter-spacing:.14em; color:var(--muted); }
.lr-ico{ font-size:22px; }
.lr-name{ font-family:"Archivo Expanded",sans-serif; font-weight:700; font-size:19px; color:var(--paper); }
.lr-desc{ font-size:14.5px; color:var(--paper-2); line-height:1.6; }
.lr-meta{ display:flex; flex-direction:column; gap:8px; align-items:flex-end; }
.skill-dot{ font-family:"IBM Plex Mono",monospace; font-size:10.5px; letter-spacing:.13em; text-transform:uppercase; color:var(--cyan); display:flex; align-items:center; gap:6px; white-space:nowrap; }
.skill-dot::before{ content:""; width:6px; height:6px; transform:rotate(45deg); background:var(--cyan); box-shadow:0 0 8px var(--cyan); }
.skill-tag{ font-family:"IBM Plex Mono",monospace; font-size:10.5px; letter-spacing:.12em; text-transform:uppercase; color:var(--amber); background:rgba(69,104,130,0.08); border:1px solid rgba(69,104,130,0.3); padding:3px 10px; border-radius:6px; white-space:nowrap; }
@media(max-width:1040px){ .ledger-row{ grid-template-columns:40px 1fr auto; } .lr-idx, .lr-desc{ display:none; } }
@media(max-width:640px){
  .ledger-row{ grid-template-columns:32px 1fr; column-gap:16px; row-gap:12px; }
  .lr-meta{ grid-column:1 / -1; flex-direction:row; flex-wrap:wrap; align-items:center; gap:8px 12px; }
  .skill-dot, .skill-tag{ white-space:normal; }
}

/* Contact panel */
.contact-wrap{ display:grid; place-items:center; padding:clamp(60px,10vh,120px) 0; }
.contact-card{ width:100%; max-width:620px; padding:46px 44px; }
.contact-card h1{ font-family:"Archivo Expanded",sans-serif; font-weight:900; font-size:clamp(32px,5vw,52px); line-height:1.04; letter-spacing:-0.015em; margin:14px 0 0; }
.contact-card .sub{ color:var(--paper-2); margin:22px 0 32px; max-width:46ch; }
.contact-rows{ display:grid; gap:16px; border-top:1px solid var(--line); padding-top:30px; }
.contact-row{ display:flex; align-items:center; gap:16px; }
.contact-row .ic{ width:42px; height:42px; flex:none; border-radius:9px; display:grid; place-items:center; border:1px solid var(--line-bright); background:rgba(210,193,182,0.06); color:var(--cyan); }
.contact-row .tx{ font-family:"IBM Plex Mono",monospace; font-size:14px; color:var(--paper); }
.contact-row .tx small{ display:block; font-size:10.5px; letter-spacing:.14em; text-transform:uppercase; color:var(--muted); margin-bottom:3px; }
.contact-row .tx a{ color:var(--cyan); }
.contact-row .tx a:hover{ text-decoration:underline; }

/* Page header block for inner pages */
.page-head{ padding-top:clamp(46px,7vh,80px); }

/* Primary site nav stays usable on small screens (base nav.links hides <1120px) */
@media(max-width:1119px){
  .nav-in:has(.links.site){ flex-wrap:wrap; }
  nav.links.site{ display:flex; order:3; width:100%; margin-left:0; justify-content:flex-start; gap:4px 6px; }
  nav.links.site a{ padding:6px 9px; font-size:11px; letter-spacing:.06em; }
  /* The nav takes its own row here, so .nav-in's space-between no longer pins
     the switcher right — and once the brand alone fills the top row (~≤430px)
     the switcher wraps onto a row of its own, where it would otherwise sit
     stranded on the left. An auto margin keeps it right-aligned in both cases. */
  .lang-switch{ margin-left:auto; }
}

/* ============================================================
   PROJECT CARD extras — originally built 2026-08-06 for the CAD-style
   "MY RESEARCHES" under-construction page (removed 2026-08-19). The
   headline draw-in animation and subject roll went with that page;
   .uc-cta and the drawing title block (.uc-block/.uc-field) survived
   because pages/projects.html uses them too.
   ============================================================ */
.uc-cta{ margin-top:38px; display:flex; gap:12px; flex-wrap:wrap; }

/* --- Drawing title block --- */
.uc-block{ margin-top:clamp(46px,7vh,80px); display:grid; grid-template-columns:repeat(5,1fr); overflow:hidden; }
@media(max-width:900px){ .uc-block{ grid-template-columns:repeat(2,1fr); } }
@media(max-width:420px){ .uc-block{ grid-template-columns:1fr; } }
/* Separators as box-shadows rather than borders: the parent's
   overflow:hidden clips the outer-edge ones, so the same rule
   works at every column count without double lines. */
.uc-field{ padding:20px 22px; display:grid; gap:7px; box-shadow:-1px 0 0 var(--line), 0 -1px 0 var(--line); }
.uc-field span{
  font-family:"IBM Plex Mono",monospace; font-size:10.5px; letter-spacing:.16em;
  text-transform:uppercase; color:var(--muted);
}
.uc-field b{
  font-family:"IBM Plex Mono",monospace; font-size:13.5px; font-weight:500;
  letter-spacing:.04em; color:var(--paper);
}
.uc-field b.uc-status{ display:flex; align-items:center; gap:9px; color:var(--amber); }
.uc-field b.uc-status::before{
  content:""; flex:none; width:7px; height:7px; transform:rotate(45deg);
  background:var(--amber); box-shadow:0 0 9px var(--amber);
}

/* --- Project screenshot (pages/projects.html, both trees). Original to this
   repo, like .uc-* and .lang-switch — the live site has no projects page to
   port from. The shot is a light-themed app on a dark page, so it needs a
   real edge: the border keeps it from bleeding into the panel, the drop
   shadow lifts it off the glass. --- */
.pj-shot{ margin:26px 0 0; }
.pj-shot a{ display:block; border-radius:10px; }
.pj-shot a:focus-visible{ outline:2px solid var(--cyan); outline-offset:4px; }
.pj-shot img{
  display:block; width:100%; height:auto; border-radius:10px;
  border:1px solid var(--line-bright);
  box-shadow:0 30px 60px -34px rgba(0,0,0,0.65);
  transition:border-color .15s ease, box-shadow .15s ease;
}
.pj-shot a:hover img{
  border-color:var(--cyan);
  box-shadow:0 30px 60px -30px rgba(0,0,0,0.75);
}
.pj-shot figcaption{
  font-family:"IBM Plex Mono",monospace; font-size:11.5px; letter-spacing:.05em;
  color:var(--muted); line-height:1.65; margin-top:13px;
}

/* ============================================================
   KARO CHAT WIDGET — floating assistant, present on every page
   (markup injected by js/karo.js). Deliberately breaks from the
   cyan/amber system into dark red/gold so it reads as a distinct,
   attention-grabbing control rather than another site section.
   ============================================================ */
:root{
  --karo-red:       #7A1B2E;
  --karo-gold:      #A67C1E;
  --karo-hint-bg:   #F2C230;
  --karo-hint-text: #241505;
}

.karo-widget{ position:fixed; right:22px; bottom:22px; z-index:400; display:flex; flex-direction:column; align-items:flex-end; gap:14px; }

.karo-fab{
  width:60px; height:60px; border-radius:50%; border:1px solid rgba(255,255,255,0.18);
  background:radial-gradient(circle at 32% 28%, var(--karo-gold), var(--karo-red) 72%);
  box-shadow:0 14px 34px -12px rgba(122,27,46,0.65), inset 0 0 0 1px rgba(255,255,255,0.06);
  cursor:pointer; display:grid; place-items:center; padding:0;
  transition:transform .25s var(--ease), box-shadow .25s;
}
.karo-fab:hover, .karo-fab:focus-visible{ transform:translateY(-3px); box-shadow:0 18px 40px -12px rgba(122,27,46,0.75), inset 0 0 0 1px rgba(255,255,255,0.08); }
.karo-fab-mark{ font-family:"Archivo Expanded",sans-serif; font-weight:900; font-size:22px; color:#FFF3DE; letter-spacing:-0.02em; text-shadow:0 1px 3px rgba(0,0,0,0.35); }

.karo-fab.is-pulsing{ animation:karoPulse 1.8s var(--ease) infinite; }
@keyframes karoPulse{
  0%{ box-shadow:0 14px 34px -12px rgba(122,27,46,0.65), 0 0 0 0 rgba(242,194,48,0.55); }
  70%{ box-shadow:0 14px 34px -12px rgba(122,27,46,0.65), 0 0 0 16px rgba(242,194,48,0); }
  100%{ box-shadow:0 14px 34px -12px rgba(122,27,46,0.65), 0 0 0 0 rgba(242,194,48,0); }
}

/* Hint bubble — solid yellow so it reads as a call-out, not a glass panel */
.karo-hint{
  max-width:220px; padding:12px 34px 12px 14px; border-radius:12px;
  background:var(--karo-hint-bg); color:var(--karo-hint-text);
  font-family:"IBM Plex Mono",monospace; font-size:12.5px; letter-spacing:.02em; line-height:1.45;
  box-shadow:0 16px 34px -14px rgba(0,0,0,0.55);
  position:relative;
  opacity:0; transform:translateY(8px) scale(.96); pointer-events:none;
  transition:opacity .3s var(--ease), transform .3s var(--ease);
}
.karo-hint.is-visible{ opacity:1; transform:none; pointer-events:auto; }
.karo-hint p{ margin:0; font-weight:600; }
.karo-hint::after{
  content:""; position:absolute; right:22px; bottom:-6px; width:12px; height:12px;
  background:var(--karo-hint-bg); transform:rotate(45deg); border-radius:2px;
}
.karo-hint-close{
  position:absolute; top:6px; right:8px; width:20px; height:20px; border:0; border-radius:50%;
  background:rgba(36,21,5,0.12); color:var(--karo-hint-text); font-size:14px; line-height:1;
  cursor:pointer; display:grid; place-items:center;
}
.karo-hint-close:hover{ background:rgba(36,21,5,0.22); }

/* Panel — reuses .glass for its border/corner-marks, but overrides the
   background to near-opaque: .glass's default translucency is tuned for
   sitting over the page's flat gradient backdrop, and reads poorly here
   since the widget can float over bright content (e.g. the hero portrait). */
.karo-panel{
  position:fixed; right:22px; bottom:94px; width:min(360px, calc(100vw - 44px));
  height:min(520px, calc(100vh - 140px));
  display:flex; flex-direction:column; overflow:hidden;
  background:linear-gradient(165deg, rgba(30,66,88,0.97), rgba(22,48,63,0.98));
  backdrop-filter:blur(14px); -webkit-backdrop-filter:blur(14px);
  opacity:0; transform:translateY(16px) scale(.98); pointer-events:none;
  transition:opacity .28s var(--ease), transform .28s var(--ease);
}
.karo-panel.is-open{ opacity:1; transform:none; pointer-events:auto; }

.karo-panel-head{ display:flex; align-items:center; justify-content:space-between; padding:16px 18px; border-bottom:1px solid var(--line); flex:none; }
.karo-panel-title{ font-family:"Archivo Expanded",sans-serif; font-weight:800; font-size:16px; color:var(--paper); }
.karo-panel-sub{ font-family:"IBM Plex Mono",monospace; font-size:11px; letter-spacing:.06em; color:var(--muted); margin-top:2px; }
.karo-panel-close{ border:0; background:transparent; color:var(--muted); font-size:20px; line-height:1; cursor:pointer; padding:4px 6px; border-radius:6px; }
.karo-panel-close:hover{ color:var(--paper); background:rgba(255,255,255,0.06); }

.karo-messages{ flex:1; overflow-y:auto; padding:16px 18px; display:flex; flex-direction:column; gap:12px; }
.karo-msg{ display:flex; }
.karo-msg-user{ justify-content:flex-end; }
.karo-msg-model{ justify-content:flex-start; }
.karo-bubble{
  max-width:82%; padding:10px 13px; border-radius:12px; font-size:14px; line-height:1.5;
  white-space:pre-wrap; word-break:break-word;
}
.karo-msg-user .karo-bubble{ background:linear-gradient(135deg, var(--karo-gold), var(--karo-red)); color:#FFF6E7; border-bottom-right-radius:4px; }
.karo-msg-model .karo-bubble{ background:rgba(255,255,255,0.06); border:1px solid var(--line-bright); color:var(--paper-2); border-bottom-left-radius:4px; }

.karo-typing{ display:flex; gap:4px; align-items:center; padding:12px 14px; }
.karo-typing span{ width:6px; height:6px; border-radius:50%; background:var(--muted); animation:karoTyping 1.1s ease-in-out infinite; }
.karo-typing span:nth-child(2){ animation-delay:.15s; }
.karo-typing span:nth-child(3){ animation-delay:.3s; }
@keyframes karoTyping{ 0%,60%,100%{ opacity:.35; transform:translateY(0); } 30%{ opacity:1; transform:translateY(-3px); } }

.karo-input-row{ display:flex; gap:10px; padding:14px; border-top:1px solid var(--line); flex:none; }
.karo-input{
  flex:1; resize:none; max-height:120px; min-height:20px;
  background:rgba(255,255,255,0.04); border:1px solid var(--line-bright); border-radius:10px;
  color:var(--paper); font-family:"Inter",sans-serif; font-size:14px; line-height:1.4;
  padding:10px 12px;
}
.karo-input:focus-visible{ outline:2px solid var(--karo-gold); outline-offset:1px; }
.karo-input::placeholder{ color:var(--muted); }
.karo-send{
  flex:none; width:38px; height:38px; border-radius:10px; border:0; cursor:pointer;
  background:linear-gradient(135deg, var(--karo-gold), var(--karo-red)); color:#FFF6E7; font-size:15px;
  display:grid; place-items:center; transition:opacity .2s, transform .2s;
}
.karo-send:hover{ transform:translateY(-1px); }
.karo-send:disabled{ opacity:.5; cursor:default; transform:none; }

@media(max-width:480px){
  .karo-widget{ right:14px; bottom:14px; }
  .karo-panel{ right:14px; left:14px; width:auto; bottom:88px; }
}
