/* ---------------------------------------------------------------------------
   Pedro Palavra — site styles
   The components below are CSS translations of the compiled design-system
   components (NavBar, Button, Label, SectionHeading, Tag, TextLink,
   ImageFrame, ProjectCard, FooterBlock). Structure, spacing and states follow
   the design system's own definitions; only the delivery changes (CSS classes
   instead of React inline styles).
   --------------------------------------------------------------------------- */

html{scroll-behavior:smooth}
html.is-intro{overflow:hidden}

/* Available to a screen reader and to a crawler, invisible on the page. */
.vh{
  position:absolute;width:1px;height:1px;
  margin:-1px;padding:0;border:0;
  clip:rect(0 0 0 0);clip-path:inset(50%);
  overflow:hidden;white-space:nowrap;
}

@media (prefers-reduced-motion:reduce){
  html{scroll-behavior:auto}
}

.page{position:relative;z-index:1;background:var(--surface-page)}

/* --- NavBar --------------------------------------------------------------- */

.nav{
  position:fixed;top:0;left:0;right:0;
  z-index:40;
  height:var(--nav-height);
  display:flex;align-items:center;justify-content:space-between;
  padding:0 var(--page-margin);
  background:var(--veil-light);
  -webkit-backdrop-filter:var(--blur-veil);
  backdrop-filter:var(--blur-veil);
  border-bottom:var(--border-width-hairline) solid var(--border-hairline);
  color:var(--ink-900);
  opacity:0;
  transition:opacity var(--dur-reveal) var(--ease-out),
             background var(--dur-base) var(--ease-out),
             color var(--dur-base) var(--ease-out),
             border-color var(--dur-base) var(--ease-out);
}
.nav.is-visible{opacity:1}
.nav.is-inverse{
  background:var(--veil-dark);
  color:var(--paper);
  border-bottom-color:var(--border-hairline-inverse);
}

.nav__wordmark{
  font-size:var(--size-body-s);
  font-weight:var(--weight-semibold);
  text-transform:uppercase;
  letter-spacing:0.2em;
  color:inherit;
}
.nav__wordmark:hover{color:inherit}

.nav__items{display:flex;align-items:center;gap:var(--space-6)}
.nav__items:hover .nav__item{opacity:0.45}
.nav__items:hover .nav__item:hover{opacity:1}

.nav__item{
  display:flex;align-items:baseline;gap:var(--space-2);
  color:inherit;
  font-size:var(--size-label);
  font-weight:var(--weight-medium);
  text-transform:uppercase;
  letter-spacing:var(--ls-label);
  opacity:0.75;
  transition:opacity var(--dur-fast) var(--ease-out);
}
.nav__item.is-active{opacity:1}
.nav__item:hover{color:inherit}
.nav__item span:first-child{border-bottom:1px solid transparent;padding-bottom:2px}
.nav__item.is-active span:first-child{border-bottom-color:currentColor}
.nav__item .num{
  font-family:var(--font-mono);
  font-weight:var(--weight-regular);
  opacity:0.55;
  letter-spacing:0;
}

@media (max-width:760px){
  .nav__items{gap:var(--space-4)}
}

/* --- the bar on a phone --------------------------------------------------

   Four labels and a wordmark cannot share a 360px bar without being shrunk
   until they are no longer readable, and a fixed bar that overflows is worse
   than one that wraps: what falls off the right edge cannot be scrolled to.

   So below 700px the bar carries the wordmark and one control, and the same
   four links move into a panel underneath it. The links are not duplicated,
   they are the same elements relaid out, so the active-section highlight and
   everything in page.js keep working untouched.

   The panel is the site's night surface: ink ground, paper type, hairlines
   between rows, and the numbers come back in the accent colour, the way the
   section labels carry them everywhere else. The rows are set at reading size
   with 48px of height, which is a thumb rather than a cursor.
   ------------------------------------------------------------------------ */

.nav__toggle{display:none}

