/* ==========================================================================
   Rathakrishnan Nagilan — Portfolio
   styles.css

   Direction taken from two references: an editorial monochrome layout with
   hairline grid divisions, and a dark portfolio hero with a cyan accent and
   a full-height photo bleeding off the right edge.

   The photo is masked into the background rather than framed — that is the
   move both references share, and it is what makes the page feel composed
   rather than assembled from boxes.

   Contents
   01. Tokens
   02. Reset & base
   03. Utilities
   04. Background
   05. Buttons
   06. Header / navigation
   07. Hero + bleeding photo
   08. Sections
   09. About
   10. Skills
   11. Experience
   12. Certifications
   13. Contact
   14. Footer
   15. Lightbox
   16. Scroll reveal
   17. Responsive
   18. Reduced motion & print
   ========================================================================== */


/* ==========================================================================
   01. TOKENS
   ========================================================================== */
:root {
  /* Matte charcoal with a blue cast — flatter and less saturated than a
     true blue-black, so surfaces read as unlit material rather than glass */
  --c-bg:   #070B12;
  --c-bg-1: #0B111C;
  --c-bg-2: #101827;
  --c-bg-3: #16202F;

  /* Matte steel blue. Desaturated on purpose: a bright cyan reads glossy,
     which is exactly what "matte" rules out. 5.7:1 on --c-bg. */
  --c-acc:      #22A7F0;
  --c-acc-2:    #5CC0F5;   /* hover / highlight step */
  --c-acc-soft: rgba(34, 167, 240, 0.12);
  --c-acc-line: rgba(34, 167, 240, 0.38);

  --c-hi:    #FFFFFF;
  --c-text:  #DCE3ED;
  --c-muted: #94A1B4;   /* 6.9:1 on --c-bg */
  /* Panels are lighter than the page, so faint text has to clear 4.5:1
     against the panel, not just the background. #77828F measured 4.38:1 on
     the panel surface; this measures 4.86:1 there and 5.1:1 on the page. */
  --c-faint: #808B98;

  --c-line:   rgba(220, 227, 237, 0.09);
  --c-line-2: rgba(220, 227, 237, 0.18);

  --f-display: 'Space Grotesk', system-ui, -apple-system, 'Segoe UI', sans-serif;
  --f-body:    'Inter', system-ui, -apple-system, 'Segoe UI', sans-serif;
  --f-mono:    'JetBrains Mono', ui-monospace, 'SF Mono', Menlo, monospace;

  --fs-display: clamp(2.6rem, 1.4rem + 5vw, 5.6rem);
  --fs-h2:      clamp(1.7rem, 1.3rem + 1.8vw, 2.6rem);
  --fs-h3:      clamp(1.05rem, 1rem + 0.4vw, 1.25rem);
  --fs-lead:    clamp(1rem, 0.95rem + 0.3vw, 1.14rem);
  --fs-body:    1rem;
  --fs-sm:      0.9375rem;
  --fs-xs:      0.8125rem;
  --fs-2xs:     0.75rem;

  --s-1: .25rem; --s-2: .5rem; --s-3: .75rem; --s-4: 1rem;
  --s-5: 1.5rem; --s-6: 2rem;  --s-7: 3rem;   --s-8: 4rem; --s-9: 6rem;

  --section-y: clamp(4.5rem, 3rem + 6.5vw, 8.5rem);
  --container: 1280px;
  --gutter:    clamp(1.25rem, 0.9rem + 1.8vw, 3rem);

  --r-sm: 6px; --r-md: 10px; --r-lg: 14px; --r-pill: 999px;

  /* Matte shadows: broad, soft and low-contrast. No coloured glow anywhere —
     a glow is a specular highlight, which a matte surface does not produce. */
  --sh-1: 0 2px 6px rgba(0, 0, 0, 0.28);
  --sh-2: 0 14px 34px rgba(0, 0, 0, 0.36);
  --sh-3: 0 30px 64px rgba(0, 0, 0, 0.44);
  --glow: 0 0 40px rgba(34, 167, 240, 0.35);

  --d-fast: 160ms; --d-mid: 300ms; --d-slow: 560ms;
  --e-out:    cubic-bezier(0.22, 1, 0.36, 1);
  --e-spring: cubic-bezier(0.34, 1.32, 0.64, 1);

  --z-canvas:  1;
  --z-photo:   2;
  --z-content: 3;
  --z-header:  40;
  --z-lightbox: 100;
}


/* ==========================================================================
   02. RESET & BASE
   ========================================================================== */
*, *::before, *::after { box-sizing: border-box; }

html { scroll-behavior: smooth; scroll-padding-top: 6rem; -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  min-height: 100dvh;
  background: var(--c-bg);
  color: var(--c-muted);
  font-family: var(--f-body);
  font-size: var(--fs-body);
  line-height: 1.7;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}
body.is-locked { overflow: hidden; }

h1, h2, h3 {
  margin: 0;
  font-family: var(--f-display);
  color: var(--c-hi);
  line-height: 1.06;
  font-weight: 700;
  letter-spacing: -0.03em;
}

p { margin: 0 0 var(--s-4); }
p:last-child { margin-bottom: 0; }
a { color: inherit; text-decoration: none; }
ul, ol { margin: 0; padding: 0; list-style: none; }
img, canvas, svg { display: block; max-width: 100%; }
img { height: auto; }
button { font: inherit; color: inherit; background: none; border: 0; cursor: pointer; }

