/* ==========================================================================
   Goutham Inamanamelluri — portfolio
   Pure HTML + CSS. No JavaScript anywhere on this site.

   Look: "obsidian & pearl" with crimson accents, lit glass
   edges, glossy meters and a soft aurora background. Light and dark themes
   follow the visitor's OS setting.

   1.  Fonts + icons
   2.  Design tokens (light + dark)
   3.  Base + atmosphere (aurora, grain)
   4.  Page shell: sidebar / masthead / section navigation
   5.  Sections + shared components (cards, chips, bullets, logos)
   6.  Profile
   7.  Work experience
   8.  Expertise (donuts + meters)
   9.  Technical skills
   10. Education + certifications
   11. Footer, back-to-top, tracking pixel
   12. Accessibility modes + print
   ========================================================================== */


/* 1. Fonts + icons -------------------------------------------------------- */

/* Text fonts are self-hosted (SIL Open Font License; license files sit next to
   them in /fonts). Latin subset, variable weight. If a file fails to load, the
   system stacks in --font-sans / --font-serif take over.                      */
@font-face {
  font-family: "Inter";
  src: url(../fonts/inter-latin-wght-normal.woff2) format("woff2");
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC,
                 U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
                 U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: "Source Serif 4";
  src: url(../fonts/source-serif-4-latin-wght-normal.woff2) format("woff2");
  font-weight: 200 900;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC,
                 U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
                 U+2212, U+2215, U+FEFF, U+FFFD;
}

/* Icons: inline SVG sprite defined at the top of <body> (no icon font). */
.sprite { position: absolute; width: 0; height: 0; overflow: hidden; }
.icon   { display: block; flex: none; width: 1em; height: 1em; fill: currentColor; }