@media (max-width:700px){
  .nav{padding:0 var(--space-4)}
  .nav__wordmark{white-space:nowrap}

  .nav__toggle{
    display:inline-flex;align-items:center;gap:var(--space-3);
    -webkit-appearance:none;appearance:none;
    background:none;border:0;padding:var(--space-3) 0;margin:0;
    color:inherit;cursor:pointer;
    font-family:var(--font-core);
    font-size:var(--size-label);
    font-weight:var(--weight-semibold);
    text-transform:uppercase;
    letter-spacing:var(--ls-label);
    line-height:1;
  }
  .nav__bars{display:block;width:18px;height:12px;position:relative}
  .nav__bars i{
    position:absolute;left:0;right:0;height:1.5px;background:currentColor;
    transition:transform var(--dur-fast) var(--ease-out),
               opacity var(--dur-fast) var(--ease-out);
  }
  .nav__bars i:first-child{top:2px}
  .nav__bars i:last-child{bottom:2px}
  .nav.is-open .nav__bars i:first-child{transform:translateY(3.25px) rotate(45deg)}
  .nav.is-open .nav__bars i:last-child{transform:translateY(-3.25px) rotate(-45deg)}

  /* the bar stops taking its colour from whatever is behind it once the
     panel is down, so the control never sits on two grounds at once */
  .nav.is-open{
    background:var(--ink-900);color:var(--paper);
    border-bottom-color:transparent;
    -webkit-backdrop-filter:none;backdrop-filter:none;
  }

  /* tap anywhere off the panel to close it */
  .nav.is-open::after{
    content:"";position:fixed;inset:var(--nav-height) 0 0;
    background:rgba(11,11,10,0.5);
    -webkit-backdrop-filter:var(--blur-veil);backdrop-filter:var(--blur-veil);
    z-index:-1;
  }

  .nav__items{
    position:fixed;left:0;right:0;top:var(--nav-height);
    flex-direction:column;align-items:stretch;gap:0;
    padding:var(--space-2) var(--space-4) var(--space-5);
    background:var(--ink-900);
    border-bottom:var(--border-width-hairline) solid var(--border-hairline-inverse);
    opacity:0;visibility:hidden;
    transform:translateY(-10px);
    transition:opacity var(--dur-base) var(--ease-out),
               transform var(--dur-base) var(--ease-out),
               visibility 0s linear var(--dur-base);
  }
  .nav.is-open .nav__items{
    opacity:1;visibility:visible;transform:none;
    transition-delay:0s,0s,0s;
  }
  /* the desktop bar dims its siblings on hover; on a panel that reads as a
     row being switched off, so it does not travel down here */
  .nav__items:hover .nav__item{opacity:1}

  .nav__item{
    justify-content:space-between;align-items:baseline;
    min-height:48px;padding:var(--space-3) 0;
    font-size:var(--size-heading-s);
    font-weight:var(--weight-medium);
    text-transform:none;
    letter-spacing:var(--ls-heading);
    color:var(--paper);
    opacity:1;
    border-bottom:var(--border-width-hairline) solid var(--border-hairline-inverse);
  }
  .nav__item:last-child{border-bottom:0}
  .nav__item span:first-child{border-bottom:0;padding-bottom:0}
  .nav__item.is-active span:first-child{border-bottom:0}
  .nav__item.is-active{color:var(--paper)}
  .nav__item .num{
    display:block;opacity:1;
    color:var(--signal-400);
    font-size:var(--size-label);
    letter-spacing:var(--ls-label);
  }
  .nav__item.is-active .num{color:var(--signal-500)}
}

/* the panel slides; with reduced motion it simply appears */
@media (max-width:700px) and (prefers-reduced-motion:reduce){
  .nav__items{transform:none;transition:opacity 1ms linear,visibility 0s linear 1ms}
  .nav__bars i{transition:none}
}

html.is-nav-open{overflow:hidden}

/* --- Label ---------------------------------------------------------------- */

.label{
  display:flex;align-items:baseline;gap:var(--space-3);
  color:var(--text-muted);
  font-size:var(--size-label);
  font-weight:var(--weight-semibold);
  text-transform:uppercase;
  letter-spacing:var(--ls-label);
  line-height:var(--lh-label);
}
.label--accent{color:var(--text-accent)}
.label--primary{color:var(--text-primary)}
.label .num{
  font-family:var(--font-mono);
  font-weight:var(--weight-regular);
  letter-spacing:var(--ls-meta);
  opacity:0.7;
}

/* --- Button --------------------------------------------------------------- */