:focus-visible { outline: 2px solid var(--c-acc); outline-offset: 3px; border-radius: var(--r-sm); }
::selection { background: var(--c-acc); color: #04131F; }


/* ==========================================================================
   03. UTILITIES
   ========================================================================== */
.sr-only {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

.skip-link {
  position: absolute; top: -100%; left: var(--s-4); z-index: 200;
  padding: var(--s-3) var(--s-5);
  background: var(--c-acc); color: #04131F;
  font-weight: 600; border-radius: 0 0 var(--r-sm) var(--r-sm);
  transition: top var(--d-fast) var(--e-out);
}
.skip-link:focus { top: 0; }

.container { width: 100%; max-width: var(--container); margin-inline: auto; padding-inline: var(--gutter); }

.icon { width: 17px; height: 17px; flex: none; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }


/* ==========================================================================
   04. BACKGROUND
   Flat and dark, as in both references. The canvas carries only a faint
   drift of particles — the photo and the type are meant to hold the eye.
   ========================================================================== */
/* --- Three 3D objects from the subject's own world -------------------------
   A network globe, a code editor, and a stack of switches. Each is a
   preserve-3d container whose children sit on different planes.

   Only `transform` and `opacity` animate, and nothing is blurred or
   filtered — the previous background animated a 90px blur across a
   full-screen layer, which the compositor re-rasterised every frame and was
   the main cause of the input lag.
   -------------------------------------------------------------------------- */
/* Each object is anchored inside the section it belongs to, not to a
   fixed full-screen layer. A fixed layer meant all three floated over every
   section at once — including directly behind the name, which is what made
   the hero look cluttered.

   Sections clip their own overflow so nothing spills into the next one. */
main > section { overflow: hidden; }

.shape {
  position: absolute;
  z-index: 0;                 /* below .hero-inner (3) and section content */
  pointer-events: none;
  transform-style: preserve-3d;
  will-change: transform;
  opacity: 0.42;              /* background weight, not foreground */
}

/* Section content must always sit above the decoration */
.section > .container { position: relative; z-index: 1; }

/* ==========================================================================
   1. NETWORK GLOBE — upper right
   Four meridians rotated about Y plus three latitude ellipses. Because they
   share one preserve-3d parent, spinning the parent turns the whole cage as
   a solid rather than sliding flat rings past each other.
   ========================================================================== */
/* Far right of the hero, behind the photo (which is z-index 2). The name
   occupies the left half, so the two never overlap. */
.shape-globe {
  top: 16%; right: 4%;
  width: 230px; height: 230px;
  opacity: 0.3;
  animation: globe-spin 30s linear infinite;
}

.shape-globe .meridian {
  position: absolute; inset: 0;
  border: 1px solid rgba(34, 167, 240, 0.30);
  border-radius: 50%;
}
.shape-globe .meridian:nth-child(1) { transform: rotateY(0deg); }
.shape-globe .meridian:nth-child(2) { transform: rotateY(45deg); }
.shape-globe .meridian:nth-child(3) { transform: rotateY(90deg); }
.shape-globe .meridian:nth-child(4) { transform: rotateY(135deg); }

/* Latitudes are flattened circles pushed up and down the polar axis */
.shape-globe .latitude {
  position: absolute; left: 0; right: 0;
  border: 1px solid rgba(220, 227, 237, 0.14);
  border-radius: 50%;
}
.lat-a { top: 24%; height: 52%; transform: rotateX(90deg) translateZ(52px); }
.lat-b { top: 0;   height: 100%; transform: rotateX(90deg); }
.lat-c { top: 24%; height: 52%; transform: rotateX(90deg) translateZ(-52px); }

/* Two nodes orbiting the cage — the "traffic" on the network */
.shape-globe .sat {
  position: absolute; top: 50%; left: 50%;
  width: 7px; height: 7px; margin: -3.5px;
  border-radius: 50%;
  background: var(--c-acc);
  box-shadow: 0 0 12px rgba(34, 167, 240, 0.9);
}
.sat-1 { animation: orbit-1 9s linear infinite; }
.sat-2 { animation: orbit-2 13s linear infinite; }

@keyframes globe-spin {
  from { transform: rotateX(-16deg) rotateY(0deg); }
  to   { transform: rotateX(-16deg) rotateY(360deg); }
}
@keyframes orbit-1 {
  from { transform: rotateY(0deg)   translateZ(105px); }
  to   { transform: rotateY(360deg) translateZ(105px); }
}
@keyframes orbit-2 {
  from { transform: rotateX(70deg) rotateY(0deg)   translateZ(105px); }
  to   { transform: rotateX(70deg) rotateY(-360deg) translateZ(105px); }
}


/* ==========================================================================
   2. CODE EDITOR — mid left
   A window tilted in 3D, with a title bar and syntax-coloured line stubs.
   The caret line sweeps down as if the file were being typed.
   ========================================================================== */
.shape-editor {
  top: var(--section-y); right: 4%;
  width: 250px;
  border: 1px solid rgba(34, 167, 240, 0.22);
  border-radius: 8px;
  background: rgba(11, 17, 28, 0.55);
  overflow: hidden;
  animation: editor-float 16s ease-in-out infinite alternate;
}

.editor-bar {
  display: flex; align-items: center; gap: 6px;
  padding: 8px 10px;
  border-bottom: 1px solid rgba(220, 227, 237, 0.10);
  background: rgba(16, 24, 39, 0.7);
}
.editor-bar i {
  width: 7px; height: 7px; border-radius: 50%;
  background: rgba(220, 227, 237, 0.22);
}
.editor-bar i:first-child { background: rgba(34, 167, 240, 0.55); }

.editor-body { display: block; padding: 12px 10px 14px; }

/* Each line is a gutter number stub plus one or two token bars */
.code-line {
  display: flex; align-items: center; gap: 6px;
  height: 7px; margin-bottom: 9px;
}
.code-line.indent  { padding-left: 14px; }
.code-line.indent2 { padding-left: 28px; }

.code-line b {
  width: 8px; height: 3px; border-radius: 2px;
  background: rgba(220, 227, 237, 0.16);   /* gutter */
}
.code-line u {
  height: 5px; border-radius: 2px;
  background: rgba(220, 227, 237, 0.16);
  width: 46px;
}
.code-line u.t-key { width: 30px; background: rgba(34, 167, 240, 0.60); }
.code-line u.t-fn  { width: 54px; background: rgba(220, 227, 237, 0.34); }
.code-line u.t-str { width: 62px; background: rgba(92, 192, 245, 0.42); }
.code-line u.t-num { width: 20px; background: rgba(34, 167, 240, 0.38); }

/* Typing sweep: a highlight travelling down the lines */
.code-line:nth-child(1) { animation: type-line 6s ease-in-out infinite; animation-delay: 0s; }
.code-line:nth-child(2) { animation: type-line 6s ease-in-out infinite; animation-delay: .35s; }
.code-line:nth-child(3) { animation: type-line 6s ease-in-out infinite; animation-delay: .7s; }
.code-line:nth-child(4) { animation: type-line 6s ease-in-out infinite; animation-delay: 1.05s; }
.code-line:nth-child(5) { animation: type-line 6s ease-in-out infinite; animation-delay: 1.4s; }
.code-line:nth-child(6) { animation: type-line 6s ease-in-out infinite; animation-delay: 1.75s; }

@keyframes type-line {
  0%, 100% { opacity: 0.5; }
  8%       { opacity: 1; }
  40%      { opacity: 0.65; }
}
@keyframes editor-float {
  from { transform: perspective(900px) rotateY(19deg) rotateX(7deg) translateY(0); }
  to   { transform: perspective(900px) rotateY(9deg)  rotateX(-4deg) translateY(-22px); }
}


/* ==========================================================================
   3. SWITCH STACK — lower right
   Three rack units seen in perspective, port LEDs blinking out of sync the
   way a live switch actually looks.
   ========================================================================== */
.shape-rack {
  top: var(--section-y); right: 5%;
  width: 180px; height: 130px;
  animation: rack-turn 24s ease-in-out infinite alternate;
}

.shape-rack .unit {
  position: absolute; left: 0;
  display: flex; align-items: center; gap: 7px;
  width: 100%; height: 30px;
  padding: 0 12px;
  border: 1px solid rgba(34, 167, 240, 0.26);
  border-radius: 4px;
  background: rgba(16, 24, 39, 0.5);
}
.shape-rack .unit:nth-child(1) { top: 0;    transform: translateZ(22px); }
.shape-rack .unit:nth-child(2) { top: 42px; transform: translateZ(0); }
.shape-rack .unit:nth-child(3) { top: 84px; transform: translateZ(-22px); }

.shape-rack .led {
  width: 5px; height: 5px; border-radius: 1px;
  background: rgba(34, 167, 240, 0.75);
  animation: led-blink 2.4s steps(1, end) infinite;
}
/* Prime-ish offsets so no two LEDs ever settle into the same rhythm */
.shape-rack .led:nth-child(1) { animation-delay: .0s; }
.shape-rack .led:nth-child(2) { animation-delay: .7s; }
.shape-rack .led:nth-child(3) { animation-delay: .3s; }
.shape-rack .led:nth-child(4) { animation-delay: 1.3s; }
.shape-rack .led:nth-child(5) { animation-delay: .9s; }
.shape-rack .led:nth-child(6) { animation-delay: 1.9s; }
.shape-rack .led:nth-child(7) { animation-delay: .5s; }
.shape-rack .led:nth-child(8) { animation-delay: 1.6s; }

@keyframes led-blink {
  0%, 40%  { opacity: 1; }
  41%, 70% { opacity: 0.18; }
  71%      { opacity: 1; }
}
@keyframes rack-turn {
  from { transform: perspective(900px) rotateX(16deg) rotateY(-26deg); }
  to   { transform: perspective(900px) rotateX(9deg)  rotateY(-13deg); }
}


/* Below 1100px the section headings widen into the margin these sit in, so
   they would land behind text. Hidden rather than shrunk — decoration that
   collides with copy is worse than no decoration. */
/* On wide screens the timeline and the contact rows are capped so the right
   margin the decorations sit in is genuinely empty. Neither needs the full
   1280px anyway — a single work entry and four short contact rows read
   better at a measured width. */
@media (min-width: 1101px) {
  .timeline,
  .stack-contact { max-width: 68ch; }
}

/* Below that the content widens back out into this margin, so the objects
   would land behind copy. Hidden rather than shrunk — decoration that
   collides with text is worse than no decoration. */
@media (max-width: 1100px) {
  .shape-editor, .shape-rack { display: none; }
}
@media (max-width: 900px) {
  .shape-globe { display: none; }
}

/* Cursor trail. Sits above the page but below the header and lightbox, and
   never intercepts input. */
#trail-canvas {
  position: fixed; inset: 0; z-index: 20;
  width: 100%; height: 100%;
  pointer-events: none;
}

/* .bg-grade removed: the tinted radial wash was the "colour matting", and a
   flat background also means one less full-screen layer to composite. */

/* Hairline vertical rules, from the editorial reference */
.bg-grain {
  position: fixed; inset: 0; z-index: 0;
  pointer-events: none;
  background-image:
    linear-gradient(to right, var(--c-line) 1px, transparent 1px),
    linear-gradient(to right, var(--c-line) 1px, transparent 1px);
  background-size: 100% 100%, 100% 100%;
  background-position: 22% 0, 78% 0;
  background-repeat: no-repeat;
  opacity: 0.6;
}

.site-footer { position: relative; z-index: var(--z-content); }
main > section { position: relative; z-index: var(--z-content); }
main > .hero { z-index: auto; }


/* ==========================================================================
   05. BUTTONS
   ========================================================================== */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--s-3);
  min-height: 52px; padding: 0 var(--s-6);
  border-radius: var(--r-sm);
  font-family: var(--f-body); font-size: var(--fs-sm); font-weight: 600;
  transition: transform var(--d-fast) var(--e-out),
              background-color var(--d-mid) var(--e-out),
              border-color var(--d-mid) var(--e-out),
              color var(--d-mid) var(--e-out),
              box-shadow var(--d-mid) var(--e-out);
}