/* Brand colours (chosen to stay legible on the white skill tiles) */
.icon--d3-dot-js        { color: #f9a03c; }
.icon--gulp             { color: #da4648; }
.icon--microsoftoutlook { color: #0072c6; }
.icon--microsoftonenote { color: #80397b; }
.icon--microsoftexcel   { color: #217346; }
.icon--microsoftaccess  { color: #ba141a; }
.icon--microsoftword    { color: #2b579a; }
.icon--apple            { color: #5b6370; }
.icon--ubuntu           { color: #e95420; }
.icon--windows          { color: #0078d6; }
.icon--php              { color: #4f5b93; }
.icon--python           { color: #3776ab; }
.icon--postgresql       { color: #336791; }
.icon--mysql            { color: #00758f; }
.icon--visualstudiocode { color: #007acc; }
.icon--visualstudio     { color: #5c2d91; }
.icon--typescript       { color: #007acc; }
.icon--html5            { color: #e34f26; }
.icon--css3             { color: #1572b6; }
.icon--csharp           { color: #68217a; }   /* C# purple, like the .NET badges */
.icon--cplusplus        { color: #00599c; }
.icon--c                { color: #5d7ea6; }
.icon--javascript       { color: #e8c500; }


/* 2. Design tokens -------------------------------------------------------- */

@property --ring-angle {                 /* lets the avatar ring rotate; ignored where unsupported */
  syntax: "<angle>";
  inherits: false;
  initial-value: 0deg;
}
@property --pp {                         /* donut arc, 0-100: animated while the Expertise card scrolls in */
  syntax: "<number>";
  inherits: true;
  initial-value: 0;
}
@property --M {                           /* tiles per row (Technical Skills) */
  syntax: "<number>";
  inherits: true;
  initial-value: 3;
}
@property --c {                           /* tiles per row after balancing */
  syntax: "<number>";
  inherits: true;
  initial-value: 3;
}
@property --nn {                         /* the donut's centre number counting up */
  syntax: "<integer>";
  inherits: true;
  initial-value: 0;
}

:root {
  color-scheme: light;

  --font-sans: "Inter", ui-sans-serif, system-ui, -apple-system, "Segoe UI Variable Text",
               "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif;
  --font-serif: "Source Serif 4", ui-serif, "Iowan Old Style", "Palatino Linotype", Palatino,
                "Book Antiqua", Georgia, Cambria, serif;

  /* ---- Light: pearl & champagne ---- */
  --bg:          #f4f1ec;
  --surface:     rgb(255 255 255 / .90);
  --surface-alt: rgb(13 26 45 / .05);
  --ink:         #0c1729;      /* headings */
  --ink-soft:    #364257;      /* body */
  --ink-mute:    #566174;      /* captions, meta */
  --line:        rgb(13 26 45 / .10);
  --track:       rgb(13 26 45 / .09);

  --accent:      #c8102e;
  --accent-ink:  #ffffff;
  --accent-soft: rgb(200 16 46 / .09);
  --link:        #b00d28;
  --focus:       #1b5fd1;
  --mark:         var(--accent);                    /* drop cap + icons share one red: crimson here, a brighter shade of it in dark */
  --mark-soft:    var(--accent-soft);
  --theme-icon:   url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23e8294a' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M21 12.8A9 9 0 1 1 11.2 3a7 7 0 0 0 9.8 9.8z'/%3E%3C/svg%3E");

  --grad-mark:   linear-gradient(135deg, #e8294a 0%, #c8102e 55%, #a30d27 100%);   /* bullets */
  --grad-accent: linear-gradient(135deg, #e8294a 0%, #c8102e 55%, #a30d27 100%);
  --meter-a: #c8102e;
  --meter-b: #ff6b81;

  --hl:     rgb(255 255 255 / .95);                /* top inner highlight */
  --edge-1: rgb(200 16 46 / .22);                  /* lit-edge gradient: start */
  --edge-2: rgb(200 16 46 / .45);                  /*                    end   */
  --glow-1: rgb(200 16 46 / .10);                  /* aurora blobs */
  --glow-2: rgb(232 41 74 / .12);
  --glow-3: rgb(99 102 241 / .08);
  --grain:  .035;

  --shadow-sm: 0 1px 2px rgb(13 26 45 / .06), 0 10px 26px -16px rgb(13 26 45 / .28);

  /* Sidebar / masthead: dark panel in both themes */
  --side-bg:     #0a1730;
  --side-ink:    #f4f7fc;
  --side-mute:   #aebbd0;
  --side-line:   rgb(255 255 255 / .10);
  --side-mark:   #e8294a;                           /* menu icons: the same red, readable on the navy sidebar */
  --side-grad:
    radial-gradient(90% 38% at 0% 0%, rgb(255 90 120 / .24), transparent 70%),
    radial-gradient(80% 34% at 100% 100%, rgb(232 41 74 / .16), transparent 70%),
    linear-gradient(180deg, #0e1f3d 0%, #08111f 100%);

  --radius:    1.1rem;
  --radius-sm: .8rem;
  --content:   76rem;
  --tile:      5.75rem;
}

/* ---- Theme switching --------------------------------------------------------
   The dark colours below are used (a) on a dark device while the round switch
   (#theme-flip) is off, and (b) on a light device once the visitor flips it.
   On a dark device, flipping the switch falls back to the light colours above.
   (The first block keeps dark mode working in old browsers without :has().)    */
@supports not selector(:has(*)) {
  @media (prefers-color-scheme: dark) {
    :root {
    color-scheme: dark;
      --mark:         #e8294a;
      --mark-soft:    rgb(232 41 74 / .14);
      --grad-mark:    linear-gradient(135deg, #ff6f86 0%, #e8294a 55%, #b50f2c 100%);
      --theme-icon:   url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23e8294a' stroke-width='2' stroke-linecap='round'%3E%3Ccircle cx='12' cy='12' r='4'/%3E%3Cpath d='M12 2v2M12 20v2M4.9 4.9l1.4 1.4M17.7 17.7l1.4 1.4M2 12h2M20 12h2M4.9 19.1l1.4-1.4M17.7 6.3l1.4-1.4'/%3E%3C/svg%3E");
      /* ---- Dark: obsidian ---- */
      --bg:          #070a12;
      --surface:     rgb(17 23 36 / .80);
      --surface-alt: rgb(255 255 255 / .055);
      --ink:         #f3f6fb;
      --ink-soft:    #c9d3e2;
      --ink-mute:    #98a6bb;
      --line:        rgb(255 255 255 / .09);
      --track:       rgb(255 255 255 / .09);
  
      --accent:      #ff7a8c;
      --accent-ink:  #1b0a0f;
      --accent-soft: rgb(255 122 140 / .13);
      --link:        #ff9aa8;
      --focus:       #8db8ff;
  
      --grad-accent: linear-gradient(135deg, #ff9aa8 0%, #ff5c75 50%, #e11d48 100%);
      --meter-a: #e8294a;
      --meter-b: #ff8fa1;
  
      --hl:     rgb(255 255 255 / .09);
      --edge-1: rgb(255 255 255 / .30);
      --edge-2: rgb(255 122 140 / .34);
      --glow-1: rgb(255 77 109 / .20);
      --glow-2: rgb(225 29 72 / .14);
      --glow-3: rgb(99 102 241 / .17);
      --grain:  .05;
  
      --shadow-sm: 0 1px 2px rgb(0 0 0 / .45), 0 12px 30px -16px rgb(0 0 0 / .65);
  
      --side-bg: #060d19;
      --side-grad:
        radial-gradient(90% 38% at 0% 0%, rgb(255 77 109 / .20), transparent 70%),
        radial-gradient(80% 34% at 100% 100%, rgb(232 41 74 / .14), transparent 70%),
        linear-gradient(180deg, #0a1426 0%, #050a14 100%);
    }
  }
}
@media (prefers-color-scheme: dark) {
  :root:not(:has(#theme-flip:checked)) {
    color-scheme: dark;
    --mark:         #e8294a;
    --mark-soft:    rgb(232 41 74 / .14);
    --grad-mark:    linear-gradient(135deg, #ff6f86 0%, #e8294a 55%, #b50f2c 100%);
    --theme-icon:   url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23e8294a' stroke-width='2' stroke-linecap='round'%3E%3Ccircle cx='12' cy='12' r='4'/%3E%3Cpath d='M12 2v2M12 20v2M4.9 4.9l1.4 1.4M17.7 17.7l1.4 1.4M2 12h2M20 12h2M4.9 19.1l1.4-1.4M17.7 6.3l1.4-1.4'/%3E%3C/svg%3E");
    /* ---- Dark: obsidian ---- */
    --bg:          #070a12;
    --surface:     rgb(17 23 36 / .80);
    --surface-alt: rgb(255 255 255 / .055);
    --ink:         #f3f6fb;
    --ink-soft:    #c9d3e2;
    --ink-mute:    #98a6bb;
    --line:        rgb(255 255 255 / .09);
    --track:       rgb(255 255 255 / .09);

    --accent:      #ff7a8c;
    --accent-ink:  #1b0a0f;
    --accent-soft: rgb(255 122 140 / .13);
    --link:        #ff9aa8;
    --focus:       #8db8ff;

    --grad-accent: linear-gradient(135deg, #ff9aa8 0%, #ff5c75 50%, #e11d48 100%);
    --meter-a: #e8294a;
    --meter-b: #ff8fa1;

    --hl:     rgb(255 255 255 / .09);
    --edge-1: rgb(255 255 255 / .30);
    --edge-2: rgb(255 122 140 / .34);
    --glow-1: rgb(255 77 109 / .20);
    --glow-2: rgb(225 29 72 / .14);
    --glow-3: rgb(99 102 241 / .17);
    --grain:  .05;

    --shadow-sm: 0 1px 2px rgb(0 0 0 / .45), 0 12px 30px -16px rgb(0 0 0 / .65);

    --side-bg: #060d19;
    --side-grad:
      radial-gradient(90% 38% at 0% 0%, rgb(255 77 109 / .20), transparent 70%),
      radial-gradient(80% 34% at 100% 100%, rgb(232 41 74 / .14), transparent 70%),
      linear-gradient(180deg, #0a1426 0%, #050a14 100%);
  }
}
@media (prefers-color-scheme: light) {
  :root:has(#theme-flip:checked) {
    color-scheme: dark;
    --mark:         #e8294a;
    --mark-soft:    rgb(232 41 74 / .14);
    --grad-mark:    linear-gradient(135deg, #ff6f86 0%, #e8294a 55%, #b50f2c 100%);
    --theme-icon:   url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23e8294a' stroke-width='2' stroke-linecap='round'%3E%3Ccircle cx='12' cy='12' r='4'/%3E%3Cpath d='M12 2v2M12 20v2M4.9 4.9l1.4 1.4M17.7 17.7l1.4 1.4M2 12h2M20 12h2M4.9 19.1l1.4-1.4M17.7 6.3l1.4-1.4'/%3E%3C/svg%3E");
    /* ---- Dark: obsidian ---- */
    --bg:          #070a12;
    --surface:     rgb(17 23 36 / .80);
    --surface-alt: rgb(255 255 255 / .055);
    --ink:         #f3f6fb;
    --ink-soft:    #c9d3e2;
    --ink-mute:    #98a6bb;
    --line:        rgb(255 255 255 / .09);
    --track:       rgb(255 255 255 / .09);

    --accent:      #ff7a8c;
    --accent-ink:  #1b0a0f;
    --accent-soft: rgb(255 122 140 / .13);
    --link:        #ff9aa8;
    --focus:       #8db8ff;

    --grad-accent: linear-gradient(135deg, #ff9aa8 0%, #ff5c75 50%, #e11d48 100%);
    --meter-a: #e8294a;
    --meter-b: #ff8fa1;

    --hl:     rgb(255 255 255 / .09);
    --edge-1: rgb(255 255 255 / .30);
    --edge-2: rgb(255 122 140 / .34);
    --glow-1: rgb(255 77 109 / .20);
    --glow-2: rgb(225 29 72 / .14);
    --glow-3: rgb(99 102 241 / .17);
    --grain:  .05;

    --shadow-sm: 0 1px 2px rgb(0 0 0 / .45), 0 12px 30px -16px rgb(0 0 0 / .65);

    --side-bg: #060d19;
    --side-grad:
      radial-gradient(90% 38% at 0% 0%, rgb(255 77 109 / .20), transparent 70%),
      radial-gradient(80% 34% at 100% 100%, rgb(232 41 74 / .14), transparent 70%),
      linear-gradient(180deg, #0a1426 0%, #050a14 100%);
  }
}

@media (min-width: 40rem) { :root { --tile: 6.75rem; } }


/* 3. Base + atmosphere ---------------------------------------------------- */

*, *::before, *::after { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: 4.75rem;      /* clears the sticky mobile section bar */
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink-soft);
  font-family: var(--font-sans);
  font-size: 1rem;
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

main:focus { outline: none; }          /* target of the skip link */

/* Aurora: three soft colour blobs that stay put while the page scrolls. */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background:
    radial-gradient(56rem 38rem at 80% -8%,  var(--glow-1), transparent 62%),
    radial-gradient(46rem 36rem at 12% 46%,  var(--glow-3), transparent 60%),
    radial-gradient(48rem 34rem at 96% 82%,  var(--glow-2), transparent 62%);
}

/* Film grain: a faint texture that makes the gradients feel less digital. */
body::after {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 90;
  pointer-events: none;
  opacity: var(--grain);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 .5 0 0 0 0 .5 0 0 0 0 .5 0 0 0 1 0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}

img { display: block; max-width: 100%; height: auto; }

h1, h2, h3, h4, p, ul, ol, figure { margin: 0; }
ul, ol { padding: 0; list-style: none; }
h1, h2, h3 { text-wrap: balance; }

a {
  color: var(--link);
  text-decoration-thickness: .08em;
  text-underline-offset: .2em;
}
a:hover { text-decoration-thickness: .14em; }

:focus-visible {
  outline: 3px solid var(--focus);
  outline-offset: 3px;
  border-radius: .25rem;
}

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

.skip-link {
  position: absolute;
  left: 1rem; top: -5rem;
  z-index: 100;
  padding: .75rem 1.1rem;
  border-radius: .6rem;
  background: var(--accent);
  color: var(--accent-ink);
  font-weight: 700;
  text-decoration: none;
}
.skip-link:focus { top: 1rem; outline: 3px solid #fff; outline-offset: 2px; box-shadow: 0 0 0 6px #0b1a30; }


/* 4. Page shell ----------------------------------------------------------- */
/* Mobile / tablet: masthead on top, then a sticky, horizontally scrollable
   section bar.  Desktop (>= 64rem): a fixed dark sidebar holding both.      */

.shell    { display: block; }
.sidebar  { display: contents; }          /* lets .mbar stick to the page on small screens */

.masthead {
  display: flex;
  align-items: center;
  gap: 1rem;
  padding: 1.25rem 1rem 1.1rem;
  background: var(--side-grad);
  color: var(--side-ink);
  --focus: #9cc4ff;
}

/* Avatar: a red ring that makes one slow turn when the page loads
   (finite on purpose, so nothing keeps moving while you read).              */
.avatar-ring {
  --ring-angle: 0deg;
  flex: none;
  display: grid;
  padding: 3px;
  border-radius: 50%;
  background: conic-gradient(from var(--ring-angle), #ffb3bf, #e8294a, #ff6f86, #b50f2c, #e8294a, #ffb3bf);
  box-shadow: 0 0 22px rgb(232 41 74 / .38), 0 0 44px rgb(255 90 120 / .18);
  animation: ring-spin 4.5s cubic-bezier(.2, .7, .2, 1) 1;
}
@keyframes ring-spin { to { --ring-angle: 360deg; } }

.avatar {
  width: 4.5rem; height: 4.5rem;
  border: 3px solid #08111f;
  border-radius: 50%;
  object-fit: cover;
}

.masthead h1 {
  font: 700 1.45rem/1.15 var(--font-serif);
  letter-spacing: -.01em;
  color: #fff;
}
.role   { margin-top: .3rem; font-size: .95rem; font-weight: 600; color: var(--side-ink); line-height: 1.35; text-wrap: balance; }
.tagline{ font-size: .85rem; color: var(--side-mute); line-height: 1.4; }

/* Name: white-to-champagne gradient with one gentle sheen on load. Plain white if unsupported. */
@supports ((background-clip: text) or (-webkit-background-clip: text)) {
  .masthead h1 {
    background: linear-gradient(100deg, #ffffff 0%, #ffe6ea 30%, #ffffff 48%, #ffb3bf 70%, #ffffff 100%);
    background-size: 220% 100%;
    -webkit-background-clip: text;
            background-clip: text;
    -webkit-text-fill-color: transparent;
    animation: name-sheen 4s ease-in-out 1 both;
  }
}
@keyframes name-sheen { from { background-position: 0% 0; } to { background-position: 100% 0; } }

.contact { margin-top: .6rem; font-style: normal; }
.contact a {
  display: inline-flex;
  align-items: center;
  gap: .5rem;
  color: var(--side-ink);
  font-size: .9rem;
  text-decoration-color: var(--side-mark);
}
.contact a:hover { color: #fff; }
@media (max-width: 63.999rem) { .contact a { padding-block: .45rem; } }   /* easier to tap on phones and tablets */
.contact svg { flex: none; color: var(--side-mark); }

.masthead > div { min-width: 0; }
@media (min-width: 40rem) and (max-width: 63.999rem) { .masthead { justify-content: center; } }   /* tablet: centred, not left-heavy */          /* lets long text shrink instead of overflowing */
.masthead h1, .contact a { overflow-wrap: anywhere; }

/* Very narrow phones (≤ 360px) */
@media (max-width: 22.5rem) {
  .masthead { gap: .85rem; padding-inline: .75rem; }
  .avatar   { width: 3.75rem; height: 3.75rem; }
  .masthead h1 { font-size: 1.3rem; }
  .contact a { font-size: .82rem; gap: .4rem; }
}
@media (max-width: 20rem) {                  /* foldables (~280px): keep the address on one line */
  .contact svg { display: none; }
  .contact a { font-size: .78rem; }
}

.sidebar-foot { display: none; }            /* desktop sidebar only */

/* Gloss button (fixed colours: it always sits on the dark panel) */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .6rem;
  width: 100%;
  min-height: 2.9rem;
  padding: .7rem 1.1rem;
  border: 1px solid rgb(232 41 74 / .55);
  border-radius: .9rem;
  background: linear-gradient(180deg, rgb(255 255 255 / .30), transparent 55%),
              linear-gradient(135deg, #e8294a 0%, #c8102e 55%, #a30d27 100%);
  box-shadow: inset 0 1px 0 rgb(255 255 255 / .42), 0 14px 28px -12px rgb(232 41 74 / .7);
  color: #fff;
  font-size: .95rem;
  font-weight: 700;
  text-decoration: none;
  transition: transform .2s, box-shadow .2s;
}
.btn:hover {
  transform: translateY(-2px);
  box-shadow: inset 0 1px 0 rgb(255 255 255 / .5), 0 18px 32px -12px rgb(232 41 74 / .85);
}


/* Phone / tablet menu (below 64rem) ------------------------------------------
   A slim sticky bar holding one wide Menu button (the header above already
   shows name and contact, so nothing is repeated here). The button links to
   #menu; :target opens a full sheet of section tiles, and choosing a section
   moves :target away, so the sheet closes by itself. No JavaScript.          */

.mbar {
  position: sticky;
  top: 0;
  z-index: 40;
  padding: .5rem .75rem;
  background: var(--side-bg);
  color: var(--side-ink);
  border-bottom: 1px solid rgb(232 41 74 / .24);
  box-shadow: 0 14px 28px -18px rgb(0 0 0 / .75);
  --focus: #9cc4ff;
}
@supports (((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) and (color: color-mix(in srgb, red, blue))) {
  .mbar {
    background: color-mix(in srgb, var(--side-bg) 97%, transparent);
    -webkit-backdrop-filter: blur(16px) saturate(160%);
            backdrop-filter: blur(16px) saturate(160%);
  }
}

.mbar-btn {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: .75rem;
  width: 100%;
  min-height: 2.9rem;
  padding: .4rem .45rem .4rem 1.05rem;
  border: 1px solid rgb(232 41 74 / .5);
  border-radius: 999px;
  background: linear-gradient(180deg, rgb(255 255 255 / .16), rgb(255 255 255 / .04));
  box-shadow: inset 0 1px 0 rgb(255 255 255 / .22);
  color: #fff;
  font-size: .98rem;
  font-weight: 700;
  text-decoration: none;
  transition: background-color .2s, box-shadow .2s;
}
.mbar-btn:hover { box-shadow: inset 0 1px 0 rgb(255 255 255 / .3), 0 0 0 3px rgb(232 41 74 / .16); }
.mbar-btn-label { display: inline-flex; align-items: center; gap: .7rem; }
.mbar-btn svg { flex: none; color: var(--side-mark); }
.mbar-chev {
  display: grid;
  place-items: center;
  flex: none;
  width: 2.1rem; height: 2.1rem;
  border: 1px solid rgb(255 255 255 / .14);
  border-radius: 50%;
  background: rgb(255 255 255 / .1);
}

.mnav {
  position: fixed;
  inset: 0;
  z-index: 60;
  visibility: hidden;
  opacity: 0;
  pointer-events: none;
  transition: opacity .22s ease, visibility 0s linear .22s;
  --focus: #9cc4ff;
}
.mnav:target {
  visibility: visible;
  opacity: 1;
  pointer-events: auto;
  transition: opacity .22s ease;
}
.mnav-scrim {
  position: absolute;
  inset: 0;
  background: rgb(3 8 18 / .64);
  -webkit-backdrop-filter: blur(5px);
          backdrop-filter: blur(5px);
}
.mnav-sheet {
  position: absolute;
  left: .6rem; right: .6rem; top: .6rem;
  max-height: calc(100vh - 1.2rem);
  max-height: calc(100dvh - 1.2rem);
  overflow-y: auto;
  padding: 1rem;
  border: 1px solid rgb(232 41 74 / .28);
  border-radius: 1.5rem;
  background: var(--side-grad);
  box-shadow: inset 0 1px 0 rgb(255 255 255 / .12), 0 34px 70px -22px rgb(0 0 0 / .9);
  color: var(--side-ink);
  transform: translateY(-12px) scale(.985);
  transition: transform .26s cubic-bezier(.2, .7, .2, 1);
}
.mnav:target .mnav-sheet { transform: none; }

.mnav-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: .9rem;
  padding-left: .25rem;
  font: 700 1.15rem/1 var(--font-serif);
  color: #fff;
}
.mnav-close {
  display: grid;
  place-items: center;
  width: 2.6rem; height: 2.6rem;
  border: 1px solid rgb(255 255 255 / .2);
  border-radius: 50%;
  background: rgb(255 255 255 / .08);
  color: #fff;
  text-decoration: none;
}
.mnav-close:hover { background: rgb(255 255 255 / .15); }

.mnav-list { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: .55rem; }
.mnav-list li:last-child:nth-child(odd) { grid-column: 1 / -1; }   /* odd one out spans the row */
.mnav-list a {
  display: flex;
  align-items: center;
  gap: .7rem;
  min-height: 3.5rem;
  padding: .7rem .9rem;
  border: 1px solid rgb(255 255 255 / .1);
  border-radius: 1rem;
  background: linear-gradient(180deg, rgb(255 255 255 / .10), rgb(255 255 255 / .03));
  box-shadow: inset 0 1px 0 rgb(255 255 255 / .08);
  color: #fff;
  font-size: .95rem;
  font-weight: 600;
  line-height: 1.2;
  text-decoration: none;
  transition: border-color .2s, background-color .2s;
}
.mnav-list a:hover, .mnav-list a:focus-visible { border-color: rgb(232 41 74 / .55); background: linear-gradient(180deg, rgb(255 255 255 / .16), rgb(255 255 255 / .06)); }
.mnav-list .icon { flex: none; width: 1.3rem; height: 1.3rem; color: var(--side-mark); }
@media (max-width: 26rem) { .mnav-list a { gap: .55rem; padding-inline: .7rem; font-size: .86rem; } }   /* keeps "Artificial Intelligence" inside its tile */

@media (max-width: 21rem) {                          /* very narrow phones (≤ 336px): one column so no label is squeezed */
  .mnav-list { grid-template-columns: minmax(0, 1fr); }
  .mnav-sheet { padding: .85rem; }
}

.mnav-cta { margin-top: .9rem; }                    /* same "Get in touch" button as the desktop sidebar */

.mnav-anchor { position: fixed; top: 0; left: 0; width: 0; height: 0; }   /* #nomenu: closes the sheet without scrolling */

/* Desktop sidebar navigation (hidden below 64rem, where the bar + sheet take over) */
.toc { display: none; --focus: #9cc4ff; }
.toc a {
  position: relative;
  display: flex;
  align-items: center;
  gap: .55rem;
  min-height: 2.6rem;
  padding: .45rem .8rem;
  border-radius: .75rem;
  color: var(--side-mute);
  font-size: .92rem;
  font-weight: 600;
  text-decoration: none;
  transition: background-color .2s, color .2s, box-shadow .2s;
}
.toc a .icon { width: 1.1rem; height: 1.1rem; color: var(--side-mark); }
.toc a:hover {
  background: linear-gradient(135deg, rgb(255 255 255 / .12), rgb(255 255 255 / .04));
  color: #fff;
}

/* Highlights the section in view — progressive enhancement, no JS needed.   */
@supports (scroll-target-group: auto) {
  .toc ul { scroll-target-group: auto; }
  .toc a:target-current {
    background: linear-gradient(135deg, rgb(255 255 255 / .17), rgb(255 255 255 / .06));
    box-shadow: inset 0 1px 0 rgb(255 255 255 / .22), 0 0 0 1px rgb(232 41 74 / .28);
    color: #fff;
  }
}

@media (min-width: 64rem) {
  html { scroll-padding-top: 2rem; }

  .mbar, .mnav, .mnav-anchor { display: none; }

  /* The sidebar column's dark colour is also painted by the page itself, so it
     runs the full height of the window (even during overscroll or in tall or
     oddly sized windows) and never leaves a pale strip under the sidebar.     */
  body { background: linear-gradient(90deg, var(--side-bg) 20rem, var(--bg) 20rem); }

  .shell {
    display: grid;
    grid-template-columns: 20rem minmax(0, 1fr);
    grid-template-rows: 1fr auto;
    min-height: 100vh;
  }

  main { grid-column: 2; }

  .sidebar {
    display: flex;
    flex-direction: column;
    gap: 2.25rem;
    grid-column: 1;
    grid-row: 1 / span 2;
    align-self: start;
    position: sticky;
    top: 0;
    height: 100vh;
    height: 100dvh;
    overflow-y: auto;
    scrollbar-width: thin;
    scrollbar-color: rgb(255 255 255 / .28) transparent;
    padding: 3rem 1.75rem 2rem;
    background: var(--side-grad);
    color: var(--side-ink);
    border-right: 1px solid rgb(232 41 74 / .16);
    box-shadow: 14px 0 40px -30px rgb(0 0 0 / .45);
    --focus: #9cc4ff;
  }

  .masthead { display: block; padding: 0; background: none; text-align: center; }   /* centred identity block */
  .avatar-ring { margin: 0 auto 1.4rem; width: max-content; }
  .avatar   { width: 7rem; height: 7rem; }
  .masthead h1 { font-size: 1.85rem; }
  .role     { font-size: 1rem; margin-top: .55rem; }
  .tagline  { font-size: .9rem; }
  .contact  { margin-top: 1.1rem; }

  /* Identity at the top, the menu straight beneath it, and the contact button
     pinned to the bottom edge; any spare height sits between menu and button. */
  .toc { display: block; }
  .toc ul { display: flex; flex-direction: column; gap: .15rem; }
  .sidebar-foot { display: block; margin-top: auto; padding-top: 1.35rem; border-top: 1px solid var(--side-line); }

  @supports (scroll-target-group: auto) {
    .toc a:target-current::before {                 /* red marker on the active item */
      content: "";
      position: absolute;
      left: -1.75rem; top: 22%; bottom: 22%;
      width: 3px;
      border-radius: 0 3px 3px 0;
      background: linear-gradient(180deg, #ff6f86, #e8294a);
      box-shadow: 0 0 12px rgb(232 41 74 / .65);
    }
  }
}

/* Tall monitors: let the sidebar breathe a little more so it fills out. */
@media (min-width: 64rem) and (min-height: 62rem) {
  .sidebar { padding-block: 3.5rem 2.5rem; }
  .avatar { width: 8rem; height: 8rem; }
  .toc a { min-height: 3.1rem; font-size: 1rem; }
  .toc ul { gap: .3rem; }
  .btn { min-height: 3.2rem; }
}

/* Laptop screens are short (a 1366x768 laptop leaves ~650px): tighten the
   sidebar so identity, all seven links and the button fit without scrolling. */
@media (min-width: 64rem) and (max-height: 54rem) {
  .sidebar { padding: 1.4rem 1.5rem 1.2rem; gap: .8rem; }
  .avatar-ring { margin-bottom: .75rem; }
  .avatar { width: 4.75rem; height: 4.75rem; }
  .masthead h1 { font-size: 1.5rem; }
  .role { margin-top: .35rem; font-size: .92rem; }
  .tagline { font-size: .85rem; }
  .contact { margin-top: .6rem; }
  .toc a { min-height: 2.3rem; padding-block: .3rem; }
  .toc ul { gap: .1rem; }
  .sidebar-foot { padding-top: .9rem; }
  .btn { min-height: 2.6rem; padding-block: .5rem; }
}
@media (min-width: 64rem) and (max-height: 40rem) {
  .sidebar { padding: 1rem 1.25rem .9rem; gap: .5rem; }
  .avatar { width: 3.5rem; height: 3.5rem; }
  .avatar-ring { margin-bottom: .5rem; }
  .masthead h1 { font-size: 1.3rem; }
  .tagline { display: none; }
  .contact { margin-top: .4rem; }
  .toc a { min-height: 2rem; padding-block: .2rem; font-size: .88rem; }
  .sidebar-foot { padding-top: .6rem; }
  .btn { min-height: 2.3rem; }
}


/* 5. Sections + shared components ---------------------------------------- */

main { padding: 1.75rem .75rem 2.5rem; min-width: 0; }
@media (min-width: 40rem) { main { padding: 2.5rem 1.5rem 3rem; } }
@media (min-width: 64rem) { main { padding: 4rem 3rem 3rem; } }

.content { width: 100%; max-width: var(--content); margin-inline: auto; }

.section + .section { margin-top: 4rem; }

.section-title {
  display: flex;
  flex-wrap: wrap;                                    /* the rule drops to its own line when it would be a stub */
  align-items: center;
  gap: .5rem .8rem;
  margin-bottom: 1.4rem;
  font: 700 clamp(1.45rem, .35rem + 5.2vw, 1.85rem)/1.2 var(--font-serif);   /* shrinks on tiny phones */
  letter-spacing: -.012em;
  color: var(--ink);
}
.section-title::after {                              /* red hairline running to the edge */
  content: "";
  flex: 1 1 3rem;                                     /* at least 3rem beside the title, else it wraps below it */
  min-width: 0;
  height: 1px;
  margin-left: .35rem;
  background: linear-gradient(90deg, var(--mark), transparent 90%);
  opacity: .75;
}
.section-icon {
  display: grid;
  place-items: center;
  flex: none;
  width: 2.75rem; height: 2.75rem;
  border-radius: .85rem;
  border: 1px solid color-mix(in srgb, var(--mark) 55%, transparent);
  background:
    linear-gradient(150deg, rgb(255 255 255 / .35), transparent 55%),
    var(--mark-soft);
  box-shadow: inset 0 1px 0 var(--hl), 0 6px 16px -8px color-mix(in srgb, var(--mark) 60%, transparent);
  color: var(--mark);
  font-size: 1.2rem;                 /* .icon is 1em */
}

/* Cards: translucent "glass" with a lit gradient edge and a hover sheen. */
.card, .glance li {
  position: relative;
  background:
    linear-gradient(180deg, rgb(255 255 255 / .05), transparent 14rem),
    var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: inset 0 1px 0 var(--hl), var(--shadow-sm);
}
.card { padding: 1.15rem; }
@media (min-width: 40rem) { .card { padding: 1.7rem; } }

.card::before, .glance li::before {                 /* lit edge */
  content: "";
  position: absolute;
  inset: -1px;
  padding: 1px;
  border-radius: inherit;
  background: linear-gradient(150deg, var(--edge-1), transparent 34%, transparent 66%, var(--edge-2));
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
          mask: linear-gradient(#000 0 0) content-box exclude, linear-gradient(#000 0 0);
  pointer-events: none;
}
.card::after, .glance li::after {                   /* diagonal sheen that sweeps across on hover */
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: linear-gradient(115deg, transparent 38%, rgb(255 255 255 / .13) 50%, transparent 62%) no-repeat;
  background-size: 300% 100%;
  background-position: 100% 0;
  transition: background-position 1.1s cubic-bezier(.2, .7, .2, 1);
  pointer-events: none;
}
.card:hover::after, .glance li:hover::after { background-position: 0 0; }

.subtitle {
  margin-bottom: .9rem;
  font: 700 .74rem/1.3 var(--font-sans);
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--ink-mute);
}

.ext { font-family: "Segoe UI Symbol", "Apple Symbols", system-ui, sans-serif; font-size: .85em; text-decoration: none; }   /* ↗ arrow */

.chips { display: flex; flex-wrap: wrap; gap: .4rem; }
.chips li {
  padding: .22rem .7rem;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: linear-gradient(180deg, rgb(255 255 255 / .10), transparent), var(--surface-alt);
  box-shadow: inset 0 1px 0 var(--hl);
  color: var(--ink-soft);
  font-size: .78rem;
  font-weight: 600;
  line-height: 1.5;
}

.bullets li {
  position: relative;
  padding-left: 1.2rem;
  break-inside: avoid;
}
.bullets li + li { margin-top: .6rem; }
.bullets li::before {
  content: "";
  position: absolute;
  left: .1rem; top: .7em;
  width: .42rem; height: .42rem;
  border-radius: 50%;
  background: var(--grad-mark);
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--mark) 22%, transparent);
}

/* Logo on a white tile — logos are authored for light backgrounds */
.logo-tile {
  --h: 3.5rem;                         /* tile height */
  --pad: .35rem;
  display: grid;
  place-items: center;
  flex: none;
  height: var(--h);
  min-width: var(--h);
  padding: var(--pad) calc(var(--pad) * 1.6);
  border: 1px solid rgb(255 255 255 / .6);
  border-radius: .85rem;
  background: #fff;
  box-shadow: 0 6px 18px -8px rgb(0 0 0 / .45);
}
.logo-tile img {
  width: auto;
  height: calc(var(--h) - var(--pad) * 2 - 2px);
  max-width: 7rem;
  object-fit: contain;
}


/* 6. Profile -------------------------------------------------------------- */

/* The profile text is drawn as SVG text: every line is stretched to the exact
   column width (textLength), so there are no uneven word gaps. Fifteen pre-computed
   layouts (line breaks tuned for the real fonts, with hyphenation) switch by
   column width. The real paragraph stays in the page, visually hidden, for
   screen readers, search engines and print. Browsers without container queries
   simply show that real paragraph, justified.                                  */
#profile { container-type: inline-size; }
.prose { display: grid; gap: 1.1rem 3.25rem; }
@container (min-width: 44rem) { .prose { grid-template-columns: 1fr 1fr; align-items: start; } }

.prose-col { container-type: inline-size; min-width: 0; }

/* Fallback / accessible copy */
.prose-text {
  font-size: clamp(1rem, .95rem + .2vw, 1.0625rem);
  line-height: 1.78;
  color: var(--ink-soft);
  text-align: justify;
  text-justify: inter-word;
  hyphens: auto;
  -webkit-hyphens: auto;
  hyphenate-limit-chars: 6 3 3;
  overflow-wrap: break-word;
}
.prose-col:first-child .prose-text::first-letter {
  float: left;
  margin: .04em .1em 0 0;
  font: 700 3.5em/.8 var(--font-serif);
  color: var(--accent);
}

/* The SVG layouts (one is shown at a time) */
.pv { display: none; width: 100%; height: auto; overflow: visible; color: var(--ink-soft); }
.pv text { font-family: var(--font-sans); font-size: 17px; font-weight: 400; fill: currentColor; }
.pv .dropcap { font-family: var(--font-serif); font-weight: 700; font-size: 64px; fill: var(--mark); }   /* same red as the icons (see the theme tokens) */

@supports (container-type: inline-size) {
  .prose-text {                                         /* visually hidden, still read by assistive tech */
    position: absolute !important;
    width: 1px; height: 1px;
    margin: -1px; padding: 0; border: 0;
    overflow: hidden;
    clip: rect(0 0 0 0);
    clip-path: inset(50%);
    white-space: nowrap;
  }
  @container (max-width: 236.199px) { .pv--1 { display: block; } }
  @container (min-width: 236.2px) and (max-width: 260.699px) { .pv--2 { display: block; } }
  @container (min-width: 260.7px) and (max-width: 275.999px) { .pv--3 { display: block; } }
  @container (min-width: 276px) and (max-width: 291.699px) { .pv--4 { display: block; } }
  @container (min-width: 291.7px) and (max-width: 318.699px) { .pv--5 { display: block; } }
  @container (min-width: 318.7px) and (max-width: 344.799px) { .pv--6 { display: block; } }
  @container (min-width: 344.8px) and (max-width: 379.799px) { .pv--7 { display: block; } }
  @container (min-width: 379.8px) and (max-width: 412.399px) { .pv--8 { display: block; } }
  @container (min-width: 412.4px) and (max-width: 443.399px) { .pv--9 { display: block; } }
  @container (min-width: 443.4px) and (max-width: 480.799px) { .pv--10 { display: block; } }
  @container (min-width: 480.8px) and (max-width: 523.199px) { .pv--11 { display: block; } }
  @container (min-width: 523.2px) and (max-width: 573.599px) { .pv--12 { display: block; } }
  @container (min-width: 573.6px) and (max-width: 617.099px) { .pv--13 { display: block; } }
  @container (min-width: 617.1px) and (max-width: 665.999px) { .pv--14 { display: block; } }
  @container (min-width: 666px) { .pv--15 { display: block; } }
}

.glance { display: grid; gap: .85rem; margin-top: 1.25rem; }
@container (min-width: 46rem) { .glance { grid-template-columns: repeat(3, 1fr); } }   /* #profile is the container */
.glance li {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: .5rem;
  padding: 1.05rem 1.2rem;
  border-radius: var(--radius-sm);
}
.glance .icon { flex: none; width: 1.45rem; height: 1.45rem; color: var(--mark); }
.glance strong { display: block; font-size: .72rem; letter-spacing: .12em; text-transform: uppercase; color: var(--ink-mute); }
.glance span   { display: block; margin-top: .15rem; color: var(--ink); font-weight: 600; line-height: 1.4; text-wrap: balance; }


/* 7. Work experience ------------------------------------------------------ */

.jump { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem; margin: -.4rem 0 1.5rem; }
.jump span { font-size: .85rem; color: var(--ink-mute); margin-right: .15rem; }
@media (max-width: 35.999rem) { .jump { justify-content: center; } .jump span { flex: 0 0 100%; text-align: center; } .jump a { min-height: 2.75rem; } }   /* "Jump to:" on its own line, centred chips below, 44px tall */
.jump a {
  display: inline-flex;
  align-items: center;
  min-height: 2.4rem;
  padding: .4rem 1rem;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: linear-gradient(180deg, rgb(255 255 255 / .10), transparent), var(--surface);
  box-shadow: inset 0 1px 0 var(--hl);
  color: var(--ink);
  font-size: .85rem;
  font-weight: 600;
  text-decoration: none;
  transition: border-color .2s, color .2s, box-shadow .2s;
}
.jump a:hover {
  border-color: color-mix(in srgb, var(--accent) 55%, transparent);
  color: var(--accent);
  box-shadow: inset 0 1px 0 var(--hl), 0 8px 18px -10px color-mix(in srgb, var(--accent) 70%, transparent);
}

.job + .job { margin-top: 1.4rem; }
.job { container: job / inline-size; }          /* layouts below follow the card's own width (the desktop sidebar takes 20rem of the viewport) */

.job-head {
  display: grid;
  grid-template-columns: auto 1fr;
  align-items: center;
  gap: .4rem 1rem;
  padding-bottom: 1.2rem;
  border-bottom: 1px solid var(--line);
}
.job-head h3 { font-size: 1.35rem; line-height: 1.25; color: var(--ink); }
.job-role  { color: var(--ink); font-weight: 600; }
.job-dates { grid-column: 1 / -1; font-size: .88rem; color: var(--ink-mute); }
.job-dates time { white-space: nowrap; }
.job-head .logo-tile { width: 8.4rem; }   /* same width for all three employers */
@container job (max-width: 35.999rem) {
  .job-head { grid-template-columns: minmax(0, 1fr); }
  .job-head .logo-tile { justify-self: start; }
}
@container job (min-width: 44rem) {
  .job-head { grid-template-columns: auto 1fr auto; }
  .job-dates {
    grid-column: auto;
    padding: .38rem .9rem;
    border-radius: 999px;
    background: linear-gradient(180deg, rgb(255 255 255 / .10), transparent), var(--surface-alt);
    border: 1px solid color-mix(in srgb, var(--mark) 40%, var(--line));
    box-shadow: inset 0 1px 0 var(--hl);
    color: var(--ink-soft);
    text-align: right;
  }
}

.job .chips { margin-top: 1.2rem; }

.job-group { margin-top: 1.6rem; }
.job-group h4 {
  margin-bottom: .8rem;
  font: 700 .74rem/1.3 var(--font-sans);
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--accent);
}
@container job (min-width: 44rem) {
  .job-group .bullets { column-count: 2; column-gap: 3rem; }
}


/* 8. Expertise ------------------------------------------------------------ */

.expertise { display: grid; grid-template-columns: minmax(0, 1fr); gap: 2.25rem; }
@media (min-width: 52rem) { .expertise { grid-template-columns: 1fr 1fr; gap: 3rem; } }

.donuts { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1.75rem .75rem; }

.donut { display: grid; justify-items: center; gap: .75rem; text-align: center; }
.donut-chart {
  --size: 7rem;
  --thick: .72rem;
  --pp: var(--p);                       /* final values; the animation below starts from 0 */
  --nn: var(--p);
  position: relative;
  isolation: isolate;
  width: min(var(--size), 100%);
  aspect-ratio: 1;
}
.donut-chart::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background: conic-gradient(var(--meter-a), var(--meter-b) calc(var(--pp) * 1%), var(--track) 0);
  -webkit-mask: radial-gradient(farthest-side, transparent calc(100% - var(--thick)), #000 calc(100% - var(--thick) + 1px));
          mask: radial-gradient(farthest-side, transparent calc(100% - var(--thick)), #000 calc(100% - var(--thick) + 1px));
}
.donut-chart::after {                                  /* soft halo behind the ring (not masked, so it is not clipped) */
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: 50%;
  box-shadow: 0 0 .85rem .05rem color-mix(in srgb, var(--meter-a) 42%, transparent);
}
.donut-value {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  font: 700 1.4rem/1 var(--font-serif);
  color: var(--ink);
}
.donut-value::before { counter-reset: n var(--nn); content: counter(n) "%"; }   /* the number is drawn here (the label carries the accessible text) */
.donut-label { font-weight: 700; font-size: .92rem; color: var(--ink); line-height: 1.3; }

.meters { display: grid; gap: 1.05rem; }
.meter {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: .4rem .75rem;
  align-items: baseline;
}
.meter-name  { color: var(--ink); font-weight: 600; font-size: .95rem; }
.meter-value { color: var(--ink-mute); font-size: .88rem; font-variant-numeric: tabular-nums; }
.meter-track {
  grid-column: 1 / -1;
  height: .6rem;
  border-radius: 999px;
  background: var(--track);
  box-shadow: inset 0 1px 2px rgb(0 0 0 / .25);
  overflow: hidden;
}
.meter-fill {
  position: relative;
  display: block;
  height: 100%;
  width: calc(var(--v) * 1%);
  border-radius: inherit;
  background: linear-gradient(90deg, var(--meter-a), var(--meter-b));
  box-shadow: 0 0 14px color-mix(in srgb, var(--meter-a) 55%, transparent);
}
.meter-fill::after {                                   /* glossy top highlight */
  content: "";
  position: absolute;
  inset: 0 0 52% 0;
  border-radius: inherit;
  background: linear-gradient(180deg, rgb(255 255 255 / .42), rgb(255 255 255 / .05));
}

/* Scroll-in animation. When the Expertise card scrolls into view the donuts sweep
   round (their numbers count up) and the bars fill from the left, one after
   another, over about a second and a half. A scroll-driven animation only flips
   a switch (--seen) as the card enters; the sweep itself is timed, so it looks
   the same however fast the visitor scrolls. No script. Browsers without these
   features simply show the final values. It deliberately runs even when the
   device asks for reduced motion (the site owner's choice); the avatar ring and
   name shimmer still stop.                                                    */
@keyframes donut-in       { from { --pp: 0; --nn: 0; } }
@keyframes bar-in         { from { width: 0; } }
@keyframes expertise-seen { from { --seen: 0; } to { --seen: 1; } }

@supports (animation-timeline: view()) {
  .expertise {
    --seen: 1;                                      /* default = finished charts; the animation below sets 0 until the card is reached */
    animation: expertise-seen linear both;
    animation-timeline: view();
    animation-range: entry 12% entry 13%;
  }

  @container style(--seen: 0) {                    /* waiting: charts empty while the card is off-screen */
    .donut-chart { --pp: 0; --nn: 0; }
    .meter-fill  { width: 0; }
  }
  @container style(--seen: 1) {                    /* seen: play the timed sweep */
    .donut-chart, .meter-fill {
      animation-duration: 1.5s;
      animation-timing-function: cubic-bezier(.2, .7, .2, 1);
      animation-fill-mode: both;
      animation-delay: calc(var(--i, 0) * .14s);
    }
    .donut-chart { animation-name: donut-in; }
    .meter-fill  { animation-name: bar-in; }
  }

  .donut:nth-child(1), .meter:nth-child(1) { --i: 0; }
  .donut:nth-child(2), .meter:nth-child(2) { --i: 1; }
  .donut:nth-child(3), .meter:nth-child(3) { --i: 2; }
  .donut:nth-child(4), .meter:nth-child(4) { --i: 3; }
  .meter:nth-child(5) { --i: 4; }
  .meter:nth-child(6) { --i: 5; }
}


/* 9. Technical skills ----------------------------------------------------- */

.skill-row { display: grid; gap: 1rem; padding-block: 1.5rem; border-top: 1px solid var(--line); }
.skill-row:first-child { padding-top: 0; border-top: 0; }
.skill-row:last-child  { padding-bottom: 0; }
#technicalskills > .card { container: skills / inline-size; }
@container skills (min-width: 46rem) {
  .skill-row { grid-template-columns: 10.5rem 1fr; gap: 1.75rem; }
}

.skill-row h3 {
  display: flex;
  align-items: flex-start;
  gap: .6rem;
  font-size: 1rem;
  line-height: 1.35;
  color: var(--ink);
}
.skill-row h3 .icon { margin-top: .15rem; width: 1.1rem; height: 1.1rem; color: var(--mark); }   /* beats the brand colour */

/* Tiles: one size everywhere, rows balanced and centred - using plain percentages only.
   The Technical Skills card (named container "skills") decides --M, the most tiles that fit
   in a row (a tile is never smaller than --tile: 5.75rem on phones, 6.75rem from 40rem).
   Every list says how many tiles it has (--n); where round() exists the row is balanced:
   --c = ceil(n / ceil(n / M)), so 6 tiles at M = 5 become 3 + 3 instead of 5 + 1.
   A list of --c tiles is centred by percentage padding of (M - c) * (width + gap) / (2M) on each
   side, and each tile is (list width - gaps) / c wide - which is exactly the width M tiles would
   have, so every tile in every list is the same size. No container units are used for sizing.
   Breakpoints: n * tile + (n - 1) * .65rem, plus 12.25rem for the label column when it sits
   beside the tiles (card >= 46rem).                                                          */
.tiles {
  --M: 3;                                                 /* most tiles per row (set below) */
  --c: var(--M);                                          /* tiles per row after balancing */
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: flex-start;
  gap: .65rem;
  min-width: 0;
  padding-inline: calc((var(--M) - var(--c)) * (100% + .65rem) / (2 * var(--M)));
}
.tiles > .tile {
  flex: 0 0 calc((100% - (var(--c) - 1) * .65rem) / var(--c) - .5px);   /* half a pixel of slack: rounding can never push the last tile of a row onto the next line */
  min-width: 0;
}
@media (min-width: 40rem) { .tiles { --M: 5; } }          /* fallbacks by viewport (used where container queries are missing) */
@media (min-width: 64rem) { .tiles { --M: 6; } }
@supports (width: round(up, 1.5px, 1px)) {
  .tiles { --c: round(up, calc(var(--n, 1) / round(up, calc(var(--n, 1) / var(--M)), 1)), 1); }
}

@media (max-width: 39.999rem) {                            /* --tile = 5.75rem */
  @container skills (max-width: 12.1499rem) { .tiles { --M: 1; } }
  @container skills (min-width: 12.15rem) { .tiles { --M: 2; } }
  @container skills (min-width: 18.55rem) { .tiles { --M: 3; } }
  @container skills (min-width: 24.95rem) { .tiles { --M: 4; } }
  @container skills (min-width: 31.35rem) { .tiles { --M: 5; } }
  @container skills (min-width: 37.75rem) { .tiles { --M: 6; } }
}
@media (min-width: 40rem) {                               /* --tile = 6.75rem */
  @container skills (max-width: 14.1499rem) { .tiles { --M: 1; } }
  @container skills (min-width: 14.15rem) { .tiles { --M: 2; } }
  @container skills (min-width: 21.55rem) { .tiles { --M: 3; } }
  @container skills (min-width: 28.95rem) { .tiles { --M: 4; } }
  @container skills (min-width: 36.35rem) { .tiles { --M: 5; } }
  @container skills (min-width: 43.75rem) { .tiles { --M: 6; } }
  @container skills (min-width: 46rem) { .tiles { --M: 4; } }
  @container skills (min-width: 48.6rem) { .tiles { --M: 5; } }
  @container skills (min-width: 56rem) { .tiles { --M: 6; } }
  @container skills (min-width: 63.4rem) { .tiles { --M: 7; } }
  @container skills (min-width: 70.8rem) { .tiles { --M: 8; } }
}

.tile {
  position: relative;
  display: grid;
  aspect-ratio: 148 / 167;
  overflow: hidden;
  border: 1px solid color-mix(in srgb, var(--ink) 14%, transparent);   /* dark hairline in light, pale in dark */
  border-radius: var(--radius-sm);
  background: #fff;
  color: #17233a;
  box-shadow: 0 6px 16px -8px rgb(0 0 0 / .45);
  transition: transform .25s cubic-bezier(.2, .7, .2, 1), box-shadow .25s, border-color .25s;
}
.tile::after {                                         /* soft gloss over the top-left corner */
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(155deg, rgb(255 255 255 / .55), transparent 38%, rgb(13 26 45 / .05));
  pointer-events: none;
}
.tile:hover {
  transform: translateY(-3px);
  border-color: var(--mark);
  box-shadow: 0 16px 30px -10px color-mix(in srgb, var(--accent) 45%, rgb(0 0 0 / .5)), 0 0 0 1px var(--mark);
}
.tile > img { width: 100%; height: 100%; object-fit: contain; padding: .3rem; box-sizing: border-box; }   /* baked-in logos never touch the edge */

/* Tile without an embedded label: glyph or small logo + caption */
.tile--icon {
  grid-template-rows: 1fr 1.95rem;                 /* the caption zone is always two lines tall, so an icon never moves when a caption wraps */
  place-items: center;
  padding: .7rem .25rem .6rem;
  text-align: center;
}
.tile--icon .icon { width: 2.6rem; height: 2.6rem; }
.tile--icon .icon--mysql { transform: scale(1.2); }   /* the wordmark is wide and light: give it the same optical weight as its neighbours */
.tile--icon > img { width: 2.7rem; height: 2.7rem; object-fit: contain; padding: 0; }

/* Badge tiles, for technologies without a good logo (the .NET family): one shape and one
   type style, so the group looks even. Colour hints the family: .NET purple, NLog orange,
   log4net red. The label sits in a rounded square; two-line labels use a smaller size.   */
.tmark {
  --tm-a: #7a58ee; --tm-b: #512bd4; --tm-fs: .98rem;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  width: 2.7rem; height: 2.7rem;
  border-radius: .8rem;
  background: linear-gradient(150deg, var(--tm-a), var(--tm-b));
  color: #fff;
  font: 800 var(--tm-fs)/1.05 var(--font-sans);
  letter-spacing: -.02em;
  text-align: center;
  box-shadow: inset 0 1px 0 rgb(255 255 255 / .38), 0 8px 14px -8px var(--tm-b);
}
.tmark--2 { --tm-fs: .76rem; line-height: 1.08; }
.tmark--sm { --tm-fs: .8rem; letter-spacing: -.03em; }
.tmark--nlog { --tm-a: #ffb84d; --tm-b: #f08a0c; color: #2b1500; }
.tmark--l4n { --tm-a: #d83a42; --tm-b: #a3141e; }
.tmark--iis { --tm-a: #1f6fd0; --tm-b: #0a4fa8; }
.tmark--us  { --tm-a: #0f78c0; --tm-b: #02558f; }
.tile--icon span:last-child {
  font-size: .8rem;
  font-weight: 700;
  line-height: 1.2;
}


/* 9b. AI ------------------------------------------------------------------ */

.section-lede { margin: -.7rem 0 1.4rem; color: var(--ink-mute); }
.section-lede, .edu p, .cert p, .ai p, .job-dates, .job-group h4, .job-role, .job-head h3 { text-wrap: balance; }   /* short copy: even lines, no stranded word */

/* Five tiles: 5 across on wide sections, 3 on tablets, 2 on phones. Flex rows
   are centred, so a short last row sits in the middle instead of hanging left.
   (Container query: the section's own width decides, with or without sidebar.) */
#ai { container-type: inline-size; }

.ai-grid { --gap: 1.1rem; display: flex; flex-wrap: wrap; justify-content: center; gap: var(--gap); }

.ai {
  --ai: #d97757;
  flex: 0 0 calc((100% - var(--gap)) / 2);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: .9rem;
  padding: 1.4rem .9rem 1.3rem;
  text-align: center;
}
@container (min-width: 36rem) { .ai { flex-basis: calc((100% - var(--gap) * 2) / 3); } }
@container (min-width: 56rem) { .ai { flex-basis: calc((100% - var(--gap) * 4) / 5); } }

.ai--claude  { --ai: #d97757; }
.ai--chatgpt { --ai: #10a37f; }
.ai--gemini  { --ai: #5b8def; }
.ai--kimi    { --ai: #0ea5c6; }
.ai--glm     { --ai: #7c5cf0; }

/* Logo sits on a white glossy tile (the OpenAI and Z.ai marks are black). The
   tile's glow takes the tool's tint.                                         */
.ai-mark {
  display: grid;
  place-items: center;
  flex: none;
  width: 4.5rem; height: 4.5rem;
  border-radius: 1.2rem;
  border: 1px solid rgb(255 255 255 / .6);
  background: linear-gradient(155deg, #fff 0%, #fff 55%, #eef1f6 100%);
  box-shadow: inset 0 1px 0 #fff, 0 14px 28px -12px var(--ai), 0 0 0 1px color-mix(in srgb, var(--ai) 22%, transparent);
  transition: transform .25s cubic-bezier(.2, .7, .2, 1);
}
.ai-mark img { width: 2.6rem; height: 2.6rem; object-fit: contain; }
/* Kimi's logo is a white "K" meant for a dark backing, so this one tile is dark. */
.ai--kimi .ai-mark {
  background: linear-gradient(155deg, #34343d 0%, #0d0d12 100%);
  border-color: rgb(255 255 255 / .38);
  box-shadow: inset 0 1px 0 rgb(255 255 255 / .22), 0 14px 28px -12px var(--ai), 0 0 0 1px color-mix(in srgb, var(--ai) 60%, transparent);
}
.ai:hover .ai-mark { transform: translateY(-3px) scale(1.04); }
.ai > div { min-width: 0; }
.ai h3 { font-size: 1.15rem; line-height: 1.2; color: var(--ink); }
.ai p  { margin-top: .15rem; font-size: .88rem; line-height: 1.35; color: var(--ink-mute); }


/* 10. Education + certifications ----------------------------------------- */

.edu-grid, .cert-grid { display: grid; gap: 1.1rem; }
.cert-grid { grid-template-columns: repeat(auto-fill, minmax(min(100%, max(19rem, 30%)), 1fr)); }   /* at most 3 across, so 6 cards never become 4 + 2 */
.cert .earned { display: block; }

/* Two education cards side by side only when the section itself is wide enough
   (container query, so it works with or without the sidebar). */
#education { container-type: inline-size; }
@container (min-width: 48rem) { .edu-grid { grid-template-columns: 1fr 1fr; } }

.edu, .cert { display: flex; align-items: center; gap: 1.15rem; }
.edu { flex-direction: column; justify-content: center; gap: .9rem; }   /* logo above the details, both centred on the card */
.edu > div, .cert > div { flex: 1 1 8rem; min-width: 0; }
.edu > div { flex: 0 1 auto; max-width: 24rem; text-align: center; }
.edu .meta time { white-space: nowrap; }     /* dates break between the two months, never inside one */
.cert { align-items: flex-start; }           /* card titles line up across the row */
.cert > div { align-self: stretch; display: flex; flex-direction: column; }
.cert .edu-link { margin-top: auto; align-self: flex-start; }   /* links line up along the bottom of the row */
.edu h3, .cert h3 { font-size: 1.05rem; line-height: 1.3; color: var(--ink); }
.edu p, .cert p   { font-size: .92rem; line-height: 1.5; }
.edu .meta, .cert .meta { margin-top: .15rem; color: var(--ink-mute); }
.edu-link { display: inline-block; margin-top: .15rem; padding-block: .3rem; font-size: .9rem; font-weight: 600; }

.edu .logo-tile { --h: 3.75rem; --pad: .45rem; }
.edu .logo-tile img { max-width: 8.5rem; }
.badge { flex: none; width: 5.25rem; height: 5.25rem; }
.badge img { width: 100%; height: 100%; object-fit: contain; filter: drop-shadow(0 8px 12px rgb(0 0 0 / .28)); }
.cert .badge { width: 5rem; height: 5rem; }


/* 11. Footer, back-to-top, tracking pixel -------------------------------- */

.site-footer {
  grid-column: 2;
  padding: 2rem 1rem 2.5rem;
  background: linear-gradient(90deg, transparent, var(--mark), transparent) top / 100% 1px no-repeat;
  color: var(--ink-mute);
  font-size: .88rem;
  text-align: center;
}
@media (min-width: 64rem) { .site-footer { padding-inline: 3rem; } }
@media (max-width: 35.999rem) { .site-footer .sep { display: none; } .site-footer p a { display: block; padding-block: .5rem; } }   /* phones: name, then e-mail */

.to-top {
  position: fixed;
  right: 1rem; bottom: 4.6rem;                     /* sits above the theme switch */
  z-index: 30;
  display: grid;
  place-items: center;
  width: 3rem; height: 3rem;
  border-radius: 50%;
  border: 1px solid color-mix(in srgb, var(--mark) 70%, transparent);
  background: linear-gradient(180deg, rgb(255 255 255 / .28), transparent 55%), var(--grad-accent);
  color: var(--accent-ink);
  font-size: 1.25rem;
  font-weight: 700;
  line-height: 1;
  text-decoration: none;
  box-shadow: inset 0 1px 0 rgb(255 255 255 / .45), 0 12px 26px -8px color-mix(in srgb, var(--accent) 70%, rgb(0 0 0 / .6));
  transition: transform .2s, box-shadow .2s;
}
.to-top:hover { transform: translateY(-3px); }
@media (min-width: 64rem) { .to-top { right: 2rem; bottom: 5.6rem; } }

/* Light / dark switch: a real checkbox (keyboard + screen-reader friendly) drawn as a round
   button. It flips the device's theme for this visit; no JavaScript. It stays hidden in
   browsers that cannot do it (no :has()), where it would do nothing.                          */
.theme-flip { display: none; }
@supports selector(:has(*)) {
  .theme-flip {
    display: block;
    -webkit-appearance: none;
            appearance: none;
    position: fixed;
    right: 1rem; bottom: 1rem;
    z-index: 35;
    width: 2.9rem; height: 2.9rem;
    margin: 0; padding: 0;
    border: 1px solid rgb(232 41 74 / .6);
    border-radius: 50%;
    background:
      var(--theme-icon) center / 1.4rem no-repeat,
      linear-gradient(180deg, rgb(255 255 255 / .16), transparent 55%),
      var(--side-bg);
    box-shadow: inset 0 1px 0 rgb(255 255 255 / .25), 0 12px 26px -8px rgb(0 0 0 / .6);
    cursor: pointer;
    transition: transform .2s, box-shadow .2s;
  }
  .theme-flip:hover { transform: translateY(-3px); box-shadow: inset 0 1px 0 rgb(255 255 255 / .3), 0 16px 30px -8px rgb(0 0 0 / .7); }
}
@media (min-width: 64rem) { .theme-flip { right: 2rem; bottom: 2rem; } }
@supports not selector(:has(*)) { .to-top { bottom: 1rem; } }
@media (min-width: 64rem) { @supports not selector(:has(*)) { .to-top { bottom: 2rem; } } }

/* Where supported, only show the button once the page has been scrolled. */
@supports (animation-timeline: scroll()) {
  .to-top {
    opacity: 0;
    visibility: hidden;
    animation: to-top-in linear both;
    animation-timeline: scroll(root block);
    animation-range: 12rem 22rem;
  }
  @keyframes to-top-in { to { opacity: 1; visibility: visible; } }
}

.pixel { position: absolute; left: 0; bottom: 0; width: 1px; height: 1px; opacity: 0; pointer-events: none; }


/* 12. Accessibility modes + print ---------------------------------------- */

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .avatar-ring, .masthead h1 { animation: none; }
  *, *::before, *::after { transition-duration: .01ms !important; }
}

/* Windows High Contrast etc.: drop decorative gradients, keep real text. */
@media (forced-colors: active) {
  .masthead h1 {
    background: none;
    -webkit-text-fill-color: CanvasText;
    color: CanvasText;
    animation: none;
  }
  .pv .dropcap { fill: CanvasText; }
  .card::before, .card::after, .glance li::before, .glance li::after, .tile::after { display: none; }
  .meter-track, .meter-fill, .tile, .card, .chips li { border: 1px solid CanvasText; }
  .ai-mark, .tile, .logo-tile { forced-colors-adjust: none; }   /* logos are drawn for their own backing */
  .sidebar, .masthead, .mbar, .mnav-sheet { background-image: none; }
}

@media print {
  :root {                                                   /* beats the dark-theme tokens even after the theme switch was flipped */
    color-scheme: light !important;
    --bg: #fff !important; --surface: #fff !important; --surface-alt: #f3f3f3 !important;
    --ink: #000 !important; --ink-soft: #222 !important; --ink-mute: #444 !important; --line: #bbb !important; --track: #ddd !important;
    --accent: #c8102e !important; --link: #b00d28 !important; --mark: #c8102e !important; --meter-a: #c8102e !important; --meter-b: #ff6b81 !important;
  }
  html { scroll-behavior: auto; }
  body { background: #fff; font-size: 10.5pt; }
  body::before, body::after { display: none; }

  .toc, .mbar, .mnav, .mnav-anchor, .to-top, .theme-flip, .skip-link, .pixel, .jump, .sidebar-foot { display: none !important; }

  .shell { display: block; }
  .sidebar { display: block; position: static; height: auto; padding: 0 0 1rem; background: none; color: #000; border: 0; box-shadow: none; }
  .masthead { display: flex; padding: 0 0 1rem; background: none; color: #000; }
  .masthead h1, .role, .tagline, .contact a { color: #000; }
  .masthead h1 { background: none; -webkit-text-fill-color: #000; animation: none; }
  .avatar-ring { background: none; box-shadow: none; padding: 0; animation: none; }
  .avatar { width: 4.5rem; height: 4.5rem; border: 0; }

  main { padding: 0; }
  .card, .glance li { background: #fff; box-shadow: none; break-inside: avoid; }
  .card::before, .card::after, .glance li::before, .glance li::after, .tile::after { display: none; }
  .donut-chart, .meter-fill { animation: none !important; }
  .donut-chart { --pp: var(--p) !important; --nn: var(--p) !important; }   /* paper never shows an empty chart */
  .meter-fill  { width: calc(var(--v) * 1%) !important; }
  .donut-chart::before, .meter-track, .meter-fill, .bullets li::before, .chips li, .tmark, .tile, .ai-mark { -webkit-print-color-adjust: exact; print-color-adjust: exact; }   /* charts are backgrounds: ask the browser to print them */
  .pv { display: none !important; }                       /* paper gets the real paragraph */
  .prose-text { position: static !important; width: auto; height: auto; margin: 0; overflow: visible; clip: auto; clip-path: none; white-space: normal; }
  .prose-col:first-child .prose-text::first-letter { color: #000; }
  .job { break-inside: auto; }
  .job-group, .skill-row, .cert, .edu { break-inside: avoid; }
  .section-title { break-after: avoid; }
  .section-title::after { display: none; }
  .site-footer { padding: 1rem 0 0; background: none; }
  a { color: #000; text-decoration: none; }
}