.btn{
  display:inline-flex;align-items:center;justify-content:center;gap:var(--space-3);
  font-family:var(--font-core);
  font-size:var(--size-label);
  font-weight:var(--weight-semibold);
  text-transform:uppercase;
  letter-spacing:var(--ls-label);
  line-height:1;
  padding:15px 26px;
  border-radius:var(--radius-none);
  border:var(--border-width-hairline) solid transparent;
  background:none;
  cursor:pointer;
  white-space:nowrap;
  transition:background var(--dur-fast) var(--ease-out),
             color var(--dur-fast) var(--ease-out),
             border-color var(--dur-fast) var(--ease-out),
             transform var(--dur-fast) var(--ease-out);
}
.btn:active{transform:scale(var(--press-scale))}
.btn .glyph{transition:transform var(--dur-fast) var(--ease-out)}
.btn:hover .glyph{transform:translateX(3px)}

.btn--solid{background:var(--surface-inverse);color:var(--text-inverse);border-color:var(--surface-inverse)}
.btn--solid:hover{background:var(--surface-accent);border-color:var(--surface-accent);color:var(--text-inverse)}

.btn--accent{background:var(--surface-accent);color:var(--paper);border-color:transparent}
.btn--accent:hover{background:var(--signal-600);color:var(--paper)}

.btn--outline{background:transparent;color:var(--text-primary);border-color:var(--border-strong)}
.btn--outline:hover{background:var(--surface-inverse);color:var(--text-inverse)}

/* --- TextLink ------------------------------------------------------------- */

.tlink{
  display:inline-flex;align-items:baseline;gap:var(--space-2);
  color:var(--text-primary);
  border-bottom:1px solid transparent;
  padding-bottom:1px;
  transition:color var(--dur-fast) var(--ease-out),border-color var(--dur-fast) var(--ease-out);
}
.tlink:hover{border-bottom-color:currentColor;color:var(--text-link-hover)}
/* "inverse" here means "sits on ink" — every use of it in this site does.
   It cannot resolve --text-inverse, because inside [data-theme="night"] that
   token flips back to ink-900 and the link disappears into its own ground. */
.tlink--inverse{color:var(--paper)}
.tlink--inverse:hover{color:var(--signal-400)}
.tlink--sm{font-size:var(--size-body-s)}
.tlink .glyph{transition:transform var(--dur-fast) var(--ease-out)}
.tlink:hover .glyph{transform:translate(2px,-2px)}

/* --- Tag ------------------------------------------------------------------ */

.tag{
  display:inline-flex;align-items:center;
  padding:6px 10px 5px;
  font-family:var(--font-core);
  font-size:var(--size-label);
  font-weight:var(--weight-medium);
  text-transform:uppercase;
  letter-spacing:var(--ls-label);
  line-height:var(--lh-label);
  border-radius:var(--radius-none);
  color:var(--text-secondary);
  border:var(--border-width-hairline) solid var(--border-hairline);
  background:transparent;
}

/* --- SectionHeading ------------------------------------------------------- */

.heading{display:flex;flex-direction:column;gap:var(--space-5);align-items:flex-start}
.heading h2{
  margin:0;
  font-size:var(--size-display-m);
  font-weight:var(--weight-semibold);
  line-height:var(--lh-display);
  letter-spacing:var(--ls-display);
  text-transform:uppercase;
  text-wrap:balance;
}
.heading--l h2{font-size:var(--size-display-l)}
.heading p{
  margin:0;
  max-width:var(--measure-prose);
  font-size:var(--size-body-l);
  color:var(--text-secondary);
  text-wrap:pretty;
}

/* --- ImageFrame ----------------------------------------------------------- */

.frame{margin:0;display:flex;flex-direction:column;gap:var(--space-3)}
.frame__box{
  position:relative;
  overflow:hidden;
  aspect-ratio:var(--aspect-portrait);
  background:var(--surface-media);
  border-radius:var(--radius-none);
}
.frame--still .frame__box{aspect-ratio:var(--aspect-still)}
.frame--cinema .frame__box{aspect-ratio:21 / 10}
.frame--portrait .frame__box{aspect-ratio:var(--aspect-portrait)}
.frame__box img{
  width:100%;height:100%;object-fit:cover;
  transition:transform var(--dur-slow) var(--ease-out);
}

/* The work is colourful and the page should say so. The grid holds the colour
   back just enough to stay calm as a set of eight, and gives all of it to
   whichever project you are actually looking at. Photographs that are not a
   grid tile — the portrait, the project pages — are never held back. */