.btn-solid { background: var(--c-acc); color: #04131F; box-shadow: var(--glow); }
.btn-solid:hover { transform: translateY(-2px); box-shadow: var(--sh-2); }
.btn-solid:active { transform: translateY(0) scale(0.99); }

.btn-line { border: 1px solid var(--c-acc); color: var(--c-acc); background: transparent; }
.btn-line:hover { background: var(--c-acc-soft); transform: translateY(-2px); }
.btn-line:active { transform: translateY(0) scale(0.99); }


/* ==========================================================================
   06. HEADER / NAVIGATION
   ========================================================================== */
.site-header {
  position: fixed; top: 0; left: 0; right: 0; z-index: var(--z-header);
  border-bottom: 1px solid transparent;
  transition: background-color var(--d-mid) var(--e-out), border-color var(--d-mid) var(--e-out);
}
.site-header.is-stuck {
  background: rgba(7, 11, 18, 0.82);
  backdrop-filter: blur(18px);
  -webkit-backdrop-filter: blur(18px);
  border-bottom-color: var(--c-line);
}

.nav {
  display: flex; align-items: center; justify-content: space-between; gap: var(--s-4);
  width: 100%; max-width: var(--container); margin-inline: auto;
  padding: var(--s-5) var(--gutter);
}

.brand {
  display: inline-flex; align-items: center; gap: var(--s-3);
  min-height: 44px;
  font-family: var(--f-display); font-weight: 700;
  font-size: 1.15rem; letter-spacing: -0.02em;
  color: var(--c-hi);
}
.brand-mark { width: 9px; height: 9px; border-radius: 50%; background: var(--c-acc); box-shadow: var(--glow); }

.nav-menu { display: flex; align-items: center; gap: var(--s-2); }

.nav-link {
  display: inline-flex; align-items: center; min-height: 44px; padding: 0 var(--s-4);
  color: var(--c-muted); font-size: var(--fs-sm); font-weight: 500;
  transition: color var(--d-mid) var(--e-out);
}
.nav-link:hover { color: var(--c-hi); }
.nav-link.is-active { color: var(--c-acc); }

.nav-cta {
  display: inline-flex; align-items: center; min-height: 42px;
  margin-left: var(--s-3); padding: 0 var(--s-5);
  border: 1px solid var(--c-acc); border-radius: var(--r-sm);
  color: var(--c-acc); font-size: var(--fs-sm); font-weight: 600;
  transition: background-color var(--d-mid) var(--e-out);
}
.nav-cta:hover { background: var(--c-acc-soft); }

.nav-toggle {
  display: none; flex-direction: column; justify-content: center; gap: 6px;
  width: 46px; height: 46px; padding: 0 12px;
  border: 1px solid var(--c-line-2); border-radius: var(--r-sm);
}
.nav-toggle-bar { display: block; height: 2px; width: 100%; border-radius: 2px; background: var(--c-hi); transition: transform var(--d-mid) var(--e-out); }
.nav-toggle.is-open .nav-toggle-bar:nth-child(1) { transform: translateY(4px) rotate(45deg); }
.nav-toggle.is-open .nav-toggle-bar:nth-child(2) { transform: translateY(-4px) rotate(-45deg); }


/* ==========================================================================
   07. HERO + BLEEDING PHOTO
   ========================================================================== */
.hero {
  position: relative;
  display: flex; align-items: center;
  min-height: 100dvh;
  padding-top: clamp(6.5rem, 5rem + 6vw, 9rem);
  padding-bottom: var(--s-8);
  overflow: hidden;              /* the photo runs off the edge */
}

/* --- The photo ------------------------------------------------------------
   Anchored to the right edge, full height, and masked so it dissolves into
   the background on its left and bottom. No frame, no border, no card. */
.hero-photo {
  position: absolute;
  top: 0; right: 0; bottom: 0;
  z-index: var(--z-photo);
  width: min(56%, 860px);
  pointer-events: none;
  will-change: transform;
}

.hero-photo img {
  width: 100%; height: 100%;
  object-fit: cover;
  object-position: 50% 22%;
  filter: grayscale(1) contrast(1.16) brightness(0.82);

  /* Two masks intersected: fade on the left, fade at the bottom.
     The bottom fade runs over 42% with three stops rather than a straight
     ramp — a short linear fade still leaves a visible edge because the eye
     picks up the sudden change in gradient slope, not the gradient itself.
     -webkit-mask-composite uses the older keyword set, so both are set. */
  -webkit-mask-image:
    linear-gradient(to right, transparent 0%, #000 34%, #000 100%),
    linear-gradient(to top, transparent 0%, rgba(0,0,0,0.35) 14%, rgba(0,0,0,0.85) 30%, #000 46%, #000 100%);
  -webkit-mask-composite: source-in;
  mask-image:
    linear-gradient(to right, transparent 0%, #000 34%, #000 100%),
    linear-gradient(to top, transparent 0%, rgba(0,0,0,0.35) 14%, rgba(0,0,0,0.85) 30%, #000 46%, #000 100%);
  mask-composite: intersect;
}

/* Belt and braces: a wash in the page colour over the bottom of the photo.
   If mask-composite is unsupported the mask silently does nothing, and this
   is what still hides the hard edge. */
.hero-photo::after {
  content: '';
  position: absolute; inset: auto 0 0 0;
  height: 46%;
  background: linear-gradient(to top, var(--c-bg) 4%, rgba(7, 11, 18, 0.72) 34%, transparent 100%);
  pointer-events: none;
}

/* Accent rim light across the photo — the cyan edge from the reference */
.hero-photo-light {
  position: absolute; inset: 0;
  background:
    linear-gradient(115deg, transparent 42%, rgba(34, 167, 240, 0.26) 62%, transparent 78%),
    radial-gradient(40% 50% at 78% 34%, rgba(34, 167, 240, 0.18), transparent 70%);
  mix-blend-mode: screen;
  -webkit-mask-image: linear-gradient(to right, transparent 0%, #000 38%, #000 100%);
          mask-image: linear-gradient(to right, transparent 0%, #000 38%, #000 100%);
  pointer-events: none;
}

.hero-inner { position: relative; z-index: var(--z-content); }
.hero-copy  { max-width: min(52ch, 56%); }

.kicker {
  display: inline-flex; align-items: center; gap: var(--s-3);
  margin-bottom: var(--s-6);
  color: var(--c-faint);
  font-family: var(--f-mono); font-size: var(--fs-2xs);
  letter-spacing: 0.24em; text-transform: uppercase;
}
.kicker-line { width: 34px; height: 1px; background: var(--c-acc); }

.hero-greet {
  margin-bottom: var(--s-2);
  color: var(--c-muted);
  font-size: var(--fs-lead);
  font-weight: 400;
}

.hero-title {
  margin-bottom: var(--s-3);
  font-size: var(--fs-display);
  line-height: 0.98;
}
.hero-title-line { display: block; }

/* --- Name animation --------------------------------------------------------
   Each letter rises out of its own line box. The line clips, so the letters
   appear to be pushed up from below rather than fading in place.
   .is-split is only added once JS has done the splitting, so the plain text
   stays visible if the script never runs. */
.hero-title.is-split .hero-title-line {
  overflow: hidden;
  padding-bottom: 0.08em;   /* room for descenders inside the clip */
}
.hero-title.is-split .char {
  display: inline-block;
  transform: translateY(105%) rotate(3deg);
  opacity: 0;
  animation: char-rise 760ms var(--e-spring) forwards;
}
/* Spaces would otherwise collapse once the letters become inline-block */
.hero-title.is-split .char:not(:first-child) { white-space: pre; }

@keyframes char-rise {
  to { transform: translateY(0) rotate(0); opacity: 1; }
}

/* The accent line under the name, as in the reference */
.hero-role {
  margin-bottom: var(--s-5);
  color: var(--c-acc);
  font-family: var(--f-display);
  font-size: clamp(1.15rem, 0.95rem + 1vw, 1.9rem);
  font-weight: 700;
  letter-spacing: -0.02em;
}

.hero-summary { max-width: 50ch; margin-bottom: var(--s-6); font-size: var(--fs-lead); color: var(--c-muted); }

.hero-actions { display: flex; flex-wrap: wrap; gap: var(--s-4); margin-bottom: var(--s-8); }

/* --- Social circles, bottom left ------------------------------------------ */
.social-row { display: flex; gap: var(--s-3); }
.social {
  display: grid; place-items: center;
  width: 44px; height: 44px;
  border: 1px solid var(--c-line-2); border-radius: 50%;
  color: var(--c-muted);
  transition: color var(--d-mid) var(--e-out),
              border-color var(--d-mid) var(--e-out),
              transform var(--d-fast) var(--e-out),
              box-shadow var(--d-mid) var(--e-out);
}
.social:hover { color: var(--c-acc); border-color: var(--c-acc); transform: translateY(-3px); box-shadow: var(--glow); }
.social svg { width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }

/* --- Editorial slide counter ---------------------------------------------- */
.hero-count {
  position: absolute; z-index: var(--z-content);
  right: var(--gutter); bottom: var(--s-6);
  margin: 0;
  color: var(--c-hi);
  font-family: var(--f-mono); font-size: 1.1rem; letter-spacing: 0.08em;
}
.hero-count span { color: var(--c-faint); }

.scroll-cue {
  position: absolute; z-index: var(--z-content);
  left: 50%; bottom: var(--s-6); transform: translateX(-50%);
  display: grid; place-items: center; width: 44px; height: 44px;
}
.scroll-cue-track { position: relative; width: 1px; height: 36px; background: var(--c-line-2); overflow: hidden; }
.scroll-cue-dot { position: absolute; left: 0; width: 1px; height: 14px; background: var(--c-acc); animation: cue 2.2s var(--e-out) infinite; }
@keyframes cue {
  0%   { transform: translateY(-16px); opacity: 0; }
  40%  { opacity: 1; }
  100% { transform: translateY(36px); opacity: 0; }
}


/* ==========================================================================
   08. SECTIONS
   ========================================================================== */
.section { padding-block: var(--section-y); }

.section-head {
  max-width: 62ch;
  margin-bottom: clamp(2.25rem, 1.6rem + 2.4vw, 3.5rem);
  padding-top: var(--s-5);
  border-top: 1px solid var(--c-line);
}
.section-index {
  display: block; margin-bottom: var(--s-3);
  color: var(--c-acc);
  font-family: var(--f-mono); font-size: var(--fs-2xs); letter-spacing: 0.24em;
}
.section-title {
  font-size: var(--fs-h2);
  margin-bottom: var(--s-3);
  overflow: hidden;          /* clips the rise below */
  padding-bottom: 0.06em;
}
.section-sub { margin-bottom: 0; color: var(--c-muted); font-size: var(--fs-lead); }

/* --- Section title animation on scroll -------------------------------------
   The heading is pushed up out of its own box as the section arrives, with
   a rule drawing itself underneath. Driven by .is-visible on the header, so
   it uses the same observer as everything else. */
.reveal-ready .section-head[data-reveal] .section-title {
  display: block;
  transform: translateY(100%);
  transition: transform 760ms var(--e-spring);
  transition-delay: 90ms;
}
.reveal-ready .section-head[data-reveal].is-visible .section-title {
  transform: translateY(0);
}

.section-head { position: relative; }
.reveal-ready .section-head[data-reveal]::after {
  content: '';
  position: absolute; left: 0; top: 0;
  width: 100%; height: 1px;
  background: var(--c-acc);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 900ms var(--e-out);
}
.reveal-ready .section-head[data-reveal].is-visible::after { transform: scaleX(1); }


/* ==========================================================================
   09. ABOUT
   ========================================================================== */
.about-grid { display: grid; grid-template-columns: 1.35fr 0.65fr; gap: clamp(2rem, 1.2rem + 3vw, 4.5rem); align-items: start; }
.about-copy { max-width: 60ch; }
.lead { font-size: var(--fs-lead); color: var(--c-text); font-weight: 500; }

.facts { display: grid; margin: 0; }
.fact { display: flex; flex-wrap: wrap; justify-content: space-between; gap: var(--s-3); padding-block: var(--s-4); border-bottom: 1px solid var(--c-line); }
.fact:first-child { border-top: 1px solid var(--c-line); }
.fact dt { color: var(--c-faint); font-family: var(--f-mono); font-size: var(--fs-2xs); letter-spacing: 0.14em; text-transform: uppercase; }
.fact dd { margin: 0; color: var(--c-text); font-size: var(--fs-sm); font-weight: 500; text-align: right; }


/* ==========================================================================
   10. SKILLS & CONTACT ROWS
   ========================================================================== */
/* --------------------------------------------------------------------------
   ROWS
   Capabilities and Get in touch are no longer boxes. Each entry is a
   full-width row divided by a hairline: a large index, the title, and the
   detail pushed to the right. On hover a dark frosted wash slides in from
   the left and the row shifts — the emphasis moves along the row rather
   than lifting a card off the page.
   -------------------------------------------------------------------------- */
.stack { border-top: 1px solid var(--c-line); }

.row {
  position: relative;
  display: grid;
  grid-template-columns: 4.5rem minmax(0, 1fr) minmax(0, 1.15fr);
  align-items: start;
  gap: var(--s-5);
  padding: var(--s-6) var(--s-5);
  border-bottom: 1px solid var(--c-line);
  isolation: isolate;
  transition: background-color var(--d-mid) var(--e-out);
}

/* Wash that wipes across on hover.
   No backdrop-filter: a blur that re-samples everything behind it on every
   pointer move is expensive, and with seven rows on screen it showed. A
   plain gradient reads the same and costs nothing. */
.row::before {
  content: '';
  position: absolute; inset: 0;
  z-index: -1;
  background: linear-gradient(90deg, rgba(34, 167, 240, 0.12), rgba(34, 167, 240, 0.03) 55%, transparent);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform var(--d-slow) var(--e-out);
}
.row:hover::before,
.row:focus-within::before { transform: scaleX(1); }

/* Accent bar on the left edge */
.row::after {
  content: '';
  position: absolute; left: 0; top: 0; bottom: 0;
  width: 2px; background: var(--c-acc);
  transform: scaleY(0); transform-origin: top;
  transition: transform var(--d-mid) var(--e-out);
}
.row:hover::after,
.row:focus-within::after { transform: scaleY(1); }

.row-index {
  font-family: var(--f-mono);
  font-size: var(--fs-sm);
  color: var(--c-faint);
  letter-spacing: 0.12em;
  transition: color var(--d-mid) var(--e-out);
}
.row:hover .row-index { color: var(--c-acc); }

.row-title { font-size: var(--fs-h3); margin-bottom: var(--s-2); }
.row-desc  { margin: 0; font-size: var(--fs-sm); color: var(--c-muted); }

.row-tags { display: flex; flex-wrap: wrap; gap: var(--s-2); align-content: flex-start; }
.row-tags li {
  padding: 5px var(--s-3);
  border: 1px solid var(--c-line);
  border-radius: var(--r-sm);
  color: var(--c-muted);
  font-family: var(--f-mono); font-size: var(--fs-2xs);
  transition: color var(--d-fast) var(--e-out), border-color var(--d-fast) var(--e-out);
}
.row-tags li:hover { color: var(--c-acc); border-color: var(--c-acc-line); }

/* --- Contact rows --------------------------------------------------------- */
.stack-contact .row { grid-template-columns: 9rem minmax(0, 1fr) auto; align-items: center; padding-block: var(--s-5); }
.stack-contact .row > a {
  display: contents;      /* the anchor spans the row without altering layout */
}
.row-label {
  color: var(--c-faint);
  font-family: var(--f-mono); font-size: var(--fs-2xs);
  letter-spacing: 0.16em; text-transform: uppercase;
}
.row-value {
  color: var(--c-text);
  font-family: var(--f-display); font-size: var(--fs-h3); font-weight: 500;
  word-break: break-word;
}
.row-arrow {
  display: grid; place-items: center;
  width: 40px; height: 40px;
  border: 1px solid var(--c-line); border-radius: 50%;
  color: var(--c-muted);
  transition: transform var(--d-mid) var(--e-out),
              color var(--d-mid) var(--e-out),
              border-color var(--d-mid) var(--e-out);
}
.row-arrow svg { width: 17px; height: 17px; fill: none; stroke: currentColor; stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }
.row-link:hover .row-arrow { transform: translateX(6px); color: var(--c-acc); border-color: var(--c-acc); }

/* The location row is not a link — it must not signal that it is */
.row-static::before, .row-static::after { display: none; }
.row-static { cursor: default; }

/* .card / .tags removed with the box layout — rows use .row-* instead */


/* ==========================================================================
   11. EXPERIENCE
   ========================================================================== */
.timeline-item { display: grid; grid-template-columns: 22px 1fr; gap: var(--s-5); }
.timeline-rail { position: relative; display: flex; justify-content: center; }
.timeline-rail::before { content: ''; position: absolute; top: 12px; bottom: 0; width: 1px; background: linear-gradient(to bottom, var(--c-acc-line), transparent); }
.timeline-node { width: 9px; height: 9px; margin-top: 8px; border-radius: 50%; background: var(--c-acc); box-shadow: var(--glow); }

.timeline-body { padding-left: 0; }
.timeline-period { margin-bottom: var(--s-2); color: var(--c-acc); font-family: var(--f-mono); font-size: var(--fs-2xs); letter-spacing: 0.12em; }
.timeline-role { font-size: var(--fs-h3); margin-bottom: var(--s-1); }
.timeline-org { margin-bottom: var(--s-4); color: var(--c-muted); font-size: var(--fs-sm); }
.timeline-points { display: grid; gap: var(--s-3); }
.timeline-points li { position: relative; padding-left: var(--s-5); font-size: var(--fs-sm); color: var(--c-muted); }
.timeline-points li::before { content: ''; position: absolute; left: 0; top: 0.75em; width: 10px; height: 1px; background: var(--c-acc-line); }


/* ==========================================================================
   12. CERTIFICATIONS
   Image-led tiles. The certificate fills the whole tile and the caption sits
   on a frosted veil over the bottom of it, rather than in a strip beneath —
   the tile is the image, not a box containing one.
   ========================================================================== */
.cert-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: var(--s-4);
}

.cert-card,
.cert-pending {
  position: relative;
  display: block;
  width: 100%;
  aspect-ratio: 4 / 3;
  padding: 0;
  border: 1px solid var(--c-line);
  border-radius: var(--r-lg);
  background: var(--c-bg-1);
  overflow: hidden;
  text-align: left;
  isolation: isolate;
  transition:
    transform var(--d-mid) var(--e-out),
    border-color var(--d-mid) var(--e-out),
    box-shadow var(--d-mid) var(--e-out);
}
.cert-card:hover,
.cert-card:focus-visible {
  transform: translateY(-5px);
  border-color: var(--c-acc-line);
  box-shadow: var(--sh-2);
}

.cert-media {
  position: absolute; inset: 0;
  display: block;
  padding: var(--s-5) var(--s-5) 5rem;
  background: var(--c-bg-2);
}
/* contain, not cover: these run from 4:3 to a 9:16 phone screenshot, and
   cropping would cut the substance out of the tall one */
.cert-media img {
  width: 100%; height: 100%;
  object-fit: contain;
  filter: grayscale(1) brightness(0.82) contrast(1.05);
  transition: transform var(--d-slow) var(--e-out), filter var(--d-mid) var(--e-out);
}
.cert-card:hover .cert-media img,
.cert-card:focus-visible .cert-media img {
  transform: scale(1.04);
  filter: grayscale(0) brightness(1) contrast(1);
}

/* Frosted veil carrying the caption — dark blur, no gloss */
.cert-veil {
  position: absolute; inset: auto 0 0 0;
  height: 62%;
  background: linear-gradient(to top, rgba(7, 11, 18, 0.94) 22%, rgba(7, 11, 18, 0.72) 52%, transparent);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  -webkit-mask-image: linear-gradient(to top, #000 55%, transparent);
          mask-image: linear-gradient(to top, #000 55%, transparent);
  pointer-events: none;
}

.cert-info {
  position: absolute; inset: auto 0 0 0;
  display: flex; flex-direction: column; gap: var(--s-2);
  padding: var(--s-5);
  transition: transform var(--d-mid) var(--e-out);
}
.cert-card:hover .cert-info { transform: translateY(-2px); }

.cert-name {
  color: var(--c-hi);
  font-family: var(--f-display); font-size: var(--fs-sm); font-weight: 600;
  line-height: 1.4;
}
.cert-badge {
  align-self: flex-start;
  padding: 3px var(--s-3);
  border: 1px solid var(--c-line-2); border-radius: var(--r-sm);
  background: rgba(7, 11, 18, 0.6);
  color: var(--c-muted);
  font-family: var(--f-mono); font-size: var(--fs-2xs);
}
.cert-badge-pending { border-color: var(--c-acc-line); color: var(--c-acc); }

/* Expand affordance, top right */
.cert-open {
  position: absolute; top: var(--s-4); right: var(--s-4);
  display: grid; place-items: center;
  width: 36px; height: 36px;
  border: 1px solid var(--c-line-2); border-radius: 50%;
  background: rgba(7, 11, 18, 0.72);
  backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px);
  color: var(--c-text);
  opacity: 0; transform: scale(0.9);
  transition: opacity var(--d-mid) var(--e-out), transform var(--d-mid) var(--e-out);
}
.cert-open svg { width: 15px; height: 15px; fill: none; stroke: currentColor; stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }
.cert-card:hover .cert-open,
.cert-card:focus-visible .cert-open { opacity: 1; transform: scale(1); }

/* --- In-progress tile ----------------------------------------------------- */
.cert-pending {
  border-style: dashed;
  background: transparent;
  display: flex; flex-direction: column; justify-content: flex-end;
  padding: var(--s-5);
}
.cert-pending .cert-info { position: static; padding: 0; }
.cert-pending-ring {
  position: absolute; top: var(--s-5); left: var(--s-5);
  width: 34px; height: 34px; border-radius: 50%;
  border: 1px dashed var(--c-acc-line);
}
.cert-pending-note {
  margin-top: var(--s-3);
  color: var(--c-faint);
  font-family: var(--f-mono); font-size: var(--fs-2xs); line-height: 1.6;
}


/* ==========================================================================
   13. CONTACT
   ========================================================================== */
.contact-cta { display: flex; justify-content: center; margin-top: var(--s-7); }


/* ==========================================================================
   14. FOOTER
   ========================================================================== */
.site-footer { padding-block: var(--s-7); border-top: 1px solid var(--c-line); }
.footer-inner { text-align: center; }
.footer-name { margin-bottom: var(--s-1); color: var(--c-hi); font-family: var(--f-display); font-weight: 700; }
.footer-meta { margin-bottom: var(--s-3); font-size: var(--fs-sm); color: var(--c-muted); }
.footer-copy { margin-bottom: 0; font-family: var(--f-mono); font-size: var(--fs-2xs); color: var(--c-faint); }


/* ==========================================================================
   15. LIGHTBOX
   ========================================================================== */
.lightbox { position: fixed; inset: 0; z-index: var(--z-lightbox); display: grid; place-items: center; padding: var(--gutter); }
.lightbox[hidden] { display: none; }

.lightbox-scrim {
  position: absolute; inset: 0;
  background: rgba(3, 5, 9, 0.92);
  backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px);
  animation: fade-in var(--d-mid) var(--e-out);
}
@keyframes fade-in { from { opacity: 0; } to { opacity: 1; } }

.lightbox-panel { position: relative; width: min(100%, 1040px); max-height: 90dvh; animation: zoom-in var(--d-mid) var(--e-spring); }
@keyframes zoom-in { from { opacity: 0; transform: scale(0.95) translateY(10px); } to { opacity: 1; transform: scale(1) translateY(0); } }

.lightbox-figure { display: flex; flex-direction: column; gap: var(--s-4); margin: 0; }
.lightbox-img { width: 100%; max-height: 72dvh; object-fit: contain; border: 1px solid var(--c-line); border-radius: var(--r-md); background: var(--c-bg-1); }
.lightbox-caption { display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: var(--s-3); text-align: center; }
.lightbox-title { color: var(--c-hi); font-family: var(--f-display); font-size: var(--fs-h3); font-weight: 600; }
.lightbox-meta { padding: 3px var(--s-3); border: 1px solid var(--c-acc-line); border-radius: var(--r-sm); color: var(--c-acc); font-family: var(--f-mono); font-size: var(--fs-2xs); }

.lightbox-btn {
  position: absolute; display: grid; place-items: center;
  width: 48px; height: 48px; border-radius: 50%;
  border: 1px solid var(--c-line-2);
  background: rgba(11, 17, 28, 0.92); color: var(--c-text);
  transition: background-color var(--d-fast) var(--e-out), color var(--d-fast) var(--e-out);
}
.lightbox-btn:hover { background: var(--c-acc); color: #04131F; }
.lightbox-btn svg { width: 21px; height: 21px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }

.lightbox-close { top: -60px; right: 0; }
.lightbox-prev  { top: 50%; left: -60px;  transform: translateY(-50%); }
.lightbox-next  { top: 50%; right: -60px; transform: translateY(-50%); }


/* ==========================================================================
   16. SCROLL REVEAL
   ========================================================================== */
.reveal-ready [data-reveal] {
  opacity: 0; transform: translateY(24px);
  transition: opacity var(--d-slow) var(--e-out), transform var(--d-slow) var(--e-out);
  transition-delay: var(--reveal-delay, 0ms);
}
.reveal-ready [data-reveal].is-visible { opacity: 1; transform: none; }

/* Rows slide in from the left, in sequence — reads as a list being written
   rather than a set of cards fading up together.

   Deliberately NO clip-path here. It hid the section outright when the
   reveal did not fire: opacity and transform degrade to "slightly offset
   but readable", whereas a 100% inset clip degrades to nothing at all. */
.reveal-ready .row[data-reveal] {
  opacity: 0;
  transform: translateX(-26px);
  transition:
    opacity var(--d-slow) var(--e-out),
    transform var(--d-slow) var(--e-out);
  transition-delay: var(--reveal-delay, 0ms);
}
.reveal-ready .row[data-reveal].is-visible {
  opacity: 1;
  transform: none;
}

/* Tiles settle back into place in 3D */
.reveal-ready .cert-item[data-reveal] {
  opacity: 0;
  transform: perspective(1000px) translateY(34px) rotateX(8deg) scale(0.97);
  transform-origin: 50% 100%;
  transition:
    opacity var(--d-slow) var(--e-out),
    transform 720ms var(--e-spring);
  transition-delay: var(--reveal-delay, 0ms);
}
.reveal-ready .cert-item[data-reveal].is-visible {
  opacity: 1;
  transform: perspective(1000px) translateY(0) rotateX(0) scale(1);
}


/* ==========================================================================
   17. RESPONSIVE
   ========================================================================== */
@media (max-width: 1024px) {
  .about-grid { grid-template-columns: 1fr; }
  .hero-copy  { max-width: 62%; }
  .lightbox-prev { left: var(--s-2); }
  .lightbox-next { right: var(--s-2); }
}

@media (max-width: 960px) {
  .nav-toggle { display: flex; }
  .nav-menu {
    position: absolute; top: 100%; left: var(--gutter); right: var(--gutter);
    flex-direction: column; align-items: stretch; gap: var(--s-1);
    padding: var(--s-3);
    border: 1px solid var(--c-line); border-radius: var(--r-lg);
    background: rgba(7, 11, 18, 0.98);
    backdrop-filter: blur(20px); -webkit-backdrop-filter: blur(20px);
    box-shadow: var(--sh-3);
    opacity: 0; visibility: hidden; transform: translateY(-10px);
    transition: opacity var(--d-mid) var(--e-out), transform var(--d-mid) var(--e-out), visibility var(--d-mid);
  }
  .nav-menu.is-open { opacity: 1; visibility: visible; transform: translateY(0); }
  .nav-link, .nav-cta { justify-content: center; width: 100%; margin-left: 0; min-height: 48px; }
  .nav-cta { margin-top: var(--s-2); }
  .lightbox-close { top: -56px; }
}

/* Below this the two-column hero stops working: the photo moves behind the
   copy and drops in opacity so the text stays readable over it. */
@media (max-width: 860px) {
  .hero { padding-top: 7.5rem; }
  .hero-copy { max-width: 100%; }
  .hero-photo {
    width: 100%;
    opacity: 0.3;
  }
  .hero-photo img {
    object-position: 60% 18%;
    -webkit-mask-image: linear-gradient(to bottom, #000 0%, #000 45%, transparent 88%);
    -webkit-mask-composite: source-over;
    mask-image: linear-gradient(to bottom, #000 0%, #000 45%, transparent 88%);
    mask-composite: add;
  }
  .hero-photo-light { display: none; }
  .bg-grain { display: none; }
  .hero-count { display: none; }
}

/* Three columns in a row do not survive a narrow screen */
@media (max-width: 780px) {
  .row {
    grid-template-columns: 1fr;
    gap: var(--s-4);
    padding-inline: var(--s-4);
  }
  .row-index { font-size: var(--fs-2xs); }

  .stack-contact .row { grid-template-columns: 1fr auto; align-items: center; }
  .stack-contact .row-label { grid-column: 1; }
  .stack-contact .row-value { grid-column: 1; }
  .stack-contact .row-arrow { grid-column: 2; grid-row: 1 / span 2; }
}

@media (max-width: 560px) {
  .fact { flex-direction: column; gap: var(--s-1); }
  .fact dd { text-align: left; }
  .hero-actions { gap: var(--s-3); }
  .btn { width: 100%; }
  .lightbox-img { max-height: 60dvh; }
}

@media (max-height: 540px) and (orientation: landscape) {
  .hero { min-height: auto; padding-block: 7rem 3rem; }
  .scroll-cue, .hero-count { display: none; }
}


/* ==========================================================================
   18. REDUCED MOTION & PRINT
   ========================================================================== */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
  /* Nothing may be left mid-reveal: clip-path and 3D transforms must reset */
  .reveal-ready [data-reveal],
  .reveal-ready .row[data-reveal],
  .reveal-ready .cert-item[data-reveal] {
    opacity: 1;
    transform: none;
    clip-path: none;
  }
  .scroll-cue-dot { animation: none; }
  .hero-photo { transform: none !important; }

  /* The rotating solids are the largest motion on the page */
  .shape { animation: none; }

  /* Letters must never be left sitting below their clip */
  .hero-title.is-split .char { animation: none; opacity: 1; transform: none; }
  .reveal-ready .section-head[data-reveal] .section-title { transform: none; }
  .reveal-ready .section-head[data-reveal]::after { transform: scaleX(1); }
}

@media print {
  .shapes, #trail-canvas, .bg-grain,
  .site-header, .scroll-cue, .hero-count, .lightbox { display: none !important; }
  body { background: #fff; color: #000; }
  .hero-photo { position: static; width: 40%; opacity: 1; }
  .section { padding-block: 1.5rem; }
  h1, h2, h3 { color: #000; }
  .row, .cert-card, .cert-pending { border-color: #ccc; background: none; }
  .cert-veil, .cert-open { display: none; }
}