.pcard .frame__box img{
  filter:saturate(0.45) contrast(1.02);
  transition:filter var(--dur-base) var(--ease-out),transform var(--dur-slow) var(--ease-out);
}
.pcard:hover .frame__box img{
  filter:none;
  transform:scale(var(--media-zoom));
}
.frame__ph{
  position:absolute;inset:0;
  display:flex;align-items:flex-end;
  padding:var(--space-4);
  font-family:var(--font-mono);
  font-size:var(--size-meta);
  letter-spacing:var(--ls-meta);
  color:var(--text-muted);
  border:var(--border-width-hairline) solid var(--border-hairline);
}
.frame__idx{
  position:absolute;top:var(--space-4);left:var(--space-4);
  font-family:var(--font-mono);
  font-size:var(--size-meta);
  color:var(--text-muted);
}
.frame__box.has-img .frame__idx{color:var(--paper);text-shadow:0 1px 4px rgba(11,11,10,0.6)}
.frame figcaption{
  font-family:var(--font-mono);
  font-size:var(--size-meta);
  letter-spacing:var(--ls-meta);
  color:var(--text-muted);
}

/* --- ProjectCard ---------------------------------------------------------- */

.pcard{display:flex;flex-direction:column;gap:var(--space-4);color:var(--text-primary)}
.pcard:hover{color:var(--text-primary)}
.pcard__row{display:flex;align-items:baseline;justify-content:space-between;gap:var(--space-4)}
.pcard__title{
  font-size:var(--size-heading-s);
  font-weight:var(--weight-semibold);
  text-transform:uppercase;
  letter-spacing:0.02em;
  transition:color var(--dur-fast) var(--ease-out);
}
.pcard:hover .pcard__title{color:var(--text-link-hover)}
.pcard__year{font-family:var(--font-mono);font-size:var(--size-meta);color:var(--text-muted);white-space:nowrap}
.pcard__blurb{
  margin:0;
  max-width:52ch;
  font-size:var(--size-body-s);
  line-height:var(--lh-body);
  color:var(--text-secondary);
  text-wrap:pretty;
}
.pcard__tags{display:flex;flex-wrap:wrap;gap:var(--space-2)}

/* --- page sections -------------------------------------------------------- */

.section{padding:var(--section-gap) var(--page-margin) 0;max-width:var(--max-width);margin:0 auto}
.section--flush{padding-top:var(--space-10)}

.intro{
  display:flex;flex-wrap:wrap;gap:var(--space-7) var(--space-9);
  align-items:flex-end;justify-content:space-between;
}
.intro p{
  margin:0;max-width:var(--measure-prose);
  font-size:var(--size-body-l);line-height:var(--lh-body);
  color:var(--text-secondary);text-wrap:pretty;
}
.intro__actions{display:flex;gap:var(--space-3);flex-wrap:wrap}

.work__grid{
  display:grid;
  grid-template-columns:repeat(auto-fit,minmax(320px,1fr));
  gap:var(--space-8) var(--space-7);
  margin-top:var(--space-8);
}
.work__foot{
  margin-top:var(--space-7);
  padding-top:var(--space-5);
  border-top:var(--border-width-hairline) solid var(--border-hairline);
}

.services{margin-top:var(--space-8);border-top:var(--border-width-hairline) solid var(--border-hairline)}
.service{
  display:grid;grid-template-columns:64px minmax(0,1fr) minmax(0,1.1fr);
  gap:var(--space-7);
  padding:var(--space-7) 0;
  border-bottom:var(--border-width-hairline) solid var(--border-hairline);
  align-items:start;
}
.service__num{
  font-family:var(--font-mono);font-size:var(--size-meta);
  letter-spacing:var(--ls-meta);color:var(--text-muted);padding-top:6px;
}
.service h3{
  margin:0;
  font-size:clamp(1.5rem,2.4vw,2.125rem);
  font-weight:var(--weight-semibold);
  line-height:0.98;
  letter-spacing:-0.04em;
  text-transform:uppercase;
}
.service p{
  margin:0;font-size:1.0625rem;line-height:var(--lh-body);
  color:var(--text-secondary);text-wrap:pretty;
}
.service__tags{display:flex;flex-wrap:wrap;gap:var(--space-2);margin-top:var(--space-5)}

.about{display:grid;grid-template-columns:minmax(0,0.8fr) minmax(0,1.2fr);gap:var(--space-8);align-items:start}
.about p{
  margin:var(--space-6) 0 0;max-width:var(--measure-prose);
  font-size:var(--size-body-l);line-height:var(--lh-body);
  color:var(--text-secondary);text-wrap:pretty;
}
.about p + p{margin-top:var(--space-5)}
.history{margin-top:var(--space-7);border-top:var(--border-width-strong) solid var(--border-strong)}
.history__row{
  display:grid;grid-template-columns:120px minmax(0,1fr) minmax(0,0.9fr);
  gap:var(--space-5);padding:18px 0;
  border-bottom:var(--border-width-hairline) solid var(--border-hairline);
  align-items:baseline;
}
.history__years{font-family:var(--font-mono);font-size:var(--size-meta);letter-spacing:var(--ls-meta);color:var(--text-muted)}
.history__place{font-size:0.9375rem;font-weight:var(--weight-semibold);text-transform:uppercase;letter-spacing:var(--ls-heading)}
.history__role{font-size:0.9375rem;line-height:1.4;color:var(--text-secondary)}

/* --- contact -------------------------------------------------------------- */

.contact{
  margin-top:var(--section-gap);
  padding:var(--space-11) var(--page-margin);
  background:var(--surface-page);
  color:var(--text-primary);
}
.contact__grid{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,0.85fr);gap:var(--space-8);align-items:end}
.contact h2{
  margin:var(--space-6) 0 0;
  font-size:clamp(2.5rem,6.4vw,5.5rem);
  font-weight:var(--weight-semibold);
  line-height:var(--lh-display);
  letter-spacing:var(--ls-display);
  text-transform:uppercase;
}
.contact p{
  margin:var(--space-6) 0 0;max-width:52ch;
  font-size:var(--size-body-l);line-height:var(--lh-body);
  color:var(--text-secondary);text-wrap:pretty;
}
.contact__side{display:grid;gap:var(--space-5)}
.contact__mail{
  display:flex;align-items:baseline;justify-content:space-between;gap:var(--space-4);
  font-size:clamp(1.125rem,2.3vw,1.75rem);
  font-weight:var(--weight-semibold);
  letter-spacing:-0.04em;
  text-transform:uppercase;
  border-bottom:var(--border-width-hairline) solid var(--border-hairline);
  padding-bottom:var(--space-4);
}
.contact__mail .glyph{transition:transform var(--dur-fast) var(--ease-out);display:inline-block}
.contact__mail:hover .glyph{transform:translateX(4px)}
/* Two short facts, so they do not need a fixed pair of columns. Given room they
   sit side by side; below about 380px of side -- where "Behance" and "LinkedIn"
   were being folded onto three lines inside 141px -- they stack. */
.contact__pair{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:var(--space-5)}
.contact__actions{display:flex;gap:var(--space-3);margin-top:var(--space-2);flex-wrap:wrap}

.fact__k{font-family:var(--font-mono);font-size:var(--size-meta);color:var(--text-muted)}
.fact__v{margin-top:var(--space-2);font-size:0.9375rem;font-weight:var(--weight-semibold);text-transform:uppercase;letter-spacing:var(--ls-heading)}

/* --- FooterBlock ---------------------------------------------------------- */

.footer{
  background:var(--surface-inverse);
  color:var(--text-inverse);
  padding:var(--space-9) var(--page-margin) var(--space-6);
}
.footer__grid{display:grid;grid-template-columns:minmax(0,1.4fr) repeat(2,minmax(0,1fr));gap:var(--space-7);align-items:start}
.footer__brand{display:flex;flex-direction:column;gap:var(--space-4)}
.footer__wordmark{font-size:var(--size-heading-m);font-weight:var(--weight-semibold);letter-spacing:var(--ls-heading)}
.footer__note{margin:0;max-width:var(--measure-narrow);font-size:var(--size-body-s);color:var(--ink-300)}
.footer__col{display:flex;flex-direction:column;gap:var(--space-4)}
.footer__col .label{color:var(--text-inverse);opacity:0.6}
.footer__links{display:flex;flex-direction:column;gap:var(--space-3)}
.footer__links a{color:var(--text-inverse)}
.footer__links a:hover{color:var(--signal-400)}
.footer__meta{
  margin-top:var(--space-9);padding-top:var(--space-4);
  border-top:var(--border-width-hairline) solid var(--border-hairline-inverse);
  display:flex;justify-content:space-between;gap:var(--space-4);
  font-family:var(--font-mono);font-size:var(--size-meta);letter-spacing:var(--ls-meta);
  color:var(--ink-400);
}

/* --- scroll reveal -------------------------------------------------------- */

.reveal{
  opacity:0;
  transform:translateY(18px);
  transition:opacity var(--dur-reveal) var(--ease-out),transform var(--dur-reveal) var(--ease-out);
}
.reveal.is-in{opacity:1;transform:none}

@media (prefers-reduced-motion:reduce){
  .reveal{opacity:1;transform:none}
}

/* --- narrow --------------------------------------------------------------- */

@media (max-width:900px){
  .about{grid-template-columns:minmax(0,1fr);gap:var(--space-7)}
  .contact__grid{grid-template-columns:minmax(0,1fr);gap:var(--space-7)}
  .service{grid-template-columns:40px minmax(0,1fr);gap:var(--space-4) var(--space-5)}
  .service > div:last-child{grid-column:2}
  .footer__grid{grid-template-columns:minmax(0,1fr);gap:var(--space-7)}
  .history__row{grid-template-columns:minmax(0,1fr);gap:var(--space-1)}
}

/* Three columns of history inside the narrower half of a two-column about
   section is one column too many. Between 900px -- where about is still split
   -- and about 1250px, the role was arriving in 163px: "Equipment and spatial
   design, concept and 3D to production" set two words to a line, ten lines
   deep, next to a place name occupying one. The years stay in their own column
   because that is what makes it a table; the place and what it was drop into
   one lane together, which is how you read them anyway. */
@media (min-width:901px) and (max-width:1250px){
  .history__row{
    grid-template-columns:120px minmax(0,1fr);
    gap:2px var(--space-5);
    align-items:baseline;
  }
  .history__years{grid-row:span 2}
  .history__place,
  .history__role{grid-column:2}
}

/* --- typeset for a phone ---------------------------------------------------
   Every size in the scale is a clamp, and below roughly 630px all of them are
   sitting on their floor. Those floors were chosen for a narrow laptop, where
   the text still has 700 or 900 pixels to run in. On a 360px screen the same
   floors are the wrong size for the column they are in: a 44px uppercase
   heading in a 320px measure fits about ten characters, so "Four disciplines,
   one foundation" arrived as four lines of one word each, and the body at 18px
   was running at 29 characters a line where 35 to 45 reads comfortably.

   Proportion is what carries the identity here, not absolute size. Display-l
   is 7.5% of the content width on a laptop; 32px on a phone is 10% of it. The
   headline is still the largest thing on the page by a distance -- it has just
   stopped being larger than the page.

   These are the tokens, so one block covers the home page, the personal page
   and all nine projects. Sizes that are already phone-appropriate at their
   floor -- heading-s in the nav, the label and meta sizes, body-s -- are left
   exactly as they are.
   -------------------------------------------------------------------------- */

@media (max-width:600px){
  :root{
    --size-display-l:2rem;       /* 44px -> 32px : project titles, section heads */
    --size-display-m:1.625rem;   /* 32px -> 26px : "Selected work" and its kind */
    --size-heading-l:1.5rem;     /* 32px -> 24px : headings inside a project */
    --size-body-l:1rem;          /* 18px -> 16px : all long-form prose */
  }

  /* The section heading and its paragraph sat a full 24px apart at a size that
     no longer needs it. */
  .heading{gap:var(--space-4)}

  /* The number was taking 40px plus a 24px gutter out of a 305px column, which
     left the description of each discipline reading at 22 characters a line --
     the narrowest prose on the home page. On a phone it becomes an index above
     the heading instead of a column beside it, which is how every other number
     on this site behaves anyway. */
  .service{grid-template-columns:minmax(0,1fr);gap:var(--space-2)}
  .service > div:last-child{grid-column:1;margin-top:var(--space-4)}
  .service__num{padding-top:0}
}

/* --- the doodle ------------------------------------------------------------
   The way into the personal page, and the only way in: it is not in the nav,
   not in the footer links, and not a section of the site. A small scribble in
   the corner of the footer, the kind of mark you make on a page while you are
   thinking about something else.

   At rest it is nearly invisible — a faint line most people will scroll past.
   Hovering or tabbing to it draws the stroke in and puts Pedro's own words
   beside it. Finding it is the whole point, so nothing here announces itself.
   -------------------------------------------------------------------------- */

.doodle{
  display:inline-flex;
  align-items:center;
  gap:var(--space-2);
  color:var(--text-inverse);
  text-decoration:none;
  /* pulled out of the meta row's baseline so it reads as a mark on the page
     rather than as a third item in a list */
  margin-left:auto;
  padding:2px 4px;
}
.doodle__mark{
  width:26px;height:24px;
  overflow:visible;
  flex:none;
}
.doodle__mark path{
  fill:none;
  stroke:currentColor;
  stroke-width:2.2;
  stroke-linecap:round;
  stroke-linejoin:round;
  /* the line is drawn in on hover: long dash, offset all the way out */
  /* a quarter of the line is already there: enough of a mark to notice and
     hover, not enough to read as a button. The rest arrives when you do. */
  stroke-dasharray:120;
  stroke-dashoffset:92;
  opacity:0.3;
  transition:stroke-dashoffset 700ms var(--ease-out), opacity 300ms var(--ease-out);
}
.doodle__note{
  font-family:var(--font-mono);
  font-size:var(--size-meta);
  letter-spacing:var(--ls-meta);
  white-space:nowrap;
  opacity:0;
  transform:translateX(-6px);
  transition:opacity 260ms var(--ease-out) 220ms, transform 260ms var(--ease-out) 220ms;
}

.doodle:hover .doodle__mark path,
.doodle:focus-visible .doodle__mark path{
  stroke-dashoffset:0;
  opacity:0.95;
}
.doodle:hover .doodle__note,
.doodle:focus-visible .doodle__note{
  opacity:0.8;
  transform:none;
}
.doodle:focus-visible{outline:1px dashed currentColor;outline-offset:4px}

/* On a touch screen there is no hover to reward, so the mark simply sits
   there a little more visibly and can be tapped. */
@media (hover:none){
  .doodle__mark path{stroke-dashoffset:0;opacity:0.4}
}

@media (prefers-reduced-motion:reduce){
  .doodle__mark path{transition:opacity 1ms}
  .doodle__note{transition:opacity 1ms}
}

/* --- the personal page -----------------------------------------------------
   A warmer paper, so that arriving here feels like arriving somewhere else.
   It is the one page that is not the portfolio, and half a shade of pink is
   enough to say so without changing a single other rule.
   -------------------------------------------------------------------------- */

body.is-personal{
  --paper:#FBF0EA;
  --surface-page:#FBF0EA;
  --surface-media:#F3E1D8;
}

/* --- the same mark, one step louder ----------------------------------------
   The footer doodle is deliberately almost invisible: a quarter of a spiral at
   30% and a note that only exists on hover. That is right for a footer, and it
   means most people never find the page behind it.

   In the contact block it gets to be findable. Someone reading that section has
   already decided to get in touch, and this is the one place where a second
   look at who they are writing to is worth offering. So the line is further
   drawn and the note is already legible -- still a mark rather than a button,
   still no label in the navigation, but hard to miss if you are looking at the
   section at all.
   -------------------------------------------------------------------------- */

.doodle--open{
  margin-left:0;
  margin-top:var(--space-6);
  padding-left:0;
}
.doodle--open .doodle__mark path{
  stroke-dashoffset:64;
  opacity:0.5;
}
.doodle--open .doodle__note{
  opacity:0.5;
  transform:none;
  transition:opacity 260ms var(--ease-out);
}

/* The note never wraps, so that revealing it on hover cannot reflow the line
   it sits on. In the contact block it is shown from the start and the sentence
   is long: on a phone that made a 441px element inside a 360px screen and the
   end of it was simply cut off. Here it is allowed to wrap. */
@media (max-width:700px){
  .doodle{max-width:100%;align-items:flex-start}
  .doodle__note{white-space:normal}
  .doodle__mark{margin-top:2px}
}

/* The "Elsewhere" pair is laid out inline in the markup, which a stylesheet
   cannot override, but it never said what to do when the two links no longer
   fit on one line. On a 360px screen the second one ran eight pixels off the
   edge. Wrapping costs nothing at any width where they already fit. */
.fact__v{flex-wrap:wrap}
.doodle--open:hover .doodle__mark path,
.doodle--open:focus-visible .doodle__mark path{stroke-dashoffset:0;opacity:0.95}
.doodle--open:hover .doodle__note,
.doodle--open:focus-visible .doodle__note{opacity:0.9}

/* The footer doodle sits on ink and takes --text-inverse to read light against
   it. The contact block is already night-themed, so inside it that token has
   flipped back to dark and the mark went black on black. Here it wants the
   section's own foreground. */
.contact .doodle--open{color:var(--text-primary)}
